Consortium    Solutions    Middleware    Forge    MyObjectWeb 
ObjectWeb Consortium
Print

Advanced - Powered by Google






Fractal

Project Links
· Home
· Documentation
· Download
· License
· What's New
· Wiki

Developers' Corner
· Workplan
· SVN Repository
· ObjectWeb Forge Site

About
· Team
· Users
· Partners
· Mailing List Archive

About this document

  • Title: User Guide
  • Author: Romain Rouvoy (Universitetet i Oslo)
  • Version: 3.0.1 (fraclet-java)
  • Released: February 23th, 2008

Table of Contents

  1. Overview of Spoon
  2. Annotation Description
  3. Spoon/Maven2 Configuration
  4. Revisiting the HelloWorld Example

About Spoon

Spoon is a Java 5 open compiler built on javac. It uses compile-time reflection to specify program analysis and transformations. Spoon provides the user with a representation of the Java AST called a meta-model, which allows both for reading and writing. Each interface of the meta-model is a compile-time program element (CtElement), which represents an AST node. Using this meta-model and a specific API, Spoon allows the programmer to process Java 5 programs. This processing is implemented with a visitor pattern that scans each visited program element and can apply some user-defined processing jobs called processors. In particular, the processing can be annotation-driven, in a similar way to XDoclet, but using Java 5 annotations. In that case, programmers define so-called annotation processors. Once the program's model has been processed, a processor pretty prints the Java program, which is usually compiled again to generate the processed program's class files.

