Ninja framework endpoint throws 500 error when trying to map JSON to custom object
I successfully reproduced your issue, and then fixed it.
First, for easy way to try/test, I recommend (temporary) modifications:
package controllers;import models.RecurOrderJSON;import ninja.Context;import ninja.Result;public class RecurringController { public Result processRecurring(Context context, RecurOrderJSON recurOrderJSON) { log.info("recurOrderJSON => " + recurOrderJSON); return ninja.Results.ok(); }}
And then, update your model this way:
package models;import java.util.Map;import com.fasterxml.jackson.annotation.JsonIgnoreProperties;@JsonIgnoreProperties(ignoreUnknown = true)public class RecurOrderJSON { public String id; public String event_type; public String request_id; public Map data; @Override public String toString() { return "RecurOrderJSON [id=" + id + ", event_type=" + event_type + ", request_id=" + request_id + ", data=" + data.toString() + "]"; }}
You can notice:
- The data type must stay raw (generic can't be used here)
- the important @JsonIgnoreProperties(ignoreUnknown = true) annotation to avoid deserialize issue, if ever your source data does not perfectly match your model (be sure to use the recent version of annotation, in fasterxml sub-package, instead of the old one, in codehaus sub-package)
- the toString() implementation only allowing quick check of OK/KO deserialization
Then you can easily test the system with wget, or curl:
curl -H 'Content-Type: application/json' -d "@/tmp/jsonINput.json" -X POST http://localhost:8080/recurring
Notice it is very important to specify the Content-type for good interpretation.
With the /tmp/jsonINput.json file containing exactly the json contents you specified in your question.
This way, everything is working like a charm, obtaining this output:
recurOrderJSON => RecurOrderJSON [id=hook-XXXXX, event_type=tx-pending, request_id=attempt-XXXXXXX, data={button_id=static, publisher_organization=org-XXXXXXX, campaign_id=camp-097714a40aaf8965, currency=USD, order_currency=USD, id=tx-XXXXXXX, category=new-user-order, modified_date=2018-10-15T05:41:12.577Z, order_total=9680, button_order_id=btnorder-77c9e56fd990f127, publisher_customer_id=XymEz8GO2M, rate_card_id=ratecard-41480b2a6b1196a7, advertising_id=null, event_date=2018-10-15T05:41:06Z, status=pending, pub_ref=null, account_id=acc-4b17f5a014d0de1a, btn_ref=srctok-0adf9e958510b3f1, order_id=null, posting_rule_id=null, order_line_items=[{identifier=Antique Trading Card, description=Includes Lifetime Warranty, amount=9680, publisher_commission=968, attributes={}, total=9680, quantity=1}], order_click_channel=webview, order_purchase_date=null, validated_date=null, amount=968, customer_order_id=null, created_date=2018-10-15T05:41:12.577Z, commerce_organization=org-XXXXXX}]
Given the specific input code with data
field commented out
//public Map data;
and the posted input JSON that includes this field, the request should fail with 400 Bad Request
.
The reason being that Ninja uses Jackson for JSON parsing and it will throw on unknown fields by default.
The quick workaround is to add @JsonIgnoreProperties
annotation to RecurOrderJSON
class.
e.g.
@JsonIgnoreProperties(ignoreUnknown = true)public class RecurOrderJSON { ...}
See: Ignoring new fields on JSON objects using Jackson
Now if the error was not 400 there isn't much information to go by as there doesn't seem to be anything else obviously wrong with the code.
Either post an SSCCE demonstrating the problem or attempt to debug by surfacing the error page with the following method:
- Launch the application in debug mode with
mvn package ninja:run
- Access the end-point with a tool that allows to inspect the response in detail such as curl e.g.
- Store request JSON in
input.json
- Run
curl -v -o result.html -H 'Content-Type: application/json' --data '@input.json' http://localhost:8080/recurring
- Open
result.html
to examine the response
- Store request JSON in
Might it be that you are performing a bad request (hence the JSON is not found) but for some Ninja bug it returns error 500?
For example you can take a look here where is stated that parsing an empty JSON in a JSON request does leads to a misguiding error (500) while it is supposed to return 400 "Bad Request"