2014년 8월 4일 월요일

How to do development OSGi Bundles at Apache Karaf.


OSGi Framework
  • Apache Felix
  • Eclipse Equinox

OSGi Bundle 개발 방식
  1. Eclipse Plug-in Project
    • 내부 Equinox Framework을 사용할 수 있다.
    • Maven을 사용하더라도, Manifest 파일을 자동으로 생성할 수 없다.
  2. Simple Maven Project
    • Felix, Karaf의 Dependency 설정이 복잡하다.
    • Eclipse OSGi Framework을 사용할수 없다.
  3. Maven org.apache.karaf.archetypes 사용
    • Felix, Karaf, Blueprint Dependeycy 설정을 지원

Karaf.archetype 종류
  • karaf-command-archetype
  • karaf-bundle-archetype
  • karaf-blueprint-archetype
  • karaf-feature-archetype

Karaf.archetype 추가


Remote Karaf Debug 방식
  • karaf 실행 파일의 자바 옵션에 다음을 추가
-Xdebug -agentlib:jdwp=transport=dt_socket,address=9999,server=y,suspend=n



한 장비에 두 개 이상의 Karaf을 설치 할 때

  • 오류 포트 충돌
karaf@root()> Exception in thread "JMX Connector Thread [service:jmx:rmi://0.0.0.0:44444/jndi/rmi://0.0.0.0:1099/karaf-root]" java.lang.RuntimeException:
Port already in use: 44444;
You may have started two containers.  If you need to start a second container or the default ports are already in use update the config file etc/org.apache.karaf.management.cfg and change the Registry Port and Server Port to unused ports...

  • 해결방법
etc/org.apache.karaf.management.cfg에서 포트 변경





Bundle simple Code
package com.esum.osgi.pilot.SayService;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

public class Activator implements BundleActivator {

  private ServiceRegistration<?> tellMeService;

  public void start(BundleContext context) {
     System.out.println("Starting the bundle");
     TellMeMessage tellme = new TellMeMessage();
     tellMeService =context.registerService(TellMeMessage.class.getName(), tellme, null);
  }

  public void stop(BundleContext context) {
     System.out.println("Stopping the bundle");
     tellMeService.unregister();
  }

}

ServiceRegistration에 등록되는 서비스는 인터페이스가 꼭 있어야 한다.
package com.esum.osgi.pilot.SayService;

import java.util.Date;

public interface TellMeMessage {
  
  public String tell();
}


package com.esum.osgi.pilot.SayService.imp;

import java.util.Date;

public class TellMeMessageImp {
  
  public String tell() {
     return "안녕하세요. 현제 시간:"+new Date()+", 입니다.";
  }
}

maven clean install → 자동생성되 MANIFEST.MF
Manifest-Version: 1.0
Bnd-LastModified: 1406184204292
Build-Jdk: 1.7.0_55
Built-By: yunchang-lee
Bundle-Activator: com.esum.osgi.pilot.SayService.Activator
Bundle-Description: SayService OSGi bundle project.
Bundle-ManifestVersion: 2
Bundle-Name: SayService Bundle
Bundle-SymbolicName: SayService
Bundle-Version: 1.0.0
Created-By: Apache Maven Bundle Plugin
Export-Package: com.esum.osgi.pilot.SayService;version="1.0.0";uses:="or
g.osgi.framework"
Import-Package: org.osgi.framework;version="[1.7,2)"
Tool: Bnd-2.1.0.20130426-122213

Karaf에 설치

Blueprint Bundle code



<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
  default-activation="lazy">

  <bean id="bundle-activator" class="com.esum.osgi.pilot.SayClient.Activator" />
  
  <reference id="tellMeService" availability="mandatory"
     activation="eager" interface="com.esum.osgi.pilot.SayService.TellMeMessage">
     <reference-listener ref="bundle-activator"
         bind-method="onBindService" unbind-method="onUnbindService" />
  </reference>

</blueprint>



package com.esum.osgi.pilot.SayClient;

import com.esum.osgi.pilot.SayService.TellMeMessage;

public class Activator {
  public void onBindService(TellMeMessage tellMeService) {
     if (tellMeService == null) {
         System.out.println("tellMeService is null");
     } else {
         System.out.println("Message: " + tellMeService.tell());
     }
  }

  public void onUnbindService(TellMeMessage tellMeService) {
     System.out.println("tellMeService unbound");
  }
}


Bundle build시에 Dependency 포함하기


<dependencies>
     <dependency>
         <groupId>org.osgi</groupId>
         <artifactId>org.osgi.core</artifactId>
         <version>${osgi.version}</version>
         <scope>provided</scope>
     </dependency>
     <dependency>
         <groupId>com.esum.utils</groupId>
         <artifactId>DateUtils</artifactId>
         <version>0.0.1-SNAPSHOT</version>
     </dependency>
  </dependencies>
<build>
     <plugins>
         <plugin>
             <groupId>org.apache.felix</groupId>
             <artifactId>maven-bundle-plugin</artifactId>
             <version>${maven-bundle-plugin.version}</version>
             <extensions>true</extensions>
             <configuration>
                 <instructions>
 <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
                     <Embed-Transitive>true</Embed-Transitive>
                     <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                     <Bundle-Version>${project.version}</Bundle-Version>
                     <Bundle-Activator>com.esum.osgi.pilot.SayService.Activator</Bundle-Activator>
                     <Export-Package>
                         com.esum.osgi.pilot.SayService*;version=${project.version}
                     </Export-Package>
                     <Import-Package>
                         *
                     </Import-Package>

                 </instructions>
             </configuration>
         </plugin>
     </plugins>
  </build>


Bundle에서 Properties 사용하기
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
         xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0">
       
  <cm:property-placeholder persistent-id="env" />

  <bean id="bundle-activator" class="com.esum.osgi.pilot.SayClient.Activator">
     <property name="nodeName" value="${node.id}"/>
  </bean>
  
  <reference id="tellMeService" availability="mandatory"
     activation="eager" interface="com.esum.osgi.pilot.SayService.TellMeMessage">
     <reference-listener ref="bundle-activator"
         bind-method="onBindService" unbind-method="onUnbindService" />
  </reference>

</blueprint>
OSGI ClassLoader

Which Mobile App Development Option is Better?

Different alternatives to native code development have their own advantages and philosophy behind. No one tool or approach can be clearly ma...