It appears that our implementation of using Quartz - JDBCJobStore along with Spring, Hibernate and Websphere is throwing unmanaged threads.
I have done some reading and found a tech article from IBM stating that the usage of Quartz with Spring will cause that. They make the suggestion of using CommnonJ to address this issue.
I have done some further research and the only examples I have seen so far all deal with the plan old JobStore that is not in a database.
So, I was wondering if anyone has an example of the solution for this issue.
Thanks
We have a working solution for this (two actually).
1) Alter the quartz source code to use a WorkManager daemon thread for the main scheduler thread. It works, but requires changing quarts. We didn't use this though since we didn't want maintain a hacked version of quartz. (That reminds me, I was going to submit this to the project but completely forgot)
2) Create a WorkManagerThreadPool to be used as the quartz threadpool. Implement the interface for the quartz ThreadPool, so that each task that is triggered within quartz is wrapped in a commonj Work object that will then be scheduled in the WorkManager. The key is that the WorkManager in the WorkManagerThreadPool has to be initialized before the scheduler is started, from a Java EE thread (such as servlet initialization). The WorkManagerThreadPool must then create a daemon thread which will handle all the scheduled tasks by creating and scheduling the new Work objects. This way, the scheduler (on its own thread) is passing the tasks to a managed thread (the Work daemon).
Not simple, and unfortunately I do not have code readily available to include.
Adding another answer to the thread, since i found a solution for this, finally.
My environment: WAS 8.5.5, Quartz 1.8.5, no Spring.
The problem i had was the (above stated) unmanaged thread causing a NamingException from ctx.lookup(myJndiUrl), that was instead correctly working in other application servers (JBoss, Weblogic); actually, Webpshere was firing an "incident" with the following message:
javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the server runtime is not able to associate the operation's thread with any J2EE application component. This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request. Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application. Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names.
The following steps solved the problem:
1) upgraded to quartz 1.8.6 (no code changes), just maven pom
2) added the following dep to classpath (in my case, EAR's /lib folder), to make the new WorkManagerThreadExecutor available
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-commonj</artifactId>
<version>1.8.6</version>
</dependency>
Note: in QTZ-113 or the official Quartz Documentation 1.x 2.x there's no mention on how to activate this fix.
3) added the following to quartz.properties ("wm/default" was the JNDI of the already configured DefaultWorkManager in my WAS 8.5.5, see Resources -> AsynchronousBeans -> WorkManagers in WAS console):
org.quartz.threadExecutor.class=org.quartz.custom.WorkManagerThreadExecutor
org.quartz.threadExecutor.workManagerName=wm/default
Note: right class is org.quartz.custom.WorkManagerThreadExecutor for quartz-scheduler-1.8.6 (tested), or org.quartz.commonj.WorkManagerThreadExecutor from 2.1.1 on (not tested, but verified within actual quartz-commonj's jars on maven's repos)
4) moved the JNDI lookup in the empty constructor of the quartz job (thanks to m_klovre's "Thread outside of the J2EE container"); that is, the constructor was being invoked by reflection (newInstance() method) from the very same J2EE context of my application, and had access to java:global namespace, while the execute(JobExecutionContext) method was still running in a poorer context, which was missing all of my application's EJBs
Hope this helps.
Ps. as a reference, you can find here an example of the quartz.properties file I was using above
Check this article:
http://www.ibm.com/developerworks/websphere/techjournal/0609_alcott/0609_alcott.html
basically, set the taskExecutor property on SchedulerFactoryBean to use a org.springframework.scheduling.commonj.WorkManager TaskExecutor which will use container managed threads.
Just a note: the above QUARTZ-708's link is not valid anymore.
This new issue (in a new Jira) seems to be addressing the problem: http://jira.terracotta.org/jira/browse/QTZ-113 (fixVersion = 1.8.6, 2.0.2)
I have recently encountered this problem. Practically you need:
Implement thread pool by delegating work to Websphere Work Manager. (Quartz provides only SimpleThreadPool that run jobs on unmanaged threads). Tell quartz to use this thread pool by org.quartz.threadPool.class property
Tell quartz to use WorkManagerThreadExecutor (or implement custom one) by org.quartz.threadExecutor.class property
A bit patience with cumbersome legacy web containers :)
Here is github demo of using Quartz with Websphere (and also Tomcat).
Hope it helps someone..
You can check the below JIRA link raised on quartz regarding this.
http://jira.opensymphony.com/browse/QUARTZ-708
This has the required WebSphereThreadPool implementation which can be used with the changes in quartz.properties as mentioned to meet your requirements. Hope this helps.
Regards,
Siva
You will have to use websphere's managed thread pools. You can do this via spring and commonj. CommonJ can has a task executor that will create managed threads. You can even use a reference to a jndi managed thread resource. You can then inject the commonj task executor into the Spring based Quartz SchedulerFactoryBean.
Please see http://open.bekk.no/boss/spring-scheduling-in-websphere/ and scroll to "Quartz with CommonJ" section for more details.
The proposal from PaoloC for WAS85 ans Quartz 1.8.6 also works on WAS80 (and Quartz 1.8.6) and does not need Spring. (In my setup Spring 2.5.5 is present, but not in use in that context.)
That way I was able to override SimpleJobFactory by my own variant, using an InjectionHelper to apply CDI on every newly created job. Injection works for both #EJB (with JNDI lookup of the annotated EJB remote business interface) and #Inject (with JNDI lookup of the CDI BeanManager using a new InitialContext first, and then using this newly fetched BM to lookup the CDI bean itself).
Thank you PaoloC for that answer! (I hope this text will appear as an "answer to PaoloC" and not as an answer to the main topic. Found no way to differentiate between these.)
Related
I have Quartz Scheduler running within WebLogic 12.1.3 and backed by a JobStoreCMT, but its behavior doesn't match the configuration (see below). What am I doing wrong?
Background
Quartz has jobs that are loaded from an XML file on startup and run periodically. Some of those jobs spawn one-time jobs. Also, there are one-time jobs that are manually triggered by users. The user-initiated jobs are done from EJBs that have container-managed transactions.
Questions
The transactions in the job classes are not active in the job's execute() method. I have to call begin/commit/rollback. Shouldn't that be taken care of since wrapJobExecutionInUserTransaction is set to true? That's what the documentation says.
The documentation also says that when using XMLSchedulingDataProcessorPlugin with JobStoreCMT, org.quartz.plugin.jobInitializer.wrapInUserTransaction must be set to true. However, when I do that I get a duplicate transaction exception. What's going on?
WebLogic takes forever to shut down whenever Quartz is enabled even though all of the jobs run quickly. From the logs it looks like WebLogic is waiting for the transactions to time out. Is something in the config contributing to this?
Configuration
org.quartz.scheduler.skipUpdateCheck=true
org.quartz.scheduler.instanceName=MyTaskScheduler
org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer=true
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.wrapJobExecutionInUserTransaction=true
org.quartz.scheduler.userTransactionURL=javax.transaction.UserTransaction
org.quartz.scheduler.idleWaitTime=30000
org.quartz.scheduler.dbFailureRetryInterval=15000
org.quartz.scheduler.batchTriggerAcquisitionMaxCount=1
org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow=0
org.quartz.scheduler.makeSchedulerThreadDaemon=false
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=20
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.makeThreadsDaemons=false
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreCMT
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate
org.quartz.jobStore.dataSource=MyDataSource
org.quartz.jobStore.nonManagedTXDataSource=MyDataSourceNonXA
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.useProperties=false
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=15000
org.quartz.jobStore.maxMisfiresToHandleAtATime=20
org.quartz.jobStore.txIsolationLevelSerializable=false
org.quartz.jobStore.txIsolationLevelReadCommitted=false
org.quartz.dataSource.MyDataSource.jndiURL=MyDataSource
org.quartz.dataSource.MyDataSource.java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
org.quartz.dataSource.MyDataSource.java.naming.provider.url=t3://localhost:7003
org.quartz.dataSource.MyDataSourceNonXA.jndiURL=MyDataSourceNonXA
org.quartz.dataSource.MyDataSourceNonXA.java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
org.quartz.dataSource.MyDataSourceNonXA.java.naming.provider.url=t3://localhost:7003
org.quartz.plugin.jobInitializer.class=org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames=E:/tasks.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound=true
org.quartz.plugin.jobInitializer.scanInterval=0
org.quartz.plugin.jobInitializer.wrapInUserTransaction=false
Any help is appreciated.
I need to be able to initiate a bean at startup and have it run constantly in the background using some kind of internal event/time loop (looking for data records to process). I was wondering what the correct Java EE 7/ JBoss EAP 6.2 method of doing this would be.
Any ideas?
Use the Quartz Scheduler framework and have the job fire up as configured.
It depends what you want to achieve. There are various ways you can achieve the stated goal. Some i can think of are :-
1)Use spring which automatically instantiate singleton beans on startup and call init method while start up
2)In terms of web app , you can use loadOnstartUp servlet configuration
3)Use quarts Job to run the background jobs
EJBs should work fine in this case (standard Java EE - no external framework needed)
I am assuming you need a 'pull' mode for the data rather than having a component to 'listen' to data events
Spin up a Singleton EJB
Write your business logic which would query the data repository
#Singleton
#Startup //container initializes the bean when it starts or when the application is deployed
public class MySingletonEJB{
#Schedule //configure this annotation as per required schedule e.g. via a Cron like syntax
public void executeJob(){
//.... search data records
}
}
I need to execute some code after the start of the application server (JBoss).
I googled the annotations #startup and #create that might prove useful, but in this situation seems impossibile to operate with EntityManager or Hibernate current session (if using Hibernate).
Is there any chance to perform Hibernate operation immediately after JBoss is started?
Are you using a framework? If not, you could use a startup servlet. In your web.xml, simply mark the servlet to have a <load-on-startup> value and it will run when the webapp is started. If you want it to load after other servlets, just set the load order.
If you are using a framework, it will have its own methodologies, such as Spring's InitializingBean interface.
You could deploy a custom JBoss service or just use plain old portable ServletListener in a war.
On most of applications servers, J2EE Ejb specification forbids creating threads "by hand", since these resources should be managed by the server.
But is there any way to get threads from Tomcat, Glassfish, Jboss etc.; thus access their ThreadPool?
You can use the commonj WorkManager. It was a proposal by IBM and BEA to provide a standard means to accomplish this task (access to container managed threads).
Although it was not included in the actual specification, there are implementations available for most containers.
Use in Weblogic
Use in WebSphere
Implementation for Tomcat, JBOSS and maybe others
Spring integration
The legal way to get threads from container is using JCA (Java Connector Architecture). The component you implement using this technology is called "resource adapter" and is packaged as rar file.
The implementation is pretty verbose but not too complicated in simple cases. So, good luck.
I've seen at least one utility class for getting ahold of Tomcat's threadpool, but it's not wise to go this route. Those threads are created to service your EJB or Servlet's requests, not for you to support the EJB or Servlet. Each one you take up is just another thread that won't be available to service requests to the container.
You could probably just throw in a static ThreadPool and use a static initializer to get around the EJB spec on this one, but you'd obviously have to make sure the thread code works well otherwise it could really bork your EJB.
I'm currently developing a small EJB application running on IBM Websphere Application Server 7 (Java EE 5). The app mainly consists of one MDB listening for incoming MQ messages which are transformed and stored in a DB. Currently I'm using a lot of Singleton/Factories to share configurations, mappings, datasource lookups etc. But this actually leads to some very hard to test code. The solution might be using a (simple) DI framework like guice/spring to inject the different instances. The question is: Where to place the initialization/ setup code? Where is the main entry point of the application? How can I inject instances into the MDBs?
it might be worth looking at backing off from using Guice, and trying to work with the injection mechanisms already available with Java EE 5.
Regarding finding a suitable "startup point", unfortunately the EJB specification does not define a way where you can have a bean run at startup. However, the web profile of the EE spec does have one -- you can add a WAR to your application, and set a servlet listener component:
http://java.sun.com/javaee/5/docs/api/javax/servlet/ServletContextListener.html
You can set this to start whenever the application is loaded and started by the container (WebSphere). Watch out for classloader issues though.
Using Spring, you can do it via EJB3 interceptors, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/ejb.html#ejb-implementation-ejb3
Useful info on caveats are in the javadoc, make sure you read it: http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/ejb/interceptor/SpringBeanAutowiringInterceptor.html