Servlet mapping url mapping issue with spring and BIRT - servlets

In my application I'm using spring MVC(3.0.5) architecture along with BIRT reporting framework.
I'm trying to serve all requests including the static resources like css, js, html and image files using the spring DispatcherServlet.
For this purpose I added the following entries to my web.xml
<servlet>
<servlet-name>springapp</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
...............
...............
<servlet-mapping>
<servlet-name>springapp</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
This will direct all request to the DispatcherServlet and in my context file I added
<mvc:resources mapping="/css/**" location="/css/" />
<mvc:resources mapping="/docs/**" location="/docs/" />
<mvc:resources mapping="/images/**" location="/images/" />
<mvc:resources mapping="/js/**" location="/js/" />
<mvc:resources mapping="/themes/**" location="/themes/" />
so that these resources will be loaded from the file system.
These configurations are working fine. But I'm facing issues with my BIRT reporting engine now.
The BIRT reporting engine uses some jsp files located in a folder called webcontent which is located at the root of the application. Since we are directing all request to DispatcherServlet even the request for these jsp pages are going to the spring servlet. As I understand from some posts the jsp files are normally handled by org.apache.jasper.servlet.JspServlet which is registered in the Apache Tomcat's web.xml file and it has a servlet mapping as follows
<!-- The mapping for the JSP servlet -->
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
What are the changes that I should make in my servlet mapping to work in this environment? I need the jsp files to be handled by the default jsp servlet not by the spring servlet. How can I achieve this?
For this post I understood that the second priority in servlet matching is for the url prefix, so my url pattern / for spring servelt is overriding the default jsp servlet mapping, Is this assumption correct? If it is correct then how to overcome this?
Thank you.

The typical mapping of DispatcherServlet is <url-pattern>/</url-pattern>. In this case it still handles all requests except for requests handled by other servlets (in particular, requests to *.jsp), so that it should solve the problem.

Related

Spring <mvc:resources ... /> request routing

