/**
* Copyright 2008-2016 Qualogy Solutions B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.qualogy.qafe.business;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import com.qualogy.qafe.bind.business.action.BusinessAction;
import com.qualogy.qafe.bind.business.transaction.TransactionBehaviour;
import com.qualogy.qafe.bind.core.application.ApplicationContext;
import com.qualogy.qafe.business.action.ItemExecuter;
import com.qualogy.qafe.business.resource.ResourcePool;
import com.qualogy.qafe.business.transaction.TransActionRolledBackException;
import com.qualogy.qafe.business.transaction.TransactionManagerBuilder;
import com.qualogy.qafe.business.transaction.TransactionTemplateBuilder;
import com.qualogy.qafe.core.application.DestoryFailedException;
import com.qualogy.qafe.core.application.InitializationFailedException;
import com.qualogy.qafe.core.conflictdetection.UpdateConflictException;
import com.qualogy.qafe.core.datastore.DataIdentifier;
import com.qualogy.qafe.core.datastore.DataStore;
import com.qualogy.qafe.core.errorhandling.ExternalException;
import com.qualogy.qafe.core.framework.business.BusinessManager;
import com.qualogy.qafe.core.framework.business.UnableToManageException;
import com.qualogy.qafe.core.framework.business.UnableToProcessException;
/**
* implementation of the businessprocessor interface.
*
* @author Marc van der Wurff
*
*/
public class BusinessActionManagerImpl implements BusinessManager {
private static final Logger LOG = Logger.getLogger(BusinessActionManagerImpl.class.getName());
public void manage(final ApplicationContext context, final DataIdentifier dataId,
final BusinessAction action) throws ExternalException {
manage(context, dataId, action, false);
}
public void manage(final ApplicationContext context, final DataIdentifier dataId,
final BusinessAction action, final boolean nestedAction) throws ExternalException {
try {
validate(context, dataId, action, nestedAction);
doManage(context, dataId, action, nestedAction);
} catch (ExternalException e) {
throw e;
} catch (UpdateConflictException e) {
throw e;
} catch (Exception e) {
String message = e.getMessage();
throw new UnableToManageException(message, e);
}
}
private void doManage(final ApplicationContext context, final DataIdentifier dataId,
final BusinessAction action, final boolean nestedAction) throws ExternalException {
try {
final PlatformTransactionManager transactionManager =
TransactionManagerBuilder.build(context, action);
if (transactionManager == null) {
internaldoManage(context, dataId, action, nestedAction);
} else {
TransactionBehaviour behaviour = action.getTransactionBehaviour();
TransactionTemplate transactionTemplate =
TransactionTemplateBuilder.build(transactionManager, behaviour);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
LOG.info("proceeding with action[" + action.getId() + "] within transaction");
internaldoManage(context, dataId, action, nestedAction);
} catch (ExternalException e) {
throw new TransActionRolledBackException(e);
} catch (RuntimeException e) {
throw new TransActionRolledBackException(e);
}
}
});
}
} finally {
// if(logger.isDebugEnabled())
// logger.debug("after transaction -> " + DataStore.toLogString(id));
}
// TODO: after rollback datastore?
}
private void validate(final ApplicationContext context, final DataIdentifier dataId,
final BusinessAction action, final boolean nestedAction) {
if (action == null) {
throw new IllegalArgumentException(
"Business Action is null, possible cause is that the business-action 'ref' does not match with any existing business action in the business tier.");
}
if (context == null) {
throw new IllegalArgumentException("context is null");
}
if (dataId == null) {
throw new IllegalArgumentException("dataId is null");
}
if (!nestedAction && action.isPrivate()) {
throw new IllegalArgumentException(
"Cannot access private business action ["
+ action.getId()
+ "] from outside business tier. Either change the visibility of this action or wrap the action in a public action.");
}
}
private void internaldoManage(final ApplicationContext context, final DataIdentifier dataId,
final BusinessAction action, final boolean nestedAction) throws ExternalException {
try {
ItemExecuter.execute(context, dataId, action.getBusinessActionItems());
} catch (UnableToProcessException e) {
final String header =
"Stack, error occured:\n" + "BusinessAction: [" + action != null ? action.getId() : null
+ "] \n" + "Exception: " + e.getMessage() + "\n" + DataStore.toLogString(dataId);
StackRecorder.addHeader(dataId, header);
LOG.warning(StackRecorder.toLogString(dataId));
}
if (LOG.isLoggable(Level.INFO)) {
String message = "Succesfully performed: " + action.getId() + "\n";
message += DataStore.toLogString(dataId);
LOG.info(message);
}
LOG.fine("Application: " + (context != null ? context.getName() : "") + ", BusinessAction: "
+ (action != null ? action.getId() : ""));
}
public void destroy(ApplicationContext context) throws DestoryFailedException {
ResourcePool.getInstance().destroy(context);
}
public void init(ApplicationContext context) throws InitializationFailedException {
ResourcePool.getInstance().init(context);
}
public void refresh(ApplicationContext context) throws InitializationFailedException {
ResourcePool.getInstance().init(context);
}
}