1

I have a problem with configuration ( or basic understanding how things work at background). I create a JAVAEE project by checking Web application and ReSt api checkbox ( in intellij with glassfish 5.0). I have sample code below which web methods work but welcome page does not work. My web.xml and sample web service methods are below.

<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>test</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    **<url-pattern>/ *</url-pattern>**
</servlet-mapping>



@Path("/RestTest")
public class TestString {

@Context
ServletContext context;

@GET
@Path("insertdb/{param1}/{param2}")
@Produces(MediaType.APPLICATION_JSON)
public Object writeToDb( @PathParam("param1") String param1
                        ,@PathParam("param2") String param2){
     try{
        String password=  context.getInitParameter("DbPassword");
        Class.forName("org.mariadb.jdbc.Driver");
        Connection dbCon = DriverManager.getConnection(
                 "jdbc:mariadb://xxx/testdb", "root", password);
        PreparedStatement stmt=dbCon.prepareStatement(
                "INSERT INTO TestTable VALUES(?,?)");
        stmt.setString(1,param1);
        stmt.setString(2,param2);
        stmt.executeUpdate();

        dbCon.close();

        return "Success";
    }catch(SQLException | ClassNotFoundException ex){
        return  ex.toString();
    }

}

@GET
@Path("sum/{sum1}/{sum2}")
@Produces(MediaType.TEXT_HTML)
public String calculateSum(@PathParam("sum1") int param1
        ,@PathParam("sum2") int param2){
    return ""+(param1 + param2);
}

If i change this line url-pattern "/*" to "/" then welcome page is accessible but not methods.

Thus what i want is, having a welcome page which i will use for documentation for my web services(i dont want SOAP) and web methods must work by adding / to base url. How can i achieve that and what is difference between /* and /

Mert Serimer
  • 1,217
  • 2
  • 16
  • 38

4 Answers4

3

See here for explanation of differences: What is url-pattern in web.xml and how to configure servlet

Generally for a rest api it is best to use a path specific to all rest calls, for instance http://localhost/mywebapp/rest/...

Something like:

<servlet-mapping>
    <servlet-name>jersey-servlet/servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

You only want jersey serving particular URLs when it is bundled in a WAR that also includes html pages.

Jim Weaver
  • 983
  • 5
  • 15
1

Servlet configuration and url-pattern

As you highlighted, your problem revolves around those four lines:

<servlet-mapping>
    <servlet-name>Jersey Web Application</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

As Jim Weaver mentioned, it's a matter of url-pattern.

Solution(s)

You may consider three solutions (from the most-preferred to least-preferred):

  1. dedicated REST URL: the easiest way is to have a dedicated url-pattern such as /rest/* for your web services. You can benefit some assets such as url hierarchy or you can easily implement a security framework over it.
  2. URL rewriting may be an option and this answer suggests some library. I haven't tested those libraries myself
  3. Page redirection can be an option to go around REST filtering but in the specific case of having the url-pattern at /*, I have to say I'm not sure if it's working for the reason I'll explain in next section

now a bit of explanation of what happened

Why setting the url-pattern at /* prevent from accessing the welcome page?

Actually, it's not only the welcome page that is not accessible: it's all the resources under the defined url-pattern. Whatever get in touch with REST stays with REST... Here is the schema taken from JSR 339 Appendix C: JSR 339 Appendix C

With a GlassFish 5.0, I guess you're using JAX-RS 2.1 (JSR 370) but the sections I'm quoting have the same content

Without entering into detail, it is visible that only ContainerRequest Filters are executed in the process. Especially, it's worthy to notice that after Request Matching, requests are not forwarded to any servlet in a sense that standard resources are not reachable, unless specified by the REST method.

It's also worthy to highlight the fact the servlet filters are executed beforehand (leveraging this point is absolutely vital for managing security for example). I did not find back the source proving this point but I know it's somewhere on the web ^^.

Request matching is defined at section 3.7.2. In a nutshell, it is in three steps where the first one is the most important for your question, especially at step D:

  1. Identify a set of candidate root resource classes matching the request

    c. ...

    d. If [the set of classes whose path matches the request URL] is empty then no matching resource can be found, the algorithm terminates and an implementation MUST generate a NotFoundException (404 status) and no entity

    e. ...

highlights are mine.

The two last steps are

  1. Obtain a set of candidate resource methods for the request
  2. Identify the method that will handle the request

TL;DR

What happened when you set <url-pattern>/*<url-pattern> and tries to access to your welcome page (or any page actually):

  1. Your server receives the GET request
  2. If there are filters (such those from a security framework), there are executed
  3. REST enters the scene
  4. Pre Match filters are executed (none if your case)
  5. Fetch your root resources classes (in your example, all classes in the test package)
  6. Find if one of those class match the request URL
  7. None are found, a 404 status is returned

To avoid unnecessary URL conflicts, the best options would be having a dedicated URL for your REST methods

Al-un
  • 3,102
  • 2
  • 21
  • 40
1

To answer your question, difference between "/" and "/*"

A mapping that contains the pattern "/" matches a request if no other pattern matches. This is the default mapping. The servlet mapped to this pattern is called the default servlet. The default mapping is often directed to the first page of an application. Example :

Both requests will display same contents from index.jsp

http://myhost.com/index.jsp

and

http://myhost.com/

Now, a mapping that contains "/*" overrides all other servlets, including all servlets provided by the servlet container such as the default servlet and the JSP servlet. Whatever request you fire, it will end up in that servlet. This is thus a bad URL pattern for servlets.


Possible solution for your issue

Change the URL pattern to specific instead of default pattern.

<servlet>
    <servlet-name>webservice</servlet-name>  //servlet name
    <servlet-class>com.rest.MyRestServlet</servlet-class>  //servlet class
</servlet>
 <servlet-mapping>
    <servlet-name>webservice</servlet-name>   //servlet name
    <url-pattern>/RestTest/*</url-pattern>  //all webservice request
</servlet-mapping>

All the web service request are accessible through

http://myhost.com/RestTest/

You may also be interested to look

What is URL-pattern in web.xml and how to configure servlet

Basics of Java Servlet

Community
  • 1
  • 1
Ravi
  • 30,829
  • 42
  • 119
  • 173
0

If you mention in web xml like following all the request receive by 'Jersey Web Application' servlet. so request to index.jsp also redirect to 'Jersey Web Application' servlet

<servlet-mapping>
  <servlet-name>Jersey Web Application</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

To avoid this add some prefix to the url to separate rest request like following

<servlet-mapping>
  <servlet-name>Jersey Web Application</servlet-name>
  <url-pattern>rs/*</url-pattern>
</servlet-mapping>
janith1024
  • 1,042
  • 3
  • 12
  • 25