Java EE:从域模型动态创建和删除套接字侦听器

ins*_*pid 5 java domain-driven-design ejb jca java-ee

我正在创建一个Java EE应用程序,允许用户从Web界面添加/删除"socketinfo"表(存储在数据库中).如果用户从Web界面启用"socketinfo",则应用程序服务器必须为传入的数据包创建套接字侦听器并处理数据.如果用户禁用或删除"socketinfo",则必须删除套接字侦听器.整个产品必须包含在一只耳朵中,并且最好是顺从的.我考虑过但遇到问题的一些方法是:

  1. 为套接字创建JCA资源适配器并使用MDB作为侦听器.我遇到的问题是,当用户添加MDB时,我无法弄清楚如何以编程方式为不同的套接字部署MDB.

  2. 创建一个@ Singleton/@ Service ejb,通过仔细同步来管理守护程序线程.单例ejb可以注入业务层,以便在正确的工作流程中进行CRUD操作和套接字操作.这里的问题是,据说从EJB创建线程被认为是一种不好的做法,并且不符合规范(即使正确处理了单例生命周期并且有适当的同步机制?).

  3. 将线程放在域模型中(另一个单例?)并让EJB使用该模型.这是所有这些中最糟糕的,因为应用程序服务器往往有多个类加载器,一般来说容器支持较少,而且这样做会受到影响.

知道如何在Java EE中正确处理这种情况吗?

编辑:这个问题的扩展:假设我决定像ewernli在他的解决方案3中所建议的那样处理这个问题,我在JCA(使用自定义接口添加内部线程)中做到这一点,我不会从中获得(精心设计的单身人士?虽然创建一个资源适配器看起来并不是一个可怕的任务,但它似乎并不是完全无关紧要的,可能需要花费一些时间(对于其他开发人员来说可能更难以遵循).

ewe*_*nli 1

您的分析似乎很合理,当您说无法动态部署 MDB 以适应 JCA 时,您是对的。

还有一些设计思路:

  • 您可以编写一个返回的 JCA 连接器SocketConnections(本着 JMS 的精神),您可以使用它从套接字读取数据。继续与 JMS 类比,MDB 代表MessageListener,而您要公开的是MessageConsumer

  • 您可以使用周期性计时器来模拟线程。您拥有一个可以自行重新安排时间的计时器,而不是带有 while 循环的线程。我将其用于一个具有后台进程的应用程序,效果很好。请注意,我还直接从 EJB 生成了线程,以便在另一个应用程序中执行一些并发计算,并且效果也很好。但是,短暂存在的线程和 bean 中的业务方法将等到全部完成,因此这并不是对规范的重大违反。

  • 另一种设计是让 JCA 连接器处理线程等并将所有消息传递到 MDB。MDB 将接收数据以及有关数据对应的“通道”的信息,例如套接字端口。这就像在一个 MDB 中对所有内容进行多路复用,然后对数据进行多路分解。您的连接器可以提供额外的 API 来控制线程的创建等,并且可以将该接口注入到您的 EJB 中(类似于ConnectionFactory)。你的连接器可以提供额外的 API 来控制线程的创建等。不太清楚,但我希望你明白。如果我是对的,JCA 连接器可以确保将数据同步传送到 MDB(至少每个套接字),以便 MDB 按正确的顺序处理数据。

如果开发时间允许,我会选择#3 。

编辑

这种选择确实在一定程度上是设计纯粹性的问题。但用户生成的线程的一个问题是,您显然不能对它们使用声明性事务。不过,您也许可以自己使用 aUserTransaction来划分事务。我不知道你在这样的线程中使用“ EntityManageralso”的效果如何。如果您主要处理数据并且不使用中间件的太多功能,则可以自己生成线程。请参阅我的另一个答案:How can an EJBparallelize a long,CPU密集型进程?。我想到的其他事情(不知道它们是否有问题):安全管理器可能会阻止创建线程(?),而不创建它们,因为守护线程可能会阻止应用程序。服务器正常关闭(?)。请注意,我ServeletContextListener在启动时生成了线程,效果很好。这是经常使用的技巧,即使它违反了规范。对于“新”引入的单例 bean 来说,情况也可能如此。因此,如果您时间紧迫,您当然可以使用单例 bean 尝试您的建议,看看什么有效/无效。