Tuesday, January 27, 2009

Java WebStart success?

Just maybe, I'm on the verge of success gaining the Holy Grail: automatic continuous integration of a Java WebStart application! What are the pieces?
  • Maven and Ant
  • Artifactory
  • Hudson
  • Jetty
  • JNLP servlet
Whew! Some details on each piece...

Ant and Maven
I like Maven for the convention it brings (as in Convention over Configuration). The repositories and versioning of dependencies are wonderful. The bad news is that a WebStart application isn't the traditional JAR or WAR build that Maven knows about. (N.B. - I may come back to this, since using the JNLP servlet, it *could* be a WAR file.) The good news would seem to be that of course, there a couple plugins that do neat WebStart things - including building the JNLP file from the dependencies. You know, DRY! The first one from CodeCrate offers great promise - handle the simple case! Cool. Well, it's a fail straightaway since it can't seem to find the dependencies at all and gets a ClassNotFoundExeception. Bummer. So I go for the full Monty - Maven Webstart Plugin . There's a "cookbook recipe" which shows a "Getting started" page. But no examples for the simple case - they go straight to WAR bundles. :( And the Maven jar signing plugin will only sign the main artifact - not all the dependencies. Double fail.
Ant to the rescue! Fortunately, Ant knows how to sign jars and Hudson will run multiple steps in the build, so it is easy to mix Ant and Maven. Ant will sign the dependency jars and Maven will build the rest of the project. The only loss is not generating the JNLP from the dependencies.

Artifactory, Hudson and Jetty
Both of these are handy web-based tools. Each is easy to install and configure - UNLESS you want password protection. My first thought is to bundle both into a Tomcat instance. Should be easy enough - both give instructions on that. Password protecting Tomcat sites should be easy enough. OK, start with Artifactory. Endless headaches, fails, NullPointerException, etc. Finally come across a suggestion to never use pre-installed Tomcat instances on Linux boxes. Oh! OK - download and install Tomcat 6.0.18 - works great! The password protection works. Now, just have to add the Hudson webapp. FAIL - OutOfMemoryError out the gazoo. Having used Jetty before with good success, I revert to separate Jetty installations - one for Artifactory, one for Hudson. Even with password protection!

JNLP Servlet
Providing links to a JNLP file and having it link all its resources works fine. Just one problem: the JNLP has the codebase in it, so at build/deploy time you have to know where you're deploying to. A bit of a problem if you want to build and deploy to a test server, then promote to production. But wait, the JNLP Servlet to the rescue: it filters the JNLP and drops in the proper codebase for you. Nice! Now let's see - where's the JNLP servlet?
The JnlpDownloadServeltGuide from the Sun JavaSE 6 TechNotes says: "The servlet is packaged into the jnlp-servlet.jar file, which can be found in the SDK under samples/jnlp/servlet/" OK - I've got lots of JDK/JRE installations.
find /usr/java -name samples
Nothing. Hmm... Oh, update 11 is out - let's download that. And there's a nice document in the Java Web Start Reference pages called "Packaging JNLP Applications in a Web Archive" - sweet. That's interesting, there's a "sample" directory in this JDK. Oh, even a "jnlp" directory under that. Cool - cooking with gas now. Follow all the instructions about deploying, etc. FAIL - java.lang.ClassNotFoundException: com.sun.javaws.servlet.JnlpDownloadServlet
WTF?
jar -tvf WEB-INF/lib/jnlp-servlet.jar
Oh look! All of them are "jnlp.sample" package, not "com.sun.javaws"! Thanks a lot. So change the servlet definition in the web.xml. Finally - success!

The only remaining piece is to have Maven or Ant copy the proper files to the Jetty webapp directory. How hard can that be?


Tuesday, November 11, 2008

Why Swing UIs are so hard...

I'll tell you why - ok, well at least with issue I'm having now, which seems to be a common issue - LAYOUT.

How do you nicely lay out components? I've been reasonably happy with the layout tools NetBeans puts in for you. But I have a main window with 9 sub-panels, almost like portlets. Not all are the same size - and I want to have the user re-size them. Splitters? No, not the JSplitPane - too much overhead, can only split 2 sides. Enter the MultiSplitPane from SwingLabs - quite nice! An arbitrary grid layout even with custom split bars. BUT - how to specify a nice division. Well it provides "weight" - that's where the extra space goes. But what about the initial size? It uses each component's "preferred size" - seems like a good idea. But how do the components set their preferred size? This gets to the basic issue:

Layout - Bottom up or top down?
I attempted to have a component (tree control) set its preferred size based on the text and font it is assigned. Seems like a fine idea with good control, precision, etc. Nope! NullPointerException - the graphics aren't assigned at constructor time. Put in nice code:
String name = net.name;
FontRenderContext frc = ((Graphics2D)this.getGraphics()).getFontRenderContext();
TextLayout tl = new TextLayout(name, networkTree.getFont(), frc);
setPreferredSize(new Dimension((int)(tl.getBounds().getWidth()*1.5), 0));

NullPointerException at the line with getGraphics.

Top down...
Seems like Swing should learn from HTML/CSS - why can't a table support column widths in percentages? Seems like a simple enough thing - so I'm off to try banging that into MultiSplitPane.

Thursday, October 9, 2008

Better Swing through dynamic JVM languages...

The holy grail (?) - applying lessons learned in Web App development to Swing/desktop development. We have Python, Ruby, Groovy and now Scala on the JVM. Shouldn't they bring something to the party in terms of making my life easier to make Swing apps - which is still very tedious.

A couple good news items on this front-
Griffon for Groovy - This project shows some great promise! I hadn't been a big Groovy fan mostly because if it looks so much like Java, why not use Java? But then I realize a large impediment to starting up with Python or Ruby or Scala is the learning curve. On closer examination, it seems perhaps Groovy gets the benefits of a dynamic language while still in the overall "framework" of Java. That would be nice. One might say, 'but without the "buzz" it won't get the vast libraries of Python' - true, except for the extent to which it can just use the vast array of Java libraries. Is there an impedance mismatch? Don't know.

Monkeybars for JRuby - I just came across this project yesterday. (See http://groups.google.com/group/monkeybars) It seems to have a lot of the right objectives. The interesting thing is that there is no Ruby API for Swing components - you do the actual Swing components in a Java class and the Ruby code introspects the bytecode to manipulate stuff. Well, plausible I guess.

But interestingly, I've still not come across any Python-Swing or Scala-Swing toolkit/frameworks.

Singletons gone bad - again

I've been successful at using the swing framework, org.jdesktop.application classes in particular. I have a handful of applications sharing a rather large code base. Now however, of course we want to launch application B from application A. It actually works, but the problem is now that the Application singleton became B instead of A and when the objects in the A application go to use their resource map or action map, the get application B which of course isn't an A, so ClassCastException results. Ugh.

Option A: don't use ResourceMap and ActionMap.
I've already headed in this direction because of NetBeans' issues around keeping track of which class is the true application when it is generating code - so that wouldn't be all bad.

Option B: create one master application perhaps deriving from a new class MultipleFrameApplication extended from SingleFrameApplication. It would know how to create a new JFrame, etc. Arguments could be passed in to specify which "real" application to run - which in this case would mean which view to show first.

Option C: pass application A to the new view for application B. But somewhere we need a new JFrame, etc.

I have a related issue in that my model and helper (controller?) classes have common base classes and the models are singletons. So when application B launches, I'm not sure I want a whole new B model which would replicate the base classes of model A.

Hmm...

Tuesday, May 6, 2008

NetBeans (6.1) lost my code!

Things were going so well... I had created a Java Desktop application, got a desktop pane going, a dialog and an internal pane. It was now time to take a step back, refactor a little and etc.

I renamed my project, created a project group and BOOM! No more code. After a day or so reading about various frameworks, etc. and figuring out NetBeans 6.1 I got the program running in about an afternoon. Now I have nothing.
And now I have to Join Netbeans.org to post a message about this. Forget about it! My joining wiki.netbeans.org apparently wasn't good enough. My subscription to nbannounce was not good enough. FUGGET ABOUTIT!

The GUI builder was fairly good - but I'm going back to IntelliJ.

Tuesday, November 6, 2007

Frustrating: GWT InvocationException

I am having some success with GWT - but here's one that took me a couple hours to figure out. I created an asynchronous RPC service. Pretty much straight from the "book". Wouldn't work - wouldn't work. Tore everything back to the bare bones. (OK - the service was taking a user-defined class as an argument and returning a list.) I changed it to take a String and return a String. Still always got the InvocationException - with no cause. Finally also ripped the RemoteServiceServlet back to the basics -- did I mention I implemented the init and service methods to allow setting up other stuff I needed? Lo and behold it started working! Doh!
In the simple minded version I originally wrote it wasn't going to actually service anything, just initialize. By calling super.service(request, response) things went much better. Sometimes it IS just the simple problems.

Interesting: IntelliJ

My IDE travels have taken me back to IntelliJ for a tour with the EAP version of IntelliJ 7.0. So far - very nice! Great Maven integration. Great GWT integration! Only locked up on me once - I had three projects open and went to debug one of them.