Spring request mapping: Matching with url pattern - spring

I have a web application with Spring MVC.
web.xml
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
<url-pattern>/companies/*</url-pattern>
</servlet-mapping>
spring controller method:
class RealmInfoController{
#ResponseBody
#RequestMapping(value = {"/companies/{companyId}/realms/{realmName}"})
public RealmInfo realmInfo(#PathVariable long companyId, #PathVariable String realmName)
Handler match:
http://localhost:6122/context/companies/15877/realms/firstRealm
When the server gets this url, the spring servlet gets called. but it cannot match the controller method.
But if I change the request mapping to "/{companyId}/realms/{realmName}" then it matches the controller method. But it is not nice to define the url mapping without '/companies'. Can Spring be instructed in some way to look for match including the url pattern specified in the servlet?
Thanks.

if you want to use "companies" in request mapping you should map your dispatcher servlet to the root:
<url-pattern>/*</url-pattern>

Related

Using DispatcherServlet for RestController

I'm currently trying to understand how the Dispatcher Servlet works with the Rest Controller ,but Postman returns 404 on everything I tried thus far.
The rest controller
#RestController
#RequestMapping(value = "/applications")
public class ApplicationController {
private static final Logger logger = LoggerFactory.getLogger(ApplicationController.class);
#Autowired
#Qualifier("ApplDAO")
private ApplDAO applDAO;
#Autowired
ApplicationService objServices;
#RequestMapping(value = "for_user\\{username:\\d+}", method = RequestMethod.GET)
public Application getApp(#PathVariable("username") String username){
Application app = applDAO.getByUsername(username);
return app;
}
}
My web.xml
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring4-servlet.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>springDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
I tried using url-pattern /* but with no results.
This is the url I was trying to access http://localhost:8080/project/applications/for_user/username:acid
Is there something wrong with the URL I'm using or have I used the dispatcher wrong.
Here is the spring error
No mapping found for HTTP request with URI [/project/applications/for_user/username:acid
Answered by JB Nizet
Why do you use backslashes instead of slashes in your RequestMapping?
Why do you use the regex \d+ if you want to send username:acid (or
acid?) as user name. Just use value = "/for_user/{username}", and use
http://localhost:8080/project/applications/for_user/acid.

Spring MVC: calls from JSP not going to the controller

I am trying to pass parameters from JSP to the Spring MVC controller. However the controller doesn't get called. I have read many related posts regarding this and have tried various solutions provided but it's not working for me.
My web.xml looks like this:
<display-name>MyList</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>mylist</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mylist</servlet-name>
<url-pattern>/welcome.jsp</url-pattern>
<url-pattern>/welcome.html</url-pattern>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
My Controller:
#RequestMapping(path = "/subcategory/{id}", method = RequestMethod.GET)
public String findSubcategory(#PathVariable int id,Model model) {
List<Category> subCategoryList = this.myListDao.getSubCategories(id);
model.addAttribute("subcategories", subCategoryList);
return "searchCategory" ;
}
The relevant code from My JSP is as follows
<spring:url value="/subcategory/1" var="formUrl"/>
<c:forEach var="category" varStatus="status" items="${categories}">
<li>${category.description}</li>
</c:forEach>
It works when I have the url as /subcategory.html and have #RequestMapping("/subcategory") in my controller. When I use /subcategory/1 and change the corresponding request mapping, it does not work. I have tried various url patterns such as <url-pattern>/mylist/*</url-pattern><url-pattern>/MyList/*</url-pattern>etc. but nothing is working. I would really appreciate any help in solving this. Thanks a lot in advance.
Your current servlet mapping is overriding the default or root servlet mapping,
<servlet-mapping>
<servlet-name>mylist</servlet-name>
<url-pattern>/welcome.jsp</url-pattern>
<url-pattern>/welcome.html</url-pattern>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
Your following mapping allows any request with *.html to be accepted hence your invocation to /subcategory.html worked without any issues.
<url-pattern>*.html</url-pattern>
Instead it should be changed to,
<servlet-mapping>
<servlet-name>mylist</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Some points to remember,
<url-pattern>/*</url-pattern>
This pattern is usually recommended with Filter to continue with filter chaining. Using this pattern otherwise will make you to take care of all responsibilities like serving static resources etc to be handled explicitly.
#RequestMapping(path = "/subcategory/{id}", method = RequestMethod.GET)
instead of path, you should use value, like this:
#RequestMapping(value = "/subcategory/{id}", method = RequestMethod.GET)
Your call cannot reach the controller because your request mapping "/subcategory/{id}" does not match any url-patterns defined with your dispatcher servlet. You can try replacing these lines:
<url-pattern>/welcome.jsp</url-pattern>
<url-pattern>/welcome.html</url-pattern>
<url-pattern>*.html</url-pattern>
with
<url-pattern>/*</url-pattern>

404 Error from REST Endpoint in SpringMVC for DispatcherServlet

RESOLVED PER THIS ANSWER
Spring invokes wrong controller mapping
Spring #Controllers URLs are always interpreted relative the the Spring Dispatcher Servlet that handles them. So if you map the dispatcher servlet to /api/ in web.xml then the URL to your controller above is /api/api/choice
The double string service/service/1234 was working.
ORIGINAL POST
Accessing a REST resource endpoint gives me a 404 error although everything seems to be defined correctly:
Log output:
DEBUG DispatcherServlet with name 'mvc-dispatcher' processing GET request for [/myapp/service/1234]
DEBUG Looking up handler method for path /1234
DEBUG Did not find handler method for [/1234]
WARN No mapping found for HTTP request with URI [/myapp/service/1234] in DispatcherServlet with name 'mvc-dispatcher'
web.xml
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
SpringMVC Controller
#RestController
#RequestMapping("/service")
public class RESTController {
#RequestMapping(value="/{id}", method=RequestMethod.GET)
public String getResult ( #PathVariable String id )
{
//... get JSON result
}
}
Expected invocation: myapp/service/1234
Also tried these options:
1) Don't define a class RequestMapping, just do a Method Request Mapping
#RequestMapping("/service/{id}")
2) as well as
#RequestMapping("/service*/{id}")
#RequestMapping("/service**/{id}")
Keep getting a 404 with the log above.
update your web.xml file :
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

