Exploring the WebSphere Application Server Feature Pack for SCA, Part 4: SCA Java annotations and component implementation

Part 4 of this series on the IBM® WebSphere® Application Server V7 Feature Pack for SCA provides an overview of the Java™ experience for SCA developers and describes some fundamental principles of SCA implementations. The article also describes the feature pack's support for the Java Component Implementation and Java Common Annotations and APIs specifications.

Chao M Beck, Software Engineer, IBM

Chao Beck is a technical lead for the feature pack for Service Component Architecture (SCA) early program. She has long been a member of the Application Integration Middleware early programs team responsible for the execution of early programs for IBM WebSphere Application Server products. She handles the development and delivery of education for new product functions and the provision of customer support during pre-GA (early) programs and post-GA (customer acceleration) programs.



Stephen Kinder, Senior Technical Staff Member, IBM

Stephen Kinder is a Senior Technical Staff Member and is the lead architect for the delivery of Service Component Architecture in WebSphere Application Server. He has worked for IBM for 20 years and has been involved in WebSphere products for 10 years.



18 February 2009

Also available in Chinese Japanese Spanish

Introduction

The Service Component Architecture (SCA) assembly model offers you the ability to assemble and wire service components using commonly used programming languages. The specification lets you concentrate on solving specific problems by enabling a diverse range of service components to interact and collaborate. The language-neutral design enables the extension of SCA concepts into willing application environments, regardless of whatever specific technologies might be the focus of those environments. The SCA programming model provides meta data and APIs for enabling services to operate in an SOA aware environment.

The Java programming language is a popular choice for implementing a service. The Open SCA community has worked to define a Java variant of the SCA programming model, which is supported by the IBM WebSphere Application Server V7 Feature Pack for SCA. The programming model provides for existing Java annotations and APIs so that programmers can make services operate seamlessly for SCA business logic. Wherever possible, Java techniques like injection are used in place of APIs to simplify programming. An additional fundamental principle of the SCA programming model, which is realized in Java, is the notion of a separation of concerns, in that the developer of the service implementation need not be concerned with the details of the service implementations it references, nor does the developer need be concerned about the implementation details of the consumers that use any of the provided services.

This article provides an overview of the SCA programming model for Java. This programming model is described in two specifications:

  • The Java Component Implementation Specification extends the SCA assembly model (the core spec) by defining how a Java class provides an implementation of an SCA component and how that class is used in SCA as a component implementation. This specification defines a simple Java POJO model for creating service components.
  • The SCA Java Common Annotations and APIs Specification defines Java APIs and annotations that enable service components and service clients to be built in the Java language.

There are closely related specifications describing how other Java-based frameworks and application environments can be used in the context of SCA, such as Spring and EJB components, which can also use the common annotations and APIs. These specs and behaviors are beyond the scope of the initial delivery of the Feature Pack for SCA.

Figure 1. The SCA component
Figure 1. The SCA component

As shown in Figure 1, a component is the basic element of a business function in an SCA application. In terms of implementation, this means that a component is basically a configured instance of a single implementation. The configurable aspects of a component are:

  • A service is defined in terms of an interface, bindings, intents, and policy sets for quality of service. A good service interface is focused on providing business value. It should be loosely coupled to distributed technologies and loosely coupled to implementation technology. Following these best practices will lead to a more resilient and adaptable enterprise.
  • A reference is a description of a service dependency. It’s also defined in terms of an interface, bindings, intents and policy sets for quality of service. References enable a business service to compose and aggregate other services to provide new business services.
  • A property is also a configurable aspect of an implementation, but differs from a reference in that a property can hold complex or hierarchical data values. A property type is declared by an implementation, but its value is declared by a component. In general, properties should have a business meaning with sufficient generality as to enable the component implementation to be used in multiple applications. Properties are not meant to be used for infrastructural purposes.

Every SCA application is built from one or more components. A group of components, assembled in a composite, can be interconnected to form an assembly that exposes one or more business services.

In Figure 1, the interface is shown as a line going into the service and reference. An interface is a contract provided by a service or a contract required by a reference. The component in Figure 1 is part of an SCA domain. This domain represents an administration scoping, potentially distributed over a series of interconnected run time nodes. Components sit inside composites which sit inside a domain. For SCA-enabled WebSphere Application Server configurations, the SCA domain is equivalent in scope with the Network Deployment cell.

Bindings describe the transport and protocol configuration of services and references when interacting with endpoints or consumers, both inside and outside the SCA domain. Examples include: Web services, EJB RMI/IIOP, and so on. The bottom left and right of Figure 1 depicts bindings as lines going into the service and reference. A binding is a description of an access mechanism offered by a service, a description of an access mechanism needed by a reference.

