Saturday, November 06, 2010

Finally we've got Base64 in Java...

It was always a pain and we used those strange Sun packages (crossing fingers, of course). But now Java 6 has a little thing, that is a standard package and won't collide, at least:

public static byte[] decodeFromBase64(String encoded) {
return javax.xml.bind.DatatypeConverter
.parseBase64Binary(encoded);
}

public static String encodeToBase64(byte[] binary) {
return javax.xml.bind.DatatypeConverter
.printBase64Binary(binary);
}

Nothing special. Just nice to know. :-)

Thursday, October 28, 2010

VMWare and Spring

VMWare bangs their bells for Spring framework, trying to tell it is best choice. Lots of people excited etc.

Now (*cracks my fingers*) questions and doubts:
  1. Spring's arguments are valid. Yes, they are. With one little note: they are valid on EJB2 and JEE5, where first one has incredibly bad design, another is bulky and not really convenient. Wait a second... but we are not talking for old projects future, but for new! So, when you going to choose framework for plain new project, the we do have EJB3 and JEE6 today.
  2. RedHat (also known as a leader at Enterprises in Linux world, by the way) and Snorcle (also know as Oracle, also known as benevolent dictator, also known as Sun Microsystems eater) — both of them completely don't really like Spring. In fact, they think it is a bullshit and they think JEE6 would fit to your datacenter much better.
  3. Do you really like that XML thing? I think this is all like back to a stone-age, instead have just everything minimalistic and cute (means: modern).
  4. Template classes as intrusive as it turns your code to a bullshit. Yes, you can have a workaround for this, but the keywords here are still stays to "bad" and "design".
  5. Tell me, you configuring or you coding?.. In Spring you will code^H^H^H^Hconfigure your project in XML. Well, no, you're literally coding. You are freakin' coding in XML, don't get fooled and mislead.

    Let me explain here a bit: a configuration file is something like you can find in Unix /etc directory. It is a small, simple ASCII text file, you can put comments in there and you can parse it with your Perl/Python/Ruby or just AWK/Sed. This is what is called: configuration file and was more than 30 years around. Now what Spring brings you into? A pile of XML, that are actually built into your WAR file. They do believe you have to change XML, so no need to change source code of Java.

    But this is utterly misleading: you intrude to a deployed application anyway (sane companies will put it through a "Change Request" procedure that involves also testing and quality assurance sometimes), while configuring application means you change only that little cute file in /etc directory (or click few checkboxes in admin UI) and thus your buddy sysadmin can do that with a cigarette in his teeth with a little effort (change request still required, but a consequences are significantly smaller).
  6. Spring adds complexity, it does not removes it. Don't be fooled: you will need to have a serious and difficult learning curve as well as you will need to spend weeks to configure your XML (see above).
  7. Bugs in framework itself will cost you a lot. So make sure your framework is extensively supported, reviewed and updated. Who you will trust more: giants like Oracle and RedHat that has tons of very fat customers, or just a little VMWare — yet another player in virtual world with not the best business model? You choose.
  8. OK, you can dismiss my XML rants by changing from XML to annotations. Great point! Because here is another problem: different ways to do the same thing. Java coders chronically away from Unix, but we already been there and we know it is called as "Tim Toady" or TMTOWTDI or "There's More Than One Way To Do It" or, simply Perl. It results to things like this or like this. In contrast, the beauty of Python language lays in its great philosophy: "There should be only one — and preferably only one — obvious way to do it".
    Little note to above: I was not talking about code obfuscation.
  9. We already learned that doing often casting is a bad idea. So that's why we do have Generics for this and why we are trying to go away from casting operations as much as far as possible. However, Spring is pushing you back to a mesozoic era to fight java.lang.ClassCastException dinosaurs each next step. Stupid.
  10. \u3042\u306a\u305f\u306f\u99ac\u9e7f\u3067\u3059 — this is how to say "Good morning" to your boss in Japanese (anata ha baka desu), or exactly what you will get, once you open your ResourceBundle in VIM editor.
  11. It is going up to eleven... You normally should keep SQL separate from the code. Try it with Spring and see how it works (or not) for you.
