Autowiring a bean with list of values in a property - spring-mvc

My Xml file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="filterBySlic" class="ca.ups.tundra.msg.FilterMessagesBySlic">
<property name="slicList">
<list><value>4196</value><value>1101</value><value>2795</value></list>
</property>
<property name="messageList">
<list><value>7762</value><value>7765</value><value>7766</value><value>7767</value><value>7768</value></list>
</property>
<property name="serviceLevelList">
<list><value>E1</value><value>E3</value><value>E4</value><value>29</value></list>
</property>
<property name="serviceTypeList">
<list><value>029</value><value>096</value></list>
</property>
</bean>
</beans>
this is what I am using in my class:
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring-pred-filter.xml"});
FilterMessagesBySlic filterConfig = (FilterMessagesBySlic)context.getBean("filterBySlic");
my condition to access the list of values;
filterConfig.getSiteList().contains(msgSlic)
which is working fine.
Instead I need to use #Autowired to access those list of values! Any suggestion

you can change your lists from being anonymous inner beans to normal beans and inject them in other beans like this:
xml configuration:
<util:list id="slicList" value-type="java.lang.String">
<value>4196</value>
<value>1101</value>
<value>2795</value>
</util:list>
injecting slicList in a bean:
public class Foo {
#Resource(name = "slicList")
List<String> messageList;
}
this implies of course that the instance of Foo is managed by spring.
is it what you are looking for?

Related

Spring RestTemplate failure with upper case element names

