将POJO重新设计为EJB或客户端事务

时间:2014-07-22 21:46:42

标签: multithreading java-ee transactions timeout ejb-3.1

我有几个关于EJB事务的问题。我遇到的情况是,进程已经变得比原先预期的更长,并且有时由于超出服务器超时而失败。虽然我最初增加了超时(总交易和最大交易),但对于长时间运行的流程,我知道将这项工作尽可能地划分为更小的工作单元更有意义。在超时。因此,我根据下面的背景和随后的问题寻找有关下一步行动的一些想法或参考。

环境: EJB 3.1,JPA 2.0,WebSphere 8.5

背景 我构建了一组POJO来为企业应用程序执行一些面向批处理的工作。它们是非EJB POJO,旨在实现多个业务流程(5个相关的顺序流程,每个流程取决于它的前身)。 POJO位于普通Java项目中,而不是EJB项目中。

但是,这些POJO通过JPA访问EJB外观以进行数据库访问。 5个业务流程的抽象核心执行EJB外观的JNDI查找,以便返回域对象进行处理。最初,设计完全从服务器运行,但是需要从外部启动这些过程。因此,我创建了一个EJB包装器,以便可以远程调用这些进程(单独或作为基于公共策略接口的单个​​进程)。不幸的是,数据的大小(行宽和行数)已经远远超出了原始意图。

完成这些批处理过程所需的处理时间显着增加(从大约几个小时到每天大约1/2,并且可能会增加超过这个时间)。 5个进程中只有一个对多线程有意义(我确实实现了多线程)。由于我有包装EJB来启动1或所有,我决定为每个进程创建一个新的容器事务,而不是单个默认事务" required"当我作为一个单一过程运行时。由于一个进程是多线程的,因此尝试为每个线程创建一个新事务是有意义的,但是,作为一组POJO,我没有事务功能。

问题: 所以我的问题是,什么更有意义,为什么?将POJO重新设计为EJB本身,让包装器EJB将每个进程实例化为子进程,其中每个进程都有自己的事务,更重要的是,多线程进程可以为每个线程创建一个事务。或者尝试从容器中的JNDI查找在POJO中创建UserTransaction并尝试管理它就好像它是一个bean管理的事务(如果这甚至是一个可行的解决方案)更有意义。我知道这可能是依赖于应用程序的,但是对于Java EE容器的超时,什么是合理的?显然,我不想逃避流程,但希望确保我能完成这些批处理过程。

不幸的是,这个应用程序已经部署为生产系统。重新设计虽然可能只是在EJB中组装策略逻辑,但却是对功能的重大改变。

我确实在这里寻找其他一些线程,并通过一般的互联网搜索,但我想我会看到是否有人对另一个或另一个解决方案完全有令人信服的论据。其他链接谈论这样的主题是值得赞赏的。我是否会发布这个问题,因为有些人可能认为这是主观的,但是,我认为缩小的主题值得发布,并且可能与其他人尝试这样的过程相关。

2 个答案:

答案 0 :(得分:0)

这不是你问题的直接答案,而是你可以考虑的事情。
WebSphere 8.5特别针对这类应用程序(批处理)提供了批处理容器。批处理功能适用于必须与事务应用程序一起执行批处理工作的应用程序。批处理工作可能需要数小时甚至数天才能完成,并在运行时使用大量内存或处理能力。您可以在批处理应用程序中重用Java类,批处理步骤可以在集群中并行运行,并具有事务检查点管理。

查看以下资源:

IBM Education Assistant - Batch applications
Getting started with the batch environment

答案 1 :(得分:0)

由于过去几周我真的没有对这个问题得到很多回应或想法,我想我会回答这个问题,希望能帮助其他人做出决定,如果他们遇到这个或类似的问题情况。

最终,我将其中一个POJO重新设计为一个EJB,作为调用其他POJO的包装器。包装器EJB执行的操作与它只是一个POJO时的活动相同,只是我在主方法上添加了事务语义(REQUIRES_NEW)。主方法基于状态模式调用其他POJO,因此每个调用(或POJO)都获得自己的事务。调用主方法的EJB中的其他方法是使用NOT_SUPPORTED定义的,这样我就可以将每次调用的事务分离到主方法而不加入现有事务。

完全公开,事务语义的原始添加显着增加了处理时间(大约几天),但是由于超出事务超时,该过程没有失败。这是JPA多对一关系带来一些意想不到的问题的结果,这些关系带来了过多的数据。由于多对一关系,数据被检索。正如我之前提到的,我的一些数据行宽意外增加。数据增加是在相关的表对象中,但查询当时不需要该数据。我通过更改查询(为SELECT NEW查询创建对象,将更改的关系更改为FetchType.LAZY等)更正了这些问题。

展望未来,如果我能够投入足够的时间,我会将其余的POJO转换为EJB。执行最大量线程工作的POJO已经通过ExecutorService运行的Callable实现实现。如果我可以改变那个,那么计划将是使每个线程成为自己的交易。但是,虽然我还不确定,但由于我所看到的状态更新,我的容器似乎已经在为每个线程组(10个线程)创建事务。我将不得不做更多的调查。