Spring MVC url-pattern syntax - java

Trying to add a restful web service call to an existing Spring 3.11 MVC application, but the app has a url mapping in web.xml for spring like this:
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
So everything basically needs to end in .html
I would like for my web service to not have to do that - ideally by using a unique context/subfolder for my web services, such as /restful for example.
But I am not sure how to get it to work...
So if my controller was like this:
#ResponseBody
#RequestMapping(value="restful/test/{test}",method = RequestMethod.GET)
public String test(#PathVariable String test)
{
return "OK"+test;
}
And I wanted to access it by: localhost/blah/restful/test/text (no .html anywhere, and where blah is the application context) how should I handle the url-pattern in the web.xml -- without interfering with anything already existing in the app?
When I add another url-pattern like this:
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/restful/*</url-pattern>
</servlet-mapping>
And try to access localhost/blah/restful/test/text, I get a 404 error.
The other part of the web-xml for servlet looks like this:
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
And the view resolver in that spring-mvc.xml file is like this:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>

Assuming you're using the default MVC configuration, given
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/restful/*</url-pattern>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
and
#RequestMapping(value="restful/test/{test}", method = RequestMethod.GET)
you should be trying to access localhost/blah/restful/restful/test/text (note the double /restful).
Spring MVC, in requests with a path mapping (see Servlet Specification chapter 12), tries to extract the path segment that was matched by the container (the first /restful in this case) and therefore use the rest /restful/test/text to find an appropriate handler (your #Controller's #RequestMapping annotated method).
I would simply remove the restful part from your #RequestMapping. You'd be left with
#RequestMapping(value="/test/{test}", method = RequestMethod.GET)
which would be able to handle a request to /localhost/blah/restful/test/text.

Do you have tried this ?
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.html</url-pattern>
<url-pattern>/restful/*</url-pattern>
</servlet-mapping>
Or just in a different order like this (because order should matter):
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/restful/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>

Related

How to run angular2 and spring mvc based rest api on the same tomcat server?

I am building an angular 2 app that has to use spring mvc based rest api at the backend. I am using maven, not using spring-boot, and want to map the index.html of angular2 to the base URL of the deployed WAR file. I am seeing the index.html to be present in the MyApplication named folder in webapps folder of tomcat, but somehow trying to access the site via the base URL gives no resource available. Could somebody help me. This is my layout.
web.xml
<display-name>MyApplication</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
mvc-dispatcher-servlet.xml
<context:annotation-config/>
<context:component-scan base-package="com.rochak.*" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/angular/</value>
</property>
<property name="suffix">
<value>.html</value>
</property>
</bean>
MyController.java in com/rochak/controller
#Controller
public class MyController {
#RequestMapping(value="*")
public String getIndex(ModelMap model){
return "index";
}
}
and angular folder lies in WEB-INF folder with it's index.html
Why is index.html not being found by spring mvc?
Change your 'url-pattern' to something like '/server/'. It would work.

Spring mvc create indexservlet as root path

I use spring mvc (4.0) and I want to use a servlet to intercept the root mapping ("/") instead of the dispatcherservlet. Spring has a configuration, called "default-servlet-name". The documentation says the following:
The name of the default Servlet to forward to for static resource requests. The handler will try to auto-detect the container's default Servlet at startup time using a list of known names. If the default Servlet cannot be detected because of using an unknown container or because it has been manually configured, the servlet name must be set explicitly.
The problem with the above configuration is that the default servlet is called on every request.
Web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>index</servlet-name>
<servlet-class>com.company.main.IndexServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>index</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index</welcome-file>
</welcome-file-list>
spring-servlet-config.xml:
<mvc:annotation-driven/>
<context:annotation-config />
<mvc:default-servlet-handler default-servlet-name="index" />
<context:component-scan base-package="com.company.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/jsp/"
p:suffix=".jsp"
p:requestContextAttribute="rc" />
So, with the above configuration, the indexServlet functions as root path. But is called multiple times, because it is the default-handler. If I remove the tag "default-servlet-handler" from the spring config, the page won't load. Any workaround for this?
Thanks in advance!
The problem is that root mapping / can only by mapped by the default servlet (Java EE sense).
So IMHO, you have only one clean way to meet your requirement : you map spring dispatcher-servlet to /, you do not map IndexServlet and have spring forward to it for / URL.
You could use a ServletForwardingController for that :
In web.xml :
<servlet>
<servlet-name>index</servlet-name>
<servlet-class>com.company.main.IndexServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
In spring-servlet-config.xml:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
/=indexForwardingController
</property>
</bean>
<bean id="indexForwardingController" class="org.springframework.web.servlet.mvc.ServletForwardingController">
<property name="servletName"><value>index</value></property>
</bean>

Can't get Spring MVC dispatcher to work properly when url pattern is a path

I have a web app that we're applying spring MVC just for REST services at the moment. We want our rest services to appear under ${contextPath}/rest/**, however when I set this we get:
No mapping found for HTTP request with URI [/myapp/rest/testSvc/message] in DispatcherServlet with name 'Spring MVC Dispatcher Servlet'
My web.xml has:
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/servlet-context.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/rest</url-pattern>
</servlet-mapping>
servlet-context.xml, which is fine and is registering services as they get registered at startup.
<context:component-scan base-package="com.mycompany.myapp.rest" />
<mvc:annotation-driven />
My controller looks as follows:
#Controller
#RequestMapping(value = "/rest/testService")
public class TestREST {
#RequestMapping(value="message", method=RequestMethod.GET)
public #ResponseBody String getMessage() {
return "REST working";
}
If I cahnge the url-pattern in web.xml to *.rest and my request-mapping for message to message.rest it works.
The problem is likely that you have repeated the /rest prefix in both web.xml and #RequestMapping. It should be in one or the either, but not both, e.g.
<url-pattern>/rest</url-pattern>
and
#RequestMapping(value = "/testService")
The paths upon which #RequestMapping operates are the parts of the path that follows the servlet part, and your web.xml defines the servlet part as /path, so #RequestMapping matches against whatever is left, i.e. /testService.
In its current form, your #RequestMapping is actually matching against {contextPath}/rest/rest/testService.
Perhaps you could try changing to <url-pattern>/rest/*</url-pattern> or <url-pattern>/rest*</url-pattern> and see if that helps.

Spring MVC; avoiding file extension in url?

I just started with Spring Web MVC. I'm trying to avoid file extenstions in the url. How can i do this? (I'm using Spring 2.5.x)
Bean:
<bean name="/hello.htm" class="springapp.web.HelloController"/>
I want it to be:
<bean name="/hello" class="springapp.web.HelloController"/>
I cannot get it to work. Any ideas?
Edit:
Url-mapping
<servlet-mapping>
<servlet-name>springapp</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
I have tried changing the url-pattern with no luck (* and /*).
In 3.0, / seems to work. That is...
<url-pattern>/</url-pattern>
As far as I know you can't do this if you're using JSP's as your view for controllers.
Because when you pass a model to a JSP, Spring MVC internally performs a 'forward' to the URL of the JSP. If you use <url-pattern>/*</url-pattern> then this forward will also be handled by your DispatcherServlet and not by your JSP view.
What you can do is use <url-pattern>/something</url-pattern> and have your JSP's in a different directory
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Then you need to register your urls to be handled by a particular controller. See the following
http://static.springsource.org/spring/docs/2.0.x/reference/mvc.html
In Spring 3.2 at least, the accepted answer above is very nearly but not quite what's needed. The web.xml bit below just worked for me, and I'm adding it to the thread here for reference of whoever googles this next...
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Try first:
<servlet-mapping>
<servlet-name>spring-mvc</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
If that doesn't work then problem is somewhere else. Is your Apache set up to forward those urls to Tomcat? Something like:
JkMount /hello worker1
Have you tried <url-pattern>/*</url-pattern>
in the servlet mapping and <bean name="/hello" .../> ?

Spring MVC - Web Flow Controller

I have a j2ee application developed using spring framework and spring webflow. Currently all of my url requests go through the Web Flow. What I want is to be able to choose whether to direct it to Web Flow or an ordinary spring mvc controller. I have no idea how to direct it to custom controllers. How do I do this?
I tried having this in my web.xml but i can't direct it to the bean controller specified in mytest2-servlet.xml
<servlet>
<servlet-name>mytest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>mytest2</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation2</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mytest</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>mytest2</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/web-application-config.xml
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation2</param-name>
<param-value>
/WEB-INF/mytest2-servlet.xml
</param-value>
</context-param>
Try this in your end state
<end-state id="exit" view="externalRedirect:controllerURL" />
where 'controllerURL' is the URL that your controller listens to/
The simplest way to mix both Web Flows and plain Spring MVC Controllers is to simply register the plain Controllers at URL paths outside any of your flow paths.
For instance, here are some excerpts from our configuration files, loaded from web.xml by the single instance of the DispatchServlet:
<!-- Simple URL-view mapping without controller (or flow) -->
<mvc:view-controller path="/selectLanguage" view-name="selectLanguage"/>
<!-- Maps request paths to flows in the flowRegistry;
e.g. a path of /hotels/booking looks for a flow with id "hotels/booking". -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping" p:order="-1">
<property name="flowRegistry" ref="flowRegistry" />
<property name="interceptors">
<list>
<!-- for each flow, if a param lang=xx is added, switch locales -->
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
p:paramName="lang"/>
</list>
</property>
</bean>
<!-- The registry of executable flow definitions -->
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" base-path="/WEB-INF">
<!-- Flows created from all -flow.xml files, with the flow ID being the path name -->
<webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>
So WebFlow will register all URL paths that correspond to a WEB-INF/**/something-flow.xml file, and all other URL paths, like /selectLanguage above, can be handled by a regular Controller.
write a dispatcher-sevlet.xml or configuration file, write a separate configuration file ( for convenience ) for Spring Flows just import the files in dispatcher-servlet.xml.

Categories