Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

A transformer is the data conversation logic that transforms data from one format to another format. For example, a transformer can convert the DOM Node into a SDO dataobject. A transformer will be registered as an edge connecting the source databinding to the target databinding. The weight of a transformer represents the cost
of the transformation.

The following is an incomplete list of transformers that we ship in 1.0-incubating release.

Code Block
org.apache.tuscany.sca.databinding.sdo.DataObject2String;source=commonj.sdo.DataObject,target=java.lang.String,weight=40
org.apache.tuscany.sca.databinding.sdo.DataObject2XMLStreamReader;source=commonj.sdo.DataObject,target=javax.xml.stream.XMLStreamReader,weight=10
org.apache.tuscany.sca.databinding.sdo.XMLDocument2String;source=commonj.sdo.helper.XMLDocument,target=java.lang.String,weight=40
org.apache.tuscany.sca.databinding.sdo.String2DataObject;source=java.lang.String,target=commonj.sdo.DataObject,weight=50
org.apache.tuscany.sca.databinding.sdo.XMLDocument2XMLStreamReader;source=commonj.sdo.helper.XMLDocument,target=javax.xml.stream.XMLStreamReader,weight=10
org.apache.tuscany.sca.databinding.sdo.XMLStreamReader2DataObject;source=javax.xml.stream.XMLStreamReader,target=commonj.sdo.DataObject,weight=15
org.apache.tuscany.sca.databinding.sdo.XMLStreamReader2XMLDocument;source=javax.xml.stream.XMLStreamReader,target=commonj.sdo.helper.XMLDocument,weight=15
org.apache.tuscany.sca.databinding.sdo.DataObject2Node;source=commonj.sdo.DataObject,target=org.w3c.dom.Node,weight=40
org.apache.tuscany.sca.databinding.sdo.Node2DataObject;source=org.w3c.dom.Node,target=commonj.sdo.DataObject,weight=40

org.apache.tuscany.sca.databinding.xml.InputSource2Node;source=org.xml.sax.InputSource,target=org.w3c.dom.Node,weight=40
org.apache.tuscany.sca.databinding.xml.InputStream2Node;source=java.io.InputStream,target=org.w3c.dom.Node,weight=40
org.apache.tuscany.sca.databinding.javabeans.DOMNode2JavaBeanTransformer;source=org.w3c.dom.Node,target=java.lang.Object,weight=10000
org.apache.tuscany.sca.databinding.xml.Node2String;source=org.w3c.dom.Node,target=java.lang.String,weight=40
org.apache.tuscany.sca.databinding.xml.Node2XMLStreamReader;source=org.w3c.dom.Node,target=javax.xml.stream.XMLStreamReader,weight=40
org.apache.tuscany.sca.databinding.javabeans.JavaBean2DOMNodeTransformer;source=java.lang.Object,target=org.w3c.dom.Node,weight=10000
org.apache.tuscany.sca.databinding.xml.Reader2Node;source=java.io.Reader,target=org.w3c.dom.Node,weight=40
org.apache.tuscany.sca.databinding.xml.SAX2DOMPipe;source=org.xml.sax.ContentHandler,target=org.w3c.dom.Node,weight=30
org.apache.tuscany.sca.databinding.xml.StreamDataPipe;source=java.io.OutputStream,target=java.io.InputStream,weight=50
org.apache.tuscany.sca.databinding.xml.String2Node;source=java.lang.String,target=org.w3c.dom.Node,weight=50
org.apache.tuscany.sca.databinding.xml.String2XMLStreamReader;source=java.lang.String,target=javax.xml.stream.XMLStreamReader,weight=50
org.apache.tuscany.sca.databinding.xml.Writer2ReaderDataPipe;source=java.io.Writer,target=java.io.Reader,weight=50
org.apache.tuscany.sca.databinding.xml.XMLStreamReader2Node;source=javax.xml.stream.XMLStreamReader,target=org.w3c.dom.Node,weight=40
org.apache.tuscany.sca.databinding.xml.XMLStreamReader2String;source=javax.xml.stream.XMLStreamReader,target=java.lang.String,weight=40
org.apache.tuscany.sca.databinding.xml.Node2SimpleJavaType;source=org.w3c.dom.Node,target=java:simpleType,weight=10000
org.apache.tuscany.sca.databinding.xml.SimpleJavaType2Node;source=java:simpleType,target=org.w3c.dom.Node,weight=10000

