Spring causes incorrect controller mapping

I am creating a very simple mvc application using Spring. It has one controller, which should trigger an on-demand scan. The problem is that if I define the mapping in web.xml, it stops finding the correct controller, but when I change the context of the Spring servlet application, creating new bindings on the fly, but this time the check based on the annotation is ignored. How can I manage mappings in web.xml while still resorting to annotation-based validation?

Here are the details:

Controller:

@Controller @RequestMapping("/api") public class UserActionsController { @RequestMapping(value="/choice", method = RequestMethod.POST) public @ResponseBody NameValue addUserChoice(@Valid @RequestBody NameValue action) { return action; } } 

This is the context of the servlet application:

 <mvc:annotation-driven/> <context:component-scan base-package="com.my.package" /> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> </map> </property> <property name="defaultContentType" value="application/json" /> <property name="defaultViews"> <list> <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> </list> </property> </bean> 

Web XML:

 <servlet> <servlet-name>action-api</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action-api</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> 

The configuration above works. The problem starts when I try to change web.xml, so the controller will only be responsible for "/ api / *". I change it to <url-pattern>/api/*</url-pattern> . In this case, Spring cannot find the correct controller.

 (DispatcherServlet:819) - DispatcherServlet with name 'action-api' processing POST request for [/api/choice] (RequestMappingHandlerMapping:209) - Looking up handler method for path /choice (RequestMappingHandlerMapping:219) - Did not find handler method for [/choice] (PageNotFound:1080) - No mapping found for HTTP request with URI [/api/choice] in DispatcherServlet with name 'action-api' (DispatcherServlet:913) - Successfully completed request 

Changing the context of the servlet application helps Spring can now find the controller, but validation is no longer called.

 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="alwaysUseFullPath" value="true" /> <property name="messageConverters"> <util:list id="beanList"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"/> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> </util:list> </property> </bean> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="alwaysUseFullPath" value="true" /> </bean> <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="alwaysUseFullPath" value="true" /> </bean> 

Here is the log:

 (DispatcherServlet:819) - DispatcherServlet with name 'action-api' processing POST request for [/api/choice] (RequestMappingHandlerMapping:209) - Looking up handler method for path /choice (RequestMappingHandlerMapping:219) - Did not find handler method for [/choice] (DefaultAnnotationHandlerMapping:124) - Mapping [/api/choice] to HandlerExecutionChain with handler [ com.my.package.controller.UserActionsController@1f86dbd ] and 1 interceptor (HandlerMethodInvoker:638) - Reading [com.my.package.model.NameValue] as "application/json" using [org.springf ramework.http.converter.json.MappingJacksonHttpMessageConverter@ 2059ef] (HandlerMethodInvoker:173) - Invoking request handler method: public com.my.package.model.NameValue com.citypath.dima.controller.UserActionsController.addUserChoice(com.my.package.model.NameValue) (AnnotationMethodHandlerAdapter:1037) - Written [ com.my.package.model.NameValue@166685b ] as "application/json;charset=UTF-8" using [org.springf ramework.http.converter.json.MappingJacksonHttpMessageConverter@ 2059ef] (DispatcherServlet:957) - Null ModelAndView returned to DispatcherServlet with name 'action-api': assuming HandlerAdapter completed request handling (DispatcherServlet:913) - Successfully completed request 

It looks like Spring is doing the binding on the fly, but this time the validators are ignored. I need to have 2 controllers, say '/ api' and '/ something'. How to define it in web.xml so that Spring can find them and trigger validation?

Thanks.

+5
source share
3 answers

Spring @Controllers URLs are always interpreted relative to the Spring Dispatcher Servlet servlet that handles them. Therefore, if you map the dispatcher servlet to / api / * in web.xml, then the URL of your controller is higher than / api / api / choice

So you can configure two Spring dispatcher servlets in the web.xml file mapped to / api in web.xml and one mapped to / somethingelse in web.xml, then you can just remove / api from @RequestMappings

In my application, I use the same dispatch servlet for api and UI, and I use the public static final String, called the URL, in my various API controllers to create paths to the various open API resources. Below is an example of my API.

 @Controller @RequestMapping(CompanyPermissionsResourceController.PATH) public class CompanyPermissionsResourceController extends BaseApiController { public static final String PATH = CompanyResourceController.PATH + "/permissions"; 
+7
source

Are you sure you are making a post request to /api/choice ?

 @RequestMapping(value="/choice", method = RequestMethod.POST) 

Try to change

 @RequestMapping(value="/choice", method = RequestMethod.GET) public @ResponseBody NameValue addUserChoice(@Valid @RequestBody NameValue action) { return action; } 
+1
source

I don’t think it works like that. Put the whole path /api/choice at the method level.

-1
source

Source: https://habr.com/ru/post/972916/


All Articles