/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 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. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.processFlow.knowledgeService;
import java.io.File;
import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.net.ConnectException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Local;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Remote;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.inject.Inject;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.naming.Context;
import org.apache.log4j.Logger;
import org.drools.definition.process.Process;
import org.drools.io.Resource;
import org.jbpm.persistence.processinstance.ProcessInstanceInfo;
@Remote(IKnowledgeSession.class)
@Local(IBaseKnowledgeSession.class)
@Singleton(name="prodKSessionProxy")
@Startup
@Lock(LockType.READ)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class KnowledgeSessionService implements IKnowledgeSession, KnowledgeSessionServiceMXBean {
private static Logger log = Logger.getLogger("KnowledgeSessionService");
@Inject
private IKnowledgeSession kBean;
protected ObjectName objectName;
protected MBeanServer platformMBeanServer;
private final String gwDObjName = "processFlow.knowledgeSessionQueue";
private Connection connectionObj;
@javax.annotation.Resource(name="java:/JmsXA")
private ConnectionFactory cFactory;
@javax.annotation.Resource(name="java:/queue/processFlow.knowledgeSessionQueue")
private Destination gwDObj;
@PostConstruct
public void start() throws Exception {
Context jndiContext = null;
try {
objectName = new ObjectName("org.jboss.processFlow:type="+this.getClass().getName());
platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
try {
platformMBeanServer.getObjectInstance(objectName);
log.warn("start() following MBean already registered with Platform MBean Server : "+objectName);
}catch(InstanceNotFoundException x){
platformMBeanServer.registerMBean(this, objectName);
}
connectionObj = cFactory.createConnection();
// force immediate initialization of CDI ksessionService bean
kBean.dumpSessionStatusInfo();
} catch(Exception x) {
throw new RuntimeException(x);
}
}
@PreDestroy
public void stop() throws Exception{
log.info("stop");
try {
platformMBeanServer.unregisterMBean(this.objectName);
if(connectionObj != null)
connectionObj.close();
} catch (Exception e) {
throw new RuntimeException("Problem during unregistration of Monitoring into JMX:" + e);
}
}
public void createOrRebuildKnowledgeBaseViaKnowledgeAgentOrBuilder() {
kBean.createOrRebuildKnowledgeBaseViaKnowledgeAgentOrBuilder();
}
public void rebuildKnowledgeBaseViaKnowledgeAgent() throws ConnectException{
kBean.rebuildKnowledgeBaseViaKnowledgeAgent();
}
public void rebuildKnowledgeBaseViaKnowledgeBuilder() {
kBean.rebuildKnowledgeBaseViaKnowledgeBuilder();
}
public void addProcessToKnowledgeBase(Process processObj, Resource resourceObj) {
kBean.addProcessToKnowledgeBase(processObj, resourceObj);
}
public void addProcessToKnowledgeBase(File bpmnFile) {
kBean.addProcessToKnowledgeBase(bpmnFile);
}
public String getAllProcessesInPackage(String pkgName) throws ConnectException {
return kBean.getAllProcessesInPackage(pkgName);
}
public String printKnowledgeBaseContent() {
return kBean.printKnowledgeBaseContent();
}
public String printWorkItemHandlers() {
return kBean.printWorkItemHandlers();
}
public String printActiveProcessInstances(Map<String,Object> queryCriteria) {
return kBean.printActiveProcessInstances(queryCriteria);
}
public List<SerializableProcessMetaData> retrieveProcesses() throws Exception {
return kBean.retrieveProcesses();
}
public SerializableProcessMetaData getProcess(String processId) {
return kBean.getProcess(processId);
}
public void removeProcess(String processId) {
throw new UnsupportedOperationException();
}
public List<ProcessInstanceInfo> getActiveProcessInstances(Map<String, Object> queryCriteria) {
return kBean.getActiveProcessInstances(queryCriteria);
}
public String dumpSessionStatusInfo() {
return kBean.dumpSessionStatusInfo();
}
public String dumpBAMProducerPoolInfo() {
return kBean.dumpBAMProducerPoolInfo();
}
/***********************************************************************************************************
************* Process Instance Management : CONTAINER MANAGED TRANSACTIONS *********/
/**
*startProcessAndReturnId
*<pre>
*- this method will block until the newly created process instance either completes or arrives at a wait state
*- at completion of the process instance (or arrival at a wait state), the StatefulKnowledgeSession will be disposed
* will deliver to KSessionManagement via JMS if inbound pInstanceVariables map contains an entry keyed by IKnowledgeSession.DELIVER_ASYNC
*</pre>
*/
public Map<String, Object> startProcessAndReturnId(String processId, Map<String, Object> pInstanceVariables) {
if(pInstanceVariables != null && pInstanceVariables.containsKey(IKnowledgeSession.DELIVER_ASYNC)) {
Session sessionObj = null;
try {
pInstanceVariables.remove(IKnowledgeSession.DELIVER_ASYNC);
sessionObj = connectionObj.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer m_sender = sessionObj.createProducer(gwDObj);
ObjectMessage oMessage = sessionObj.createObjectMessage();
oMessage.setObject((HashMap<String,Object>)pInstanceVariables);
oMessage.setStringProperty(IKnowledgeSession.OPERATION_TYPE, IKnowledgeSession.START_PROCESS_AND_RETURN_ID);
oMessage.setStringProperty(IKnowledgeSession.PROCESS_ID, processId);
m_sender.send(oMessage);
Map<String, Object> returnMap = new HashMap<String, Object>();
returnMap.put(IKnowledgeSession.PROCESS_INSTANCE_ID, new Long(0));
return returnMap;
} catch(JMSException x) {
throw new RuntimeException(x);
}finally {
if(sessionObj != null) {
try { sessionObj.close(); }catch(Exception x){ x.printStackTrace(); }
}
}
} else {
return kBean.startProcessAndReturnId(processId, pInstanceVariables);
}
}
public int signalEvent(String signalType, Object signalValue, Long processInstanceId, Integer ksessionId) {
return kBean.signalEvent(signalType, signalValue, processInstanceId, ksessionId);
}
public void abortProcessInstance(Long processInstanceId, Integer ksessionId) {
kBean.abortProcessInstance(processInstanceId, ksessionId);
}
public void upgradeProcessInstance(long processInstanceId, String processId, Map<String, Long> nodeMapping) {
kBean.upgradeProcessInstance(processInstanceId, processId, nodeMapping);
}
public String printActiveProcessInstanceVariables(Long processInstanceId, Integer ksessionId) {
return kBean.printActiveProcessInstanceVariables(processInstanceId, ksessionId);
}
public Map<String, Object> getActiveProcessInstanceVariables(Long processInstanceId, Integer ksessionId) {
return kBean.getActiveProcessInstanceVariables(processInstanceId, ksessionId);
}
public void setProcessInstanceVariables(Long processInstanceId, Map<String, Object> variables, Integer ksessionId) {
kBean.setProcessInstanceVariables(processInstanceId, variables, ksessionId);
}
/**
* completeWorkItem
* <pre>
* this method will block until the existing process instance either completes or arrives at a wait state
*
* will deliver to KSessionManagement via JMS if inbound pInstanceVariables map contains an entry keyed by IKnowledgeSession.DELIVER_ASYNC
* </pre>
*/
public void completeWorkItem(Long workItemId, Map<String, Object> pInstanceVariables, Long pInstanceId, Integer ksessionId) {
if(pInstanceVariables != null && pInstanceVariables.containsKey(IKnowledgeSession.DELIVER_ASYNC)) {
Session sessionObj = null;
try {
pInstanceVariables.remove(IKnowledgeSession.DELIVER_ASYNC);
sessionObj = connectionObj.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer m_sender = sessionObj.createProducer(gwDObj);
ObjectMessage oMessage = sessionObj.createObjectMessage();
oMessage.setObject((HashMap<String,Object>)pInstanceVariables);
oMessage.setStringProperty(IKnowledgeSession.OPERATION_TYPE, IKnowledgeSession.COMPLETE_WORK_ITEM);
oMessage.setLongProperty(IKnowledgeSession.WORK_ITEM_ID, workItemId);
oMessage.setLongProperty(IKnowledgeSession.PROCESS_INSTANCE_ID, pInstanceId);
oMessage.setIntProperty(IKnowledgeSession.KSESSION_ID, ksessionId);
m_sender.send(oMessage);
} catch(JMSException x) {
throw new RuntimeException(x);
}finally {
if(sessionObj != null) {
try { sessionObj.close(); }catch(Exception x){ x.printStackTrace(); }
}
}
} else {
kBean.completeWorkItem(workItemId, pInstanceVariables, pInstanceId, ksessionId);
}
}
public int processJobExecutionContext(Serializable jobExecutionContext) {
return kBean.processJobExecutionContext(jobExecutionContext);
}
@Override
public String getCurrentTimerJobsAsJson(String jobGroup) {
return kBean.getCurrentTimerJobsAsJson(jobGroup);
}
@Override
public int purgeCurrentTimerJobs(String jobGroup) {
return kBean.purgeCurrentTimerJobs(jobGroup);
}
}