I have a simple Spring MVC application that makes an Ajax call to a ReST service using the RestTemplate class. Some of the elements in the schema start with uppercase letters. The 2 elements (code, message) with lowercase letters cause no problems. The classes generated by JAXB have the #XmlElement annotation and name property. This seems to be ignored. I've read that the JaxbAnnotationIntrospector needs to be used but none of the changes make that take effect. See class below. I've tried adding a bean class definition for RestTemplate in the Spring config, adding an object mapper but nothing helps. See error on OTPRO element in first few lines of stack trace:
[4/18/16 9:52:43:988 EDT] 00000024 SystemErr R org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized field "OTPRO" (class com.ssdr.rest.message.SSDRResponse), not marked as ignorable (7 known properties: "dt", "ot", "message", "otpro", "otphone", "code", "dtphone"])
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream#4ccbe679; line: 4, column: 14] (through reference chain: com.ssdr.rest.message.SSDRResponse["OTPRO"]); nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "OTPRO" (class com.ssdr.rest.message.SSDRResponse), not marked as ignorable (7 known properties: "dt", "ot", "message", "otpro", "otphone", "code", "dtphone"])
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream#4ccbe679; line: 4, column: 14] (through reference chain: com.ssdr.rest.message.SSDRResponse["OTPRO"])
[4/18/16 9:52:44:019 EDT] 00000024 SystemErr R at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readInternal(MappingJackson2HttpMessageConverter.java:126)
[4/18/16 9:52:44:019 EDT] 00000024 SystemErr R at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:153)
[4/18/16 9:52:44:019 EDT] 00000024 SystemErr R at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:81)
JAXB generated class:
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for documentResponse complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="documentResponse">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="code" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="message" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="OTPRO" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="OT" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="OTPhone" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="DT" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* <element name="DTPhone" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "documentResponse", propOrder = {
"code",
"message",
"otpro",
"ot",
"otPhone",
"dt",
"dtPhone"
})
public class DocumentResponse {
#XmlElement(required = true)
protected String code;
#XmlElement(required = true)
protected String message;
#XmlElement(name = "OTPRO", nillable = true)
protected String otpro;
#XmlElement(name = "OT", nillable = true)
protected String ot;
#XmlElement(name = "OTPhone", nillable = true)
protected String otPhone;
#XmlElement(name = "DT", nillable = true)
protected String dt;
#XmlElement(name = "DTPhone", nillable = true)
protected String dtPhone;
...
Service class:
SSDRResponse resp = null;
RestTemplate restTemplate = new RestTemplate();
HttpEntity<SSDRRequest> httpRequest = new HttpEntity<SSDRRequest>(req, createHeaders());
resp = restTemplate.postForObject(SERVICE_URI, httpRequest, SSDRResponse.class);
Spring config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<context:annotation-config />
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="com.ssdr" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven />
<!-- Forwards requests to the "/" resource to the "index" view -->
<!--
<mvc:view-controller path="/" view-name="index" />
-->
<!-- Make webapp/resources directory accessible to web app -->
<mvc:resources location="/resources/" mapping="/resources/**" />
<!-- Resolves view names to protected .jsp resources within the context root directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
<property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="annotationIntrospector">
<bean
class="com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector" />
</property>
</bean>
</property>
</bean>
</list>
</property>
</bean>
<!-- <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="prefixJson" value="true"/>
</bean>
</list>
</property>
</bean> -->
</beans>
NOTE: I do not want to simply ignore the upper case elements.
The solution was to use a combination of JacksonAnnotationIntrospector and JaxbAnnotationIntrospector. In this case Jackson was needed to recognize the #JsonIgnoreProperties and #JsonInclude annotations in the request. But Jackson always threw the "Unrecognized field" errors. JAXB could read the response with the uppercase fields but would not recognize the annotations on the request.
To use both introspectors the following code was added to the service class:
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
MappingJackson2HttpMessageConverter jaxMsgConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objMapper = new ObjectMapper();
/*
* Jackson introspector needed for #JsonIgnoreProperties and #JsonInclude annotations
* JAXB introspector is needed to handle the uppercase element names in the response
*/
AnnotationIntrospector primary = new JacksonAnnotationIntrospector();
AnnotationIntrospector secondary = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
AnnotationIntrospector pair = AnnotationIntrospector.pair(primary, secondary);
objMapper.setAnnotationIntrospector(pair);
jaxMsgConverter.setObjectMapper(objMapper);
messageConverters.add(jaxMsgConverter);
SSDRResponse resp = null;
RestTemplate restTemplate = new RestTemplate();
// Set message converter with Jackson and JAXB introspectors in RestTemplate
restTemplate.setMessageConverters(messageConverters);
HttpEntity<SSDRRequest> httpRequest = new HttpEntity<SSDRRequest>(req, createHeaders());
resp = restTemplate.postForObject(SERVICE_URI, httpRequest, SSDRResponse.class);
To use only the JAXB introspector:
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
MappingJackson2HttpMessageConverter jaxMsgConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper jaxMapper = new ObjectMapper();
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
jaxMapper.setAnnotationIntrospector(introspector);
jaxMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // ignore unknown properties
jaxMsgConverter.setObjectMapper(jaxMapper);
messageConverters.add(jaxMsgConverter);
My spring boot configuration (ready to use):
#Configuration
#EnableWebMvc
#EnableAutoConfiguration
#ComponentScan(basePackages = {"path.to.your.package"})
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Bean
public ObjectMapper objectMapper() {
ObjectMapper jacksonMapper = new ObjectMapper();
AnnotationIntrospector primary = new JacksonAnnotationIntrospector();
AnnotationIntrospector secondary = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
AnnotationIntrospector pair = AnnotationIntrospector.pair(primary, secondary);
jacksonMapper.setAnnotationIntrospector(pair);
jacksonMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
return jacksonMapper;
}
#Bean
public RestTemplate getRestTemplate() {
List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
MappingJackson2HttpMessageConverter jaxMsgConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = objectMapper();
jaxMsgConverter.setObjectMapper(objectMapper);
messageConverters.add(jaxMsgConverter);
HttpClientBuilder builder = HttpClientBuilder.create();
HttpClient httpClient = builder.build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate template = new RestTemplate(new BufferingClientHttpRequestFactory(factory));
template.setMessageConverters(messageConverters);
return template;
}
}

Spring MVC Converters doesn't work at all

