iPOJO Hello World

简单的样例
下面的简单样例将演示如何使用核心iPOJO概念。样例由2个组件组成。一个提供了Hello服务而另一个使用多个hello服务。这些组件使用Maven被打包成3个不同的bundle。hello.service服务包包含了服务的接口(接口和实现分离)。hello.impl服务包包含了一个实现服务的组件。hello.client服务包包含服务消费组件。

准备Maven 安装示例
第一步,下载并安装Maven;本例子使用Maven 2.2.0来创建。当你机器上安装了Maven后,你就可以编译本例子解压后的项目了,并在项目的根目录下用命令"mvn clean install"

注意:当Maven执行时会输出一些信息,并会经常下载一些需要的JAR文件到本地库中

Hello Service
第一个项目是hello.service,项目仅包含了一个服务接口。
$ mvn archetype:create -DgroupId=iPOJOTutorial -DartifactId=hello.service -Dversion=1.0.0  -DpackageName=ipojo.example.hello

使用mvn创建hello.service项目.
创建src/main/java/ipojo/example/hello/Hello.java
package ipojo.example.hello;
/**
* Hello Interface.
* @author <a href="mailto:[email protected]">Felix Project Team</a>
*/
public interface Hello {

    /**
     * Returns a message like: "Hello $user_name".
     * @param name the name
     * @return the hello message
     */
    String sayHello(String name);
}



在生成的pom.xml文件中修改和添加如下内容:
<packaging>bundle</packaging>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <version>1.4.3</version>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <Bundle-SymbolicName>
                        ${pom.artifactId}
                    </Bundle-SymbolicName>
                    <Export-Package>
                        ipojo.example.hello
                    </Export-Package>
                </instructions>
            </configuration>
        </plugin>
    </plugins>
</build>

进入hello.service根目录,输入命令:
mvn clean install


Maven报告构建成功,在根目录下的target目录下你就可以看到生成的bundle了。可以查看该jar文件中的META-INF下的MANIFEST.MF文件中是否有Export-Package、Bundle-*等关键词,如果有说明我们构建输出的是bundle。当然install命令也将我们的bundle发布到本地库中了。本地库方面的知识,读者可自行阅读Maven方面的书籍。




Hello 服务供应者
服务的实现组件是一个普通的实现了Hello Service接口的类。服务组件的实现包含在hello.impl项目中。首先我们还是使用mvn来帮助我们构建项目的骨架。


输入:mvn archetype:create -DgroupId=iPOJOTutorial -Dar
tifactId=hello.impl -Dversion=1.0.0  -DpackageName=ipojo.example.hello.impl。

服务实现如下:
package ipojo.example.hello.impl;
/**
* Component implementing the Hello service.
* @author <a href="mailto:[email protected]">Felix Project Team</a>
*/
import ipojo.example.hello.Hello;
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;  }
}

为了管理组件,iPOJO还需要metadata来描述组件提供的Hello服务。iPOJO metadata文件在hello.impl项目的根目录下,名字为metadata.xml。它包含了一下元数据(iPOJO也支持JAR的mainifest风格的语法)

<iPOJO>
    <component className="ipojo.example.hello.impl.HelloImpl" name="HelloProvider">
        <provides />
    </component>
    <instance component="HelloProvider" name="HelloService" />
</iPOJO>



pom.xml文件内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>iPOJOTutorial</groupId>
  <artifactId>hello.impl</artifactId>
  <packaging>bundle</packaging>
  <version>1.0.0</version>
  <name>hello.impl</name>
  <url>http://maven.apache.org</url>
  <dependencies>
   
  <dependency> <!--Compilation (i.e. class) dependency on the service interface -->
      <groupId>iPOJOTutorial</groupId>
      <artifactId>hello.service</artifactId>
      <version>1.0.0</version>
    </dependency>

   <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

<build>
   <plugins>
     <plugin>
       <groupId>org.apache.felix</groupId>
       <artifactId>maven-bundle-plugin</artifactId>
       <version>1.4.3</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.2.0</version>
             <executions>
               <execution>
               <goals>
                     <goal>ipojo-bundle</goal>
              </goals>
            </execution>
       </executions>
     </plugin>
   </plugins>
</build>
  </dependencies>

</project>

本项目首先依赖接口,所以比上一个项目增加了一个<dependency>。同时还增加了一个maven-ipojo-plugin。

当上面的工作完成并进入项目的根目录后,我们就可以使用mvn clean install来构建项目了。

