JAX-RS with embedded server

2019-01-16 20:30发布

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:

Grizzly:

Jersey:

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.

3条回答
乱世女痞
2楼-- · 2019-01-16 21:04

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.

查看更多
来,给爷笑一个
3楼-- · 2019-01-16 21:04

If using CXF for your JAX-WS implementation (or JAX-RS), you could just add @GZIP annotation onto the service class.

查看更多
The star\"
4楼-- · 2019-01-16 21:17

gzipping the output is the reponsibility of JAX WS implementation. You should refer to server's (Tomcat, Glassfish, JBoss, etc) documentation in order to configure your http network listeners.

查看更多
登录 后发表回答