views:

1203

answers:

4

The example documentation says that you simply need to place your files in war/ (or a subdirectory) and they should be accessible from the host (as long as they aren't JSPs or in WEB-INF). For example, if you place foo.css in war/ then you should be able to access it at http://localhost:8080/foo.css. However, this isn't working for me at all. NONE of my static files are accessible.

The docs on appengine-web.xml say that you can also specifically denote certain types as static. I've tried this as well and it makes no difference.

Am I missing something obvious?

UPDATE: Turns out one of the mappings in my web.xml was a little too aggressive. The following was the culprit:

<servlet>
 <servlet-name>Main</servlet-name>
 <servlet-class>MainServlet</servlet-class>
</servlet>
<servlet-mapping>
 <servlet-name>Main</servlet-name>
 <url-pattern>/</url-pattern>
</servlet-mapping>

It seems that it was grabbing everything that wasn't grabbed be one of the other rules, which I don't understand because there was no * on the end of the url-pattern. It also seems to be directly contradictory to the documentation that says:

Note: Static files, files that are served verbatim to users such as images, CSS or JavaScript, are handled separately from paths mentioned in the deployment descriptor. A request for a URL path that matches a path to a file in the WAR that's considered a static file will serve the file, regardless of servlet and filter mappings in the deployment descriptor. You can exclude files from those treated as static files using the appengine-web.xml file.

So, how can I have a rule that matches the base of my domain (eg. http://www.example.com/) and still allows the static files to filter through?

A: 
jitter
Er, what? He _wants_ to serve his css as static; what you're suggesting will ensure they're not.
Nick Johnson
Ahem... misread WEB-INF for WAR and thought mayb they can't reside in toplevel dir.
jitter
A: 

When using e.g tomcat for serving static files one has to specify the patterns like this:

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
</servlet-mapping>

Maybe you could try to do the same?

jakob
+1  A: 

Try manually defining the static files in appengine-web.xml like

<static-files>
  <include path="/favicon.ico" expiration="1d" />
  <include path="/static/**" />
  <include path="/**.css" />      
</static-files>

This works for me even with servlets like

<servlet-mapping>
 <servlet-name>testServlet</servlet-name>
 <url-pattern>/</url-pattern>
</servlet-mapping>

and

<servlet-mapping>
 <servlet-name>testServlet</servlet-name>
 <url-pattern>/*</url-pattern>
</servlet-mapping>

See Static Files and Resource Files

zockman
A: 

... It seems that it was grabbing everything that wasn't grabbed be one of the other rules, which I don't understand because there was no * on the end of the url-pattern. ...

[[Unfortunately, the term "default servlet" is overloaded to mean differnt things - leading to confusion. I'll try to be clear.]]

The url-pattern "/" is special (Rogue Wave calls this the "default mapping"). This defines the application's "default servlet", which is used when the URL request does not match other patterns (SRV.11.2 bullet 3 and SRV 11.1 item #4). Apparently, "/" is handled as if you specified "/*".

... It also seems to be directly contradictory to the documentation ...

Agreed, I think app engine has a bug so its not following the documentation you cited. Here's my theory of what is going on. Since there is a default servlet for your app (resulting from defining a servlet for url pattern "/"), the app stops using "default" "default servlet" provided by the container for apps that don't define their own "default servlet". The container's "default" "default servlet" is what provides the default behavior for serving up static files. I think this is consistent with how some containers behave.

I wonder what would happen if you tried specifying a servlet for a URL pattern that matches a static file. Would it serve the file (as indicated by the docs) or invoke the servlet (as indicated by this theory).

... So, how can I have a rule that matches the base of my domain (eg. http://www.example.com/) and still allows the static files to filter through? ...

If the theory is right, the solutions provided by jacob (adapted for google app engine) and zockman seem like they'd work - they map the static files to the container's "default" "default servlet".

The only other idea I have is to write your app's "default servlet" to examine the request to see if the request is for "/" or not. If so, handle it. If not, then (somehow) invoke the container's "default" "default servlet" to process the request (which will hopefully cache the file). Hopefully, once the static file has been served once, caching will bypass the servlet(s) in the future.

Sorry, I can't be more specific or provide code - I haven't work with Google app engine (yet!).


Ref:

Bert F