Of course, the main question still around: Why bother with Spring, if JEE6:
  • Is getting to be more and more lightweight than Spring 3
  • Is less complicated (recently) than Spring 3
  • Is well designed
  • Is well documented
  • Is well supported
  • Is an industry standard and chosen by industry leaders (sure).
  • Has more features
  • Is easier to learn (because it is less complicated)
  • Is not proprietary, versus Spring which is proprietary container.
I certainly don't have an answer on above. Maybe you have?

Feel free to explain. :-)

Tuesday, October 19, 2010

JSR 286 and crying developers

JSR 286 is probably a primary way of how any web-related stuff should be done. Definitely. However, it has some nasty limitations, that would lead novice to hit the wall, step on rake, step on rake again etc. One of such limitations (well, not really, but still) is to return a file. Normally, JSR286 wants you to return HTML. But what if you want to click on some button and get a PDF file or TIFF or DOC or MP3 and so on? Usually, developers are setting content type, putting some content disposition to define filename etc, put some headers to flush cache, write to the output stream, recompile and deploy.

Problem solved.
No, not really: once they call their portlet, entire application disappears and log is filled with devil's 666 lines of Java traceback from Hell. So, random desperate rants over forums begins usually with "me too!" or "pass me some code!" messages.
The real thing is: you need to read JSR286 properly. See, the JSR 168 does not allows us to use something else than just HTML. Pretty much silly. But JSR 286 allows. How? Easy: serve it as a resource. Hence the recipe:
  1. Implement/override method in GenericPortlet:
    serveResource(ResourceRequest request, ResourceResponse response)
  2. In your JSP (or whatever you use) refer to it with Resource URL. In JSP you do it like this (use it on your own way):
    renderResponse.createResourceURL().toString()
  3. In that "serveResource" thing check your request parameters and then return your content into an InputStream.
Keep in mind, that normally you're dealing with ResourceResponse, which is different than HTTP response in a servlet. So after you've put content type in usual way, "setHeader" method is actually not available. But you can always use "setProperty" instead.
Now, if you are smart enough and using Liferay :-) instead of something else, then you simply could use one-liner PortletResponseUtil class, wher you can find a bunch of "sendFile" or "write" methods. They are just for your convenience: get from byte array, InputStream etc. As an example how it works, watch:
PortletResponseUtil.sendFile(response,
"test.pdf",
new FileInputStream(new File("/tmp/test.pdf")),
"application/pdf");
Now use your own imagination how to make it actually right (by replacing FileInputStream with something more valuable, as a starter).
This is it. Enjoy. :-)

Tuesday, October 12, 2010

Thursday, October 07, 2010

Jasper Reports: gone!

