Hot questions for Using Enterprise JavaBeans in rest

Question:

I'm using JBoss 9.x Application Server and I want to create a REST api to communicate with my EJBs. I created two classes PlayerRestApi and PlayerEJB and deploy it to wildfly, but when I requested /player the response is always 404.

Note: I will post the PlayerRestApi class with a dummy return.

PlayerRestApi code:

@Local
@Path("/player")
@Consumes("application/json")
@Produces("application/json")
public class PlayerRestApi{
    PlayerEJB player;

    @GET
    public Map<String, String> getPlayer(){
        Map<String, String> r = new HashMap<String,String>();
        r.put("Name","Ronaldo");
        return r;
    }
}

When I tried this route, localhost: http://localhost:28070/appname/player Wildfly returns 404.


Answer:

You need to use for example RESTEasy libraries, I don´t know if wildfly has it out of the box (is a jboss library), you can use Jersey too.

¿Have you updated your web.xml in order to define the RESTEasy servlets?

Here is an example (you have to put your class in resteasy.resources)

<context-param>
        <param-name>resteasy.resources</param-name>
        <param-value>your JAX-RS annotated class</param-value>
    </context-param>

    <!-- Auto scan REST service -->
    <context-param>
        <param-name>resteasy.scan</param-name>
        <param-value>true</param-value>
    </context-param>

    <listener>
        <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
    </listener>

    <servlet>
        <servlet-name>resteasy-servlet</servlet-name>
        <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>resteasy-servlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

Question:

I've a JSF application that do login via JAAS. It works fine.

Now, my page calls a REST web service. I need to know who did the request.

In the request's header I have:

Cookie = JSESSIONID=XBHZuYnzgkGyQSR8kBLNSks_s7nuXAMli7Gp-9Mn.dlicitra; _ga=GA1.1.1590792307.1560863707

The web service is implemented in a Stateless EJB. The method is:

@Path(value = "myservice/{id}")
@GET
@Produces(value = "application/json")
public List<Records> getServices(
        @HeaderParam(value = "Cookie") String cookie,
        @PathParam(value = "id") Long id){
    return ... ;
}

How can I get the logged user from the cookie string?


Answer:

As explained in the comment, instead of mangling with parsing or decoding the cookie's SessionId, I'd go with the Java EE's security API built-in solution of injecting the SecurityContext into the EJB, and getting the userPrincipal from it:

@Context
private SecurityContext securityContext;

And in your method:

Principal principal = securityContext.getUserPrincipal();

See also:

Baeldung's post on Java EE 8 Security API

Question:

I try to build up a simple EJB-project on JBoss Wildfly. I want a stateless EJB to be a JAX-RS resource class. This REST-service should simply return the Person-entities saved in the database. EJB-Code:

@Stateless
@Path("/person")
public class PersonServiceBean {

    @PersistenceContext EntityManager em;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List<Person> getAllPersons(){
        return em.createQuery("FROM " + Person.class.getName()).getResultList();
    }

}

I read I need a subclass of Application with ApplicationPath-annotation

@ApplicationPath("/rest")
public class JaxRsApplication extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        return new HashSet<Class<?>>(Arrays.asList(PersonServiceBean.class));
    }

}

But still I get 404 at 'localhost:8080/rest/person'. Did I miss to configure something? I would be really thankful for help!


Answer:

The problem is that the Rest Resource must be in a WAR and not in a EJB project.

Question:

I want to create Restful application with ejb, so I create db.jar and restful.war.

In db.jar I have:

@Remote public interface DBManagerRemote

And in restful.war I have:

 @EJB private DBManagerRemote manager;

But when I deploy in glassfish I get an exception:

org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException

What am I doing wrong?

web.xml:

<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>Restful Web Application</display-name>

    <context-param>
        <param-name>resteasy.scan</param-name>
        <param-value>true</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
    </listener>

    <servlet>
        <servlet-name>resteasy-servlet</servlet-name>
        <servlet-class>
            org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>resteasy-servlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

persistence.xml in db.jar:

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
   http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="simpleFactory" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>source_name</jta-data-source>
        <class>Mybean</class>
    </persistence-unit>
</persistence>

Answer:

You are getting a NullPointerException because you're attempting to use container injection in a REST application that is using RestEasy in GlassFish.

RestEasy is not integrated with GlassFish, so injection will never occur.