I'm very new to Spring MVC and Java EE at all (I came from PHP+Zend2). My english is poor too. I use NetBeans.
My problem is that my custom converter does not work. Here's some code:
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean id="universalDAO" class="dao.UniversalDAO"/>
<bean id="sessionManager" class="utils.SessionManager"/>
<bean id="idToEntityConverterFactory" class="utils.IdToEntityConverterFactory">
<property name="dao" ref="universalDAO"/>
</bean>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<ref bean="idToEntityConverterFactory" />
<bean id="temp" class="utils.TempConverter" />
</list>
</property>
</bean>
<bean name="universalService" class="service.UniversalService">
<property name="universalDAO" ref="universalDAO"/>
</bean>
<bean name="sessionApplicationService" class="service.SessionApplicationService">
<property name="universalDAO" ref="universalDAO"/>
<property name="sessionManager" ref="sessionManager"/>
</bean>
<bean name="systemUserApplicationService" class="service.SystemUserApplicationService">
<property name="universalDAO" ref="universalDAO"/>
</bean>
<aop:aspectj-autoproxy />
<bean id="loggerAspect" class="aspect.LoggerAspect"/>
</beans>
I also have tried version with:
class="org.springframework.format.support.FormattingConversionServiceFactoryBean"
IdToEntityConverterFactory is a ConverterFactory created with this tutorial but it is not important now. I wrote simpler one not to do mess.
TempConverter.java
package utils;
import entity.Role;
import org.springframework.core.convert.converter.Converter;
public class TempConverter implements Converter<String, Role> {
#Override
public Role convert(String id) {
return new Role();
}
}
Here is .jsp fragment:
<form:select path="${names[item.index]}" items="${valueOptions[names[item.index]]}" />
When I submit the form there appears an error:
Failed to convert property value of type java.lang.String[] to required type java.util.List for property roleList; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [entity.Role] for property roleList[0]: no matching editors or conversion strategy found
I found solution to similar problem here . It has something to do with
<mvc:annotation-driven>
but I don't use such tag anywhere in my application (should I?).
My question is how to make any converter work while binding form data to Java object.
EDIT:
I figured out some workaround. I have overriden initBinder method in my Controller:
#Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
binder.setConversionService(conversionService);
}
conversionService had to be previously set in Controller of course:
private ConversionService conversionService;
//...
public void setConversionService(ConversionService conversionService) {
this.conversionService = conversionService;
}
dispatcher-servlet.xml:
<bean class="controller.SystemUserFormController" p:applicationService-ref="systemUserApplicationService" p:sessionManager-ref="sessionManager" p:conversionService-ref="conversionService" />
It works now but it is kind of inconvenience because:
I have to add extra code p:conversionService-ref="conversionService" in every Controller I need converter to be used.
It works out-of-the-box in every toutorial I found on the internet but not for me. I am just curious what am I doing different.
Kindest regards!
Your questions:
I have to add extra code p:conversionService-ref="conversionService" in every Controller I need converter to be used.
You can use #Autowired to inject ConversionService.
You can implement common parent class for your controllers with #InitBinder
You can use abstract parent bean definition <bean abstract="true" ...>
It works out-of-the-box in every toutorial I found on the internet but not for me. I am just curious what am I doing different.
Just use <mvc:annotation-driven>. This easy-to-use configuration is there so that you don't need to configure stuff manually.
How to do it
You can implement WebBindingInitializer. This bean needs to be set up on handler adapter.
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer" ref="yourBindingInitializer" />
</bean>
However this approach is kind of painful if you are not already defining hanlder adapter yourself. When you define this bean it disables some DispatcherServlet's default behavior. So you might need to do a bit more than to define this bean.
Off-topic advice
Problem with Spring is that the internet is full of obsolete tutorials. Please use the official guide and reference app. Start using namespace (or even Java) config, autowiring, #Controller components and #RequestMapping.
I belive there is not such think as mvc:annotation-config. There are 2 other things:
context:annotation-config
mvc:annotation-driven
Please tell me if I am wrong
I have tried both and both doesn't work. Here's what what have I done:
Removed p:conversionService-ref="conversionService" from my Controller bean
Added #Autowired annotation to my setter
#Autowired
public void setConversionService(ConversionService conversionService) {
this.conversionService = conversionService;
}
Added context:annotation-config/ (or mvc:annotation-driven/) to applicationContext.xml
Unfortunately setter has never been executed!
My source is here
Quote: "When Spring finds an #Autowired annotation used with setter methods, it tries to perform byType autowiring on the method."
I also have tried using setter with exactly the same type as bean class - still nothing.

Errors using Spring 4.1 #RestController

I'm trying to return JSON when using the #RestController. I'm using Spring 4.1.
Here's the exception I'm getting when calling listrestsites.html using a GET request.
I have the fasterxml Jackson core and databind jars in my build path.
Output of the accept from #requestheader = accept: application/json, text/javascript, /; q=0.01
Any help is appreciated. Thank you,
[DEBUG,ExceptionHandlerExceptionResolver] Resolving exception from
handler [public java.util.List
com.amci.spring3.controller.SitesRestController.listRestSites(java.lang.String)]:
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not
find acceptable representation [DEBUG,DefaultListableBeanFactory]
Returning cached instance of singleton bean
'exceptionControllerAdvice' [DEBUG,ExceptionHandlerExceptionResolver]
Invoking #ExceptionHandler method: public
org.springframework.web.servlet.ModelAndView
Here's my Restcontroller class:
#RestController
public class SitesRestController {
#Autowired
private AssetService assetService;
#RequestMapping("/listrestsites.html")
public List<Asset> listRestSites(#RequestHeader(value="accept") String accept) {
System.out.println(getLogLevel());
System.out.println("accept: " + accept);
return assetService.findAssets();
}
}
Also, snippet from my spring.xml:
<property name="defaultViews">
<list>
<!-- JSON View -->
<bean
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
</bean>
Please make sure that you have the following in your Spring xml file:
<context:annotation-config/>
<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>
and all items of your POJO should have getters/setters. Hope it helps
Credit answer to this question