OK, this is it. I fed up fighting Jasper Reports and simply ditched it. BIRT (or "dirt" — you call it) although has interesting things, still is even worse than the Jasper Reports. There is also Pentaho Reports available. They are actually nice, but buggy as hell, crashes and has no much features. Embedding is odd.
At first, I don't need that fancy GUI editor. I simply don't. Do you need? No, you don't either. Here is why: it requires programming anyway. So if you think you will get this sexy full-screen editor with mousedraggable objects and will pass you your girls at operations department — you're wrong, wrong and once again wrong. They won't use that. Because if boss will ask you to make red color some figures that are greater than 1000 — what you will do? It is not anymore mousedraggable and clicketyclickdroppable.
At second, I had a trouble with Japanese, but that's font package installation. Why do they do it this way — their problem. I don't like their (Jasper Report's) way to distribute fonts either.
Therefore I decided to make my own parser of my own markup, that is very similar to RML, but is more looks like just a regular HTML. Basically a 50/50 mix of them.
So far, I achieved (in compare to Jasper Reports):
  • Something like 40 times faster PDF compilation. Yes, up to forty times.
  • A very simple way to embed it to your servlet. The keyword here: "very". It is mostly a re-entrant one-liner, something like this:
    new PDFRender(OutputStream, InputStream);
  • Very small footprint.
  • Resulting PDF simply crashes my Preview.app ... BWAHAHAHAHAHAHA!
It renders still bit ugly sometimes and I still working on styles, but I have fully controlled by styles headers, footers, pagination, page layout, text body, paragraphs, True Type fonts, embedded images and a simple grid-like tables.

Soon table spanning and styling is still coming (probably right tomorrow). Later I will add SVG support for native charts (still don't know how what way to do it is the best), barcodes and lovely Japanese QRCode that is required just everywhere through.

Friday, September 17, 2010

Custom TTF Fonts in JasperReports

You hit this wall too, aren't ya? At first I was truly pissed off by the overall design of Jasper Reports (entire suite in general). At second, I am even more pissed off how fonts are handled in PDFs.

First what you do, is you're trying to install some TTF fonts into your JVM, somewhere in $JRE/lib/fonts, map them and hope things will fly. Then you probably specify that your new font in Jasper Report XML file, something like:
<font fontName="Great Font" />
...and you finding it not working: in your PDF you see Helvetica. If you expect some Asian support (Japanese, e.g.), then you will find blank space there. Familiar, eh? Of course, you go around the XML Schema and finding that Jasper Reports actually has some more arguments to the "font" aggregate, so you adding it:
<font fontName="Great Font" ispdfembedded="true"/>
...and you finding it not working: in your PDF you see Helvetica. Then you, puzzled, finding out that there is also some more attributes (although they are quite odd anyway), so you use them too:
<font fontName="Great Font" ispdfembedded="true"
pdffontname="/madly/hardcoded/path/on/the/system/to/your/greatfont.ttf"/>
...and you still finding it not working: in your PDF you see Helvetica. Then you, angry, yelling "WTF!!!", googling around and you finding a lots of people, suffering from the same problem.

The key to solve this puzzle is to deal with completely stupid implementation of Jasper Reports engine: you have to package these fonts into JAR file and embed into your application. They (developers) think that since it is Java, so "run everywhere", therefore you take your .WAR or .JAR or .EAR file and put on any possible container and it will just work, so no need to setup the environment. In reality, however, when you deploy 1000 applications like this, you also have 1000 duplications of the same stuff. It results to a horrible mess and very very VERY angry sysadmins that literally hates all the guts of Java. Moral: keep it simple, stupid.

So anyways, how to use own TTFs or at least find Japanese visible? JaperReport's answer is: put this stuff into JAR and toss in into the classpath. Here is how to do it:
  1. In the default, root package, create a property file with a magic name: jasperreports_extension.properties
    Developers could not name it more elegant, like fonts.properties or, perfectly elegant, having none of it at all.
  2. Create a package for your fonts. Let's say it is foo.bar.fonts
  3. In this strange properties file we've made above, you have to put two things at least. One is very magical static property that normally can be hardcoded once and forever somewhere deep in the guts of JasperReports and never ever remembered anymore:
    net.sf.jasperreports.extension.registry.factory.simple.font.families
    =net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
    Can you read that wide?
  4. Another property is to reference the reference to the reference of the actual files, embedded into the JAR:
    net.sf.jasperreports.extension.simple.font.families.somebullshit
    =foo/bar/fonts/fonts.xml
    That's how to let finally Jasper find the fonts.xml file. Please not one very nasty and ugly thing: there is no leading slash prior to "foo". Noticed? If you put it (as it should be), then forget it working.
  5. Now, in the foo.bar.fonts package create "fonts.xml". You can change its name in step #4.
  6. Map your fonts there as it is in examples of JasperReports (demo/fonts).
  7. Compile all this assembly into a JAR file and toss in somewhere in your app $CLASSPATH. Now your PDF should pick up the font finally.
  8. Phew!
If you still find this idiotic (like I do), you'd better try Dynamic Jasper http://http://dynamicjasper.sourceforge.net/ and it suppose to help you.

You might ask: how it should be better implemented? OK, you ever heard about X11 and how fonts are mapped there? In the same fashion. Why not use just fontmap.properties file in the JAR and just simply drop fonts there and have zero XML? Yes, it is magic name, but it is the only magic name. And then stick to something like one line per font, e.g.:
family=weight,encoding,embedded,file.ttf
Said that, it might look this way:
greatfamily=n,UTF-8,t,greatfont-nnormal.ttf
greatfamily=i,UTF-8,t,greatfont-italic.ttf
greatfamily=b,UTF-8,t,greatfont-bold.ttf
greatfamily=bi,UTF-8,t,greatfont-bold-italic.ttf
Then, you run something like $JASPER_REPORTS/bin/fontpack ...and it would create such a JAR right away for you. How that sounds? That sounds just greatly simplified yet idiotism. What it actually should be: you specify font name "Great Font" (not path to actual TTF!) in the XML and it picks up automatically from the JVM right away. If font is not installed, then it has to fall-back to the default (Helvetica, in this case) by warning the user to the log file (instead of crashing, by the way).

Still, I suffer from its performance, if this is the word. Generating PDFs are still hell very slow for my requirements. My next step will be ditching JasperReports and go OpenOffice.org as template editor and renderer iText based engine. Well, if company will pay for that. :-)

Wednesday, September 01, 2010

Nexenta 3.0 Zones: Fixing Broken Bones

As a rule of thumbs, when things installs very smoothly, I always suspect something wrong, because there is an old Ukrainian saying: "Devil lives in a silent lake". This time same thing happened to newly installed Nexenta Core 3.0 Release. Installation went just as sweet and smooth.

But when it comes to zones... :-(

Long story short: Zones are just totally broken in Nexenta Core 3.0 Release, end of story. SSH won't work, you won't login, no passwords asked, nothing. And I am quite surprised it was never fixed (probably nobody took a chance to test it). Now is the way how I fixed, grepping over bugs database:

First, before you install a zone, you have to fix broken /usr/bin/createzone Perl script. This should be done in two steps:
  1. Replace elatte-unstable with hardy-unstable on a line #41.

  2. Throw away @source_files with all its guts and replace with the following:
    my @source_files = qw(
    /lib/svc/method/nexenta-sysidtool-system
    /var/svc/manifest/system/nexenta-sysidtool.xml
    /lib/svc/method/nexenta-sysidtool-net
    );
Second, fix broken /lib/svc/method/svc-syseventd script. This is done in quite dirty way, but at least works fine:
  1. In the global zone edit the script above. Find this line (below the CDDL header):
    . /lib/svc/share/smf_include.sh
    ...and add this:
    [ `zonename` = global ] || sleep 3600 & exit 0
    ...so in result you will get this:
    . /lib/svc/share/smf_include.sh
    [ `zonename` = global ] || sleep 3600 & exit 0

This will allow required services finally start.

Now you can install your zone (zoneadm -z yourzonename install).

Third, fix shadow and passwd. Boot your zone and zlogin to it in a single mode (-S), then issue pwconv command and exit.

Finally, after you anyhow login to that thing, reconfigure broken system service once again, like this:

dpkg-reconfigure sunwcsd
svccfg import /var/svc/manifest/system/sysevent.xml

And yes, this is Unix. You should reboot your zone in order it getting working right. :-)

Monday, August 30, 2010

GlassFish v3 on OpenSolaris

OpenSolaris is dead as a distro, but it is still around, unless it's content moved/migrated to Nexenta or, later, IllumOS. Today I've got weird error from GlassFish v3 after installation. Apparently that's because OpenSolaris has chronically screwed up locales (one never grows up). Here is the way how the thing looks like in all its glory:
Waiting for DAS to start ..Error starting domain: domain1.
The server exited prematurely with exit code 6.
Before it died, it produced the following output:

UTF ERROR ["../../../src/solaris/instrument/EncodingSupport_md.c":66]: Failed to complete
iconv_open() setup
So the cure is quite simple: fix that broken locale (in fact, broken locale breaks other things anyway). To do so, install SUNWlang-enUS from the IPS and add export LANG=en_US.UTF-8 in your .profile to make it default. Maybe also good idea to add it to the skeleton... :)

