The SCA Java implementation model provides a framework to implement SCA components in Java. A component implementation can either provide a service or can also act as a client to other services. It explains how a SCA Java component implementation and non-SCA Java component implementation can get access to services and call service methods. In this article, all meta-data is defined using the annotation capability from Java 2 Standard Edition (J2SE) 5. However, SCA service clients and component implementations also use J2SE 1.4.
Basic component implementation model
This model describes the implementation of a local or remote service and implementation-specific configuration properties.
The services are represented using interfaces, which are defined using one of the following:
- A Java interface (which is SCA's preferred style)
- A Java class
- A Java interface generated from a Web Services Description Language (WSDL) port type
A Java class component implementation implements all the operations defined by the service interface, it uses @Service annotation to specify the interface of the services implemented by using Java implementation. A class that is intended to be used as the implementation of a service is not required to have an @Service annotation. The @Service annotation has two attributes:
- Interfaces -- The value is an array of interface or class objects that should be exposed as services by this component
- Value -- A shortcut for when only a single service interface is provided. An @Service with no attributes is meaningless.
The following snippets show the Java service interface named PayrollDataService and the Java implementation class of a Java interface named PayrollDataServiceImpl.
Listing 1. Java service interface
package services.payrolldata;
public interface PayrollDataService {
float getBasic(String employeeID);
float getvariablePay(String employeeID);
float getHRA(String employeeID);
float getProfessionalTax(String employeeID);
float getNetPay(String employeeID);
} |
Listing 2. Java service component implementation
package services.payrolldata;
Import org.osoa.sca.annotations.*;
@Service(PayrollDataService.class)
public class PayrollDataServiceImp implements PayrollDataService {
public float getBasic(String employeeID){ . . . }
public float getVariablePay(String employeeID){ . . . }
public float getHRA(String employeeID){ . . . }
float getProfessionalTax(String employeeID){ . . . }
public float getNetPay(String employeeID){ . . . }
}
|
If in a Java implementation class, the service interface is defined by the class itself then @Service annotation in the above code is replaced by @Service(PayrollDataServiceImp.class). The following explains the component type for this component implementation, as seen in Listing 3.
Listing 3. Component type
<!--<?xml version="1.0" encoding="ASCII"?> <componentType xmlns=http://www.osoa.org/xmlns/sca/0.9> <service name="PayrollDataService"> <interface.java interface="services.payrolldata. PayrollDataService"/> </service> </componentType> --> |
A sub classing of the interface is used to provide two services with the same interface. @Service annotation lists both the interfaces.
Implementing a remotable service
A Remotable Service is made available to access to external components by publishing it through entry points. To define a remotable service, @Remotable annotation is added in the Java interface of the service. A service whose interface is defined by a Java class is not Remotable. Java interfaces generated from WSDL port Types are remotable.
The following explains the Java interface for a remotable service with its @Remotable annotation:
Listing 4. Java interface for a remotable service with its @Remotable annotation
package services.payroll;
import org.osoa.sca.annotations.Remotable;
@Remotable
public interface PayrollService{
public PayrollStatement getPayrollStatement(String employeeID);
} |
The next snippet shows the PayrollStatement Java interface.
Listing 5. PayrollStatement Java interface
package services.payroll;
import java.util.List;
public interface PayrollStatement {
List getPayrollDetails();
float getNetPay();
} |
Remotable service interfaces make
use of marshalling technology to exchange complex data types. Service Data
Objects or JAXB data types can be passed as parameters when web service binding
is used. Remotable services use by-value data exchange semantics.
The @AllowPassByReference 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.
The following snippet shows Java component implementation that implements a remote service and allows pass by reference:
Listing 6. Java component implementation with a remote service and pass by reference
package services.payrolldata;
Import org.osoa.sca.annotations.*;
@Service(PayrollDataService.class)
@AllowsPassByReference
public class PayrollDataServiceImp implements PayrollDataService {
. . . .
} |
Implementing a local service
A local service can only be called by clients that are part of the same module. A Java local service interface is defined without a @Remotable annotation.
The following snippet shows the Java interface for a local service.
Listing 7. Java interface for a local service
package services.payrolldata;
public interface PayrollDataService {
float getBasic(String employeeID);
float getvariablePay(String employeeID);
float getHRA(String employeeID);
float getProfessionalTax(String employeeID);
float getNetPay(String employeeID);
} |
The data exchange semantics for calls to local services is by-reference, here changes made to parameters are seen by either the client or the service provider.
Implementing the stateful resource pattern
A scoped service is represented using an @Scope annotation on either the service's interface definition or on the service class. The @Scope annotation has one parameter namely value, whose value is the name of the scope.
Following are the currently supported scope values:
- Stateless(default) --Each request is handled separately. Java instances may be drawn from a pool of service instances
- request -- Service requests are delegated to the same Java interface for all local Service invocations that occur while servicing a remote service request
- Session -- Service requests are delegated to the same Java instance for all requests in the same "session"
- module -- Service requests are delegated to the same Java instance for all requests within the same "module"
Except for module scoped implementation, for the rest three the SCA runtime will prevent concurrent execution of methods on an instance of that implementation.
The following snippet shows the interface of a session-scoped service.
Listing 8. Interface of a session-scoped service
package services.profile;
import org.osoa.sca.annotations.Scope;
@Scope("session")
public interface ProfileService{
public String getFirstName();
public void setFirstName(String pName);
public String getLastName();
public void setLastName(String pName);
public boolean isLoggedIn();
public void setLoggedIn(boolean pStatus);
public String getId();
public void setId(String pId);
} |
A scoped service can implement lifecycle methods on its Java implementation using @Init annotation and @Destroy annotation. @Init -- method gets called only once at the start of its scope and after its properties and references have been injected. @Destroy -- method gets called when its scope ends.
Listing 9 shows a Java implementation class of a service with lifecycle methods.
Listing 9. Java implementation class of a service with lifecycle methods
package services.profile;
import org.osoa.sca.annotations.*;
@Service(ProfileService.class)
public class ProfileServiceImpl implements ProfileService {
public String getFirstName( ) { ....}
@Init
public void start() { . . . }
@Destroy
public void stop() { . . . }
} |
Implementing a configuration property
The @Property annotation on a field or method in the Java class is used to define configuration properties of a Java component implementation. Following are the attributes of @Property annotation:
- name -- the name of the property, default value is name of the field of the Java class
- require -- specifies whether injection is required, default value is false
Listing 10 shows the definition of a configuration property using the @Property annotation.
Listing 10. Definition of a configuration property using the @Property annotation
package services.payroll;
import org.osoa.sca.annotations.Property;
import org.osoa.sca.annotations.Reference;
import services.payrolldata.PayrollDataService;
public class PayrollServiceImpl implements PayrollService {
@Property
private String currency = "INR";
@Reference
private PayrollDataService payrollDataService;
public PayrollStatement getPayrollStatement (String employeeID) { . . . . }
} |
A client can get access to services from both SCA components and from non-SCA components.
Accessing services from SCA component implementations
The different ways to get access to a service are as follows:
Using Reference InjectionAcquiring access to a service using reference injection is specified by defining a Java class data member of type interface of the service and annotated by the @Reference annotation. The attributes of a @Reference annotation are:
- name -- the name of the reference
- required -- whether injection of a service or services is required
Listing 11 shows a Java implementation using the @Reference annotation.
Listing 11. Java implementation using the @Reference annotation
package services.profile;
import org.osoa.sca.annotations.Service;
import org.osoa.sca.annotations.Reference;
@Service(LoginService.class)
public class LoginServiceImpl implements LoginService{
@Reference(name="profileService", required=true)
private ProfileService profileService;
public int login(String employeeID, String password) { .... }
} |
Below is the corresponding component type for the above component implementation.
Listing 12. Component type
<?xml version="1.0" encoding="ASCII"?>
<componentType xmlns="http://www.osoa.org/xmlns/sca/0.9">
<service name="ProfileService ">
<interface.java interface="services.profile.LoginService"/>
</service>
<reference name="profileService">
<interface.java interface="services.profile.ProfileService"/>
</reference>
</componentType>
|
Using Module Context
The necessary things to access a service using module context are:
- a field has to be defined to accept an injected module context
- a method has to be called on the injected module context
Access to a service using module Context is specified by defining a field with a type of ModuleContext and with the @Context annotation. Listing 13 shows the ModuleContext interface with its locateService() method.
Listing 13. ModuleContext interface
package org.osoa.sca;
public interface ModuleContext {
...
Object locateService(String serviceName);
} |
Listing 14 shows a sample of a module context definition using the @Context annotation:
Listing 14. Module context definition using the @Context annotation
package innovasolutions.web.ui;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.osoa.sca.CurrentModuleContext;
import org.osoa.sca.ModuleContext;
import services.profile.LoginService;
public class LoginServlet extends HttpServlet{
private ServletContext mContext;
public void init(ServletConfig pCfg) throws ServletException{
mContext = pCfg.getServletContext();
}
public void doPost(HttpServletRequest pReq,
HttpServletResponse pResp) throws ServletException{
LoginService loginMgr = (LoginService)CurrentModuleContext.getContext().
locateService("LoginServiceComponent");
if (loginMgr == null){
throw new ServletException("LoginManager not found");
}
. . . .
} |
Accessing services from non-SCA component implementations
Non-SCA components, which are part of the SCA module, get access to services using Module Context. They use ModuleContext in their implementations to find services. They get access to current ModuleContext through the CurrentModuleContext class, which is shown in Listing 15.
Listing 15. CurrentModuleContext class
package org.osoa.sca;
public final class CurrentModuleContext {
public static ModuleContext getContext() {... }
} |
The non-SCA component implementation would include a line like the following to get access to the module context: ModuleContext moduleContext = CurrentModuleContext.getContext();
While calling service methods clients encounter following exceptions:
- Business exceptions -- raised by the implementation of the called service method
- SCA runtime exception -- thrown by the SCA runtime and signals problems in the management of the execution of components, and in the interaction with remote services. Currently supported SCA Runtime exceptions are Service Runtime Exception and Service Unavailable Exception
In Asynchronous programming of a service, a client invokes a service and carries on its execution without waiting for the service to execute.
The SCA asynchronous programming model supports three types of asynchronous calls.They are:
- Non-blocking method calls
- Conversation services
- Callbacks
Non-blocking calls
Using non-blocking calls the client invokes the service and continues processing immediately, without waiting for the service to execute. A non-blocking method is marked with the @Oneway annotation. Currently SCA supports non-blocking calls to methods that return "void" and have no declared exceptions.
Conversational Services
A conversation between a client of the service and provider of the service often happens during the execution of remotable services. Traditional programming model requires writing a significant amount of code in order to support this pattern. SCA simplifies the design of conversational services while leaving the details of ID generation, state management and routing to the SCA container.
In SCA, a session is used to maintain information about a single conversation between a client and a remotable service. SCA uses @Scope, @Session and @SessionID annotations to implement conversational services.
Callback
Callback service provides asynchronous communication from a service provider back to its client. Callbacks used by bidirectional services are services that have two interfaces, one by the service provider and the other by the client.
SCA provides callback services by using @Callback annotation on a remotable service interface, which takes the Java Class object of the interface as a parameter.
Listing 16 shows use of the @Callback annotation.
Listing 16. @Callback annotation
package somepackage;
import org.osoa.sca.annotations.Callback;
import org.osoa.sca.annotations.Remotable;
@Remotable
@Callback(MyServiceCallback.class)
public interface MyService {
public void someMethod(String arg);
}
@Remotable
public interface MyServiceCallback {
public void receiveResult(String result);
} |
Open Source runtimes and tools
There is an open source project which provides a runtime implementation of Service Component Architecture, which you can use to run SCA applications. This project is called Tuscany, currently under incubation at Apache. The major contributors to this project are IBM, BEA, Oracle, Sybase, SAP, IONA, and Siebel.
This article describes the representation and implementation of services using Java interfaces and Java class Component implementations respectively. It explains the configuration properties of a service implementation using Java annotations. You've seen various ways to access services from both SCA and non-SCA Java components -- and the various error handling mechanismsm asynchronous programming model and various asynchronous calls.
This article is a prerequisite for readers and developers who want to develop applications using SCA implementation in Java.
-
Read about the SCA 0.95 Client and Implementation Specification for Java™ (PDF).
- The SCA 0.9 Assembly Model Specification (PDF) is a good starting point for background information.
-
"Java SCA Invocation Style" (developerWorks, June 2006) offers an overview of Java usage within the SCA Plain Old Java Object (POJO) component and the data flow in and out of POJO components.
Comments (Undergoing maintenance)





