I've got a simple Restful webService using Spring Boot 2.1, Java 8, running on Eclipse Neon. Im sending the following request:
<patentListWrapper>
<patentList>
<patent>
<guid>bbb</guid>
</patent>
<patent>
<guid>ccc</guid>
</patent>
</patentList>
</patentListWrapper>
and im getting back the following (incorrect) response:
<patentListWrapper>
<patentList>
<patentList>
<guid>ddd</guid>
</patentList>
<patentList>
<guid>eee</guid>
</patentList>
</patentList>
</patentListWrapper>
ie i've got 2 patentList elements in the response ,instead of an inner patent element, and I don't know why. My 2 POJO classes to map the request are:
public class PatentListWrapper {
private List<Patent> patents;
public List<Patent> getPatentList() {
return patents;
}
public void setPatentList(List<Patent> patents) {
this.patents = patents;
}
}
and:
public class Patent {
private String guid;
public String getGuid() {
return guid;
}
public void setGuid(String guid) {
this.guid = guid;
}
public Patent() {
super();
}
}
my REST Controller class is:
#RestController
public class PndController {
#Autowired
ReadFromDb db;
#RequestMapping(value = "/guidRequest/xmlList", method = RequestMethod.POST, produces = { "application/xml", "text/xml" }, consumes = MediaType.ALL_VALUE )
public PatentListWrapper guidSearchList(#RequestBody PatentListWrapper patentListWrapper) {
System.out.println("DS in guidSearchList()");
patentListWrapper = db.readGuidsFromDb(patentListWrapper); // Set the guid in the patents List in patentListWrapper
return patentListWrapper;
}
}
and ReadFromDb class:
#Repository
public class ReadFromDb {
public PatentListWrapper readGuidsFromDb(PatentListWrapper patentListWrapper) {
List<Patent> patents= patentListWrapper.getPatentList();
for(Patent patent : patents) {
patent.setGuid("aaa");
}
patentListWrapper.setPatentList(patents);
return patentListWrapper;
}
}
I'm sending my resuest using the windows ARC Advanced Rest Client:
Rest client with Content-type=application/xml
I've established that both patentList element names map to getPatentList() in PatentListWrapper. How do I get the response envelope to match the request envelop? Any help appreciated.
it is true , just create the getter setter method with the same variable name like below instead of using different names for getter setter methods
private List<Patent> patents;
public List<Patent> getPatents() {
return patents;
}
public void setPatents(List<Patent> patents) {
this.patents = patents;
}
or use the GSON and use #JsonProperty and define the required value name , further if you are not using the IDE to generate getters and setters you better use lombok plugin .
Related
I have a Service type script class as follows:
export class HomeApiService{
apiURL = 'http://localhost:8080/api';
constructor(private http: HttpClient) {}
getProfileData():Observable<HomeModelInterface[]>{
return this.http.get<HomeModelInterface[]>(this.apiURL+'/home');}
}
I have component class as follows:
export class HomeComponent implements OnInit {
public profileData: HomeModelInterface[] | undefined ;
constructor(private homeApiService:HomeApiService) { }
ngOnInit() {
this.homeApiService.getProfileData().subscribe(data=> {
this.profileData = data;
console.log(this.profileData);
});
}
I have html file as follows:
<div *ngFor="let profile of profileData">
<h1>{{profile.data}}</h1>
</div>
Here is the backend spring boot application controller:
#RequestMapping(value = "/api/home" , method = RequestMethod.GET, produces =
"application/json")
public Object getHome() {
ResponseHome response = new ResponseHome();
response.setData(new String[]{"Greetings from Spring Boot API home!",
HttpStatus.ACCEPTED.toString()});
return response;
}
Here is my ResponseHome java class:
public class ResponseHome {
private String data[];
private String errors[];
public String[] getData() {
return data;
}
public void setData(String[] data) {
this.data = data;
}
public String[] getErrors() {
return errors;
}
public void setErrors(String[] errors) {
this.errors = errors;
}
}
Here is my frontend model typescript class to parse that json to a model class:
export interface HomeModelInterface{
data: string[];
errors: string[];
}
When i run it chrome i see the following error:
Cannot find a differ supporting object '[object Object]' of type 'object'
Can you please help?
Your data is an object not an array. In order to iterate, you should get the list that's in it. Try something like profileData.data in *ngFor.
I have an object, and of its attributes is a List. I want to send this object from Postman to my service. I'm using Spring 5.2.7 (Spring MVC, not SpringBoot) and Hibernate 5.4.17 and Java 8. My problem is very similar to this one: I want to send a Postman POST request with an Array: members: ["william", "eric", "ryan"]
This is the class I'm trying to pass in Postman (POST method):
public class ChatDescriptionDto {
private String chatID;
private List<String> members;
private String chatType;
public String getChatID() {
return chatID;
}
public void setChatID(String chatID) {
this.chatID = chatID;
}
public List<String> getMembers() {
return members;
}
public void setMembers(List<String> members) {
this.members = members;
}
public void addMembers(List<String> members)
{
if(this.members == null)
this.members = new ArrayList<>();
this.members.addAll(members);
}
public void addMember(String member)
{
if(this.members == null)
this.members = new ArrayList<>();
this.members.add(member);
}
public String getChatType() {
return chatType;
}
public void setChatType(String chatType) {
this.chatType = chatType;
}
}
I've tried this and it didn't work:
{
"chatID": "123",
"members": ["P2001222833","P2001640916"],
"chatType": "personal"
}
Edit: This is my controller:
#PostMapping("/initiateChat")
public String initiateChat(#RequestBody ChatDescriptionDto chat)
{
return chatServiceLocal.initiateChat(chat)?"Chat Description created":"Failure! Could not save.";
}
Edit 2: The method which I've written in the question, "members": ["P2001222833","P2001640916"], is the correct one. Turns out, there was some error in the server so it never started and I didn't check that.
Having no information about the Controller class you're using, the first thing I'd assume is that you're receiving an empty object, which means that Spring simply skipped the serialization. This is the case when you don't specify the parameter of the method as #RequestBody. First, make sure that you do have the annotation.
#RestController
#RequestMapping("/")
public class TestController {
#RequestMapping(value = "/test", method = RequestMethod.POST)
public ResponseEntity test(#RequestBody ChatDescriptionDto dto) {
System.out.println(dto);
return ResponseEntity.ok().build();
}
}
If that's not the case, I'd assume that the problem is with the content type you're using. Spring uses JSON by default, but you can change it in your endpoint's configuration.
To send a simple object request, you do:
{
"member":"kola"
}
To send a list object request, you do:
{
"member": ["kola","wale","ojo"]
}
This is more like listing array elements.
Any error that pops up after this, is basically not because of the request you sent.
I'm creating a Spring boot REST API which should take 2 Lists of custom objects. I'm not able to correctly pass a POST body to the API I've created. Any idea what might be going wrong ?
Below is my code :
Controller Class Method :
// Main controller Class which is called from the REST API. Just the POST method for now.
#RequestMapping(value = "/question1/solution/", method = RequestMethod.POST)
public List<Plan> returnSolution(#RequestBody List<Plan> inputPlans, #RequestBody List<Feature> inputFeatures) {
logger.info("Plans received from user are : " + inputPlans.toString());
return planService.findBestPlan(inputPlans, inputFeatures);
}
Plan Class , this will contain the Feature class objects in an array:
public class Plan {
public Plan(String planName, double planCost, Feature[] features) {
this.planName = planName;
this.planCost = planCost;
this.features = features;
}
public Plan() {
}
private String planName;
private double planCost;
Feature[] features;
public String getPlanName() {
return planName;
}
// getters & setters
}
Feature POJO Class :
// Feature will contain features like - email , archive etc.
public class Feature implements Comparable<Feature> {
public Feature(String featureName) {
this.featureName = featureName;
}
public Feature() {
}
private String featureName;
// Getters / Setters
#Override
public int compareTo(Feature inputFeature) {
return this.featureName.compareTo(inputFeature.getFeatureName());
}
}
You cannot use #RequestBody twice!
You should create a class that holds the two lists and use that class with #RequestBody
You should create json like this:
{
"inputPlans":[],
"inputFeatures":[]
}
and create Class like this:
public class SolutionRequestBody {
private List<Plan> inputPlans;
private List<Feature> inputFeatures;
//setters and getters
}
POST mapping like this:
#RequestMapping(value = "/question1/solution/", method = RequestMethod.POST)
public List<Plan> returnSolution(#RequestBody SolutionRequestBody solution) {
logger.info("Plans received from user are : " + solution.getInputPlans().toString());
return planService.findBestPlan(solution);
}
I am a beginner in REST-api development and I am facing this error : "Unsupported Media Type" while hitting my java api through postman. My Pojo Class is :
public class OrderRequest implements Serializable{
private static final long serialVersionUID = 1L;
public OrderRequest() {}
private long orderNo;
private int rateOverallExperience;
private String apiName;
private Double apiVersion;
public long getOrderNo() {
return orderNo;
}
public int getRateOverallExperience() {
return rateOverallExperience;
}
public String getApiName() {
return apiName;
}
public Double getApiVersion() {
return apiVersion;
}
public void setOrderNo(long orderNo) {
this.orderNo = orderNo;
}
public void setRateOverallExperience(int rateOverallExperience) {
this.rateOverallExperience = rateOverallExperience;
}
public void setApiName(String apiName) {
this.apiName = apiName;
}
public void setApiVersion(Double apiVersion) {
this.apiVersion = apiVersion;
}
}
My controller class for this is :
#RestController
public class OrderRatingController {
public OrderRatingController() {}
#Autowired
private OrderRequestService ordRequestService;
#Autowired
private ProductRatingService prdRatingService;
#RequestMapping(value = "/saveOrderRatings", method = RequestMethod.POST
,consumes = MediaType.APPLICATION_JSON_VALUE) //"application/json"
public OrderRequest saveOrder(#RequestBody OrderRequest requestObj) {
System.out.println("Inside saveOrder. Json Object recieved : " + requestObj);
//...OTHER CODE...
return requestObj;
}
}
I am using Jetty server(version:9.4.0.M0) to test my api.
In Postman>Body tab>raw , I have selected JSON(application/json) and sending :
{
"orderNo" : "737521F547D00D26",
"rateOverallExperience" : 4,
"apiName": "giveitemrating",
"apiVersion":"1.0"
}
Postman Header related details in a pic/snap:
When I am sending this, I get an Unsupported Media Type error. Anyone has any idea about this?
EDIT : As suggested in the comments, Updated controller class a follows : #RequestMapping(value = "/saveOrderRatings", method = RequestMethod.POST
,consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE, headers = "Accept=application/json")
Further added a header in POSTMAN gui : Accept with value application/json .
This is how postman request looks like after sending the request(still showing the error but change in resultant headers) :
enter image description here
You shouldn't need to configure the consumes or produces attribute at all. Spring will automatically serve JSON based on the following factors.
The accepts header of the request is application/json
#ResponseBody annotated method
Jackson library on classpath
You can use the #RestController instead of #Controller annotation.
I have a problem with my REST Controller. If I sent a request with a RequestBody (json) some attributes doesn't arrive the controller, although they was sent and defined at model.
I could find out that it look like an old version of files will be used from the local java web server. As I changed the System.out.println Value at Constructor still the old value was outputed.
public RestController_ApiKey_2_0() {
System.out.println("RestController_ApiKey_2_0 init");
}
I tried the following things bootless:
deleted java web server and did a new installation
cleaned the project and started server again
clean install of project
Does anyone have an idea?
Please provide more code, how do you declare a controller, and what params it can take. Also show a sample request.
Here is an example of a simple controller:
A model
public class CustomRequestBody {
private String fieldA;
private String fieldB;
public String getFieldA() {
return fieldA;
}
public void setFieldA(final String fieldA) {
this.fieldA = fieldA;
}
public String getFieldB() {
return fieldB;
}
public void setFieldB(final String fieldB) {
this.fieldB = fieldB;
}
}
Controller:
#Controller
public class MyController {
#RequestMapping(value = "/some-path", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.ACCEPTED)
public ResponseEntity handleSomePath(#RequestBody final CustomRequestBody body, final HttpServletRequest request) {
// Do the job.
}
And request will be:
HTTP POST http://some.server.com/some-path
{
"fieldA":"first value",
"fieldB":"second value"
}
Read more at Spring documentation here