Search code examples
javajakarta-eejax-rsapache-tomee

Resolve array serialization in JAX RS without Spring


I need to create a simple REST interface to a database for a data migration. What I did was generate entity-classes and beans from the database with Netbeans and write some simple REST Services. Then I ran into the serialization problem with Jettison, where lists with only one element are not serialized as lists.

I have found solutions for this problem that all seem to require Spring to redefine the serialization-provider or reconfigure Jettison's "serializeAsArray" and "arrayKeys".

Is there a way to either use Jackson or configure Jettison without the need for the Spring framework?

Here is the REST service definition:

@Path("/reseller")
@Produces({"application/json;charset=utf-8"})
public class ResellerWS {

@EJB
private ResellerFacade reseller;

@Path("/{id}")
@GET
public Reseller get(@PathParam("id") long id)
{
    ResellerReseller result = reseller.find(id);
    return result;
}

This is part of the entity that matters. resellerdepartmentList is not serialized as a list with one entry, but only as the entry itself:

@OneToMany(mappedBy = "resellerId", fetch = FetchType.EAGER)
private List<Resellerdepartment> resellerdepartmentList;

...

public List<Resellerdepartment> getResellerdepartmentList() {
    return resellerdepartmentList;
}

The service is running under a TomEE Plus 1.7.4


Solution

  • Is there a way to either use Jackson or configure Jettison without the need for the Spring framework?

    I strongly advise you to use Jackson instead of Jettison and it doesn't need Spring to be configured.


    To use Jackson as JSON provider for JAX-RS, add the jackson-jaxrs-json-provider artifact in your project dependencies:

    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>2.9.5</version>
    </dependency>
    

    This module contains the JacksonJsonProvider class, which is the basic implementation of JAX-RS abstractions (MessageBodyReader and MessageBodyWriter) needed for binding JSON content to and from Java objects.

    To configure ObjectMapper in JAX-RS, you can create a ContextResolver implementation. It will be picked up by the JacksonJsonProvider:

    @Provider
    public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
    
        private final ObjectMapper mapper;
    
        public ObjectMapperContextResolver() {
            this.mapper = createObjectMapper();
        }
    
        @Override
        public ObjectMapper getContext(Class<?> type) {
            return mapper;
        }
    
        private ObjectMapper createObjectMapper() {
            ObjectMapper mapper = new ObjectMapper();
            // Configure as per your needs
            return mapper;
        }
    }
    

    The @Provider annotation marks an implementation of an extension interface that should be discoverable by the JAX-RS runtime. Alternatively, you can register the providers in your class that extends Application.