I'm trying to migrate code from Jax-Rs (jersey implementation) to a Spring MVC entry point:
jax-rs:
#GET
#Path("{bundle}/bundle{min: (-min)*}.{extension: js|css}")
public Response getBundle(#PathParam("bundle") String bundle, #PathParam("min") String min, #PathParam("extension") String extension)
Spring MVC:
#RequestMapping(method = GET, path = "{bundle}/bundle{min:(-min)?}{extension:\\.(js|css)?}")
public void getBundle(#PathVariable String bundle, #PathVariable String min, #PathVariable String extension)
According to Spring MVC documentation, i can use regex for #RequestMapping. The syntax is similar to jaxrs but the entrypoint doesn't work (404 Not Found).
Example of value for the entrypoint: http://localhost:8080/foo/bundle-min.css
I've found a solution with #RequestMapping(method = GET, path = "{bundle}/bundle**") but i have to parse the string to catch my needed parameter values.
Your regex seems fine but replace those capturing groups with non-capturing groups, like following:
{bundle}/bundle{min:(?:-min)?}{extension:\.(?:js|css)?}
With this regex, if you fire a request to foo/bundle-min.css, the bundle would be foo, the min would be -min and the extension would be .css.
Related
I am trying to exclude a specific parameter (param 4) from caching in my rest spring boot application
I am new to the caching and not sure how can we exclude the specific parameter from caching
#Override
#Cacheable(value = "mykey")
public MyResponse myMethod(RestTemplate restTemplate, String param1, String param2, String param3, String param4){
I am expecting the param 4 field to be excluded from the caching
Key can be created using SpEL in #Cacheable annotation. Parameters can be accessed in SpEL using #aX X is index of argument. In this case.
#Cacheable(value="mykey", key="#a1+#a2+#a3")
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/annotation/Cacheable.html#key--
I created a simple Feign Client with Spring Boot like this:
#FeignClient("spring-cloud-eureka-client")
public interface GreetingClient {
#RequestMapping("/greeting")
String greeting(#RequestParam String name);
}
But when I try just to start an application I get an error:
java.lang.IllegalStateException: RequestParam.value() was empty on parameter 0
First I didn't understand what is the reason and googled a lot but didn't find an answer. Almost excidentely I figured out that it works if to write request param name explicitly:
#RequestParam("name") String name
So my question: is it a bug or could it be configured to not write request params names explicitly?
Both Spring MVC and Spring cloud feign are using the same ParameterNameDiscoverer - named DefaultParameterNameDiscoverer to find parameter name. It tries to find the parameter names with the following step.
First, it uses StandardReflectionParameterNameDiscoverer. It tries to find the variable name with reflection. It is only possible when your classes are compiled with -parameters.
Second, if it fails, it uses LocalVariableTableParameterNameDiscoverer. It tries to find the variable name from the debugging info in the class file with ASM libraries.
The difference between Spring MVC and Feign occurs here. Feign uses above annotations (like #RequestParam) on methods of Java interfaces. But, we use these on methods of Java classes when using Spring MVC. Unfortunately, javac compiler omits the debug information of parameter name from class file for java interfaces. That's why feign fails to find parameter name without -parameter.
Namely, if you compile your code with -parameters, both Spring MVC and Feign will succeed to acquire parameter names. But if you compile without -parameters, only Spring MVC will succeed.
As a result, it's not a bug. it's a limitation of Feign at this moment as I think.
Just use String greeting(#RequestParam("name") String name);
#FeignClient("spring-cloud-eureka-client")
public interface GreetingClient {
#RequestMapping("/greeting")
String greeting(#RequestParam("name") String name);
}
I use upgrade maven-compiler-plugin to solve this plobrem. you can access: https://blog.51cto.com/thinklili/2566864
This worked for me.
#FeignClient(name="session-service", url="${session.host}")
public interface SrocessingProxy {
#RequestMapping(value = "/process/{key}", method = RequestMethod.POST)
public Response processSession(#RequestParam String key, #RequestBody PayloadHolder payload);
}
//Service
#RequestMapping(value = "/process/{key}", method = RequestMethod.POST)
public Response processSession(#RequestParam String key, #RequestBody PayloadHolder payload) {
System.out.print("Key : " + key);
}
I want to have rest controller in Spring Boot to handle all requests like this: "/{arg}", EXCEPT "/sitemap.xml". How can I achieve that?
You could specify your request mapping on the controller level via regex and exclude some resources (e.g. 'excludeResourceA' and 'excludeResourceB') with:
#RestController
#RequestMapping(value = "/{arg:(?!sitemap.xml|excludeResourceA|excludeResourceB).*$}")
public class YourRestController {
// your implementation
}
Of course you can also specify the request mapping on the method level with the same regex relative to your controller path matching and you can pass the argument with #PathVariable("arg") String arg in your method signature to your method body if you need it.
I have a Spring Boot app that includes some controllers and static resources. I need to be able to have a controller that matches:
/hello
and
/hello/
but not
/wonder/hello
(or anything else). It seems that when I use the following mapping:
#RequestMapping(value = "/{slug}", method = RequestMethod.GET)
public String mapping(#PathVariable("slug") String slug)
it does a "catch-all" whereas I only need it to catch the first level. This causes issues with the static resource mapping.
use #RequestMapping("/hello") in the starting of controller
Using spring-web, I am mapping a method to receive a request containing dots "." on the path:
#RequestMapping(value = "download/{id:.+}", method = RequestMethod.GET, produces = "application/xls")
public String download(#PathVariable(value = "id") String id) { ... }
For example, /download/file.xls should be a valid address. But when I try to access that address, Spring returns Could not find acceptable representation as if it was trying to find a resource named file.xls.
Spring shouldn't execute download method rather than try to find a resource named as the path variable?
Obs.: my application is a spring-boot application.
Your #RequestMapping says it produces "application/xls", but your return type is a String and you haven't annotated the return type with #ResponseBody.
If you want to return an Excel spreadsheet, you need to produce that spreadsheet on the server and return it as a byte[] from your request mapping. I'm not sure how or why you'd return a String, unless you're controller is a simple #Controller and you're returning the view name.
Have you tried configuring your RequestMappingHandlerMapping
handler.setUseSuffixPatternMatch( false )
(I was configuring my RequestMappingHandlerMapping anyway, so for me I just needed to add that line - chances are you may be letting Spring Boot autoconfig that class).
See https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.html#setUseRegisteredSuffixPatternMatch-boolean-
Possibly you may need to turn off content negotiation as well - I can't remember exactly what Spring Boot default content negotiation is, but it might be affecting your case.
#Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false)
}
Worth noting that if you are working on a wider/existing application then both these configurations have possible implications more widely, so if that is the case then tread carefully!