成功构建bundle后,在bundle中的MANIFEST.MF内容如下:
Manifest-Version: 1.0
Private-Package: ipojo.example.hello.impl
iPOJO-Components: component { $name="HelloProvider" $classname="ipojo.
example.hello.impl.HelloImpl" $architecture="true" provides { }manipu
lation { method { $name="$init" }method { $arguments="{java.lang.Stri
ng}" $name="sayHello" $return="java.lang.String" }interface { $name="
ipojo.example.hello.Hello" }}}instance { $component="HelloProvider" $
name="HelloService" }
Built-By: zhangcm
Tool: Bnd-0.0.255
Bundle-Name: hello.impl
Created-By: Apache Maven Bundle Plugin & iPOJO
Bundle-Version: 1.0.0
Build-Jdk: 1.6.0_06
Bnd-LastModified: 1247623899280
Bundle-ManifestVersion: 2
Import-Package: org.osgi.service.log;version=1.3, org.apache.felix.ipo
jo.architecture;version= 1.2.0, ipojo.example.hello, org.apache.felix
.ipojo;version= 1.2.0, org.osgi.service.cm;version=1.2
Bundle-SymbolicName: hello.impl


Hello Service 客户端
Hello服务消费在项目hello.client中。使用mvn创建该项目:

mvn archetype:create -DgroupId=iPOJOTutorial -DartifactId=hello.client -Dversion=1.0.0  -DpackageName=ipojo.example.hello.client。
客户端代码如下:

package ipojo.example.hello.client;

import ipojo.example.hello.Hello;

/**
* Hello Service simple client.
* @author <a href="mailto:[email protected]">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; // Service Requirement

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

    /**
     * Name property.
     * Injected by the container.
     * */
    private String m_name;

    /**
     * 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++) {
            System.out.println(m_hello[i].sayHello(m_name));
        }
    }

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

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


Hello Service 客户端创建一个线程,间断性地调用Hello服务。当至少存在一个hello服务的供应者,iPOJO回调机制
会调用客户端的starting方法来启动线程。在客户端代码中,为了使用hello服务的实现组件,只需要简单地定义服务接口类型的字段。在本项目中,那它就是m_hello。请注意m_hello字段是一个Hello数组。在iPOJO中服务数组表示聚合依赖。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").

注意:iPOJO也管理服务的同步。因此,服务的调用时不需要同步块(synchronization)。这种同步是基于每线程基础上的。每一种方法访问的服务是附加在线程上的给定的服务实例,因此线程将会一直能看到同一个服务实例,甚至跨入嵌套方法调用。线程除了完全从第一个它进入的服务方法中退出为至。。因此,你不需要在run()方法之外存取服务,因为线程将永远看到相同的服务实例。

本组件提供了2个回调方法starting() stopping()分别用于激活和去激活。当组件需要得到有关组件状态改变的通知,就需要用到回调了。在iPOJO中,组件只有2个状态INVALID(组件的约束不满足,如依赖的服务不存在)和VALID(组件的约束满足)。在本例中,starting 回调方法创建并开启线程。stopping回调方法停止线程。组件元数据指示iPOJO调用这两个方法,当组件状态在VALID或者INVALID变化时。


在本项目的根目录下,创建metadata.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<iPOJO>
<component className="ipojo.example.hello.client.HelloClient"
architecture="true">
<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>

pom.xml文件内容如下:
<project>
  <modelVersion>4.0.0</modelVersion>
  <packaging>bundle</packaging>
  <groupId>iPOJOTutorial</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>iPOJOTutorial</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>1.4.3</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.2.0</version>
           <executions>
             <execution>
             <goals>
                   <goal>ipojo-bundle</goal>
            </goals>
             </execution>
         </executions>
   </plugin>
</plugins>
  </build>
</project>

构建客户端:mvn clean install


////////////////////////////////////////////////////////////////////

示例运行:
启动Felix运行本示例。
java -jar bin/felix.jar
Welcome to Felix.
=================

-> ps
START LEVEL 1
   ID   State         Level  Name
[   0] [Active     ] [    0] System Bundle (1.4.1)
[   1] [Active     ] [    1] Apache Felix Shell Service (1.0.2)
[   2] [Active     ] [    1] Apache Felix Shell TUI (1.0.2)
[   3] [Active     ] [    1] Apache Felix Bundle Repository (1.2.1)
[   4] [Active     ] [    1] Apache Felix iPOJO (1.2.0)
[   5] [Active     ] [    1] Apache Felix iPOJO Arch Command (1.2.0)
->




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

你可能感兴趣的:(apache,maven,xml,项目管理,osgi)