java how - Reasons for not directly writing Servlets for creating a REST API




json with (5)

For me the real advantage of using Spring MVC is the increase of productivity. Writing everything from scratch to tune things up make sense if you need a really customized application. Although it can be cool to create something new with no frameworks at all, when it gets bigger, you will face problems that were already solved by hundreds of damn good developers. Using Spring MVC will save you a lot of time that you would probably waste reinventing the wheel and even more time when you will have to train someone to deal with your awesome custom code.

In my current company we are starting a new project that will be a REST API in Java, deployed in a servlet container like Tomcat. In my previous experience using REST frameworks like JAX-RS with Jersey, JBOSS REST Easy, Spring MVC I know what are some of the advantages of using a framework like those over writing directly the Servlets for processing the requests.

(Of course we know that the mentioned frameworks still use Servlets under the covers)

I am finding difficult to convince them. As they are proposing to write servlets thinking it is better for performance (which can be the case but I think the overhead of using one of those frameworks should be insignificant for a REST API).

Here are my reasons:

1) Less boilerplate and more concise code (which is easier to maintain and test). With a JAX-RS framework or SpringMVC you can define a REST resource very easily by writing methods with annotations indicating the PATH of the resource, the http method to use, query and url parameters, headers like encoding accepted, etc.

Example:

@GET
@Path("/users")
@Produces({MediaType.APPLICATION_JSON}) 
public UserList getUsers(@QueryParam("group") String group) {
    return userService.findUsers(group);
}

With servlets you will need at least something like this:

Map the url for each servlet in web.xml (Which is not necessary in and above Servlet 3.0):

<servlet>
    <servlet-name>UsersServlet</servlet-name>
    <servlet-class>test.UsersServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>UsersServlet</servlet-name>
    <url-pattern>/users</url-pattern>
</servlet-mapping>

Then inside the servlet class:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    String group = request.getParameter("group");
    response.setContentType("application/json");
    PrintWriter out = response.getWriter();
    JsonSerializer someJsonSerializer = new JsonSerializer();
    String json = someJsonSerializer.serialize(userService.findUsers(group));      
    out.print(json);
}

2) Adaptability. The mentioned frameworks allow you to easily add features to your application that otherwise you will need to do it manually, like using multiple media type inputs and outputs. For example making a service to return xml or json or any other depending on the accept header. Frameworks like SpringMVC and Jersey make it very easy to configure serializers/deserializers for your requests, responses.

3) REST best practices. Normally those frameworks are built over a solid understanding of the best practices to be followed by a REST API and are defined based on standards of the REST architecture which makes easier to build a solid and standard conforming application. In the other hand Servlets give you a so high level of freedom on how to process your requests/responses that it will be more difficult to realize that you are not being RESTfull at all.

Any other?


First, I would consider setting up a simple test with two applications which have a "Hello World" servlet -- one with pure servlets, one with Spring MVC or Apache CXF or your framework of choice. Then run a performance test to prove (hopefully) that the performance hit is insignificant.

Also, serializers and deserializers are one good example, but the interceptor/filter pattern that is available in these frameworks is very useful for other things as well:

  • Authentication/Security
  • Logging of raw requests if needed
  • Header and content transformations that can be kept separate from business logic

In addition, there are tools that plug into these frameworks that will generate documentation (WADLs/WSDLs/Enunciate) and client class libraries. There are also testing libraries that can be used to generate automated tests against well known frameworks.

I used to reinvent the wheel too. But it no longer makes sense (if it ever did.)


Serveral monthes ago I put a comment saying that I was for the pure Servlet 3.0 solution against the use of RES MVC frameworks.

After monthes of usage, I confirm my choice!

I tried to install Jackson and others frameworks but it needs more work than writing the extra 5 lines of code and I don't have to cope with an extra software component to setup, learn, update...

Here is my working example:

package example;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;

/**@WebServlet(name = "booking", urlPatterns = { "/api/v1/booking" })*/
public class BookingWs extends javax.servlet.http.HttpServlet {

    public static final Logger LOGGER = LoggerFactory.getLogger(BookingWs.class);

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        try {
            // Used for JSON handling
            Gson gson = new Gson(); 

            // De-serialize from request
            BookingRequest bRequest = gson.fromJson(request.getReader(), BookingRequest.class);

            // Do your business logic.
            BookingResponse bResponse = new BookingResponse();
            bResponse.request = bRequest;
            bResponse.accepted = "bar".equalsIgnoreCase(bRequest.type);
            bResponse.reason = bResponse.accepted ? "Welcome" : "Only bar table booking left";

            // Serialize and send response back;
            response.setContentType("application/json");
            PrintWriter pw = response.getWriter();
            gson.toJson(bResponse, pw);
        } catch (Throwable t) {
            response.setStatus(500);
            PrintWriter pw = response.getWriter();
            pw.write("{\"error\":\"" + t.getLocalizedMessage() + "\"}");
        }
    }
}

class BookingRequest{
    String type;
    int seats;
    String name;
    long requiredTimestamp;
}

class BookingResponse{
    BookingRequest request;
    boolean accepted;
    String reason;
}  

Maybe theses frameworks have a feature you need absolutely, but for me it should be decisive enought to worth the hassle of extra libs.

As a French author Antoine de Saint Exupery said:

"Perfection is Achieved Not When There Is Nothing More to Add, But When There Is Nothing Left to Take Away".

I took away Jackson to get closer to it :-)

(Yes I have to admit, I used GSON, but it's a small jar, without any configuration needed).


Let me play the devil's advocate with my answer.

First, you don't need to add the servlets to the web.xml file. Servlets 3.0 allow you to use annotations.

Second, there really is a significant performance hit with these frameworks. See these benchmarks

Third, you can use GSON within a servlet, which is faster than Jackson (used by default in Spring and Jersey). This gets you even more performance especially considering that performance is critical to your requirements.

Finally, if you are concerned about boilerplate, put that code that you wrote inside the servlet in some utility class and use it from multiple servlets. That beats carrying around a framework's huge load when you (like most people) would probably be using a small fraction of its functionality.


You can use below code snippet:

String replaceAll = key.replaceAll("(.)(\\p{Upper})", "$1_$2").toLowerCase();




java rest spring-mvc servlets jax-rs