/*
* Copyright (c) 2012, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* 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 org.wso2.carbon.bpel.b4p.extension;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.common.FaultException;
import org.apache.ode.bpel.runtime.extension.AbstractLongRunningExtensionOperation;
import org.apache.ode.bpel.runtime.extension.ExtensionContext;
import org.apache.ode.utils.DOMUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.wso2.carbon.bpel.b4p.coordination.configuration.CoordinationConfiguration;
import org.wso2.carbon.bpel.b4p.coordination.context.WSConstants;
import org.wso2.carbon.bpel.b4p.coordination.dao.HTCoordinationDAOConnection;
import org.wso2.carbon.bpel.b4p.internal.B4PContentHolder;
import org.wso2.carbon.bpel.core.ode.integration.BPELServerImpl;
import java.util.concurrent.Callable;
import javax.xml.namespace.QName;
/**
* Class that implements <code><peopleActivity></code> related to BPEL4People.
*/
public class BPEL4PeopleExtensionOperation extends AbstractLongRunningExtensionOperation {
private static Log log = LogFactory.getLog(BPEL4PeopleExtensionOperation.class);
private static Log messageTraceLog = LogFactory.getLog(BPEL4PeopleConstants.MESSAGE_TRACE);
private ExtensionContext extensionContext;
private String cid;
private String outputVarName;
private PeopleActivity peopleActivity;
/**
* Initial stuff and calling an external service which causes to send back a response in an indefinite time.
* Correlation values should be set within this method.
*
* @param extensionContext ExtensionContext
* @param cid cid
* @param element ExtensionActivity
*/
@Override
public void runAsync(ExtensionContext extensionContext, String cid, Element element)
throws FaultException {
this.extensionContext = extensionContext;
this.cid = cid;
peopleActivity = new PeopleActivity(extensionContext, element);
String taskID = peopleActivity.invoke(extensionContext);
extensionContext.setCorrelationValues(new String[]{taskID});
extensionContext.setCorrelatorId(peopleActivity.inferCorrelatorId(extensionContext));
outputVarName = peopleActivity.getOutputVarName();
if (log.isDebugEnabled()) {
log.debug("B4P extension invoked by Process " + peopleActivity.getProcessId() + ", pid:" +
extensionContext.getInternalInstance().getPid() + ", task:" + taskID);
}
}
/**
* Called when the response for the above service is received
*
* @param mexId MessageExchange id
*/
@Override
public void onRequestReceived(String mexId) throws FaultException {
if (log.isDebugEnabled()) {
log.debug("People Activity Response received : mexId " + mexId);
}
Element notificationMessageEle = extensionContext.getInternalInstance().getMyRequest(mexId);
if ("".equals(outputVarName) || outputVarName == null) {
// if output variable is null or empty, these is no way to process the response from the task as we do
// not have
// a variable from bpel file to assign the values to. Hence what what we can do is to return a fault and
// exit.
log.error("Output variable not specified correctly for the remoteTask activity.Hence the error condition." +
"Please verify and correct your BPEL process remoteTask");
extensionContext.completeWithFault(
cid,
new FaultException(BPEL4PeopleConstants.B4P_FAULT,
BPEL4PeopleConstants.NON_RECOVERABLE_ERROR));
} else {
Node part = extensionContext.getPartData(notificationMessageEle,
outputVarName);
if (messageTraceLog.isTraceEnabled()) {
messageTraceLog.trace("B4P Response Message: " +
DOMUtils.domToString(notificationMessageEle));
messageTraceLog.trace("B4P Response Part: " +
DOMUtils.domToString(part));
}
if (CoordinationConfiguration.getInstance().isHumantaskCoordinationEnabled() && notificationMessageEle
.hasChildNodes()) {
String taskID = "";
Element correlationHeader = DOMUtils.findChildByName(notificationMessageEle, new QName
(BPEL4PeopleConstants.B4P_NAMESPACE, BPEL4PeopleConstants.B4P_CORRELATION_HEADER), true);
if (correlationHeader != null) {
taskID = correlationHeader.getAttributeNS(BPEL4PeopleConstants.B4P_NAMESPACE,
BPEL4PeopleConstants.B4P_CORRELATION_HEADER_ATTRIBUTE);
try {
deleteCoordinationTaskData(taskID);
} catch (Exception e) {
log.error("Error occurred while cleaning coordination data for task id " + taskID, e);
}
}
//Checking for fault
Element fault = DOMUtils.findChildByName(notificationMessageEle, new QName(WSConstants
.WS_HT_COORDINATION_PROTOCOL_FAULT));
if (fault != null) {
if (fault.hasAttribute("headerPart")) {
if (log.isDebugEnabled()) {
log.debug("Throwing Fault to People Activity Scope since received Fault Protocol Message " +
"for task" + taskID + ".");
}
extensionContext.completeWithFault(cid,
new FaultException(BPEL4PeopleConstants.B4P_FAULT, BPEL4PeopleConstants
.NON_RECOVERABLE_ERROR));
;
}
}
//Checking for Skip
Element skipped = DOMUtils.findChildByName(notificationMessageEle, new QName(WSConstants
.WS_HT_COORDINATION_PROTOCOL_SKIPPED));
if (skipped != null) {
if (skipped.hasAttribute("headerPart")) {
if (log.isDebugEnabled()) {
log.debug("Skipping People Activity since received Skipped Protocol Message for task " +
taskID + ".");
}
//Set extension as complete, since task is skipped. No value write to output variable.
extensionContext.complete(cid);
return;
}
}
}
extensionContext.writeVariable(outputVarName, notificationMessageEle);
extensionContext.complete(cid);
}
}
private boolean deleteCoordinationTaskData(final String taskID) throws Exception {
boolean success = (Boolean) ((BPELServerImpl) B4PContentHolder.getInstance().getBpelServer()).getScheduler()
.execTransaction(new Callable<Object>() {
@Override
public Object call() throws Exception {
HTCoordinationDAOConnection daoConnection = B4PContentHolder.getInstance().getCoordinationController
().getDaoConnectionFactory().getConnection();
return daoConnection.deleteTaskData(taskID);
}
});
return success;
}
}