SCA also provides a default binding that can be used by remotely deployed components in the same SCA Domain. This has the advantage of enabling the assembler to refer to services in the SCA domain by a logical name, requiring no specific binding configuration, and is therefore easier to use. Be aware that binding configuration generally does not surface into a component implementation; this is intentional and desirable. By abstracting out the binding specifics into metadata, business logic can be reused and recast even as the specific infrastructure and connectivity of an SOA matures and evolves.

This separation of concerns really divides development of an SCA application into two roles:

  • business logic developer
  • assembler.

For simple development scenarios, this is usually the same person; in enterprise deployments, however, business logic can be reused in different ways, or even assembled using enterprise-specific conventions, such that the two roles are performed by different individuals.


Java component implementation

A Java class provides an implementation of an SCA component, including its various attributes (services, references, and properties). The services provided by a Java-based implementation might have an interface defined in one of these ways:

  • a Java interface
  • a Java class
  • a Java interface generated from a Web Services Description Language (WSDL) portType.

Java for SCA enables the creation of local or remotable services. Local services can only be consumed by clients that are in the same JVM. Local services are fine-grained, tightly-coupled services that enable you to easily segment business function into discrete components. Remote services are meant to be coarse-grained business services that individually provide a business identifiable function. It is typical to implement a remote service by assembling several local services into an SCA composite.

Java implementation classes must implement all the operations defined by the service interface. If the service interface is defined by a Java interface, the Java-based component can either implement that Java interface, or implement all the operations of the interface.

A service whose interface is defined by a Java class (as opposed to a Java interface) is not remotable, while Java interfaces generated from WSDL portTypes are remotable. A Java implementation might specify the services it provides explicitly through the use of @Service. In certain cases, the use of @Service is not required and the services a Java implementation offers might be inferred from the implementation class itself. @Service can be used to specify that an implementation offers multiple services.

Figure 2 depicts a Java service interface and a Java implementation that provides a service using that interface. There is no infrastructure logic in the business component. Java 5.0 annotations make service declaration and implementation easy.

Figure 2. Java implementation example: Service in Java
Figure 2. Java implementation example: Service in Java

A Java service contract defined by an interface or implementation class might use @Remotable to declare that the service follows the semantics of remotable services as defined by the SCA Assembly specification. If @Remotable is not used, then the service is assumed to be local. If an implementation class has implemented interfaces that are not decorated with an @Remotable annotation, the class is considered to implement a single local service whose interface is defined by the public methods defined in the class.

The data exchange semantic for calls to local services is by-reference. This means that code must be written with the knowledge that changes made to parameters (other than simple types) by either the client or the provider of the service are visible to the calling service.


Java common annotations

Unlike Javadoc tags, Java annotations are reflective in that they are embedded in class files generated by the compiler and can be retained by the JVM to be made retrievable at run time.

Annotations provide a crucial mechanism for specifying elements of the SCA assembly model. For example, annotations can specify the attributes of a service's scope, the nature of implementation, plus interaction attributes, constraints, and requirements. The use of Java annotations is a well established method for specifying metadata, and this aspect is highlighted by the important role given to annotations in several Java EE specifications. The SCA assembly model can utilize introspection for Java implementations to determine the attributes and nature of SCA services. Annotations provide a way for this metadata to be represented as part of the implementation.

Listing 1 shows an example of a service interface for a PaymentService service, which is intended to be called only by clients that are operating in the same JVM and are able to directly receive and pass object references:

Listing 1
package session.pay;

  import org.osoa.sca.annotations.AllowsPassByReference;

  @AllowsPassByReference
  public interface PaymentService {
      public PaymentOutput MakePayment(PaymentInput pI);
  }
Figure 3. SCA scope annotation
Figure 3. SCA scope annotation

The Java programming model enables Java implementations to indicate how the SCA runtime must manage its state. This is covered by the SCA concept of implementation scope. Scope controls the visibility and lifecycle aspects of the implementation. Implementation scope is specified through @Scope, @Init and @Destroy Java annotations.

Invocations on a service offered by a component will be dispatched by the SCA runtime to an implementation instance according to the semantics of its implementation scope. Scopes are specified using the @Scope annotation on the implementation class. The @Scope annotation is used on either a service's interface definition or on a service implementation class itself.

A scope annotation can be added to either the interface or implementation class definition. The Feature Pack for SCA supports stateless and composite scopes:

  • The stateless scope is used when service requests have no implied correlation with prior and future requests. Each request operates independent of each other and the SCA runtime makes no guarantees of retaining state information of that service.
  • When an implementation is under composite scope, all service requests are routed to the same implementation instance for the lifetime of the containing composite (aervices deployed with the composite scope in a cluster result in one singleton per JVM). The Feature Pack for SCA does not support request or conversational scopes.

