Webstart

Started by psiegel, June 15, 2004, 15:58:38

Previous topic - Next topic

psiegel

So, I've been asked to produce a webstart version of Danger Maze by some members of the java gaming community.  I've been looking into it, but I can't get the dratted thing to work.  I'm hoping someone (ahem, Cas) might have some experience and would be able to offer some enlightenment.

I've got my jnlp file and signed jars all up and ready to go.  When I hit the link though, after downloading all the files, I get a null pointer exception and the thing quits.  If I then navigate to the directory where webstart drops the jar files and manually run the game using java on the command line, the game runs fine!  To aid in my debugging, my game does write out a log file, however I can't find this file anywhere when the game is run via webstart.

I'm starting to suspect that perhaps it's attempting to write this file that's causing the webstart version to choke.  Are there any operations (such as writing out files) that can't be done from within the webstart runtime?  Is there a good way to debug a webstart application?

Paul

psiegel

Well, after some hacking, I came up with the idea to catch the null pointer exception in my main function and then wrap all the text from the stack trace of that exception into a new RuntimeException.  Throwing this RuntimeException caused the output of that stack trace to appear in the webstart gui.

Anyway, I've discovered that the culprit is my resource loading.  I've tried this about a dozen different ways and nothing works.  I'm trying to get an InputStream, and I've tried the method getResourceAsStream(), as well as simply getResource().openStream().  I've called these two methods on all of the following classes:

ClassLoader.getSystemClassLoader().getClass();
DangerMaze.class.getClassLoader();
DangerMaze.class;

None of these things work.  The first resource I try to load is even a simple config file that's packed into the same jar as all my class files, and yet still it comes back as null.  I've tried both the raw file name, and prepending a "/".  Nothing!  Anyone have any ideas?

Paul

psiegel

Tap, tap, tap.  Anyone here?

Ok, so I managed to figure this one out, though it was painful.  I was originally attempting to do everything from within a static method.  Finally, I decided to just create a new singleton object which would be in charge of loading files from disk (or jar, as the case may be) in which I could call getClass().  I was able to successfully load stuff from my jars in webstart by calling:

URL url = getClass().getResource("/" + myResourceName);
InputStream in = url.openStream();


Using getClass().getResourceAsStream() would fail, as well as using getClass().getClassLoader() in any way.  It seems the above is the one and only way to do it.  Lame, but there you have it.  Thought I'd share my findings with anyone who might be interested.

Paul

princec

Eh, that's a bit weird. I use getClass().getResourceAsStream("/blah.dat") without any trouble at all.

Cas :)

psiegel

Yeah, I've definitely tried the "AsStream" versions and they only ever returned null.  Very strange.

While we're on the topic, what do you do for output files?  I need to create a log file, and we're considering pre-processing some images and writing them back out to disk on the first time run to increase level load time.  Up until now I've been dropping files right in the working directory, assuming it was the directory the game is installed to.  However with webstart, the working directory seems to be kind of random.

I've discovered that in linux it's the home directory, while in Windows it's the user's desktop when using IE or the webstart created shortcuts.  Worst of all, on Windows running Mozilla Firebird, the working directory is the Firebird install directory.  Ugh!

I've been thinking of using System.getProperty("user.home") and creating a subfolder called ".dangermaze", but what happens when someone uses the webstart gui to remove the app?  I'm sure that directory will get orphaned on the machine.  Is there any way to drop files into the same place webstart is caching the jar files?

Paul

princec

The Webstart persistence service. Currently I use the method you describe and leave a bit of crap on the harddisk. Wooo. I've filled 5mb of space on someone's 100GB HDD and not cleaned up after me. Bad Caspian.

Cas :)

psiegel

The webstart persistance service claims to behave like cookies, so presumably there's a size limit on the data you can store that's fairly small.  Fine for a simple log file, but 5 MB of image data I think will likely break it.  Also, I feel a little like this breaks the old "write once run anywhere" paradigm, as now I have to detect whether or not I'm being run in a webstart environment or a standard application environment.  (I'm assuming these webstart services aren't available to an app that's run via java on the command line.)

I'm sure like you I'll just end up just dropping it all into a directory in the user's directory and suck up the idea that it's going to be orphaned if/when the user uninstalls the app.  Of course, I never expected much from the webstart uninstaller, and would be surprised if anyone actually ever uses it.  At least in my non-webstart distros I can keep writing to the working directory and be assured that this crap will get deleted on uninstall.  

I suppose this all just amounts to more ammo for my "why I don't like webstart" rant.

Paul

blah

