Wednesday, September 14, 2011

SCA (Service Component Architecture)- Part 2

This is the second part in the series of articles that will cover SCA. See Part 1 for some background.


How do I create an SCA component/Composite?
The below sections use the SCA java programming model to describe the annotations that are available, followed by an example.


Brief Overview of Annotations
The below is a very brief overview of the Annotations in SCA. This is just meant as a cursory reference. Please refer the SCA spec for details.

 @Service
 A Java class component uses @Service annotation to specify the interface of the services implemented. 


@Remotable
This annotation defines a remotable service in the Java interface of the service. Remotable services use by-value data exchange semantics. 



Local service
A local service can only be invoked by clients that are part of the same module. A Java local service interface is defined without a @Remotable annotation.


@AllowPassByReference
This annotation on the implementation of a remotable service is used to declare that whether
it allows pass by reference data exchange semantics on calls to it. 
Local services use by-reference data exchange semantics, so changes made to parameters are seen by both the client and the service provider.

@Scope
A @Scope annotation on either the service's interface definition or on the service class denotes a scoped service.  The scope values could be:
  • stateless: This is the default and each request in this mode is handled separately.
  • request: In this mode the requests are directed to the same Java interface for all local service invocations that occur while servicing a remote service request.
  • session : In this mode the requests are directed to the same Java instance for all requests in the same "session".
  • module :In this mode the requests are directed to the same Java instance for all requests within the same "module".

The SCA runtime will prevent concurrent execution of methods on an instance of these implementations except for the module scoped one.

Lifecycle methods on a scoped service are implemented using @Init(called only once at the start of its scope and after its properties and references have been injected) annotation and @Destroy(called when its scope ends) annotation.


@Property

This annotation on a field or method in the Java class defines the configuration properties of a Java component implementation. It takes the name of the property and the boolean to specify whether injection is required.

@Reference
This annotation is used to acquire access to a service using reference injection it takes the name of the reference and whether it is required.

@Context
This annotation along with a field of type ModuleContext is used to access a service.

@Oneway
This annotation is used to mark a non-blocking method. The method returns immediately allowing the client to continue execution.


@Session and @SessionID
These annotations along with @Scope is used to implement conversational services. A session is used to maintain information about a single conversation between a client and a remotable service. Thus, SCA simplifies the design of conversational services while leaving the details of ID generation, state management and routing to the SCA container.

@Callback
This annotation can be used to provide callback services on a remotable service interface. It takes the Java Class object of the interface as a parameter. The Callback service provides asynchronous communication from a service provider to its client. 



Examples  (Taken from Apache Tuscany)


Catalog Interface
package abc;
import org.oasisopen.sca.annotation.Remotable;


@Remotable
public interface Catalog {
    Item[] get();
}


Cart Interface


@Remotable
public interface Cart extends Collection<String, Item> {
}


Total Interface


@Remotable
public interface Total {
    String getTotal();
}

Catalog Interface Implementation


package abc;
import org.oasisopen.sca.annotation.Init;
import org.oasisopen.sca.annotation.Property;
import org.oasisopen.sca.annotation.Reference;


public class FruitsCatalogImpl implements Catalog { 
    @Property
    public String currencyCode = "USD";

    @Reference
    public CurrencyConverter currencyConverter;

    private List<Item> catalog = new ArrayList<Item>();
   
   @Init
    public void init() {
        //some code
    }
    public Item[] get() {
       return catalogArray;
    }
}


Shopping Cart Implementation 


package abc;
import org.apache.tuscany.sca.data.collection.Entry;
import org.apache.tuscany.sca.data.collection.NotFoundException;
import org.oasisopen.sca.annotation.Init;
import org.oasisopen.sca.annotation.Scope;


@Scope("COMPOSITE")
public class ShoppingCartImpl implements Cart, Total { 
    private Map<String, Item> cart; 
    @Init
    public void init() {}


    public Entry<String, Item>[] getAll() {
        return entries;
    }


    public Item get(String key) throws NotFoundException {
       //return item
    }


    public String post(String key, Item item) {
       //put in cart and return key.
        return key;
    }


    public void put(String key, Item item) throws NotFoundException {
        //update item
    }

    public void delete(String key) throws NotFoundException {}


    public Entry<String, Item>[] query(String queryString) {
     }

    public String getTotal() {
        //return total
    }
}


SCDL File
<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912"
xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.1"
targetNamespace="http://store"
name="store">

      <component name="Store">
        <tuscany:implementation.widget location="uiservices/store.html"/>
        <service name="Widget">
         <tuscany:binding.http uri="/store"/>
        </service>
<reference name="catalog" target="Catalog"/>
 <reference name="shoppingCart" target="ShoppingCart/Cart"/>
 <reference name="shoppingTotal" target="ShoppingCart/Total"/>
       </component>

<component name="Catalog">
<implementation.java class="services.FruitsCatalogImpl"/>
<property name="currencyCode">USD</property>
<service name="Catalog">
<tuscany:binding.jsonrpc uri="/Catalog"/>
    </service>
<reference name="currencyConverter" target="CurrencyConverter"/>
</component>
 
<component name="ShoppingCart">
<implementation.java class="services.ShoppingCartImpl"/>
<service name="Cart">
<tuscany:binding.atom uri="/ShoppingCart/Cart"/>
</service>    
<service name="Total">
<tuscany:binding.jsonrpc uri="/ShoppingCart/Total"/>
</service>    
</component>


<component name="CurrencyConverter">
<implementation.java class="services.CurrencyConverterImpl"/>
</component>  


       <service name="CompositeWidget" promote="Store/Widget">
         <tuscany:binding.http uri="/compositestore"/>
        </service>
</composite>