org.jbpm.bpel.integration.jms.JmsIntegrationService.java Source code

Java tutorial

Introduction

Here is the source code for org.jbpm.bpel.integration.jms.JmsIntegrationService.java

Source

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the JBPM BPEL PUBLIC LICENSE AGREEMENT as
 * published by JBoss Inc.; either version 1.0 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */
package org.jbpm.bpel.integration.jms;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.jms.JMSException;
import javax.jms.Session;
import javax.wsdl.Operation;
import javax.wsdl.Port;
import javax.wsdl.extensions.soap.SOAPAddress;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ibm.wsdl.extensions.soap.SOAPConstants;

import org.jbpm.JbpmContext;
import org.jbpm.bpel.BpelException;
import org.jbpm.bpel.endpointref.EndpointReference;
import org.jbpm.bpel.graph.def.BpelProcessDefinition;
import org.jbpm.bpel.graph.exe.BpelFaultException;
import org.jbpm.bpel.integration.IntegrationService;
import org.jbpm.bpel.integration.client.Caller;
import org.jbpm.bpel.integration.client.SoapCaller;
import org.jbpm.bpel.integration.def.InvokeAction;
import org.jbpm.bpel.integration.def.PartnerLinkDefinition;
import org.jbpm.bpel.integration.def.ReceiveAction;
import org.jbpm.bpel.integration.def.ReplyAction;
import org.jbpm.bpel.variable.def.MessageType;
import org.jbpm.bpel.variable.exe.MessageValue;
import org.jbpm.bpel.wsdl.xml.WsdlUtil;
import org.jbpm.graph.exe.Token;

/**
 * @author Alejandro Guizar
 * @version $Revision$ $Date: 2008/01/30 07:18:22 $
 */
public class JmsIntegrationService implements IntegrationService {

    private final JmsIntegrationServiceFactory factory;

    private List requestListeners = new ArrayList();

    private static final Log log = LogFactory.getLog(JmsIntegrationService.class);
    private static final long serialVersionUID = 1L;

    JmsIntegrationService(JmsIntegrationServiceFactory factory) {
        this.factory = factory;
    }

    public void receive(ReceiveAction receiveAction, Token token, boolean oneShot) {
        IntegrationControl integrationControl = getIntegrationControl(token);
        try {
            jmsReceive(receiveAction, token, integrationControl, oneShot);
        } catch (JMSException e) {
            throw new BpelException("could not create request listener", e);
        }
    }

    void jmsReceive(ReceiveAction receiveAction, Token token, IntegrationControl integrationControl,
            boolean oneShot) throws JMSException {
        Session jmsSession = integrationControl.createJmsSession();
        RequestListener requestListener = new RequestListener(receiveAction, token, integrationControl, jmsSession,
                oneShot);
        requestListeners.add(requestListener);
    }

    public void receive(List receivers, Token token) {
        IntegrationControl integrationControl = getIntegrationControl(token);
        try {
            jmsReceive(receivers, token, integrationControl);
        } catch (JMSException e) {
            throw new BpelException("could not create request listeners", e);
        }
    }

    void jmsReceive(List receivers, Token token, IntegrationControl integrationControl) throws JMSException {
        Session jmsSession = integrationControl.createJmsSession();
        Iterator receiverIt = receivers.iterator();
        while (receiverIt.hasNext()) {
            ReceiveAction receiveAction = (ReceiveAction) receiverIt.next();
            RequestListener requestListener = new RequestListener(receiveAction, token, integrationControl,
                    jmsSession);
            requestListeners.add(requestListener);
        }
    }

    public void cancelReception(ReceiveAction receiveAction, Token token) {
        try {
            jmsCancelReception(receiveAction, token, getIntegrationControl(token));
        } catch (JMSException e) {
            log.debug("could not close request listener", e);
        }
    }

    void jmsCancelReception(ReceiveAction receiveAction, Token token, IntegrationControl integrationControl)
            throws JMSException {
        RequestListener requestListener = integrationControl.removeRequestListener(receiveAction, token);
        // some competing thread might have removed the request listener already
        if (requestListener == null)
            return;
        /*
         * this service may or may not have created the request listener; in the affirmative case, the
         * call below prevents the listener from being opened when the service closes; in the negative
         * case, the call has no effect
         */
        requestListeners.remove(requestListener);
        // release listener resources
        requestListener.close();
    }

    public void reply(ReplyAction replyAction, Token token) {
        try {
            jmsReply(replyAction, token);
        } catch (JMSException e) {
            throw new BpelException("could not send reply", e);
        }
    }

