Dropwizard/Jersey is giving "Unable to process JSON" message on GET request
Asked Answered
C

2

6

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!

Conversable answered 21/4, 2016 at 14:52 Comment(0)
I
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();
}
Integument answered 21/4, 2016 at 15:7 Comment(2)
Thanks 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.Conversable
Glad it somehow helped.Integument
H
4

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.

Hashimoto answered 28/1, 2020 at 18:32 Comment(1)
Not 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.Nerve
I
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();
}
Integument answered 21/4, 2016 at 15:7 Comment(2)
Thanks 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.Conversable
Glad it somehow helped.Integument

© 2022 - 2024 — McMap. All rights reserved.