TL;DR: I'm writing a simple Tomcat/Spring/Freemarker webapp and seem to be having a lot of trouble getting Spring's DispatcherServlet to honor <mvc:resources...> configuration.
PLEASE NOTE: AFAICT this is not a duplicate of other questions since I've tried the solutions given in other answers. If someone finds an existing question and that question provides a solution I missed, I'll gladly VTC as a dup (or delete this question if desired).
I have a very simple webapp based on Freemarker. That part is working fine. I have a single request-handler method to handle all requests (#RequestMapping("/**")) but wish to serve static resources /${contextPath}/static/... using the <mvc:resources.../> facility. The resources are located in subdirectories of the top-level webapp directory.
Based on reading other questions on SO I added
<mvc:resources mapping="/static/**" location="/" />
to my Spring configuration.
No matter what I do, requests that I expect to be resolved as a static resource file are being sent to the request handler method of my controller instead. The only thing I can think of is that the #RequestMapping annotation has precedence over mvc:resources, but that doesn't make a lot of sense.
I have verified that the resource URLs are being generated correctly, i.e. the template line
<link rel="stylesheet" href="${contextPath}/static/css/gallery.css">
generates
<link rel="stylesheet" href="/gallery/static/css/gallery.css">
and the request is being received by the Tomcat server, just routed to the wrong place.
I've read most of the questions on SO about this subject and I believe I'm doing it right (see for example Trying to get mvc resources to serve my static resources), but clearly I'm missing something obvious.
Environment
Eclipse Luna
Java 8
Tomcat 8
Freemarker 2.3.23
Spring 4.2.0
Windows 7 SP1
Deployed Layout
Standard Java EE Tomcat directory structure
webapps
|- gallery
|- css
|- images
|- js
|- META-INF
|- WEB-INF
|- classes
|- lib
|- views
Tomcat Context Definition
<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="D:\dev\tools\apache-tomcat-8.0.24\wtpwebapps\gallery"
path="/gallery" reloadable="true"
source="org.eclipse.jst.j2ee.server:gallery"/>
Spring Servlet Config
WEB-INF/main-servlet.xml
...
<mvc:resources mapping="/static/**" location="/" />
<mvc:annotation-driven/>
<context:component-scan base-package="com.mysite.gallery"/>
...
I've tried all possible orderings of these statements but that seems to have no effect. I also tried adding
<mvc:default-servlet-handler/>
with no effect.
WEB-INF/web.xml
Standard Spring MVC DispatcherServlet config
...
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>main</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
...
RequestMapping method
...
#RequestMapping("/**")
public String gallery(ModelMap modelMap, HttpServletRequest req, HttpServletResponse resp)
{
etc...
Freemarker Template
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="${contextPath}/static/css/photoswipe.css">
<link rel="stylesheet" href="${contextPath}/static/css/default-skin/default-skin.css">
<link rel="stylesheet" href="${contextPath}/static/css/gallery.css">
<script src="${contextPath}/static/js/photoswipe.min.js"></script>
<script src="${contextPath}/static/js/photoswipe-ui-default.min.js"></script>
</head>
<body>
<div>
...
You gave the answer in your question: The only thing I can think of is that the #RequestMapping annotation has precedence over mvc:resources, but that doesn't make a lot of sense.
You may think it does not make sense, but is is how Spring fellow decided it should be, at least by default...
But you have different ways for static ressources to have precedences on the #RequestMapping annotated controller.
The simplest way is to add an "order=0" attribute to the <mvc:resources.../> tag :
<mvc:resources mapping="/static/**" location="/" order="0"/>
and to write it in WEB-INF/main-servlet.xml before <mvc:annotation-driven/>
I tested in with Spring 3.2.4 and it works like you want. But it looks like driving spring framework where it was not designed for, so I cannot guarantee that it will work on other versions.
You could also map the dispatcher servlet to / instead of /*. That way all static resources (and also JSP) that can be served directly by the servlet container will be. The main caveat with that mapping, is that root will no longer be served by Spring dispatcher servlet. One possible workaround it to use a /home URL for the root controller, and put a welcome file in web xml :
<servlet>
<servlet-name>main</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/home</welcome-file>
</welcome-file-list>
That way, you to not even need to use /mappings/images/img.gif, just use /images/img.gif/.
But there is another caveat, that I have always accepted (because I could not find any workaround): if /url is served by one controller, /url.jsp or /url.jpeg will give a 404 error. As the container default servlet knows about .jpeg or .jsp files it will catch the request and fail.

Spring MVC 3 - Need help in resolving the url-pattern issue

I am developing an app with spring mvc and here is my web.xml
<servlet>
<servlet-name>admin</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>admin</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
For serving static content, I added the following line in my admin-servlet.xml
<context:component-scan base-package="com.prasanna.blog.Server" />
<mvc:resources mapping="/resources/**" location="/"/>
I have 5 controllers each mapped to particular url for example adminRequests.java is mapped to /admin/*
#Controller
#RequestMapping("/admin/*")
public class AdminRequests
Then I have methods inside the class mapped to particular urls.
The problem is, I am getting 404 error when the url-pattern in web.xml is mapped as / .But when I change the url pattern in web.xml to /app or any other , my index.html is served without any issues.
I am not sure where the problem is. Please advice
When you map Url pattern / to Spring's Dispatcher Servlet, all the request to your application is forwarded to Dispatcher Servlet. Although in this case you defined the static resources using <mvc:resources> tag, but your index.html is not resolved properly because it is not rendered as /resources/index.html but /index.html.
I would suggest you to add one more <servlet-mapping> in your web.xml before spring's <servlet-mapping>. For example:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/index.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>admin</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Hope that will work for you.
No that did not resolve the issue. But I saw another thread discussing the same issue and one of the answer there worked. I removed <mvc:resources> line from spring xml and added the below lines in the web.xml
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
Now my static content is served without any issues but I don't like this method. It feels like a very dirty hack. Now if I have to serve images, I have to add mapping for each image type. I am not sure whether the spring version is a problem because I use mongodb in the backend with spring data. It took a hell of a time to set up my pom.xml because there were some issues with the spring data version and mongodb driver.

Servlet mapping in jetty server

I am trying to edit a website:
server : Jetty
framework : spring
index.html page is in ./web/
From this, mapping to webpages in ./web/WEB_INF/template using Servlet. We would like to add one more module in this index.html.. requests help on Servlet mapping.
A servlet is mapped in web.xml:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.myclass.etcetera.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet</url-pattern>
</servlet-mapping>
It is thus accessible through http://localhost:8080/app/MyServlet
If you are using the latest version of the servlet API (3.0), you can map it using the #WebServlet annotation on the servlet itself (and of course, specify there the url-pattern on which the servlet will respond)

Setup a Filter that will set the Response Header to only Image File(s)

I am having a caching problem based on the discussion that I have in this link
But I am not sure how to go about with the suggestion on setting the response headers on my Spring MVC.
Does anybody know how to setup a some sort of a filter that will add add a response header only on image files?
I currently am not an expert on J2EE web development with SPring MVC.
Any idea?
Spring comes with a Resources Servlet.
<!-- Serves static resource content from .jar files such as blartoch.jar -->
<servlet>
<servlet-name>Resources Servlet</servlet-name>
<servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
<load-on-startup>50</load-on-startup>
</servlet>
<!-- Map all /resources requests to the Resource Servlet for handling -->
<servlet-mapping>
<servlet-name>Resources Servlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
We are using an ear file and all of my resources are in a jar in the ear. If you are only deploying a WAR file (perhaps to tomcat), then try putting your resources in a jar and putting the jar in your WAR file's /WEB-INF/lib directory.
If you store your resources (inside the jar) in the following directory:
/META-INF/common/images
requests for your resources will look something like this:
<img src="<c:url value="/resources/common/images/cuteKitten.jpg"/>"/>

Flex Cairngorm Spring Blazeds - Remoting Error - help me please

I seem to be getting the following error when I try to access a Remote Java class (on Spring/BlazeDS) from the Flex/Cairngorm application. I am going crazy at the moment trying to see what is wrong - any help would be greatly appreciated - thanks Mike.
**Error: C0007E: RemoteObject not found for mycomponentsService
at RemoteObjects/getService()
at com.adobe.cairngorm.business::ServiceLocator/getRemoteObject()
at com.nomura.dashboard.client.business::DashBoardDelegate()**
All my config files are below:
Cairngorm - BusinessDelegate.as
this.service = ServiceLocator.getInstance().getRemoteObject("**mycomponentsService**");
Cairngorm - Services.mxml
mx:RemoteObject id="mycomponentsService"
destination="remotecomponentService"
showBusyCursor="true">
Spring/BlazeDS - application-config.xml
flex:remote-service ref="remotecomponentService"
bean id="remotecomponentService"
class="com.mycompany.dashboard.server.dao.ComponentsDAO"
Spring/BlazeDS - services-config.xml
channel-definition id="myamf" class="mx.messaging.channels.AMFChannel"
endpoint url="http://localhost:8080/dashboard-server/spring/messagebroker/amf"
class="flex.messaging.endpoints.AMFEndpoint"
The web.xml also contains Spring references - see below
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4">
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<display-name>dashboard-server</display-name>
<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/*-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map /spring/* requests to the DispatcherServlet -->
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/spring/*</url-pattern>
</servlet-mapping>
</web-app>
Can we see your web.xml also please? I am surprised to see the word "spring" in the endpoint URL. My endpoints have always looked like
url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf"
E.g.: I think your services-config.xml should look more like this.
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}/dashboard-server/messagebroker/amf"
class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
I would also suggest not hardcoding the end-point URL so much. Just go with
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint class="flex.messaging.endpoints.AMFEndpoint"
url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" />
</channel-definition>
Update:
OK, so your web.xml looks OK, as does having the spring in your URL. What I don's see in your Spring configuration file (application-config.xml) is the Spring URL mapping. For example, in my Spring config files, in addition to the the bean definitions, there is a mapping. E.g.:
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/histogram/**=bean.HistogramController
/counter/**=bean.CounterController
</value>
</property>
</bean>
<bean id="bean.HistogramController" class="ch.comp.app.HistogramXportController" />
<bean id="bean.CounterController" class="ch.comp.app.CounterXportController" />
(I have one app that is Spring-based, and another that uses BlazeDS, but not both...so I might be missing something. That said, what I'm asking still should be valid. In theory. But take it with a grain of salt.)
Maybe some some super basic debugging is in order. Can you check to see if the calls to your server are returning HTTP 404 or not on theses problem endpoints? A couple ways to do this:
Check the access logs for GET /dashboard-server/spring/messagebroker/amf. What is the HTTP status code for these requests? (Free, easy, no new tools.)
If you are using FireFox as a browser, add the Tamper Data plug in. You don't have to tamper with the data, but it shows you what is being called, what is returned, and all the HTTP headers.
Use a full on Flash/Flex oriented protocol sniffer tool, like Charles Web Debugging Proxy.
It will very helpful to narrow down the problem to know if where these requests are failing on the communications stack.
I have attached web.xml below. In terms of the word "Spring" - I am using the standard BlazrDS/Spring integration WAR file which requires "spring" to be there. The bean id="remotecomponentService" is acutally a Spring bean.
Are you saying even with the BlazeDS/Spring WAR I can use your solution above?
The web.xml also contains Spring references - see below
<web-app version="2.4">
<display-name>dashboard-server</display-name>
<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/*-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map /spring/* requests to the DispatcherServlet -->
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/spring/*</url-pattern>
</servlet-mapping>
</web-app>

Resources