IBM BPM, V8.0.1, All platforms > Programming IBM BPM > Service Component Architecture programming > SCA programming model fundamentals > Invocation styles
SCA data object containment and wrapper usages
The SCA execution environment requires that invocation parameters be contained within a business object wrapper as determined by the operation and the interface.
Some interfaces require no wrapper when a single argument is accepted while other interfaces require a wrapper for any operation.
For example, a Java method which accepts a single parameter does not require the parameter be wrapped. All Document Literal Wrapped style WSDL operations require a wrapper regardless of the number of parameters.
When a wrapper is required, it can be instantiated by using the BOFactory.createByType(...) method as illustrated in the following example code:
Service service = (Service) locateService_servicePartner(); Type inputType = service.getReference().getOperationType("echoMulti").getInputType(); ServiceManager serviceManager = new ServiceManager(); BOFactory boFactory = (BOFactory) serviceManager.locateService("com/ibm/websphere/bo/BOFactory"); DataObject wrapper = boFactory.createByType(inputType); wrapper.set(0, new Integer(5)); wrapper.set(1, new Integer(10)); service.invoke("echoMulti", wrapper);When no wrapper is required for single argument operations, the OperationType.getInputType() returns the type of the first and only argument. In this case, the createByType method can only be used when the Type describes a specific complex type. This method cannot be used for simple types or for abstract types such as xs:anyType.
Containment
Most business objects use a containment relationship which enforces a single parent relationship. Setting a business object value into the property of another business object moves the value to the new property, which results in removal from the original parent. You can see this relationship in action when you view the XML representation of the DataObjects:
<parent> <child> ... </child> </parent>In this example, “child” is always contained within the enclosing elements of its parent. It can be moved to another parent container, but cannot exist as a sub-element of two parents without copying the XML text <child>…</child>.
In order to avoid damaging the existing containment relationship, a DataObject must first be cloned before being set into another property. To prevent unnecessary cloning of DataObject parameters and facilitate a simplified programming model, the SCA container provides input and output types with non-containment properties when the interface is either a Java interface or a WSDL interface using the document literal wrapped style. No clone is necessary when the wrapper is created by using the Type returned by the OperationType.getInputType() or OperationType.getOuputType() methods for these interface types. To instantiate the wrapper for these types, use the BOFactory.createByType(...) method.
When the wrapper is created for other interface styles or by other Business Object Factory methods such as createByElement, the necessity of cloning DataObject parameters must be managed by the caller. Whether management of the containment relationship is necessary for the caller can be determined by introspecting the complex Property for the non-containment attribute: Property.isContainment().
Type type = operationType.getInputType(); List properties = type.getProperties(); for(int i=0;i<properties.size();i++){ Property property = (Property)properties.get(i); if(property.getType().getInstanceClass() == null || property.getType().getInstanceClass().equals(DataObject.class)){ //Property is a complex type if(!property.isContainment()){ //The property is a non-containment complex property. If a DataObject is set to this property, its parent will not be changed } else{ //The property is a containment (ordinary) property. If a DataObject is set to this property, its previous parent will be discarded } } else{ //The property is a simple type. All simple type properties are non-containment } }Regardless of whether a non-containment or containment wrapper type is passed when the invocation is made, the container can present the type found in the Operation metadata to downstream or upstream components. That is, the container prefers to use the type information as returned by the OperationType.getInputType() and OperationType.getOutputType() methods, and can replace another wrapper with the mentioned types as is appropriate.When serialized, a non-containment property does not include the XML representation of the business object, but instead includes only a reference to the business object, which is expressed as a URI. Since this URI is likely not meaningful to the application, direct serialization of container provided non-containment business objects is not advised.
Object Reference Visibility
Data Object and Java Object parameters which are passed either directly or as a non-containment property of a wrapper are provided directly to component implementations when the invocation occurs on the same thread and within the same module. This means that the caller and the target both view the same business object or Java object, and therefore modifications made to the object in the target component be visible to the caller after the completion of the processing. The object reference is never passed between multiple threads or outside of a single module, so anytime the invocation is transferred to another thread or module, a copy of the original object is provided to the caller.
To promote component implementations which can be used in multiple wiring configurations, it is best to avoid expecting that any object modifications be visible upstream. Instead, if any modifications must be made visible to the caller, return the modified values. Doing so assures that the component can be used consistently regardless of how it is wired and invoked.