What is the relation between #RequestMapping and Locale in Spring Boot? - java

If my understanding is correct, you can add/remove params for saveEmployee() freely. For example, when you add "loc" as follows, saveEmployee() receives the "non-null object" when the event happens. And the same goes for queryParams.
#Controller
public class Employee {
#RequestMapping("/save")
public void saveEmployee(Locale loc,
#RequestParam Map<String, String> queryParams) {
// saving employee
}
}
How could this method receive non-null Locale object by just adding a param "loc" here?
I would like to know the logic behind this.

Spring does it for you by using LocaleResolver or LocaleContextResolver, for the current request locale, determined by the most specific locale resolver available, in effect, the configured LocaleResolver / LocaleContextResolver in an MVC environment.
21.3.3 Defining #RequestMapping handler methods
An #RequestMapping handler method can have a very flexible signatures. The supported method arguments and return values are described in the following section. Most arguments can be used in arbitrary order with the only exception of BindingResult arguments.
Supported method argument types
java.util.Locale for the current request locale, determined by the most specific locale resolver available, in effect, the configured LocaleResolver / LocaleContextResolver in an MVC environment.

Spring's DispatcherServlet which forwards request from client to your controller gives you that parameters. In order to do that, it search the object from ApplicationContext to which bean(Controller) belongs.

Spring looks at the method arguments, their types and annotations, then determines if it can provide an object of that type/annotation.
If it cannot, it'll throw an exception, otherwise it will call the method with the object it decided fits the type/annotation.
For the list of supported types/annotations, read the documentation:
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-arguments
As you can see, java.util.Locale is listed.

I think you need xml setting for your locale
Do you want to try the followning xml setting
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
<mvc:interceptors>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="language" />
</bean>
</mvc:interceptors>

Related

Spring Integration - Invoking Methods in Application Code