Tuesday, August 17, 2010

Mirroring ZFS rpool

OK, time to mirror my rpool. Apparently, it rendered for that works with FreeBSD, but does not with Solaris. (WTF!?)
# zpool attach rpool c0t0d0 c0t1d0
cannot label 'c0t1d0': EFI labeled devices are not supported on root pools.
Ewww... :-(

Here is the steps to cure this illness:
  1. format -e will give you all the drives available.
  2. If you found one it needs to be formatted, use fdisk and create 100% Solaris2 partition.
  3. Your drive supposed to be in /dev/rdsk/ somewhere (don't forget to look in "rdsk", instead in "dsk"). In my case /dev/rdsk/c0t1d0
  4. Fix broken bones for the Disk Format:
    prtvtoc /dev/rdsk/c0t0d0 | fmthard -s - /dev/rdsk/c0t1d0
    Then fmthard should tell you something like: "New volume table of the contents now in place". If it didn't — you're out of luck and try to figure out why. :-)
  5. Try to attach a drive to rpool, but it may scream, something like this:
    zpool attach rpool c0t0d0 c0t1d0
    invalid vdev specification
    use '-f' to override the following errors:
    /dev/dsk/c0t0d0 overlaps with /dev/dsk/c0t1d0

    Well, so be it. Use '-f' option to force it:

    zpool attach -f rpool c0t0d0 c0t1d0

    Please be sure to invoke installgrub(1M) to make 'c0t1d0' bootable.
    Make sure to wait until resilver is done before rebooting.
  6. Normally, you're done: zpool status should show you a mirrored rpool. But you're almost there: still you need to install GRUB.
  7. Install GRUB this way:
    installgrub -m /boot/grub/stage1 /boot/grub/stage2 /dev/rdsk/c0t1d0
Basically this is it, now you might try to boot from another drive. But wait your rpool resilvered though... :-)

