How to call a stateless EJB from a spring rest servlet component
Tech-Today

How to call a stateless EJB from a spring rest servlet component


In my recent project I was ask to develop a rest servlet (using jersey) in a spring web project that would call an stateless EJB, where the business logic is.  This project is deployed on glassfish.

After several hours I was able to figure out how to make it work, and my main problem is simply the JNDI name, I was only able to access it using it's global name which you can see on the glassfish console log. It's very important so look at your console.

I would just copy and paste the most important files as they are in my working project. Note that I have 2 projects, that are deploy sub-modules of an ear project. First is a web project and the second is an ejb project.

The Web Project
web.xml
<web-app version="3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name>XXX - Customer Gateway</display-name>

<context-param>
<param-name>locatorFactorySelector</param-name>
<param-value>classpath:WEB-INF/beanRefContext.xml</param-value>
</context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.XXX.cg</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
beanRef.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean id="com.XXX"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>applicationContext.xml</value>
</list>
</constructor-arg>
</bean>
</beans>
applicationContext.xml
<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"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd"
default-autowire="byName">

<context:component-scan base-package="com.XXX" />
<context:annotation-config />
<tx:annotation-driven />
<tx:jta-transaction-manager />

<jee:jndi-lookup id="XXXCgDataSource" jndi-name="XXXCgDataSource"
lookup-on-startup="true" />

<bean id="entityManager"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="XXXCgDataSource" />
<property name="persistenceUnitName" value="XXXPU" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManager" />
<property name="dataSource" ref="XXXCgDataSource" />
</bean>

<!-- JNDI Lookup -->
<jee:jndi-lookup id="xxxServiceBean"
jndi-name="java:global/XXX-cg-ear-0.0.1-SNAPSHOT/XXX-cg-ejbs/XXXServiceBean"
resource-ref="true" lookup-on-startup="true"
expected-type="com.XXX.cg.service.xxx.local.XXXServiceBeanLocal"
proxy-interface="com.XXX.cg.service.xxx.local.XXXServiceBeanLocal" />

<!-- Load in application properties reference -->
<bean id="propertiesBean" name="propertiesBean"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/XXX-cg.properties" />
</bean>

<bean id="LogginInjector" class="com.XXX.commons.logger.LoggerPostProcessor" />
</beans>
The class where the stateless EJB is being called
@Path("/XXX")
@Component
public class XXXServiceImpl {
@Log
private Logger log;

@EJB
protected XXXServiceBeanLocal XXXServiceBean;

@POST
@Path("/register")
@Produces({ MediaType.APPLICATION_JSON })
public Response register(@FormParam("email") String email,
@FormParam("macid") String macid, @FormParam("type") String type) {
//...
String reply = XXXServiceBean.register(email, macid, type);
//...
return resp;
}
}
And that's it for the web project. And for the ejb project we have:
beanRefContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean id="com.sido"
class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>ejbApplicationContext.xml</value>
</list>
</constructor-arg>
</bean>
</beans>
applicationContext.xml

<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"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
default-autowire="byName">

<context:annotation-config />
<context:component-scan base-package="com.XXX" />
<tx:annotation-driven />

<jee:jndi-lookup id="XXXCgDataSource" jndi-name="XXXCgDataSource"
lookup-on-startup="true" />

<bean id="entityManager"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="XXXCgDataSource" />
<property name="persistenceUnitName" value="XXXPU" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManager" />
<property name="dataSource" ref="XXXCgDataSource" />
</bean>

</beans>
ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:ejb="http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
version="3.1">

<!-- <display-name>XXX-cg-ejbs</display-name> -->
<module-name>XXX-cg-ejbs</module-name>

<interceptors>
<interceptor>
<interceptor-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</interceptor-class>
</interceptor>
</interceptors>
<assembly-descriptor>
<interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor</interceptor-class>
</interceptor-binding>
</assembly-descriptor>
</ejb-jar>
The actual interface and class XXX interface

/**
* @author czetsuya
* @created May 4, 2012
**/
package com.sido.cg.service.XXX.local;

import javax.ejb.Local;

@Local
public interface XXXServiceBeanLocal {
String register(String email, String macId, String type);
String create(String email, String macId, String type);
}
XXX class

/**
* @author Edward P. Legaspi
* @created May 4, 2012
**/
package com.sido.cg.service.XXX;

import javax.ejb.Stateless;
import javax.interceptor.Interceptors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor;

import com.sido.cg.service.XXX.local.XXXServiceBeanLocal;

@Interceptors(SpringBeanAutowiringInterceptor.class)
@Stateless
public class XXXServiceBean implements XXXServiceBeanLocal {
@Autowired
private XXXService XXXService;

public String register(String email, String macId, String type) {
return XXXService.register(email, macId, type);
}

public String create(String email, String macId, String type) {
return XXXService.create(email, macId, type);
}

}
And I believe that's all you need to call a stateless ejb from another web project powered by spring. Take note that you can also inject spring bean from the ejb stateless bean using SpringBeanAutowiringInterceptor.




- Custom Application Context Or Name In Jboss Or Wildfly
As far as I know there are 3 ways to deploy an application in JBoss or Wildfly with a custom application context name. 1.) By adding jboss-web.xml in your web project WEB-INF folder; <?xml version="1.0" encoding="UTF-8"?> <jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"...

- How To Setup Seam3-security In Jboss 7
Recently, I've done some research on several Java Security Framework that can perform authentication, authorization and cryptography. I've worked with Apache Shiro, it's really good and complete but I've found several problems like there's...

- How To Run Activiti In Glassfish/postgresql In Jta Mode
What you need: 1.) Glassfish 2.) Postgresql - make sure that max_transactions is set to at least 10. Otherwise you will encounter the no session error because by default the value is 0. 3.) Checkout travelexpenses from: https://svn.camunda.com/fox/demo/activiti-cdi/travelexpenses/trunk/...

- How To Enable Jersey Rest Api In A Maven Web Project
This tutorial assumes that you already know how to create a maven project in eclipse. Steps: 1.) Create a new maven web project. (this assumes that you have maven plugin installed in your eclipse). 2.) In your META-INF/web.xml file make sure that you...

- Using Ejb3.1 As The Backing Bean For Jsf Using Cdi (jsr-330)
This tutorial assumes that you already have knowledge on EJB, JSF, maven and injection. These are the steps as well as the code I use to make it work. 1.) Create 2 maven projects (web, ejb - has HelloBean class) 2.) 2.) In the web part we need to create...



Tech-Today








.