Skip to main content

Separate compilation in the JAXB RI 2.1

Posted by kohsuke on September 5, 2006 at 2:41 PM PDT

I just finished implementing the proposed separate compilation feature in the JAXB RI 2.1. So today I'm going to talk about how this proposed feature works, in the hope of getting more feedback for this proposal. You can play with this today by downloading the latest 2.1 continuous build of the JAXB RI.

The "separate compilation" that I'm talking about works like this. Alice has an extensible schema A and its corresponding JAXB classes:

<br /><schema xmlns="" targetNamespace="A"><br />  <complexType name="myType"/><br /></schema><br /><br />@XmlType(namespace="A",name="myType")<br />class MyType {}<br />

Maybe she wrote the schema and then generated the classes, or maybe she wrote classes and then generated the schema. Or maybe she wrote both by hand. It doesn't matter. Alice distributes this a.xsd and a.jar that contains these.

Now Bob has a schema B that refers to A. Maybe like this:

<br /><schema xmlns="" targetNamespace="B" xmlns:a="A"><br />  <import namespace="A" schemaLocation=""/><br />  <complexType name="extendedType"><br />    <complexContent><br />      <extension base="a:myType"/><br />    </complexContent><br />  </complexType><br /></schema><br />

He wants to generate Java classes for this schema, and he wants the schema compiler to do this by reusing classes in a.jar and not generating a new MyType class. In 2.0, this was somewhere between hard to impossible. But in 2.1, this is going to be much easier.

Case 1: a.jar is generated by XJC

The first case to consider is when Alice wrote a.xsd and generated a.jar by XJC. In this case, when invoking XJC, Alice would do it like this:
$ xjc -episode a.episode a.xsd

This tells XJC to compile a.xsd and then also generate what I call an "episode" file, which contains information about what schema stuff produced what Java stuff. This generated file is actually just a JAXB customization file, although unfortunately this version uses SCD, which makes it non-portable (there are ways to make this portable --- more work ahead.)

Anyway, with this, Bob will compile b.xsd like the following, to generate classes that refer to existing classes in a.jar. The specified a.episode tells the compiler to do the right thing.

$ xjc b.xsd -b a.episode

Since distributing two things is tedious and error prone, Alice can also choose to put a.episode into a.jar in /META-INF/sun-jaxb.episode. With this, Bob can run XJC like this to achieve the same effect, but this time without worrying about the additional file:

$ xjc b.xsd a.jar

Case 2: a.xsd is generated by schemagen

It's really the same thing as in the above case. When Alice generates a.xsd, she'd do it like this (or use the @episode if you invoke schemagen via the ant task:)

$ schemagen -episode a.episode ....sourcefiles...

This tells schemagen to generate schema files as well as an episode file. Bob can then use this episode file, along with the schema, to refer to Alice's existing classes:

$ xjc b.xsd -b a.episode

Pretty easy, huh?

Case 3: a.xsd and a.jar are both manually written

You can manually write the episode file (if you look at a few of them, you'll find that it's pretty easy to do so), or you can run schemagen just to get the episode file and discard all the schemas.


So that's what' we are planning to do in 2.1. Let us know what you think, while we can still change things...


<p>How to reuse with ant?</p> <p>Let's say we have a.jar ...

How to reuse with ant?

Let's say we have a.jar with /META-INF/sun-jaxb.episode in it. Now how do i write ant task so it would use it?

What i've found is that i can include episode file itself in a <binding> tag. Or add <arg value="a.jar"/> at the and of <xjc> tag.

Is there a way to include it in the <classpath> ? In case i'l be using 3 or 5 of them (a.jar, b.jar, c.jar ...)

<p>Is there a way to automaticaly generate episode file ...

Is there a way to automaticaly generate episode file AFTER the lib was made? Lets say its third-party lib.

Is episode part of the XJCTask ant task?

I was wondering if this was added to the XJC ant task as well as the command line. I was unable to find it when I decompiled the current version we are using (jaxb-xjc-2.1.4.jar). It would be really helpful to do so if it hasn't been done already.

Found it.

Forget it I realized I could use the following: <xjc destdir="${source.gen}" header="false" extension="true"> <schema file="foo.xsd"/> <binding file="foo.xjb"/> <produces dir="${source.gen}" includes="**/*.java"/> <arg value="-episode" /> <arg value="foo.episode" /> </xjc>

Works great, what about simple types

This works great for complex types. A nice feature. However, this is not honored for simple types: Is this by design or a bug? Ben

Hi, Is this fixed for simple types yet? I am still seeing ...

Is this fixed for simple types yet? I am still seeing that it is not being honored with jaxb version 2.2.3..