Wednesday, June 02, 2010

Fight with OpenNMS on OpenSolaris

I've tried to install OpenNMS on OpenSolaris from standalone installer (shipped in one single JAR file that you suppose to run). Everything fine (mostly) as long as you follow the instructions, but some ugly things needs to be mentioned:
  • Your JRE is not enough. See, OpenNMS will ask you to install full blown JDK. What for — I have no idea. But that's why we hate most Java developers: they are unable to make cute small things in most cases.
  • Your PostgreSQL will say something rude to the installer and latter will be upset, asking you personal questions. So make sure, in prior to running the installer, you did the following:
    postgres=# create user opennms with password 'opennms';

    postgres=# alter user opennms with password 'opennms';
    ALTER ROLE

    postgres=# create database opennms owner opennms;
    CREATE DATABASE

    postgres=# grant all privileges on database opennms to opennms;
    GRANT
  • You changed your passwords for "opennms" user in DB and also you fixed your trust store where password it "changeit".
Everything else should work, as long as your ports are opened properly. In order to know if something wrong (and it usually is), try to see what's running and what's not by issuing a command:

$OPEN_NMS/bin/opennms -v status

This will list all the processes and will show you the status.

Thursday, May 13, 2010

Cloud vs Grid computing

Folks, enough!
There is no such thing as "versus" and it is not anything that you don't know yet. Grid computing is an engine on a chassis, where cloud computing is a complete car that you drive on. Hence, grid computing is how data is distributed in heterogeneous fashion skipping geographical constraints, while cloud computing is how data is accessed. So the complete product is all these things working together. End of story.
And, yes, it has been around for last 20 years: "The Network Is The Computer", if you still didn't noticed...