org.apache.tuscany.sca.databinding.axiom.Object2OMElement;source=java:simpleType,target=org.apache.axiom.om.OMElement,weight=10000
org.apache.tuscany.sca.databinding.axiom.OMElement2Object;source=org.apache.axiom.om.OMElement,target=java:simpleType,weight=10000
org.apache.tuscany.sca.databinding.axiom.OMElement2String;source=org.apache.axiom.om.OMElement,target=java.lang.String,weight=40
org.apache.tuscany.sca.databinding.axiom.OMElement2XMLStreamReader;source=org.apache.axiom.om.OMElement,target=javax.xml.stream.XMLStreamReader,weight=10
org.apache.tuscany.sca.databinding.axiom.String2OMElement;source=java.lang.String,target=org.apache.axiom.om.OMElement,weight=40
org.apache.tuscany.sca.databinding.axiom.XMLStreamReader2OMElement;source=javax.xml.stream.XMLStreamReader,target=org.apache.axiom.om.OMElement,weight=10

org.apache.tuscany.sca.databinding.jaxb.JAXB2Node;source=javax.xml.bind.JAXBElement,target=org.w3c.dom.Node,weight=30
org.apache.tuscany.sca.databinding.jaxb.Node2JAXB;source=org.w3c.dom.Node,target=javax.xml.bind.JAXBElement,weight=30
org.apache.tuscany.sca.databinding.jaxb.Reader2JAXB;source=java.io.Reader,target=javax.xml.bind.JAXBElement,weight=30
org.apache.tuscany.sca.databinding.jaxb.XMLStreamReader2JAXB;source=javax.xml.stream.XMLStreamReader,target=javax.xml.bind.JAXBElement,weight=10

org.apache.tuscany.sca.databinding.saxon.Node2NodeInfoTransformer;source=org.w3c.dom.Node,target=net.sf.saxon.om.NodeInfo,weight=10
org.apache.tuscany.sca.databinding.saxon.NodeInfo2NodeTransformer;source=net.sf.saxon.om.NodeInfo,target=org.w3c.dom.Node,weight=10
org.apache.tuscany.sca.databinding.saxon.Object2ValueTransformer;source=java.lang.Object,target=net.sf.saxon.value.Value,weight=10000
org.apache.tuscany.sca.databinding.saxon.Value2ObjectTransformer;source=net.sf.saxon.value.Value,target=java.lang.Object,weight=10000
org.apache.tuscany.sca.databinding.saxon.SimpleType2ValueTransformer;source=java:simpleType,target=net.sf.saxon.value.Value,weight=10000
org.apache.tuscany.sca.databinding.saxon.Value2SimpleTypeTransformer;source=net.sf.saxon.value.Value,target=java:simpleType,weight=10000
org.apache.tuscany.sca.databinding.saxon.NodeInfo2DataObjectTransformer;source=net.sf.saxon.om.NodeInfo,target=commonj.sdo.DataObject,weight=20
org.apache.tuscany.sca.databinding.saxon.DataObject2NodeInfoTransformer;source=commonj.sdo.DataObject,target=net.sf.saxon.om.NodeInfo,weight=10

org.apache.tuscany.sca.databinding.sdo2om.DataObject2OMElement;source=commonj.sdo.DataObject,target=org.apache.axiom.om.OMElement,weight=1000
org.apache.tuscany.sca.databinding.sdo2om.XMLDocument2OMElement;source=commonj.sdo.helper.XMLDocument,target=org.apache.axiom.om.OMElement,weight=1000


Logical Type vs. Physical Type

The runtime's main job is to connect user components together so typically the actual type used would be determined by the user code that implements the source or target. The databinding framework's role here is to convert from the type used by the source to the type used by the target. The internal types used by the runtime should not influence this - which is an essential separation to maintain given the components and the wire connecting them need to work on different runtimes (implemented in different languages).