I have a outbound-channel-adapter, where the relevant configuration is shown below.
<int:outbound-channel-adapter channel="foo-fileChannel" ref="foo-handlerTarget" method="handleFeedFile">
<int:poller fixed-delay="5000" receive-timeout="1000" max-messages-per-poll="10" />
</int:outbound-channel-adapter>
<int:channel id="foo-fileChannel">
<int:queue />
</int:channel>
<bean id="foo-handlerTarget" class="com.abc.FooFeedHandlerImpl">
<property name="fooDescriptorFile" value="${feed.foo.fooDescriptorFile}" />
<property name="fileIdRegex" ref="foo-fileRegex" />
<property name="processId" value="${feed.processId}" />
<property name="workingLocation" value="${feed.foo.workingLocation}" />
<property name="remoteLocation" value="${feed.foo.remoteLocation}" />
<property name="stalenessThreshold" value="${feed.foo.stalenessThreshold}" />
</bean>
And in FooFeedHandlerImpl...
public void handleFeedFile(File retrievedFile) {
handleFeedFile(retrievedFile, null);
}
public void handleFeedFile(File retrievedFile, String processKey) {
if (isHandlerForFileName(retrievedFile.getName())) {
processFeed(retrievedFile, processKey);
}
}
Questions:
Which handleFeedFile method gets invoked by the channel adapter?
When I invoke a method in the application code using Spring integration, how are the method parameters determined?
Thanks for any help!
Edit:
I ran my process locally (downloaded a local SFTP server - http://www.coreftp.com/server/index.html) and determined that the handleFeedFile(File file) method was invoked.
You probably want to refer to F.6 Message Mapping rules and conventions.
Multiple parameters could create a lot of ambiguity with regards to determining the appropriate mappings. The general advice is to annotate your method parameters with #Payload and/or #Header/#Headers Below are some of the examples of ambiguous conditions which result in an Exception being raised.
and:
Multiple methods:
Message Handlers with multiple methods are mapped based on the same rules that are described above, however some scenarios might still look confusing.
If you're not in a position to annotate your target methods, then you might be able to use a SpEL expression to call your intended method:
3.3.2 Configuring An Outbound Channel Adapter
Like many other Spring Integration components, the and also provide support for SpEL expression evaluation. To use SpEL, provide the expression string via the 'expression' attribute instead of providing the 'ref' and 'method' attributes that are used for method-invocation on a bean. When an Expression is evaluated, it follows the same contract as method-invocation where: the expression for an will generate a message anytime the evaluation result is a non-null value, while the expression for an must be the equivalent of a void returning method invocation.
According to the documentation on Spring integration, the POJO (bean foo-handlerTarget) in your case will get called with a Message object containing the payload. Have you executed your code? I'd expect it generates a NoSuchMethodError.
You need a
public void handleFeedFile(Message<?> message);
method.

localeChangeInterceptor does not work

I have very standard configuration, I kept editing many times, checked other questions on SO but by my final configuration most people had their issues resolved, however no result for me. Whenever firing requests like:
http://localhost:8080/appName/?lang=es_MX
or
http://localhost:8080/appName?lang=es_MX it does not resolve to correct locale, it does just do nothing.
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages" />
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"></bean>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
</mvc:interceptors>
I know that default locale resolver by headers work so is my messageResource and .jsp configuration is correct, since I set up one browser explicitly to have es_MX locale and it resolves with AcceptHeaderLocaleResolver correctly.
Does it have to do with the way my handler mappings are defined?
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home( Model model, Locale locale, HttpServletRequest hr) {
String header = hr.getHeader("User-Agent");
model.addAttribute("header", header);
String contextPath = hr.getContextPath();
model.addAttribute("contextPath", contextPath);
return "index";
}
God I spent so much time on this...please help
I solved it by placing interceptor into servlet-context.xml instead of my other config. Now trying to figure it out why in servlet-context.xml it works and in my dedicated config it doesn't, your insights would be valuable ! :-) I am not accepting my answer, since it does not explain why. Please explain me why this is the case(and so I could test it - ideally resulting in interceptor being placed in my custom config).
For anyone in trouble try this:
<interceptors>
<beans:bean
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
p:paramName="lang" />
</interceptors>
inside your servlet-context.xml
needs namespace:
xmlns:p="http://www.springframework.org/schema/p"
SessionLocaleResolver seems not to care about location and works in my custom config location too.
Check the API docs -> http://static.springsource.org/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/servlet/i18n/SessionLocaleResolver.html
Also the source of the resolveLocale method of SessionLocaleResolver:
public Locale resolveLocale(HttpServletRequest request) {
Locale locale = (Locale) WebUtils.getSessionAttribute(request, LOCALE_SESSION_ATTRIBUTE_NAME);
if (locale == null) {
locale = determineDefaultLocale(request);
}
return locale;
}
It will in turn get the Locale from the request:
protected Locale determineDefaultLocale(HttpServletRequest request) {
Locale defaultLocale = getDefaultLocale();
if (defaultLocale == null) {
defaultLocale = request.getLocale();
}
return defaultLocale;
}
And in the docs for the ServletRequest.getLocale method:
Returns the preferred Locale that the client will accept content in,
based on the Accept-Language header. If the client request doesn't
provide an Accept-Language header, this method returns the default
locale for the server. Returns: the preferred Locale for the client
It seems you need to change locale by updating the correct session attribute, which is the job of the LocaleChangeInterceptor.
Maybe something is wrong with the interceptor then. Does it set the locale into the correct LocaleResolver? Can you post the whole spring configuration? Is the mvc namespace correct?
There is a complete i18n tutorial here -> http://www.mkyong.com/spring-mvc/spring-mvc-internationalization-example/

Spring MappingJacksonJsonView, how to tell to use it instead of JSP view?

I'm trying to use MappingJacksonJsonView with Spring 3.0, without success. I don't know what I'm doing wrong, I think the problem is that I don't know how to tell to use the MappingJacksonJsonView to render a request. I tried to use the same name for view name and bean name of MappingJacksonView, but didn't work. I built a sample test application here: https://github.com/stivlo/restjson
In web.xml I've defined ContextLoaderListener and the mapping for dispatcherServlet.
In servlet-context.xml I've added
<mvc:annotation-driven/>
and
<bean name="jsonView"
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
In org.obliquid.restjson.web.ToDoList.java I set the logical view name as jsonView.
However, instead of using MappingJacksonJsonView, it looks for a JSP file, according to my JSP mapping.
message /restjson/WEB-INF/jsp/jsonView.jsp
description The requested resource (/restjson/WEB-INF/jsp/jsonView.jsp)
is not available.
What should I change to use MappingJacksonJsonView as a renderer?
UPDATE 1: In following tests I've found that if I add the following to my servlet-context.xml, JSON rendering works, but my other view, rendered as JSP (home) is not working anymore.
<!-- Resolve views based on string names -->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
UPDATE 2: I removed the BeanNameViewResolver and changed my ToDoList.java to return directly the Collection to be converted in JSON, instead of ModelAndView, with a #ResponseBody annotation, as follows:
#RequestMapping("/toDoList")
public #ResponseBody List<ToDoItem> test() {
List<ToDoItem> toDoList = new ArrayList<ToDoItem>();
toDoList.add(new ToDoItem(1, "First thing, first"));
toDoList.add(new ToDoItem(1, "After that, do the second task"));
return toDoList;
}
In this way it works. Even though the mapping is even more "magical". It makes me wonder, if a similar renderer exists for XML for instance, how does Spring know which renderer to pick?
Spring will use Accept header sent by the client to return most appropriate view. Here you will find my complete Spring MVC application that returns both JSON and XML.
As you can see, I only needed:
<mvc:annotation-driven />
I also used the same annotations: #RequestMapping to map request to a method and #ResponseBody to tell Spring that what I am returning from the controller is the actual response. It might however need some tweaking/formatting, and here Spring takes care of marshalling your object into most appropriate type like JSON.
You should do it this way:
In your xml file set the following: set
<mvc:annotation-driven />
After it you need to set Jackson serializer:
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
after it you can use it in your Controller:
#RequestMapping(value="/getObjects",method = RequestMethod.POST)
#ResponseBody
public List<MyObject> getCategories(){
List<MyObject> objects = daoService.gettAllObjects();
return objects;
}
Adding the following worked in my case
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="0" />
</bean>
So basically we should try to resolve any view as a bean first
you will need to see ContentNegotiatingViewResolver,and set defaultviews property to MappingJacksonJsonView, and #ResponseBody uses HttpMessageConverter to instead of ViewSolver,see the differences between them
http://ufasoli.blogspot.com/2013/08/viewresolver-vs-messageconverter-spring.html

