Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject an EJB into JAX-RS (RESTful service)

I'm trying to inject a Stateless EJB into my JAX-RS webservice via annotations. Unfortunately the EJB is just null and I get a NullPointerException when I try to use it.

@Path("book") public class BookResource {      @EJB     private BookEJB bookEJB;      public BookResource() {     }      @GET     @Produces("application/xml")     @Path("/{bookId}")     public Book getBookById(@PathParam("bookId") Integer id)     {         return bookEJB.findById(id);     } } 

What am I doing wrong?

Here is some information about my machine:

  • Glassfish 3.1
  • Netbeans 6.9 RC 2
  • Java EE 6

Can you guys show some working example?

like image 436
Zeck Avatar asked Jun 12 '10 07:06

Zeck


People also ask

How do you expose EJB as a REST service?

Now for building Restful web service from an EJB class, all that we need to do is to package the web service in a Web application (servlet 3.0/3.1) and create an application class that loads the EJB class as a Rest Root class and annotating the EJB class with @Path annotation.

Is EJB an API?

WebNMS SNMP for EJB has been designed to support EJB applications, and conform to the EJB standards. The EJB standard restricts the Enterprise Java Bean from performing certain functions, such as socket access.


2 Answers

I am not sure this is supposed to work. So either:

Option 1: Use the injection provider SPI

Implement a provider that will do the lookup and inject the EJB. See:

  • @EJB injection.

Example for com.sun.jersey:jersey-server:1.17 :

import com.sun.jersey.core.spi.component.ComponentContext; import com.sun.jersey.core.spi.component.ComponentScope; import com.sun.jersey.spi.inject.Injectable; import com.sun.jersey.spi.inject.InjectableProvider;  import javax.ejb.EJB; import javax.naming.Context; import javax.naming.InitialContext; import javax.ws.rs.ext.Provider; import java.lang.reflect.Type;  /**  * JAX-RS EJB Injection provider.  */ @Provider public class EJBProvider implements InjectableProvider<EJB, Type> {      public ComponentScope getScope() {         return ComponentScope.Singleton;     }      public Injectable getInjectable(ComponentContext cc, EJB ejb, Type t) {         if (!(t instanceof Class)) return null;          try {             Class c = (Class)t;             Context ic = new InitialContext();              final Object o = ic.lookup(c.getName());              return new Injectable<Object>() {                 public Object getValue() {                     return o;                 }             };         } catch (Exception e) {             e.printStackTrace();             return null;         }     } } 

Option 2: Make the BookResource an EJB

@Stateless @Path("book") public class BookResource {      @EJB     private BookEJB bookEJB;      //... } 

See:

  • How to Combine REST Services with EJB 3.1
  • EJB 3.1 And REST - The Lightweight Hybrid

Option 3: Use CDI

@Path("book") @RequestScoped public class BookResource {      @Inject     private BookEJB bookEJB;      //... } 

See:

  • Injecting an EJB from a jar into a jax-rs class in a war
like image 148
Pascal Thivent Avatar answered Oct 14 '22 08:10

Pascal Thivent


This thread is rather old, nevertheless i fought the same problem just yesterday. Here is my solution:

Just make the BookResource a managed bean through @javax.annotation.ManagedBean at class level.

For this to work you need to enable CDI with a beans.xml:

<?xml version="1.0" encoding="UTF-8"?> <beans 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/beans_1_0.xsd"> </beans> 

This file needs to be in WEB-INF if the BookResource is part of a war file. If the BookResource is packaged with the ejbs put it into META-INF.

If you want to use @EJB you're done. If you want to inject the EJB through @Inject than a beans.xml must be put into the ejbs jar file into META-INF as well.

What you're doing: You're just telling the container that the resource should be container managed. Therefor it supports injection as well as lifecycle events. So you have your business facade without promoting it to an EJB.

You don't need to extend javax.ws.rs.core.Application for this to work. BookResource is as a root resource automatically request scoped.

Tested with Glassfish 3.1.2 and a maven project.

Happy coding.

like image 22
Michael Simons Avatar answered Oct 14 '22 08:10

Michael Simons