springmvc cannot call controller's method - spring

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.

Related

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>

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.

cxf and spring MVC : No service was found

I have spring application, in which I use org.apache.cxf for soap and spring MVC for displayng some pages.
My web.xml contains two servlets :CXFServlet and mvc-dispatcher
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/servlet-context.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
When I has been used #ResponseBody in my controller everything was fine.
#Controller
#RequestMapping("/hello")
#ResponseBody
public class HelloController {
#RequestMapping(method = RequestMethod.GET)
public String printWelcome() {
return "hello" ;
}
}
but then i was needed to use jsp I have to use the following
#Controller
#RequestMapping("/hello")
public class HelloController {
#RequestMapping(method = RequestMethod.GET)
public ModelAndView printWelcome(ModelMap model) {
model.addAttribute("message", "hello");
return new ModelAndView("hello") ;
}
}
and when I request http://localhost:8080/hello I get "No service was found" instead of "hello"
I found that if I delete following from web.xml
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
my controller works fine.
The Servlet container you are using is matching CXFServlet instead of mvc-dispatcher for the URI http://localhost:8080/hello, resulting in your request being sent to CXFServlet, and the error message "No service was found" being returned by CXFServlet. To quote the Servlet 3.0 spec,
Versions of this specification prior to 2.5 made use of these mapping
techniques as a suggestion rather than a requirement, allowing servlet
containers to each have their different schemes for mapping client
requests to servlets.
http://download.oracle.com/otndocs/jcp/servlet-3.0-fr-eval-oth-JSpec/
You will likely need to configure you CXFServlet mapping to something else, e.g.
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
You might want to mention the container (Tomcat, Glassfish, etc.) that you are using, as there could also be a bug preventing this from working correctly.

How can I redirect the user to a servlet instead of an index file on initial page load?

Here is what I have configured in web.xml :
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
But if I change it to a servlet :
<welcome-file-list>
<welcome-file>myservlet</welcome-file>
</welcome-file-list>
I receive a 404 error message.
How can I redirect the user to a servlet instead of an index file on initial page load ?
THe servlet is based on Spring :
#Controller
public class MyController {
#RequestMapping(value="redirect")
public String displaySearch(Model model) {
model.addAttribute("test" , "test");
return "mypage";
}
}
I just need the "redirect" servlet to be invoked by default.
Edit : the spring dispatcher servlet is mapped on the '/' url pattern, is this incorrect also ?
<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>/</url-pattern>
</servlet-mapping>
Via a servlet mapping, e.g.:
<servlet-mapping>
<servlet-name>myservlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

Configuring Grizzly with a web.xml

I can start grizzly and deploy Jersey webservices on it with the following lines.
protected HttpServer create() throws Throwable {
ResourceConfig rc = new PackagesResourceConfig("com.resource", "com.provider");
HttpServer server = GrizzlyServerFactory.createHttpServer(uri, rc);
return server;
}
But is there a way to load a web.xml instead of a ResourceConfig?
<web-app>
<servlet>
<servlet-name>Jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.resource, com.provider</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
It seems that there is currently no direct way to configure grizzly with a web.xml. However I have used a partial solution that may be a beginning.
web.xml
First to understand the solution, we must understand what is the meaning of using a web.xml. It is basically use for configure your web application (see this answer for a more detail). In this case we are configuring init-params for the servlet.
The (partial) solution
Instead of using the web.xml and instead of using ResouceConfig.class, we can use Grizzly as our servlet and initializing the parameters.
For example
<web-app>
<servlet>
<servlet-name>Jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.resource, com.provider</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
would give something like :
protected HttpServer create() throws Throwable {
HashMap<String, String> initParams = new HashMap<>();
//ServerProperties.PROVIDER_PACKAGES is equal to "jersey.config.server.provider.packages"
initParams.put(ServerProperties.PROVIDER_PACKAGES, "com.resource,com.provider");
//Make sure to end the URI with a forward slash
HttpServer server = GrizzlyWebContainerFactory.create("http://localhost:8080/", initParams);
return server;
}
With this, we can therefore put all the init-params that we want to.
However this solution cannot replace a whole web.xml.

Resources