nicholas
nicholas

Reputation: 2762

EJB Object Null Pointer Exception Inside JAX-WS Web Service

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

Answers (1)

Paulius Matulionis
Paulius Matulionis

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

Related Questions