Spring Config file consisting of List of Implementations

I Am very new to Spring. I have an Interface (MessageHandler ) which has a get method, this method returns a list of Implementations of another interface (messageChecker).
public interface MessageHandler {
public void process(BufferedReader br);
public void setMessageCheckerList(List mcList);
[B]public List getMessageCheckerList();[/B]
}
In my Spring XML configuration , i have something like this ,along with other beans
<bean id="messageHandler" class="com.XXX.messagereceiver.MessageHandlerImpl">
<property name="messageCheckerList" ref="checkerList"/>
</bean>
<bean id="checkerList" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="HL7Checker"/>
</list>
</constructor-arg>
</bean>
<bean id="HL7Checker" class="com.XXX.messagereceiver.HL7CheckerImpl">
<property name="messageExecutor" ref="kahootzExecutor"/>
</bean>
Here i am passing a checkerlist - which is a list of Implementations ( For now i have only 1) of the Interface (messageChecker)
Checkerlist is containing references to Bean Id's which are actual implementaions.
HL7Checker is an implementation of an Interface messageChecker.
But when i run the main program, When i inject the bean "messageHandler" and call the getMessageCheckerList, It returns a null value. These getter and setter methods are working fine without using spring.
I am not sure what seems to be the problem.
I don't know the answer for you troubles, but I would check:
is the setter setMessageCheckerList(List) in messageHandler bean called? (either using some debugger or some trace output like System.out...). If it's not, there's probably something wrong with your Spring XML configuration setup. The bean definition you posted requires the property to be set and Spring wouldn't create the messageHandler bean without setting the property.
who calls the setMessageCheckerList(List) setter? Or even more precise, what code writes to the field which stores the value of the property? Maybe the field is initialized properly by Spring but gets overwritten to null later on?
are you sure you call the getMessageCheckerList on the very same object Spring has configured for you (that is, the messageHandler bean). The definition you have posted clearly states an instance of MessageHandlerImpl is created by Spring, but it doesn't prevent other instances to be created in other ways. So maybe the instance created by Spring holds the proper value, but you run the get... on a wrong instance?

