Implement secure HTTP server using Grizzly and Jersey

Statement : The purpose of this post is to implement secure HTTP server using Grizzly and Jersey.

Solution :

  • First you just need to create the keystore and truststore files using the below commands and this will ask you certain details about your organization and all –

keytool -genkey -keyalg RSA -keystore ./keystore_client -alias clientKey
keytool -export -alias clientKey -rfc -keystore ./keystore_client > ./client.cert
keytool -import -alias clientCert -file ./client.cert -keystore ./truststore_server

keytool -genkey -keyalg RSA -keystore ./keystore_server -alias serverKey
keytool -export -alias serverKey -rfc -keystore ./keystore_server > ./server.cert
keytool -import -alias serverCert -file ./server.cert -keystore ./truststore_client

  • Add the SSLContextConfiguration Object (containing the details about the keystore and truststore files) in the constructor of GrizzlyHttpServerFactory as per the given below code –

    private static final String KEYSTORE_LOC = “keystore_server”;

    private static final String KEYSTORE_PASS = “123456”;

    private static final String TRUSTSTORE_LOC = “truststore_server”;

    private static final String TRUSTSTORE_PASS = “123456”;

    SSLContextConfigurator sslCon = new SSLContextConfigurator();

        sslCon.setKeyStoreFile(KEYSTORE_LOC);

        sslCon.setKeyStorePass(KEYSTORE_PASS);

        sslCon.setTrustStoreFile(TRUSTSTORE_LOC);

        sslCon.setTrustStorePass(TRUSTSTORE_PASS);

