Search code examples
restweb-servicesjerseyjax-rsjersey-2.0

Why am I getting 404 error Message "Not Found" on get request for my jersey rest service?


I have actually a similar problem as described here JAX-RS Resource not found in GlassFish Server. Since one should not ask for help in the answers I make a new question.

I created a project named "SPCore" which is a simple RESTful Webservice. It uses jax-rs libs, jdk 11 and a Tomcat 9.0.44 server. I have an index.html in the webapps folder which shows Hello World. The context path is set to /sp-core. If I'm calling localhost:8080/sp-core the index.html file is returned. So that works.

I have some resources (I will only show one as example). The resource "ProcessEventResource" should return "hello world" as plain text when a GET request comes. The path is set to @Path("processEvent"). Sadly I get an error 404 when I'm calling localhost:8080/sp-core/processEvent

I tried so far:

  1. add an / at the beginning of the path declaration

  2. I added a subclass application as mentioned here in the updated answer JAX-RS Resource not found in GlassFish Server. Still I get the 404 error when calling localhost:8080/sp-core/api/rest/processEvent

I have the assumption that something with the servlets or paths is not working correctly.

In the following I will provide my project structure, the pom file, the resource and the application class. I cut some small parts (package names, group-id, ...) which refers to the company I'm working for. If you need more Information please let me know.

Project structure

pom.xml:

<?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>

<artifactId>sp-core</artifactId>
<version>1.0-SNAPSHOT</version>
<name>sp-core</name>
<packaging>war</packaging>

<properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
</properties>

<dependencies>
    <dependency>
        <groupId>javax.ws.rs</groupId>
        <artifactId>javax.ws.rs-api</artifactId>
        <version>2.1.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20210307</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.3.0</version>
        </plugin>
    </plugins>
</build>

processEventResource which simply returns hello world:

@Path("processEvent")
@Provider
public class ProcessEventResource {

    public ProcessEventResource(){
    }

    @GET
    @Produces("text/plain")
    public String processEvent() {
        return "Hello, World!";
    }
}

RestApplication class:

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

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

}

I would expect to get the hello world response when I'm calling localhost:8080/sp-core/api/rest/processEvent

Thanks in advance for your help and time.

+++++++++++++++++++++++++++Update+++++++++++++++++++++++++++

I switched from dependency javax to jersey and added a web.xml file. The new pom.xml looks like this

<name>sp-core</name>
<packaging>war</packaging>

<properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
</properties>

<dependencies>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-server</artifactId>
        <version>2.33</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.33</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.inject</groupId>
        <artifactId>jersey-hk2</artifactId>
        <version>2.33</version>
    </dependency>
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20210307</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.3.0</version>
        </plugin>
    </plugins>
</build>

The web.xml looks like this:

<display-name>sp-core</display-name>

<servlet>
    <servlet-name>RestServlet</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>RestServlet</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

Now I either get a 404 with message "Not Found" or "The requested resource [/sp-core/api/rest/processEvent] is not available". Which path should go where so I get the return "Hello World" when I call localhost:8080/sp-core/api/rest/processEvent

+++++++++++++++++++++++++++Update+++++++++++++++++++++++++++

I added init parameter to the web.xml

<init-param>
    <param-name>javax.ws.rs.core.Application</param-name>
    <param-value>abc.de.fg.SPCore.RestApplication</param-value>
</init-param>

The error message is still the same.


Solution

  • After reading many stackoverflow questions, JAX-RS docu and in the end maven docu I finally got it done. So I will show what I have done in the end.

    As I wrote in the first update I added a web.xml file which ended up looking like this.

    <web-app version="3.0" 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">
        <display-name>sp-core</display-name>
        <servlet>
            <servlet-name>restServlet</servlet-name>
            <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>javax.ws.rs.Application</param-name>
                <param-value>abc.de.fg.sp_core.RestApplication</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>restServlet</servlet-name>
            <url-pattern>/api/rest/*</url-pattern>
        </servlet-mapping>
    </web-app>
    

    Please note, that the param name for the application is javax.ws.rs.Application and not javax.ws.rs.core.Application as said in the documentation (always read the notes ...).

    I ended up only using the jersey container-servlet and the jersey-hk2 dependencies (JSON dependency is only for another resource). So the pom.xml looks like the following:

    <?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>abc.de.fg</groupId>
        <artifactId>sp-core</artifactId>
        <version>1.0-SNAPSHOT</version>
        <name>sp-core</name>
        <packaging>war</packaging>
    
        <properties>
            <maven.compiler.target>11</maven.compiler.target>
            <maven.compiler.source>11</maven.compiler.source>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey.containers</groupId>
                <artifactId>jersey-container-servlet</artifactId>
                <version>2.33</version>
            </dependency>
            <dependency>
                <groupId>org.glassfish.jersey.inject</groupId>
                <artifactId>jersey-hk2</artifactId>
                <version>2.33</version>
            </dependency>
            <dependency>
                <groupId>org.json</groupId>
                <artifactId>json</artifactId>
                <version>20210307</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.3.0</version>
                </plugin>
            </plugins>
        </build>
    </project>
    

    My RestApplication overrides the getClasses Method from the Application class. There I added all my resources. The ApplicationPath is set to /*

    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;
    import java.util.HashSet;
    import java.util.Set;
    
    @ApplicationPath("/*")
    public class RestApplication extends Application {
        public RestApplication() {
        }
    
        @Override
        public Set<Class<?>> getClasses() {
            Set<Class<?>> s = new HashSet<Class<?>>();
            s.add(ProcessEventResource.class);
            return s;
        }
    
    }
    

    And then it finally worked and I got my Hello World when requesting http://localhost:8080/sp-core/api/rest/processEvent.

    Another short problem I run into was a 500 error missing RestApplication class. Simply forgot to maven compile ...

    Hope this question and answer helps others. Cheers :)