The Source for Java Technology Collaboration
User: Password:



David Walend

David Walend's Blog

A Trip in the Way-Back Machine

Posted by dwalend on April 26, 2005 at 04:46 AM | Comments (9)

Ever want to go back in time and unmake a coding decision? Was it after a honeymoon period where you found some critical problem in something you'd bet on heavily and publicly? This happened to me recently with those seductive JDK 5 language features. Someone needed the software to work in JSDK 1.4, and I wanted to step into the way-back machine, return to September and start again. Then a fellow developer sent me a link to Retroweaver.

I started using JDK 5 features in my open source projects very early. I prototyped a version of SomnifugiJMS with the new concurrency kit to make sure JSR-166 had what I needed, and had been waiting years to use generics in JDigraph. I built releases of both these java.net projects on JDK 5 and released them over the winter. I'd planned to lead my team at work use JDK 5 in February, and maybe start using these two open source projects. At about the same time, our team's business guys realized we had a lucrative opportunity to get our research in an embedded system, provided our code base stayed compatible with JSDK 1.4.

In late March, Patrick Menard sent me a request: "[We would like to use SomnifugiJMS in our project.] Unfortunately we have to stick with java 1.4 for a while, and I saw you used quite some amount of JDK 5 specific code in your project. Do we have any change to make SomnifugiJMS run with java 1.4?" It's not just my team at work stalled at JSDK 1.4. If anyone tried to compile with SomnifugiJMS under JSDK 1.4, they got

[javac] class file has wrong version 49.0, should be 48.0

Patrick and I ran a thread of emails where I basically gave him bad advice. By combining some wishful thinking and a quick glance at the ant manual, I thought he could compile JDK 5 code into a JSDK 1.4-compatible .class file using javac. After all, generics, for loops and enums are mostly syntactic sugar expanded and cleaned up in the compiler. Patrick could hack the source code to use the backport (which worked great), and be off and running.

<javac target="1.4" blah="blah" blah="blah" ... >

gave me

javac: target release 1.4 conflicts with default source release 1.5

Rats. The next try was

<javac source="1.5" target="1.4" blah="blah" blah="blah" ... >

which gave me the same sort of error message. The next try was

<javac source="1.4" target="1.4" blah="blah" blah="blah" ... >

