adam bien's blog

JAX-RS: A JSON-B Configuration per @ApplicationPath 📎

The serialization / deserialization behaviour of the JsonbBuilder from the Jakarta EE JSON-B API can be configured with various strategies residing in the javax.json.bind.config package.

In JAX-RS you can statically configure JSON-B with ContextResolver for all JAX-RS resources:


import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;    
@Provider
public class JSONConfigurator implements ContextResolver {

    @Override
    public Jsonb getContext(Class type) {
        JsonbConfig config = new JsonbConfig().
                withPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
        return JsonbBuilder.newBuilder().
                withConfig(config).
                build();
    }
}

Also, a ContextResolver instance can be also registered programmaticaly per javax.ws.rs.core.Application implementation:


@ApplicationPath("secondapi")
public class SecondJAXRConfiguration extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new HashSet<>();
        resources.add(SecondPing.class);
        return resources;
    }

    @Override
    public Set<Object> getSingletons() {
        Set<Object> singletons = new HashSet<>();
        ContextResolver resolver = getJSONBConfiguration();
        singletons.add(resolver);
        return singletons;
    }

    ContextResolver getJSONBConfiguration() {
        return new ContextResolver<Jsonb>() {
            @Override
            public Jsonb getContext(Class type) {
                JsonbConfig config = new JsonbConfig().
                        withPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
                return JsonbBuilder.newBuilder().
                        withConfig(config).
                        build();
            }
        };
    }

Another JAX-RS application inside the same ThinWAR could expose the resources with different JSON-B configuration, or just rely on the defaults:


@ApplicationPath("firstapi")
public class FirstJAXRSConfiguration extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new HashSet<>();
        resources.add(FirstPing.class);
        return resources;
    }
}

Now the FirstPing resource:


@Path("ping")
public class FirstPing {
    @GET
    public Ping ping() {
        return new Ping("first", 1);
    }
}    

...exposes the Ping entity:


public class Ping {

    public String name;
    public long duration;

    public Ping(String name, long duration) {
        this.name = name;
        this.duration = duration;
    }
}

...using the default JSON-B configuration as: {"duration":1,"name":"first"} (with: curl http://localhost:8080/jaxrs-multiple-uris/firstapi/ping)

The SecondPing:


@Path("ping")
public class SecondPing {
    @GET
    public Ping ping() {
        return new Ping("second", 2);
    }
}

...generates the following output: {"Duration":2,"Name":"second"} (with: curl http://localhost:8080/jaxrs-multiple-uris/secondapi/ping)

The sample was created with javaee8-essentials-archetype, the 7kB ThinWAR was built and deployed with: wad.sh in 2.5s to Payara 5.193.

See you at Web, MicroProfile and Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.