serialize a POJO to JSON in a REST module

Alied Perez
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 8, 2014

Hi

I'm developing a simple REST service. it receives a type, and returns a list of POJOs.

Simple, straightforward, almost a formality. Untill...

org.codehaus.jackson.map.JsonMappingException: No serializer found for class com
.sac.pc.jira.rest.dto.Project and no properties discovered to create BeanSeriali
zer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS
) )
        at org.codehaus.jackson.map.ser.impl.UnknownSerializer.failForEmpty(Unkn
ownSerializer.java:52)
        at org.codehaus.jackson.map.ser.impl.UnknownSerializer.serialize(Unknown
Serializer.java:25)
        at org.codehaus.jackson.map.ser.std.ObjectArraySerializer.serializeConte
nts(ObjectArraySerializer.java:123)
        at org.codehaus.jackson.map.ser.std.ObjectArraySerializer.serializeConte
nts(ObjectArraySerializer.java:29)
        at org.codehaus.jackson.map.ser.std.StdArraySerializers$ArraySerializerB
ase.serialize(StdArraySerializers.java:56)
        at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(St
dSerializerProvider.java:610)
        at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(Std
SerializerProvider.java:256)
        at org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:16
04)
        at org.codehaus.jackson.jaxrs.JacksonJsonProvider.writeTo(JacksonJsonPro
vider.java:558)
        at com.sun.jersey.spi.container.ContainerResponse.write(ContainerRespons
e.java:306)

(truncated)

This is the service:

@GET
  @Path("/builds/{type}")
  public Response getBuilds(final @PathParam("type") String type) {
    logger.debug("type: {}", type);
    final List<Project> result = builds.get(type);
    logger.debug("returning: {}", result);
    return (result != null) ?
        Response.ok(result).build() :
        Response.status(Response.Status.NOT_FOUND).build();
  }

and this is the POJO:

@JsonAutoDetect
public class Project implements Serializable{
  private static final long serialVersionUID = 1L;

  private final String key;
  private final String name;

  public Project(final String key, final String name) {
    this.key = key;
    this.name = name;
  }

  @JsonProperty
  public String getKey() {
    return key;
  }

  @JsonProperty
  public String getName() {
    return name;
  }

Can anybody tell me why is this class "empty"?

Thanks in advance

Alied

4 answers

1 accepted

2 votes
Answer accepted
Alied Perez
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 15, 2014

OK, just found out:

Silly as it can be, I was missing the OSGI import for org.codehaus.jackson.annotate*, so the fix is:

POM.xml:

<project (...)>
(...)
  <build>
    <plugins>
      <plugin>
        <groupId>com.atlassian.maven.plugins</groupId>
        <artifactId>maven-jira-plugin</artifactId>
        <version>${amps.version}</version>
        <configuration>
(...)
          <instructions>
            <Import-Package>
              org.codehaus.jackson.annotate*,
(...)
            </Import-Package>
          </instructions>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Thanks, Carolyn for your time, it was just me missing an import.

So, be warned all those who read this words, forget not what you can miss, for just like the small and insignificant mistletoe, killed Baldr, the smallest of the things can give you the greatest of grieves.

3 votes
Carolyn Van Slyck May 21, 2014

I think you are really close. I was able to reproduce the error with the following setup:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/foobar")
@Produces({MediaType.APPLICATION_JSON})
public class FoobarResource
{
    @GET
    public Response get()
    {
        Foobar foobar = new Foobar("key", "name");
        return Response.ok(foobar).build();
    }
}
public class Foobar {

    private final String key;
    private final String name;

    public Foobar(final String key, final String name) {
        this.key = key;
        this.name = name;
    }

    public String getKey() {
        return key;
    }

    public String getName() {
        return name;
    }
}

I was able to fix the error by either adding @JsonAutoDetect OR @JsonProperty. Using both won't hurt but isn't required. The Serializable interface is not necessary either. Below is a working example that I have tested:

import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonProperty;

@JsonAutoDetect
public class Foobar {

    private final String key;
    private final String name;

    public Foobar(final String key, final String name) {
        this.key = key;
        this.name = name;
    }

    @JsonProperty
    public String getKey() {
        return key;
    }

    @JsonProperty
    public String getName() {
        return name;
    }
}

Just a thought but I have falsely thought that my "fixes" did not work because the fastdev plugin didn't actually load my changes. When in doubt, run atlas-clean && atlas-debug, attach a debugger, place a breakpoint on some new code that you added (e.g. declare a variable in the get method and increment it) then make sure it is hit when you use the REST API Browser.

Good luck!

Alied Perez
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 21, 2014

Hmmm, weird... My POJO is annotated as your example (see my original question)

Thanks; anyway I'll double-check everything when I'm back to that code.

Alied Perez
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 15, 2014

So, I'm having some spare time and want to come back to this pending issue.

Just before start: is there a chance that annotations mught be (somehow) lost when compiled?

I know it sounds crazy, but... (etc.)

Louis Gamor May 1, 2020

@Carolyn Van Slyck Thanks a lot.  @JsonAutoDetect worked for me like a charm. Been searching the internet for a solution for awhile now until I patiently went through this thread.

This is what I did.

package com.voting.model;

import java.io.Serializable;

import com.fasterxml.jackson.annotation.JsonAutoDetect;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@JsonAutoDetect
@AllArgsConstructor
public class Data implements Serializable {

          private static final long serialVersionUID = 1L;


          String candidateId;
          Integer candidateVotes;
}

0 votes
Carolyn Van Slyck May 20, 2014

You need to decorate your rest resource with @Produces({MediaType.APPLICATION_JSON}).

Below is an example resource that only uses JSON. You could include other media types, such as xml, and Jersey would automatically use the appropriate media type based on the Accepts header sent by the client.

@Path("/foobar")
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public class FoobarResource
{
    @GET
    public Response get()
    {
        List<FoobarBean> foobars = getFoobars();
        return Response.ok(foobars).build();
    }
}

public class FoobarBean
{
    public Integer Id;
    public String Name;
}

Alied Perez
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 20, 2014

Thanks, Carolyn, but I did that (right, I did not include it in the post, my bad).

Will keep searching.

0 votes
Alied Perez
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 8, 2014

so far, I'm using this workaround:

return (result != null) ?
        Response.ok(gson.toJson(result)).build() :
        Response.status(Response.Status.NOT_FOUND).build();

It's dirty, but works.

Will fix it later when have more documentation.

Alied Perez
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 20, 2014

I'm leaving this as answer, since it works. However, if someone has a solution, please add it here and will have my vote.

Suggest an answer

Log in or Sign up to answer