users@jaxb.java.net

Re: JAXB annotated class to include external schema

From: Wolfgang Laun <wolfgang.laun_at_gmail.com>
Date: Tue, 26 Aug 2008 19:57:30 +0200

Below is what I did to demonstrate how to incorporate classes
generated from a schema into Java classes JAXB-annotated by hand.
The basic idea is to generate Java from the schema and to
compile them together with the Java code annotated by hand.

First, here is a schema supposed to mimick Types.xsd:

--->--- Types.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:tps="http://webservices.bla.com.au/schema/common/Types.xsd"
            targetNamespace="http://webservices.bla.com.au/schema/common/Types.xsd">
<xsd:complexType name="CodeDescription">
  <xsd:sequence>
    <xsd:element name="language" type="xsd:string"/>
    <xsd:element name="author" type="xsd:string"/>
  </xsd:sequence>
</xsd:complexType>
</xsd:schema>
---<---

JAXB customization (package name) is on the bindings file:

--->--- Types.xjb
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               jaxb:version="1.0">
  <jaxb:bindings schemaLocation="Types.xsd" node="/xsd:schema">
    <jaxb:schemaBindings>
      <jaxb:package name="schema"/>
    </jaxb:schemaBindings>
   </jaxb:bindings>
</jaxb:bindings>
---<---

I compiled this using:

$ xjc -b Types.xjb -d . Types.xsd

This resulted in Files CodeDescription.java, ObjectFactory.java and
package-info.java in ./schema.

Then there are the hand-written, annotated Java classes in
./hibernate

--->--- hibernate/AccessoryCategory.java
package hibernate;
import javax.xml.bind.annotation.*;
import schema.CodeDescription;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType( name = "", propOrder = { "codeDescription" } )
@XmlRootElement( name = "AccessoryCategory" )
public class AccessoryCategory {
    @XmlElement( name = "CodeDescription",
                 namespace =
"http://webservices.bla.com.au/schema/common/Types.xsd" )
    protected CodeDescription codeDescription;
    public AccessoryCategory(){
    }
    public void setCodeDescription( CodeDescription cd ){
        codeDescription = cd;
    }
    public CodeDescription getCodeDescription(){
        return codeDescription;
    }
}
---<---
--->--- hibernate/ObjectFactory.java
package hibernate;
import javax.xml.bind.annotation.XmlRegistry;

@XmlRegistry
public class ObjectFactory {
    public ObjectFactory() {
    }
    public AccessoryCategory createAccessoryCategory() {
        return new AccessoryCategory();
    }
}
---<---
--->--- hibernate/package-info.java
@javax.xml.bind.annotation.XmlSchema(
  namespace = "http://webservices.bla.com.au/schema/afi/2008/05/13/AFIDMS.xsd",
  elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package hibernate;
---<---

The following schemagen call generates XML schemas and class files from
Java code. Notice that the input includes the Java source resulting from
the schema compilation.

$ schemagen -d classes hibernate/*.java schema/*.java

The interesting thing is that this generates two XML schema files,
the first of which is a replica of Types.xsd.

--->--- schema1.xsd
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0"
    targetNamespace="http://webservices.bla.com.au/schema/common/Types.xsd"
    xmlns:tns="http://webservices.bla.com.au/schema/common/Types.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="CodeDescription" type="tns:CodeDescription"/>

  <xs:complexType name="CodeDescription">
    <xs:sequence>
      <xs:element name="language" type="xs:string"/>
      <xs:element name="author" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>
---<---

The other one references the first schema:

--->--- schema2.xsd
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema elementFormDefault="qualified" version="1.0"
    targetNamespace="http://webservices.bla.com.au/schema/afi/2008/05/13/AFIDMS.xsd"
    xmlns:ns1="http://webservices.bla.com.au/schema/common/Types.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:import namespace="http://webservices.bla.com.au/schema/common/Types.xsd"
             schemaLocation="schema1.xsd"/>

  <xs:element name="AccessoryCategory">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="ns1:CodeDescription" minOccurs="0"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
---<---

This test program marshals and unmarshals:
--->--- Main.java
import hibernate.AccessoryCategory;
import schema.CodeDescription;
import schema.ObjectFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import javax.xml.bind.*;
import javax.xml.namespace.*;

public class Main {
    private String packPath( Class<?> a, Class<?>... b ){
        StringBuilder sb =
            new StringBuilder( a.getPackage().getName() );
        for( Class<?> c: b ){
            sb.append( ':' ).append( c.getPackage().getName() );
        }
        return sb.toString();
    }
    public void testOut( File f ) throws Exception {
        String pp = packPath( AccessoryCategory.class, CodeDescription.class );
        JAXBContext jc = JAXBContext.newInstance( pp );
        Marshaller m = jc.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        AccessoryCategory ac = new AccessoryCategory();
        CodeDescription cd = new CodeDescription();
        cd.setLanguage( "Java" );
        cd.setAuthor( "John Doe" );
        ac.setCodeDescription( cd );
        OutputStream os = new FileOutputStream( f );
        m.marshal( ac, os );
    }

    public void testIn( File f ) throws Exception {
        String pp = packPath( AccessoryCategory.class, CodeDescription.class );
        JAXBContext jc = JAXBContext.newInstance( pp );
        Unmarshaller u = jc.createUnmarshaller();
        Object o = u.unmarshal( f );
        AccessoryCategory ac = (AccessoryCategory)o;
        CodeDescription cd = ac.getCodeDescription();
        System.out.println( cd.getLanguage() + " - " + cd.getAuthor() );
        System.out.println( "got a class " + o.getClass() + " object" );
    }

    public static void main( String[] args ) throws Exception {
        Main m = new Main();
        File f = new File( "xy.xml" );
        m.testOut( f );
        m.testIn( f );
    }
}
---<---

HTH
Wolfgang


On 8/26/08, Alex Wibowo <alexwibowo_at_gmail.com> wrote:
> Hi Wolfgang,
>
> One of the type I used in the class was generated using XJC from
> "Types.xsd".
> i.e. "Types.xsd" has the type definition for "CodeDescription" (which is an
> element inside "AccessoryCategory")
>
>
> Hope that clarifies the question.
>
> By the way... when I did the maven build, I got the following error:
>
> ------------------------------------------------
> java.lang.InternalError: Error escaping one of these uris:
> schema3.xsd
>
> ------------------------------------------------
>
> ( I have no idea where this "schema3.xsd" comes from. )
>
>
>
>
>
> Thanks again..
>
>
>
>
>
>
> On Tue, Aug 26, 2008 at 3:27 PM, Wolfgang Laun <wolfgang.laun_at_gmail.com>
> wrote:
> >
> >
> > On Tue, Aug 26, 2008 at 6:23 AM, Alex Wibowo <alexwibowo_at_gmail.com> wrote:
> >
> >
> > > I cant see how the generated schema (AFIDMS.xsd) can include the
> external
> > > schema (Types.xsd). i.e.
> > >
> ---------------------------------------------------------------
> > > <xsd:include
> schemaLocation="../../../common/Types.xsd"/>
> > >
> ---------------------------------------------------------
> >
> > Why woukd you want to have this xsd:include? XML data can use definitions
> > from two or more XML schemata on separate files.
> >
> >
> ---------------------------------------------------------------------
> > To unsubscribe, e-mail:
> users-unsubscribe_at_jaxb.dev.java.net
> > For additional commands, e-mail: users-help_at_jaxb.dev.java.net
> >
> >
>
>
>
> --
> Best regards,
>
>
> WiB
>
>