Spring MVC #PathVariable getting truncated

I have a controller that provides RESTful access to information:
#RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
public ModelAndView getBlah(#PathVariable String blahName, HttpServletRequest request,
HttpServletResponse response) {
The problem I am experiencing is that if I hit the server with a path variable with special characters it gets truncated. For example:
http://localhost:8080/blah-server/blah/get/blah2010.08.19-02:25:47
The parameter blahName will be blah2010.08
However, the call to request.getRequestURI() contains all the information passed in.
Any idea how to prevent Spring from truncating the #PathVariable?
Try a regular expression for the #RequestMapping argument:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}")
This is probably closely related to SPR-6164. Briefly, the framework tries to apply some smarts to the URI interpretation, removing what it thinks are file extensions. This would have the effect of turning blah2010.08.19-02:25:47 into blah2010.08, since it thinks the .19-02:25:47 is a file extension.
As described in the linked issue, you can disable this behaviour by declaring your own DefaultAnnotationHandlerMapping bean in the app context, and setting its useDefaultSuffixPattern property to false. This will override the default behaviour, and stop it molesting your data.
Spring considers that anything behind the last dot is a file extension such as .jsonor .xml and truncate it to retrieve your parameter.
So if you have /{blahName}:
/param, /param.json, /param.xml or /param.anything will result in a param with value param
/param.value.json, /param.value.xml or /param.value.anything will result in a param with value param.value
If you change your mapping to /{blahName:.+} as suggested, any dot, including the last one, will be considered as part of your parameter:
/param will result in a param with value param
/param.json will result in a param with value param.json
/param.xml will result in a param with value param.xml
/param.anything will result in a param with value param.anything
/param.value.json will result in a param with value param.value.json
...
If you don't care of extension recognition, you can disable it by overriding mvc:annotation-driven automagic:
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
<property name="useSuffixPatternMatch" value="false"/>
</bean>
So, again, if you have /{blahName}:
/param, /param.json, /param.xml or /param.anything will result in a param with value param
/param.value.json, /param.value.xml or /param.value.anything will result in a param with value param.value
Note: the difference from the default config is visible only if you have a mapping like /something.{blahName}. See Resthub project issue.
If you want to keep extension management, since Spring 3.2 you can also set the useRegisteredSuffixPatternMatch property of RequestMappingHandlerMapping bean in order to keep suffixPattern recognition activated but limited to registered extension.
Here you define only json and xml extensions:
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
<property name="useRegisteredSuffixPatternMatch" value="true"/>
</bean>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false"/>
<property name="favorParameter" value="true"/>
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>
Note that mvc:annotation-driven accepts now a contentNegotiation option to provide a custom bean but the property of RequestMappingHandlerMapping has to be changed to true (default false) (cf. https://jira.springsource.org/browse/SPR-7632).
For that reason, you still have to override all the mvc:annotation-driven configuration. I opened a ticket to Spring to ask for a custom RequestMappingHandlerMapping: https://jira.springsource.org/browse/SPR-11253. Please vote if you are interested in.
While overriding, be careful to consider also custom Execution management overriding. Otherwise, all your custom Exception mappings will fail. You will have to reuse messageCoverters with a list bean:
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
<util:list id="messageConverters">
<bean class="your.custom.message.converter.IfAny"></bean>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</util:list>
<bean name="exceptionHandlerExceptionResolver"
class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
<property name="order" value="0"/>
<property name="messageConverters" ref="messageConverters"/>
</bean>
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService" />
<property name="validator" ref="validator" />
</bean>
</property>
<property name="messageConverters" ref="messageConverters"/>
</bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
</bean>
I implemented, in the open source project Resthub that I am part of, a set of tests on these subjects: see https://github.com/resthub/resthub-spring-stack/pull/219/files and https://github.com/resthub/resthub-spring-stack/issues/217
Everything after the last dot is interpreted as file extension and cut off by default.
In your spring config xml you can add DefaultAnnotationHandlerMapping and set useDefaultSuffixPattern to false (default is true).
So open your spring xml mvc-config.xml (or however it is called) and add
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="useDefaultSuffixPattern" value="false" />
</bean>
Now your #PathVariable blahName (and all other, too) should contain the full name including all dots.
EDIT: Here is a link to the spring api
Using the correct Java configuration class :
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter
{
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer)
{
configurer.favorPathExtension(false);
}
#Override
public void configurePathMatch(PathMatchConfigurer configurer)
{
configurer.setUseSuffixPatternMatch(false);
}
}
I also ran into the same issue, and setting the property to false didn't help me either. However, the API says:
Note that paths which include a ".xxx" suffix or end with "/" already
will not be transformed using the default suffix pattern in any case.
I tried adding "/end" to my RESTful URL, and the problem went away. I'm not please with the solution, but it did work.
BTW, I don't know what the Spring designers were thinking when they added this "feature" and then turned it on by default. IMHO, it should be removed.
I resolved by this hack
1) Added HttpServletRequest in #PathVariable like below
#PathVariable("requestParam") String requestParam, HttpServletRequest request) throws Exception {
2) Get the URL directly (At this level no truncation) in the request
request.getPathInfo()
Spring MVC #PathVariable with dot (.) is getting truncated
adding the ":.+" worked for me, but not until I removed outer curly brackets.
value = {"/username/{id:.+}"} didn't work
value = "/username/{id:.+}" works
Hope I helped someone :]
I just ran into this and the solutions here didn't generally work as I expected.
I suggest using a SpEL expression and multiple mappings, e.g.
#RequestMapping(method = RequestMethod.GET,
value = {Routes.BLAH_GET + "/{blahName:.+}",
Routes.BLAH_GET + "/{blahName}/"})
The file extension problem only exists if the parameter is in the last part of the URL. Change
#RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
to
#RequestMapping(
method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/safe")
and all will be well again-
If you can edit the address that requests are sent to, simple fix would be to add a trailing slash to them (and also in the #RequestMapping value):
/path/{variable}/
so the mapping would look like:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/")
See also Spring MVC #PathVariable with dot (.) is getting truncated.
//in your xml dispatcher add this property to your default annotation mapper bean as follow
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="alwaysUseFullPath" value="true"></property>
</bean>
The problem that you are facing is due to spring interpreting the last part of the uri after the dot (.) as a file extension like .json or .xml . So when spring tries to resolve the path variable it simply truncates the rest of the data after it encounters a dot (.) at the end of the uri.
Note: also this happens only if you keep the path variable at the end of the uri.
For example consider uri : https://localhost/example/gallery.df/link.ar
#RestController
public class CustomController {
#GetMapping("/example/{firstValue}/{secondValue}")
public void example(#PathVariable("firstValue") String firstValue,
#PathVariable("secondValue") String secondValue) {
// ...
}
}
In the above url firstValue = "gallery.df" and secondValue="link" , the last bit after the . gets truncated when the path variable gets interpreted.
So, to prevent this there is two possible ways:
1.) Using a regexp mapping
Use a regex at the end part of mapping
#GetMapping("/example/{firstValue}/{secondValue:.+}")
public void example(
#PathVariable("firstValue") String firstValue,
#PathVariable("secondValue") String secondValue) {
//...
}
By using + , we indicate any value after the dot will also be part of the path variable.
2.) Adding a slash at the end of our #PathVariable
#GetMapping("/example/{firstValue}/{secondValue}/")
public void example(
#PathVariable("firstValue") String firstValue,
#PathVariable("secondValue") String secondValue) {
//...
}
This will enclose our second variable protecting it from Spring’s default behavior.
3) By overriding Spring's default webmvc configuration
Spring provides ways to override the default configurations that gets imported by using the annotations #EnableWebMvc.We can customize the Spring MVC configuration by declaring our own DefaultAnnotationHandlerMapping bean in the application context and setting its useDefaultSuffixPattern property to false.
Example:
#Configuration
public class CustomWebConfiguration extends WebMvcConfigurationSupport {
#Bean
public RequestMappingHandlerMapping
requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping
= super.requestMappingHandlerMapping();
handlerMapping.setUseSuffixPatternMatch(false);
return handlerMapping;
}
}
Keep in mind that overriding this default configuration, affects all urls.
Note : here we are extending the WebMvcConfigurationSupport class to override the default methods. There is one more way to override the deault configurations by implementing the WebMvcConfigurer interface.
For more details on this read : https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html
Java based configuration solution to prevent truncation (using a not-deprecated class):
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
#Configuration
public class PolRepWebConfig extends WebMvcConfigurationSupport {
#Override
#Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
final RequestMappingHandlerMapping handlerMapping = super
.requestMappingHandlerMapping();
// disable the truncation after .
handlerMapping.setUseSuffixPatternMatch(false);
// disable the truncation after ;
handlerMapping.setRemoveSemicolonContent(false);
return handlerMapping;
}
}
Source: http://www.javacodegeeks.com/2013/01/spring-mvc-customizing-requestmappinghandlermapping.html
UPDATE:
I realized having some problems with Spring Boot auto-configuration when I used the approach above (some auto-configuration doesn't get effective).
Instead, I started to use the BeanPostProcessor approach. It seemed to be working better.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
private static final Logger logger = LoggerFactory
.getLogger(MyBeanPostProcessor.class);
#Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof RequestMappingHandlerMapping) {
setRemoveSemicolonContent((RequestMappingHandlerMapping) bean,
beanName);
setUseSuffixPatternMatch((RequestMappingHandlerMapping) bean,
beanName);
}
return bean;
}
private void setRemoveSemicolonContent(
RequestMappingHandlerMapping requestMappingHandlerMapping,
String beanName) {
logger.info(
"Setting 'RemoveSemicolonContent' on 'RequestMappingHandlerMapping'-bean to false. Bean name: {}",
beanName);
requestMappingHandlerMapping.setRemoveSemicolonContent(false);
}
private void setUseSuffixPatternMatch(
RequestMappingHandlerMapping requestMappingHandlerMapping,
String beanName) {
logger.info(
"Setting 'UseSuffixPatternMatch' on 'RequestMappingHandlerMapping'-bean to false. Bean name: {}",
beanName);
requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
}
}
Inspired from: http://ronaldxq.blogspot.com/2014/10/spring-mvc-setting-alwaysusefullpath-on.html
if you are sure that your text will not match any of default extensions you can use below code:
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseRegisteredSuffixPatternMatch(true);
}
}
My preferable solution to prevent the Spring MVC #PathVariable to get truncated is to add trailing slash at the end of the path variable.
For example:
#RequestMapping(value ="/email/{email}/")
So, the request will look like:
http://localhost:8080/api/email/test#test.com/

Categories