Merge pull request #968 from rishy/Batch-API

added "UpdateClient" and "ApplyLoan" commands with dependency resolution
This commit is contained in:
Vishwas Babu A J
2014-06-23 15:16:39 -07:00
15 changed files with 794 additions and 103 deletions
@@ -41,8 +41,7 @@ import org.springframework.stereotype.Component;
public class BatchApiResource {
private final PlatformSecurityContext context;
@SuppressWarnings("rawtypes")
private final ToApiJsonSerializer toApiJsonSerializer;
private final ToApiJsonSerializer<BatchResponse> toApiJsonSerializer;
private final BatchApiService service;
private final BatchRequestJsonHelper batchRequestJsonHelper;
@@ -56,9 +55,8 @@ public class BatchApiResource {
* @param batchRequestJsonHelper
*/
@Autowired
public BatchApiResource(final PlatformSecurityContext context, @SuppressWarnings("rawtypes")
final ToApiJsonSerializer toApiJsonSerializer, final BatchApiService service,
final BatchRequestJsonHelper batchRequestJsonHelper) {
public BatchApiResource(final PlatformSecurityContext context, final ToApiJsonSerializer<BatchResponse>
toApiJsonSerializer, final BatchApiService service, final BatchRequestJsonHelper batchRequestJsonHelper) {
this.context = context;
this.toApiJsonSerializer = toApiJsonSerializer;
@@ -88,7 +86,7 @@ public class BatchApiResource {
//Gets back the consolidated BatchResponse from BatchApiservice
List<BatchResponse> result = new ArrayList<>();
//if the request is to be handled as a Transaction. All requests will be rolled back on error
//If the request is to be handled as a Transaction. All requests will be rolled back on error
if(enclosingTransaction) {
try {
@@ -48,6 +48,21 @@ public class CommandContext {
public static Builder resource(final String resource) {
return new Builder(resource);
}
/**
* Returns a boolean value if the relativeUrl 'matches' one of the regex keys in
* the available commandStrategies. It take CommandContext object as parameter
* which contains a 'resource' member as a regex key for available commandStrategies.
*
* @param other
* @return boolean
*/
public boolean matcher(CommandContext other) {
if(this.resource.matches(other.resource) && this.method.equals(other.method)) {
return true;
}
return false;
}
@Override
public int hashCode() {
@@ -52,6 +52,12 @@ public class CommandStrategyProvider {
return (CommandStrategy) this.applicationContext.getBean(this.commandStrategies.get(commandContext));
}
for(ConcurrentHashMap.Entry<CommandContext,String> entry : this.commandStrategies.entrySet()) {
if(commandContext.matcher(entry.getKey())) {
return (CommandStrategy) this.applicationContext.getBean(this.commandStrategies.get(entry.getKey()));
}
}
return new UnknownCommandStrategy();
}
@@ -61,7 +67,9 @@ public class CommandStrategyProvider {
* within the constructor.
*/
private void init() {
this.commandStrategies.put(CommandContext.resource("clients").method("POST").build(), "CreateClientCommandStrategy");
this.commandStrategies.put(CommandContext.resource("clients").method("POST").build(), "createClientCommandStrategy");
this.commandStrategies.put(CommandContext.resource("clients\\/\\d+").method("PUT").build(), "updateClientCommandStrategy");
this.commandStrategies.put(CommandContext.resource("loans").method("POST").build(), "applyLoanCommandStrategy");
}
}
@@ -0,0 +1,69 @@
package org.mifosplatform.batch.command.internal;
import org.mifosplatform.batch.command.CommandStrategy;
import org.mifosplatform.batch.domain.BatchRequest;
import org.mifosplatform.batch.domain.BatchResponse;
import org.mifosplatform.batch.exception.ErrorHandler;
import org.mifosplatform.batch.exception.ErrorInfo;
import org.mifosplatform.portfolio.loanaccount.api.LoansApiResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.Gson;
/**
* Implements {@link org.mifosplatform.batch.command.CommandStrategy} and applies a new loan
* on an existing client. It passes the contents of the body from the BatchRequest
* to {@link org.mifosplatform.portfolio.client.api.LoansApiResource} and gets back
* the response. This class will also catch any errors raised by
* {@link org.mifosplatform.portfolio.client.api.LoansApiResource} and map those errors
* to appropriate status codes in BatchResponse.
*
* @author Rishabh Shukla
*
* @see org.mifosplatform.batch.command.CommandStrategy
* @see org.mifosplatform.batch.domain.BatchRequest
* @see org.mifosplatform.batch.domain.BatchResponse
*/
@Component
public class ApplyLoanCommandStrategy implements CommandStrategy{
private final LoansApiResource loansApiResource;
@Autowired
public ApplyLoanCommandStrategy(final LoansApiResource loansApiResource) {
this.loansApiResource = loansApiResource;
}
@Override
public BatchResponse execute(BatchRequest request) {
final BatchResponse response = new BatchResponse();
final String responseBody;
response.setRequestId(request.getRequestId());
response.setHeaders(request.getHeaders());
//Try-catch blocks to map exceptions to appropriate status codes
try {
//Calls 'SubmitLoanFunction' function from 'LoansApiResource' to Apply Loan to an existing client
responseBody = loansApiResource.calculateLoanScheduleOrSubmitLoanApplication(null, null, request.getBody());
response.setStatusCode(200);
//Sets the body of the response after loan is successfully applied
response.setBody(responseBody);
}
catch (RuntimeException e) {
//Gets an object of type ErrorInfo, containing information about raised exception
ErrorInfo ex = ErrorHandler.handler(e);
response.setStatusCode(ex.getStatusCode());
response.setBody(new Gson().toJson(ex));
}
return response;
}
}
@@ -3,13 +3,13 @@ package org.mifosplatform.batch.command.internal;
import org.mifosplatform.batch.command.CommandStrategy;
import org.mifosplatform.batch.domain.BatchRequest;
import org.mifosplatform.batch.domain.BatchResponse;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.exception.PlatformInternalServerException;
import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException;
import org.mifosplatform.batch.exception.ErrorHandler;
import org.mifosplatform.batch.exception.ErrorInfo;
import org.mifosplatform.portfolio.client.api.ClientsApiResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.Gson;
/**
* Implements {@link org.mifosplatform.batch.command.CommandStrategy} to handle
@@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired;
* @see org.mifosplatform.batch.domain.BatchRequest
* @see org.mifosplatform.batch.domain.BatchResponse
*/
@Component
public class CreateClientCommandStrategy implements CommandStrategy{
private final ClientsApiResource clientsApiResource;
@@ -32,51 +33,36 @@ public class CreateClientCommandStrategy implements CommandStrategy{
@Autowired
public CreateClientCommandStrategy(final ClientsApiResource clientsApiResource) {
this.clientsApiResource = clientsApiResource;
}
}
@Override
public BatchResponse execute(final BatchRequest request) {
final BatchResponse response = new BatchResponse();
final String responseBody;
final String responseBody;
response.setRequestId(request.getRequestId());
response.setHeaders(request.getHeaders());
// try-catch blocks to map exceptions to appropriate status codes
//Try-catch blocks to map exceptions to appropriate status codes
try {
//calls 'create' function from 'ClientsApiResource' to create a new client
//Calls 'create' function from 'ClientsApiResource' to create a new client
responseBody = clientsApiResource.create(request.getBody());
response.setRequestId(request.getRequestId());
response.setHeaders(request.getHeaders());
response.setStatusCode(200);
//sets the body of the response after the successful creation of the client
//Sets the body of the response after the successful creation of the client
response.setBody(responseBody);
} catch (AbstractPlatformResourceNotFoundException e) {
}
catch (RuntimeException e) {
response.setStatusCode(404);
response.setBody("error : " + e.toString());
//Gets an object of type ErrorInfo, containing information about raised exception
ErrorInfo ex = ErrorHandler.handler(e);
} catch (UnsupportedParameterException e) {
response.setStatusCode(400);
response.setBody("error : " + e.toString());
} catch(PlatformApiDataValidationException e) {
response.setStatusCode(400);
response.setBody("error : " + e.toString());
} catch (PlatformDataIntegrityException e) {
response.setStatusCode(403);
response.setBody("error : " + e.toString());
} catch (PlatformInternalServerException e) {
response.setStatusCode(500);
response.setBody("error : " + e.toString());
}
response.setStatusCode(ex.getStatusCode());
response.setBody(new Gson().toJson(ex));
}
return response;
}
@@ -3,6 +3,7 @@ package org.mifosplatform.batch.command.internal;
import org.mifosplatform.batch.command.CommandStrategy;
import org.mifosplatform.batch.domain.BatchRequest;
import org.mifosplatform.batch.domain.BatchResponse;
import org.springframework.stereotype.Component;
/**
* Provides a default CommandStrategy by implementing
@@ -12,6 +13,7 @@ import org.mifosplatform.batch.domain.BatchResponse;
*
* @author Rishabh Shukla
*/
@Component
public class UnknownCommandStrategy implements CommandStrategy {
@Override
@@ -0,0 +1,73 @@
package org.mifosplatform.batch.command.internal;
import org.mifosplatform.batch.command.CommandStrategy;
import org.mifosplatform.batch.domain.BatchRequest;
import org.mifosplatform.batch.domain.BatchResponse;
import org.mifosplatform.batch.exception.ErrorHandler;
import org.mifosplatform.batch.exception.ErrorInfo;
import org.mifosplatform.portfolio.client.api.ClientsApiResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.Gson;
/**
* Implements {@link org.mifosplatform.batch.command.CommandStrategy} and updates the
* information of an existing client. It passes the contents of the body from the BatchRequest
* to {@link org.mifosplatform.portfolio.client.api.ClientsApiResource} and gets back
* the response. This class will also catch any errors raised by
* {@link org.mifosplatform.portfolio.client.api.ClientsApiResource} and map those errors
* to appropriate status codes in BatchResponse.
*
* @author Rishabh Shukla
*
* @see org.mifosplatform.batch.command.CommandStrategy
* @see org.mifosplatform.batch.domain.BatchRequest
* @see org.mifosplatform.batch.domain.BatchResponse
*/
@Component
public class UpdateClientCommandStrategy implements CommandStrategy {
private final ClientsApiResource clientsApiResource;
@Autowired
public UpdateClientCommandStrategy(final ClientsApiResource clientsApiResource) {
this.clientsApiResource = clientsApiResource;
}
@Override
public BatchResponse execute(BatchRequest request) {
final BatchResponse response = new BatchResponse();
final String responseBody;
response.setRequestId(request.getRequestId());
response.setHeaders(request.getHeaders());
//Get the clientID
final String relativeUrl = request.getRelativeUrl();
final Long clientId = Long.parseLong(relativeUrl.substring(relativeUrl.indexOf('/') + 1));
//Try-catch blocks to map exceptions to appropriate status codes
try {
//Calls 'update' function from 'ClientsApiResource' to update a client
responseBody = clientsApiResource.update(clientId, request.getBody());
response.setStatusCode(200);
//Sets the body of the response after the successful update of client information
response.setBody(responseBody);
} catch (RuntimeException e) {
//Gets an object of type ErrorInfo, containing information about raised exception
ErrorInfo ex = ErrorHandler.handler(e);
response.setStatusCode(ex.getStatusCode());
response.setBody(new Gson().toJson(ex));
}
return response;
}
}
@@ -0,0 +1,50 @@
package org.mifosplatform.batch.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException;
/**
* Provides an Error Handler method that returns an object of type {@link ErrorInfo}
* to the CommandStrategy which raised the exception. This class uses various subclasses
* of RuntimeException to check the kind of exception raised and provide appropriate
* status and error codes for each one of the raised exception.
*
* @author Rishabh Shukla
*
* @see org.mifosplatform.batch.command.CommandStrategy
* @see org.mifosplatform.batch.command.internal.CreateClientCommandStrategy
*/
public class ErrorHandler extends RuntimeException{
/**
* Sole Constructor
*/
ErrorHandler() {
super();
}
/**
* Returns an object of ErrorInfo type containing the information regarding
* the raised error.
*
* @param exception
* @return ErrorInfo
*/
public static ErrorInfo handler(RuntimeException exception) {
if(exception instanceof AbstractPlatformResourceNotFoundException) {
return new ErrorInfo(404, 1001, "Requested Resource was not Found");
} else if(exception instanceof UnsupportedParameterException) {
return new ErrorInfo(400, 2001, "UnsupportedParameterException: Check for any unsupported Parameters");
} else if(exception instanceof PlatformApiDataValidationException) {
return new ErrorInfo(400, 2002, "ApiDataValidationException: Re-Check the input data");
} else if(exception instanceof PlatformDataIntegrityException) {
return new ErrorInfo(403, 3001, "DataIntegrityException: Check for any duplicate data");
}
return new ErrorInfo(500, 9999, "Internal Server Error");
}
}
@@ -0,0 +1,93 @@
package org.mifosplatform.batch.exception;
/**
* Provides members to hold the basic information about the exceptions raised in
* commandStrategy classes.
*
* @author Rishabh Shukla
*
* @see ErrorHandler
*/
public final class ErrorInfo {
private Integer statusCode;
private Integer errorCode;
private String message;
/**
* Constructor to initialize the members of this class.
*
* @param statusCode
* @param errorCode
* @param message
*/
public ErrorInfo(final Integer statusCode, final Integer errorCode, final String message) {
super();
this.statusCode = statusCode;
this.errorCode = errorCode;
this.message = message;
}
/**
* Constructor so JSON serialization will work with out special Serialiazer
*/
ErrorInfo() {
super();
}
/**
* Getter method to provide the statusCode for an object of this type.
*
* @return Integer
*/
public Integer getStatusCode() {
return this.statusCode;
}
/**
* Setter method to set the statusCode for an object of this type.
*
* @param statusCode
*/
public void setStatusCode(final Integer statusCode) {
this.statusCode = statusCode;
}
/**
* Getter method to provide the errorCode for an object of this type.
*
* @return Integer
*/
public Integer getErrorCode() {
return this.errorCode;
}
/**
* Setter method to set the errorCode for an object of this type.
*
* @param errorCode
*/
public void setErrorCode(final Integer errorCode) {
this.errorCode = errorCode;
}
/**
* Getter method to provide the message of the error for an object
* of this type.
*
* @return String
*/
public String getMessage() {
return this.message;
}
/**
* Setter method to set the message of the error for an object
* of this type.
*
* @param message
*/
public void setMessage(final String message) {
this.message = message;
}
}
@@ -2,16 +2,22 @@ package org.mifosplatform.batch.service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import javax.ws.rs.core.Response.Status;
import org.mifosplatform.batch.command.CommandContext;
import org.mifosplatform.batch.command.CommandStrategy;
import org.mifosplatform.batch.command.CommandStrategyProvider;
import org.mifosplatform.batch.domain.BatchRequest;
import org.mifosplatform.batch.domain.BatchResponse;
import org.mifosplatform.batch.exception.ErrorInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.google.gson.Gson;
/**
* Implementation for {@link BatchApiService} to iterate through all the incoming
* requests and obtain the appropriate CommandStrategy from CommandStrategyProvider.
@@ -26,6 +32,7 @@ import org.springframework.transaction.annotation.Transactional;
public class BatchApiServiceImpl implements BatchApiService{
private final CommandStrategyProvider strategyProvider;
private final ResolutionHelper resolutionHelper;
/**
* Constructs a 'BatchApiServiceImpl' with an argument of
@@ -34,27 +41,77 @@ public class BatchApiServiceImpl implements BatchApiService{
* @param strategyProvider
*/
@Autowired
public BatchApiServiceImpl(final CommandStrategyProvider strategyProvider) {
public BatchApiServiceImpl(final CommandStrategyProvider strategyProvider,
final ResolutionHelper resolutionHelper) {
this.strategyProvider = strategyProvider;
this.resolutionHelper = resolutionHelper;
}
/**
* Returns the response list by getting a proper {@link org.mifosplatform.batch.command.CommandStrategy}.
* execute() method of acquired commandStrategy is then provided with the separate Request.
*
* @param requestList
* @return List<BatchResponse>
*/
private List<BatchResponse> handleBatchRequests(final List<BatchRequest> requestList) {
final List<BatchResponse> responseList = new ArrayList<>(requestList.size());
final List<BatchResponse> responseList = new ArrayList<>();
for(final BatchRequest br: requestList) {
final ConcurrentHashMap<Long, ArrayList<BatchRequest>> requestMap = this.resolutionHelper.getDependencyMap(requestList);
for(ConcurrentHashMap.Entry<Long, ArrayList<BatchRequest>> entry : requestMap.entrySet()) {
final CommandStrategy commandStrategy = this.strategyProvider.getCommandStrategy(CommandContext.
resource(br.getRelativeUrl()).method(br.getMethod()).build());
final ArrayList<BatchRequest> mappedList = entry.getValue();
final BatchResponse response = commandStrategy.execute(br);
for(BatchRequest br: mappedList) {
//If this request is dependent on any other request in the list
if(br.getReference() != null) {
BatchResponse parentResponse = new BatchResponse();
//Fetch the response of the request on which it is dependent from responseList
for(final BatchResponse res: responseList) {
if(res.getRequestId().equals(br.getReference())) {
parentResponse = res;
}
}
//If parentResponse has returned a successful request
if(parentResponse.getStatusCode() == 200) {
br = this.resolutionHelper.resoluteRequest(br, parentResponse);
} else {
//Something went wrong with the parent request, create a response with status code 409
final BatchResponse response = new BatchResponse();
response.setRequestId(br.getRequestId());
response.setStatusCode(Status.CONFLICT.getStatusCode());
//Some detail information about the error
final ErrorInfo conflictError = new ErrorInfo(Status.CONFLICT.getStatusCode(), 8001,
"Parent request with id " + parentResponse.getRequestId() + " was erroneous!");
response.setBody(new Gson().toJson(conflictError));
responseList.add(response);
//Proceed with next list entry
continue;
}
}
final CommandStrategy commandStrategy = this.strategyProvider.getCommandStrategy(CommandContext.
resource(br.getRelativeUrl()).method(br.getMethod()).build());
final BatchResponse response = commandStrategy.execute(br);
responseList.add(response);
}
responseList.add(response);
}
return responseList;
}
@Override
public List<BatchResponse> handleBatchRequestsWithoutEnclosingTransaction(final
List<BatchRequest> requestList) {
@@ -0,0 +1,176 @@
package org.mifosplatform.batch.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.mifosplatform.batch.domain.BatchRequest;
import org.mifosplatform.batch.domain.BatchResponse;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.jayway.jsonpath.JsonModel;
/**
* Provides methods to create dependency map among the various batchRequests.
* It also provides method that takes care of dependency resolution among
* related requests.
*
* @author Rishabh Shukla
* @see BatchApiServiceImpl
*/
@Component
public class ResolutionHelper {
private FromJsonHelper fromJsonHelper;
@Autowired
public ResolutionHelper(final FromJsonHelper fromJsonHelper) {
this.fromJsonHelper = fromJsonHelper;
}
/**
* Returns a map containing requests that are divided in accordance of dependency relations
* among them. Each different list is identified with a "Key" which is the "requestId" of
* the request at topmost level in dependency hierarchy of that particular list.
*
* @param requestList
* @return ConcurrentHashMap<Long, List<BatchRequest>>
*/
public ConcurrentHashMap<Long, ArrayList<BatchRequest>> getDependencyMap(final List<BatchRequest> requestList) {
//Create a map with a '-1L' which will contain a list of independent requests
final ConcurrentHashMap<Long, ArrayList<BatchRequest>> dependencyMap = new ConcurrentHashMap<>();
dependencyMap.put(-1L, new ArrayList<BatchRequest>());
//For every request in the requestList
for(final BatchRequest br : requestList) {
final Long reference = br.getReference();
//If current request is dependent on some other request
if(reference != null) {
//Then find the request on which br is dependent on
for(final BatchRequest parentRequest : requestList) {
//If request on which br is dependent is found
if(parentRequest.getRequestId().equals(reference)) {
//Then start the process of adding it to one of the key in the dependencyMap
//If referenced request is in the list with key "-1L"
if(dependencyMap.get(-1L).contains(parentRequest)) {
//Then create a new list with key = reference
final ArrayList<BatchRequest> newList = new ArrayList<>();
newList.add(parentRequest);
newList.add(br);
//And add this list to the map
dependencyMap.put(reference, newList);
//Also remove parentRequest from the list at '-1L'
final ArrayList<BatchRequest> listCopy = dependencyMap.get(-1L);
listCopy.remove(parentRequest);
dependencyMap.replace(-1L, listCopy);
}
//If referenced request is not in key '-1L'
else {
//Find the list in which it is present
for(final ConcurrentHashMap.Entry<Long, ArrayList<BatchRequest>> entry: dependencyMap.entrySet()) {
if(entry.getValue().contains(parentRequest)) {
final ArrayList<BatchRequest> listCopy = entry.getValue();
listCopy.add(br);
//Add this request to this list
dependencyMap.replace(entry.getKey(), listCopy);
}
}
}
}
}
}
//If request is independent then add it to '-1L'
else {
final ArrayList<BatchRequest> listCopy = dependencyMap.get(-1L);
listCopy.add(br);
dependencyMap.replace(-1L, listCopy);
}
}
return dependencyMap;
}
/**
* Returns a BatchRequest after dependency resolution. It takes a request and the
* response of the request it is dependent upon as its arguments and change the body
* or relativeUrl of the request according to parent Request.
*
* @param request
* @param lastResponse
* @return BatchRequest
*/
public BatchRequest resoluteRequest(final BatchRequest request,final BatchResponse parentResponse) {
//Create a duplicate request
final BatchRequest br = request;
final JsonModel responseJsonModel = JsonModel.model(parentResponse.getBody());
//Gets the body from current Request as a JsonObject
final JsonObject jsonRequestBody = this.fromJsonHelper.parse(request.getBody()).getAsJsonObject();
JsonObject jsonResultBody = new JsonObject();
//Iterate through each element in the requestBody to find dependent parameter
for(Entry<String, JsonElement> element: jsonRequestBody.entrySet()) {
String paramVal = element.getValue().getAsString();
//If a dependent parameter is found
if(paramVal.contains("$.")) {
//Get the value of the parameter from parent response
final String resParamValue = responseJsonModel.get(paramVal).toString();
//Add the value after dependency resolution
jsonResultBody.add(element.getKey(), this.fromJsonHelper.parse(resParamValue));
}
else {
jsonResultBody.add(element.getKey(), element.getValue());
}
}
//Set the body after dependency resolution
br.setBody(jsonResultBody.toString());
//Also check the relativeUrl for any dependency resolution
String relativeUrl = request.getRelativeUrl();
if(relativeUrl.contains("$.")) {
final String parameter = relativeUrl.substring(relativeUrl.indexOf('/') + 1, relativeUrl.length());
//Get the value of the parameter from last response
final String resParamValue = responseJsonModel.get(parameter).toString();
relativeUrl = relativeUrl.replace(parameter, resParamValue);
br.setRelativeUrl(relativeUrl);
}
return br;
}
}
@@ -35,13 +35,11 @@
org.mifosplatform.template.*,
org.mifosplatform.template.service.*,
org.mifosplatform.useradministration.*,
org.mifosplatform.batch.*">
org.mifosplatform.batch">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
type="annotation" />
</context:component-scan>
<bean id="CreateClientCommandStrategy"
class="org.mifosplatform.batch.command.internal.CreateClientCommandStrategy"/>
<bean id="auditorAware"
class="org.mifosplatform.infrastructure.core.domain.AuditorAwareImpl" />
<jpa:auditing auditor-aware-ref="auditorAware" />
@@ -55,8 +53,7 @@
<jpa:repositories base-package="org.mifosplatform.mix.domain" />
<jpa:repositories base-package="org.mifosplatform.scheduledjobs.domain" />
<jpa:repositories base-package="org.mifosplatform.template.domain" />
<jpa:repositories base-package="org.mifosplatform.batch.domain"/>
<import resource="infrastructure.xml" />
<import resource="securityContext.xml" />