runscript executed multiple times for #Autowired jdbcTemplate and h2 in-memory database

I've inherited a project and am trying to get a set of integration tests running against an in-memory h2 database. In order for them to pass some tables, relationships and reference data needs creating.
I can see the problem in that the script referenced in RUNSCRIPT is being executed multiple times and therefore generating Index "XXX_IDX" already exists errors and other violations. So is there a way to force the script to only be run once or do I need a external database? It seems that the script is run on every connection which I assume is by design.
properties file
my.datasource.url=jdbc:h2:mem:my_db;DB_CLOSE_DELAY=-1;MODE=Oracle;MVCC=TRUE;INIT=RUNSCRIPT FROM 'classpath:/create-tables-and-ref-data.sql'
XML config
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url" value="${my.datasource.url}"/>
<!-- other properties for username, password etc... -->
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="myDataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
many Java classes in the following pattern
#Component
public class SomethingDAOImpl implements SomethingDAO {
#Autowired
public SomethingDAOImpl(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
#Component
public class SomethingElseDAOImpl implements SomethingElseDAO {
#Autowired
public SomethingElseDAOImpl(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
With the default bean scope being singleton I thought this would just work, but I guess i'm missing something. Also, if I switch to an real Oracle instance that already has the tables and reference data set-up, the tests all pass.
In many cases, it is possible to write the SQL script so that no exceptions are thrown:
create table if not exists test(id int, name varchar(255));
create index if not exists test_idx on test(name);
I ended up using an alternative approach, as I could not write the SQL in a way that could be reapplied without error.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd">
<jdbc:initialize-database data-source="myDataSource" enabled="true" ignore-failures="ALL">
<jdbc:script location="classpath:create-and-alter-tables-first-then-add-test-data.sql" />
</jdbc:initialize-database>
</beans>
which is executed once at context initialization.
Note: other namespaces and beans omitted for brevity.

How do I restrict route extensions in #RequestMapping paths for Spring MVC controllers?

I have a fairly simple task that I want to accomplish, but can't seem to find information for Spring MVC routing about it. I have a very simple controller that routes a path to a view:
#Controller
#RequestMapping(value = "/help")
public class HelpController {
private static final String HELP = "help";
#RequestMapping(method = RequestMethod.GET)
public String help(Model model, Locale locale) {
model.addAttribute("locale", locale);
return HELP;
}
}
I would like to throw a 404 if http://mysite.com/help.some.extension.is.entered, but Spring seems to resolve the example to /help. The javadoc says that the #RequestMapping annotation is just a servlet URI mapping, but I thought /help means it needs to be an exact match. Any clarification would be appreciated.
For Spring 4 it's pretty easy to solve:
<mvc:annotation-driven>
<mvc:path-matching suffix-pattern="false" />
</mvc:annotation-driven>
So you still can use mvc:annotation-driven for your config.
You can mention it in the #RequestMapping annotation
it is same as Servlet URL pattern only.
#Controller
public class HelpController {
private static final String HELP = "help";
#RequestMapping(value = "/help" method = RequestMethod.GET)
public String help(Model model, Locale locale) {
model.addAttribute("locale", locale);
return HELP;
}
#RequestMapping(value = "help/*" method = RequestMethod.GET)
public String helpWithExtraWords() {
return "error";
}
}
The best way I can think of is to configure your RequestMappingHandlerMapping explicitly to not consider suffixpaths, this way:
<bean name="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="useSuffixPatternMatch" value="false"></property>
</bean>
However, if you have configured your Spring MVC using mvc:annotation-driven, this will not work, you will have to expand out the entire handlerAdapter definition, which is not that difficult to do, along these lines(this is not complete, you can look through org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser for the entire definition):
<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>
<property name="validator">
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
</property>
</bean>
</property>
<property name="messageConverters">
<list>
<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>
</list>
</property>
</bean>
<bean name="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="useSuffixPatternMatch" value="false"></property>
</bean>
With Spring 3.0.X You can use the useDefaultSuffixPattern property.
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="useDefaultSuffixPattern" value="false" />
</bean>
You will need to remove </mvc:annotation-driven>
Refer URL Pattern Restricting in SPRING MVC

Resources