0
votes

I know the title looks like many people have asked this question before, but I did a lot of research and couldn't find any solution solves my problem. I've spent two days on this issue so please help me out!

I am trying to build a simple "hello world" type of restful web service with Eclipse Kepler Service Release 2, Jersey, Eclipse build-in maven, Servlet 3.0 and Tomcat 7.0. When I run my service using "Run As" --> "Run on Server", there is no problem loading the default "index.jsp" page, but I keep getting the HTTP 404 error when loading my service.

This image shows my project layout.

My class that implements Application is like the following:

package com.ys.java.ws;

import java.util.HashSet;
import java.util.Set;

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

import com.ys.java.ws.resources.MyService;

@ApplicationPath("/ys")
public class MyApplication extends Application {
    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> s = new HashSet<Class<?>>();
        s.add(MyService.class);
        return s;
    }

}

My resource class is:

package com.ys.java.ws.resources;

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

@Path("/test")
public class MyService {

    public MyService() {

    }

    @GET
    @Path("/hello")
    //@Produces(MediaType.TEXT_PLAIN)
    @Produces("text/html")
    public String getTestMsg() {
        return "It works";
    }
}

My pom.xml file is:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ys.java.ws</groupId>
    <artifactId>ysNoWebXML</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>ysNoWebXML Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <!-- Servlet 3.0 API -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
        </dependency>
        <!--JAX-rs web service API -->
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-common</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>2.23.1</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>TestService</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

My web.xml is:

<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>Servlet 3.0 Web Application</display-name>
    <servlet>
        <servlet-name>com.ys.java.ws.MyApplication</servlet-name>
    </servlet>
    <servlet-mapping>
        <servlet-name>com.ys.java.ws.MyApplication</servlet-name>
        <url-pattern>/rest</url-pattern>
    </servlet-mapping>
</web-app>

Note that: in MyApplication class, I set @ApplicationPath("/ys") and in web.xml I set <url-pattern>/rest</url-pattern>. I intensionally do this since according to jax-rs document,

If both the <servlet-mapping> and @ApplicationPath are specified, the <servlet-mapping> takes precedence.

I want to test if it is the case, but no matter which path I use, I get HTTP 404 error.

2
I don't see what URL you are using to do the test access to your running application.Lee Meador
I don't have enough points to add more than 2 urls. So... I tested the following: localhost:8080/TestService/rest/test/hello ---- get 404, localhost:8080/TestService/ys/test/hello --- get 404, localhost:8080/TestService --- works, load default index.jspuser2573741

2 Answers

0
votes

Here is an example of the way the web.xml works:

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
    <servlet>
        <servlet-name>comingsoon</servlet-name>
        <servlet-class>mysite.server.ComingSoonServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>comingsoon</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Maybe you need to have both servlet-name and servlet-class. Notice the servlet-name in the servlet-mapping section has to match the servlet-name in the servlet section.

Notice how you also need a star in the url-pattern. Yours would look like "/rest/*".

0
votes

I finally got it work! Post my solution here just in case anyone has similar problems in the future.

There are a few mistakes I made before and corrected now.

  1. Adding /* in the <url-pattern> is important. I saw many tutorials do not use *, but it is wrong.
  2. You do NOT need the <servlet-class> tag in servlet 3.0. Instead, put the fully qualified name of your application class in the <servlet-name> tag. So the jax-rs document is correct.
  3. This bullet is not that critical, but I was curious about it and now understand it and just share it. So "jersey-container-servlet-core" and "jersey-container-servlet" are similar packages, but the former one adapts to Jersey 2.x and won't work for Jersey 3.x. This blog talks about details. For this reason, only "jersey-container-servlet" is needed in my pom.xml file.

So my final web.xml is:

<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>Servlet 3.0 Web Application</display-name>
    <servlet>
        <servlet-name>com.ys.java.ws.MyApplication</servlet-name>
    </servlet>
    <servlet-mapping>
        <servlet-name>com.ys.java.ws.MyApplication</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>