Alternate servlet definition to web.xml? - google-app-engine

I am using google app engine, and I define all my servlet paths in web.xml. Is there a way to define these in code instead of xml? I ask because the web.xml file is very verbose and I have many servlets. If I could register the servlets in java code somewhere I can probably shorten things.
Thanks

You can define a "main" servlet whose job it is to dispatch to other servlets; in your web.xml, you would write something like:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>com.mydomain.myapp.Dispatcher</servlet-class>
</servlet>
</web-app>
This would map /* (your entire app) to your dispatcher class. You could then register your various servlets with the dispatcher under different paths (e.g. you could use the Spring DispatcherServlet or your own).

Related

How do I configure Java EE running on GAE to work with Angular UI Router in html5Mode?

I am attempting to set the UI Router location provider html5Mode to true for my Angular application: locationProvider.html5Mode(true). While this works client side (appropriately redirects) I am running into issues server side. I am running an instance Java Enterprise Edition on Google App Engine.
I have configured my web.xml as outlined for Java EE section in the Angular ui-router FAQ:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
<error-page>
<error-code>404</error-code>
<location>/</location>
</error-page>
<servlet>
<servlet-name>SystemServiceServlet</servlet-name>
<servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
<init-param>
<param-name>services</param-name>
<param-value>
<!-- stuff specific to my GAE app -->
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SystemServiceServlet</servlet-name>
<url-pattern>/_ah/spi/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Sadly even with the above configuration when I browse to client based routes I am still receiving a 404 error from the server. I have tried various values (/index.html, index.html) for the error-page > location element with the same result.
I am probably missing something obvious in my configuration, but am at a loss to what I am doing wrong.

Mapping two servlets in web.xml where one URL pattern is substring of the other

I have a web application where I would like to tie a JSP to address http://host:port/status and a servlet to addresses like http://host:port/status/.... Is this possible? According to this article it should be possible ("container prefers an exact path match over a wildcard path match") at least for some containers and the Java Servlet Specification contains similar examples (albeit without wildcard, on p. 12-123 in April 2013 version), but if I try the following in web.xml it appears as if the JSP is never called and all requests (also to http://host:port/status) are routed to the servlet. My JSP and servlet are hosted on Google App Engine.
<servlet>
<servlet-name>Status</servlet-name>
<jsp-file>/Status.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>Status</servlet-name>
<url-pattern>/status</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>StatusUpload</servlet-name>
<servlet-class>com.example.StatusUploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>StatusUpload</servlet-name>
<url-pattern>/status/*</url-pattern>
</servlet-mapping>
Instead of mapping the same url to two different JSPs/Servlets in web.xml you can use a URL Rewriting filter like Tuckey UrlRewriteFilter which uses a configuration file urlrewrite.xml which would also be placed in WEB-INF. It uses regex in the rules.
These two rules should do what you want:
<rule>
<from>^/status$</from>
<to>/Status.jsp</to>
</rule>
<rule>
<from>^/status/(.*)$</from>
<to>/StatusUpload/?param=$1</to>
</rule>
Then in WEB-INF you would not map the JSP anymore but would map the Servlet to StatusUpload. When the user goes to /status/postfix the URL Rewriting filter will forward to the servlet (with the postfix part passed as a parameter) in the backend without the address the user sees in the address bar changing.

Servlet-Filter is not honoured for welcome file

I am using a Filter do generate dynamicly content to be visible for webcrawlers (https://developers.google.com/webmasters/ajax-crawling/docs/specification). This filter is working fine if the incoming url contains a path (http://www.unclestock.com/app.jsp#!s=GOOG). If the incoming url contains just my domain (and a fragment), say http://www.unclestock.com#!s=GOOG, the welcome file (app.jsp) is returned, but the filter is not honnoured.
My web.xml contains the following filter map:
<filter-mapping>
<filter-name>crawler</filter-name>
<url-pattern>/app.jsp</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>app.jsp</welcome-file>
</welcome-file-list>
I have tried to use an index.html welcome file instead, which redirects to app.jsp. The filter is then executed. However, this does not solve my problem: A client side redirect is not followed by the crawlers (which is the idea), and with server side redirect, I would loose my url fragment (which I also need).
Do you see any alternative solution?
I'm using Google Appengine.
I solved it by using a welcome servlet which does a RequestDispatcher forward. Note that the dispatcher FORWARD must be added to the filter-mapping in order to have the filter working during the foward.
web.xml:
<filter-mapping>
<filter-name>crawler</filter-name>
<url-pattern>*.jsp</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<welcome-file-list>
<welcome-file>welcome</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>welcome</servlet-name>
<servlet-class>Welcome</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>welcome</servlet-name>
<url-pattern>/welcome</url-pattern>
</servlet-mapping>
Welcome.java:
public class Welcome extends RemoteServiceServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
RequestDispatcher rd = req.getRequestDispatcher("app.jsp");
rd.forward(req, resp);
}
}

My controller/servlet with "/" mapping isn't overriding "Hello App Engine!"

I'm working with Spring MVC on google app engine and even though I've gotten a basic hello world example working, I can't get my servlet to show up when I use the request mapping of "/". Even when I specify "/" as my request mapping in my controller, I keep getting the "Hello App Engine!" page with a link to my project. I've already pulled the welcome-file declaration out of my web xml.
Basically...
package my.package.for.spring.stuff.controllers;
import ....;
// It doesn't seem to make a difference if
// I have this reqeustmapping or not...
#Controller
public class MainController {
// If I change mapping to "/main" and then go to
// localhost:8888/main then everything works as expected
#RequestMapping("/")
public String HelloWorld() {
return "MyView";
}
}
is still going to the "Hello App Engine!" page. Also, here is my web.xml...
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<servlet>
<servlet-name>SpringAppEngine</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringAppEngine</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
And then here is my spring xml...
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="my.package.for.spring.stuff" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/views/main/" p:suffix=".jsp" />
</beans>
Why is the app engine generated welcome file still showing up even though I'm declaring the root mapping in my controller? I know my setup should be right because when I change the requestmapping, everything works as expected.
The servlet 3.0 spec says:
A string containing only the ’/’ character indicates the "default"
servlet of the application.
And it also says:
By default all applications will have index.htm(l) and index.jsp in
the list of welcome-file-list. The descriptor may to be used to
override these default settings.
So, I guess that the container considers that the implicit index.html welcome file is an exact match, which takes precedence over the default servlet mapped to /.
The solution is to delete the index.html file or, probably, to define an explicit empty welcome file list in the descriptor.
Apparently pulling the index.html mapping out of the web.xml isn't enough, you actually have to delete the index.html. If someone can post an answer explaining why I'll still upvote and accept.
This post helped me and I think I can expand on why removing the file fixes the problem. According the GAE, any file in the war directory (except JSPs and anything in WEB-INF) gets a mapping to that file name. This implicit mapping appears to supercede any servlet rules in web.xml:
https://developers.google.com/appengine/docs/java/gettingstarted/staticfiles
Once you remove or rename index.html, your servlet rule for "/" is used instead of the implicit mapping for the static file.

Tomcat, web.xml, exclude path

In my application, i need to process all the requests from users in a single servlet, however, i happen to have a folder with static content, which i would like to also serve statically.
In my web.xml file, i have the following:
<servlet>
<servlet-name>all</servlet-name>
<servlet-class>a.b.c.WidgetlistXml</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>all</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Is there a way i can exclude, say, all .zip files from this?
PS. I know this has been asked on StackOverflow before, but the latest posts were from about 2006, and they also concerned Spring or other frameworks. I use none, and since 2006 something could have changed in url-patterns. By the way, finding the docs on web.xml is not that simple either.
Thank you in advance.
Set a DefaultServlet for your static contents. Here is an example:
http://tomcat.apache.org/tomcat-7.0-doc/default-servlet.html#where

Resources