XFire

Home
Bug/Issue Reporting
Download
FAQ
Get Involved
License
News
Stack Comparison
Support
User's Guide
XFire Team

M5

Javadocs
Reports

M6-SNAPSHOT

Javadocs
Reports

Developers

Developer Space
CVS
Building
Architecture
Interesting Projects
Release Process

Aegis is the default XFire binding which maps XML to POJOs. It supports code first development only at this point - i.e. you write your service in POJOs and it will generate the XML schema/wsdl for you.

Mapping Overview

Aegis has a flexible mapping system so you can control how your beans are controlled. By default your POJOs are serialized based on their name and namespaces. If you have a class in the "org.codehaus.xfire" package named "Employee" it would be serialized in namespace "http://xfire.codehaus.org" with the local name "YourBean."

Fore example, the java class:

public class Employee
{
  private String name;
  private String title;

  public String getName() { return name; }
  public void setName(String name) { this.name = name; }

  public String getTitle() { return title; }
  public void setTitle(String title) { this.title = title; }
}

In XML this translates to:

<Employee xmlns="http://xfire.codehaus.org">
  <name>Santa Claus</name>
  <title>Chief Present Officer (CPO)</title>
</Employee>

In XML Schema this would become a complex type:

<xsd:complexType name="Employee">
  <xsd:sequence>
    <xsd:element name="name" type="xsd:string" minOccurs="0" maxOccurs="1/>
    <xsd:element name="title" type="xsd:string" minOccurs="0" maxOccurs="1/>
  </xsd:sequence
</xsd:complexType>

Controlling Mappings with XML

Its easy to control how your service and its beans are mapped to xml. If you are using Java 5.0 skip straight down to that section otherwise read on to learn how to configure serialization via mapping files.

Mapping files sit next your bean or service on the class path. In the above example you would have a file named "/org/codehaus/xfire/YourBean.aegis.xml". They follow the general format:

<mappings>
  <mapping uri="">
    <method name="methodName">
      <return-type mappedName="" componentType=""/>
      <parameter index="" mappedName=""/>
    </method>
    <property name="" mappedName="" style="attribute|element" componentType=""/>
  </mapping>
</mappings>

Note that <method> is used to configure methods on your service and <property> is used to configure properties on your javabeans.

Controlling Naming

Lets pretend that in the above example you would like the elements names to be capatilized and in the namespace "urn:north-pole:operations". You could achieve this through a mapping file like so:

<mappings xmlns:np="urn:north-pole:operations">
  <mapping>
    <property name="name" mappedName="np:Name"/>
    <property name="title" mappedName="np:Title"/>
  </mapping>
</mappings>

Notice that we declared the namespace on the mappings element and then used the prefix to specify the element QNames for the name/title properties.

This will result in a mapping like so:

<Employee xmlns="http://xfire.codehaus.org" xmlns:np="urn:north-pole:operations">
  <np:Name>Santa Claus</np:Name>
  <np:Title>Chief Present Officer (CPO)</np:Title>
</Employee>

But why didn't Employee end up in the "urn:north-pole:operations" namespace? Employee ends up being an "abstract" xml schema type, so we need to go to where the Employee is referenced in our service and another mapping file. For example if we have a service like so:

public class EmployeeService
{
    Employee getEmployee(String id) { ... }
}

We would need another mapping file:

<mappings xmlns:np="urn:north-pole:operations">
  <mapping>
    <method name="getEmployee">
      <return-type mappedName="np:Employee">
    </method>
  </mapping>
</mappings>

Ignoring properties

If you don't want to serialize a certain property it is easy to ignore it:

<mappings>
  <mapping>
    <property name="propertyName" ignore="true"/>
  </mapping>
</mappings>

Handling Collections

You undoubted use Collections in your code. Pre Java 5 it is impossible to determine the "component type" of a Collection by introspection. So you need to give Aegis some hints. For a service which returned a Collection of employees like so:

public class EmployeeService
{
    Collection getEmployees(String id) { ... }
}

You would need to supply metadata which gave the component type in a mapping file like this one:

<mappings>
  <mapping>
    <method name="getEmployees">
      <return-type componentType="org.codehaus.xfire.Employee">
    </method>
  </mapping>
</mappings>

Handling Maps

Java Maps don't map well to XML Schema (no pun intended) because there is no Map concept in XML Schema so your clients. Maps are transformed to a collection of {key, value} tuples. In addition to providing the type of the value, you must also provide Aegis with the type of the key:

public class GiftService
{
    Map getGiftList() { /* returns a map of NiceChild => Present */ }
}

The mapping file should look like this:

<mappings>
  <mapping>
    <method name="getGiftList">
      <return-type keyType="org.codehaus.xfire.NiceChild" componentType="org.codehaus.xfire.Present">
    </method>
  </mapping>
</mappings>

This will generate the following type:

<xsd:complexType name="NiceChild2PresentMap">
  <xsd:sequence>
    <xsd:element name="entry" minOccurs="0" maxOccurs="unbounded">
      <xsd:complexType>
        <xsd:sequence>
          <xsd:element name="key" type="ns1:NiceChild" minOccurs="0" maxOccurs="1"/>
          <xsd:element name="value" type="ns1:Present" minOccurs="0" maxOccurs="1"/>
        </xsd:sequence>
      </xsd:complexType>
    </xsd:element>
  </xsd:sequence>
</xsd:complexType>

Working in Java 5

Everything mentioned above will still work in Java 5.0 but you will get several additional features:

  1. Support for Generics and Collections
  2. Enum Support
  3. Ability to use Attributes to control naming
  4. Nice integration with XFire's JSR 181 support

Of the above generics and enums should work out of the box. Just declare and use.

Aegis Annotations

Lets say we would like to control the naming of our elements again. Via annotations it would look like so:

import org.codehaus.xfire.aegis.java5.XmlElement;

@XmlType(namespace="urn:north-pole:operations")
public class Employee
{
  private String name;
  private String title;

  @XmlElement(name="Name", namespace="urn:north-pole:operations")
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }

  @XmlElement(name="Title", namespace="urn:north-pole:operations")
  public String getTitle() { return title; }
  public void setTitle(String title) { this.title = title; }
}

Notice, annotations are declared on the read method of a property.

Voila, this should serialize as:

<np:Employee xmlns:np="urn:north-pole:operations">
  <np:Name>Santa Claus</np:Name>
  <np:Title>Chief Present Officer (CPO)</np:Title>
</np:Employee>

You could of course use the XmlAttribute type as well:

import org.codehaus.xfire.aegis.java5.XmlElement;
...
public class Employee
{
  private String name;
  private String title;

  @XmlAttribute(name="Name", namespace="urn:north-pole:operations")
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }

....
}

This would serialize as:

<np:Employee np:Name="Santa Claus" xmlns:np="urn:north-pole:operations">
  <np:Title>Chief Present Officer (CPO)</np:Title>
</np:Employee>