An implementation can declare lifecycle methods that are called when a component instance is instantiated or when the scope is expired. @Init denotes that the method must be called upon the first use of an instance during the lifetime of the scope. @Destroy specifies the method to be called when the scope ends. Only public methods that have no arguments can be annotated as lifecycle methods.

An example of a service implementation that uses scope and lifecycle annotations is:

Listing 2
package session.shop;

@Scope("stateless")
public class ShoppingCartServiceImpl implements ShoppingCartService {
    public void addToCart(int quantity) {
        //Code to populate shopping cart resources.
        ...
        return;
    }

    @Init
    public void beginCart() {
        //code to initialize shopping cart resources.
    }

    @Destroy
    public void endCart() {
        //code to free shopping cart resources.
    }

}

The SCA assembly model provides a way to specify attributes that you would typically find in Java annotations via a component type or composite file, without the need for an implementation language that supports annotation. The side file provides an alternative to annotations when the annotation style does not match the installation’s needs.

Configuration properties

Properties are used to tailor implementations by enabling SCA component definitions to specify values which condition the behavior of the implementation. The @Property annotation is used to annotate the Java class field that either holds an injected property, or designates a setter method that is used by the runtime to set an SCA property value.

The type of an injected property can be a simple Java type or a complex Java type. Either the Java class field or the type of the setter method input argument can determine the type of the injected property. A public setter method might be used to inject a property value even when the @Property annotation on the field is not there. In this case, the name of the field or setter method is used to determine the name of the property. Non-public fields must use an @Property annotation to be injected. The setter method is used when both setter method and a field for a property are present in the Java implementation.

The @Property annotation has the following attributes:

  • name (optional): the name of the property, defaults to the name of the field of the Java class.
  • required (optional): specifies whether injection is required, defaults to false.

Below are two examples of using an @Property annotation statement to define a property definition for a string. The first (Listing 3) is accomplished by annotating the field, using a property field definition, while the second (Listing 4) does it by annotating the setter method,using a property setter. Using a private field and annotating the setter method is considered a best practice.

Listing 3
@Property(name="currency", required=”true”)
	protected String currency;
Listing 4
@Property(name="currency", required=”true”)
public void setCurrency( String theCurrency ){
	currency =thecurrency;
}

Properties can be used to change the behavior of a component at run time without making code changes. Assume there is a BankUpdate component in a bank that uses SCA. Using the example above, the balance “currency” can be set to different values based on the bank’s policy.

Listing 5 shows an example from the BankUpdate component implementation that uses an @Property annotation to identify a property called maxCurrency. Suppose the property has a default value of $1,000.

Listing 5
private int  maxCurrency  = 1000;

// Property declaration using a setter method
@Property(name = "maxCurrency", override = "may")
public void setMaxCurrency(int maxCurrency) {
    this.maxCurrency = maxCurrency;
}

Listing 6 shows customization of the component by setting the maxCurrency property to 1500 in the composite SCDL file to override the default value (1000) defined in the component type.

Listing 6
<component name="BankUpdateComponent">
    <implementation.java class="balance.BankUpdateImpl" />
    <property name="maxCurrency">1500</property>
    ...
</component>

Accessing services

Java SCA implementations interact with services through service references. Service references are sometimes called proxies, the common industry term used in distributed programming.

An SCA component can obtain a service reference through injection, or programmatically through the component Context API. Using reference injection is the recommended way to obtain a service reference for SCA Java implementations, since it results in code with minimal use of middleware APIs. The ComponentContext API should be used in cases where reference injection is not possible, such as within an EJB or servlet. This API returns references to services that are exposed in the SCA domain.

Figure 4. Reference injection
Figure 4. Reference injection

The @Reference annotation is used to annotate a Java class field or a setter method that is used to inject a service reference, used to invoke the service. The interface of the service injected is defined by either the type of the Java class field or the type of the setter method input argument.

Listing 7
private HelloService helloService;
@Reference (name="helloService", required=true)
 public setHelloService(HelloService service){
 helloService = service;
}

public void clientMethod() {
String result = helloService.hello("Hello World!");
}

Like the Property annotation, The @Reference annotation has the following attributes:

  • name (optional): the name of the reference, defaults to the name of the field of the Java class.
  • required (optional): whether injection is required. Defaults to true.

CompositeContext API

The SCA V1.0 Java specification does not specify an API that enables a Java consumer to get a reference to a service unless it is statically wired to the service through the SCA assembly mechanisms. The Feature Pack for SCA provides a WebSphere Application Server extension that enables this capability called the CompositeContext API (Figure 5).

Figure 5. CompositeContext API
Figure 5. CompositeContext API

Java programs that use the CompositeContext API must be deployed in the same topology (either base server or Network Deployment cell) as the target service, and the service must be deployed in the SCA domain. In this initial release of the Feature Pack for SCA, the service is only available over the default binding.

