作为顾问,您很少会对客户使用的技术发表意见,当听到您的声音时,它会变得更加非凡。 我当前的情况属于通常的情况:我坚持使用运行JBoss 5.1 EAP的Java 6,在不久的将来没有前进的机会(而且我自一年半前就感到高兴,那是具有JOnAS的Java 5) 4)。 有时,其他人会怀疑我是否在博物馆里工作,但我认为自己更像是考古学家而不是策展人。
语境
最近,我接触到了一个必须从专有框架迁移到更长期技术的应用程序。 该应用程序由一个网络前台办公室和一个Swing后台办公室组成。 关键的困难是使Swing部分与服务器部分进行通信,因为这两个部分都位于两个不同的网络区域中,这些区域由防火墙隔开(具有一些用于RMI和HTTP的开放端口)。 此外,我们的安全团队要求必须确保此类通信的安全。
艰难的选择
以下因素在我的体系结构选择中起作用:
- 我的技能,我在Spring中比在EJB3中拥有更多的经验
- 我的团队技能,更倾向于Swing
- 尽可能重用现有代码或至少接口
- 对Web服务的现有要求:
- Web服务安全性是通过反向代理实现的,其可靠性并不是我见过的最好的(轻描淡写)
- Web服务应用程序必须位于专用基础结构上
- 成熟的EJB文化
- 可用的JAAS LoginModule,用于来自Swing的安全EJB调用和Web服务
现在,它基本上可以归结为在HTTP或EJB3上公开Spring Web服务。 在第一种情况下,缺点包括没有Spring远程处理,性能(甚至可靠性)问题以及在不同服务器上进行部署的经验,因此对于开发团队而言,打包更为复杂。 在第二种情况下,它们包括稍微更高的复杂性(是的,EJB3比使用EJB 2.1更容易,但是仍然),更长的启动时间,并且当遇到困难时我无法适当地支持我的团队。
最后,我决定完全使用Spring服务,但是将它们放在EJB3外观的后面。 这看起来似乎很奇怪,但是我认为我能同时兼顾:EJB3的技能保持在最低限度(事务将由Spring管理),而该技术则使我直接通过反向代理。 考虑到上述因素,我愿意就此类解决方案提出建议和争论,但越快越好:-)
设计
为了最大程度地简化设计,每个Spring服务将仅具有一个且只有一个EJB3外观,该外观会将调用委派给基础服务。 大多数IDE都可以处理样板委派代码(地狱,您甚至可以将Project Lombok与@Delegate
-我正在考虑)。
在课程级别,将使用以下课程设计:
这只是标准的EJB设计,带有添加的Spring实现。
在模块级别,这意味着我们将需要在服务层使用一些复杂的包装:
- 业务接口模块
- Spring实现模块
- EJB3模块,包括远程接口和会话Bean(由于使用Maven EJB插件,它将产生两个不同的工件)
如何
最后,开发EJB3外观并使用Spring bean注入它非常简单。 神奇之处在于会话bean类顶部的JavaEE 5 Interceptors
批注,该批注引用SpringBeanAutowiringInterceptor
类,在实例化(以及激活)每个引用的依赖项后,它将在Spring注入中启动。
在我们的案例中,唯一的依赖关系是委托Spring bean,该委托将使用遗留@Autowired
进行注释。
importjavax.ejb.Stateless;
importjavax.interceptor.Interceptors;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor;
importch.frankel.blog.ejb.spring.service.client.RandomGeneratorService;
@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
publicclassRandomGeneratorBeanimplementsRandomGeneratorService{
@Autowired
privatech.frankel.blog.ejb.spring.service.RandomGeneratorServicedelegate;
@Override
publicintgenerateNumber(intlowerLimit,intupperLimit){
returndelegate.generateNumber(lowerLimit,upperLimit);
}
}
为了工作,我们必须使用特定的Spring配置文件,该文件引用在我们的服务模块中定义的Spring应用程序上下文以及激活注释配置。
<?xml version="1.0" encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.1.xsd[
<context:annotation-config/>
<bean>
<constructor-arg>
<list>
<value> classpath:ejb-service.xml </value>
</list>
</constructor-arg>
</bean>
</beans>
必须将此文件命名为beanRefContext.xml并使其在EJB JAR的根目录中可用(当然,还应将Spring服务模块设置为依赖项)。
结论
有时,您必须做出一些仅在您的上下文中相关的有趣的体系结构选择。 在这些情况下,很高兴知道有人为您铺平了道路:这就是Spring服务上的EJB3外观。
翻译自: https://blog.frankel.ch/ejb3-facade-over-spring-services/