Article on caGrid Serialization
| |
|
|
| |
Contents |
|
| |
|
|
Overview
Clients and services in caBIG communicate through the grid using Globus grid clients and service infrastructure, respectively. The grid communication protocol is XML, and thus the client and service APIs must transform the transferred objects to and from XML. This XML serialization of caBIG objects is restricted in that each object that travels on the grid must do so as XML, which adheres to an XML schema registered in the Global Model Exchange (GME). As the caDSR and EVS define the properties, relationships, and semantics of caBIG data types, the GME defines the syntax of the XML serialization of them. Furthermore, Globus services are defined by the Web Service Description Language (WSDL). The WSDL describes the various operations the service provides to the grid. The inputs and outputs of the operations, among other things, in WSDL are defined by XML schemas. As caBIG requires that the inputs and outputs of service operations use only registered objects, these input and output data types are defined by the XSDs, which are registered in GME. In this way, the XSDs are used both to describe the contract of the service and to validate the XML serialization of the objects it uses.
Object Serialization
As mentioned in a preceding section, objects must serialize to and from XML as they traverse the grid. This section details the alternative approaches for that process. Standard Globus Serialization caGrid is built using the Globus 4 toolkit. The Globus toolkit has a complete set of tools for automatic generation of serializable objects using models defined in XSDs. Using this mechanism, Globus has the ability to automatically create a set of Java Beans which represent this model which will be able to be serialized and deserialized automatically at client and service runtime via the Globus toolkit with no extra configuration. In order to use these types in a grid service, the developer must describe the types that will be used in the WSDL file. This will enable Globus to locate the types and generate the required beans during stub generation time. For more information on this process, please see the Globus documentation. Using this approach, the object-oriented client and service APIs are written using the Globus generated Java Objects. The toolkit will automatically serialize and deserialize the Objects as they travel to and from the grid.
Here are some useful links:
- Globus 4.0 Java WS Core developer's documentation (describes how Globus uses the Apache Axis toolkit to serialize types): Globus 4.0 Java WS Core developers documentation
. - Apache Axis type mappings page for various XML schema types: Apache Axis type mappings

Custom Serialization
If a developer already has a Java object model already in use that is either not serializable or uses a custom serialize, the developer will need to configure the Globus service and client to be able to use the custom serialize. This can be done by using the Globus type-mapping configuration xml in the services WSDD and in the client's configuration WSDD. This type-mapping paradigm is documented in the Globus documentation, but the basics are covered in this document. If a user has an object called MyObject that has its own serializer, then the following configuration must be placed in both the service WSDD and the client configuration WSDD:
<service ...> ... <typeMapping encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" serializer="gov.nih.nci.cabig.MySerializerFactory" deserializer="gov.nih.nci.cabig.MyDeserializerFactory" type="java:gov.nih.nci.cabig.bean.MyType" qname="ns1:myType" xmlns:ns1=http://cabig.nci.nih.gov/1/myType /> ... </service>
This configuration will now allow the service to use the MySerializerFactory and MyDeserializerFactory to marshal its object back and forth across the grid. The typeMapping element must be in the server and client wsdd and in order for the custom serializer and deserializer to be invoked.
Programmatic Deserialization
De-serializing an object is easy if you use provided caGrid utility classes.
If you have the Java classes for these objects, you can use caGrid's Utils class from the Core project to deserialize the XML:
Class clazz = Class.forName("your class name here"); Reader reader = new StringReader("your xml here");// or FileReader("filename"); Object o = gov.nih.nci.cagrid.common.Utils.deserializeObject(reader, clazz); // cast o as a type, etc.
Class clazz = Class.forName("your class name here"); Reader reader = new StringReader("your xml here");// or FileReader("filename"); InputStream wsdd = new FileInputStream("path/to/client-config.wsdd"); Object o = gov.nih.nci.cagrid.common.Utils.deserializeObject(reader, clazz, wsdd); // cast o as a type, etc.
caCORE SDK Serialization
![]() |
| Credential Delegation Service (CDS) |
The components used to support this functionality are shown in the "SDK (Castor) Serialization Framework" Image. The Factory class' sole responsibility is to be hooked into the underlying Axis framework, and return an appropriate instance of the Serializer and Deserializer classes as needed. Both of these classes internally utilize the Castor APIs to marshal and unmarshal the Java Beans as needed. They leverage the EncodingUtils to access the appropriate Castor mapping. This utility first attempts to read a configuration parameter, "castorMapping", from the current Axis context. This property can be specified in the client and service WSDD file, as shown in the highlighted section of the example mapping image. The value of this parameter is expected to be a classpath reference to the Castor XML mapping file that should be used. This parameter allows multiple services or clients running in the same environment to use different mappings. If this parameter is not set, the mapping is expected to be loaded from the default location (/xml-mapping.xml). This location will work for SDK generated Java Beans, as it is included in their jar files under said location. However, as mentioned, the preferred approach is to explicitly specify a unique location because if two SDK-generated systems were used in the same environment (or the caCORE standard client.jar is used), only one of the mappings would be loadable (as determined by the classpath settings).
Introduce Support
Introduce supports automatically specifying SDK Serialization and the appropriate WSDD configurations are made automatically. The service's serialization behavior is controlled by the server-config.wsdd file in the root directory of the service, and the client behavior is controlled by the client-config.wsdd file in the "client" package of the service (in the src folder). Introduce clients overload the default Axis behavior of looking for client-config.wsdd in the working directory and load the file as a resource from the service's jars. As the file is placed in a service-specific package, this behavior allows multiple (potentially conflicting) client APIs to be used in the same context.
Controlling Generation of Beans
By default, when you add a schema (data type) to Introduce, Java Beans will automatically be created for these types and they will automatically be serialized and deserialized.
Custom Serialization in Introduce
If you use custom serialization as described above, however, these will not be generated because it is expected you have your own classes on the classpath. Shown below is an example of using custom serialization in Introduce. This will prevent these classes from being generated.
Default Serialization without Generation of Beans in Introduce
If you want to use default serialization but don't want Introduce to generate your beans, you can specify this in introduce.xml. If you find the section that defines the Namespaces, locate the definition of the schema of interest, and add an attribute as follows:
generateStubs="false"
then open your service and re-save it. Your service's build process will no longer generate beans for this schema, so you should be sure to have these classes on your classpath. An example is shown below (note the highlighted section):
One example use case for doing this is if you want to add specific business logic to the generated beans. You can initially generate them, copy the generated beans into your source tree, and then configure them to not be regenerated.
Use of maxOccurs and minOccurs
Previously, a user has needed to pass some optional "Double" values in a service. When the "Double" attribute is defined, it is converted to type "xs:double". In the Introduce generated framework (Java stub code), this attribute is declared as primitive java type (instead of java.land.Double). This prevents the user from detecting null values in the Java code.
The explanation is that when Introduce writes the schema for the service interface, it does not set the minOccurs maxOccurs as it is intended to use the defaults. When using a primitive, if you want it to be optional, then you would need to set the minOccurs to 0. This will tell axis to map it to the Double and not the double. However, you can still achieve this by creating your own type in a schema that sets the minOccurs to 0 and import it into Introduce and use that type.









