All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fasterxml.jackson.jaxrs.smile.JacksonSmileProvider Maven / Gradle / Ivy

Go to download

Functionality to handle Smile (binary JSON) input/output for JAX-RS implementations (like Jersey and RESTeasy) using standard Jackson data binding.

The newest version!
package com.fasterxml.jackson.jaxrs.smile;

import java.lang.annotation.Annotation;

import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.*;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.dataformat.smile.SmileFactory;
import com.fasterxml.jackson.jaxrs.base.ProviderBase;
import com.fasterxml.jackson.jaxrs.cfg.Annotations;

/**
 * Basic implementation of JAX-RS abstractions ({@link MessageBodyReader},
 * {@link MessageBodyWriter}) needed for binding
 * Smile ("application/x-jackson-smile") content to and from Java Objects ("POJO"s).
 *

* Actual data binding functionality is implemented by {@link ObjectMapper}: * mapper to use can be configured in multiple ways: *

    *
  • By explicitly passing mapper to use in constructor *
  • By explictly setting mapper to use by {@link #setMapper} *
  • By defining JAX-RS Provider that returns {@link ObjectMapper}s. *
  • By doing none of above, in which case a default mapper instance is * constructed (and configured if configuration methods are called) *
* The last method ("do nothing specific") is often good enough; explicit passing * of Mapper is simple and explicit; and Provider-based method may make sense * with Depedency Injection frameworks, or if Mapper has to be configured differently * for different media types. *

* Note that the default mapper instance will be automatically created if * one of explicit configuration methods (like {@link #configure}) * is called: if so, Provider-based introspection is NOT used, but the * resulting Mapper is used as configured. *

* Note that there is also a sub-class -- ({@link JacksonJaxbSmileProvider}) -- that * is configured by default to use both Jackson and JAXB annotations for configuration * (base class when used as-is defaults to using just Jackson annotations) * * @author Tatu Saloranta */ @Provider @Consumes(MediaType.WILDCARD) @Produces(MediaType.WILDCARD) public class JacksonSmileProvider extends ProviderBase { /** * Default annotation sets to use, if not explicitly defined during * construction: only Jackson annotations are used for the base * class. Sub-classes can use other settings. */ public final static Annotations[] BASIC_ANNOTATIONS = { Annotations.JACKSON }; /* /********************************************************** /* Context configuration /********************************************************** */ /** * Injectable context object used to locate configured * instance of {@link ObjectMapper} to use for actual * serialization. */ @Context protected Providers _providers; /* /********************************************************** /* Construction /********************************************************** */ /** * Default constructor, usually used when provider is automatically * configured to be used with JAX-RS implementation. */ public JacksonSmileProvider() { this(null, BASIC_ANNOTATIONS); } /** * @param annotationsToUse Annotation set(s) to use for configuring * data binding */ public JacksonSmileProvider(Annotations... annotationsToUse) { this(null, annotationsToUse); } public JacksonSmileProvider(ObjectMapper mapper) { this(mapper, BASIC_ANNOTATIONS); } /** * Constructor to use when a custom mapper (usually components * like serializer/deserializer factories that have been configured) * is to be used. * * @param annotationsToUse Sets of annotations (Jackson, JAXB) that provider should * support */ public JacksonSmileProvider(ObjectMapper mapper, Annotations[] annotationsToUse) { super(new SmileMapperConfigurator(mapper, annotationsToUse)); } /** * Method that will return version information stored in and read from jar * that contains this class. */ @Override public Version version() { return PackageVersion.VERSION; } /* /********************************************************** /* Abstract method impls /********************************************************** */ /** * Helper method used to check whether given media type * is Smile type or sub type. * Current implementation essentially checks to see whether * {@link MediaType#getSubtype} returns * "smile" or something ending with "+smile". */ @Override protected boolean hasMatchingMediaType(MediaType mediaType) { /* As suggested by Stephen D, there are 2 ways to check: either * being as inclusive as possible (if subtype is "smile"), or * exclusive (major type "application", minor type "smile"). * Let's start with inclusive one, hard to know which major * types we should cover aside from "application". */ if (mediaType != null) { // Ok: there are also "xxx+smile" subtypes, which count as well String subtype = mediaType.getSubtype(); return SmileMediaTypes.APPLICATION_JACKSON_SMILE_TYPE.getSubtype().equalsIgnoreCase(subtype) || "smile".equalsIgnoreCase(subtype) || subtype.endsWith("+smile"); } /* Not sure if this can happen; but it seems reasonable * that we can at least produce smile without media type? */ return true; } /** * Method called to locate {@link ObjectMapper} to use for serialization * and deserialization. If an instance has been explicitly defined by * {@link #setMapper} (or non-null instance passed in constructor), that * will be used. * If not, will try to locate it using standard JAX-RS * {@link ContextResolver} mechanism, if it has been properly configured * to access it (by JAX-RS runtime). * Finally, if no mapper is found, will return a default unconfigured * {@link ObjectMapper} instance (one constructed with default constructor * and not modified in any way) * * @param type Class of object being serialized or deserialized; * not checked at this point, since it is assumed that unprocessable * classes have been already weeded out, * but will be passed to {@link ContextResolver} as is. * @param mediaType Declared media type for the instance to process: * not used by this method, * but will be passed to {@link ContextResolver} as is. */ @Override protected ObjectMapper _locateMapperViaProvider(Class type, MediaType mediaType) { if (_providers != null) { ContextResolver resolver = _providers.getContextResolver(ObjectMapper.class, mediaType); /* Above should work as is, but due to this bug * [https://jersey.dev.java.net/issues/show_bug.cgi?id=288] * in Jersey, it doesn't. But this works until resolution of * the issue: */ if (resolver == null) { resolver = _providers.getContextResolver(ObjectMapper.class, null); } if (resolver != null) { ObjectMapper mapper = resolver.getContext(type); // 07-Feb-2014, tatu: just in case, ensure we have correct type if (mapper.getFactory() instanceof SmileFactory) { return mapper; } } } return null; } @Override protected SmileEndpointConfig _configForReading(ObjectReader reader, Annotation[] annotations) { return SmileEndpointConfig.forReading(reader, annotations); } @Override protected SmileEndpointConfig _configForWriting(ObjectWriter writer, Annotation[] annotations) { return SmileEndpointConfig.forWriting(writer, annotations); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy