Overloading SpringBoot #PostMapping controller method not working - spring-boot

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";
}
}

Related

FeignException com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.http.ResponseEntity`

Any Help please !!
I receive this error when I'm calling my endpoint which call Feign in the background :
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of
`org.springframework.http.ResponseEntity` (no Creators, like default constructor, exist): cannot deserialize
from Object value (no delegate- or property-based Creator)
at [Source: (BufferedReader); line: 1, column: 2]
This is my endpoint inside Controller :
#RestController
#RequestMapping(Routes.URI_PREFIX)
public class CartoController {
#Autowired
private ReadCartographyApiDelegate readCartographyApiDelegate;
#GetMapping(value = "/cartographies/{uid}", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseWrapper<ReadCartographyResponse> readCarto(HttpServletRequest request,
#PathVariable(name = "uid") String uid) {
ResponseEntity<ReadCartographyResponse> result ;
try {
result = readCartographyApiDelegate.readCartography(uid);
}catch (Exception e){
throw new TechnicalException("Error during read Carto");
}
return responseWrapperWithIdBuilder.of(result.getBody());
}
}
Interface ReadCartographyApiDelegate generated automatically by openApi from yaml file :
#javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "...")
public interface ReadCartographyApiDelegate {
default Optional<NativeWebRequest> getRequest() {
return Optional.empty();
}
default ResponseEntity<ReadCartographyResponse> readCartography(String uid) {
getRequest().ifPresent(request -> {
for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
String exampleString = "null";
ApiUtil.setExampleResponse(request, "application/json", exampleString);
break;
}
}
});
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
}
This my ReadCartoApiDelegateImpl which implements ReadCartographyApiDelegate interface :
#Service
public class ReadCartographyApiDelegateImpl implements ReadCartographyApiDelegate {
private EcomGtmClient ecomGtmClient;
public ReadCartographyApiDelegateImpl(EcomGtmClient ecomGtmClient) {
this.ecomGtmClient = ecomGtmClient;
}
#Override
public ResponseEntity<ReadCartographyResponse> readCartography(String uid) {
ResponseEntity<ReadCartographyResponse> response = ecomGtmClient.readCartography(uid);
return response;
}
}
This is the feign client :
#FeignClient(name = "ecomGtmSvc", url = "http://localhost/")
public interface EcomGtmClient {
#GetMapping(value = "/read-carto/{uid}")
ResponseEntity<ReadCartographyResponse> readCartography(#PathVariable("uid") String uid);
}
The problem is that ResponseEntity (spring class) class doesn't contain default constructor which is needed during creating of instance. is there Any config to resolve this issue ?
If you want access to the body or headers on feign responses, you should use the feign.Response class. ResponseEntity does not work with feign because it is not meant to. I think it is best if you just return Response from your feign client method. You should then be able to pass the body to the ResponseEntity instance in the Controller.
What is your reason to even use the response-wrapper, i can't really figure that out from your code?
Sadly I couldn't find any documentation on the Response class, but here's the link to the source on GitHub.
https://github.com/OpenFeign/feign/blob/master/core/src/main/java/feign/Response.java
My Suggestion would be
#FeignClient(name = "ecomGtmSvc", url = "http://localhost/")
public interface EcomGtmClient {
#GetMapping(value = "/read-carto/{uid}")
ReadCartographyResponse readCartography(#PathVariable("uid") String uid);
}
#RestController
#RequestMapping(Routes.URI_PREFIX)
public class CartoController {
#Autowired
private ReadCartographyApiDelegate readCartographyApiDelegate;
#GetMapping(value = "/cartographies/{uid}", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseWrapper<ReadCartographyResponse> readCarto(HttpServletRequest request,
#PathVariable(name = "uid") String uid) {
ReadCartographyResponse result ;
try {
result = readCartographyApiDelegate.readCartography(uid);
}catch (Exception e){
throw new TechnicalException("Error during read Carto");
}
// I don't know where you get the builder from, so I assume it does something import and is needed
return responseWrapperWithIdBuilder.of(result);
}
}
Of course you'd also have to change all intermediate classes.
The Response Output was the correct Object that I have to put, cause every time I need to check the status from my feign client endpoint to do différent logic
#FeignClient(name = "ecomGtmSvc", url = "http://localhost/")
public interface EcomGtmClient {
#GetMapping(value = "/read-carto/{uid}")
ReadCartographyResponse readCartography(#PathVariable("uid") String uid);
}

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 {}

Distinguish different values in #PostMapping, #GetMapping or #RequestMapping

#PostMapping(value = { "/weblogin", "/mobilelogin" })
#ResponseStatus(HttpStatus.OK)
public AccessTokenResponseModel login() { // need to distinguish "/weblogin" or "/mobilelogin" }
In spring boot, How can I distinguish the post request comes from "/weblogin" or "/mobilelogin"
in login() method?
You could use the BEST_MATCHING_PATTERN_ATTRIBUTE attribute.
#PostMapping(value = { "/weblogin", "/mobilelogin" })
#ResponseStatus(HttpStatus.OK)
public AccessTokenResponseModel login(HttpServletRequest httpRequest) {
final String requestMapping = ( String ) httpRequest.getAttribute( HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE );
final boolean isMobileLogin = requestMapping.contains("/mobilelogin");
....
}

RestController return CompletableFuture<List>

I try to create rest controller which return all products. I want to use CompletableFuture to return list with product.
I have async request to spring data
#Async
#Query("select product from Product product")
CompletableFuture<List<Product>> findAllAsync();
and controller
#Async
#RequestMapping(path = "/products", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody
CompletableFuture<List<ProductData>> loadAllProducts2(){
return this.products.findAllAsync()
.thenApplyAsync(Collection::stream)
.thenApplyAsync(s -> s.map(Product::data))
.thenApplyAsync(s -> s.collect(Collectors.toList()));
}
ProgramData is simple DTO:
public final class ProductData {
private final String name;
private final String label;
public ProductData(String name, String label) {
this.name = name;
this.label = label;
}
public String getName() {
return this.name;
}
public String getLabel() {
return this.label;
}
}
Spring return nothing, in log output is :
o.s.b.a.e.mvc.EndpointHandlerMapping : Did not find handler method for [/products]
Any ideas what's wrong ?
I removed target directory and It did work.

How to bind a cookie value to a pojo field in Spring MVC?

For example, I'd like to bind the value of the cookie in the current request to the pojo below.
#RequestMapping(path="/", method= GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> handleTheRequest(Foo foo){
return blah;
}
public class Foo{
private string cookieValue;
//Other fun fields
public void setCookieValue(String value){
this.cookieValue = value;
}
public string getCookieValue(){
return cookieValue;
}
}
Can you try ?
#RequestMapping(path="/", method= GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> handleTheRequest(#RequestBody Foo foo){
return blah;
}

Resources