非托管线程 Spring Quartz Websphere Hibernate

发布于 2024-07-06 13:48:42 字数 276 浏览 7 评论 0原文

看来我们使用 Quartz - JDBCJobStore 以及 Spring、Hibernate 和 Websphere 的实现会引发非托管线程。

我读了一些书,发现 IBM 的一篇技术文章指出,将 Quartz 与 Spring 一起使用会导致这种情况。 他们建议使用 CommnonJ 来解决这个问题。

我做了一些进一步的研究,到目前为止我看到的唯一示例都涉及不在数据库中的计划旧 JobStore。

所以,我想知道是否有人有解决此问题的示例。

谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

半岛未凉 2024-07-13 13:48:42

我们对此有一个可行的解决方案(实际上是两个)。

1) 更改quartz源代码以使用WorkManager守护线程作为主调度程序线程。 它可以工作,但需要更换夸脱。 但我们没有使用它,因为我们不想维护石英的黑客版本。 (这提醒了我,我本来打算将其提交给项目,但完全忘记了)

2)创建一个 WorkManagerThreadPool 用作石英线程池。 实现quartz ThreadPool 的接口,以便quartz 中触发的每个任务都包装在一个commonj Work 对象中,然后该对象将在WorkManager 中进行调度。 关键是 WorkManagerThreadPool 中的 WorkManager 必须在调度程序启动之前从 Java EE 线程初始化(例如 servlet 初始化)。 然后,WorkManagerThreadPool 必须创建一个守护线程,该线程将通过创建和调度新的 Work 对象来处理所有计划任务。 这样,调度程序(在其自己的线程上)将任务传递给托管线程(工作守护进程)。

并不简单,不幸的是我没有现成的代码可供包含。

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.

我的痛♀有谁懂 2024-07-13 13:48:42

添加另一个答案到线程中,因为我终于找到了解决方案。

我的环境:WAS 8.5.5,Quartz 1.8.5,无 Spring。

我遇到的问题是(上述)非托管线程导致 ctx.lookup(myJndiUrl) 出现 NamingException,而该线程在其他应用程序服务器(JBoss、Weblogic)中正常工作); 实际上,Webpshere 正在引发一个“事件”,并显示以下消息:

javax.naming.ConfigurationException:无法完成“java:”名称上的 JNDI 操作,因为服务器运行时无法将该操作的线程与任何 J2EE 应用程序组件关联起来。 当使用“java:”名称的 JNDI 客户端未在服务器应用程序请求的线程上执行时,可能会出现这种情况。 确保 J2EE 应用程序不会对静态代码块内或由该 J2EE 应用程序创建的线程中的“java:”名称执行 JNDI 操作。 此类代码不一定在服务器应用程序请求的线程上运行,因此不受“java:”名称上的 JNDI 操作支持。

以下步骤解决了该问题:

1) 已升级到quartz 1.8.6(没有代码更改),只需 maven pom

2) 将以下 dep 添加到类路径(在我的例子中,EAR 的 /lib 文件夹),以使新的 WorkManagerThreadExecutor 可用

<dependency>
  <groupId>org.quartz-scheduler</groupId>
  <artifactId>quartz-commonj</artifactId>
  <version>1.8.6</version>
</dependency>

注意:在 < a href="http://jira.terracotta.org/jira/browse/QTZ-113" rel="nofollow">QTZ-113 或官方 Quartz 文档 1.x 2.x 没有提及如何激活此修复程序。

3) 在quartz.properties中添加了以下内容(“wm/default”是我的WAS 8.5.5中已配置的DefaultWorkManager的JNDI,请参阅Resources -> AsynchronousBeans -> WorkManagers 在 WAS 控制台中):

org.quartz.threadExecutor.class=org.quartz.custom.WorkManagerThreadExecutor
org.quartz.threadExecutor.workManagerName=wm/default

注意:对于quartz-scheduler-1.8.6(已测试),正确的类是 org.quartz.custom.WorkManagerThreadExecutor,或 org.quartz.commonj.WorkManagerThreadExecutor2.1.1开始(未经测试,但在实际quartz-commonj 的 jars 在 Maven 的仓库中)