The easiest solution for you is to:

  1. remove any resteasy jars that you have in your application
  2. completely remove the web.xml
  3. add some standard JAX-RS bootstrap code to your web app:

    @ApplicationPath("/")
    public class JAXRSConfiguration extends Application {
    }
    

This will then use the JAX-RS implementation that is built into GlassFish.

Question:

I have a project maven - EAR, in the same i have a RESTful JAX-RS that work with jersey and it is consuming with JSON, when I try get list to RESTful since EJB, bring not nothing. However when add list in the same REST it works well.!

this is the RESTful with list in the same class!.

@Path("/courseMockRS")
@Consumes({"application/json"})
@Produces({"application/json"})
public class CourseMock_RS {

@GET
@Path("/all_courses")
public List<CourseMock> AllCourses() {
    List<CourseMock> courses = getCoursesMock();
    return courses;
}

public List<CourseMock> getCoursesMock() {
    List<CourseMock> coursesMocks = new ArrayList<CourseMock>();

    CourseMock mock = new CourseMock();
    mock.setName("SOA Analist");
    mock.setAuthor("SOA Education");
    mock.setReleaseDate("16/07/2015");
    coursesMocks.add(mock);

    mock = new CourseMock();
    mock.setName("SOA Architect");
    mock.setAuthor("SOA ET");
    mock.setReleaseDate("16/07/2015");
    coursesMocks.add(mock);

    mock = new CourseMock();
    mock.setName("SOA Consultant");
    mock.setAuthor("SOA ET");
    mock.setReleaseDate("16/07/2015");
    coursesMocks.add(mock);

    return coursesMocks;
}
}

Thus it works well!

[{"name":"SOA Analist","author":"SOA Education","releaseDate":"16/07/2015"},    
{"name":"SOA Architect","author":"SOA ET","releaseDate":"16/07/2015"},
{"name":"SOA Consultant","author":"SOA ET","releaseDate":"16/07/2015"}]

But when implement EJB not found!, However the application it is deployed and the Stateless resource is accepted.

This is the resources from EJB.

DTO

public class CourseMock {

private String name;
private String author;
private String releaseDate;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getAuthor() {
    return author;
}

public void setAuthor(String author) {
    this.author = author;
}

public String getReleaseDate() {
    return releaseDate;
}

public void setReleaseDate(String releaseDate) {
    this.releaseDate = releaseDate;
}   
}

Facade

@Stateless
@LocalBean
public class CourseFacadeMock implements ICourseMockFacade{

private CourseMock mock;

@Override
public List<CourseMock> getCoursesMock() {
    List <CourseMock> coursesMocks = new ArrayList<CourseMock>();

    mock= new CourseMock();
    mock.setName("Analista SOA");
    mock.setAuthor("SOA Education");
    mock.setReleaseDate("16/07/2015");        
    coursesMocks.add(mock);

    mock= new CourseMock();
    mock.setName("SOA Analist");
    mock.setAuthor("SOA Education");
    mock.setReleaseDate("16/07/2015");
    coursesMocks.add(mock);

    mock = new CourseMock();
    mock.setName("SOA Architect");
    mock.setAuthor("SOA ET");
    mock.setReleaseDate("16/07/2015");
    coursesMocks.add(mock);

    mock = new CourseMock();
    mock.setName("SOA Consultant");
    mock.setAuthor("SOA ET");
    mock.setReleaseDate("16/07/2015");
    coursesMocks.add(mock);

    return coursesMocks;

}

}

Interface Facade

@Local
public interface ICourseMockFacade {

public List<CourseMock> getCoursesMock();
}

And the RESTful

@Path("/courseMockRS")
@Consumes({"application/json"})
@Produces({"application/json"})
public class CourseMock_RS {

@EJB
ICourseMockFacade courseMockFacade;

@GET
@Path("/all_courses")
public List<CourseMock> AllCourses() {
    List<CourseMock> courses = courseMockFacade.getCoursesMock();
    return courses;
}    
}

Thus fails.. The Exception is NUllPointerException. Help, please!.


Answer:

I´ve created a project with your code and it's working perfectly assuming you have in place the JAX-RS Configuration class with something like:

@ApplicationPath("resources")
public class JAXRSConfiguration extends Application {

}

In this case, if the EJB is not injected, maybe, the problem is in your beans.xml file, the property bean-discovery-mode should be set to "all". As an example:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
   bean-discovery-mode="all">
</beans>

I hope it helps.