Where runtime types do matter is in the conversion between some serialized form and an in-memory representation and the two places where that occurs are in the configuration properties and in the binding implementations. To handle configuration properties (with the XPath requirement) we use DOM in the Java runtime; I believe the C++ runtime uses SDO. Each transport binding also tends to deserialize using a specific technology - for example, AXIOM for Axis2, JAXB for JAX-WS, Serializable for RMI and so the databinding framework is used to convert between the form generated by the binding and the form used by the component.

The logical type represents the data type the user thinks is flowing across a wire. This could be a Java type, a XML type, a CORBA type, whatever depending on the /logical/ service contract defined in the assembly.

The physical type is the actual representation of that type that is flowed by the runtime. In the Java runtime this will always be a Java type (i.e. some subclass of Object). In some cases it will be the same as the logical type - e.g. when a Java component calls another Java component over a local wire using a Java interface then both logical and physical types will be the same. In many cases though they will be different - for example, if the service contract was WSDL then the logical type would be the XML type used by the WSDL.

Within the runtime the same logical type may have different physical forms. For example, the same XML document could be represented physically as a DOM, a StAX stream, an SDO, a JAXB object, or an AXIOM stream. The framework supports conversion between these different physical forms.

1. A component (A) consumes a service provided by another component (B). The implementation of A prefers SDO while the implementation of B prefers JAXB.

In the SCA term, A is wired to B using a reference.

  • Data is represented by an interface which is independent of the databinding
  • Data is represented by an interface or class which is databinding-specific (either generated or dynamic)

2. A component (A) consumes a web service using axis2. Axis2 engine expects to handle AXIOM objects.

3. A component is exposed as a service over a transport/protocol.

Where runtime types do matter is in the conversion between some serialized form and an in-memory representation and the two places where that occurs are in the configuration properties and in the binding implementations. To handle configuration properties (with the XPath requirement) we use DOM in the Java runtime; I believe the C++ runtime uses SDO. Each transport binding also tends to deserialize using a specific technology - for example, AXIOM for Axis2, JAXB for JAX-WS, Serializable for RMI and so the databinding framework is used to convert between the form generated by the binding and the form used by the component.

interfaces for services and references are the contracts for SCA assembly.

Data Transformations

How to transform data across databindings

  • A databinding is a terminal for the data transformation
  • Three types of databindings depending on how the data is represented by the databinding
    • Some databindings can feed the data for consumption
    • Some databindings serve a sink to receive data
    • Some databindings can bridge the sink so that data coming into the sink can be consumed by others
      Scenario 1: Source --> Source
      Scenario 2: Source --> Sink
      Scenario 3: Sink --> Source (Pipe)

How to use databindings?
Declare the data binding for the interfaces

  • Data Binding requirement can be expressed as:
    • SCDL extension
Code Block

@Remotable
public interface MyInterface {
    Node call(Node msg); 
    XMLStreamReader call1(XMLStreamReader msg); 
}

Fine-grained databinding control

Java annotations for a remotable interface

What's behind the magic?

Load and build the data binding metadata

  • The XML or annotation is loaded/processed as the DataBindingDefinition model object
  • The builder will resolve the DataBindingDefinition and create DataBinding as the runtime context for transformation

Databinding transformer graph

Image Removed

The algorithm to calculate the transformation path

  • The transformers are registered and selected using the following algorithm.
    • The data transformation capabilities for various databindings can be nicely modeled as a weighted, directed graph with the following rules. (Illustrated in the attached diagram).
    • Each databinding is mapped to a vertex.
    • If databinding A can be transformed to databinding B, then an edge will be added from vertex A to vertex B.
    • The weight of the edge is the cost of the transformation from the source to the sink.
  • In the data interceptor on the wire, if we find out that the data needs to be transformed from databinding A to databinding E. Then we can apply Dijkstra's Shortest Path Algorithm to the graph and figure the most performed path. It can be A->E, or A>C->E depending on the weights. If no path can be found, then the data cannot be mediated.
    Transform data
  • Direct transformation

...

The data transformation graph

Databinding transformer graph

Image Added

