Search code examples
javaservletsjerseyjax-rs

JAX-RS (Jersey) API in standalone Servlet 5 container does not start


Just want to build a Java application with a REST API (JAX-RS implemented by Jersey 2.33) that runs in a standalone Servlet 5 container, e.g. Tomcat 10. For this the build process (via Maven) creates a *.war file which is put subsequently into the webapps/ folder to start it.

The problem is that the JAX-RS API, that is to say its servlet, is not coming up. So calling the URL

http://localhost:8080/weld/api/address

produces HTTP Status 404 (not found).

The pom.xml looks as follows:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.test</groupId>
    <artifactId>weld</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>weld Maven Webapp</name>


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <servlet-api.version>5.0.0</servlet-api.version>
        <jax-rs-api.version>2.1.6</jax-rs-api.version>
        <jersey.version>2.33</jersey.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>${servlet-api.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jakarta.ws.rs</groupId>
            <artifactId>jakarta.ws.rs-api</artifactId>
            <version>${jax-rs-api.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>${jersey.version}</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>weld</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

The required dependencies and the rest to get it to work I have read from the Jersey documentation. The *.war doesn't contain any web.xml because since Servlet API 3.1 this is optional. The class javax.ws.rs.core.Application which should actually auto-detected and bootstrap the JAX-RS API looks as follows:

package de.test.weld;

import org.glassfish.jersey.server.ResourceConfig;

import javax.ws.rs.ApplicationPath;

@ApplicationPath("api")
public class MyApplication extends ResourceConfig {

   public MyApplication() {
       registerClasses(AddressService.class);
   }
}

The Java class with the very endpoint looks then like this:

package de.test.weld;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/address")
public class AddressService {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getAddress() {
        return "any text, bla, nonsense";
    }
}

Anything essential seems to be missing so that the Jersey Sevlet can be started.

A glimpse into the *.war looks like this:

$> jar -tvf webapps/weld.war 
     0 Sat Mar 13 13:13:24 CET 2021 META-INF/
   131 Sat Mar 13 13:13:22 CET 2021 META-INF/MANIFEST.MF
     0 Sat Mar 13 13:13:24 CET 2021 WEB-INF/
     0 Sat Mar 13 13:13:24 CET 2021 WEB-INF/classes/
     0 Sat Mar 13 13:13:24 CET 2021 WEB-INF/classes/de/
     0 Sat Mar 13 13:13:24 CET 2021 WEB-INF/classes/de/test/
     0 Sat Mar 13 13:13:24 CET 2021 WEB-INF/classes/de/test/weld/
     0 Sat Mar 13 13:13:24 CET 2021 WEB-INF/lib/
   619 Sat Mar 13 13:13:24 CET 2021 WEB-INF/classes/de/test/weld/AddressService.class
  1025 Sat Mar 13 13:13:24 CET 2021 WEB-INF/classes/de/test/weld/TestServlet.class
   581 Sat Mar 13 13:13:24 CET 2021 WEB-INF/classes/de/test/weld/MyApplication.class
 25058 Fri Mar 12 15:26:10 CET 2021 WEB-INF/lib/jakarta.annotation-api-1.3.5.jar
 19479 Fri Mar 12 15:26:10 CET 2021 WEB-INF/lib/osgi-resource-locator-1.0.3.jar
1174508 Fri Mar 12 15:26:10 CET 2021 WEB-INF/lib/jersey-common-2.33.jar
942190 Fri Mar 12 15:26:10 CET 2021 WEB-INF/lib/jersey-server-2.33.jar
 18140 Fri Mar 12 15:26:10 CET 2021 WEB-INF/lib/jakarta.inject-2.6.1.jar
253811 Fri Mar 12 15:26:10 CET 2021 WEB-INF/lib/jersey-client-2.33.jar
 91930 Fri Mar 12 15:26:10 CET 2021 WEB-INF/lib/jakarta.validation-api-2.0.2.jar
 32383 Fri Mar 12 15:26:10 CET 2021 WEB-INF/lib/jersey-container-servlet-2.33.jar
 73402 Fri Mar 12 15:26:10 CET 2021 WEB-INF/lib/jersey-container-servlet-core-2.33.jar
140376 Fri Mar 12 15:11:24 CET 2021 WEB-INF/lib/jakarta.ws.rs-api-2.1.6.jar
     0 Sat Mar 13 13:13:24 CET 2021 META-INF/maven/
     0 Sat Mar 13 13:13:24 CET 2021 META-INF/maven/de.test/
     0 Sat Mar 13 13:13:24 CET 2021 META-INF/maven/de.test/weld/
  2757 Sat Mar 13 13:12:34 CET 2021 META-INF/maven/de.test/weld/pom.xml
   106 Sat Mar 13 13:13:24 CET 2021 META-INF/maven/de.test/weld/pom.properties

Here are some information about the versions in use: Java 11, Maven 3.6, JAX-RS (Jersey 2.33), Servlet API 5.0.0, Tomcat 10 or Jetty 11


Solution

  • You need to use Jersey 3.x. The 3.x line is the first line that makes use of the Jakarta namespace. You have all the Jakarta dependencies (JAX-RS, Servlet), just the Jersey version you are using does not make use of them. See the Jersey docs for the latest 3.x version.

    In the new Jakarta EE, all the javax packaging has changed to jakarta, e.g. jakarta.ws.rs.ApplicationPath. Once you change the Jersey version (assuming you don't have any other old dependencies, you should get import errors. All the javax imports should show errors. They should all be switched out with jakarta. All the javax imports (that includes JAX-RS, Servlet, Inject, etc).