Monday, March 29, 2010

DTrace. Quick start.

Here.

OpenSolaris and ISO images

You have an OpenSolaris box and you also want to archive some things on DVD (well, just in case). Here the things everyone on Solaris should know (in case you don't):
  1. First, make an ISO out of the directory that allows full 31 character filenames, instead to truncate them 8.3 format which is compatible with MS-DOS. You also might consider "joliet-long" option in order to allow Joliet filenames to be up to 103 Unicode characters. This breaks the Joliet specs, but appears to work. The following example is just a straight-forward:
    mkisofs -J -l -o foobar.iso /path/to/the/folder
  2. Second, you want to test and verify it. In Solaris, prior to mounting, you should make a block device from the file, first. In this case, lofiadm is your friend in this way:
    pfexec lofiadm -a foobar.iso
    Please note that you will need to escalate a privileges, because it will create a new device in /dev/lofi directory. To know all the list, simply run lofiadm as is. In this example it appears as "/dev/lofi/1" device.
  3. Now is a time to mount the device. Create some directory (e.g. /tmp/foobar) and mount the device (not the .iso file):
    pfexec mount -F hsfs /dev/lofi/1 /tmp/foobar/
    Things looks OK? :)
  4. Un-mount your filesystem and remove mount point to cleanup the mess behind you:
    pfexec umount /tmp/foobar; rmdir /tmp/foobar
  5. Remove block device (same mess):
    pfexec lofiadm -d /dev/lofi/1
  6. I usually don't burn CD/DVD's on a server remotely due to a number of issues with that, but if you like, you can do it. Normally, you want to use "cdrw" on Solaris (SUNWcdrw package in IPS, in case you haven't it installed) like this:
    cdrw -C -i /path/to/your/foobar.iso
    This will also detect automatically you're burning DVD or CD, will check the size and so on.
  7. Probably remove your .iso image as well. :-)
That's was a Solaris way and is slightly different that on a typical Linux box.

Friday, March 26, 2010

Mail.app, show me a plain text!

I hate HTML messages. Especially, when you ask your mates not to send HTML for simple text. They do. You won't shoot em, because you will have to do their job as well (this leads to lack of sleep). So there is other way: force Mail.app display a plain text. Normally, there is no checkbox in Preferences, but Mail.app still "eats" this preference in plist, like this:
<key>PreferPlainText</key>
<true/>
Cool. So we can do this:
defaults write com.apple.mail PreferPlainText -bool TRUE

Now restart Mail.app and you've done.

Monday, February 01, 2010

What 2010 is going to bring us?

I am thinking: is 2010 is a year for epic failures? Project Kenai is going to be closed "for better user experience" which means "no more Kenai for the rest of us", only for those, who pays to the god Oracle goddamn money. And Jobs with his strange not-really-an-iPhone XXL, called iPad — next laptop will be 4x times bigger as well?

Now, recently new NetBeans 6.8 tutor came out — http://netbeans.org/kb/docs/web/hibernate-webapp.html — with a multitude of the code, that results to a simple CRUD. Tendency is ridiculous again: now with embedding parts of query language right into your code. "Brilliant" design! — they welcomed things which they wanted go away from.

Wait, a president elections in my country now happening...

Thursday, January 14, 2010

Bye-bye, Postfix...

Times ago I've dumped Sendmail and replaced with a Postfix. Now, after a while, having a number of requirements that needs to be implemented with something more sophisticated, it is a time to replace Postfix for something better, easier and more flexible.

