Package org.mifosplatform.batch.service

Source Code of org.mifosplatform.batch.service.BatchApiServiceImpl

/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.batch.service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;

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.ErrorHandler;
import org.mifosplatform.batch.exception.ErrorInfo;
import org.mifosplatform.batch.service.ResolutionHelper.BatchRequestNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.google.gson.Gson;

import edu.emory.mathcs.backport.java.util.Collections;

/**
* Implementation for {@link BatchApiService} to iterate through all the
* incoming requests and obtain the appropriate CommandStrategy from
* CommandStrategyProvider.
*
* @author Rishabh Shukla
*
* @see org.mifosplatform.batch.domain.BatchRequest
* @see org.mifosplatform.batch.domain.BatchResponse
* @see org.mifosplatform.batch.command.CommandStrategyProvider
*/
@Service
public class BatchApiServiceImpl implements BatchApiService {

    private final CommandStrategyProvider strategyProvider;
    private final ResolutionHelper resolutionHelper;
    private final TransactionTemplate transactionTemplate;
    private List<BatchResponse> checkList = new ArrayList<>();

    /**
     * Constructs a 'BatchApiServiceImpl' with an argument of
     * {@link org.mifosplatform.batch.command.CommandStrategyProvider} type.
     *
     * @param strategyProvider
     * @param resolutionHelper
     * @param transactionTemplate
     */
    @Autowired
    public BatchApiServiceImpl(final CommandStrategyProvider strategyProvider, final ResolutionHelper resolutionHelper,
            final TransactionTemplate transactionTemplate) {
        this.strategyProvider = strategyProvider;
        this.resolutionHelper = resolutionHelper;
        this.transactionTemplate = transactionTemplate;
    }

    /**
     * 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
     * @param uriInfo
     * @return List<BatchResponse>
     */
    private List<BatchResponse> handleBatchRequests(final List<BatchRequest> requestList, final UriInfo uriInfo) {

        final List<BatchResponse> responseList = new ArrayList<>(requestList.size());

        final List<BatchRequestNode> batchRequestNodes = this.resolutionHelper.getDependingRequests(requestList);
        checkList.clear();

        for (BatchRequestNode rootNode : batchRequestNodes) {
            final BatchRequest rootRequest = rootNode.getRequest();
            final CommandStrategy commandStrategy = this.strategyProvider.getCommandStrategy(CommandContext
                    .resource(rootRequest.getRelativeUrl()).method(rootRequest.getMethod()).build());
            final BatchResponse rootResponse = commandStrategy.execute(rootRequest, uriInfo);

            responseList.add(rootResponse);
            responseList.addAll(this.processChildRequests(rootNode, rootResponse, uriInfo));
        }

        Collections.sort(responseList, new Comparator<BatchResponse>() {

            @Override
            public int compare(BatchResponse source, BatchResponse testee) {
                return source.getRequestId().compareTo(testee.getRequestId());
            }
        });

        checkList = responseList;
        return responseList;

    }

    private List<BatchResponse> processChildRequests(final BatchRequestNode rootRequest, BatchResponse rootResponse, UriInfo uriInfo) {

        final List<BatchResponse> childResponses = new ArrayList<>();
        if (rootRequest.getChildRequests().size() > 0) {

            for (BatchRequestNode childNode : rootRequest.getChildRequests()) {

                BatchRequest childRequest = childNode.getRequest();
                BatchResponse childResponse;

                try {

                    if (rootResponse.getStatusCode().equals(200)) {
                        childRequest = this.resolutionHelper.resoluteRequest(childRequest, rootResponse);
                        final CommandStrategy commandStrategy = this.strategyProvider.getCommandStrategy(CommandContext
                                .resource(childRequest.getRelativeUrl()).method(childRequest.getMethod()).build());

                        childResponse = commandStrategy.execute(childRequest, uriInfo);

                    } else {
                        // Something went wrong with the parent request, create
                        // a response with status code 409
                        childResponse = new BatchResponse();
                        childResponse.setRequestId(childRequest.getRequestId());
                        childResponse.setStatusCode(Status.CONFLICT.getStatusCode());

                        // Some detail information about the error
                        final ErrorInfo conflictError = new ErrorInfo(Status.CONFLICT.getStatusCode(), 8001, "Parent request with id "
                                + rootResponse.getRequestId() + " was erroneous!");
                        childResponse.setBody(conflictError.getMessage());
                    }
                    childResponses.addAll(this.processChildRequests(childNode, childResponse, uriInfo));

                } catch (Throwable ex) {

                    childResponse = new BatchResponse();
                    childResponse.setRequestId(childRequest.getRequestId());
                    childResponse.setStatusCode(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
                    childResponse.setBody(ex.getMessage());
                }

                childResponses.add(childResponse);
            }
        }

        return childResponses;
    }

    @Override
    public List<BatchResponse> handleBatchRequestsWithoutEnclosingTransaction(final List<BatchRequest> requestList, UriInfo uriInfo) {

        return handleBatchRequests(requestList, uriInfo);
    }

    @Override
    public List<BatchResponse> handleBatchRequestsWithEnclosingTransaction(final List<BatchRequest> requestList, final UriInfo uriInfo) {

        try {
            return this.transactionTemplate.execute(new TransactionCallback<List<BatchResponse>>() {

                @Override
                public List<BatchResponse> doInTransaction(TransactionStatus status) {
                    try {
                        return handleBatchRequests(requestList, uriInfo);
                    } catch (RuntimeException ex) {

                        ErrorInfo e = ErrorHandler.handler(ex);
                        BatchResponse errResponse = new BatchResponse();
                        errResponse.setStatusCode(e.getStatusCode());
                        errResponse.setBody(e.getMessage());

                        List<BatchResponse> errResponseList = new ArrayList<>();
                        errResponseList.add(errResponse);

                        status.setRollbackOnly();
                        return errResponseList;
                    }
                }

            });
        } catch (TransactionException ex) {
            ErrorInfo e = ErrorHandler.handler(ex);
            BatchResponse errResponse = new BatchResponse();
            errResponse.setStatusCode(e.getStatusCode());

            for (BatchResponse res : checkList) {
                if (!res.getStatusCode().equals(200)) {
                    errResponse.setBody("Transaction is being rolled back. First erroneous request: \n" + new Gson().toJson(res));
                    break;
                }
            }

            checkList.clear();
            List<BatchResponse> errResponseList = new ArrayList<>();
            errResponseList.add(errResponse);

            return errResponseList;
        }

    }
}
TOP

Related Classes of org.mifosplatform.batch.service.BatchApiServiceImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.