Feign Client + Eureka POST request body - spring

I'm trying to use Feign and Eureka to forward a post request from server A to server B. Both servers are discrovered sucessfully by Eureka.
This works:
#Feignclient
public interface MyFeignClient {
#RequestMapping(value = "test", = RequestMethod.POST, consumes = "application/json")
ResponseEntity<String> theActualMethod(
HttpServletRequest request,
#RequestHeader("firstHeader") String header1,
#RequestHeader("secondHeader") byte[] header2);
}
However, when I change the second argument to #RequestBody in order to read the POST request content, I get an exception:
java.lang.IllegalStateException: Method has too many Body parameters: public abstract org.springframework.http.ResponseEntity MyFeignClient.theActualMethod(javax.servlet.http.HttpServletRequest,java.lang.String,byte[])

The problem was that a method in Feign interface cannot have more than one 'general' argument. you can have as many header arguments as you want but not more than one as body. Since #RequestBody doesn't do anything it is regarded not as a header but as another variable in addition to the HttpServletRequest request variable.
So I had to change my business logic to have only one parameter.

For me, the issue was that I used #Param (as in feign.Param) instead of #RequestParam (as in org.springframework.web.bind.annotation.RequestParam). Changing all #Param to #RequestParam solved it for me.
I Don't know why this is but a related question on Feign's repository might explain a little.

Related

How to display x-www-form-urlencoded format request with springdoc-openapi-ui

My environment
springboot:2.6.4
springdoc-openapi-ui:1.6.6
Probrem
I want to create an API definition to receive requests in x-www-form-urlencoded format.
Using #RequestBody will create a swagger-ui display with no Parameter notation, just the body. However, when receiving a request in x-www-form-urlencoded format, it is necessary to receive it with #RequestParam, and if this is done, the swagger-ui display is created as a query parameter.
#PostMapping(value = "/v1/hoge")
public ResponseEntity<SampleResponse> postProc(
#RequestParam("param1") int param1,
#RequestParam("param2") String param2,
#RequestParam("param3") String param3,
HttpServletRequest request) {
  ・・・
}
swagger-image
However, since there is no actual query parameter, I do not want to display the Parameter in the same way as when receiving a request with #RequestBody.
The display without parameters is correct, as in POST /user in the following link.
http://158.101.191.70:8081/swagger-ui/4.5.0/index.html#/user/createUser
Is there a solution to this problem?
I might have a solution for you:
#PostMapping(value = "/v1/hoge", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity<SampleResponse> postProc(
#RequestPart("param1") int param1,
#RequestPart("param2") String param2,
#RequestPart("param3") String param3,
HttpServletRequest request) {
  ・・・
}
In a perfect world, you could stick to the #RequestParam but I believe there is currently a bug with springdoc that make it impossible.

Spring REST - Deserializing object from GET request query