In addition, Spoon provides templates in pure Java, which are Java class that contains template parameters, which are defined as fields annotated with @Parameter. Template parameters can represent primitive values (such as literal values, program element's names, types), or actual CtElements (ASTs). In the template code, all the references to template parameters can be substituted by their actual values using the substitution engine API provided by Spoon. The templates are useful to express patterns that can be used for generating code, as exampled by Generative Programming.

To implement Fraclet with have developed a set of Spoon processors and templates to process our annotations. This tutorial does not detail the implementation of the processors and templates but focus on the use of Fraclet annotations.

Available Annotations

A small set of annotations have been defined for easy programming of Fractal components. The table below summarises these annotations.

AnnotationLocationDescription
@ComponentClassAnnotation to describe a component.
@InterfaceInterfaceAnnotation to describe a server interface.
@RequiresFieldAnnotation to describe a client interface.
@AttributeFieldAnnotation to describe an component attribute.
@LifecycleMethodAnnotation to handle a step of the component life cycle.
@ControllerFieldAnnotation to access the controller part of the component.

In addition to this small annotations set, additional annotations are also available for handling advanced concepts of Fractal.

AnnotationLocationDescription
@DataClassAnnotation to describe a data exchanged between components.
@LegacyClassAnnotation to include a legacy Fractal ADL definition.
@MembraneClassAnnotation to describe the controller part of the component.
@NodeClassAnnotation to define the node hosting the component.

Core Annotations

@Component

Details:
This class annotation describes a component and is used to generate the associated Fractal ADL definition. This annotation is mandatory for any definition of a component (abstract or concrete).

Parameters:

ParameterTypeDescriptionContingency
nameStringname of the associated Fractal description.Optional
provides@Interface[]explicit list of server interfaces.Optional

PS. The attribute provides is used when the server interfaces implemented by the component are not using the @Interface annotation (e.g., the interface java.lang.Runnable).

Examples:

@Component
public class MyComponent implements Runnable { 
    (...)
}

Generate the following Fractal ADL definition:
  <definition name="MyComponent">
    (...)               
    <content class="MyComponent"/>  
  </definition>
@Component(name="MyComponentDefinition")
public class MyComponent implements Runnable {
    (...)
}

Generate the following Fractal ADL definition:
  <definition name="MyComponentDefinition">
    (...)               
    <content class="MyComponent"/>  
  </definition>
@Component(name="MyComponentDefinition", provides=@Interface(name="r", signature=Runnable.class))
public class MyComponent implements Runnable {
    (...)
}

Generate the following Fractal ADL definition:
  <definition name="MyComponentDefinition">
    <interface name="r" role="server" cardinality="singleton" contingency="mandatory" signature="java.lang.Runnable"/>  
    (...)                
    <content class="MyComponent"/>    
  </definition>

@Interface

Details:
This interface annotation is used to describe a server interface provided by a component. Once tagged with this annotation, the interface will automatically be recognized as a server interface for the components implementing this interface. Furthermore, a Fractal ADL (abstract) definition will be generated for this interface.

Parameters:

ParameterTypeDescriptionContingency
nameStringname of the server interface.Optional
(default value is the Class name)
signatureClass<?>signature of the server interface.Optional
(default value is the Class signature)

Examples:

@Interface
public interface Service { 
    (...)
}

Generate the following Fractal ADL abstract definition:
  <definition name="Service">
    <interface name="service" signature="Service" role="server" cardinality="singleton" contingency="mandatory"/>
  </definition>
@Interface(name="s")
public interface Service { 
    (...)
}

Generate the following Fractal ADL abstract definition:
  <definition name="Service">
    <interface name="s" signature="Service" role="server" cardinality="singleton" contingency="mandatory"/>
  </definition>
@Interface(name="s")
public interface Service {
    (...)
}
@Component
public class Server implements Service {
    (...)
}                        

Generate the following Fractal ADL definitions:
  <definition name="Service">
    <interface name="service" signature="Service" role="server" cardinality="singleton" contingency="mandatory"/>
  </definition>            

  <definition name="Server" extends="Service">
    (...)
    <content class="Server"/>
  </definition>

@Attribute

Details:
This field annotation describes an attribute supported by a component. Fields marked with this annotation will automatically be handled by the attribute controller of the component.

Parameters:

ParameterTypeDescriptionContingency
nameStringname of the argument used to configure the attribute.Optional
(default value is the field name)
valueStringdefault value of the attribute.Optional
(attribute is defined as mandatory if no value is defined)

Example:

@Component
public class Server implements Service {
    @Attribute(value=">>")
    private String header ;
    @Attribute(name="msg")
    private String message ;
    (...)
}        

Generates the following Fractal ADL definitions:
  <definition name="Server" arguments="msg,header=>>">
    <interface name="service" signature="Service" role="server" cardinality="singleton" contingency="mandatory"/>
    <content class="Server"/>
    <attributes signature="ServerAttributes">
      <attribute name="message" value="${msg}"/>
      <attribute name="header" value="${header}"/>
    </attributes>
  </definition>

@Requires

Details:
This field annotation describes a client interface.

Parameters:

ParameterTypeDescriptionContingency
nameStringname of the client interface.Optional
cardinalityCardinalitycardinality of the client interface.
(values are Cardinality.SINGLETON | Cardinality.COLLECTION)
Optional
(default value is Cardinality.SINGLETON)
contingencyContingencycontingency of the client interface.
(values are Contingency.MANDATORY | Contingency.OPTIONAL)
Optional
(default value is Contingency.MANDATORY)

Example:

@Component
public class Client implements Runnable {
    @Requires(name = "default")
    private Service defaut;
    @Requires(cardinality = Cardinality.COLLECTION)
    private Map<String,Service> service = new HashMap<String,Service>();

}

Generates the following Fractal ADL definitions:
  <definition name="Client">
    <interface name="default" signature="Service" role="client" cardinality="singleton" contingency="mandatory"/>
    <interface name="service" signature="Service" role="client" cardinality="collection" contingency="mandatory"/>
    <content class="Client"/>
  </definition>

@Lifecycle

Details:
This method annotation provides a way to define a lifecycle handler supported by the controller part of the associated Fractal component.

Parameters:

ParameterTypeDescriptionContingency
valueSteplife cyle transition to handle.
(values are Step.CREATE | Step.START | Step.STOP | Step.DESTROY).
Required

Example:

@Component
public class Client implements Runnable {
    @LifeCycle(Step.START)
    private void init() {
        System.out.println("Starting the component Client...");
    }
    (...)
}

@Controller

Details:

This class annotation provides access to the controllers supported by the component.

Parameters:

ParameterTypeDescriptionContingency
valueStringThe name of the controller.
(possible values are name-controller | super-controller | binding-controller | attribute-controller | lifecycle-controller | component | any other controller)
Optional (default value is component)

Examples:

@Component
public class Client implements Runnable {
    @Controller
    private org.objectweb.fractal.api.Component comp; 
    (...)
}
@Component
public class Client implements Runnable {
    @Controller("name-controller")
    private NameController nc; 
    (...)
}

Additional Annotations

@Data

Details:
This class annotation describes data exchanged between components (via their client/server interfaces).

Example:

@Data
public class Message { 
    (...)
}

@Legacy

Details:
This class annotation describes a set of legacy definitions that need to be extended by the component definition.

Parameters:

ParameterTypeDescriptionContingency
valueString[]List of definitions to integrate.Mandatory

Example:

@Component
@Legacy("MyDefinition")
public class Client implements Runnable {
    (...)
}

Generates the following Fractal ADL definition:
  <definition name="Client" extends="MyDefinition">
    (...)
  </definition>

@Membrane

Details:
This class annotation describes the controller part of the component.

Parameters:

ParameterTypeDescriptionContingency
controllerStringIdentifier of the component controller.Mandatory
templateStringIdentifier of the template controller.Mandatory

Example:

@Component
@Membrane(controller="myPrimitive")
public class Client implements Runnable {
    (...)
}

Generates the following Fractal ADL definition:
  <definition name="Client">
    (...)
    <controller desc="MyPrimitive"/>
  </definition>
@Component
@Membrane(template="myTemplate")
public class Client implements Runnable {
    (...)
}

Generates the following Fractal ADL definition:
  <definition name="Client">
    (...)
    <template-controller desc="MyTemplate"/>
  </definition>

@Node

Details:
This class annotation describes the name of the node hosting the component instance for a distributed deployment (using Fractal RMI).

Parameters:

ParameterTypeDescriptionContingency
valueStringName of the hosting node.Mandatory

Example:

@Component
@Node("clientNode")
public class Client implements Runnable {
    (...)
}

Generates the following Fractal ADL definition:
  <definition name="Client" extends="MyDefinition">
    (...)
    <virtual-node name="clientNode">
  </definition>

Configuration

Spoon Configuration

You should first describe the list of spoonlets that need to be applied to your source code. Fraclet basically provides two spoonlets for introducing the Fractal API callbacks and generating the Fractal ADL definitions, respectively. To do so, you should create a file named spoon.cfg.xml at the root of your project containing the following definition:

<?xml version="1.0" encoding="UTF-8"?>
<spoon>
  <spoonlet groupId="org.objectweb.fractal.fraclet.java" artifactId="fractal-spoonlet" version="3.0.1" />
  <spoonlet groupId="org.objectweb.fractal.fraclet.java" artifactId="fractaladl-spoonlet" version="3.0.1" />
</spoon>

Maven2 Configuration

Then, you should describe the list of spoonlets as Maven2 artefact dependencies.

<project>
  (...)
  <dependencies>
    (...)
    <dependency>
      <groupId>org.objectweb.fractal.fraclet.java</groupId>
      <artifactId>fractal-spoonlet</artifactId>
      <version>3.0.1</version>
    </dependency>
    <dependency>
      <groupId>org.objectweb.fractal.fraclet.java</groupId>
      <artifactId>fractaladl-spoonlet</artifactId>
      <version>3.0.1</version>
    </dependency>
  </dependencies>
  (...)
<project>

Finally, you should extend the Maven2 build process by using the Spoon Maven2 plugin.

<project>
  (...)
  <build>
    <plugins>
      <plugin>
        <groupId>net.sf.alchim</groupId>
        <artifactId>spoon-maven-plugin</artifactId>
        <version>0.7</version>
        <executions>
          <execution>
            <goals>
              <goal>recompile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  (...)
<project>

Revisiting HelloWorld

This section provides a quick overview of the benefits of Fraclet. In particular, it illustrates that, using annotations, component source code becomes more concise and easier to maintain. Moreover, using Fraclet, more than 60% of the source code (Java, FractalADL) can be saved.

HelloWorld Architecture Overview

The figure below introduces the well-known HelloWorld example implemented with Fractal components.

HelloWorld Components Implementation

The source code below represents the Java code and the Fraclet annotations written to implement the Client and the Server Fractal components:

@Component(provides=@Interface(name="r",signature=Runnable.class))
public class Client implements Runnable {
  @Requires(name = "s")
  private Service defaut;
  @Attribute(value="Hello !")
  protected String message;
            
  public void run() {
    this.defaut.print(this.message);
} }

The Client class defines the Runnable interface as a Fractal interface using the @Interface annotation. The field defaut is annoted as a client interface (using @Requires), and will be named "s". The attribute message is annoted as a Fractal attribute (using @Attribute), which will be automatically initialized to "Hello !".

@Interface(name="s")
public interface Service {
  void print(String message);
}

The Service interface is marked with @Interface to define the name of the Fractal interface as "s".

@Component                              
public class Server implements Service {
  @Attribute private String header;
  @Attribute private int counter;
                
  public void print(final String message) {
    for (int i = 0; i < this.counter; i++)
      System.out.println(this.header + message);
} }

The Server class inherits automatically from the Service annotations. The header and the counter attributes are defined as Fractal attributes (using @Attribute), whose initial value will be defined when the component will be created.

HelloWorld Architecture Definition

The assembly definition below represents the FractalADL assembly defined to describe the HelloWorld Fractal component:

<definition name="HelloWorld" extends="ClientComposite(s=>server)">
  <component name="server" definition="Server('>>',2)"/>
</definition>

This definition creates a composite component HelloWorld. Then it specifies that the definition of the component named server is Server and that the values of the header and the counter attributes are '>>' and 2, respectively.

Directory Structure

The directory structure below presents the list of compiled, generated and written files when using Fraclet to implement the HelloWorld example:

%example%
  * src/main/java
    - Client.java
    - Server.java
    - Service.java
  * src/main/resources
    - HelloWorld.fractal
  * target/generated-sources/spoon
    - Client.java
    - Client.fractal
    - ClientAttributes.java
    - ClientComposite.fractal
    - Server.java
    - Server.fractal
    - ServerAttributes.java
    - Service.java
    - Service.fractal
  * target/classes
    - Client.class
    - Client.fractal
    - ClientAttributes.class
    - ClientComposite.fractal
    - Server.class
    - Server.fractal
    - ServerAttributes.class
    - Service.class
    - Service.fractal
    - HelloWorld.fractal

Copyright © 1999-2008, ObjectWeb Consortium | contact | webmaster | Last modified at 2008-10-14 10:36 AM