Spring servlet URL mapping

I need to add Restful URL in existing spring based web service.
Each URL is well mapped but after clicking Restful URL such as
http://localhost:9090/Mercury/rest/invoice,
all contextroot path is changed as http://localhost:9090/Mercury/rest
The point is that I want to use both restful(/rest) and *.do URL pattern
How can I set contextroot path up without /rest ?
web.xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Controller
#Controller
#RequestMapping("/rest")
public class InvoiceController {
#RequestMapping(value="/{name}", method=RequestMethod.GET)
public String getInvoice(#PathVariable String name, Model model) {
model.addAttribute("name", name);
return "rest.body";
}
Please refer Spring Pet Clinic on github, to learn how to configure various views.Sample view config xml. Here is the outline.
The ContentNegotiatingViewResolver delegates to the
InternalResourceViewResolver and BeanNameViewResolver, and uses the
requested media type (determined by the path extension) to pick a
matching view. When the media type is 'text/html', it will delegate to
the InternalResourceViewResolver's JstlView, otherwise to the
BeanNameViewResolver.

springmvc cannot call controller's method

Currently I got a problem when I configure my springmvc web project.
Below is my web.xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
And I defined my dispatcher-servlet.xml like this
<context:component-scan base-package="xxx.controller"
<mvc:annotation-driven />
And in package xxx.controller I define a class TestController
#Controller
#RequestMapping(value="/api")
public class TestController {
#RequestMapping(value = "/hello")
#ResponseBody
public String hello(){
System.out.println("comming hello");
return "hello world";
}
}
Now when I start tomcat, and want to access to localhost:8080/testproject/api/hello, The spring informs me
[10:10:58|WARN |(org.springframework.web.servlet.PageNotFound)]=[No mapping found for HTTP request with URI [/testproject/api/hello] in DispatcherServlet with name 'dispatcher']
But if I modify the url-pattern in web.xml to
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
It is ok to access to localhost:8080/testproject/api/hello. I do not know why this happens. I do want to use /api/* rather than /.
Could anyone helps me configure the controller path mapping? Many thanks!
You are telling your application to run in /api context when you define the following:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
so to access your controller the URL would have to be localhost:8080/api/api/hello
Just get rid of the /api from your dispatcher as you have and then your mapping should automatically default to localhost:8080/api/hello and work.
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Otherwise if you want to run your application in /api context always you have the option of removing #RequestMapping(value="/api") from your controller.
That way it only recognises the mapping on method.

Resources