+

Search Tips   |   Advanced Search

Develop SCA service clients

We can develop a Service Component Architecture (SCA) service client starting with either a Java interface or a WSDL file for the SCA service to invoke.

We can develop SCA service clients that can both access and invoke an SCA service based on the Service Component Architecture specification. An SCA client can consume a diverse set of services such as enterprise beans, web services, and other SCA services, through the capabilities of the respective SCA bindings and using the Plain Old Java Object (POJO) client programming model.

To develop SCA service clients, we can start with either an existing WSDL file and use the wsimport tool to generate the Java interface or we can start with an existing Java interface.

Develop SCA client components starting with an existing WSDL file

When we have an existing WSDL file that describes the SCA service interface as a WSDL portType, along with XSD schema definitions of the business data, we can use the wsimport tool to generate the SCA Java representations of the business service interfaces and the business data. The wsimport tool generates Java classes that we can use to write a Java implementation that reflects the business logic. Use the generated output of the proxy class and the JAXB data binding types in the Java client to invoke the SCA service using the simple POJO programming model.

The generated annotated Java classes that correspond to your business data contain all the necessary information that the JAXB runtime environment requires to build and parse the XML for marshaling and unmarshaling. In other words, the data programming model is limited to object instantiation and the use of getter and setter methods, and we do not need to write code to convert the data between the XML wire format and the Java application.

Now that we have the generated annotated Java classes, use the Java interface and data type classes to create the reference proxy as described in the developing SCA clients starting with a Java interface section.

Develop SCA client components starting with a Java interface

When we have a Java interface to the SCA service, obtained either by starting from a WSDL and generating the Java classes or by starting with Java code, use the Java interface and data type classes to create the reference proxy. If the client is designed so that its reference proxy is injected from the SCA container, the Java interface is the same type as the proxy field and this file contains the corresponding @Reference annotation. We can only create the static reference from another SCA component implementation that acts as a client of the original service. If the reference proxy is created programmatically, create a proxy variable that has the same type as the Java interface, and use an API such as CompositeContext.getService(Class <B>interfaze, ) to create the reference proxy. The generated Java interface type is the interface parameter that is passed to this API. Read about locating and invoking SCA services to learn more about creating the reference proxy dynamically.

Regardless of whether the proxy is created by injection methods or programmatically, the Java interface is the class of the proxy and the generated JAXB types are the parameter types which includes inputs, outputs, and exceptions.

Considerations for local and remotable interfaces

It is important to understand that a remotable interface uses an XML wire format for data. Therefore, clients must use a JAXB-based programming model for the data types. In contrast, a local interface uses pass-by-reference semantics, so there is no data copy. Using the local interface, data is read and written without any special programming model such as JAXB.

Though WSDL-based interfaces are always remotable, we can also mark a Java interface that is not generated from a WSDL file as remotable by annotating it with the @Remotable annotation. The @Remotable annotation results in a data copy with XML serialization as defined by JAXB.

Define the remotable interface is straightforward when you start with a WSDL interface, because you use the wsimport tool to generate the JAXB data types that you use when you write the SCA client. The remotable interface is less apparent when starting from a remotable Java interface, unless the Java types are decorated with JAXB annotations. XML serialization behaves differently than Java serialization. For an POJO that is not annotated, Java serialization preserves instance data including private fields, whereas JAXB serialization preserves JavaBeans properties.

The focus of this topic is the use of remotable interfaces.

We can develop a component that consumes or acts as a client of the target service using a component reference. In addition to consuming a service from another component's reference, the product also provides a mechanism for consuming an SCA service over the default binding from a non-SCA component.

  1. Determine if you are developing the SCA service client starting with an existing WSDL file or with an existing Java interface.

  2. Develop the client Java interfaces and data types from a WSDL file if you are not starting with an existing Java interface. Use the wsimport command to generate the SCA service client Java interfaces.

  3. Create the reference proxy based on the Java interface.

    1. Create a reference proxy field or setter method that has the same type as the generated Java interface

    2. Annotate this field or setter with the @Reference annotation.

    Now we have completed the steps required to add the reference to the Java component implementation

  4. Create a component definition using the Java implementation.

    In the composite definition, add a <reference> element that refers back to the original interface and the field or setter of the SCA implementation. The reference is added as a child element of the component. The component is part of a composite definition.

    The <reference> name attribute must correspond to the field or setter containing the @Reference annotation. For a field containing the @Reference annotation, the name attribute must match exactly. For a setter containing the @Reference annotation, use the usual Java conventions for translating an annotated setter into a corresponding field, which in turn must match the name attribute.

    For the interface:

    • If the SCA client development started with an existing WSDL file, create an <interface.wsdl> element as a child element of the <reference> element that points to the WSDL portType.

    • If the SCA client development started from existing Java interface, create an <interface.java> element as a child element of the <reference> element that points to the original Java interface. This is optional, since the runtime environment can introspect the Java interface.

    In addition to these aspects of the component definition described by these development procedures, there are other aspects of defining a component. These aspects include adding bindings, configuring property values, defining intents, attaching policy sets, and resolving references. We can create multiple components using this same implementation, but all component definitions are the same with respect to the <implementation.wsdl> element and <reference> element described in this step.

  5. Deploy the SCA component by creating the SCA business level application from a deployable composite.

    In the previous step, you defined a component providing the SCA service within a composite definition. This composite is either a deployable composite, or one used recursively as a composite implementation of a component in a higher-level composite. To learn how to deploy the SCA service, read about deploying and administering business-level applications.