From memory, the persistence service was / was accompanied by something spefically designed for caching arbitrarily large amounts of data locally.

Alternatively - and perhaps much much more neatly - you could perhaps use temporary files (the File API has special methods for this) for your image caching etc. From memory, it's up to the OS when to delete them, and most OS's don't delete until the machine is rebooted - or maybe not even then, if there's plenty of free disk space. You can insist that the file is deleted when the JVM exits - or not!

IIRC, I've created temp files, and told the JVM to leave them. They've then sat in my /tmp directory on linux for months. It would be nice to imagine that windows would do something similar, and would only completely clear out the temp directory when that "you have run out of disk space. I can autmoatically recover XXX Mb. You may want to delete additional files" dialog appears. ?

...

As for logfiles, you should probably be just logging to System.out, and which webstart automatically captures and puts in a file IF THE USER WANTS IT. If someone has a bug and it's repeatable it takes one email to tell them to turn on the logging in the webstart GUI; if it's not repeatable, my logging probably won't have recorded enough info for me to debug it anyway (since it's likely a race condition, which requirs a lot more debugging than I'd leave in a production build!).

So, I'm tempted to believe that a developer who doesn't like this and insists on creating a log file independent of user choice is overstepping their bounds - it's my PC, not theirs.

psiegel

The temporary file idea isn't bad.  It certainly feels better to me than just ditching some files in the user's home directory.  I'd still prefer to put the files someplace where an uninstaller can clean them up.  I suppose I could try to use the working directory first, but check if "dangermaze.jar" exists in the working directory, and if not revert to using temporary files.  Of course, if the OS does delete the temporary files we'd have to recreate them on the next run of the game, and that's not great.   It's a tough call on which is worse: abandoning 5-10 MB of files or possibly deleting said files to early having to delay game load time to recreate them.

As for the logging -- we use the java.util.logging facility.  We have it configured to go to both System.err and a file.  The level of detail in the log file is user configurable, and I suppose we could make the dropping of a file configurable as well, though honestly I never thought anyone would begrudge us a <10 KB text file.  And one less step in debugging is always nice -- got a problem, just send us the log file.

Hmm, now that I think of it, our user settings are going to be an issue as well.  These are in a settings.cfg file that we include in our distribution, which a webstart user isn't going to have access to being that it has to be packed inside a jar.  I suppose we'll have to copy that file to another location so the user can have access to it.  Which brings me right back to making a directory in the user folder that will ultimately get abandoned.  That or make a gui front end to the settings in the game, though that's a bit of a pain in the ass.  Oh well, I suppose we wouldn't be the first app to abandon files in the user directory.

You know, it'd be nice if webstart had some facility for specifying application created files that should be removed along with the app itself on uninstall.  Or some kind of hooks into the uninstall process for specifying custom operations.

Paul

princec

I really wouldn't worry about putting crap in the user's home directory. If they're uninstalling ... then you probably haven't impressed them anyway and you're not losing a customer.

Cas :)

blah

Quote from: "psiegel"
Hmm, now that I think of it, our user settings are going to be an issue as well.  These are in a settings.cfg file that we include in our distribution, which a webstart user isn't going to have access to being that it has to be packed inside a jar.  

Use muffins for this? Thats pretty much what they're meant for IIRC...

Quote
You know, it'd be nice if webstart had some facility for specifying application created files that should be removed along with the app itself on uninstall.  Or some kind of hooks into the uninstall process for specifying custom operations.
Paul

Seconded, with great feeling  :?

gregorypierce

Quote from: "princec"I really wouldn't worry about putting crap in the user's home directory. If they're uninstalling ... then you probably haven't impressed them anyway and you're not losing a customer.

Cas :)

Evil  :twisted:

princec

:P
What's the size limit on muffins? I'd use them but I need, like, 20MB of space.

Cas :)

oNyx

Nobody knows :?

QuoteA JNLP client should track the amount of storage that a given application uses. A PersistenceService implementation provides methods to get the current storage usage and limits and to request more storage. Storage is allocated on a per file basis, but a JNLP Client will typically grant or deny the request based on the total storage is use by an application.

So basically... no idea. It seems to work fine for pretty small files... hadn't tried anything bigger than ~2kb yet.

oNyx

Meh knows! :D

Requesting 0xFFFFFF bytes results in this:

(the 1.4.x dialog is similar)

If the user presses 'Yes' you get everything you wanna... and if he presses 'No' all you get is ~262kb (in this case at least).

long granted=ps.create(muffinURL, 0xFFFFFF);

There you get the number of bytes you can use.

Well, that's cool... kinda.