I'm trying to implement an endpoint that takes a serialized object from request parameter and deserializes it into a POJO. Is there an easy way how to do this with Spring?
The example of a query:
http://localhost/routes/departures?trip=%7B%22stopId%22:%22U321Z102%22,%22routeId%22:%22L991D1%22,%22headSign%22:%22Nemocnice+Motol%22%7D
which should translate into this:
trip: {"stopId":"U321Z102","routeId":"L991D1","headSign":"Nemocnice Motol"}
Also, those parameter values may contain spaces and special characters (ěščř...). Will Spring handle this? Alternatively I could send those parameters separately and not serialized, but I'm worried this would be an issue.
You need to send the user by using post request (send a userDTO that has the same type and attributes names than the one in the back end )
your rest controller is going to look like this
#PostMapping("/users")
#PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
public ResponseEntity<User> createUser(#Valid #RequestBody UserDTO userDTO) throws URISyntaxException {
log.debug("REST request to save User : {}", userDTO);

how to apply post method to all request mappings in spring

How i can access to request POST data from different url-s to one controller method, for example I have /countries & /countries/{id} URL, It works very good with first one, because my code is
#RequestMapping(value = {"/{id}", "/{id}/"}, method = RequestMethod.GET)
public String getCountry(#PathVariable(value = "id", required = true) int id,ModelMap model) {
}
#RequestMapping(method = RequestMethod.POST)
public String deleteCountry(ModelMap model,HttpServletRequest request) {
}
And when I try to request POST data from second url I'm getting
HTTP Status 405 - Request method 'POST' not supported
Which is expectable because I haven't POST method with this mapping, but if I will be made one method for one mapping my code will be too ugly ant terrible, what solution I can use?
Hum why not add the "array" of value to your second method as well ?
#RequestMapping(value = {"", "/{id}"},method = RequestMethod.POST)
public String deleteCountry(ModelMap model,
HttpServletRequest request) {
Btw using POST verb to call an action that looks like it will delete the resource seems wrong, it should be a DELETE verb used
EDIT
But in reality, you should be creating 2 methods, as both those method are not supposed to do the same thing.
POST /countries should be creating country resources
POST /countries/{id} should be doing something else.
For an update prefer PUT /countries/{id}
And for a delete, prefer DELETE /countries/{id}
There is one way to have separate handler interceptors for different controllers.
Refer this link for details.
bind Spring HandlerInterceptor only to one controller
But I feel, it may be good you can create a common method to share business logic for this.
As Interceptor comes with proxy class for your controller which can be avoided unless you have complex logic.

5 levels of media type Spring REST

I am trying to apply CQRS principles on my REST API with domain-driven-design principles, using the 5 levels of Media Types, as explained in these articles:
https://www.infoq.com/articles/rest-api-on-cqrs
http://byterot.blogspot.ch/2012/12/5-levels-of-media-type-rest-csds.html
My technical context is Spring REST framework version 3.2.
Basically, i need to be able to map my commands using different "domain-model" media types.
Therefore, i would expect the following mapping to work:
#Controller
#RequestMapping("resources")
public class MyController {
#RequestMapping(value = "{id}", method = RequestMethod.PUT, consumes = "application/json;domain-model=CommandOne")
#ResponseBody
public void commandOne(#PathVariable Long id, #RequestBody CommandOne commandOne) {
LOG.info("Using command {}", commandOne);
}
#RequestMapping(value = "{id}", method = RequestMethod.PUT, consumes = "application/json;domain-model=CommandTwo")
#ResponseBody
public void commandTwo(#PathVariable Long id, #RequestBody CommandTwo commandTwo) {
LOG.info("Using command {}", commandTwo);
}
}
Problem is, I am getting mapping errors when requesting for a PUT:
PUT /resources/123
Content-Type: application/json;domain-model=CommandOne
Error is:
java.lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path ...
Spring doesn't allow me to map the same uri the different domain-model Media Types. Any idea how could I achieve that? Am I missing something?
Many thanks
:o)
That's because the content-type is still the same application/json. Please look at Content-Type syntax
What you are passing as domain-model=CommandOne is just a parameter and Spring doesn't recognize as a difference to call the different methods.
This is described in more detail on answer
Does HTTP content negotiation respect media type parameters
This was submitted as a BUG to the Spring team but they closed with "Work as designed".
Unfortunately Spring can't treat this case currently.

Parsing JSON request body with Spring MVC

I am using Spring 4.1 framework for developing webservices. When I return a Java object as response, it is automatically converted to JSON and delivered to client, so I assume that JSON parser is in classpath and it is configured properly. However it fails to convert the request body from JSON into Java object and client is getting a HTTP response of 400.
Here is how the webservice looks like:
public class Details{
public Details(){
}
int code;
int area;
}
#RequestMapping(value = "/api/update/{phoneNumber}", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> update(#PathVariable final String phoneNumber, #RequestBody Details details)
Here is how the request looks like:
Method: Post
Content-Type: application/json; charset=utf-8
Body: {"code":0,"area":12}
If I collect the request body as string and parse it manually then it works, so it gets the valid JSON but for some reason it is not parsing it automatically. I have no clue on how to fix it. Please help. Thanks in advance.
You have package-private properties in your Details class, so they are probably not recognised by json-converter.
You have several options:
define them as public (not recommended)
provide getters and setters
if you are using jackson, you can annotate them with #JsonProperty, leaving them package-private
Finally I got the reason for this. I was using inner classes which were not static. Making those static fixed the issue.

Resources