My choice is now Apache James (http://james.apache.org/).

Tests went fine, things works as expected. Configuration is dull easy, like for those, who see an email server for the first time in their life. Apache James looks pretty good inside (source code), is extensible, has nice plugins and great API to make your own, if you like (that's exactly what I really need). Some folks reports it handles about 3K messages per a minute. I think, that's impressive number, but I don't need such anyways. :-)

The greatest thing of all this story: this particular mail server is a 100% pure Java.

Wednesday, January 13, 2010

How to run background process in GWT

There is no such thing as "background process" in Google Web Toolkit client, because... it is a client part. So you can not do threads, can not do daemons, since it supposed to be cross-compiled to JavaScript and run in a browser pretty ugly way. However, you can repeatedly call the same function. In JavaScript it is timeout. But you want to avoid JSNI for this. Hence, do the following: use a com.google.gwt.user.client.Timer. If you want call it periodically each 5 seconds, you can do something like this:
private void updaterProcess() {
Timer timer = new Timer() {
@Override
public void run() {
// call stuff here
}
};

timer.scheduleRepeating(5000);
}

Shift happens...

Google got pissed off:

"We have decided we are no longer willing to continue censoring our results on Google.cn, and so over the next few weeks we will be discussing with the Chinese government the basis on which we could operate an unfiltered search engine within the law, if at all. We recognize that this may well mean having to shut down Google.cn, and potentially our offices in China."

Complete story here: http://googleblog.blogspot.com/2010/01/new-approach-to-china.html

Well done, Google! Well done.

Tuesday, January 12, 2010

How things gets screwed up, when you're not thinking...

Short note how JNLP is screwed up in the GlassFish.
You like GlassFish, aren't ya? Now, consider, you want distribute your application over JNLP, as I did on my radio website. It is an MP3 player with an ability send SMS messages, so far. Note, the website is in Ukrainian language, but you can simply click on that whacky image somewhere in the middle of the article. :-)

Since it is Java Web Start, the way you put it to the GlassFish is using Enterprise Application, then create a client to it, and then put your stuff there, pack as an ".ear" and deploy. Sounds cool, right? Yes, sounds very-very cool. Note that since it is Java Web Start, you don't want to listen to your complaining users for like "WTF is this?!" etc., instead you want your application:
  • Be damn fast.
  • Be damn small.
  • Be damn quick.
However, not with Enterprise Application. Once you've packed your app as ".ear", it will suck up a sh*tload of useless jar's, verify each by unpacking, checking etc. On an average user's Vista laptop, where all the resources went to antivirus and antimalware package, you do not want it happen ever. Some of my users complained they had to wait 8 (eight, EIGHT) minutes to load a very little tiny application, like that one. Take a look what you've got in your cache among other crap: Java EE jar! Application Server runtime! OMG!..

Now... The obvious question is how to cure all this mess to make your 200K application start literally in a moment? Forget stupid Enterprise Application, once you go with JNLP. It is still good if you do EJB things (I do, so far so good). Never touch JEE for client part (make sure it is server thing in your app) and deploy as a simple GUI that talks to your server via webservices (REST or SOAP is fine). Deploy it just manually, as a static data somewhere on the server.

How deploy it manually on GlassFish. I assume you're using NetBeans? If no, you should. :-) So go to the properties of your Project, select "Web Start enabled", sign your jars with an SSL certificate and rebuild all the stuff. In your Project's "dist" folder you will find ready to go app (almost). Then edit codebase URL in order it point to your website over HTTP instead using file:// from local system. Tar/gzip all the dist/ folder with everything inside, scp to your server and unpack to the static folder of the GlassFish ($ROOT/domains/$DOMAIN/docroot) or, if it is GlassFish + Liferay, then look inside deployed Liferay package.

That's it.

P.S. Sun, I hope Oracle will kick your ass very hard to gently encourage you think properly and organize your technology the way it be once actually usable for everyone.