Spring RequestMapping - spring

Currently every page in my current location has a web-url as follows.
/test/test
In my controller the rest mapping works just fine and finds a page test.jsp.
/test/test.jsp does not work.
Now I need to do redirects from old urls to new urls. These have .jsp in every one of their urls. When I set up the url I get a 404 error. When I remove the .jsp heading it at least hits my request mapping.
I need to find a way where the controller can recognize jsp's with or without the jsp extension. I am trying to then redirct.
Here is part of my application context.
<beans:bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<beans:property name="viewClass"
value="org.springframework.web.servlet.view.tiles2.TilesView" />
</beans:bean>
Here is the setting in my web.xml.
<servlet>
<servlet-name>appServlet</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>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

I'd write a servlet Filter that checks if the request path ends with ".jsp", and if so does a redirect to the same path without ".jsp".

Related

CXF Redirect url to a static html page

I have my web.xml
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<init-param>
<param-name>static-resources-list</param-name>
<param-value>/myfiles/(\w.*)+(.html|.js)</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
spring config:
<jaxrs:server id="services" address="/">
<jaxrs:serviceBeans>
<bean class="com.abc.MyController"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
My restful resources are working good with URLs http://localhost/appname/resource...
Now I have a src/main/webapp/myfiles/fileOne.html in my source.
I would like to use URL http://localhost/appname/file to redirect to fileOne.html. How do I do that??
EDIT:
I have added static-resources-list in above web.xml cxf configuration. I know that http://localhost/appname/myfiles/fileOne.html works but I want to use URL http://localhost/appname/file to serve the fileOne.html. How do I do that?
Found solution; Just in case anyone needs it.
redirects-list param at CXF servlet configuration didn't serve my purpose. So I added below servlet configuration in web.xml to redirect to my html page.
<servlet>
<servlet-name>swagger-ui</servlet-name>
<jsp-file>/myfiles/fileOne.html</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>swagger-ui</servlet-name>
<url-pattern>/file</url-pattern>
</servlet-mapping>
Your CXFServlet url mapping is the problem. You gave the mapping as /*. So all the requests, even the static resources are routed to CXFServlet. Try making the CXFServlet mapping to something else. It will work just fine. You don't need static-resources-list.
Because you gave the url mapping for CXFServlet as /*, every URL tries to find the response from CXFServlet which is giving the response as not found because it's jax-rs server doesn't know about the static resources.
You can something like this in servlet tag:
<init-param>
<param-name>static-welcome-file</param-name>
<param-value>/index.html</param-value>
</init-param>

Can't map dispatcherServlet to context root

this is the current configuration i am using for spring mvc:
1- web.xml:
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/config/dispatcherServlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2- dispatcherServlet.xml:
<context:component-scan base-package="com.app" />
<context:annotation-config />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
3- Controller: my web pages are under webapp folder directly
#Controller
public class SearchController {
private Log log = LogFactory.getLog(getClass());
#RequestMapping("/search.jsp")
public String search(Model model, HttpServletRequest request,
HttpSession session) {
log.debug("Search Controller");
return "search";
}
ISSUE: when trying to access the search page as follows:
http://localhost:8080/MyAPP/search.jsp
the controller is not invoked, but when i was mapping the dispatcher servlet to /mapping/* and accessing the search page as follows:
http://localhost:8080/MyAPP/mapping/search.jsp
the controller was invoked correctly, i am using spring 3.0.5.RELEASE.
please advise, thanks.
I think you are forgetting about the built in default servlet configured in your web server/servlet container. For example in Tomcat7/conf/web.xml there exists:
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- The mappings for the JSP servlet -->
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
which is catching the *.jsp before it ever gets to Spring. I tested this locally by removing all of the Spring configuration and could still get the search.jsp.
How DefaultAnnotationHandlerMapping works should be useful in explaining why this works they way it does.
When you had <url-pattern>/mapping/*</url-pattern> you created a more specific match than the simple / so requests were ignored by the default (i.e. Tomcat) servlet and routed to your correctly configured controller.
One way to fix this is to force everything through your servlet by using <url-pattern>/*</url-pattern> but you will also need to make a few other changes to avoid mapping resolution problems.
I moved the *.jsp files into the (standard?) subdirectory /WEB-INF and added
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>/WEB-INF/*</url-pattern>
</servlet-mapping>
to web.xml and changed dispatcherServlet.xml to match like so:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>
If you do not make these changes, a request to /search.jsp would be resolved by the InternalResourceViewResolver you configured to /search.jsp sending Tomcat into an infinite forwarding loop!
No mapping found for HTTP request with URI [/WEB-INF/pages/apiForm.jsp] may be useful here.
Aside: For most of my Spring XML configured projects I use /WEB-INF/views to keep the view layer separate from any configuration in the /WEB-INF root.
The following mapping will cause the dispatcher servlet to handle urls that were not explicitly mapped by other url mappings within web.xml. Think of this as almost a catch all mapping, as long as the url was not handled by some other mapping.
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
When you configure the ViewResolver as follows:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
The ViewMapping must point to a JSP within your project or else the catch all mapping provided for the dispatcher is going to attempt to handle the forward/redirect to the appropriate view. You must make sure that a view exists within your project for the result of the viewresolver, which is /search.jsp. This means there must be a search.jsp within the root of your projects web content folder. It is much more common to see these views placed within the WEB-INF folder and a mapping of:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>

Spring-jersey how to expose services under more than one context

I use spring-jersey to expose rest services. My web.xml looks as follows:
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Let say standard.
I have a lot of rest services in many packages and I need to goup them in two context, let say "base" and "advanced" services. Moreover I need to get rid of the "rest" prefix in url-pattern. So I thought about group them into two packages and then in web.xml define two jersey servlets with com.sun.jersey.config.property.packages init param:
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.example.app.rest.base</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/base/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Another Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.example.app.rest.advanced</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Another Jersey REST Service</servlet-name>
<url-pattern>/advanced/*</url-pattern>
</servlet-mapping>
Unfortunately due to component scan set in applicationContext.xml
<context:component-scan base-package="com.example.app" />
property com.sun.jersey.config.property.packages is ignored (all rest services can be accessed under each context) and it cannot be handle like that.
I am wondering how can I deal with that in other way. The only thing which I don't want to do is to set
<url-pattern>/*</url-pattern>
that catch everyting.
You can specify multiple packages. Just separate them by a comma.
<context:component-scan base-package="com.example.app,com.sun.jersey" />
You can also define two component-scan items and they should work just as well, too.
If the package differentiation won't help, use a filter.
<context:component-scan base-package="org.example">
<context:include-filter type="regex" expression=".*Repository"/>
</context:component-scan>
And then, just make a separate applicationContext for each service but use an init-param of contextConfigLocation and init-value of the location/name of that app context. So, if you make a specific app context to load for each service, the component scan filtering will load everything you need for one service and exclude the other one.
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/rest-service1.xml</param-value>
</init-paraam>
Actually, if you make a separate xml file for each, you can just go back to using the different package at that point, I believe.

Spring MVC Tiles - Not picking up resource folder

I need to change mapping for my spring servlet to point to /sample vs. /sample.html.
I made a change in the url pattern to the following. The urlPattern is
<url-pattern>*.html</url-pattern>
<servlet>
<servlet-name>appServlet</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>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Once this change is made, none of the style sheets reference in a folder are picking up. I thought this was because DispatcherServlet was trying to read this. When I try the following to my servlet-context.xml file, NOTHING works.
<bean id="viewResolver"
class="org.springframework.web.servlet.view.ResourceBundleViewResolver"
p:basename="views" />
<context:component-scan base-package="*****" />
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"
p:definitions="/WEB-INF/tiles-defs.xml" />
<mvc:resources mapping="/_res/**" location="/_res/"/>
I thought maybe I needed to add another view resolver, but that doesn't make any difference.
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
Any help would be greatly appreciated. It seems no matter what I do I get a 404 Error.
The resourses are accessed througt the spring dispatcher. So you need to make sure that the requests are delegated to the spring dispatcher sevlet in the web.xml.
You must delegate all requests to the dispatcher, not only html, but also css, images,...

spring 3 mvc multiple application context instances

here is my web.xml:
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Enables clean URLs with JSP views e.g. /welcome instead of /app/welcome -->
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/*.xml
</param-value>
</context-param>
<!-- Handles all requests into the application -->
<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/*.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Maps all /app requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Why there are two instances of application context created?
When I add a scheduled method with #Scheduled it is invoked twice, because of those two application contexts.
You are loading twice times the same spring config files. Of course you have two separate application contexts. At first I would rename the servlet name for the DispatcherServerlet to "spring3mvc". The servlet definition should look like this:
<servlet>
<servlet-name>spring3Mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
If you have it in this way, you should have a spring config file "spring3Mvc-servlet.xml" in your "WEB-INF" directory. Spring will find this file automatically because of the right naming convention. In this file you should just have the beans who are important for springMVC. It could look like this:
<context:component-scan base-package="org.company.gui.controller"/>
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".view.jsp"/>
</bean>
This should fix your problem.
I noticed that you have
<load-on-startup>1</load-on-startup>
in the following block
<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/*.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
try removing that... it worked for me
Do you have any other spring filters or jsp pages in your web.xml not shown in your code snippet?
I ask, to answer your question, because I believe this quote from Spring documentation could explain what might be happening...
"In the web MVC framework, each
DispatcherServlet has its own
WebApplicationContext, which inherits
all the beans already defined in the
root WebApplicationContext. These
inherited beans defined can be
overridden in the servlet-specific
scope, and new scope-specific beans
can be defined local to a given
servlet instance."
If you answered "yes" to my web.xml question, then my guess is that Spring instantiates a root WebApplicationContext when a spring filter is created (via ContextLoaderListener). So, this would happen BEFORE...
Then, when the DispatcherServlet is created, the "contextConfigLocation" refers to the same files (that is, the same bean names), so a new WebApplicationContext gets overridden bean names local to that servlet!
I wonder, even if you answered "no", whether this might still happen anyway. Since you set "contextConfigLocation" (used by the ContextLoaderListener) and "override" it in DispatcherServlet configuration; I assume Spring is not checking whether those configurations are using the same file set.
You can run these scenarios through a debugger and put breakpoints on WebApplicationContext methods to find out for sure.
Workaround:
To solve the problem, either:
1) make sure your 2 contextConfigLocations don't overlap in files they use
Or:
2) break out the Scheduling bean in its own xml file and make sure it's referred to by only one of the 2 contextConfigLocations

Resources