#PathVariable annotation used on a Map method argument - spring-mvc

SpringMVC's official doc has the following line:
When a #PathVariable annotation is used on a Map argument, the map is populated with all URI template variables.
My understanding is that I can get a Map object with all path variables like this:
#RequestMapping(path = "/{year}/{month}/{day}")
public String getMap(#PathVariable Map<String, String> pathVariables) {
.....;
}
But I got error: "Could not find #PathVariable [pathVariables] in #RequestMapping" instead. Anyone knows why?

Which version of Spring do you use? Spring has supported this feature since 3.2.

Related

KafkaListener annotation at class level with errorhandler property ignored

When using the kafkalistener annotation at class level and the provided errorhandler property is ignored. When method is annotated with kafkalistner and the provided errorhandler is working. Is it expected behavior?
This is really bug. The piece of code:
String errorHandlerBeanName = resolveExpressionAsString(kafkaListener.errorHandler(), "errorHandler");
if (StringUtils.hasText(errorHandlerBeanName)) {
endpoint.setErrorHandler(this.beanFactory.getBean(errorHandlerBeanName, KafkaListenerErrorHandler.class));
}
Is missed in the:
private void processMultiMethodListeners(Collection<KafkaListener> classLevelListeners, List<Method> multiMethods,
Object bean, String beanName) {
Unfortunately I don't see a simple way to workaround this. Please, consider to have a single #KafkaListener method with an Object as payload and manual type routing in that method to others.
Feel free to raise a GitHub issue on the matter!

What is the difference between #PathParam and #PathVariable [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
To my knowledge both serves the same purpose. Except the fact that #PathVariable is from Spring MVC and #PathParam is from JAX-RS. Any insights on this?
#PathVariable and #PathParam both are used for accessing parameters from URI Template
Differences:
As you mention #PathVariable is from spring and #PathParam is from JAX-RS.
#PathParam can use with REST only, where #PathVariable used in Spring so it works in MVC and REST.
QueryParam:
To assign URI parameter values to method arguments. In Spring, it is #RequestParam.
Eg.,
http://localhost:8080/books?isbn=1234
#GetMapping("/books/")
public Book getBookDetails(#RequestParam("isbn") String isbn) {
PathParam:
To assign URI placeholder values to method arguments. In Spring, it is #PathVariable.
Eg.,
http://localhost:8080/books/1234
#GetMapping("/books/{isbn}")
public Book getBook(#PathVariable("isbn") String isbn) {
#PathParam is a parameter annotation which allows you to map variable URI path fragments into your method call.
#Path("/library")
public class Library {
#GET
#Path("/book/{isbn}")
public String getBook(#PathParam("isbn") String id) {
// search my database and get a string representation and return it
}
}
for more details : JBoss DOCS
In Spring MVC you can use the #PathVariable annotation on a method argument to bind it to the value of a URI template variable
for more details : SPRING DOCS
#PathParam is a parameter annotation which allows you to map variable URI path fragments into your method call.
#PathVariable is to obtain some placeholder from the URI (Spring call it an URI Template)
Some can use #PathParam in Spring as well but value will be null when URL request is being made
Same time if We use #PathVarriable then if value is not being passed then application will throw error
#PathVariable
#PathVariable it is the annotation, that is used in the URI for the incoming request.
http://localhost:8080/restcalls/101?id=10&name=xyz
#RequestParam
#RequestParam annotation used for accessing the query parameter values from the request.
public String getRestCalls(
#RequestParam(value="id", required=true) int id,
#RequestParam(value="name", required=true) String name){...}
Note
whatever we are requesting with rest call i.e, #PathVariable
whatever we are accessing for writing queries i.e, #RequestParam
#PathParam: it is used to inject the value of named URI path parameters that were defined in #Path expression.
Ex:
#GET
#Path("/{make}/{model}/{year}")
#Produces("image/jpeg")
public Jpeg getPicture(#PathParam("make") String make, #PathParam("model") PathSegment car, #PathParam("year") String year) {
String carColor = car.getMatrixParameters().getFirst("color");
}
#Pathvariable: This annotation is used to handle template variables in the request URI mapping ,and used them as method parameters.
Ex:
#GetMapping("/{id}")
public ResponseEntity<Patient> getByIdPatient(#PathVariable Integer id) {
Patient obj = service.getById(id);
return new ResponseEntity<Patient>(obj,HttpStatus.OK);
}

Spring 3.2 Jackson2 (400 Bad request)

I know spring 3.2 does convert a json to a list of objects with RequestBody annotation. Its not working for me. I can use regular Jackson object mapper to do it. Just checking if any one can help me.. Below is my json and controller method
[{"uniqueJqGridId":"1","fileProcessingDate":"2012-09-24","createdTimeStamp":"1348569180191","csoCode":"A-A ","cycleDate":"2012-09-24","accountDate":"2012-10-02","originName":"NCAA ","amount":"-95996.33","policyNumber":"C ","transactionCode":"PCH","id":"1"}]
#RequestMapping(method = RequestMethod.POST, value = "/washTransactions", headers="Content-Type=application/json")
public #ResponseBody RequestStatus washTransactions(#RequestBody List<ReconPolicy> policiesToWash)throws Exception{
reconciliationService.applyWashToTransactions(policiesToWash,getCurrentUser());
return new RequestStatus(true);
}
You're facing Java's Type Erasure problem. Spring is not able to pass the exact class type to the method so it's actually getting something like List<?> policiesToWash.
A workaround would be to create a class like
public class WashablePolishes extends ArrayList<ReconPolicy>
This way spring will retain the type through the super type chain.
or you could change your method to
public #ResponseBody RequestStatus washTransactions(#RequestBody ReconPolicy[] policiesToWash) throws Exception {...}
Thanks for you reply Varun. Starting from Spring 3.2,There is no type erasure problem. I found the issue after enabling spring debugging, I figure out it is failing on some unknown properties, I had to annotate my class with #JsonIgnoreProperties. Now it works.

Spring MVC handler returns String with extra quotes

I'm using Spring 3.1 and I have a handler that should return a String value.
Here's how my handler looks like:
#RequestMapping(value = TEST_HANDLER_PATH, method = RequestMethod.POST)
public ResponseEntity<String> handleTest(HttpServletRequest request,
#RequestParam("parma1") String param) throws Exception {
String ret = ...
...
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "text/plain;charset=utf-8");
return new ResponseEntity<String>(ret, headers, HttpStatus.CREATED);
}
I also tried annotating method with #ResponseBody with return ret; at the end.
In both cases, when I hit the service, I get extra quotes around String value (e.g. "This is a test").
I'm guessing this is due to message conversion. That's why I tried defining Content-Type header, to hit StringHttpMessageConverter explicitly, to no avail.
Had the same problem.
Just make sure you register a org.springframework.http.converter.StringHttpMessageConverter as well as your Jackson one so that Strings are treated literally and not attempted to be converted to JSON (with extra quotes).
Just instantiate with default constructor or constructor with your preferred Charset. The media types should be set for you with the standard internal defaults. If you're configuring via code extending WebMvcConfigurerAdapter then you just add the converters in the configureMessageConverters(List<HttpMessageConverter<?>> converters) method.
In my case, I had over-engineered =)
Had introduced a converter for bean's toString Operations like this:
class SerializableToString implements Converter<Serializable, String>
restricting that (only to my beans), resolved the issue X)
Note: debugging with a breakpoint # org.springframework.core.convert.support.GenericConversionService.getConverter helped.
In a related scenario, I had an IntegrationFlow for a GET that incorrectly requested a transform. Basically the target service would receive the #PathVariable as a quote escaped string
return IntegrationFlows.from("getThing")
.transform(Transformers.toJson())
.handle(
The .transform(Transformers.toJson()) was forcing the strings to be escaped in the URI, so simply removing it - it shouldn't have been there - fixed the issue.
Turns out there was a JSON message converter registered in one of the imports.

Spring 3 MVC Request parameter mapping. Two parameters from the same class while calling a handler in the controller

I am trying to figure out how to pass two different parameters of the same class through the URL to a handler method in the controller. For example, given a "Foo" class with an "id" parameter(I am saying just one parameter to keep it simple, but think from a class with loads of them), the code of the controller looks as it follows:
#Controller(value = "customerCareRemoteService")
public class CustomerCareRemoteServiceImpl {
// Othe methods/requests
#RequestMapping(value = "/" + "prueba" , method = RequestMethod.GET)
public #ResponseBody String prueba(Foo pFoo1, Foo pFoo2) {
//stupid and not interesting code
String answer = "pFoo1.id is " + pFoo1.id + ". pFoo2.id is " + pFoo2.id.";
System.out.println(answer);
return answer;
}
}
So, when I call this method, there is no way to differ between the two parameters:
http://myfakeurl/prueba?id=1&id=2
How should I deal with that? Is there any way to "prefix" the parameters? I have seen #RequestParam but it does not work for me, because it can not be used with my very own and beauty personal classes(or am I wrong?). Also I would like to avoid wrapper classes. Thank you for your time.
You should use #PathVariable to solve this problem.
Your mapping url would be like this.
#RequestMapping(value = "/" + "prueba" + "/{id1}/{id2}" , method = RequestMethod.GET)
and the arguements in your function would be.
public #ResponseBody String prueba(#PathVariable int pFoo1, #PathVariable int pFoo2)
In this way you can get both the ID in your controller for further operation using them.
Hope this helped you.
Cheers.
So, with some help from a workmate, I have came to the next page that talks about that thema:
Customizing Parameter Names When Binding Spring MVC Command Objects
Which leads to the next StackOverFlow question:
How to customize parameter names when binding spring mvc command objects
So it looks like there is no easy solution available like "using annotation X", but to create your own resolver, and use custom annotations (as a good newbie, I am still trying to understand it :-S).

Resources