Best way of cache-management with spring for static files - java

I want use cache control in spring mvc for static files.
I have gone through the following scenarios
Using WebContentHandlerInterceptor.
Using browser cache headers.
Using mvc:resources
Version number/build number for the js files.
But my problem is when the user comes for the first time it is loaded with the latest static files. If I update any JS files that are needed to be updated in the test or production server before the cache expiration. The browser is taking only from cache until I reload using F5 or Ctrl+F5.
When the user is requested a page, then all static files are to be checked and if they are not modified then it has to use cache otherwise take the latest one from the server.
Please help me.. I am newbee to this stackoverflow.

To ensure browser to download the latest version of your static files is to add a parameter to the URL.
For example, your request will look like resources/scripts/menu.js?ver=1.0.

Related

Remove .html extension using Google Appengine with Java

I am incredibly confused here. I've been using Google Appengine for our webserver and it's been working out great so far, but I had a request to have the webpages load without the .html extension. I've been doing some reading and see that I need to create an app.yaml file to map the url to something else? This is what I have in my file so far:
application: company-website
version: 1
runtime: java
threadsafe: true
handlers:
- url: /about
script: about.html
I've been trying to read how to do this on their documentation site but I can't seem to find anything referencing how to remove the extension and still have it point to the right html file. Can anyone help me out? Can I just do this in the appengine-web.xml file, also? It seems like I could just do it in there without creating an app.yaml file.
Any help would be appreciated. Thanks!
edit: tried some more things.. Tried moving the file I'm trying to remove the extension on to its own folder like so:
/root
-index.html
-/about
-index.html
And this was OK, when I typed my domain.com/about/ it appears to be working but when I typed domain.com/about it does not. Very frustrating.
In an ideal world we would have the option to configure a rewrite like apache's mod_rewrite in the underlying web server. Sadly it is not possible to configure a rewrite on such a level.
I searched around a bit and found that the most common answer for a rewrite is to user either UrlRewriteFilter or to wire up the servlets yourself. Both options are explained in
Catch-all URL rewrite on Google App Engine (Java)
Pretty URLs in Google App Engine
Both work in the same way and will require the app to serve static content through app engine. This will result in app engine instance hours and slower responses since all you static files move from Google's content delivery network (cdn) to your bottleneck app. The aproaches possibly also require you to deploy your static files as resource instead (How-To configure static-files and resources), at least that is how i have done this before.
These are the 'pure Java' options you have. The app.yaml approach that Josep Valls described will work in with Java on App Engine. The main question here is if the app.yaml configuration is low level enough to be a rewrite that google recognizes in its cdn, or whether you'll still burn through instance hours because all content is served through instances.
The documentation tells us:
For efficiency, App Engine stores and serves static files separately
from application files. Static files are not available in the
application's file system. If you have data files that need to be read
by the application code, the data files must be application files, and
must not be matched by a static file pattern.
Since this comes right before the section that explains how to configure the static file pattern handlers one should assume that the configuration of such handlers will not break the logic that is mentioned above - that is
stores and serves static files separately from application files
Whether this assumption is correct is an easy experiment which i shall conduct given time and report my findings here.
These are all the existing options I could find and know of. If anyone knows more on this topic, please comment / respond.
EDIT (7.12.2015)
My maven target appengine:devserver is completely oblivious to settings in the app.yaml. I'll have to experiment with this during one of the next deployment phases or use mvn gcloud:run.
... later that day:
Rewriting the URL via Servlet (like with Paul Tuckey's UrlRewriteFilter) does not work for static files. You would have to deploy the files as resource files. Static files reside somewhere else and will not be found if forwarded to by a servlet. At least that's how i understand it.
In Python and Go you can use regular expression matching in your url handlers; if Java also uses app.yaml you could probably do this:
- url: /(about|other|sections)$
static_files: \1\.html

Caching with Play framework and Java

I am running an application with Play and Java, and I need to set up expiration date for various types of assets: images, css, javascript etc.
I have the following in the conf/routes file:
GET /assets/*file controllers.Assets.at(path="/public", file)
I was able to set expiration date for one individual file in application.conf:
"assets.cache./public/js/pages/validation.js"="max-age=7200"
But I am not able to set it for a whole folder. I have tried
"assets.cache./public/js/pages/*.js"="max-age=7200"
"assets.cache./public/js/pages/*"="max-age=7200"
but nothing happens. I was hoping to set the expiration date for everything in the /js/pages folder.
I've also tried
assets.defaultCache="max-age=7200"
per instructions at
http://www.jamesward.com/2014/04/29/optimizing-static-asset-loading-with-play-framework
as well as
http.cacheControl=7200
per documentation http://www.playframework.com/documentation/1.2.3/configuration#http
and none of these work. The changes above were done in application.conf.
I know there is a way to do the same by defining controllers that change the response() for the routes that I want to set the expiration date for:
far future Expires header for static contents
But I would like to know how to configure expiration date for assets from the application.conf file.
Our application is running on S3 Linux instances, so configuring the expire date on the server is not an option.
Thank you!
Play framework does not support "assets.cache./public/js/pages/*.js"="max-age=7200"
but assets.defaultCache="max-age=7200" should work.
In debug/dev mode (starting app using play run) assets.defaultCache is ignored, so it is always 'no-cache'. Make sure you are running it in prod mode(using play start).
I can't find any reference in docs, but same can be checked in https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/play/api/controllers/Assets.scala AssetInfo::cacheControl function

Displaying images from outside of java application context.

This was a question about testing file upload functionality using a local java server on Windows 7 platform. Since the question evolved with Marko's input, I have edited it, so that those who run into the same challenge do not waste time on evolution details and reach conclusions sooner.
The challenge was to direct uploaded file to a folder outside of the WAR structure and successfully read it from there. For example: upload an image into c:/tmp/ and then redirect to a confirmation page that displays the image <img src="c:/tmp/test.jpg" />. The upload worked but image would not be displayed. And based on Marko's input, this makes sense because browser sitting at localhost will refuse to load anything from local disk structure using c:. Maybe these are security considerations similar to those with file input control where we cannot set a default path...
The following tag will work in a locally created .html file but when pasted into a jsp, it won't work. And the difference is that browser uses localhost to get to the jsp.
<img src="c:/tmp/test.jpg" />
Solutions
I think that Marko's answer pretty much defines what needs to be done. While I didn't go with that approach, it clearly is the better way to do it and I will accept that as the answer. Thanks, Marko!
For those who don't want to bother installing a Web server and are willing to live with a bit of a hack, here's what I have done. Again, I didn't want to upload files into my WAR structure because I would then need to remember about clearing that folder before deploying to the server. But that upload folder still needs to be accessible, so I simply created another dummy project and put that upload folder under its WebContent. This works for the purposes of my local testing. The only nuisance is that after uploading a file, I need to refresh the dummy project's WebContent in Eclipse.
config.properties
#for uploading files
fileUploadDirectory=C:/javawork/modelsite/tmp/WebContent
#for building html links
publicFileServicePrefix=http://localhost:8080/tmp
<img src="http://localhost:8080/tmp/test.jpg" /> // this works - tmp is the name of my dummy project.
If you are citing literally the HTML that goes to the browser (the one that you access via "vieew source") then this has nothing to do with Java. The browser is the one who interprets these links. If they fail to load, the problem is in the browser/file system.
UPDATE
According to the results of your additional diagnostics, I conclude that the browser (sensibly!) refuses to load anything from your local disk if it is referenced from an HTML file coming from an internet URL, even when that URL is localhost.
UPDATE 2
(Deleted, irrelevant)
UPDATE 3
However you handle the files uploaded to the server, it's definitely not going to look like your solution -- the file is on the server's local filesystem, not client's. This sort of thing can be handled at the Apache HTTP server level -- reserve an URL section for static content and configure Apache with a base directory from which to serve the static content. Even if you run the server locally, on the same machine where you test it, you still need to go through the network interface.

A static file upload (text or HTML) cause full deployment in Google App Engine?

I have to change some contents in a html or text file. Or I have to upload an image. I have to re-deploy my application on GAE. Is there any way that I can upload such static files to the desire location from my hard disk?
Please thanks for your help.
Changing the static data you're serving requires a redeploy, always. Note that App Engine only uploads the modified files, though, not everything.
If you wish, you can serve 'static' files from the datastore, though.
No. You will have to redeploy your app in order to upload/update a static file.
But, one can easily find themselves in a scenario where you may wish to update a static file without redeploying. For e.g. suppose I changed some code in some java classes and the changes are still incomplete. Meanwhile, if I wish to change some css style or upload an image, i'll have to wait till the java classes are ready.
One workaround is that you can deploy your app(provided there are no compilation error) to a new major version. Since the static files are shared across all versions, you can see the changes appear in other versions too.

applet fails to load class from jar

Some users are complaining that the applet no longer works, When they view the java console they are greeted with a java.lang.noClassDefFoundError and checking my access log's I see they have downloaded the jar file that contains the class, and then issue a get request for the particular class.
Different users break on different classes.
Some users are fine.
Any ideas what could cause this/fix this.
I have checked to make sure the file is in their java cache, cleared the cache etc. nothing seems to fix them.
If they hit a qa site it breaks as well.
The jar is getting corrupted in transit, We are looking at getting patches from oracle/bea for the server.
It appears that if a connection is too slow (Modem speeds) that weblogic will signal the end of a transfer by sending a packet with len=0.
The network will signal java saying the download completed successfully and then java fails with a java.lang.noClassDefFoundError.
This can occur if the class itself can be loaded but some dependency of that class cannot be. Are there external JARs that are dependencies?
Are you sure the jar file contains all the necessary classes? Open it up in your favorite Zip application and double check. Maybe a recent build of that jar got messed up and doesn't have everything in it.
I'm assuming that you have made some updates by your wording. It is highly likely that some users have a previous Jar file cached.
When deploying a new applet version in a live configuration I perform the following:
Ensure the page holding the applet is not cached - use HTTP no-caching techniques. You may want to redeploy from a new page with these headers to ensure that it's not the case.
Deploy the jar file from a different URL for each update (I encode the version number in a directory, but you can equally rename the jar file).
If applet performs any client server interaction ensure that you check version numbers and report incorrect version to the user.
Even if you follow this the user may still have a problem, ask them to try these one at a time (listed in order they should try):
Press refresh on the browser window.
Restart all browser windows
Uninstall all Java VMs found on "Add/Remove programmes" and reinstall latest Java (yes, they must do this at their own risk!)

Categories

Resources