Results

You have created an SCA component that can consume an existing SCA service using a WSDL or Java interface.


Example

The following example illustrates using an existing WSDL interface to generate a Java interface used to create a Java implementation that is an SCA client. If we are starting with an existing Java interface, begin with step 4 to follow this example.

  1. Copy the following sample account.wsdl WSDL file to a temporary directory.
    <?xml version="1.0" encoding="UTF-8"?> 
    
    <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
         xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
         xmlns:account="http://www.myaccount.com/account"
         targetNamespace="http://www.myaccount.com/account"
         name="AccountService">
    
          <wsdl:types>
             <schema targetNamespace="http://www.myaccount.com/account"
                 xmlns="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:account="http://www.myaccount.com/account">
    
                   <element name="computeAccountAverage">
                     <complexType>
                         <sequence>
                             <element name="account" type="account:Account" />
                             <element name="days" type="xsd:int" />
                         </sequence>
                     </complexType>
                 </element>
                 <element name="computeAccountAverageResponse">
                     <complexType>
                         <sequence>
                             <element name="return" type="xsd:float" />
                         </sequence>
                     </complexType>
                 </element>
    
                 <complexType name="Account">
                     <attribute name="accountNumber" type="xsd:int" />
                     <attribute name="accountID" type="xsd:string" />
                     <attribute name="accountType" type="xsd:string" />
                     <attribute name="balance" type="xsd:float" />
                 </complexType>
    
              </schema>
         </wsdl:types>
    
         <wsdl:message name="computeAccountAverageRequest">
             <wsdl:part element="account:computeAccountAverage"
                 name="parameters" />
         </wsdl:message>
    
         <wsdl:message name="computeAccountAverageResponse">
             <wsdl:part element="account:computeAccountAverageResponse"
                 name="parameters" />
         </wsdl:message>
    
         <wsdl:portType name="AccountService">
             <wsdl:operation name="computeAccountAverage">
                 <wsdl:input message="account:computeAccountAverageRequest" name="accountReq"/>
                 <wsdl:output message="account:computeAccountAverageResponse" name="accountResp"/>
             </wsdl:operation>
         </wsdl:portType>
    
         <wsdl:binding name="AccountServiceSOAP" type="account:AccountService">
             <soap:binding style="document"
                 transport="http://schemas.xmlsoap.org/soap/http" />
             <wsdl:operation name="computeAccountAverage"> 
                <soap:operation
                     soapAction="computeAccountAverage" />
                 <wsdl:input name="accountReq"> 
                    <soap:body use="literal" />
                 </wsdl:input>
                 <wsdl:output name="accountResp">
                     <soap:body use="literal" />
                 </wsdl:output>
             </wsdl:operation>
    
          </wsdl:binding>
    
         <wsdl:service name="AccountWSDLService">
             <wsdl:port binding="account:AccountServiceSOAP"
                 name="AccountServicePort">
                 <soap:address location=""/>
             </wsdl:port>
         </wsdl:service>
    </wsdl:definitions>

  2. Run the wsimport command from the app_server_root/bin/ directory.

      app_server_root\bin\wsimport.bat -keep -verbose account.wsdl

    Run the wsimport command,

      app_server_root/bin/wsimport.sh -keep -verbose account.wsdl

    (iseries)

      app_server_root/bin/wsimport -keep -verbose account.wsdl

    After generating the template files using the wsimport command, the following Java files are generated:

    com/myaccount/account/Account.java
    com/myaccount/account/AccountService.java
    com/myaccount/account/AccountWSDLService.java
    com/myaccount/account/ComputeAccountAverage.java
    com/myaccount/account/ComputeAccountAverageResponse.java
    com/myaccount/account/ObjectFactory.java
    com/myaccount/account/package-info.java

  3. Identify the generated Java interface from the generated classes.
    //
    // Generated By:JAX-WS RI IBM 2.1.1 in JDK 6 (JAXB RI IBM JAXB 2.1.3 in JDK 1.6)
    //
    package com.myaccount.account;
    ...
    @WebService(name = "AccountService", targetNamespace = "http://www.myaccount.com/account")
    
    public interface AccountService {
        /**
         *
         * @param days
         * @param account
         * @return
         *     returns float
         */
        @WebMethod(action = "computeAccountAverage")
        @WebResult(targetNamespace = "")
        @RequestWrapper(localName = "computeAccountAverage", 
                        targetNamespace = "http://www.myaccount.com/account",
                        className = "com.myaccount.account.ComputeAccountAverage")
        @ResponseWrapper(localName = "computeAccountAverageResponse", 
                         targetNamespace = "http://www.myaccount.com/account", 
                         className = "com.myaccount.account.ComputeAccountAverageResponse")
        public float computeAccountAverage(
            @WebParam(name = "account", targetNamespace = "")
            Account account, @WebParam(name = "days", targetNamespace = "")
            int days);
    
    }

    This code example is a Java interface, not merely a Java class. The @WebService annotation is present in this Java interface. It is important to know that this example is not the same as the generated @WebServiceClient class, com.myaccount.account.AccountWSDLService. This class is not an interface and is actually not needed in our SCA application.

  4. Now that we have Java interface either by generating the Java interface from a WSDL file or we have an existing Java interface, you are ready to develop the SCA client from the Java interface.

  5. Place the @Reference annotation on a public or protected field or setter, with the same type as the Java interface.
    package com.myaccount.client;
    
    import bank.process.BankProcess;
    import org.osoa.sca.annotations.Reference;
    import org.osoa.sca.annotations.Service;
    
    import com.myaccount.account.*;
    
    @Service(BankProcess.class)
    public class AccountClientComponent implements BankProcess {
    
       // Note the type, AccountService', is the Java interface generated from    // from the WSDL portType
        private AccountService accountServiceRef;
    
        //
        // Injected by the SCA container     //
        @Reference
        public void setAccountServiceRef(AccountService accountServiceRef) {
            this.accountServiceRef = accountServiceRef;
        }
    
        public String someMethod(String input) {
    
            //... some business logic 
    
            //  We'll show a simple example of JAXB API usage         ObjectFactory factory = new ObjectFactory();
            Account account = factory.createAccount();
            account.setAccountNumber(4);
            account.setAccountID("CHECKING");
    
            int days = 5;
    
            float avg = accountServiceRef.computeAccountAverage(account, days);
    
            //... the rest of the business logic 
        }
    }

  6. Create a component using the component implementation. When using a WSDL portType interface, create component definitions in the composite definition that references the original portType along with the SCA Java implementation. In SCA, a component is a configured instance of a component implementation. There are other aspects of defining a component that are not shown here such as configuring bindings, configuring property values, defining intents, attaching policy sets, and resolving references. Shown here are the aspects of component creation that are common for all component definitions using the implementation developed in this example. This example also includes bindings we can modify or omit for other components using this component implementation.
    <?xml version="1.0" encoding="UTF-8"?>
    
    <composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
         targetNamespace="http://bank.process/customer"
             name="bpComposite">
    
          <component name="BankProcessComponent">
    
              <implementation.java class="com.myaccount.client.AccountClientComponent"/>
             <!-- The @name attribute corresponds to the setter that is annotated with the @Reference annotation. -->
    
             <reference name="accountServiceRef">
                  <!-- This statement specifies the QName of the WSDL portType, "http://www.myaccount.com/account#AccountService" in the syntax as                   illustrated in the interface.wsdl statement.  -->
    
                 <interface.wsdl interface="http://www.myaccount.com/account#wsdl.interface(AccountService)" />
                 <binding.ws uri="http://localhost:9080/BankingComponent/AccountService"/>
    
      <!-- This example uses the SCA web services binding.  However, it does not matter which specific binding  you choose.  We can also choose to use the SCA default binding or the SCA EJB binding.  -->
    
              </reference>
         </component> 
    </composite>

  7. Configure the composite definition when starting with a Java interface.

    The following snippet is another example of the syntax if you develop an SCA client starting with a Java interface rather than with a WSDL portType. To simplify this example, use the same AccountService Java interface from the previous step but in this case, assume that it was not generated from a WSDL file.

    <?xml version="1.0" encoding="UTF-8"?>
    
    <composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
         targetNamespace="http://bank.process/customer"
             name="bpComposite">
    
          <component name="BankProcessComponent"> 
    
             <implementation.java class="com.myaccount.client.AccountClientComponent"/>
    
             <!-- The @name value corresponds to the setter that is annotated with the @Reference annotation. -->
                    <reference name="accountServiceRef">
    
                  <!-- Because the runtime can introspect the interface, it is unnecessary to specify                    the interface.java in the composite definition. This is what the interface looks like if you include it. 
    
                              <interface.java interface=com.myaccount.account.AccountService/> -->
    
                   <!-- The SCA binding type is omitted. It does not matter which specific SCA binding you choose. --> 
             </reference>
         </component> 
    </composite>

  8. After a component is defined as part of a deployable composite, either directly or recursively through use of one or more layers of components with composite implementation, you are now ready to deploy the SCA component by creating a SCA business level application.


Related concepts

  • SCA in WebSphere Application Server: Overview
  • SCA components
  • SCA composites
  • SCA domain


    Related tasks

  • Deploy and administering business-level applications
  • Develop SCA services from existing WSDL files
  • Develop SCA services with existing Java code
  • wsimport command for JAX-WS applications
  • Specify bindings in an SCA environment
  • Use the SCA default binding to find and locate SCA services
  • Manage policy sets using the administrative console

  • Considerations for developing SCA applications using EJB bindings
  • Service Component Architecture specifications and APIs