Spring MVC - Jackson deserialize braces - spring

I have REST POST method which accepts #RequestBody String name.
When I send there from Postman json like this:
{
"name": "some_name"
}
I get a String variable which contains: '{ "name": "some_name" }'.
But when I send from postman just some_name I get variable which contains 'some_name'.
How it's possible?

You are telling Jackson to parse the payload into a String, so it does. If you want Jackson to parse a JSON payload into a POJO, do something like:
#RestController
public class MyController {
#PostMapping("my/endpoint")
public NameDto post(#RequestBody NameDto dto) {
// do stuff
return dto;
}
class NameDto {
private String name;
public NameDto() { }
public String getName() {
return this.name;
}
publid void setName(String s) {
this.name = s;
}
}
}
}
Depending on your use case, you may want to refactor NameDto into it's own file and modify the access to public.

Related

Overloading SpringBoot #PostMapping controller method not working

I have faced some challenge and to describe shortly I created test application. Code you can see and error you can see below.
#RestController
public class TestController {
#PostMapping(value = "/test",params = { "a", "b" })
public String test(#RequestPart MultipartFile a, #RequestPart(required = false) MultipartFile b) {
return "test1";
}
#PostMapping(value = "/test", params = { "b" })
public String test(#RequestPart MultipartFile b) {
return "test2";
}
}
I`m trying to execute this request from postman:
And I`m getting such error in logs:
Resolved [org.springframework.web.bind.UnsatisfiedServletRequestParameterException:
Parameter conditions "a, b" OR "b" not met for actual request parameters: ]
The thing is, if I will put parameters also in postman (not in body, in request url: localhost:8080/test?b=anything) it will work fine, but I don`t need request params in url.
Is there some possible way to make it work?
I am able to override #PostMapping. But the type of the parameter should be different.
#PostMapping(value="/test" )
public String testApi(#ModelAttribute MultipartDTO multipartDTO) {
return "test1";
}
#PostMapping(value="/test" ,params = { "b" })
public String test(#RequestParam String b) {
return "test2";
}
/** DTO **/
#Data
public class MultipartDTO{
private MultipartFile a;
private MultipartFile b;
}
you can not map the same signature twice which contains the same Http methods then below error will occur.
java.lang.IllegalStateException: Ambiguous handler methods
try this one
#RestController
public class TestController {
#PostMapping("/test")
public String test(#RequestParam MultipartFile a, #RequestParam(required = false) MultipartFile b) {
return "test1";
}
#PostMapping("/test2")
public String test(#RequestParam MultipartFile b) {
return "test2";
}
}
You should try something like below.
#RestController
public class TestController {
#PostMapping(value = "/test")
public String test(#RequestParam MultipartFile a, #RequestParam(required = false) MultipartFile b) {
return "test1";
}
#PostMapping(value = "/test")
public String test(#RequestParam MultipartFile b) {
return "test2";
}
}

How to get query Params from URL along with generics and not as String for GET request in spring boot

I wanted to read the parameters with the same data type and not as string from my GET request. I am actually getting the entire Request params as String. Need to know if there is way to read the params with their specified data types
Yes. Please refer below examples of GET and POST both which suits your problem.
Suppose your Json is:
{
"name" : "john"
"age" : 30
}
Your mapping class is
public class user {
private String name;
private Long age;
//getter & setter
}
Your controller class will be :
#RestController
#RequestMapping("/user")
public class UserController {
#PostMapping("/add")
public void addUser(#RequestBody User user) {
System.print.out(user.getName());
}
// URL will be http://localhost:8080/user?userId=
#GetMapping
public void getUser(#RequestParam Long userId) {
}
// URL will be http://localhost:8080/user/1
// likewise you can specify multiple path variable in URL separated by "/"
#GetMapping
public void getUser(#PathVariable("id") long id) {
}

415--Unsupported Media Type in Spring

I am getting unsupported mediatype error.
My User Profile class looks like this
Class UserProfile{
private int age;
private String name,
private String currenecy;
}
And this is the method in controller
#RequestMapping(value = "/Create", method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE, produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<UserProfileResponse> createUserProfile(#RequestBody UserProfile userProfile)
{
UserProfileResponse userProfileResponse = new UserProfileResponse();
int id = createUserProfileData(userProfile)
userProfileResponse.setId(id);
return new ResponseEntity<UserProfileResponse>(userProfileResponse,HTTPStatus.OK);
}
I am trying to send the request through POSTMAN but getting
Error 415--Unsupported Media Type
My Request in POstman looks like this
Content-Type:application/json
Accept:application/json
Method is : POST
{
"age":28,
"name":"Sam",
"currency": "INR"
}
Suggest me what I am missing?
Don't forget to select "JSON" format, filled in arbitrary JSON string in the textarea.
Also use either Accept or Content-type at a time.
If that doesn't work then can you check like below by removing consumes and adding headers manually.
#RequestMapping(value = "/Create", method=RequestMethod.POST, headers = "Accept=application/json",produces=MediaType.APPLICATION_JSON_VALUE)
I could see the response coming back with your code. I am deliberately returning the same object just to test the connectivity. Following is my code:
#RequestMapping(value = "/create", method= RequestMethod.POST,consumes= MediaType.APPLICATION_JSON_VALUE, produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<UserProfile> createUserProfile(#RequestBody UserProfile userProfile)
{
System.out.println("Got request");
return new ResponseEntity<>(userProfile, HttpStatus.OK);
}
Used getter and setter in UserProfile
public class UserProfile {
private int age;
private String name;
private String currenecy;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCurrenecy() {
return currenecy;
}
public void setCurrenecy(String currenecy) {
this.currenecy = currenecy;
}
}
Finally after after spending some time.. I figured out why it was not working.
In my java based spring configuration file I missed "#EnableWebMvc".
After adding it, my problem got resolved.
#Configuration
**#EnableWebMvc** // This annotation was missing.
#ComponentScan(basePackages="com.hemant.*")
public class TestConfiguration {}

FeignClient: Serialize RequestParam to JSON

I have a spring boot application in which I am trying to use Feign to communicate with a remote service. My #FeignClient is defined as follows:
#FeignClient(name="TEST_SERVICE", url="URL")
#Component
public interface SomeServiceClient
{
#RequestMapping(
method = RequestMethod.POST,
value = "/someService",
consumes = "application/json",
produces = "application/json"
)
SomeServiceResult getServiceResult(
#RequestParam(value = "mode") String mode,
#RequestParam(value = "payload") SomeServicePayload payload
);
}
I would like the payload object of type SomeServicePayload to be serialized into JSON. I expected this to happen automatically, but it does not. Instead, payload is serialized to its fully qualified class name.
Do I need to set a custom encoder/decoder combination for this client? How would I do this?
#FeignClient under the hood used toString() method for bulding request string. The easiest way to create proper request is to override toString() method manually:
class SomeServicePayload{
String payload;
#Override
public String toString() {
return "{\"payload\":\"" + payload + "\"}";
}
}
Or for complex objects by using ObjectMapper:
public class SomeServicePayload{
private String payload;
public String getPayload() {
return payload;
}
public void setPayload(String payload) {
this.payload = payload;
}
private ObjectMapper mapper = new ObjectMapper();
#Override
public String toString() {
try {
return mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
//...
}
return null;
}
}

Spring rest controller giving unsupported content type

Hello all here is what i have:
StockController.java
#RestController
public class StockController {
#Autowired
private StockRepository repository;
#RequestMapping(value = "stockmanagement/stock")
public ResponseEntity<?> addStock(#RequestBody String stock
) {
System.out.println(stock);
return new ResponseEntity<>(HttpStatus.OK);
}
when I make a request like so using chrome advanced rest extension :
Raw Headers
Content-Type: application/json
Raw Payload
{"stock": {"productId": 2, "expiryAndQuantity" : {}, "id": 0}}
It works fine in that out comes a string of json
However when i try to replace String stock with Stock stock where stock looks like this:
public class Stock {
#Id
private String id;
private String productId;
private Map<LocalDateTime, Integer> expiryAndQuantity;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public Map<LocalDateTime, Integer> getExpiryAndQuantity() {
return expiryAndQuantity;
}
public void setExpiryAndQuantity(Map<LocalDateTime, Integer> expiryAndQuantity) {
this.expiryAndQuantity = expiryAndQuantity;
}
#Override
public String toString() {
return String.format(
""
);
}
}
I get an error where by the following is fed back to me:
"status": 415
"error": "Unsupported Media Type"
"exception": "org.springframework.web.HttpMediaTypeNotSupportedException"
"message": "Content type 'application/json;charset=UTF-8' not supported"
"path": "/stockmanagement/stock"
My question is; how do i create a request which maps to my Stock object.
You can try with #JsonRootName annotation, by default Spring serialize using no root name value. like this:
{"productId": 2, "expiryAndQuantity" : {}, "id": 0}
But if you want that your serialization has a rootname you need to use #JsonRootName annotation.
#JsonRootName(value = "Stock")
And it'll produce something like this
{"Stock": {"productId": 2, "expiryAndQuantity" : {}, "id": 0}}
You can see more here
http://www.baeldung.com/jackson-annotations
instead of accepting a String Accept a Stock object.and accept it from a post request than having a get request
#RequestMapping(value = "stockmanagement/stock",method=RequestMethod.POST)
public ResponseEntity<?> addStock(#RequestBody Stock stock){
}
and your request should be sent like this
{
"productId": 2
,"expiryAndQuantity" : null
,"id": 0
}
all parameter names should be equal to the objects filed names,since spring has jackson binders on class path and object will be created inside the controller method. if you are planning on passing different parameters from the post request you can use
#JsonProperty("pid")
private String productId;
on the field name.

Resources