Reputation: 2762
I'm tried to develop a web service application that utilize EJB function inside web service class but the EJB object is null during run time.
I'm configure the web service using Spring Application Context. Is there any problem with it?
Code:
public class CreditCardService implements ICreditCardService {
private static final Logger logger = Logger.getLogger(CreditCardService.class.getName());
@EJB
private CreditcardFacadeLocal databaseFacade;
@Override
public void addCreditCard(Creditcard card) {
logger.log(Level.INFO, "Add credit card start");
databaseFacade.addCreditCard(card); // NPE Here
logger.log(Level.INFO, "Add create card finish");
}
}
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>CreditCardWebService</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<enabled>true</enabled>
<async-supported>false</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>
/services/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
Beans.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" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<!-- <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> -->
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!-- Create Web Service End Point using Spring DI-->
<jaxws:endpoint xmlns:tns="http://service.peter.com/"
id="creditcardservice" implementor="com.peter.service.CreditCardService"
wsdlLocation="wsdl/creditcardservice.wsdl" endpointName="tns:CreditCardServicePort"
serviceName="tns:CreditCardServiceService" address="/CreditCardServicePort">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
</jaxws:endpoint>
</beans>
What is the reason the ejb ojbect is null? Is it relate to Spring DI of CreditCardService class but does not instantiate the ejb object?
What is the purpose of CXF servlet? Is it use to handle web service request?
Please help.
Thanks.
Upvotes: 1
Views: 2604
Reputation: 23415
CXF
servlet is used to handle web service request. CXF
is a stack for web services which is based on JAX-WS
but have some features JAX-WS
does not. Take a look here.
You can not inject your EJB
object using @EJB
annotation in your web service. @EJB
annotation only works with managed beans, such as servlets, etc... Or in EJB
context.
To inject your EJB
you need to make the JNDI
look up in your web service. So it would be something like this:
/**
* Java global JNDI.
*/
private static final String JAVA_GLOBAL = "java:global/";
/**
* Application name in application server.
*/
private static final String APP_NAME = "YourAppName/";
/**
* Application EJB jar name.
*/
private static final String APP_EJB = "your-ejb/";
/**
* Credit EJB constant.
*/
public static final String CREDIT_EJB = JAVA_GLOBAL + APP_NAME + APP_EJB + "CreditcardFacade!your.package.CreditcardFacadeLocal";
Now create a generic method to get your EJB
objects from JNDI
:
/**
* Gets local EJB from JNDI.
*
* @param jndiName JNDI constant name to look up for EJB
* @param <T> generic object
* @return local EJB object loaded from JNDI
*/
public static <T> T getLocalEJB(String jndiName) {
try {
InitialContext context = new InitialContext();
return (T) context.lookup(jndiName);
} catch (NamingException e) {
LOGGER.error("Naming exception occurred while trying to load EJB from JNDI with JNDI name: " + jndiName, e);
throw new RuntimeException("Naming exception occurred while trying to load EJB from JNDI with JNDI name: " + jndiName, e);
}
}
Now you can get your EJB like this:
CreditcardFacadeLocal facade = JndiUtils.getLocalEJB(JndiUtils.CREDIT_EJB);
I have done it myself in CXF web service, everything works perfectly.
Upvotes: 1