2

I'm trying to expose some EJBs as REST web service using JAX-RS annotations. When I deploy war file containing EJB Jar in WEB-INF/lib to Wildfly 8, I can see in web admin panel EJB Jar as deployed, But I cannot reach REST endpoints and get 404.

This is content of web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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/web-app_3_1.xsd"
         version="3.1">
    <servlet-mapping>
        <servlet-name>javax.ws.rs.core.Application</servlet-name>
        <url-pattern>/separated/*</url-pattern>
    </servlet-mapping>
</web-app>

This is a sample session bean I'm trying to serve as web service and put in jar file:

@Stateless(name = "TestSessionEJB")
@LocalBean
public class TestSessionBean {

    @PersistenceContext(unitName = "TestPU")
    private EntityManager em;

    public AuthenticationSessionBean() {
    }

    @GET
    @Path("ep")
    public String testEP() {
        return "Hello from testEP()";
    }
}

I cannot reach testEP through /<war_file_name>/separated/ep. Added ejb-jar.xml descriptor to WEB-INF/, still no success. I made another service with classes compiled and deployed directly in war file's WEB-INF/classes:

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

@Path("/ep")
public class TestRestEp {

    @GET
    public String doGet() {
        return "success";
    }
}

Here I can reach doGet() through /<war_file_name>/integrated/ep.

Am I missing something? Can I deploy EJBs as separated jar files and expose them as REST web services with no wrapper?

UPDATE: I annotated TestSessionBean with ApplicationPath("separated") and made it extending from javax.ws.rs.Application. Still getting 404 but this time It's different; 404 without "Not Found" body. If I make an endpoint path same as an endpoint in TestRestApp, e.g @Path("ep") It maps to endpoint in TestRestApp and I get "success" instead of "Hello from testEP()" by navigating to /<war_file_name>/separated/ep. If I annotate a method in TestSessionBean with a path not defined in TestRestApp result is 404. I cleared my web.xml out of servlet definitions and still same result.

reith
  • 2,028
  • 13
  • 26

1 Answers1

4

First

Simply annotating an EJB class's method with JAX-RS annotations will not make the method a JAX-RS resource method. You need to make TestSessionBean a root resource class by annotating it with @Path, like you did with TestRestEp. Or you can make this class a Sub-Resource and have a Root resource pass the request to this class. I'd just stick to the former, if you have no idea what the latter means.

Second

Keeping in mind Wildfly (JBoss) modular architceture

Stated in the Resteasy (Wildfly's JAX-RS implementation) Reference Guide:

Resteasy and JAX-RS are automically loaded into your deployment's classpath, if and only if you are deploying a JAX-RS Application.

That being said, your web.xml doesn't create a JAX-RS application. You are basically depending on the (default JAX-RS specified) javax.ws.rs.Application servlet, which is only loaded if the JAX-RS module is loaded into the Server.

When you have an Application subclass, with the @ApplicationPath annotation, this creates a JAX-RS application and the JAX-RS module is loaded into the Server and the classpath will be scanned for resource classes.

Also stated in the JAX-RS spec:

The resources and providers that make up a JAX-RS application are configured via an application-supplied subclass of Application. An implementation MAY provide alternate mechanisms for locating resource classes and providers (e.g. runtime class scanning) but use of Application is the only portable means of configuration.

So I would stick to the Application subclass. No web.xml needed

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Thanks, It was helpful. Could you please see my update? And about your second point, isn't having `TestRestApp` enough for `TestSessionBean` too? I saw sample codes with empty class extending Application for this setup, though they did not intend to make separated ejb-jar. – reith Nov 16 '14 at 10:59
  • Your application class should not have any resource methods. If you just leave the `TestSessionBean` how it originially was, just adding `@Path("/test")`, if you create an `Application` class say with `@ApplicationPath("/separated")`, then you can access `/separated/test/ep` – Paul Samsotha Nov 16 '14 at 11:06
  • You're right. I made another class for Application setup and annotated `TestSessionBean` with `Path("ep")` and dropped `Path(..)` from method. It didn't work, but your solution worked. Thanks. – reith Nov 16 '14 at 11:19
  • Do you have an example how this would work with `jboss-deployement-strucure.xml`, without subclassing `Application`? – Jörn Horstmann Feb 08 '15 at 20:47
  • @JörnHorstmann I removed that statement from the post. I forgot what I was thinking when I posted it. Possibly I was simply thinking along the lines of how to deploy the jax-rs module in JBOSS, but completely forgetting that even with the module deployed, we still need to declare an application. Only ways I know are either in web.xml or in Application subclass. – Paul Samsotha Feb 09 '15 at 05:25
  • Dear @Paul Samsotha I have a problem with exposing EJB as a Rest in weblogic: Even though I add a class inherited from Application which annotated with `@ApplicationPath("/resources")` , I could not call the stateless web service with class annotation of `@Path("/getdata")` and method annotation of `@GET @Path("/getaccount")` The URL I used in Weblogic is: `http://localhost:7001/resources/getdata/getaccount` – Hosein Aqajani Aug 30 '19 at 07:20