/*
* Copyright 2013 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.executor;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManagerFactory;
import org.jbpm.executor.impl.AvailableJobsExecutor;
import org.jbpm.executor.impl.ClassCacheManager;
import org.jbpm.executor.impl.ExecutorImpl;
import org.jbpm.executor.impl.ExecutorRunnable;
import org.jbpm.executor.impl.ExecutorServiceImpl;
import org.jbpm.executor.impl.event.ExecutorEventSupport;
import org.jbpm.executor.impl.jpa.ExecutorQueryServiceImpl;
import org.jbpm.executor.impl.jpa.ExecutorRequestAdminServiceImpl;
import org.jbpm.executor.impl.jpa.JPAExecutorStoreService;
import org.jbpm.executor.impl.mem.InMemoryExecutorAdminServiceImpl;
import org.jbpm.executor.impl.mem.InMemoryExecutorQueryServiceImpl;
import org.jbpm.executor.impl.mem.InMemoryExecutorStoreService;
import org.jbpm.shared.services.impl.TransactionalCommandService;
import org.kie.api.executor.Executor;
import org.kie.api.executor.ExecutorAdminService;
import org.kie.api.executor.ExecutorQueryService;
import org.kie.api.executor.ExecutorService;
import org.kie.api.executor.ExecutorStoreService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Creates singleton instance of <code>ExecutorService</code> that shall be used outside of CDI
* environment.
*/
public class ExecutorServiceFactory {
private final static String mode = System.getProperty( "org.jbpm.cdi.executor.mode", "singleton" );
private final static String availableJobsExecutorName = System.getProperty(
"org.jbpm.cdi.executor.jndi", "java:module/AvailableJobsExecutor" );
private static final Logger logger = LoggerFactory.getLogger(ExecutorServiceFactory.class);
private static ExecutorService serviceInstance;
public static synchronized ExecutorService newExecutorService(EntityManagerFactory emf){
if ( mode.equalsIgnoreCase( "singleton" ) ) {
if (serviceInstance == null) {
serviceInstance = configure(emf);
}
return serviceInstance;
} else {
return configure(emf);
}
}
public static synchronized ExecutorService newExecutorService(){
if ( mode.equalsIgnoreCase( "singleton" ) ) {
if (serviceInstance == null) {
serviceInstance = configure();
}
return serviceInstance;
} else {
return configure();
}
}
public static synchronized void resetExecutorService(ExecutorService executorService) {
if (executorService.equals(serviceInstance)) {
serviceInstance = null;
}
}
private static ExecutorService configure(EntityManagerFactory emf) {
ExecutorEventSupport eventSupport = new ExecutorEventSupport();
// create instances of executor services
ExecutorQueryService queryService = new ExecutorQueryServiceImpl(true);
Executor executor = new ExecutorImpl();
ExecutorAdminService adminService = new ExecutorRequestAdminServiceImpl();
// create executor for persistence handling
TransactionalCommandService commandService = new TransactionalCommandService(emf);
ExecutorStoreService storeService = new JPAExecutorStoreService(true);
((JPAExecutorStoreService)storeService).setCommandService(commandService);
((JPAExecutorStoreService)storeService).setEmf(emf);
((JPAExecutorStoreService)storeService).setEventSupport(eventSupport);
((ExecutorImpl) executor).setExecutorStoreService(storeService);
((ExecutorImpl) executor).setEventSupport(eventSupport);
// set executor on all instances that requires it
((ExecutorQueryServiceImpl) queryService).setCommandService(commandService);
((ExecutorRequestAdminServiceImpl) adminService).setCommandService(commandService);
// configure services
ExecutorService service = new ExecutorServiceImpl(executor);
((ExecutorServiceImpl)service).setQueryService(queryService);
((ExecutorServiceImpl)service).setExecutor(executor);
((ExecutorServiceImpl)service).setAdminService(adminService);
((ExecutorServiceImpl)service).setEventSupport(eventSupport);
return service;
}
private static ExecutorService configure() {
// create instances of executor services
ExecutorEventSupport eventSupport = new ExecutorEventSupport();
ExecutorQueryService queryService = new InMemoryExecutorQueryServiceImpl(true);
Executor executor = new ExecutorImpl();
ExecutorAdminService adminService = new InMemoryExecutorAdminServiceImpl(true);
InMemoryExecutorStoreService storeService = new InMemoryExecutorStoreService(true);
((InMemoryExecutorStoreService)storeService).setEventSupport(eventSupport);
((ExecutorImpl) executor).setExecutorStoreService(storeService);
((ExecutorImpl) executor).setEventSupport(eventSupport);
// set executor on all instances that requires it
((InMemoryExecutorQueryServiceImpl) queryService).setStoreService(storeService);
((InMemoryExecutorAdminServiceImpl) adminService).setStoreService(storeService);
// configure services
ExecutorService service = new ExecutorServiceImpl(executor);
((ExecutorServiceImpl)service).setQueryService(queryService);
((ExecutorServiceImpl)service).setExecutor(executor);
((ExecutorServiceImpl)service).setAdminService(adminService);
((ExecutorServiceImpl)service).setEventSupport(eventSupport);
return service;
}
public static ExecutorRunnable buildRunable(EntityManagerFactory emf, ExecutorEventSupport eventSupport) {
ExecutorRunnable runnable = new ExecutorRunnable();
AvailableJobsExecutor jobExecutor = null;
try {
jobExecutor = InitialContext.doLookup(availableJobsExecutorName);
} catch (Exception e) {
jobExecutor = buildJobExecutor(emf, eventSupport);
}
runnable.setAvailableJobsExecutor(jobExecutor);
return runnable;
}
private static AvailableJobsExecutor buildJobExecutor(EntityManagerFactory emf, ExecutorEventSupport eventSupport) {
AvailableJobsExecutor jobExecutor;
jobExecutor = new AvailableJobsExecutor();
ClassCacheManager classCacheManager = new ClassCacheManager();
ExecutorQueryService queryService = new ExecutorQueryServiceImpl(true);
TransactionalCommandService cmdService = new TransactionalCommandService(emf);
ExecutorStoreService storeService = new JPAExecutorStoreService(true);
((JPAExecutorStoreService) storeService).setCommandService(cmdService);
((JPAExecutorStoreService) storeService).setEmf(emf);
((ExecutorQueryServiceImpl) queryService).setCommandService(cmdService);
jobExecutor.setClassCacheManager(classCacheManager);
jobExecutor.setQueryService(queryService);
jobExecutor.setExecutorStoreService(storeService);
jobExecutor.setEventSupport(eventSupport);
// provide bean manager instance as context data as it might not be available to
// be looked up from JNDI in non managed threads
try {
Object beanManager = InitialContext.doLookup("java:comp/BeanManager");
jobExecutor.addContextData("BeanManager", beanManager);
} catch (NamingException ex) {
logger.debug("CDI beans cannot be used in executor commands, because no CDI manager has been found in JNDI.");
}
return jobExecutor;
}
public static ExecutorRunnable buildRunable(ExecutorEventSupport eventSupport) {
ExecutorRunnable runnable = new ExecutorRunnable();
AvailableJobsExecutor jobExecutor = null;
try {
jobExecutor = InitialContext.doLookup(availableJobsExecutorName);
} catch (Exception e) {
jobExecutor = new AvailableJobsExecutor();
ClassCacheManager classCacheManager = new ClassCacheManager();
InMemoryExecutorStoreService storeService = new InMemoryExecutorStoreService(true);
InMemoryExecutorQueryServiceImpl queryService = new InMemoryExecutorQueryServiceImpl(true);
queryService.setStoreService(storeService);
jobExecutor.setClassCacheManager(classCacheManager);
jobExecutor.setQueryService(queryService);
jobExecutor.setExecutorStoreService(storeService);
jobExecutor.setEventSupport(eventSupport);
// provide bean manager instance as context data as it might not be available to
// be looked up from JNDI in non managed threads
try {
Object beanManager = InitialContext.doLookup("java:comp/BeanManager");
jobExecutor.addContextData("BeanManager", beanManager);
} catch (NamingException ex) {
logger.debug("CDI beans cannot be used in executor commands, because no CDI manager has been found in JNDI.");
}
}
runnable.setAvailableJobsExecutor(jobExecutor);
return runnable;
}
}