Reputation: 457
I am trying to set up a RESTful API using Spring so that I can send an HTTP POST request and receive a response.
The post request that I'm testing with looks exactly like this:
POST http://localhost:8081/decide
Accept: application/json
Cache-Control: no-cache
Content-Type: application/json
{
"previousDecisions": [0, 1, 2]
}
When I send that request (I'm using IntelliJ's 'Test RESTful Web Services' feature) I am getting an error response.
What I want to happen is, there is a class called Decide
with a constructor that needs only an array of integers and its only member variable is an array of integers. I want to pass the above request to the DecideController
to create an instance of Decide
. Then Decide
has a method that returns a Node
object. I want to return a JSON version of that Node
instance.
From what I've seen with Spring it automatically converts a Java object to a JSON format when it returns.
Here is my entire Decide class:
package com.thesisapp.server.jugtours.model;
import java.io.Serializable;
public class Decide implements Serializable {
private int[] decisionList;
public Decide() {
this.decisionList = new int[0];
}
public Decide(int[] decisionList) {
this.decisionList = decisionList;
}
public Node getNode() {
//Use the game class to get a root node for the entire story tree
Node rootNode = (new Game()).getFullStoryTree();
//Traverse the story tree using the decisionList to get to the current node
Node currentNode = rootNode;
for (int whichChild : this.decisionList) {
currentNode = currentNode.getChild(whichChild);
}
return currentNode;
}
}
Side Note: I just added the implements Serializable
after doing some research and it did not have an affect on the error message I received. However adding that default constructor did have an affect on the error message.
And here is my entire DecideController class
package com.thesisapp.server.jugtours.web;
import com.thesisapp.server.jugtours.model.Node;
import com.thesisapp.server.jugtours.model.Decide;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@RestController
public class DecideController {
@PostMapping("/decide")
public Node decide(@RequestBody Decide decide) {
return decide.getNode();
}
}
Again here is the request I am sending in:
POST http://localhost:8081/decide
Accept: application/json
Cache-Control: no-cache
Content-Type: application/json
{
"previousDecisions": [0, 1, 2]
}
Here is what I want the response to look like, just JSON form of all the member variables from the Node
class:
{
"id": 0,
"text": "some text here",
"decisions": [],
"children": [],
"speaker": 0,
"checkpoint": true
}
Here are the two responses I have managed to get (before and after adding that default constructor to the Decide
class)
{
"timestamp": "2019-09-04T02:31:05.762+0000",
"status": 500,
"error": "Internal Server Error",
"message": "Type definition error: [simple type, class com.thesisapp.server.jugtours.model.Decide]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.thesisapp.server.jugtours.model.Decide` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)\n at [Source: (PushbackInputStream); line: 2, column: 3]",
"path": "/decide"
}
{
"timestamp": "2019-09-04T01:50:03.990+0000",
"status": 500,
"error": "Internal Server Error",
"message": "No message available",
"path": "/decide"
}
I don't really have any idea at what is going wrong here. Let me know if I didn't provide enough info/code. I have very little experience with this stuff but I appreciate any help, thank you!!
Upvotes: 1
Views: 405
Reputation: 1529
You need getters/setters for decisionList
on the Decide
class so Jackson can properly bind to it. In addition your JSON request body does not map to the Decide object you've defined. By passing in
{
"previousDecisions": [0, 1, 2]
}
Your Decide class should look like this:
public class Decide {
private int[] previousDecisions;
public int[] getPreviousDecisions(){
return previousDecisions;
}
public void setPreviousDecisions(int[] previousDecisions){
this.previousDecisions = previousDecisions;
}
}
So either change your field name in Decide
from decisionList
to previousDecisions
and add getters/setters, or pass decisionList
as the property in JSON and add getters/setters to the class:
{
"decisionList": [0, 1, 2]
}
Upvotes: 1