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>
Related
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.
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>
I could start my application with REST endpoints exposed without problem.
However, I have another spring ApplicationContext created elsewhere and would like to be accessible from my REST endpoints.
Currently, I have to use a Singleton to lookup the beans. But is there a way to wire an existing ApplicationContext?
Below is what I have.
web.xml
<web-app>
<context-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>package1.MyJaxRsApplication</param-value>
</context-param>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<listener>
<listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
applicationContext.xml
<beans>
<context:component-scan base-package="package2.rest" />
</beans>
I think u will have to package your service interfaces as a separate jar and use it on other application. Together with that you will have to define service consuming spring configuration use it in you other application
<bean name="/ExposedService.htm" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="exposedService"/>
<property name="serviceInterface" value="com.app.client.ExposedService"/>
</bean>
Ok I understand the fact that any web application context configured through DispatcherServlet inherits all the beans already defined in the root WebApplicationContext. Nevertheless i have configured some interceptors in my root ApplicationContext
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="2"/>
<property name="interceptors">
<list>
<ref bean="statisticsInterceptor"/>
<ref bean="sessionDiagnosticsInterceptor"/>
...
Then in my web.xml I have something like this:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext*.xml
</param-value>
</context-param>
<servlet>
<servlet-name>dispatcher</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>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>dispatcher-api</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/appOtherContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dispatcher-api</servlet-name>
<url-pattern>/example/apiOther/*</url-pattern>
</servlet-mapping>
So the problem I have is that every time I go to any URL that contains "/example/apiOther/", the Interceptors will not be reached/run. My question is: WHY? What is the scope of the handlerMapping? I thought that because it is in the root applicationContext it should apply to all child contexts. I've been doing some research and I think that HandlerMappings are limited to its context even if it is the root Context. Is that right?
As you configure your interceptors through DefaultAnnotationHandlerMapping, they will be used only for controllers in same ApplicationContext. You can (even it is not very nice) declare the interceptors in root application context, provided the DefaultAnnotationHandlerMapping that referes to them is declared in servlet application context where you declare your controllers, either directly or through annotations.
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.