How to serve static resources from a Vaadin/Spring application? - java

I have Vaadin web application with spring security integration for authentication. The configuration of the Vaadin servlet is pretty simple:
<servlet>
<servlet-name>Vaadin Application Servlet</servlet-name>
<servlet-class>com.example.SpringApplicationServlet</servlet-class>
<init-param>
<param-name>applicationBean</param-name>
<param-value>mainApplication</param-value>
</init-param>
<init-param>
<param-name>widgetset</param-name>
<param-value>com.example.widgetset.CustomWidgetSet</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Vaadin Application Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
The servlet initializes the Spring Context and returns the Vaadin application. I have also configured the security for that and have a custom login form configured like this:
<servlet>
<servlet-name>login</servlet-name>
<jsp-file>/jsp/login.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>login_error</servlet-name>
<jsp-file>/jsp/loginError.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>login_error</servlet-name>
<url-pattern>/login_error</url-pattern>
</servlet-mapping>
The login form is styled with an external css and there are also some images. Basically the images are located in /jsp/img and the stylesheet in /jsp/login.css. So the WAR structure looks like:
/jsp
/META-INF
/VAADIN
/WEB-INF
Neither the images nor the css gets loaded, because obviously all those requests are mapped to the vaadin servlet. How can I define some static resources directory, which wouldn't be served by the Vaadin servlet? I have tried the spring mvc:resources but that didn't work. Thank you for your help.
Bye,
Filip
I have figured this out. Although it is rather a workaround. I have mapped the Vaadin Application Servlet to something like /app/* instead of to /* (Remember that in this case you also have to map the same servlet to /VAADIN/*). With this configuration I am able to access the jsp directory from my webapp and everything works fine. I have deleted the whole Spring Resources configuration, as this just didn't work.
So once more, I am still pretty not pretty comfortable with this solution and would rather have my RESOURCES dir configured other way, but the client is happy :). If anyone has got the right solution I would appreciate to read it.

Use a url rewrite filter to get more contro on url mapping.
<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>
then map Vaadin application to /vaadin for example and configure url maping in urlrewrite.xml
<rule>
<from>/styles/**</from>
<to last="true">/styles/$1</to>
</rule>
<rule>
<from>/images/**</from>
<to last="true">/images/$1</to>
</rule>
<rule>
<from>/**</from>
<to>/vaadin/$1</to>
</rule>
<outbound-rule>
<from>/vaadin/**</from>
<to>/$1</to>
</outbound-rule>
EDIT
Other option is put static files in /VAADIN/ directory.

I have figured this out. Although it is rather a workaround. I have mapped the Vaadin Application Servlet to something like /app/* instead of to /* (Remember that in this case you also have to map the same servlet to /VAADIN/*). With this configuration I am able to access the jsp directory from my webapp and everything works fine. I have deleted the whole Spring Resources configuration, as this just didn't work.
So once more, I am still pretty not pretty comfortable with this solution and would rather have my RESOURCES dir configured other way, but the c

Might be late but for who is still having problems with serving static content while using vaadin /* mapping, the solution I found was using apache's default servlet org.apache.catalina.servlets.DefaultServlet, so a web.xml will have something like:
<?xml version="1.0" encoding="UTF-8"?>
<web-app
id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/j2ee"
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_3_0.xsd">
<servlet>
<servlet-name>myservlet</servlet-name>
<servlet-class>com.vaadin.server.VaadinServlet</servlet-class>
<init-param>
<param-name>UI</param-name>
<param-value>com.ex.myprj.MyUI</param-value>
</init-param>
<!-- If not using the default widget set-->
<init-param>
<param-name>widgetset</param-name>
<param-value>com.ex.myprj.AppWidgetSet</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>myservlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Static content Servlet</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Static content Servlet</servlet-name>
<url-pattern>/customer/*</url-pattern>
</servlet-mapping>
</web-app>
So in the example above, despite having vaadin at /*, the /customer/* part will be served as static content by the DefaultServlet

Related

AppEngine React and Jersey - The scratchDir you specified is unusable

I have a Java-based REST API (via Jersey 1.18) that I've deployed in an AppEngine application alongside a React front end.
My web.xml declares two servlets:
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
...
<servlet>
<servlet-name>react</servlet-name>
<jsp-file>/index.html</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>react</servlet-name>
<url-pattern>/login</url-pattern>
...
</servlet-mapping>
...
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
</servlet>
<jsp-config>
<taglib>
<taglib-uri>http://www.myapp.com/customtags</taglib-uri>
<taglib-location>/WEB-INF/custom-tags/UserRefTag.tld</taglib-location>
</taglib>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
and, of course, the Jersey filter:
<filter>
<filter-name>jersey</filter-name>
<filter-class>com.sun.jersey.spi.container.servlet.ServletContainer</filter-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.myapp.servlets;com.myapp.tasks;com.wordnik.swagger.jersey.listing
</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.provider.packages</param-name>
<param-value>com.myapp.audit;com.myapp.filters</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
<param-value>/WEB-INF/jsp</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.WebPageContentRegex</param-name>
<param-value>/(js|css|(WEB-INF/jsp)|_ah|ipn|woff|woff2|ui|json|html)/.*</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>com.myapp.audit.AuditLogInterceptor</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.myapp.filters.CorsFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jersey</filter-name>
<url-pattern>/tasks/*</url-pattern>
...
</filter-mapping>
I've specified, in appengine-web.xml the relevant static resources:
<static-files>
<include path="/static/**" expiration="10s"/>
<!-- react ui resources (eg: manifest.json etc) -->
<include path="*.html" expiration="10s"/>
<include path="*.json" expiration="10s"/>
<include path="*.js" expiration="10s"/>
</static-files>
So, ideally, when a user hits an endpoint like /login then it should translate to the react servlet, and be directed to index.html, which is the react app. ReactRouter should then kick in and render the login page. All static, until it checks for a session or something.
This all works wonderfully well in the devserver. When I load /login, it renders my react app. When the react app calls the backend REST endpoints, they all work.
Then, I put it on appengine (standard environment), and it's a different story. The REST endpoints all respond, but the react app doesn't fire. All I get is: Error /login or similar.
When I look in the appengine logs, I see this:
:WARN:oaj.EmbeddedServletOptions:RequestDA26342E: The scratchDir you specified: [/base/data/home/apps/g~myapp-alpha/alpha2.419176782209598562/jsp] is unusable
Googling around, this error appears to be related to directory permissions in the WebContainer, but that's all obfuscated from me, because this is appengine.
What does this error really mean?
What is the problem?
How can I resolve it?
It turns out, after much hacking, that specifying an HTML file in the element was what was causing problems.
Whatever webcontainer appengine uses was trying to compile it, but appengine is supposed to pre-compile all JSPs on upload so it doesn't have to do this. Their setup obviously can't cope with that.
The fix was to move and rename /index.html into /WEB-INF/jsp/index.jsp
It was all perfectly happy then.

Jersey JAX-RS: Specifying /* as base URL pattern

I have a Dynamic Web application, and because of the requirements, I am specifying two types of servlet mappings in the web.xml file; Faces Servlet & Jersey(JAX-RS implementation).
My problem is, that if I try to use '/' as the base url-pattern in the Jersey configuration, then the resources of Faces Servlets stop working, i.e., nothing happens if I make REST call to those resources, otherwise everything works fine if I place something like'/rest/' in the Jersey Configuration. My web.xml file looks like this:
<!-- Jersey -->
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.saf.web.v2.beans</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>100</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
Is there a way to specify the Jersey mapping so there is nothing in the url-pattern but '/*' and Faces Servlet resources also work fine at the same time.
Thanks!
If you define that Jersey should serve all requests (this is what /* means) the Faces Servlet doesn't have a chance any more. So in general: There is no such way.
Maybe you could work around this be mapping Jersey to /rest and writing an own Servlet mapped to /* which dispatches to one of the other servlets. I would not recommend that.
I had the same problem but I fixed it by using
/rest/*
for jersey's servlet
and other part of application can have any other url-pattern, as in your case it is *.xhtml for JSF's servlet.

weblogic server not serving html, js and css files

I have deployed a sample spring java application to weblogic server (11g, 10.3.6). I have index.html at the root and I set that as the welcome-file in web.xml. But when I try to access the application, I am getting 'Error 404 -- Not Found'. Also, I noticed same issue with js and css files.
index.jsp works fine at the same location.
Here is my web.xml.
<display-name>hello</display-name>
<welcome-file-list>
<welcome-file>/index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/applicationContext.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>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
The reason for this is the root level mapping(/) for your Spring DispatcherServlet. All the requests are forward to Spring servlet:
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
I workaround this situation by using *.do for my Spring controllers and update the servlet mapping as mentioned here:
<servlet-mapping>
<servlet-name>appServlet/servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
But this will require you to update the 'calls to your Spring controller' with a .do at the end of the URLs.

Configuring Restlet with App engine

I am using google app engine to develop my software's backend using java along with Restlet framework. I have index.jsp under my war directory which I want to treat as default page when somebody goes to my website(e.g. example.com). So I have mentioned it under welcome-file-list section in web.xml.
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
Also, I have my Restlet servlet mapped to "/*" in web.xml.
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
But the problem occurs here, because even the call to default page i.e. example.com, also goes to the restlet which obviously doesn't find the mapping in its router. So I decided to instead map restlet servlet to "/restlet/*".
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/restlet/*</url-pattern>
</servlet-mapping>
But with this I get the HTTP 404 error because somehow even though web.xml successfully routes the call to restlet, but restlet doesn't find the mapping in this case in its router object. I have obviously changed the mapping in the restlet router to match the new pattern "restlet/*".
router.attach("/restlet/doSomething",DoSomething.class);
It would be really great if someone can help me with this. Following is my complete web.xml:
<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
<init-param>
<param-name>org.restlet.application</param-name>
<param-value>com.mWallet.loyaltyCardCase.LoyaltyCardCaseWebService
</param-value>
</init-param>
</servlet>
<!-- Catch all requests -->
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/restlet/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
Thanks!
Manas
You don't need to change the mapping in the restlet router to match the new pattern "restlet/*" because the restlet router will now be considering "example.com/restlet/" as the base url.
So, if you change the router to match "/restlet/doSomething", your actual url will be "example.com/restlet/restlet/doSomething", which obviously will not work.
So, change your restlet routing to:
router.attach("/doSomething",DoSomething.class);
I did it in my project and its working.
i think you forgot to write below code in web.xml
<servlet>
<servlet-name>RestletServlet</servlet-name>
<servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
<init-param>
<param-name>org.restlet.application</param-name>
<param-value>com.wa.gwtamazon.server.RestApi</param-value>
</init-param>
<!-- Catch all requests -->
<servlet-mapping>
<servlet-name>RestletServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
and i already answer in this link Restlet API example may will help you.

Servlet not loading on startup

TL;DR: <load-on-startup> does not seem to be causing my Jersey web services to load on startup
I’m trying to set up a simple RESTful web service that will act as a registry for the other RESTful services in the container.
To do this I had planned on registering each other web service with the registry service in a static initialize block. Everything was going well until I remembered that servlets aren’t loaded until their first access.
A quick web search turned up the <load-on-startup> tag that can be added to the servlet definition in web.xml. Unfortunately, this was already set in my configuration and adding some logging to the static blocks verified that the classes were indeed not being loaded until the first access of each service.
I’m developing these servlets using Jersey annotations and deploying them to Apache Tomcat (both 7.0.22 embedded in netbeans and 6.0.33 deployed remotely fail in the same way).
Besides this perceived misbehavior, the servlets have been performing correctly.
Any ideas on what I could be doing wrong?
My web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>CORSFilter</filter-name>
<filter-class>com.foo.bar.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>ServletAdaptor</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<description>Multiple packages, separated by semicolon(;), can be specified in param-value</description>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.foo.bar.webservices</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>
It was a couple years ago and a couple years of Java Web Stack knowledge later.
I believe this was a case of mistaken identity. I had a non container managed resource that I was trying to get to load on startup. The jersey servlet container was most assuredly loading on start up as the web.xml was specifying. The classes that I wanted to preload were not being referenced by the container itself so were not being loaded with the container.

Categories