/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* 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.jbpm.process.workitem.jms;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.naming.InitialContext;
import org.drools.core.process.instance.impl.WorkItemImpl;
import org.jbpm.process.workitem.AbstractLogOrThrowWorkItemHandler;
import org.kie.api.runtime.process.WorkItem;
import org.kie.api.runtime.process.WorkItemManager;
import org.kie.internal.runtime.Cacheable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JMSSendTaskWorkItemHandler extends AbstractLogOrThrowWorkItemHandler implements Cacheable {
private static final Logger logger = LoggerFactory.getLogger(JMSSendTaskWorkItemHandler.class);
private String connectionFactoryName;
private String destinationName;
private ConnectionFactory connectionFactory;
private Destination destination;
private boolean transacted = false;
public JMSSendTaskWorkItemHandler() {
this.connectionFactoryName = "java:/JmsXA";
this.destinationName = "queue/KIE.SIGNAL";
init();
}
public JMSSendTaskWorkItemHandler(String connectionFactoryName, String destinationName) {
this.connectionFactoryName = connectionFactoryName;
this.destinationName = destinationName;
init();
}
public JMSSendTaskWorkItemHandler(ConnectionFactory connectionFactory, Destination destination) {
this.connectionFactory = connectionFactory;
this.destination = destination;
init();
}
public JMSSendTaskWorkItemHandler(String connectionFactoryName, String destinationName, boolean transacted) {
this.connectionFactoryName = connectionFactoryName;
this.destinationName = destinationName;
this.transacted = transacted;
init();
}
public JMSSendTaskWorkItemHandler(ConnectionFactory connectionFactory, Destination destination, boolean transacted) {
this.connectionFactory = connectionFactory;
this.destination = destination;
this.transacted = transacted;
init();
}
protected void init() {
try {
InitialContext ctx = new InitialContext();
if (this.connectionFactory == null) {
this.connectionFactory = (ConnectionFactory) ctx.lookup(connectionFactoryName);
}
if (this.destination == null) {
this.destination = (Destination) ctx.lookup(destinationName);
}
logger.info("JMS based work item handler successfully activated on destination {}", destination);
} catch (Exception e) {
logger.error("Unable to initialize JMS send work item handler due to {}", e.getMessage(), e);
}
}
protected Message createMessage(WorkItem workItem, Session session) throws JMSException {
BytesMessage message = session.createBytesMessage();
// set properties
addPropertyIfExists("KIE_Signal", workItem.getParameter("Signal"), message);
addPropertyIfExists("KIE_SignalProcessInstanceId", workItem.getParameter("SignalProcessInstanceId"), message);
addPropertyIfExists("KIE_SignalWorkItemId", workItem.getParameter("SignalWorkItemId"), message);
addPropertyIfExists("KIE_SignalDeploymentId", workItem.getParameter("SignalDeploymentId"), message);
addPropertyIfExists("KIE_ProcessInstanceId", workItem.getProcessInstanceId(), message);
addPropertyIfExists("KIE_DeploymentId", ((WorkItemImpl)workItem).getDeploymentId(), message);
Object data = workItem.getParameter("Data");
if (data != null) {
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oout = new ObjectOutputStream(bout);
oout.writeObject(data);
message.writeBytes(bout.toByteArray());
} catch (IOException e) {
logger.warn("Error serializing context data", e);
}
}
return message;
}
@Override
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
if (connectionFactory == null || destination == null) {
throw new RuntimeException("Connection factory and destination must be set for JMS send task handler");
}
Connection connection = null;
Session session = null;
MessageProducer producer = null;
try {
connection = connectionFactory.createConnection();
session = connection.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
Message message = createMessage(workItem, session);
producer = session.createProducer(destination);
producer.send(message);
} catch (Exception e) {
handleException(e);
} finally {
if (producer != null) {
try {
producer.close();
} catch (JMSException e) {
logger.warn("Error when closing producer", e);
}
}
if (session != null) {
try {
session.close();
} catch (JMSException e) {
logger.warn("Error when closing queue session", e);
}
}
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
logger.warn("Error when closing queue connection", e);
}
}
}
}
@Override
public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
// no-op
}
@Override
public void close() {
connectionFactory = null;
destination = null;
}
protected void addPropertyIfExists(String propertyName, Object properyValue, Message msg) throws JMSException {
if (properyValue != null) {
msg.setObjectProperty(propertyName, properyValue);
}
}
}