Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAX-RS with embedded server

Clarification: this question was about GZIPping an JAX-WS-based REST service, but I've decided to change the topic to make it easier to find

I'm implementing a REST service via JAX-WS Provider <Source>, and publishing it with standard Endpoint (the reason is that I want to avoid using a servlet container or application server).

Is there a way to make server to gzip response content, if Accept-Encoding: gzip is present?


HOW-TO

Samples provided by nicore actually works, and it allows you to make JAX-RS-styled server on top of embedded lightweight server without servlet container, but there are few moments to be considered.

If you prefer to manage classes by yourself (and save a time during startup), you may use the following:

Example

JAX-RS hello world class:

@Path("/helloworld")
public class RestServer {

    @GET
    @Produces("text/html")
    public String getMessage(){
        System.out.println("sayHello()");
        return "Hello, world!";
    }
}

Main method:

For Simple Server:

public static void main(String[] args) throws Exception{
    DefaultResourceConfig resourceConfig = new DefaultResourceConfig(RestServer.class);
    // The following line is to enable GZIP when client accepts it
    resourceConfig.getContainerResponseFilters().add(new GZIPContentEncodingFilter());
    Closeable server = SimpleServerFactory.create("http://0.0.0.0:5555", resourceConfig);
    try {
        System.out.println("Press any key to stop the service...");
        System.in.read();
    } finally {
        server.close();
    }
}

For Grizzly2:

public static void main(String[] args) throws Exception{
    DefaultResourceConfig resourceConfig = new DefaultResourceConfig(RestServer.class);
    // The following line is to enable GZIP when client accepts it
    resourceConfig.getContainerResponseFilters().add(new GZIPContentEncodingFilter());
    HttpServer server = GrizzlyServerFactory.createHttpServer("http://0.0.0.0:5555" , resourceConfig);
    try {
        System.out.println("Press any key to stop the service...");
        System.in.read();
    } finally {
        server.stop();
    }
}

Resolved dependencies:

Simple:

  • Simple Framework itself
  • jersey-simple-server

Grizzly:

  • grizzly-framework
  • grizzly-http
  • grizzly-http-server (different repository!)
  • jersey-grizzly2

Jersey:

  • jersey-archive

Notice

Make sure the javax.ws.rs archive didnt get into your classpath, as it conflicts with Jersey's implementation. The worst thing here is a silent 404 error with no logging - only a small note on FINER level is logged.

like image 584
Alex Abdugafarov Avatar asked Nov 26 '11 09:11

Alex Abdugafarov


People also ask

Does Tomcat support JAX-RS?

Since the basic Tomcat server does not support JAX-RS, a straightforward deployment of a JAX-RS based application will fail.

What is the difference between JAX-RS and Jersey?

JAX-RS is an specification (just a definition) and Jersey is a JAX-RS implementation. Jersey framework is more than the JAX-RS Reference Implementation. Jersey provides its own API that extend the JAX-RS toolkit with additional features and utilities to further simplify RESTful service and client development.

What are the implementations of JAX-RS?

JAX-RS is a standard defined in Java Specification Request 311 (JSR-311) and Jersey / RESTEasy are implementations of it.

What is jetty and jersey?

Jersey is an open source framework for developing RESTful Web Services in Java. It is a reference implementation of the Java API for RESTful Web Services (JAX-RS) specification. Jetty is a Java HTTP (Web) server and Java Servlet container.


1 Answers

If you really want to do REST with Java I would suggest you to to use a JAX-RS implementation (RESTeasy, Jersey...).

If your main concern is the dependency on a servlet container, you could use the JAX-RS RuntimeDelegate to register your application as a JAX-RS endpoint.

// Using grizzly as the underlaying server
SelectorThread st = RuntimeDelegate.createEndpoint(new MyApplication(), SelectorThread.class);

st.startEndpoint();

// Wait...
st.stopEndpoint();

Concerning GZIP encoding, each JAX-RS provider has different approaches. Jersey provides a filter to accomplish the encoding transparently. RESTEasy provides an annotation for that.

EDIT

I did some small tests. The following two things will definitely work for you, assuming you are using Maven.

Using Jersey + SimpleServer:

    public static void main( String[] args ) throws Exception {

    java.io.Closeable server = null;

    try {
        // Creates a server and listens on the address below.
        // Scans classpath for JAX-RS resources
        server = SimpleServerFactory.create("http://localhost:5555");
        System.out.println("Press any key to stop the service...");
        System.in.read();
    } finally {
        try {
            if (server != null) {
                server.close();
            }
        } finally {
            ;
        }
    }
}

with maven dependencies

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-core</artifactId>
    <version>1.10</version>
</dependency>
<dependency>
    <groupId>com.sun.jersey.contribs</groupId>
    <artifactId>jersey-simple-server</artifactId>
    <version>1.10</version>
</dependency>

Or using the Jersey + Grizzly2:

public static void main(String[] args) throws Exception {

    HttpServer server = null;

    try {
        server = GrizzlyServerFactory.createHttpServer("http://localhost:5555");
        System.out.println("Press any key to stop the service...");
        System.in.read();
    } finally {
        try {
            if (server != null) {
                server.stop();
            }
        } finally {
            ;
        }
    }
}

with maven dependencies

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-core</artifactId>
    <version>1.10</version>
</dependency>
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-grizzly2</artifactId>
    <version>1.10</version>
</dependency>

Honestly speaking I was not able to get the RuntimeDelegate sample working, too. There certainly is a way to start RESTEasy out of the box, too but I cannot recall it at the moment.

like image 157
nre Avatar answered Oct 01 '22 02:10

nre