Asynchronous programming

The Java programming model for SCA provides for non-blocking and callback asynchronous patterns, as shown in Figure 6. A non-blocking one-way invocation of a service enables the client to carry on executing without waiting for the service to run. The invoked service executes immediately or at some later time. A response from the service, if any, must be fed back to the client through a separate mechanism, since no response is available at invocation.

Figure 6. Asynchronous patterns
Figure 6. Asynchronous patterns

Asynchronous model

The @OneWay annotation indicates the non-blocking interaction style. One-way invocations represent the simplest form of asynchronous programming, where the client of the service invokes the service and continues processing immediately, without waiting for the service to execute.

Any method that returns "void" and has no declared exceptions can be marked with an @OneWay annotation.

SCA does not define a mechanism for making non-blocking calls to methods that return values or are declared to throw exceptions. Asynchronous responses might be modeled in a way so that both the consumer and provider create a pair of one-way requests such that a one-way request from the consumer to the provider is used to invoke the service, and a one-way request from the provider to the consumer provides the response.

Policy annotations

SCA provides facilities for the attachment of policy-related metadata to SCA assemblies. Implementation policy influences how implementations, services, and references behave at run time, and interaction policy influences how services should behave when invoked. The SCA Policy Framework includes two main concepts:

  • Intents express abstract, high-level policy requirements.
  • Policy sets express low-level detailed concrete policies.

SCA Java defines the @Requires annotation to enable the attachment of intents to a Java class or interface, or to elements within classes and interfaces, such as methods and fields.

Here is an example of the @Requires annotation that attaches two intents, confidentiality.message and integrity.message (from the Security domain):

@Requires({CONFIDENTIALITY, INTEGRITY})

Java for SCA also provides annotations that correspond to specific policy intents defined in the SCA Policy Framework. In general, the Java annotations have the same names as the intents defined by SCA. If the intent is a qualified intent, qualifiers are supplied as an attribute to the annotation in the form of a string or an array of strings.

For example, the SCA confidentiality intent can be specified as:

@Requires(CONFIDENTIALITY)
or
@Confidentiality

An example of a Java annotation for a specific qualified intent is:

@Authentication ( {“message”, “transport”} )

The abstract intents are then realized by SCA through the expression of concrete policy for the interaction policy on the bindings, or they cause the SCA container to condition the environment prior to the service getting control for the implementation policy. The abstract intents enable the generic expression of needed behavior to be mapped to specific bindings, but maintain the separation of concerns between what is important for the business logic provider, and the implementation detail of infrastructural decisions that affect the access paths to and from the service.

Example: Business logic bound to metadata

The following SCDL example shows how an SCA service can be exposed as both a Web service and an EJB service without changing the business logic.

Consider a HistoryService that stores an audit trail of payments made to an online payment system. The business logic, which might include a record being stored in a database table, is implemented using Java programming language and JDBC in a HistoryServiceImpl.class class, which is part of history.sca.jdbc package. This service performs the audit trail as part of a larger global transaction. The service can be made available over different bindings based on the need of the application. A scenario requiring the use of default binding, giving the most flexibility for the SCA runtime to choose a wiring mechanism, would specify the three scenarios (Figures 7 through 9) in the SCDL:

Figure 7. A service with SCA binding
Figure 7. A service with SCA binding
Figure 8. A scenario that requires the same service to be accessible like a Web service
Figure 8. A scenario that requires the same service to be accessible like a Web service
Figure 9. A scenario that requires interaction with EJB services and needs the capability of an EJB container
Figure 9. A scenario that requires interaction with EJB services and needs the capability of an EJB container

The implementation remains the same in all of the above cases. The choice of binding decides how this service is invoked by its client: as a Web service or as an EJB service. The service is developed using a technology familiar to the developer with a concentration on the business logic: in this case, how to create audit trails for payments. The wiring aspects are controlled by the assembler by choosing the binding appropriate for a deployment, hence freeing the developer from adding wiring-specific code, while providing flexibility to choose a binding that works best for each scenario.


Summary

The Java experience for SCA programmers should be one that leverages the ease-of-use characteristics of Java 5, which utilizes annotations and dependency injection, and demonstrates a real, tangible separation of concerns that frees business logic from configuration and protocol specific APIs that burden many applications today. When this Java experience is coupled with the visual composition metaphors that can be realized by tools to edit the SCA assembly, the focus of developing the application aligns directly with the principles of SOA -- loosely-coupled, reused, coarse-grained services composed from a broad-array of implementation and implementation technologies -- with the focus squarely on the business service itself, without the burden of any specific implementation.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=370399
ArticleTitle=Exploring the WebSphere Application Server Feature Pack for SCA, Part 4: SCA Java annotations and component implementation
publish-date=02182009