Table of Contents
In this chapter, we will illustrate the creation of your first SCA application with a very simple example 'HelloWorld'.This (too) simple example allows us to explain easily most of SCA concepts with a minimum of code (no useless code).
The 'HelloWorld' example defines a client component that can call a print service with a message ("Hello World!") as parameter on the server component. The composite includes client and server components and provides a service used to run the example.
The UML component diagram of this example looks like this:
Our basic application will be defined as a composite
helloworld
. This composite contains two
components:
the Client
component
is a simple client that will call the print service provided by the server,
provides a service 'r' (implements the java.lang.Runnable
interface) promoted to the helloworld
composite and used to run the example,
requires a service defined by the
PrintService
interface.
the Server
component
is a simple server,
provides a service named printService
implementing the PrintService
interface.
This section will show you how to write the HelloWorld SCA application with standard Java code (POJOs).
Example source code can be found in the
examples/helloworld-pojo
folder of the distribution
or in the trunk/examples/helloworld-pojo
of the
OW2 FraSCAti SVN repository.
You can implement SCA components and services with simple POJOs. This is possible by the following SCA coding convention:
Java classes implementing SCA components must have a default constructor without parameters
SCA Properties and References can be defined either by
public or protected setter methods
public or protected fields unless there is a public or protected setter method for the same name.
Services can be defined as a standard Java interface implementation.
For more details, see the SCA Java Component Implementation V1.0 specification (page 8).
The first step is to define your component contract, i.e. component service interface(s).
Our Hello World service will provide a single interface with one method "print" that will be used to print the message given as parameter.
The Hello World Service implementation:
package org.ow2.frascati.examples.helloworld.pojo; /** A basic service used to print messages. */ public interface PrintService { void print(String msg); }
No SCA specific code is needed.
The Server implementation is also a standard POJO. You just have to implement the previously defined service interface.
package org.ow2.frascati.examples.helloworld.pojo; /** The print service implementation. */ public class Server implements PrintService { private String header = "->"; private int count = 1; /** Default constructor. */ public Server() { System.out.println("SERVER created."); } /** PrintService implementation. */ public void print(final String msg) { System.out.println("SERVER: begin printing..."); for (int i = 0; i < count; ++i) { System.out.println(header + msg); } System.out.println("SERVER: print done."); } /** Set the Header property. */ public void setHeader(final String header) { System.out.println("SERVER: setting header to '" + header + "'."); this.header = header; } /** Set the count property. */ public void setCount(final int count) { System.out.println("SERVER: setting count to '" + count + "'."); this.count = count; } }
The Client implementation is quite easy. It implements the
java.lang.Runnable
interface as this interface
will be exposed as a service (used to run the example) and provides a
private field and a setter for the required service:
org.ow2.frascati.examples.helloworld.pojo.PrintService
.
package org.ow2.frascati.examples.helloworld.pojo; /** A print service client. */ public class Client implements Runnable { private PrintService s; /** Default constructor. */ public Client() { System.out.println("CLIENT created."); } /** Run the client. */ public void run() { s.print("Hello World!"); } /** Set the reference of the service. */ public void setPrintService(PrintService service) { this.s = service; } }
An SCA composite assembles SCA components to form SCA
applications. An SCA composite is defined in an
xxx.composite
file.
We will define a helloworld composite that will contain 2 components: our Client and Server components. The composite will promote the Runnable interface defined on the client component. This service will be used to start this example, i.e., call the print service on the server.
A composite definition can be basically written with the help of an XML editor but there is a nice alternative integrated in the Eclipse IDE: the Eclipse STP SCA project. This project aims to provide tools for SCA such as a SCA Metamodel, a composite designer, an XML editor, samples and is compatible with OW2 FraSCAti. The following picture is a screenshot of the SCA composite designer for our example:
Here is the related
helloworld-pojo.composite
definition:
1 <?xml version="1.0" encoding="ISO-8859-15"?> 2 <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" 3 name="helloworld-pojo"> 4 5 <service name="r" promote="client/r"/> 6 7 <component name="client"> 8 <implementation.java class="org.ow2.frascati.examples.helloworld.pojo.Client"/> 9 10 <service name="r"> 11 <interface.java interface="java.lang.Runnable"/> 12 </service> 13 14 <reference name="printService" target="server/printService"> 15 <interface.java interface="org.ow2.frascati.examples.helloworld.pojo.PrintService"/> 16 </reference> 17 </component> 18 19 <component name="server"> 20 <implementation.java class="org.ow2.frascati.examples.helloworld.pojo.Server"/> 21 22 <service name="printService"> 23 <interface.java interface="org.ow2.frascati.examples.helloworld.pojo.PrintService"/> 24 </service> 25 26 <property name="header">--->> </property> 27 </component> 28 29 </composite>
The core XML element of a composite definition is of course, the
composite element (line 2). The name
attribute is the composite name and is mandatory. Inside a
composite tag, you can define services (line 5),
references, properties, and components (lines 7 and 19).
A service element defines a service by giving the
service name
(mandatory) and if the service
promotes another defined service with the promote
attribute. As an example, a service r
is defined
(line 5) as a promotion of the service r
defined in
the client
component (line 10). In this case, no
more information is needed.
The syntax used to reference elements: the '/' character is used to jump into a component and name one of its services or references.
A complete service definition (line 10) needs to specify at
least the full Java name of the implemented interface. We can see that
the r
service defined in the
client
component implements the
java.lang.Runnable
Java interface (line
11).
A component element (lines 7 and 19) can contain
the same definitions as a composite element except
components definitions.The name
attribute is the
component name and is mandatory. We have to specify the implementation
class of the component. For instance, the client
component is implemented by the
org.ow2.frascati.examples.helloworld.pojo.Client
Java class (line 8).
A reference element is used to define an SCA
reference (a service required by a component). Its definition (line
14) is quite the same as a service definition. You have
to specify the reference name
, the
target
ed service definition (both mandatory). The
full Java name of the reference interface is also mandatory. The
printService
reference (line 14) defines a
reference using a service implementing the
org.ow2.frascati.examples.helloworld.pojo.PrintService
Java interface. The reference will be wired to the
printService
of the server
component as defined in the target
attribute during
the instanciation process.
Finally, an SCA property can be defined by a
property element (surprising, isn't it?) by specifying
its name (mandatory). The default value of the property is set inside
the property tag as shown by the example line 26. In the example, we
defined a property named header
with the
'-->> ' default value.
You can simply compile your business code either by using your favorite IDE (Eclipse, NetBeans, etc.) or by using your favorite build tool (ant, make). This operation will result in the production of an archive (jar file) with your business classes.
You can also use a script provided by OW2 FraSCAti by specifying the source folder and the name of the jar file that will be produced.
This script is just a wrapper to the Java command available in your environment.
$ frascati compile examples/helloworld-pojo/ helloworld-pojo
Once compiled, you can run the OW2 FraSCAti runtime in order to
parse your SCA composite definition file,
instanciate your SCA components, and
start your SCA application.
The following command shows you how to start your application by
calling the method run
of the r
service on
the helloworld-pojo
composite.
$ frascati run helloworld-pojo -libpath examples/helloworld-pojo/target/helloworld-pojo.jar --service-name r --method-name run
Using SCA is very easy since business code can be fully implemented with standard Java objects (POJOs) with no SCA specific code. You just have to have in mind that your business application should be a set of components and wires between components.
The only SCA specific need is to describe your SCA application architecture in a composite definition. Hopefully, the SCA graphical modeler (integrated into the Eclipse IDE) is available to hide the XML syntax.