Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migration of unmigrated content due to installation of a new plugin

...

In the project directory, the pom.xml file contains the instructions to build the bundle. The bundle uses the maven-bundle-plugin (see here for more information on this plug-in).

Div
classpom

<project>
   

Wiki Markup
{div:class=pom} <project> &nbsp;&nbsp;&nbsp;

<modelVersion>4.0.0</modelVersion>

&nbsp;&nbsp;&nbsp; <packaging>bundle</packaging> &nbsp;&nbsp;&nbsp; {color:#ff0000}


    <packaging>bundle</packaging>
    <groupId>ipojo.example</groupId>

{color} {color:#ff0000}&nbsp;&nbsp;&nbsp;


    <artifactId>hello.service</artifactId>

{color} {color:#ff0000}&nbsp;&nbsp;&nbsp;


    <version>1.0.0</version>

{color} {color:#ff0000}&nbsp;&nbsp;&nbsp; <name>Hello


    <name>Hello Service</name>

{color} <build> &nbsp;&nbsp;&nbsp; <plugins> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <plugin> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.felix</groupId>

&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;


            <artifactId>maven-bundle-plugin</artifactId>

&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <version>2.0.1</version> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <extensions>true</extensions> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <configuration> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <instructions> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <Bundle-SymbolicName> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; $\{pom.artifactId} &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </Bundle-SymbolicName> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {color:#ff0000}<Export-Package>{color} {color:#ff0000}&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ipojo.example.hello{color} {color:#ff0000}&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </Export-Package>{color} &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </instructions> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </configuration> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </plugin> &nbsp;&nbsp;&nbsp; </plugins> </build> </project> {div}

Then, the project is ready to be built issuing the following Maven command inside the project directory:

Code Block

mvn clean install

Maven should report that the build was a success; if an error was reported then verify the previous steps. Upon success the Hello service component JAR file is installed into the local Maven repository. A copy of the bundle JAR file will also be present in the "target" directory inside the project directory.

Hello Service Provider

The component implementation of the service is a simple Java class implementing the Hello service interface. The implementation is in the hello.impl project. The file src/main/java/ipojo/example/hello/impl/HelloImpl.java contains the following service implementation:

...


/**
 * Component implementing the Hello service.
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class HelloImpl implements Hello {

    /**
     * Returns an 'Hello' message.
     * @param name : name
     * @return Hello message
     * @see ipojo.example.hello.Hello#sayHello(java.lang.String)
     */
    public String sayHello(String name) { return "hello " + name;  }
}

To manage the component, iPOJO needs some metadata to understand that the component provides the Hello service. iPOJO metadata file is at the root of the hello.impl project ("metadata.xml"). It contains the following metadata (Note: iPOJO also supports a JAR manifest-based syntax):

...


<?xml version="1.0" encoding="UTF-8"?>
<ipojo 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="org.apache.felix.ipojo http://felix.apache.org/ipojo/schemas/CURRENT/core.xsd" 
    xmlns="org.apache.felix.ipojo">
      
  <component classname="ipojo.example.hello.impl.HelloImpl"
    name="HelloProvider">
    <provides />
  </component>
  
  <instance component="HelloProvider" name="HelloService" />
</ipojo>

In the above XML-based metadata, the component element has a mandatory 'classname'_attribute. This attribute tells iPOJO the implementation class of the component. Since the component in this example provides a service, the component element also specifies a child '_provides' element. The 'provides' element informs iPOJO that it must manage the publishing of a service. When the 'provides' element does not contain an interface attribute, as is the case in this example, iPOJO will expose all implemented interfaces of the component as a service; it is also possible to specify the precise service interface. The 'instance' element asks iPOJO to create an instance of your component when the bundle is started.

Finally, the "pom.xml" file contains instructions to build the bundle:

Wiki Markup
{div:class=pom}
<project>
&nbsp;&nbsp;<modelVersion>4.0.0</modelVersion>
&nbsp; <packaging>bundle</packaging>
&nbsp;&nbsp;{color:red}<groupId>ipojo.example</groupId>{color}
{color:red}&nbsp;&nbsp;<artifactId>hello.impl</artifactId>{color}
{color:red}&nbsp;&nbsp;<version>1.0.0</version>{color}

&nbsp;&nbsp;{color:red}<name>Hello Service Provider</name>{color}

{color:red}&nbsp; <dependencies>{color}
{color:red}&nbsp;&nbsp; &nbsp;<dependency> <!--Compilation (i.e. class) dependency on the service interface -->{color}
{color:red}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<groupId>ipojo.example</groupId>{color}
{color:red}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<artifactId>hello.service</artifactId>{color}
{color:red}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<version>{color}{color:#ff0000}1.0.0{color}{color:red}</version>{color}
{color:red}&nbsp;&nbsp; &nbsp;</dependency>{color}
{color:red}&nbsp; </dependencies>{color}


&nbsp;&nbsp;<build>
&nbsp;&nbsp; <plugins>
&nbsp;&nbsp;&nbsp;&nbsp; <plugin>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <groupId>org.apache.felix</groupId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <artifactId>maven-bundle-plugin</artifactId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <version>2.0.1</version>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <extensions>true</extensions>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <configuration>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <instructions>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <Bundle-SymbolicName>$\{pom.artifactId}</Bundle-SymbolicName>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {color:red}<Private-Package>ipojo.example.hello.impl</Private-Package>{color}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </instructions>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </configuration>
&nbsp;&nbsp;&nbsp;&nbsp; </plugin>
&nbsp;&nbsp;&nbsp;&nbsp; <plugin>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <groupId>org.apache.felix</groupId>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <artifactId>maven-ipojo-plugin</artifactId>
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; <version>1.6.0</version>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<executions>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <execution>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <goals>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <goal>ipojo-bundle</goal>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </goals>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</execution>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </executions>
&nbsp;&nbsp;&nbsp;&nbsp; </plugin>
&nbsp;&nbsp; </plugins>
&nbsp;</build>
</project>
{div}

The text highlighted in red above indicates the important information related to the project. The first part of the POM file indicates that the packaging format is an iPOJO bundle and also includes some information about the project (name, groupId, and artifactId). This information is not used by iPOJO, but is used by Maven. The rest of the POM file contains the bundle configuration. In the instructions element, you need to enter the bundle name, the bundle description, and the exported packages. The service provider bundle exports the package of Hello interface.

Then, the project is ready to be built issuing the following Maven command inside the project directory:

Code Block

mvn clean install

Maven should report that the build was a success; if an error was reported then verify the previous steps. Upon success the Hello service component JAR file is installed into the local Maven repository. A copy of the bundle JAR file will also be present in the "target" directory inside the project directory.

Hello Service Client

The Hello service consumer is inside the hello.client project. The file src/main/java/ipojo/example/hello/client/HelloClient.java contains the following Hello service client:

...


package ipojo.example.hello.client;

import ipojo.example.hello.Hello;

/**
 * Hello Service simple client.
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class HelloClient implements Runnable {

    /**
     *  Delay between two invocations.
     */
    private static final int DELAY = 10000;

    /**
     * Hello services.
     * Injected by the container.
     * */
    private Hello[] m_hello;

    /**
     * End flag.
     *  */
    private boolean m_end;

    /**
     * Run method.
     * @see java.lang.Runnable#run()
     */
    public void run() {
        while (!m_end) {
            try {
                invokeHelloServices();
                Thread.sleep(DELAY);
            } catch (InterruptedException ie) {
                /* will recheck end */
            }
        }
    }

    /**
     * Invoke hello services.
     */
    public void invokeHelloServices() {
        for (int i = 0; i < m_hello.length; i++) {
            // Update with your name.
            System.out.println(m_hello[i].sayHello("world"));
        }
    }

    /**
     * Starting.
     */
    public void starting() {
        Thread thread = new Thread(this);
        m_end = false;
        thread.start();
    }

    /**
     * Stopping.
     */
    public void stopping() {
        m_end = true;
    }
}


            <version>2.0.1</version>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <Bundle-SymbolicName>
                        ${pom.artifactId}
                    </Bundle-SymbolicName>
                    <Export-Package>
                        ipojo.example.hello
                    </Export-Package>
                </instructions>
            </configuration>
        </plugin>
    </plugins>
</build>

</project>

Then, the project is ready to be built issuing the following Maven command inside the project directory:

Code Block

mvn clean install

Maven should report that the build was a success; if an error was reported then verify the previous steps. Upon success the Hello service component JAR file is installed into the local Maven repository. A copy of the bundle JAR file will also be present in the "target" directory inside the project directory.

Hello Service Provider

The component implementation of the service is a simple Java class implementing the Hello service interface. The implementation is in the hello.impl project. The file src/main/java/ipojo/example/hello/impl/HelloImpl.java contains the following service implementation:

Code Block
java
java

/**
 * Component implementing the Hello service.
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class HelloImpl implements Hello {

    /**
     * Returns an 'Hello' message.
     * @param name : name
     * @return Hello message
     * @see ipojo.example.hello.Hello#sayHello(java.lang.String)
     */
    public String sayHello(String name) { return "hello " + name;  }
}

To manage the component, iPOJO needs some metadata to understand that the component provides the Hello service. iPOJO metadata file is at the root of the hello.impl project ("metadata.xml"). It contains the following metadata (Note: iPOJO also supports a JAR manifest-based syntax):

Code Block
xml
xml

<?xml version="1.0" encoding="UTF-8"?>
<ipojo 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="org.apache.felix.ipojo http://felix.apache.org/ipojo/schemas/CURRENT/core.xsd" 
    xmlns="org.apache.felix.ipojo">
      
  <component classname="ipojo.example.hello.impl.HelloImpl"
    name="HelloProvider">
    <provides />
  </component>
  
  <instance component="HelloProvider" name="HelloService" />
</ipojo>

In the above XML-based metadata, the component element has a mandatory 'classname'_attribute. This attribute tells iPOJO the implementation class of the component. Since the component in this example provides a service, the component element also specifies a child '_provides' element. The 'provides' element informs iPOJO that it must manage the publishing of a service. When the 'provides' element does not contain an interface attribute, as is the case in this example, iPOJO will expose all implemented interfaces of the component as a service; it is also possible to specify the precise service interface. The 'instance' element asks iPOJO to create an instance of your component when the bundle is started.

Finally, the "pom.xml" file contains instructions to build the bundle:

Div
classpom

<project>
  <modelVersion>4.0.0</modelVersion>
  <packaging>bundle</packaging>
  <groupId>ipojo.example</groupId>
  <artifactId>hello.impl</artifactId>
  <version>1.0.0</version>

  <name>Hello Service Provider</name>

  <dependencies>
    <dependency> <!--Compilation (i.e. class) dependency on the service interface -->
      <groupId>ipojo.example</groupId>
      <artifactId>hello.service</artifactId>
      <version>1.0.0</version>
    </dependency>
  </dependencies>

  <build>
   <plugins>
     <plugin>
       <groupId>org.apache.felix</groupId>
       <artifactId>maven-bundle-plugin</artifactId>
       <version>2.0.1</version>
       <extensions>true</extensions>
       <configuration>
         <instructions>
           <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
           <Private-Package>ipojo.example.hello.impl</Private-Package>
         </instructions>
       </configuration>
     </plugin>
     <plugin>
             <groupId>org.apache.felix</groupId>
             <artifactId>maven-ipojo-plugin</artifactId>
             <version>1.6.0</version>
             <executions>
               <execution>
               <goals>
                     <goal>ipojo-bundle</goal>
              </goals>
            </execution>
       </executions>
     </plugin>
   </plugins>
 </build>
</project>

The text highlighted in red above indicates the important information related to the project. The first part of the POM file indicates that the packaging format is an iPOJO bundle and also includes some information about the project (name, groupId, and artifactId). This information is not used by iPOJO, but is used by Maven. The rest of the POM file contains the bundle configuration. In the instructions element, you need to enter the bundle name, the bundle description, and the exported packages. The service provider bundle exports the package of Hello interface.

Then, the project is ready to be built issuing the following Maven command inside the project directory:

Code Block

mvn clean install

Maven should report that the build was a success; if an error was reported then verify the previous steps. Upon success the Hello service component JAR file is installed into the local Maven repository. A copy of the bundle JAR file will also be present in the "target" directory inside the project directory.

Hello Service Client

The Hello service consumer is inside the hello.client project. The file src/main/java/ipojo/example/hello/client/HelloClient.java contains the following Hello service client:

Code Block
java
java

package ipojo.example.hello.client;

import ipojo.example.hello.Hello;

/**
 * Hello Service simple client.
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class HelloClient implements Runnable {

    /**
     *  Delay between two invocations.
     */
    private static final int DELAY = 10000;

    /**
     * Hello services.
     * Injected by the container.
     * */
    private Hello[] m_hello;

    /**
     * End flag.
     *  */
    private boolean m_end;

    /**
     * Run method.
     * @see java.lang.Runnable#run()
     */
    public void run() {
        while (!m_end) {
            try {
                invokeHelloServices();
                Thread.sleep(DELAY);
            } catch (InterruptedException ie) {
                /* will recheck end */
            }
        }
    }

    /**
     * Invoke hello services.
     */
    public void invokeHelloServices() {
        for (int i = 0; i < m_hello.length; i++) {
            // Update with your name.
            System.out.println(m_hello[i].sayHello("world"));
        }
    }

    /**
     * Starting.
     */
    public void starting() {
        Thread thread = new Thread(this);
        m_end = false;
        thread.start();
    }

    /**
     * Stopping.
     */
    public void stopping() {
        m_end = true;
    }
}

The Hello service client creates a thread that periodically invokes the available Hello services. The thread starts when at least one Hello service provider is present using iPOJO's call back mechanism. In the client code, to use the hello the component implementation simply declares a field of the type of the service and then simply uses it directly in its code. In this example, it is the m_hello field is declared as the service field; notice that the field is an array of Hello. In iPOJO an array of services represents an aggregate or multiple cardinality dependency, whereas if a scalar value represents a singular or unary cardinality dependency. In other words, for a singular dependency simply remove the array brackets from the example (e.g., HelloService m_hello[]. After declaring a field for the service, the rest of the component code can simply assume that the service field will be initialized, e.g., m_hello[i].sayHello("world").

Notice that iPOJO manages service synchronization too. So, the service invocations do not require synchronization blocks. This synchronization is maintained on a per thread basis, where each method that accesses a service is instrumented to attach the given service instance to the thread so that the thread will continue to see the same service instances even across nested method invocations. The thread will not see different service instances until it completely exits from the first method it entered which used a services. Thus, you would not want to access services in the run() method above, because the thread would always see the same service instance.

The component provides two callback methods for its activation and deactivation, starting() and stopping(), respectively. Callbacks are used when the component needs to be informed about a component state change. In iPOJO, the component state is either INVALID (i.e., not all of the component's constraints are satisfied) or VALID (i.e., all of the component's constraints are satisfied). In this example, the starting callback method creates and starts a thread; the stopping callback method stops the thread. The component metadata will instruct iPOJO to invoke these methods when the component's state changes to VALID or INVALID respectively.

The iPOJO metadata file describing the component is "metadata.xml" and contains the following metadata:

Code Block
xml
xml

<?xml version="1.0" encoding="UTF-8"?>
<ipojo 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="org.apache.felix.ipojo http://felix.apache.org/ipojo/schemas/CURRENT/core.xsd" 
    xmlns="org.apache.felix.ipojo">

  <component classname="ipojo.example.hello.client.HelloClient">
    <requires field="m_hello" />
    <callback transition="validate" method="starting" />
    <callback transition="invalidate" method="stopping" />
    <properties>
      <property field="m_name" name="hello.name" />
    </properties>
  </component>

  <instance component="ipojo.example.hello.client.HelloClient">
    <property name="hello.name" value="clement" />
  </instance>
</ipojo>

The component element again has the 'classname' attribute that refers to the component implementation class. The 'requires' element describes the Hello service dependency by simply specifying its associated component field. The 'callback'_elements describe which method to invoke when the component's state changes. Then the '_instance' element asks iPOJO to create an instance of the component (notice that no instance name is provided here, iPOJO will give an instance name to the instance automatically).

Finally, the "pom.xml" file contains instructions to build the bundle:

Div
classpom

<project>
  <modelVersion>4.0.0</modelVersion>
  <packaging>bundle</packaging>
  <groupId>ipojo.example</groupId>
  <artifactId>hello.client</artifactId>
  <version>1.0.0</version>
  <name>Hello Client</name>

  <dependencies>
    <dependency> <!-- Compilation (i.e. class) dependency on the service interface -->
      <groupId>ipojo.example</groupId>
      <artifactId>hello.service</artifactId>
      <version>1.0.0</version>
    </dependency>
  </dependencies>

  <build>
     <plugins>
     <plugin>
     <groupId>org.apache.felix</groupId>
     <artifactId>maven-bundle-plugin</artifactId>
     <version>2.0.1</version>
     <extensions>true</extensions>
     <configuration>
       <instructions>
         <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
         <Private-Package>ipojo.example.hello.client</Private-Package>
       </instructions>
     </configuration>
   </plugin>
   <plugin>
           <groupId>org.apache.felix</groupId>
           <artifactId>maven-ipojo-plugin</artifactId>
           <version>1.6.0</version>
           <executions>
             <execution>
             <goals>
                   <goal>ipojo-bundle</goal>
            </goals>
             </execution>
         </executions>
   </plugin>
 </plugins>
  </build>
</project>

The Hello service client creates a thread that periodically invokes the available Hello services. The thread starts when at least one Hello service provider is present using iPOJO's call back mechanism. In the client code, to use the hello the component implementation simply declares a field of the type of the service and then simply uses it directly in its code. In this example, it is the m_hello field is declared as the service field; notice that the field is an array of Hello. In iPOJO an array of services represents an aggregate or multiple cardinality dependency, whereas if a scalar value represents a singular or unary cardinality dependency. In other words, for a singular dependency simply remove the array brackets from the example (e.g., HelloService m_hello[]. After declaring a field for the service, the rest of the component code can simply assume that the service field will be initialized, e.g., m_hello[i].sayHello("world").

Notice that iPOJO manages service synchronization too. So, the service invocations do not require synchronization blocks. This synchronization is maintained on a per thread basis, where each method that accesses a service is instrumented to attach the given service instance to the thread so that the thread will continue to see the same service instances even across nested method invocations. The thread will not see different service instances until it completely exits from the first method it entered which used a services. Thus, you would not want to access services in the run() method above, because the thread would always see the same service instance.

The component provides two callback methods for its activation and deactivation, starting() and stopping(), respectively. Callbacks are used when the component needs to be informed about a component state change. In iPOJO, the component state is either INVALID (i.e., not all of the component's constraints are satisfied) or VALID (i.e., all of the component's constraints are satisfied). In this example, the starting callback method creates and starts a thread; the stopping callback method stops the thread. The component metadata will instruct iPOJO to invoke these methods when the component's state changes to VALID or INVALID respectively.

The iPOJO metadata file describing the component is "metadata.xml" and contains the following metadata:

...


<?xml version="1.0" encoding="UTF-8"?>
<ipojo 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="org.apache.felix.ipojo http://felix.apache.org/ipojo/schemas/CURRENT/core.xsd" 
    xmlns="org.apache.felix.ipojo">

  <component classname="ipojo.example.hello.client.HelloClient">
    <requires field="m_hello" />
    <callback transition="validate" method="starting" />
    <callback transition="invalidate" method="stopping" />
    <properties>
      <property field="m_name" name="hello.name" />
    </properties>
  </component>

  <instance component="ipojo.example.hello.client.HelloClient">
    <property name="hello.name" value="clement" />
  </instance>
</ipojo>

The component element again has the 'classname' attribute that refers to the component implementation class. The 'requires' element describes the Hello service dependency by simply specifying its associated component field. The 'callback'_elements describe which method to invoke when the component's state changes. Then the '_instance' element asks iPOJO to create an instance of the component (notice that no instance name is provided here, iPOJO will give an instance name to the instance automatically).

Finally, the "pom.xml" file contains instructions to build the bundle:

Wiki Markup
{div:class=pom} <project> &nbsp;&nbsp;<modelVersion>4.0.0</modelVersion> &nbsp;&nbsp;<packaging>bundle</packaging> &nbsp;&nbsp;{color:red}<groupId>ipojo.example</groupId>{color} {color:red}&nbsp;&nbsp;<artifactId>hello.client</artifactId>{color} {color:red}&nbsp;&nbsp;<version>1.0.0</version>{color} {color:red}&nbsp;&nbsp;<name>Hello Client</name>{color} {color:red}&nbsp;&nbsp;<dependencies>{color} {color:red}&nbsp;&nbsp; &nbsp;<dependency> <\!-\-{color} {color:red}Compilation (i.e. class) dependency on the service interface \-\-{color}{color:red}>{color} {color:red}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<groupId>ipojo.example</groupId>{color} {color:red}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<artifactId>hello.service</artifactId>{color} {color:red}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<version>{color}{color:#ff0000}1.0.0{color}{color:red}</version>{color} {color:red}&nbsp;&nbsp; &nbsp;</dependency>{color} {color:red}&nbsp; </dependencies>{color} &nbsp; <build> &nbsp;&nbsp;&nbsp;&nbsp; <plugins> &nbsp;&nbsp;&nbsp;&nbsp; <plugin> &nbsp;&nbsp;&nbsp;&nbsp; <groupId>org.apache.felix</groupId> &nbsp;&nbsp;&nbsp;&nbsp; <artifactId>maven-bundle-plugin</artifactId> &nbsp;&nbsp;&nbsp;&nbsp; <version>2.0.1</version> &nbsp;&nbsp;&nbsp;&nbsp; <extensions>true</extensions> &nbsp;&nbsp;&nbsp;&nbsp; <configuration> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <instructions> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <Bundle-SymbolicName>$\{pom.artifactId}</Bundle-SymbolicName> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {color:red}<Private-Package>ipojo.example.hello.client</Private-Package>{color} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </instructions> &nbsp;&nbsp;&nbsp;&nbsp; </configuration> &nbsp;&nbsp; </plugin> &nbsp;&nbsp; <plugin> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <groupId>org.apache.felix</groupId> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <artifactId>maven-ipojo-plugin</artifactId> &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; <version>1.6.0</version> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <executions> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <execution> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <goals> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <goal>ipojo-bundle</goal> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </goals> &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </execution> &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; </executions> &nbsp;&nbsp; </plugin> &nbsp;</plugins> &nbsp; </build> </project> {div}

The text highlighted in red above indicates the information related to the project. The dependencies element tells Maven that the client bundle has a compilation dependency on the service provider bundle. In this case, the client bundle needs the Hello service interface to compile. After building the service provider bundle JAR file, Maven installs it into a local repository on your machine. To resolve compilation dependencies, Maven looks in the local repository to find required JAR files.
After the skeleton "pom.xml" file is modified, the project is ready to be built issuing the following Maven command inside the project directory:
mvn clean install
Maven should report that the build was a success; if an error was reported then verify the previous steps. Upon success the Hello service component JAR file is installed into the local Maven repository. A copy of the bundle JAR file will also be present in the "target" directory inside the project directory.

...

Install the Hello service bundle, the Hello service provider and the client that were created above:

Div
classshell

start

Wiki Markup
{div:class=shell} start

file:../hello.service/target/hello.service-1.0.0.jar


start

file:../hello.impl/target/hello.impl-1.0.0.jar


start

file:../hello.client/target/hello.client-1.0.0.

jar {div}

jar

By starting the Hello service provider bundle, the client component will automatically be activated. So, the 'hello world' messages are displayed.

Div
classshell

-> hello world
hello world

Wiki Markup
{div:class=shell} \-> hello world hello world {div}

Stop the provider (with the 'stop 7' command) and the client will automatically be deactivated since its dependency is no longer valid. If multiple Hello services are deployed, the client will connect to all of them. If you restart the bundle (with the start 7 command), the client becomes valid.

During these operations, you can use the arch command to check the state of instances..

Div
classshell

-> stop 7
-> arch
Instance ArchCommand -> valid
Instance

Wiki Markup
{div:class=shell} \-> stop 7 \-> arch Instance ArchCommand \-> valid {color:red}Instance ipojo.example.hello.client.HelloClient-0 \-> invalid{color} \-> arch \-instance ipojo.example.hello.client.HelloClient-0 instance name="

ipojo.example.hello.client.HelloClient-0

" &nbsp;component.type="ipojo.example.hello.client.HelloClient" &nbsp;state="{color:red}invalid{color}" bundle="8" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object name="

-> invalid
-> arch -instance ipojo.example.hello.client.

HelloClient@137c60d" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {color:red}handler name="org.apache.felix.ipojo.handlers.dependency.DependencyHandler" state="invalid"{color} {color:red}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{color}{color:red}requires aggregate="true" optional="false" state="resolved" specification="ipojo.example.hello.Hello"{color} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handler

HelloClient-0
instance name="ipojo.example.hello.client.HelloClient-0"
 component.type="ipojo.example.hello.client.HelloClient"
 state="invalid" bundle="8"
        object name="ipojo.example.hello.client.HelloClient@137c60d"
        handler name="org.apache.felix.ipojo.handlers.dependency.DependencyHandler" state="invalid"
               requires aggregate="true" optional="false" state="resolved" specification="ipojo.example.hello.Hello"
        handler name="org.apache.felix.ipojo.handlers.lifecycle.callback.LifecycleCallbackHandler"

state="valid"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handler


        handler name="org.apache.felix.ipojo.handlers.architecture.ArchitectureHandler"

state="valid"

\


->

start

7


hello

world

\


->

arch


Instance

ArchCommand

\

->

valid {color:red}Instance

valid
Instance ipojo.example.hello.client.HelloClient-0

\

->

valid

{color}


Instance

HelloService

\

->

valid

\


->

arch

\

-instance

ipojo.example.hello.client.HelloClient-0


instance

name="ipojo.example.hello.client.HelloClient-0"

&nbsp;component


 component.type="ipojo.example.hello.client.HelloClient"

&nbsp;


  state="valid"

bundle="8"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object


        object name="ipojo.example.hello

.client.HelloClient@137c60d" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {color:red}handler

.client.HelloClient@137c60d"
        handler name="org.apache.felix.ipojo.handlers.dependency.DependencyHandler"

state="valid"

{color} {color:red}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{color}{color:red}requires


               requires aggregate="true"

optional="false"

state="resolved"

specification="ipojo.example.hello.Hello"{color} {color:red}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{color} {color:red}uses

specification="ipojo.example.hello.Hello"
                        uses service.id="38"

instance.name="HelloService"

{color} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handler


        handler name="org.apache.felix.ipojo.handlers.lifecycle.callback.LifecycleCallbackHandler"

state="valid"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; handler


        handler name="org.apache.felix.ipojo.handlers.architecture.ArchitectureHandler"

state="valid"

{div}

Conclusion

We saw how to use easily iPOJO to build service-oriented components. Subscribe to the Felix users mailing list by sending a message to users-subscribe@felix.apache.org; after subscribing, email questions or feedback to users@felix.apache.org.

...