which gave me the expected seventy-odd syntax errors from trying to compile JDK 5 generic notation as if it were JSDK 1.4 code, and convinced me there was no love in the world. I decided to fork v3 to be a JDK 1.4 version of SomnifugiJMS (instead of using CVS' somewhat unsatisfactory branching feature), switched the backport to be the standard and set about stripping the JDK 5 language features out.

About that time, Patrick sent a message describing how he'd gotten SomnifugiJMS with the JDK 5 features to work on JSDK 1.4. He'd used Retroweaver to mix out the JDK 5 language changes at the byte code level. Retroweaver does not yet include support for java.util.concurrent, but handled generics and for loops once I grokked the ant target. I made the backport the default and juc support a separate subproject to keep the JDK dependencies out, and released SomnifugiJMS alpha-0-7 last week.

More About Using Retroweaver

I contacted Retroweaver's creator, Toby Reyelts, to better fill in some details in this blog. Toby had originally only intended to support new language features like generics, enums, autoboxing, and static imports. Enough people (possibly double-counting me) have asked for support of j.u.c he has decided to add it to some future release.

Toby's advice for supporting both JSKD 1.4 and JDK 5 at the same time was straightforward: Provide two different downloads. One made for standard JDK 5, one for JSDK 1.4. The retroweaved release will run fine on JDK 5, but will rely on the retroweaver-rt.jar. Interaction with JDK 5 parts may not work as hoped. For example, a com.rc.retroweaver.runtime.Enum_ can not be part of a JDK 5 java.util.EnumSet.

Wishing for Subversion Again

I am currently supporting one version of SomnifugiJMS with a single build file. To support a JDK 5 version separate from a JSDK 1.4 version, I would want two separate branches of the code. The JSDK 1.4 version would use Retroweaver and the concurrency backport (like the v3 directory I created for alpah-0-7), and would not have the juc subproject at all. The JDK 5 branch would have the net.walend.somnifugi.juc source in the somnifugi subproject and would not have the net.walend.somnifugi backport. Setting up this kind of branching is trivial in Subversion ("svn copy trunk jdk14" should do it), but java.net uses CVS. CVS branching is enough less pleasant that I am going to wait for Toby to release a version of Retroweaver that supports the concurrency backport.

This blog involves five new technologies: JDK 5, the juc backport, Retroweaver, Subversion and SomnifugiJMS alpha-0-7. (Well, six -- I'm using Mac OSX 10.4). JDK 5 had some features I wanted to use for a long time, but I almost had to stop using them. The juc backport worked fine. Retroweaver worked very well, but is very new. Subversion seems rock solid, but it's for source code. And the developer of SomnifugiJMS (that's me) isn't at all embarrassed about keeping projects in alpha for ever. Some might argue that I'd picked up JDK 5 too soon, but other emerging technologies (Retroweaver and the juc backport) had already anticipated the problems I would encounter.

What's the right time to adopt new technology? How does that interplay with Sun, the developer community on java.net and at large?


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • In the J2EE space, JDK 5 is very frustrating. Until the major commercial app servers support it we can't use it, but many of the technologies that we'd like to use (like JAXB 2) require it.

    Toby's Retroweaver is a great help, but wouldn't it have made more sense for something like Retroweaver to be an "official" deliverable from Sun et. al.?

    Posted by: johnreynolds on April 26, 2005 at 06:30 AM

  • I've been pondering making the switch using Retroweaver as my compatibility stabilisers, so far the idea of tip-toeing around the bits of Java 5.0 Retroweaver doesn't support has convinced me to stay put. (esp. when you're not fully to-to-speed on the new syntax anyway). Also worth noting is that the JSR 166 backport isn't 100% compatible either, but most awkwardly all the package names in the backport have been changed.. how did your SomnifugiJMS user handle that? change all the code by hand/ide? I understand why, because Sun dosnt like anybody distributing code in the java.* packages.. but also it'd cause classloading problems (I think) forcing it to be loaded by the bootclasspath override? Not too hot if your using java web start. It'd be nice if retroweaver could integrate & alias to the jsr-166 backport without requiring code changes.

    Posted by: osbald on April 26, 2005 at 10:33 AM

  • Oh, yeah? Well, my company is still on 1.3! You fancy-pants developers with your assert() statements...

    Posted by: richunger on April 26, 2005 at 10:37 AM

  • richunger,

    Just wait until all of us are using NetBeans 42.0 with "telepathic intent-based programming." We'll all have antennae coming out of our heads, and you'll really feel like a poor cousin.

    Dave

    Posted by: dwalend on April 27, 2005 at 05:05 AM

  • osbald,

    I used separate packages. The default net.walend.somnifugi.backport package uses the backport, and is in the somnifugi subproject. I created a new subproject to hold net.walend.somnifugi.juc. The somnifugi subproject gets retroweaved and uses the backport. The juc subproject does not get retroweaved and uses the juc concurrency classes.

    A better way to handle this problem would be using a source code branch. One branch would be a JSDK 1.4 only code base that uses retroweaver and the backport. The other would be a JDK 5 code base that uses juc and doesn't use retroweaver. You would build two releases, one for JSDK 1.4 and one for JDK 5. I did not want to deal with CVS branches becase they are a pain, especially after using subversion.

    Toby (created retroweaver) advocates this two-release approach because it avoids some annoying problems. More on that in a minute.

    Dave

    Posted by: dwalend on April 27, 2005 at 05:44 AM

  • johnreynolds,

    Sun is an odd duck as companies go. They created five versions of java and gave them away. They have to balance their quarterly bottom line with their desire to get more people coding in Java and their desire to get people to switch to JDK 5. Sun does not ask us for donations. More power to them.

    Toby has a crowd of people (me included) encouraging him to add more parts of JDK 5 to retroweaver. But JDK 5 has too many changes for him to possibly keep up with alone. Sun would be in a worse position -- Retroweaver is Toby giving up his free time to create a great tool. Sun can not claim that kind of charitable motivation.

    I would like Sun to consider breaking up the massive library that comes with the JDK into smaller parts so that we can use new major features sooner and more independently. However, I recognize the spectacularly high cost of that approach. It is hard to say what the right balance is.

    Dave

    Posted by: dwalend on April 27, 2005 at 05:50 AM

  • Toby asked me to emphasis creating two releases: one for JDK 5 and one for JSDK 1.4. That approach makes my EnumSet example fall apart; code that uses java.util.EnumSet will not compile under JSDK 1.4. If someone used the EnumSet code with JSDK 1.4, they will get a ClassNotFoundException or worse.

    Dave

    Posted by: dwalend on April 27, 2005 at 05:57 AM

  • I think casting is evil and that's why I jumped on generics and Java when it was released last fall. Doing nothing is always the easiest thing to do, but not always the right thing to do. For me, using the new language features and some of the minor additions in the API was the right thing to do. Sometimes is hurts though - especially when you try to release on OS X. But it hurts even more when you are lusting after the new features from J2EE (fortunately I'm developing a J2SE app).

    Even though I get beaten up for using the lastest technologies and tools, I still do it. For me, if you're standing still then you're moving backward.

    I appreciate your decision to use JDK 5. Somebody has to lead.

    Posted by: scirka on April 27, 2005 at 11:21 AM

  • Sounds like a familiar scenario! I have been using retroweaver to target 1.4 for some time but I recently also had to produce a version of an API for 1.3.1 (way - way back prehistory machine). Retroweaver can target 1.3.1 however I found that the retroweaver-rt jar itself is compiled for 1.4 - with a quick look in the buildfile though you can see retroweaver retroeaves itself to target 1.4 and you can easily tweak this to produce a version of the retroweaver runtime classes for 1.3.1.

    Posted by: anarchi on May 01, 2005 at 06:45 AM





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds