Статьи

OSGi — Простой Hello World с сервисами

В этом посте мы разработаем простое приложение Hello World с OSGi . Мы будем использовать Felix в качестве контейнера OSGi . В следующем посте мы продолжим работу с этим приложением и будем использовать Spring Dynamic Modules для его улучшения.

Чтобы сделать разработку интересной, мы создадим два пакета:

  • Пакет, предоставляющий сервис HelloWorld
  • Пакет, использующий сервис для печати привет через регулярный промежуток времени.

Итак, начнем с первого комплекта. Сначала нам нужен очень простой сервис, обеспечивающий простую печать в консоли:

1
2
3
4
5
package com.bw.osgi.provider.able;
  
public interface HelloWorldService {
    void hello();
}
01
02
03
04
05
06
07
08
09
10
package com.bw.osgi.provider.impl;
  
import com.bw.osgi.provider.able.HelloWorldService;
  
public class HelloWorldServiceImpl implements HelloWorldService {
    @Override
    public void hello(){
        System.out.println("Hello World !");
    }
}

Мы не можем сделать проще. Затем нам нужно экспортировать Сервис с помощью активатора:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.bw.osgi.provider;
  
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
  
import com.bw.osgi.provider.able.HelloWorldService;
import com.bw.osgi.provider.impl.HelloWorldServiceImpl;
  
public class ProviderActivator implements BundleActivator {
    private ServiceRegistration registration;
  
    @Override
    public void start(BundleContext bundleContext) throws Exception {
        registration = bundleContext.registerService(
                HelloWorldService.class.getName(),
                new HelloWorldServiceImpl(),
                null);
    }
  
    @Override
    public void stop(BundleContext bundleContext) throws Exception {
        registration.unregister();
    }
}

Гораздо больше кода здесь. Для тех, кто не уверен в OSGi, несколько объяснений. Метод запуска будет вызываться при запуске модуля и остановка при его остановке. В методе start мы регистрируем наш сервис в контексте пакета, используя имя интерфейса в качестве имени экспортируемого сервиса. Третий параметр, null, указывает, что мы не предоставляем никакой конфигурации для этого сервиса. В методе stop мы просто отменяем регистрацию сервиса.

Теперь наш первый комплект готов. Мы можем построить это. Для этого мы будем использовать Maven и maven-bundle-plugin для непосредственной сборки OSGi Bundle. Вот файл pom.xml для проекта.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="UTF-8"?>
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    <modelVersion>4.0.0</modelVersion>
  
    <groupId>OSGiDmHelloWorldProvider</groupId>
    <artifactId>OSGiDmHelloWorldProvider</artifactId>
    <version>1.0</version>
  
    <dependencies>
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.osgi.core</artifactId>
            <version>1.4.0</version>
        </dependency>
    </dependencies>
  
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
  
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>OSGiDmHelloWorldProvider</Bundle-SymbolicName>
                        <Export-Package>com.bw.osgi.provider.able</Export-Package>
                        <Bundle-Activator>com.bw.osgi.provider.ProviderActivator</Bundle-Activator>
                        <Bundle-Vendor>Baptiste Wicht</Bundle-Vendor>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

А затем используйте mvn install для его сборки.

Мы будем работать в папке с именем osgi, поэтому мы скопируем этот новый пакет в папку osgi.

Мы уже можем проверить это в контейнере OSGi. Если у вас нет Феликса, давайте загрузим его здесь. Вы должны выбрать «Распределение Феликса».

Затем распакуйте его в папку osgi, которую мы создали ранее. Теперь у вас должна быть эта структура папок:

1
2
3
osgi
  - felix
  - OSGiDmHelloWorldProvider-1.0.jar

Итак, мы можем зайти в папку Felix и запустить Felix:

1
2
3
4
5
wichtounet@Linux-Desktop:~/Desktop/osgi/felix$ java -jar bin/felix.jar
_______________
Welcome to Apache Felix Gogo
 
g!

И установите наш комплект:

1
2
g! install file:../OSGiDmHelloWorldProvider-1.0.jar
Bundle ID: 5

Установка успешно установлена, мы можем попробовать запустить ее и посмотреть ее статус:

