Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

Excerpt

For CXF 2.1 or newer

What is Aegis?

Aegis is a databinding. That is, it is a subsystem that can map Java objects to XML documents described by XML schema, and vica-versa. Aegis is designed to give useful mappings with a minimum of programmer effort, while allowing detailed control and customization.

...

You can use Aegis as a client to talk to Aegis, by using the very same Java classes and configuration files in the client environment that you use on the server. However, it's not all that practical to use Aegis as a client to talk to some a service using some other data binding, since Aegis lacks a 'wsdl2java' tool.

Every CXF service and client uses a front end: JAX-WS, Simple, etc. Each of these provides a place to configure the data binding, both in Spring and via Java code.

For example, here is a Simple front-end service using Aegis as a data binding.

Using Aegis on the client side also carries severe risks of compatibility problems. Since there is no WSDL to specify the contract, small changes in your code or in CXF can result in a situation where the client and the server are incompatible. If you want to use Aegis on the client side, you should be sure to use exactly the same version of CXF on both sides. If you cannot do that, you should consider generating JAX-WS/JAX-B code for the client using wsdl2java.

Every CXF service and client uses a front end: JAX-WS, Simple, etc. Each of these provides a place to configure the data binding, both in Spring and via Java code.

For example, here is a Simple front-end service using Aegis as a data binding.

Code Block
xml
xml

<simple:server id="pojoservice" serviceClass="demo.hw.server.HelloWorld" 
  address="/hello_world">
  <simple:serviceBean>
Code Block
xmlxml

  <simple:server id="pojoservice" serviceClass="demo.hw.server.HelloWorld" address="/hello_world">
  	<simple:serviceBean>
  		<bean class="demo.hw.server.HelloWorldImpl" />
  	</simple:serviceBean>
         <simple:dataBinding>
       <bean class="orgdemo.apachehw.cxf.aegis.databinding.AegisDatabindingserver.HelloWorldImpl" />
  </simple:serviceBean>
  </simple<simple:dataBinding>
    <bean class="org.apache.cxf.aegis.databinding.AegisDatabinding" />
  </simple:server>dataBinding>
 </bean>simple:server>

AegisDatabinding is the class that integrates Aegis into CXF as a databinding.

Aegis Operations - The Simple Case

Note that AegisDatabinding beans, like all databinding beans, are not reusable. The example above uses an anonymous nested bean for the databinding. If you make a first-class bean for a databinding, be sure to use scope='prototype' if you are inclined to define more than one endpoint.

Aegis Operations - The Simple Case

How does Aegis workHow does Aegis work? Aegis maintains, for each service, a set of mappings from Java types (Class<?> objects) to XML Schema types. It uses that mapping to read and write XML. Let's look at a simple service, where all the Java types involved are either Java built-in types, other types with predefined mappings to XML Schema, or simple bean-pattern classes that have properties that (recursively) are simple.

Let's start with serializing: mapping from Java to XML. (JAXB calls this marshalling, and cannot decide how many 'l's to use in spelling it.) Given a Java object, Aegis looks to see if it has a mapping. By default, Aegis has a set of default mappings for the basic types defined in XML Schema, plus a few other special items. These mappings are implemented by Java classes, parts of Aegis, that can turn objects in to XML and vica visa versa. In particular, note that Aegis will map a DataSource or DataHandler to an MTOM attachment.

...

How about the reverse process: deserializing? (JAXB calls this unmarshalling.) In this case, by default, Aegis is presented with an XML element and asked to produce a Java object. Recall, however, that the Aegis maintains a mapping from Java types to XML Schema Types. By default, an XML instance document offers no information as to the type of a given element. How can Aegis determine the Java type? Outside of CXF, the application would have to tell Aegis the expected type for the root element of a document. Inside CXF, however, Aegis

Or, as an alternative, Aegis can add xsi:type attributes to top-level elements when writing. It will always respect them when reading.

Inside CXF, Aegis gets the benefit of the Message and Part information for the service. The WSDL service configuration for a service gives enough information to associate an XML Schema type with each part. Once the front-end has determined the part, it can call Aegis with the QName for the schema type, and Aegis can look it up in the mapping.Will it be in the mapping? Yes, because Aegis precreates mappings for the types in the service's parts. Aegis cannot dynamically create or choose a Java class based on XML schema, so the type creators cannot start from XMLthe QName for the schema type, and Aegis can look it up in the mapping.