    private void jmsReply(ReplyAction replyAction, Token token) throws JMSException {
        // extract the output parts
        Map parts = replyAction.writeMessage(token);

        // obtain the outstanding request for the partner link, operation and
        // message exchange of the replier
        IntegrationControl integrationControl = getIntegrationControl(token);
        OutstandingRequest request = integrationControl.removeOutstandingRequest(replyAction, token);

        Session jmsSession = integrationControl.createJmsSession();
        try {
            request.sendReply(parts, replyAction.getFaultName(), jmsSession);
        } finally {
            jmsSession.close();
        }
    }

    public void invoke(InvokeAction invokeAction, Token token) {
        // acquire caller for partner
        IntegrationControl integrationControl = getIntegrationControl(token);
        Caller caller = integrationControl.createCaller(invokeAction, token);
        try {
            // extract input parts
            Map inputParts = invokeAction.writeMessage(token);
            log.debug("sending input " + inputParts + " on " + invokeAction + " for " + token);

            // is this a request/response operation?
            Operation operation = invokeAction.getOperation();
            if (operation.getOutput() != null) {
                try {
                    // send input, block for output
                    Map outputParts = caller.call(operation.getName(), inputParts);
                    log.debug("received output " + outputParts + " on " + invokeAction + " for " + token);
                    // assign output parts
                    invokeAction.readMessage(token, outputParts);
                } catch (BpelFaultException e) {
                    replaceMessageType(e, token);
                    throw e;
                }
            } else {
                // fire and forget
                caller.callOneWay(operation.getName(), inputParts);
            }
        } finally {
            integrationControl.removeCaller(invokeAction, token);
            caller.close();
        }
    }

    /**
     * Replaces the transient message type in the given fault exception with the persistent object
     * from the process definition. {@link SoapCaller} produces faults with transient message types.
     */
    private static void replaceMessageType(BpelFaultException faultException, Token token) {
        // extract the message value from the exception
        MessageValue faultData = faultException.getFaultInstance().getMessageValue();

        // BPEL-286 a request/response call that throws SOAPException raises fault with no data
        if (faultData == null)
            return;

        // retrieve persistent type from import definition
        BpelProcessDefinition processDefinition = (BpelProcessDefinition) token.getProcessInstance()
                .getProcessDefinition();
        MessageType persistentType = processDefinition.getImportDefinition()
                .getMessageType(faultData.getType().getName());

        // replace transient type with persistent type
        faultData.setType(persistentType);
    }

    public void cancelInvocation(InvokeAction invokeAction, Token token) {
        Caller caller = getIntegrationControl(token).removeCaller(invokeAction, token);
        if (caller != null)
            caller.close();
    }

    public EndpointReference getMyReference(PartnerLinkDefinition partnerLink, Token token) {
        IntegrationControl integrationControl = getIntegrationControl(token);
        EndpointReference myReference = integrationControl.getPartnerLinkEntry(partnerLink).getMyReference();
        // fill in address, if missing
        if (myReference.getAddress() == null) {
            Port myPort = myReference.selectPort(integrationControl.getMyCatalog());
            SOAPAddress soapAddress = (SOAPAddress) WsdlUtil.getExtension(myPort.getExtensibilityElements(),
                    SOAPConstants.Q_ELEM_SOAP_ADDRESS);
            if (soapAddress != null)
                myReference.setAddress(soapAddress.getLocationURI());
        }
        return myReference;
    }

    public void close() {
        JbpmContext jbpmContext = factory.getJbpmConfiguration().getCurrentJbpmContext();
        // open request listeners only if transaction is not marked for rollback
        if (!jbpmContext.getServices().getTxService().isRollbackOnly()) {
            try {
                openRequestListeners();
            } catch (JMSException e) {
                throw new BpelException("could not open request listeners", e);
            }
        } else
            closeRequestListeners();
    }

    private void openRequestListeners() throws JMSException {
        for (int i = 0, n = requestListeners.size(); i < n; i++) {
            RequestListener requestListener = (RequestListener) requestListeners.get(i);
            requestListener.open();
        }
    }

    private void closeRequestListeners() {
        for (int i = 0, n = requestListeners.size(); i < n; i++) {
            RequestListener requestListener = (RequestListener) requestListeners.get(i);
            try {
                requestListener.close();
            } catch (JMSException e) {
                log.debug("could not close request listener", e);
            }
        }
    }

    IntegrationControl getIntegrationControl(Token token) {
        return factory.getIntegrationControl(token.getProcessInstance().getProcessDefinition());
    }

    public static JmsIntegrationService get(JbpmContext jbpmContext) {
        return (JmsIntegrationService) jbpmContext.getServices().getService(IntegrationService.SERVICE_NAME);
    }
}