Version 9

    JBoss Retro

     

    The Problem

     

    We want to develop software that can take of advantage of JDK5 features while still being able to run the software in JDK1.4

     

    The Solution

     

    • Weave the classes such that the bytecode is 48.0 version compatible

    • Replace invocations to JDK5 api with code that does the same thing.

     

    How do I do it?

     

    There are two parts to the weaving:

    • retro which does the weaving, currently this requires to be run using JDK5 because of the way Enum constants are retrieved, this should be improved in future

    • retrocheck which checks that all constructor/field/method signatures has been weaved correctly and that all used api has an equivalent replacement, this needs to be run on JDK1.4

     

    Examples of using these ant tasks can found in the webservices project or JBoss Cache - search for targets named jbossretro.

     

    Some ant fragments from the microcontainer project are:

        <!-- ============================= -->
        <!-- Paths etc. for the retro task -->
        <!-- ============================= -->
        <property name="build.classes.retro" value="${module.output}/classes-retro"></property>
        <property name="build.lib.retro" value="${module.output}/lib14"></property>
        <path id="jbossretro.classpath">
          <path refid="apache.ant.classpath"></path>
          <path refid="jboss.jbossretro.classpath"></path>
          <path refid="jboss/backport.concurrent.classpath"></path>
          <path refid="javassist.classpath"></path>
        </path>
    
      <!-- Run jbossretro on the classes -->
      <target name="retro">
        <mkdir dir="${build.lib.retro}"></mkdir>
        <taskdef name="retro" classname="org.jboss.ant.tasks.retro.Retro" classpathref="jbossretro.classpath"></taskdef>
        <retro compilerclasspathref="jbossretro.classpath" destdir="${build.classes.retro}">
          <classpath refid="jbossretro.classpath"></classpath>
          <classpath refid="library.classpath"></classpath>
          <classpath refid="dependentmodule.classpath"></classpath>
          <classpath>
            <pathelement path="${build.classes}"></pathelement>
          </classpath>
          <src path="${build.classes}"></src>
        </retro>
      </target>
    
       <!-- Create the jdk14 compatible jar from the retrod classes -->
        <jar jarfile="${build.lib.retro}/${jar.prefix}14.jar" manifest="${build.etc}/default.mf">
          <fileset dir="${build.classes.retro}"></fileset>
          <fileset dir="${build.resources}">
             <include name="schema/**"></include>
          </fileset>
        </jar>
    

     

    Runtime dependency

     

     

    Question, why not use Retroweaver or Retrotranslator?

     

    • They both use asm which could conflict with the dependency from cglib/hibernate

    • Javassist is much better/easier than asm

    • Neither of these projects are "Professional OpenSource" meaning we cannot get fixes for commercial purposes

    • Simple tests on our first project to use it JBossWS, showed the api replacement was incomplete

    • It makes sense to use the same weaving technology that we use for JBossAOP for this project as well

     

    Availability

     

    The binaries are available here

    The source is available in public svn.

     

    Limitations

    See JBossRetroPitfalls for some of the JDK 5 libraries that do not translate to their JDK 1.4.2 equivalents when retroweaved with specific versions of JBoss Retro.  These are bugs and will be fixed in future versions of JBoss Retro, but can easily be worked around in your code.