Dropwizard/Jersey is giving "Unable to process JSON" message on GET request
Solution 1
Looks like your json marshaller is not able to marshall google's Optional class. Try to return Company from the controller, and not Optional:
@GET
@Path("/{id}")
@UnitOfWork
public Company getById(@PathParam("id") LongParam id) {
return companyDAO.findById(id.get()).get();
}
Solution 2
I was getting the error Unable to Process JSON. Troubleshooted more than 4 hours until I found the problem.
The error is caused because of Enum getter.
If you are using Enum fields/getters/setters in your POJO, Jackson will fail to map your JSON to Java Object, and it will crash, leading to the mentioned error.
Admin
Updated on June 28, 2022Comments
-
Admin almost 2 years
I'm trying to make my first simple project with Dropwizard. I have a MySQL-database, and the idea is to get the data (companies) from there and represent it as JSON. I have followed the Getting started page by Dropwizard and this tutorial to get connected to database with Hibernate.
The idea is that URL "/companies" serves all the companies as JSON, and it is working fine.
URL "/companies/{id}" is supposed to give a single company with given id, but every request gives code 400 and message "Unable to process JSON". The details field in the response says
"No serializer found for class jersey.repackaged.com.google.common.base.Present and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )"
If I give an id of company that does not exist in database, the class in mentioned message changes to
jersey.repackaged.com.google.common.base.Absent
The company class is here:
public class Company { @ApiModelProperty(required = true) @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; @Column(name = "name") private String name; @Column(name = "address") private String address; @Column(name = "zipcode") private String zipCode; @Column(name = "email") private String eMail; @Column(name = "mobile") private String mobile; public Company() { } public Company (String name, String address, String zipCode, String eMail, String mobile) { this.name = name; this.address = address; this.zipCode = zipCode; this.eMail = eMail; this.mobile = mobile; } @JsonProperty public long getId() { return id; } @JsonProperty public void setId(long id) { this.id = id; } @JsonProperty public String getName() { return name; } @JsonProperty public void setName(String name) { this.name = name; } @JsonProperty public String getAddress() { return address; } @JsonProperty public void setAddress(String address) { this.address = address; } @JsonProperty public String getZipCode() { return zipCode; } @JsonProperty public void setZipCode(String zipCode) { this.zipCode = zipCode; } @JsonProperty public String geteMail() { return eMail; } @JsonProperty public void seteMail(String eMail) { this.eMail = eMail; } @JsonProperty public String getMobile() { return mobile; } @JsonProperty public void setMobile(String mobile) { this.mobile = mobile; } }
DAO is here:
public class CompanyDAO extends AbstractDAO<Company> { public CompanyDAO(SessionFactory sessionFactory) { super(sessionFactory); } public List<Company> findAll() { return list(namedQuery("com.webapp.project.core.Company.findAll")); } public Optional<Company> findById(long id) { return Optional.fromNullable(get(id)); } }
Application class:
public class HelloWorldApplication extends Application<HelloWorldConfiguration> { public static void main(String[] args) throws Exception { new HelloWorldApplication().run(args); } @Override public String getName() { return "hello-world"; } /** * Hibernate bundle. */ private final HibernateBundle<HelloWorldConfiguration> hibernateBundle = new HibernateBundle<HelloWorldConfiguration>( Company.class ) { @Override public DataSourceFactory getDataSourceFactory( HelloWorldConfiguration configuration ) { return configuration.getDataSourceFactory(); } }; @Override public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) { bootstrap.addBundle(new SwaggerBundle<HelloWorldConfiguration>() { @Override protected SwaggerBundleConfiguration getSwaggerBundleConfiguration(HelloWorldConfiguration sampleConfiguration) { return sampleConfiguration.getSwaggerBundleConfiguration(); } }); bootstrap.addBundle(hibernateBundle); } @Override public void run(HelloWorldConfiguration configuration, Environment environment) { final CompanyDAO companyDAO = new CompanyDAO(hibernateBundle.getSessionFactory()); environment.jersey().register(new CompaniesResource(companyDAO)); environment.jersey().register(new JsonProcessingExceptionMapper(true)); } }
Configuration class:
public class HelloWorldConfiguration extends Configuration { @Valid @NotNull private DataSourceFactory database = new DataSourceFactory(); @NotNull private SwaggerBundleConfiguration swaggerBundleConfiguration; @JsonProperty("swagger") public void setSwaggerBundleConfiguration (SwaggerBundleConfiguration conf) { this.swaggerBundleConfiguration = conf; } @JsonProperty("swagger") public SwaggerBundleConfiguration getSwaggerBundleConfiguration () { return swaggerBundleConfiguration; } @JsonProperty("database") public void setDataSourceFactory(DataSourceFactory factory) { this.database = factory; } @JsonProperty("database") public DataSourceFactory getDataSourceFactory() { return database; } }
Resource class:
@Path("/companies") @Api("Companies") @Produces(MediaType.APPLICATION_JSON) public class CompaniesResource { private CompanyDAO companyDAO; public CompaniesResource(CompanyDAO companyDAO) { this.companyDAO = companyDAO; } @GET @ApiOperation( value = "Gives list of all companies", response = Company.class, code = HttpServletResponse.SC_OK ) @UnitOfWork public List<Company> findAll () { return companyDAO.findAll(); } @GET @Path("/{id}") @UnitOfWork public Optional<Company> getById(@PathParam("id") LongParam id) { return companyDAO.findById(id.get()); } }
I would be happy for any responses!
-
Admin about 8 yearsThanks for your reply and stopping me from beating my head to wall. I tried like you told and noticed that there was no get()-method for Optional class, which made me realize that I had wrong class imported. I had imported jersey.repackaged.com.google.common.base.Optional, and the correct one was com.google.common.base.Optional.
-
gmaslowski about 8 yearsGlad it somehow helped.
-
Admin over 2 yearsNot exactly true. You can use @JsonProperty (com.fasterxml.jackson.annotation) on your enums and pass a valid String representation to allow your POJO to have Enum values.