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 ...
https://www.czetsuyatech.com/2012/05/javaee-call-ejb-from-spring-rest.html
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
beanRefContext.xml
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.




Post a Comment