The algorithm to calculate the transformation path

  • The transformers are registered and selected using the following algorithm.
    • The data transformation capabilities for various databindings can be nicely modeled as a weighted, directed graph with the following rules. (Illustrated in the attached diagram).
    • Each databinding is mapped to a vertex.
    • If databinding A can be transformed to databinding B, then an edge will be added from vertex A to vertex B.
    • The weight of the edge is the cost of the transformation from the source to the sink.
  • In the data interceptor on the wire, if we find out that the data needs to be transformed from databinding A to databinding E. Then we can apply Dijkstra's Shortest Path Algorithm to the graph and figure the most performed path. It can be A->E, or A>C->E depending on the weights. If no path can be found, then the data cannot be mediated.
    Transform data
  • Direct transformation
  • Multi-hop transformation

Logical Type vs. Physical Type

The runtime's main job is to connect user components together so typically the actual type used would be determined by the user code that implements the source or target. The databinding framework's role here is to convert from the type used by the source to the type used by the target. The internal types used by the runtime should not influence this - which is an essential separation to maintain given the components and the wire connecting them need to work on different runtimes (implemented in different languages).

Where runtime types do matter is in the conversion between some serialized form and an in-memory representation and the two places where that occurs are in the configuration properties and in the binding implementations. To handle configuration properties (with the XPath requirement) we use DOM in the Java runtime; I believe the C++ runtime uses SDO. Each transport binding also tends to deserialize using a specific technology - for example, AXIOM for Axis2, JAXB for JAX-WS, Serializable for RMI and so the databinding framework is used to convert between the form generated by the binding and the form used by the component.

The logical type represents the data type the user thinks is flowing across a wire. This could be a Java type, a XML type, a CORBA type, whatever depending on the /logical/ service contract defined in the assembly.

The physical type is the actual representation of that type that is flowed by the runtime. In the Java runtime this will always be a Java type (i.e. some subclass of Object). In some cases it will be the same as the logical type - e.g. when a Java component calls another Java component over a local wire using a Java interface then both logical and physical types will be the same. In many cases though they will be different - for example, if the service contract was WSDL then the logical type would be the XML type used by the WSDL.

Within the runtime the same logical type may have different physical forms. For example, the same XML document could be represented physically as a DOM, a StAX stream, an SDO, a JAXB object, or an AXIOM stream. The framework supports conversion between these different physical forms.

1. A component (A) consumes a service provided by another component (B). The implementation of A prefers SDO while the implementation of B prefers JAXB.

In the SCA term, A is wired to B using a reference.

  • Data is represented by an interface which is independent of the databinding
  • Data is represented by an interface or class which is databinding-specific (either generated or dynamic)

2. A component (A) consumes a web service using axis2. Axis2 engine expects to handle AXIOM objects.

3. A component is exposed as a service over a transport/protocol.

Where runtime types do matter is in the conversion between some serialized form and an in-memory representation and the two places where that occurs are in the configuration properties and in the binding implementations. To handle configuration properties (with the XPath requirement) we use DOM in the Java runtime; I believe the C++ runtime uses SDO. Each transport binding also tends to deserialize using a specific technology - for example, AXIOM for Axis2, JAXB for JAX-WS, Serializable for RMI and so the databinding framework is used to convert between the form generated by the binding and the form used by the component.

interfaces for services and references are the contracts for SCA assembly.

Data Transformations

How to transform data across databindings

  • A databinding is a terminal for the data transformation
  • Three types of databindings depending on how the data is represented by the databinding
    • Some databindings can feed the data for consumption
    • Some databindings serve a sink to receive data
    • Some databindings can bridge the sink so that data coming into the sink can be consumed by others
      Scenario 1: Source --> Source
      Scenario 2: Source --> Sink
      Scenario 3: Sink --> Source (Pipe)

How to use databindings?
Declare the data binding for the interfaces

  • Data Binding requirement can be expressed as:
    • SCDL extension
Code Block

@Remotable
public interface MyInterface {
    Node call(Node msg); 
    XMLStreamReader call1(XMLStreamReader msg); 
}

Fine-grained databinding control

Java annotations for a remotable interface

Deal with different IDLs
Dealing with WSDL/XSD based IDLs

...