Community
Participate
Working Groups
Build Identifier: Virgo 2.1.0.RELEASE + Snaps built from Git as of 2010-09-09 Using Snaps (self-built 2010-09-09) on Virgo 2.1.0.RELEASE and everything works happily except for resolving a JSP view from a snaps-bundle (the situation it is not working in is when an ExceptionResolver tries to return a page to the client). In my case I have created a JSP file in the WEB-INF/views-directory of my snap bundle. Then I created the following Spring config in this bundle: <mvc:annotation-driven /> <!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean> The web.xml of this bundle looks like this: <servlet> <servlet-name>callback-controller</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/context/controller-servlet.xml </param-value> </init-param> <init-param> <param-name>contextClass</param-name> <param-value>org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value> </init-param> <init-param> <param-name>detectAllHandlerExceptionResolvers</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>callback-controller</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>/WEB-INF/views/*</url-pattern> </servlet-mapping> My host bundle's web.xml looks like this: <filter> <filter-name>host-filter</filter-name> <filter-class>org.eclipse.virgo.snaps.core.SnapHostFilter</filter-class> </filter> <context-param> <param-name>contextClass</param-name> <param-value>org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/context/global-context.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter-mapping> <filter-name>host-filter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> </filter-mapping> I can happily interact with all my controllers in the snaps bundle, but when one of them returns a ModelAndView which should be resolved to a JSP inside the snaps bundle, I get the following exception: java.lang.NullPointerException org.eclipse.virgo.snaps.core.internal.webapp.container.ServletManager.findMatch(ServletManager.java:95) org.eclipse.virgo.snaps.core.internal.webapp.container.StandardVirtualContainerRequestDispatcher.service(StandardVirtualContainerRequestDispatcher.java:89) org.eclipse.virgo.snaps.core.internal.webapp.WebAppSnap.handleRequest(WebAppSnap.java:153) org.eclipse.virgo.snaps.core.RequestRouter.service(RequestRouter.java:51) org.eclipse.virgo.snaps.core.SnapHostFilter.doFilter(SnapHostFilter.java:62) org.eclipse.virgo.snaps.core.RequestRouter.forward(RequestRouter.java:60) org.eclipse.virgo.snaps.core.internal.webapp.container.SnapHttpServletRequest$1.forward(SnapHttpServletRequest.java:92) org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:239) org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250) org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1060) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:798) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:647) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:552) javax.servlet.http.HttpServlet.service(HttpServlet.java:690) javax.servlet.http.HttpServlet.service(HttpServlet.java:803) org.eclipse.virgo.snaps.core.internal.webapp.container.ImmutableFilterChain.doFilter(ImmutableFilterChain.java:47) org.eclipse.virgo.snaps.core.internal.webapp.container.StandardVirtualContainerRequestDispatcher$1.doWithClassLoader(StandardVirtualContainerRequestDispatcher.java:104) org.eclipse.virgo.snaps.core.internal.webapp.container.StandardVirtualContainerRequestDispatcher$1.doWithClassLoader(StandardVirtualContainerRequestDispatcher.java:1) org.eclipse.virgo.snaps.core.internal.webapp.container.StandardVirtualContainerRequestDispatcher.doWithThreadContextClassLoader(StandardVirtualContainerRequestDispatcher.java:121) org.eclipse.virgo.snaps.core.internal.webapp.container.StandardVirtualContainerRequestDispatcher.service(StandardVirtualContainerRequestDispatcher.java:101) org.eclipse.virgo.snaps.core.internal.webapp.WebAppSnap.handleRequest(WebAppSnap.java:153) org.eclipse.virgo.snaps.core.RequestRouter.service(RequestRouter.java:51) org.eclipse.virgo.snaps.core.SnapHostFilter.doFilter(SnapHostFilter.java:62) Reproducible: Always Steps to Reproduce: 1. Create a Snaps Host bundle and a Snap Bundle 2. Configure the Host bundle's filter to listen to FORWARDs as well 3. Configure a JSP servlet-mapping in the Snap Bundle's web.xml 4. Try to reference a JSP view from a snaps bundle
As requested in the corresponding mailinglist topic (http://www.eclipse.org/forums/index.php?t=msg&th=203933), these are the OSGi manifest headers in use: Snap-Host: Bundle-SymbolicName: purchase.interface Bundle-Version: 1.0.0.SNAPSHOT Web-ContextPath: /purchase Snap-Bundle: Snap-Host: purchase.interface;version="1.0.0" Bundle-Version: 1.0.0.SNAPSHOT Snap-ContextPath: /callback Note that although the host's version is 1.0.0.SNAPSHOT the snap successfully attaches itself to it, despite the explicit mentioning of the host's version "1.0.0".
One thing that caught my eye: Is there a specific reason that jsp servlet url-pattern is modified in the snap? i.e. <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>/WEB-INF/views/*</url-pattern> </servlet-mapping> Thanks Dmitry
A bit of research: Snaps includes its own copy of default servlets that is different from the one included by stock gemini tomcat. see: /org.eclipse.virgo.snaps.core/src/main/resources/META-INF/snaps/default-web.xml In this configuration JspServlet is named "__jsp-servlet" not "jsp" gemini-web on the other hand will look for web.xml in config and if not found use /org.eclipse.gemini.web.tomcat/src/main/resources/web-embed.xml as a default web.xml In that configuration JspServlet is named "jsp". ==== The work around for now is to use __jsp-servlet when working with snaps to get past NPE. I think a potential solution is to stop snap deployment if merged web.xml is missing a servlet definition, i.e. only has a servlet-mapping but no servlet config. Another thing to look at is why snaps and gemini should have different default web.xml configurations. Can they be merged? Do they have to be different? What about snaps and jetty? Could that default web.xml be made discoverable with a service publication?
Some more research: 1. org.eclipse.virgo.snaps.core.internal.webapp.container.ServletManager.processServletMappingDefinitions already has a comment to check mapping vs. servlet config. i.e. // TODO Validate, probably in WebXml, the referenced servlets exist, etc 2. There are two good places to plug in with validation: a. org.eclipse.virgo.snaps.core.internal.webapp.config.BundleWebXmlLoader.loadWebXml b. or as the comment in #1 mentioned - add validate() method on the WebXml. Thoughts?
This bug has an assignee, so changing status to ASSIGNED.
Rudimentary validation fix: check for missing servlets/filters. Commits: 7f2ec88e267651dace666ebb2e2e0beabee5d9d2 and 0bea5f2145b81ee5bd6a461eb7ab9a279118bcf2
Verified for 3.7.0.RC01