/*
* #%L
* Processiva Business Processes Platform
* %%
* Copyright (C) 2012 Cohesiva
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package com.cohesiva.processes.jbpm.serviceImpl.base;
import java.nio.charset.Charset;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.persistence.info.WorkItemInfo;
import org.drools.persistence.jpa.JPAKnowledgeService;
import org.drools.process.instance.WorkItem;
import org.drools.runtime.Environment;
import org.drools.runtime.EnvironmentName;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.process.WorkItemManager;
import org.jbpm.persistence.processinstance.ProcessInstanceInfo;
import org.jbpm.process.audit.JPAWorkingMemoryDbLogger;
import org.jbpm.process.workitem.email.EmailWorkItemHandler;
import org.jbpm.process.workitem.wsht.MinaHTWorkItemHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.cohesiva.processes.jbpm.handlers.BaseAsynchronousWorkItemHandler;
import com.cohesiva.processes.jbpm.handlers.BaseSynchronousWorkItemHandler;
import com.cohesiva.processes.jbpm.service.base.IJbpmBase;
import com.cohesiva.processes.jbpm.service.base.ISessionManager;
import com.cohesiva.processes.jbpm.service.handlers.IHandlersService;
import com.cohesiva.processes.jbpm.service.processes.IProcessesVariablesService;
import com.cohesiva.processes.jbpm.serviceImpl.processes.ProcessService;
@Service
public class JbpmBase implements IJbpmBase {
private StatefulKnowledgeSession ksession = null;
private JPAWorkingMemoryDbLogger logger = null;
private MinaHTWorkItemHandler humanTaskHandler = null;
@Autowired
private ISessionManager sessionManager;
@Autowired
private ProcessService processService;
@Autowired
private IHandlersService handlersService;
@Autowired
private EmailWorkItemHandler emailWorkItemHandler;
@Autowired
private IProcessesVariablesService processVariables;
// Injected database connection:
@PersistenceUnit(unitName = "jbpmPU")
private EntityManagerFactory emf;
// Service initialization method - load jbpm session
@PostConstruct
public void init() {
try {
if (ksession == null) {
System.out.println("DEFOLT CZARSET: "
+ Charset.defaultCharset());
// load up the knowledge base
KnowledgeBase kbase = readKnowledgeBase();
// create knowledge session to interact with the engine
ksession = createKnowledgeSession(kbase);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@PreDestroy
public void destroy() {
if (humanTaskHandler != null) {
try {
humanTaskHandler.dispose();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (logger != null) {
logger.dispose();
}
if (ksession != null) {
ksession.dispose();
}
}
public StatefulKnowledgeSession getSession() {
return ksession;
}
private KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory
.newKnowledgeBuilder();
kbuilder.add(ResourceFactory
.newClassPathResource("jbpm/basket/basketWeekly.bpmn"),
ResourceType.BPMN2);
kbuilder.add(ResourceFactory
.newClassPathResource("jbpm/basket/basketSubscribe.bpmn"),
ResourceType.BPMN2);
kbuilder.add(ResourceFactory
.newClassPathResource("jbpm/basket/basketUnsubscribe.bpmn"),
ResourceType.BPMN2);
kbuilder.add(ResourceFactory
.newClassPathResource("jbpm/basket/basketPayment.bpmn"),
ResourceType.BPMN2);
kbuilder.add(ResourceFactory
.newClassPathResource("jbpm/basket/basketBalanceInquiry.bpmn"),
ResourceType.BPMN2);
/*
* kbuilder.add(
* ResourceFactory.newClassPathResource("jbpm/hr/getCV.bpmn"),
* ResourceType.BPMN2);
*/
return kbuilder.newKnowledgeBase();
}
private StatefulKnowledgeSession createKnowledgeSession(KnowledgeBase kbase) {
Environment env = KnowledgeBaseFactory.newEnvironment();
env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, emf);
// { Try restoring latest session from persistence.
try {
ksession = JPAKnowledgeService.loadStatefulKnowledgeSession(
sessionManager.getLatestSessionId(), kbase, null, env);
} catch (RuntimeException e) {
System.out
.println("Nie można odtworzyć ostatnio używanej sesji, zostanie utworzona nowa");
}
// }
// { No session restored - create new session and save it's id.
if (ksession == null) {
ksession = JPAKnowledgeService.newStatefulKnowledgeSession(kbase,
null, env);
sessionManager.saveLatestSessionId(ksession.getId());
}
// }
// Register db logger.
logger = new JPAWorkingMemoryDbLogger(ksession);
// Register work item handlers.
this.registerHandlers(ksession);
// Restore asynchronous work item that were not finished.
this.restoreWorkItems(ksession);
return ksession;
}
private void registerHandlers(StatefulKnowledgeSession ksession) {
WorkItemManager workItemManager = ksession.getWorkItemManager();
humanTaskHandler = new MinaHTWorkItemHandler(ksession);
humanTaskHandler.setIpAddress("127.0.0.1");
humanTaskHandler.setPort(9123);
// connect on startup to listen for notifications from human task server
humanTaskHandler.connect();
// register email work item handler
workItemManager.registerWorkItemHandler("Email", emailWorkItemHandler);
// register human task work item handler
workItemManager.registerWorkItemHandler("Human Task", humanTaskHandler);
// {{ register custom work item handlers
List<BaseSynchronousWorkItemHandler> syncHandlers = handlersService
.getCustomSyncHandlers();
for (BaseSynchronousWorkItemHandler syncHandler : syncHandlers) {
workItemManager.registerWorkItemHandler(
syncHandler.getWorkItemId(), syncHandler);
}
List<BaseAsynchronousWorkItemHandler> asyncHandlers = handlersService
.getCustomAsyncHandlers();
for (BaseAsynchronousWorkItemHandler asyncHandler : asyncHandlers) {
asyncHandler.setKSession(ksession);
workItemManager.registerWorkItemHandler(
asyncHandler.getWorkItemId(), asyncHandler);
}
// }
}
/*
* Function restores asynchronous work items of unfinished processes
* or kills process instance if work item shouldn't be restored
*/
private void restoreWorkItems(StatefulKnowledgeSession ksession) {
List<WorkItemInfo> persistedWorkItems = handlersService
.getPersistedHandlers();
for (WorkItemInfo workItemInfo : persistedWorkItems) {
String handlerId = workItemInfo.getName();
BaseAsynchronousWorkItemHandler asyncHandler = handlersService
.getAsyncHandler(handlerId);
if (asyncHandler != null && asyncHandler.shouldBeRestored()) {
// { restore handler and continue process
WorkItem workItem = workItemInfo.getWorkItem(
ksession.getEnvironment(), null);
if (workItem != null) {
asyncHandler.setKSession(ksession);
asyncHandler.executeWorkItem(workItem,
ksession.getWorkItemManager());
}
// }
} else {
// { kill process
long instanceId = workItemInfo.getProcessInstanceId();
ksession.signalEvent(processVariables.getKillSignal(), null,
instanceId);
// }
}
}
}
public MinaHTWorkItemHandler getHumanTaskHandler() {
return this.humanTaskHandler;
}
public void signalEvent(String event, String processId) {
List<ProcessInstanceInfo> runningInstances = processService
.getRunningInstances(processId);
for (ProcessInstanceInfo instance : runningInstances) {
ksession.signalEvent(event, null, instance.getId());
}
}
}