Java spring REST controller: incomplete request body - java

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

Related

How to load different property value conditionally

I have a condition where I want to use the same method to be called for request coming from mobile app and request coming from webapp with different clientId and different Client secret and redirect uris,base uris .
When a request comes from mob we have header "source" value as mobile and when request comes from web we have header "source" value as web.
I want to have something like that when request comes from web ,values of client id,clientsecret,baseurl,redirecturl of web is loaded and when request comes from mobile
values of client id,clientsecret,baseurl,redirecturl of mobile is loaded.
I want to avoid to write the same logic either by creating in different method or different endpoint for mobile/web.I wan to use the same method and the same endpoint ,just that values injected from conifguration will be different based on the header value
How can I achieve this??Is there a way to #Autowire different config class based on condition
TokenController
public class TokenController {
#GetMapping("/getToken")
public ResponseEntity<?> fetchToken(#RequestParam("foo") String foo) {
ResponseEntity<?> tokenInfo = tokenInfoServiceImpl.getTokenDetails(foo);
return tokenInfo;
}}
TokenServiceImpl
public class TokenServiceImpl{
#Autowired
SSOConfig ssoConfig;
public ResponseEntity<?> getTokenDetails(String foo) {
HttpHeaders tokenExchangeHeaders = prepareRestTemplateHeader(ssoConfig.getClientId(),
ssoConfig.getClientSecret());
String baseUrl =soConfig.getBaseurl();
String redirectUrl = ssoConfig.getRedirectUrl();
//rest of the logic
}
}
SSOConfig class
#Configuration
#ConfigurationProperties(prefix = "sso.web")
public class SSOConfig {
private String baseurl;
private String redirectUrl;
private String tokenClientId;
private String tokenClientSecret;
//Getters and Setters
}
For your TokenController class, you should be able to add an argument to process a RequestHeader.
public class TokenController {
#GetMapping("/getToken")
public ResponseEntity<?> fetchToken(#RequestHeader(name = "source") String source, #RequestParam("foo") String foo) {
ResponseEntity<?> tokenInfo = null;
if ("mobile".equals(source)) {
ResponseEntity<?> tokenInfo = tokenInfoServiceImpl.getTokenDetails(foo);
} else {
//do something else
}
return tokenInfo;
}}
There's a great tutorial on this at Baeldung

Redirect to a POST request from one controller to another controller Spring Boot

I have a springboot project with 2 controller files as below:
File1.java
#PostMapping("/test")
public String testMap(String s){
if(s!=null){
return "found it";
}
else {
// need to go to POST request in another controller
}
return "not found";
}
File2.java
#PostMapping("/test2")
public String testMap2(String s){
if(s!=null){
return "found it";
}
return "not found 2";
}
I have tried adding java HttpURLConnection lines to send a POST request in File1.java but it does not perform the operations within testMap2, instead it exits with not found
Could you please give some suggestions on how I could accomplish this?
You could use RestTemplate to create another POST request, although I strongly suggest avoiding that.
Since both of these controllers are in the same project, try extracting the common logic into a #Service which should be injected in both controllers.
For example:
File1.java
#RestController
public class MyFirstController {
private MyBusinessLogic myBusinessLogic;
// Constructor injection
public MyFirstController(MyBusinessLogic myBusinessLogic) {
this.myBusinessLogic = myBusinessLogic;
}
#PostMapping("/test")
public String testMap(String s){
if(s!=null){
return "found it";
}
else {
return myBusinessLogic.doSomething(s);
}
return "not found";
}
}
File2.java:
#RestController
public class MySecondController {
private MyBusinessLogic myBusinessLogic;
// Constructor injection
public MySecondController(MyBusinessLogic myBusinessLogic) {
this.myBusinessLogic = myBusinessLogic;
}
#PostMapping("/test2")
public String testMap2(String s){
if(s!=null){
return myBusinessLogic.doSomething(s);
}
return "not found 2";
}
}
Finally create a service for the common logic:
#Service
public class MyBusinessLogic {
public String doSomething(String s) {
// common logic goes here
}
}
You can use RestTemplate.
Lets say our controller looks like this:
#RestController
#RequestMapping(value = "first/")
public class FirstRestController {
#PostMapping("test")
public String getTest(String s){
return service.doSomething(s);
}
}
Basically, add this method as a bean in one of your config classes. #Bean puts the method in application context. Now we can inject this method in our services.
#Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
Now, one of our service methods in Second App, we must call the endpoint of First.
#Service
public class SecondAppService{
#Autowired
private RestTemplate restTemplate;
public String callFirst() {
final URI uri =UriComponentsBuilder.fromUriString(PATH+"first/").toUri();
restTemplate.postForEntity(uri, "something", String.class);
// check your resttemplate docs, i used postForEntity here.
// if necessery return something with response, this method expects the return string but you get the idea.
}
}
This should work.

I want to send a List(which is a member of an object) from Postman to Spring REST API

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.

Spring boot restful web service. Xml response wrongly formatted

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 .

Unsupported Media Type while hitting my JAVA api through Postman

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.

Categories

Resources