Wednesday, March 26, 2008

Integrating Grails with EJB 2 applications

When attempting to convince an organization to adopt Grails you may have to demonstrate more than the superior developer productivity it provides. Integrating with legacy systems or even new systems that may continue to be developed in other tools will probably become an important topic. One way to integrate is to use the Grails ORM DSL to hook legacy database tables into a Grails application. Another way is to connect to existing EJB based applications. As you would expect Grails makes this so easy it seems like cheating.

In this example we have an EJB 2 server running in WebLogic. There is a CMP entity bean called Employee, a stateless session bean called EmpSession and a data transfer object called vEmployee. The EJB components and the DTO are in a jar called EmpEjb.jar. The session bean contains methods for retrieving and saving Employee entities via the vEmployee DTOs. We will focus on on how to get access to the EmpSession instance from our Grails application.

First we'll add a couple of beans to our grails-app/conf/spring/resources.groovy file using the SpringBuilder DSL.

beans = {
ejbJndi(org.springframework.jndi.JndiTemplate){
environment = [
"java.naming.factory.initial" : "weblogic.jndi.WLInitialContextFactory",
"java.naming.provider.url" : "t3://some.enterprise.server:7001",
"java.naming.security.principal" : "dave",
"java.naming.security.credentials" : "1234"
]
}
empSession(org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean){
jndiName = "EmpSession"
businessInterface = "com.enterprise.some.ejb.session.EmpSession"
jndiTemplate = ref("ejbJndi")
}
}

Let's look at what this code is doing. We have what looks like a method: ejbJndi. It is really a Spring bean id and its argument is the bean class. The block that follows includes one or more property assignments in the form of properyName = propertyValue. for the ejbJndi bean we only have one property, environment, which in turn contains several entries. The entries take the form of a map of propKey:propBody pairs. This sets up our JNDI Template which Spring will use to lookup our session bean.

Next we declare our remote session bean using Spring's SimpleRemoteStatelessSessionProxyFactoryBean (they said "Simple" not "Short"). We declare this the same way as the ejbJndi bean. This one has three properties, the session bean's jndi name, its remote interface class and a reference to the JNDI Template. For this last property we use the form property = ref("referencedBeanId").

Now we need to copy some jars to our application/lib directory. Since we are using WebLogic all of the EJB and JNDI classes we will need are in weblogic.jar. You may have one or more jars depending on your application server. Our EJB components and our DTO classes are in a single jar, EmpEjb.jar. These may often be in different jars, in which case both would need to be placed in the lib directory.

Beans defined in resources.groovy can be auto-wired by name so we can just place def empSession in any Service or Controller class and start calling session methods.

With this ability to integrate so easily with legacy applications there is just one less reason not to start using Grails in the enterprise.

7 comments:

Sen said...

Thanks for posting this article. As we were looking for integrating with EJB 2 applications.

Great !!!!

I can forward this article to my architect :)

Sen

Shawn Hartsock said...

Good stuff! I need to try and do this with some of my projects and was wondering how.

Thanks!

slv said...
This comment has been removed by the author.
Anonymous said...

Excellent this is what I was looking for to integrate a Grails app with my old EJB2.1 app.
Thanks

Ariel said...

Just for the record, to avoid server restart problems you can put the following property
refreshHomeOnConnectFailure = true when declaring the Bean reference:

empSession(org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean){
jndiName = "EmpSession"
businessInterface = "com.enterprise.some.ejb.session.EmpSession"
jndiTemplate = ref("ejbJndi")
refreshHomeOnConnectFailure = true
}

Anonymous said...

Nice dispatch and this post helped me alot in my college assignement. Say thank you you for your information.

Kris said...

Hi,
I'm a youngster who never had the pleasure of EJB 2 until recently. We have a project going and I'd love to use grails but am really really struggling to set up a POC using glassfish.

I have a simple stateless ejb which I know works because I've tested it using a simple servlet.

I'm getting a lot of issues with the naming context line in the environment definition when I try to deploy the app?

Have you/anyone else got an example environment environment config line for Glassfish ?

Kris