4)JNDI 查找移至quartz 作业的空构造函数(感谢 m_klovre 的“J2EE 容器外部的线程”); 也就是说,构造函数是通过反射(newInstance() 方法)从我的应用程序的同一 J2EE 上下文中调用的,并且可以访问 java:global 命名空间,而execute(JobExecutionContext) 方法仍在较差的上下文中运行,该上下文缺少我的应用程序的所有 EJB

希望这会有所帮助。

诗。 作为参考,您可以在此处找到我上面使用的quartz.properties 文件的示例

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

一影成城 2024-07-13 13:48:42

检查这篇文章:
http://www.ibm.com/developerworks/websphere/techjournal/ 0609_alcott/0609_alcott.html

基本上,将 SchedulerFactoryBean 上的 taskExecutor 属性设置为使用 org.springframework.scheduling.commonj.WorkManager TaskExecutor ,它将使用容器管理的线程。

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.

蓝礼 2024-07-13 13:48:42

请注意:上述 QUARTZ-708 的链接不再有效。
这个新问题(在新的 Jira 中)似乎正在解决该问题:http://jira.terracotta.org/jira/browse/QTZ-113(修复版本 = 1.8.6、2.0.2)

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)

A君 2024-07-13 13:48:42

我最近遇到了这个问题。 实际上您需要:

  1. 通过将工作委托给 Websphere Work Manager 来实现线程池。 (Quartz 仅提供在非托管线程上运行作业的 SimpleThreadPool)。 通过org.quartz.threadPool.class属性告诉quartz使用这个线程池 通过
  2. org.quartz.threadExecutor告诉quartz使用WorkManagerThreadExecutor(或者实现自定义一个) .class 属性
  3. 对繁琐的遗留 Web 容器有点耐心:)

这是 将 Quartz 与 Websphere(以及 Tomcat)结合使用的github 演示

希望它可以帮助别人..

I have recently encountered this problem. Practically you need:

  1. 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
  2. Tell quartz to use WorkManagerThreadExecutor (or implement custom one) by org.quartz.threadExecutor.class property
  3. A bit patience with cumbersome legacy web containers :)

Here is github demo of using Quartz with Websphere (and also Tomcat).

Hope it helps someone..

茶色山野 2024-07-13 13:48:42

您可以查看以下有关quartz 的 JIRA 链接。

http://jira.opensymphony.com/browse/QUARTZ-708

这有所需的 WebSphereThreadPool 实现可以与上述的quartz.properties 中的更改一起使用以满足您的要求。 希望这可以帮助。

问候,
湿婆

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

囚你心 2024-07-13 13:48:42

您将必须使用 websphere 的托管线程池。 您可以通过 spring 和 commonj 来完成此操作。 CommonJ 可以有一个任务执行器来创建托管线程。 您甚至可以使用对 jndi 托管线程资源的引用。 然后,您可以将 commonj 任务执行器注入到基于 Spring 的 Quartz SchedulerFactoryBean 中。

请参阅http://open.bekk.no/boss/spring-scheduling- in-websphere/ 并滚动到“Quartz with CommonJ”部分以了解更多详细信息。

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.

歌枕肩 2024-07-13 13:48:42

PaoloC 针对 WAS85 和 Quartz 1.8.6 的提案也适用于 WAS80(和 Quartz 1.8.6),并且不需要 Spring。 (在我的设置中存在 Spring 2.5.5,但在该上下文中未使用。)

这样我就能够通过我自己的变体覆盖 SimpleJobFactory,使用 InjectionHelper 在每个新创建的作业上应用 CDI。 注入适用于@EJB(使用带注释的EJB远程业务接口的JNDI查找)和@Inject(首先使用新的InitialContext对CDI BeanManager进行JNDI查找,然后使用这个新获取的BM来查找CDI bean本身)。

谢谢 PaoloC 的回答! (我希望本文将作为“PaoloC 的答案”而不是主要主题的答案出现。没有找到区分它们的方法。)

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.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文