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