Migrating jboss-service.xml/SAR to Singleton Session Beans
jfisherdev Sep 27, 2017 4:36 PMWhen initially migrating from JBoss AS 4.2.2 to WildFly 9.0.2.Final I continued to use jboss-service.xml/SAR deployments for singleton services.
I got this to work with some adjustments [no xmbean descriptors, not using <depends/> for managed resources, etc]; however, I am looking to get away from this approach in favor
of deploying them as standard Java EE Singleton Session Beans using annotations. The main reasons being portability, the benefits/capabilities of having these be managed EE resources, and the fact that many services do not necessarily need the JMX instrumentation provided by SAR deployments.
So far, the process has not been too difficult and has mainly meant doing the following:
- Replace the SAR deployment with a standard EJB JAR deployment and add an <ejb> module to the application.xml in EAR applications
- Add @Singleton and @Startup annotations to the service implementation class
- Annotate lifecycle start()/stop() methods with @PostConstruct and @PreDestroy
- Instrument the service as a JMX resource if needed
The one area where I do have questions is with expressing dependencies of two types that were previously expressed with the <depends/> element in jboss-service.xml descriptors:
- Dependencies on other singleton services
- Dependencies on managed resources which are accessed via JNDI [Stateless Session Beans, JMS resources, such as connection factories and destinations]
The first type, which you could still use the <depends/> element for in WildFly 9 SAR deployments, I believe can be expressed using the javax.ejb.DependsOn annotation.
The second type, which you could NOT use in WildFly 9 SAR deployments, is the one I am less certain about. This one is especially of interest because one thing I found with using SAR deployments in WildFly 9 is that sometimes exceptions would be thrown from a service lifecycle methods that access EJBs or JMS resources via programmatic JNDI lookup and would usually say something to the effect that the resource could not be found in JNDI.
To accomplish the equivalent of something like this:
<depends>jboss.mq.destination:service=Topic,name=appTopic</depends> <depends>jboss.j2ee:jndiName=ejb/AppServiceBean</depends>
I believe I would need to use resource injection like this:
@Resource(lookup = "java:/topic/appTopic") private Destination appTopic; //Using portable namespace binding, but could use others @EJB(lookup ="java:/global/appName/moduleName/ejb/AppServiceBean") private AppService appService;
I haven't used resource injection extensively, but if I'm understanding things correctly that would ensure these are available. Am I correct to say that the lookup values NOT resolved relative to the global "java:/" namespace if not specified like they are when accessed in a programmatic fashion [e.g. "topic/appTopic" is bound in the java:/ namespace, but can be found using Context.lookup("topic/appTopic") without the namespace qualifier]. This seems to be the case, because in my initial attempt at this the injection failed without including the namespace.
Overall I think I'm moving in the right direction with this, but would appreciate confirmation or clarification on the items identified.