EJB3 façade over Spring services
As a consultant, you seldom get to voice out your opinions regarding the technologies used by your customers and it's even more extraordinary when you're heard. My current context belongs to the usual case: I'm stuck with Java 6 running JBoss 5.1 EAP with no chance of going forward in the near future (and I consider myself happy since a year and a half ago, that was Java 5 with JOnAS 4). Sometimes, others wonder if I'm working in a museum but I see myself more as an archaeologist than a curator.
Context
I recently got my hands on an application that had to be migrated from a proprietary framework, to more perennial technologies. The application consists of one web-front office and a Swing back-office. The key difficulty was to make the Swing part communicate with the server part, since both lives in two different network zones, separated by a firewall (with some open ports for RMI and HTTP). Moreover, our Security team enforces that such communications has to be secured.The hard choice
The following factors played a part in my architecture choice:- My skills, I've plenty more experience in Spring than in EJB3
- My team skills, more oriented toward Swing
- Reusing as much as possible the existing code or at least interfaces
- Existing requirement toward web-services:
- Web services security is implemented through the reverse proxy, and its reliability is not the best I've ever seen (to put it mildly)
- Web services applications have to be located on dedicated infrastructure
- Mature EJB culture
- Available JAAS LoginModule for secure EJB calls and web-services from Swing
Design
To ease the design to the maximum, each Spring service will have exactly one and only one EJB3 façade, which will delegate calls to the underlying service. Most IDEs will be able to take care of the boilerplate delegating code (hell, you can even use Project Lombok with @Delegate - I'm considering it). On the class level, the following class design will be used:
This is only standard EJB design, with the added Spring implementation. On the module level, this means we will need a somewhat convoluted packaging for the service layer:
- A Business Interfaces module
- A Spring Implementations module
- An EJB3 module, including remote interfaces and session beans (thanks to the Maven EJB plugin, it will produce two different artifacts)
How-to
Finally, developing the EJB3 façade and injecting it with Spring beans is ridiculously simple. The magic lies in the JavaEE 5 Interceptors annotation on top of the session bean class that references the SpringBeanAutowiringInterceptor class, that will kick in Spring injection after instantiation (as well as activation) on every referenced dependency. The only dependency in our case is the delegate Spring bean, which as to be annotated with legacy @Autowired.
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor;
import ch.frankel.blog.ejb.spring.service.client.RandomGeneratorService;
@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class RandomGeneratorBean implements RandomGeneratorService {
@Autowired
private ch.frankel.blog.ejb.spring.service.RandomGeneratorService delegate;
@Override
public int generateNumber(int lowerLimit, int upperLimit) {
return delegate.generateNumber(lowerLimit, upperLimit);
}
}In order to work, we have to use a specific Spring configuration file, which references the Spring application context defined in our services module as well as activate annotation configuration.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://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>Warning: it's mandatory to name this file beanRefContext.xml and to make it available at the root of the EJB JAR (and of course to set the Spring service module as a dependency).
Conclusion
Sometimes, you have to make some interesting architectural choices that are pertinent only in your context. In these cases, it's good to know somebody paved the road for you: this is the thing with EJB3 façade over Spring services. To go further:- Spring documentation regarding EJB 3 injection interceptor
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)






Comments
Witold Szczerba replied on Sun, 2012/05/20 - 2:57pm
Hi,
I think that better solution would be to expose your back-end as HTTP REST instead of that "EJB remote". Using HTTP is easy: JAX-RS or Spring equivalent are nice to use. Jackson would handle object->json and vice versa mapping under the hood. The main advantage is that your swing application becomes much lighter, as it does not need JBoss libraries any more... unless JBoss' EJB3 remote client libs are not that heavy. I remember they were quite big for Glassfish v2 - like 30MB, so it was more or less 70% the size of entire application (I don't know how does it look like in newer versions). Especially painful, considering the app was distributed across offices using WebStart.
P.S.
Lombok is fantastic, isn't it?
Stuart Mcintyre replied on Sun, 2012/05/20 - 11:03pm
I didn't quite understand the need for a hybrid solution?
I think both Spring and EJB3 are good options for services, but I would personally use one or the other. Exposing stateless session beans as web services is just as easy as implementing a web service in Spring.
Nicolas Frankel replied on Mon, 2012/05/21 - 1:19am
@Witold and Stuart,
I understand the situation is quite strange and I'm afraid I wasn't clear enough, so here's another try. Implementing Web Services in my organization is quite a nightmare:
As for a pure EJB solution, I prefer someone else to handle all problems that occur on any technology first use.
Hope my stance is clearer now.