URI BASE_URI = URI.create(http://0.0.0.0:” + config.getPort());

        String resources = “com.secure.server.main”;

        BeanConfig beanConfig = new BeanConfig();

        beanConfig.setVersion(“1.0.1”);

        beanConfig.setSchemes(new String[] { “https” });

        beanConfig.setBasePath(“”);

        beanConfig.setResourcePackage(resources);

        beanConfig.setScan(true);

        final ResourceConfig rc = new ResourceConfig();

        rc.packages(resources);

        rc.register(io.swagger.jaxrs.listing.ApiListingResource.class);

        rc.register(io.swagger.jaxrs.listing.SwaggerSerializers.class);

        rc.register(JacksonFeature.class);

        rc.register(JacksonJsonProvider.class);

        rc.register(new CrossDomainFilter());

    return GrizzlyHttpServerFactory.createHttpServer(BASE_URI, rc, true,

new SSLEngineConfigurator(sslCon).setClientMode(false).setNeedClientAuth(false);

  • Job is done. Now you just need to integrate all the code together. You can refer my github link to get the full code of the implementation. Happy coding 🙂
Advertisements

How to avoid getting extra double quotes and slashes in your API JSON response

Statement – While working with REST apis, most of the time we would be expecting the clean JSON response from the API. But few time we get the unstructured JSON response like below in case of children array –

{
“_page”: {
“start”: 0,
“next”: 12,
“count”: 2
}
“children”: [
“{\”_attachments\”:\”attachments/\”,\”_rid\”:\”wEIcANyrmAULAAAAAAAAAA==\”,\”id\”:\”11\”,\”_self\”:\”dbs/wEIcAA==/colls/wEIcANyrmAU=/docs/wEIcANyrmAULAAAAAAAAAA==/\”,\”value\”:\”Vanessa\”,\”key\”:\”38\”,\”_etag\”:\”\\”0c0054c7-0000-0000-0000-59ca35ab0000\\”\”,\”_ts\”:1506424239}”,
“{\”_attachments\”:\”attachments/\”,\”_rid\”:\”wEIcANyrmAUMAAAAAAAAAA==\”,\”id\”:\”12\”,\”_self\”:\”dbs/wEIcAA==/colls/wEIcANyrmAU=/docs/wEIcANyrmAUMAAAAAAAAAA==/\”,\”value\”:\”Neal\”,\”key\”:\”13\”,\”_etag\”:\”\\”0c0056c7-0000-0000-0000-59ca35ab0000\\”\”,\”_ts\”:1506424239}”
]
}

So to avoid this, we just need to take care of few things in our implementation –

  1. In the Root class object, use JSONArray object instead of List of String or Object like below –

public class PageResponse {

@JsonProperty(“_page”)

private Pagination page;

@JsonProperty(“records”)

private JSONArray records = null;

}

  1. Wherever you are setting this JSONArray, try to set it by the following piece of code –

List<Object> finalRes = new ArrayList<Object>();

JSONParser parser = new JSONParser();

JSONArray finalJsonArray = (JSONArray) parser.parse(finalRes.toString());

PageResponse pageResponse = new PageResponse();

pageResponse.setRecords(finalJsonArray);

In this way, you would be getting the clean JSON response from your REST API given below –

{
  "_page": {
    "start": 0,
    "next": 13,
    "count": 3
  },
  "records": [
    {
      "_attachments": "attachments/",
      "_rid": "wEIcANyrmAULAAAAAAAAAA==",
      "id": "11",
      "_self": "dbs/wEIcAA==/colls/wEIcANyrmAU=/docs/wEIcANyrmAULAAAAAAAAAA==/",
      "value": "Vanessa",
      "key": "38",
      "_etag": "\"0c0054c7-0000-0000-0000-59ca35ab0000\"",
      "_ts": 1506424239
    },
    {
      "_attachments": "attachments/",
      "_rid": "wEIcANyrmAUMAAAAAAAAAA==",
      "id": "12",
      "_self": "dbs/wEIcAA==/colls/wEIcANyrmAU=/docs/wEIcANyrmAUMAAAAAAAAAA==/",
      "value": "Neal",
      "key": "13",
      "_etag": "\"0c0056c7-0000-0000-0000-59ca35ab0000\"",
      "_ts": 1506424239
    },
    {
      "_attachments": "attachments/",
      "_rid": "wEIcANyrmAUNAAAAAAAAAA==",
      "id": "13",
      "_self": "dbs/wEIcAA==/colls/wEIcANyrmAU=/docs/wEIcANyrmAUNAAAAAAAAAA==/",
      "value": "Marguerite",
      "key": "13",
      "_etag": "\"0c0058c7-0000-0000-0000-59ca35ab0000\"",
      "_ts": 1506424239
    }
  ]
}

Hope it helps. 🙂

Dependecny Injection using Grizzly and Jersey

Statement: Implementation of Dependency Injection using Grizzly and Jersey

Please follow the below steps to do the same –

  • Create a class called Hk2Feature which implements Feature.

package com.sample.di;

import javax.ws.rs.core.Feature;

import javax.ws.rs.core.FeatureContext;

import javax.ws.rs.ext.Provider;

@Provider

public class Hk2Feature implements Feature {

  public boolean configure(FeatureContext context) {

    context.register(new MyAppBinder());

    return true;

  }

}

  • Create a class called MyAppBinder which extends AbstractBinder and you need to register all the services here like below –

package com.sample.di;

import org.glassfish.hk2.utilities.binding.AbstractBinder;

public class MyAppBinder extends AbstractBinder {

  @Override

  protected void configure() {

    bind(MainService.class).to(MainService.class);

  }

}

  • Now, it’s time to write your own services and inject all the required services in your appropriate controllers like below code –

package com.sample.di;

public class MainService {

  public String testService(String name) {

    return “Hi” + name + “..Testing Dependency Injection using Grizlly Jersey “;

  }

}

package com.sample.di;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

@Path(“/main”)
public class MainController {

@Inject
public MainService mainService;

@GET
public String get(@QueryParam(“name”) String name) {
return mainService.testService(name);
}

@GET
@Path(“/test”)
@Produces(MediaType.APPLICATION_JSON)
public String ping() {
return “OK”;
}
}

Now hit the url http://localhost:8080/main?name=Tanuj and you will get your result. This is how you can achieve dependency injection in Grizzly Jersey application. Find the detailed implementation of the above skeleton in my repo. Happy Coding 🙂

Generate Swagger UI through Grizzly and Jersey Application.

Statement : Generate Swagger UI for the listing of all the REST APIs through Grizzly and Jersey Application.

  • Add following dependency in pom.xml –

<dependency>

<groupId>io.swagger</groupId>

<artifactId>swagger-jersey2-jaxrs</artifactId>

<version>1.5.9</version>

</dependency>

  • Bundle Swagger UI and docs folder through you main application class using the below code –

package com.main;

import java.io.IOException;

import java.net.URI;

import org.glassfish.grizzly.http.server.CLStaticHttpHandler;

import org.glassfish.grizzly.http.server.HttpServer;

import org.glassfish.grizzly.http.server.ServerConfiguration;

import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;

import org.glassfish.jersey.jackson.JacksonFeature;

import org.glassfish.jersey.server.ResourceConfig;

import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;

import io.swagger.jaxrs.config.BeanConfig;

public class MainApp {

// Base URI the Grizzly HTTP server will listen on

public static final URI BASE_URI = URI.create(http://0.0.0.0:8080&#8221;);

public static HttpServer getLookupServer() {

String resources = “com.main”;

BeanConfig beanConfig = new BeanConfig();

beanConfig.setVersion(“1.0.1”);

beanConfig.setSchemes(new String[] { “http” });

beanConfig.setBasePath(“”);

beanConfig.setResourcePackage(resources);

beanConfig.setScan(true);

final ResourceConfig resourceConfig = new ResourceConfig();

resourceConfig.packages(resources);

resourceConfig.register(io.swagger.jaxrs.listing.ApiListingResource.class);

resourceConfig.register(io.swagger.jaxrs.listing.SwaggerSerializers.class);

resourceConfig.register(JacksonFeature.class);

resourceConfig.register(JacksonJsonProvider.class);

return GrizzlyHttpServerFactory.createHttpServer(BASE_URI, resourceConfig);

}

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

final HttpServer server = getLookupServer();

server.start();

ClassLoader loader = MainApp.class.getClassLoader();

CLStaticHttpHandler docsHandler = new CLStaticHttpHandler(loader, “swagger-ui/”);

docsHandler.setFileCacheEnabled(false);

ServerConfiguration cfg = server.getServerConfiguration();

cfg.addHttpHandler(docsHandler, “/docs/”);

}

}

  • Take the latest code of swagger-ui. Copy all the content of the dist folder and create a folder named  swagger-ui inside src/main/resources and paste all the copied contents. Now change the url in index.file which is inside the copied folder like below –

    url: http://0.0.0.0:8080/swagger.json

  • Lastly, annotate your controller with @Api and @ApiOperation.

Hope it works. Now to run your Grizzly Jersey Application, go to browser and type localhost:8080/docs/. You will see Swagger UI having all the details of your REST APIs.

Happy coding and sharing as well. 🙂 You can find the git repo for the above implementation.