Will it be in the mapping? Yes, inside CXF because Aegis precreates mappings for the types in the service's parts. Aegis cannot dynamically create or choose a Java class based on XML schema, so the type creators cannot start from XML. Thus, outside CXF you are responsible for ensuring that your top-level types are mapped.

Schema Validation

As of CXF 2.3, the Aegis databinding can leverage the Schema Validation capabilities built into the Woodstox 4.x Stax parser to validate incoming requests. To enable this, you must do the following:

  1. Make sure you are using the Woodstox 4.x Stax parser and not a 3.x or other parser. By default, CXF 2.3 ships with an appropriate version of Woodstox.
  2. If not using the CXF bundle jar, (example, if using maven), you'll need to add the cxf-wstx-msv-validation-2.3.0.jar to the classpath
  3. If not using maven or similar to obtain the cxf-wstx-msv-validation jar, you'll also need to add the msv validation jars as CXF does not ship them by default. You will need:
    Code Block
    
    isorelax-20030108.jar
    msv-core-2009.1.jar
    relaxngDatatype-20020414.jar
    xercesImpl-2.9.1.jar
    xml-resolver-1.2.jar
    xsdlib-2009.1.jar
    
  4. If not using a default bus (such as configuring your own spring context), you'll need to add:
    Code Block
    xml
    xml
    
    <import resource="classpath:META-INF/cxf/cxf-extension-wstx-msv-validation.xml" />
    
    to load the validator utilities that Aegis will use.
  5. Turn on schema validation like you would for JAXB by using the @SchemaValidation annotation or setting the "schema-validation-enabled" property on the endpoint to "true".

Using Java Classes That Aren't Visible to the Service Interface

...

Aegis can handle all of these. For all except interfaces, there are two mechanisms that involved: the root class list and xsi:type attributes.

As explained above, Aegis can write 'anything', but it can only read objects of types that are mapped. You must give Aegis a list of all the types that you want to use over and above those visible from the service, and you must instruct Aegis to send xsi:type attributes when sending
objects of such types.
These type attributes allow Aegis to identify the type of these additional objects and look them up in the mappings.

Interfaces and abstract types require one further step. Obviously, Aegis cannot instantiate (run 'new') on an interface. So Thus, knowing that a particular XML Schema type maps to an interface is not enough information. To be able to read an XML element that corresponds to an interface, Aegis must know a 'proxy class' that implements the interface. You must give Aegis a mapping from interface types to proxy class names.

...

  • rootClasses is a collection of Java Class<?> objects. These are added to the list of types known to Aegis. Aegis will create a mapping for each. For convenience, there is a rootClassNames property for use from Spring. It is a list of Strings containing class names.
  • writeXsiTypes is a boolean. Set it to true to send xsi:type attributes.

...

  • defaultNillable defines the default value of the nillable attribute of xsd:element items in the xsd:sequences built for non-primitive types. By default, it is true, since any Java reference can be null. However, nillable='true' has annoying consequences in some wsdl2java tools (turning scalars into arrays, e.g.), and so many programmers prefer to default to false.

...

By and large, front-ends map services to XML schema, filling in XML Schema elements and types for messages and parts. Data bindings then map from those schema items to Java. However, Aegis also provides XML configuration for methods and parameters, which 'poach' in the territory of the front end. This works well for the Simple front end, which has no other way to control these mappings. The present author is not sure what will happen in the event of a conflict between Aegis and any other front-end, like JAX-WS, that has explicit configuration. The Thus, Aegis service configuration is best used with the Simple front end.

...

This is a copy of the XML Schema for mapping XML files that is annotated with comments.

Bean

...

Mapping

Here is a very simple mapping. It takes a property named 'horse', renames it to 'feathers', and makes it an attribute instead of an element.

...

Later on, we will explain how to replace the default mappings that Aegis provides for basic types. However, tehre there are some cases where you may want to simply specify one of the provided type mappings for one of your properties. You can do that from the XML mapping file without creating any Java customization.

...

This example specifies that getUnannotatedStrings returns a return an element names named UnannotatedStringCollection which is a raw collection of String values. It then specifies the first parameter of getValues is also a raw collection of String values.

Code Block
xml
xml
<mappings>
	   <mapping>
		      <method name="getUnannotatedStrings">
			         <return-type name="UnannotatedStringCollection" 
             componentType="java.lang.String"/>
		      </method>
        <method name="getValues">
         <parameter index="0" componentType="java.lang.String"/>
        </method>
	   </mapping>
</mappings>

Annotations

...

Note, however, that Aegis goes does not handle package-info.java classes, and so XmlSchema must be applied to a class.

...