简体   繁体   中英

Dropwizard example giving 400 error when creating new resource

I am new to the Dropwizard framework. I am trying to work on creating a new resource similar to person and people resource mentioned in the tutorial here https://github.com/dropwizard/dropwizard/tree/master/dropwizard-example .

I am creating a document class like this -

@Entity
@Table(name = "document")
@NamedQueries({
        @NamedQuery(
                name = "com.example.helloworld.core.Document.findAll",
                query = "SELECT d FROM Document d"
        ),
        @NamedQuery(
                name = "com.example.helloworld.core.Document.findById",
                query = "SELECT d FROM Document d WHERE d.Id = :Id"
        )
})
public class Document {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long Id;

    @Column(name = "ProcessingSetID")
    private String ProcessingSetID;

    @Column(name = "processed")
    private String processed;

    public long getId() {
        return Id;
    }

    public void setId(long id) {
        this.Id = id;
    }

    public String getProcessingSetID() {
        return ProcessingSetID;
    }

    public void setProcessingSetID(String processingSetID) {
        ProcessingSetID = processingSetID;
    }

    public String getProcessed() {
        return processed;
    }

    public void setProcessed(String processed) {
        this.processed = processed;
    }
}

My document Dao is like this,

public Optional<Document> findById(Long id) {
    return Optional.fromNullable(get(id));
}

public Document create(Document document) {
    return persist(document);
}

public List<Document> findAll() {
    return list(namedQuery("com.example.helloworld.core.Document.findAll"));
}
}

I am trying to call the POST method on my document resource,

@Path("/documents")
@Produces(MediaType.APPLICATION_JSON)

public class DocumentsResource {

    private final DocumentDao documentDAO;
    private static final Logger log = LoggerFactory.getLogger(DocumentsResource.class);

    public DocumentsResource(DocumentDao documentDAO) {
        this.documentDAO = documentDAO;
    }

    @POST
    @UnitOfWork
    public Document createDocument(Document document) {
        log.info("inside POST method of document.");
        System.out.println("inside POST method of document.....");
        return documentDAO.create(document);
    }

    @GET
    @UnitOfWork
    public List<Document> listDocuments() {
        return documentDAO.findAll();
    }
}

But I am getting a 400 response back from my client request, please find below the client request

Client client = Client.create();

WebResource webResource = client.resource("http://localhost:8080/documents");

String input = "{\"processed\":\"new process\",\"ProcessingSetID\":\"new iD\"}";

ClientResponse response = 
        webResource.type("application/json").post(ClientResponse.class, input);

if (response.getStatus() != 200) {
    throw new RuntimeException("Failed : HTTP error code : "
            + response.getStatus());
}

I tried to debug the problem, but the call is not reaching the POST method at the first place. It seems that it is not creating the document object from the JSON string, but i could not see a reason for that. Also when I do an entry directly in my database and make a GET call, perfect JSON string equivalent to object is received.

To get helpful message regarding 400 error, register this on jersey:

environment.jersey().register(new JsonProcessingExceptionMapper(true));

It will give more detailed message on 400 response, useful for debugging.

A little background: Dropwizard utilizes Jersey , and Jersey is what ultimately gives you back the 400 Bad Request response, probably along with a vague and laconic message.

In order to see exactly what did bother Jackson (which in turn bothered Jersey), I started out by sending a blank (empty) JSON object and see whether it was accepted (it did - and all the fields in the POJO where zero-initialized). Then I started to add fields, sending each such object along, until I reached the problematic field (in my case it was a boolean field which should have been a Boolean ).

I think I can spot two difficulties in your POJO (the Document class):

  1. The getters/setters should be annotated with @JsonProperty .

  2. Try to change Id 's type to Long (nullable long). If you are concerned about getting a null in that field, you can have the getter return a zero or any default value instead.

I faced the same issue. The errors are suppressed and not passed properly in the stack trace. What I did was to add a try catch around the function. Then added a debugger point in the exception. I was able to figure out the exact reason.

You could try something like this.

@POST
@UnitOfWork
public Document createDocument(Document document) throws Exception{
....
}

Add debugger points in the Exception class. You will find out the exact reason of the parsing failure.

Hope I am clear and it helps!

Http status 400 means "bad request". Which it is, the json you are sending is not a valid Document . This in turn means you will never reach the body of

@POST
@UnitOfWork
public Document createDocument(Document document){}

To solve it, try passing the json:

String input = "{\"id\":\"123456789\",\"processed\":\"new process\",\"ProcessingSetID\":\"new iD\"}";

Replace 123456789 with your actual id.

PS. it might be a good idea (depending on your scenario) to create a DTO for Document instead of passing the actual entity around.

If you are registering the Jersey's CsrfProtectionFilter in your Dropwizard *Application.java within the run(...) method, make sure you're adding the X-Requested-By header to all of your state changing HTTP calls ( POST , PUT , etc). The server will return an HTTP 400 Bad Request if that header is not found in the request.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM