bary
bary

Reputation: 1739

Java SOAP based WebService endpoint over HTTP2

Is it possible to write SOAP based WebService and client that comunicate over HTTP2 before java 9 release?

If yes, how I should approche this task?

Background.Recently I read and watched some cool stuff about HTTP2.

Article: HTTP/2: A jump-start for Java developers

Book chapter: High Performance Browser Networking

And videos:

unRESTful Web Services with HTTP2 by Fabian Stäber

Simone Bordet - HTTP 2.0 & Java: Current Status

In short HTTP/2 is more efficent, solves problems of HTTP/1.1 and is transparent to the web applications (simplifing its just different representation of message over the wire).

It looks like you can easly switch to HTTP2, when using RESTful Web Services. All you need to do on your server side is to deploy your application over Jetty (or other container that supports HTTP2).

And on client side use special Jetty HttpClient:

// Standard HTTP/1.1 client
new HttpClient();

// HTTP/2 transport client
new HttpClient(new HttpClientTransportOverHTTP2());

And you can comunicate over HTTP2.

On the other hand, SOAP based WebServices are quite diffent (they are based on JAX-WS API). You can define your Server side endpoint like this:

@WebService
public class HelloWorld {
    public String hello(String name) {
        return "Hello " + name;
    }
}

generate some code with java wsgen, and run it like this:

public class RunService {
   public static void main(String[] args) {
       Endpoint.publish("http://localhost:8080/wsServerExample", new HelloWorld());
   }
}

And for the client when you generate code from WSDL (with java wsimport), you can call this service like this:

public class WsClient {
    public static void main(String args[]) {
        HelloWorldService shs = new HelloWorldService();
        HelloWorld sh = shs.getHelloWorldPort();
        ((BindingProvider) sh).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://localhost:8080/wsServerExample");
        System.out.println(sh.hello("bary"));
    }
}

For server you can provide diffrent immplementation of HttpServer by changing property com.sun.net.httpserver.HttpServerProvider, for example:

System.setProperty("com.sun.net.httpserver.HttpServerProvider", "org.eclipse.jetty.http.spi.JettyHttpServerProvider");

but this won`t give you HTTP2 transport (am I right ?).

So it looks for me, that this HTTP transport for SOAP based WebServices is burried somewere deep inside java API and can`t be switched to HTTP2 before java 9 (or at least I dont know how this can be done)?

Am I missing something? If you have any ideas pleas share.

Thanks

Upvotes: 3

Views: 1996

Answers (1)

Erunafailaro
Erunafailaro

Reputation: 1959

To enable the server side to offer an http/2 endpoint, you need a server that supports http/2 (jetty or undertow support it as of April 2017).

Furthermore, the server must be configured to offer https, i.e. you must add a ssl/tls-certificate. So you create a java keystore containing your server-certificate.

Although https is not mandatory for http/2 to work, most clients require the connection to be encrypted. Additionally, when using servers like jetty or undertow, you must add support for alpn (Application-Layer Protocol Negotiation) by adding adding an alpn-jar.

If you use Spring Boot and Undertow as your server, you configure it like this:

@Bean
UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
    UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
    factory.addBuilderCustomizers(
            builder -> builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true));
    return factory;
}

This should be added to your application.properties:

server.port=8443
server.ssl.key-store=classpath:sample.jks
server.ssl.key-store-password=secret
server.ssl.key-password=password

When starting your server, you must add the ALPN-jar to your boot classpath:

-Xbootclasspath/p:/home/user_x/.m2/repository/org/mortbay/jetty/alpn/alpn-boot/8.1.8.v20160420/alpn-boot-8.1.8.v20160420.jar

Your http/2-client must trust the server's certificate. If you created a self-signed certificate for your server, you must add its public key to your client's jvm trust store:

$ keytool -import -trustcacerts -keystore /opt/java/jre/lib/security/cacerts \
-storepass changeit -noprompt -alias mycert -file /tmp/examplecert.crt

This answer was inspired by this blog post: https://vanwilgenburg.wordpress.com/2016/04/01/spring-boot-http2/

Upvotes: 0

Related Questions