We've got a JAX-RS application that runs on Apache TomEE. We slightly customize the default Jettison provider to better adhere to JSON conventions used by JavaScript frontend. TomEE allows to do it via its resources.xml file:
<resources>
<Service id="jettison" class-name="org.apache.cxf.jaxrs.provider.json.JSONProvider">
serializeAsArray = true
dropRootElement = false
arrayKeys = members,roles
supportUnwrapped = true
writeXsiType = false
</Service>
</resources>
Now we are migrating to GlassFish v4.1, and we notice that JSON output differs from what we had in TomEE - thus completely breaking frontend. I'm looking for similar mechanism to customize JSON marshaller in GlassFish. In fact, I'm already a little bit stuck with Jersey, MOXy, Jackson, Jettison. How do we know which JSON provider is actually used? How do we select one? How do we customize the behavior?
The application is pure JAX-RS and does not use any JSON processor directly, instead relying on marshalling of JAXB-annotated classes. Introduction of any non-JavaEE dependencies is highly undesirable, since the application is intended to be portable across containers (TomEE, GlassFish, some day WildFly). Config-file method, similar to TomEE, is preferable; programmatic way is acceptable, too - but only if portability is maintained.
Glassfish uses MOXy as the default provider. Internally it has the libraries to handle Jackson, Jettison, and MOXy, but the default is MOXy. There are two ways to disable MOXy
jersey.config.server.disableMoxyJson
to true
. XxxJsonFeature
that disables MOXy. For instance the JacksonFeature
that comes with jersey-media-json-jackson
Note that Glassfish comes with a Jackson provider, but it is Jackson 1.x. If you want to use 2.x, instead of the using the jersey-media-json-jackson
dependency listed above, it would be better to use the underlying Jackson provider dependency, which is
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.6.0</version>
</dependency>
You can register the JacksonJsonProvider
or the JacksonJaxbJsonProvider
for JAXB annotation support.
To configure Jackson, the easiest way to implement a ContextResolver
, as seen in this answer. The JacksonJsonProvider
will lookup this ContextResolver
to retrieve the ObjectMapper
used for (de)serialization.
You will also need to remember to disable MOXy, as mentioned above.
Also one thing to note is that this solution is portable. With JAX-RS, the only portable application configuration is through an Application
subclass
@ApplicationPath("/api")
public class MyApplication extends Application {}
That being said, the disabling of MOXy in the case of Glassfish, is nothing more than setting a property. In the Application
class, you can override getProperties()
which returns a Map<String, Object>
. This is where you can set the property. And because it s nothing more than a String (no outside dependencies), it remains portable
@ApplicationPath("/api")
public class MyApplication extends Application {
@Override
public Map<String, Object> getProperties() {
Map<String, Object> props = new HashMap<>();
props.put("jersey.config.server.disableMoxyJson", true);
return props;
}
}
As far as the above Jackson dependency, it is also a portable solution. It it nothing (JAX-RS) implementation specific. It implements and uses standard JAX-RS APIs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With