01
02
03
04
05
06
07
08
09
10
11
12
g! start 5
g! bundle 5
Location             file:../OSGiDmHelloWorldProvider-1.0.jar
State                32
Version              1.0.0
LastModified         1279124741320
Headers              [Tool=Bnd-0.0.357, Bundle-Activator=com.bw.osgi.provider.ProviderActivator, Export-Package=com.bw.osgi.provider.able, Build-Jdk=1.6.0_20, Bundle-Version=1.0.0, Created-By=Apache Maven Bundle Plugin, Bundle-ManifestVersion=2, Manifest-Version=1.0, Bundle-Vendor=Baptiste Wicht, Bnd-LastModified=1279124686551, Bundle-Name=Unnamed - OSGiDmHelloWorldProvider:OSGiDmHelloWorldProvider:bundle:1.0, Built-By=wichtounet, Bundle-SymbolicName=OSGiDmHelloWorldProvider, Import-Package=com.bw.osgi.provider.able,org.osgi.framework;version="1.5"]
BundleContext        org.apache.felix.framework.BundleContextImpl@2353f67e
BundleId             5
SymbolicName         OSGiDmHelloWorldProvider
RegisteredServices   [HelloWorldService]
ServicesInUse        null

Все в порядке. Наш сервис хорошо зарегистрирован

Теперь мы попробуем использовать эту услугу в нашем втором пакете. Наш потребительский класс будет очень простым:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.bw.osgi.consumer;
  
import javax.swing.Timer;
  
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
  
import com.bw.osgi.provider.able.HelloWorldService;
  
public class HelloWorldConsumer implements ActionListener {
    private final HelloWorldService service;
    private final Timer timer;
  
    public HelloWorldConsumer(HelloWorldService service) {
        super();
  
        this.service = service;
  
        timer = new Timer(1000, this);
    }
  
    public void startTimer(){
        timer.start();
    }
  
    public void stopTimer() {
        timer.stop();
    }
  
    @Override
    public void actionPerformed(ActionEvent e) {
        service.hello();
    }
}

И теперь мы должны создать активатор, чтобы получить услугу, а затем передать ее потребителю. Это даст что-то вроде этого:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.bw.osgi.consumer;
  
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
  
import com.bw.osgi.provider.able.HelloWorldService;
  
public class HelloWorldActivator implements BundleActivator {
    private HelloWorldConsumer consumer;
  
    @Override
    public void start(BundleContext bundleContext) throws Exception {
        ServiceReference reference = bundleContext.getServiceReference(HelloWorldService.class.getName());
  
        consumer = new HelloWorldConsumer((HelloWorldService) bundleContext.getService(reference));
        consumer.startTimer();
    }
  
    @Override
    public void stop(BundleContext bundleContext) throws Exception {
        consumer.stopTimer();
    }
}

Мы получаем ссылку на сервис из контекста пакета, используя имя класса. После этого мы получаем экземпляр службы из контекста пакета.

Мы также создаем небольшой файл pom.xml для сборки пакета:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="UTF-8"?>
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    <modelVersion>4.0.0</modelVersion>
    <groupId>OSGiDmHelloWorldConsumer</groupId>
    <artifactId>OSGiDmHelloWorldConsumer</artifactId>
    <version>1.0</version>
    <packaging>bundle</packaging>
  
    <dependencies>
        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.osgi.core</artifactId>
            <version>1.0.0</version>
        </dependency>
  
        <dependency>
            <groupId>OSGiDmHelloWorldProvider</groupId>
            <artifactId>OSGiDmHelloWorldProvider</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>
  
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
  
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>OSGiDmHelloWorldConsumer</Bundle-SymbolicName>
                        <Bundle-Activator>com.bw.osgi.consumer.HelloWorldActivator</Bundle-Activator>
                        <Bundle-Vendor>Baptiste Wicht</Bundle-Vendor>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Затем мы используем mvn install для создания пакета и устанавливаем его в контейнер:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
g! start 6
g! Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
Hello World !
g! stop 6

И вот мы здесь. Мы создали наше первое приложение с использованием OSGi. С помощью этой технологии вы можете создавать модули действительно независимо.

В следующем посте о OSGi мы увидим, как использовать Spring, чтобы упростить разработку OSGi и сконцентрировать наши усилия на приложении, а не на OSGi.

Источники двух пакетов доступны здесь:

Справка: OSGi — Simple Hello World с услугами нашего партнера JCG Баптиста Вихта по адресу

Статьи по Теме :