Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "OSGi R7 Remote Services between Python and Java"

(Created page with "This tutorial shows the use of[https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html Remote Services] and [https://travis-ci.org/ECF/Py4j-RemoteServicesPr...")
 
 
(51 intermediate revisions by the same user not shown)
Line 1: Line 1:
This tutorial shows the use of[https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html Remote Services] and [https://travis-ci.org/ECF/Py4j-RemoteServicesProvider Python.Java Distribution Provider] to create services between Python and Java.  By 'create services between Python and Java' what is meant is both service implementations written in Java...with Python consumers, and service implementations in Python with Java consumers.  The code presented below are examples, and everything about the examples (e.g. the service API, impl, and consumer code) can be replaced with one's own micro services.
+
==Introduction==
  
With OSGi R7 and [https://www.eclipse.org/ecf/NewAndNoteworthy_3.14.0.html ECF's Photon/3.14.0 implementation], it's also possible to use [https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html#d0e1407 Asynchronous Remote Services] between Python and Java.  This is also shown below.
+
[https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html OSGi Remote Services] have traditionally been declared, implemented, and consumed in Java.  For example [https://wiki.eclipse.org/Using_the_Bndtools_Remote_Services_Project_Templates this tutorial].  ECF's Photon release, however, includes a [https://github.com/ECF/Py4j-RemoteServicesProvider new distribution provider for connecting Java/OSGi and Python runtimes].
  
==Hello Service Interface==
+
In addition, a Python implementation of OSGi R7 RSA has recently been contributed to the [http://ipopo.readthedocs.io iPOPO framework].  [http://ipopo.readthedocs.io iPOPO ] is a pure Python implementation of much of OSGi, and iPOPO 0.8.0+ includes a pure-Python implementation of RSA.
  
Here is a Java Interface that defines the 'IHello' service
+
This tutorial shows the use of [https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html OSGi R7 Remote Services] and [https://github.com/ECF/Py4j-RemoteServicesProvider Python.Java Distribution Provider] to expose OSGi remote services both from Java->Python, and Python->Java.  The tutorial presents a sample remote service, but developers can use the same mechanisms to expose and consume arbitrary services between Python and Java.
  
 +
==Java Service Declaration==
 +
 +
IHello service declaration:
 +
<hr>
 
<source lang="java">
 
<source lang="java">
package org.eclipse.ecf.examples.hello;
 
 
 
import java.util.concurrent.CompletableFuture;
 
import java.util.concurrent.CompletableFuture;
 
 
import org.osgi.util.promise.Promise;
 
import org.osgi.util.promise.Promise;
  
/**
 
* Example remote service interface.  Has async methods (CompletableFuture<String> and Promise<String>
 
* return types), as defined by the
 
* <a href="https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html#d0e1407">Asynchronous Remote Services</a>
 
* specification.  As per the intent, when invoked remotely, these methods will immediately
 
* return a CompletableFuture or Promise that will subsequently return a result of declared type (String in below).
 
* If the osgi.basic.timeout service property is set, the CompletableFuture or promise will timeout
 
* after the given milliseconds.
 
*
 
*/
 
 
public interface IHello {
 
public interface IHello {
  
/**
+
    String sayHello(String from, String message);
* Synchronously provide 'from' and 'message' Strings to service, and receive a
+
 
* String response.
+
    CompletableFuture<String> sayHelloAsync(String from, String message);
+
 
* @param from a String identifying the sender
+
    Promise<String> sayHelloPromise(String from, String message);
* @param message a String message
+
* @return String response from remote service after synchronously invoking remote method
+
*/
+
String sayHello(String from, String message);
+
+
/**
+
* Asynchronously invoke remote method and provide String result via returned
+
* CompletableFuture.
+
*
+
* @param from a String identifying the sender
+
* @param message a String message
+
* @return CompletableFuture that invokes remote method asynchronously to complete. 
+
* Will throw java.util.concurrent.TimeoutException if response is not
+
* received in within timeout provided via osgi.basic.timeout service prop on imple
+
*/
+
CompletableFuture<String> sayHelloAsync(String from, String message);
+
+
/**
+
* Asynchronously invoke remote method and provide String result via returned
+
* Promise.
+
*
+
* @param from a String identifying the sender
+
* @param message a String message
+
* @return Promis that invokes remote method asynchronously to complete. 
+
* Will throw java.util.concurrent.TimeoutException if response is not
+
* received in within timeout provided via osgi.basic.timeout service prop on impl
+
*/
+
Promise<String> sayHelloPromise(String from, String message);
+
+
 
}
 
}
 
</source>
 
</source>
 +
<hr>
 +
[https://github.com/ECF/Py4j-RemoteServicesProvider/blob/master/examples/org.eclipse.ecf.examples.hello/src/org/eclipse/ecf/examples/hello/IHello.java IHello source with documentation].
  
==Python.Java Services  
+
This interface defines one synchronous method '''sayHello(String from, String message)''' and two async methods:  '''sayHelloAsync''', and '''sayHelloPromise'''. These are OSGi R7 asynchronous methods strictly because of the CompletableFuture and Promise return types and the presence of the '''osgi.async''' service intent in the Component properties.  As per the [https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html#d0e1407 Async Remote Services] specification, return types are interpreted by the distribution provider as async methods, and so will not block the calling thread even if the underlying communication is blocked or fails.
  
 +
==Java Service Implementation==
  
Once you have created a [https://wiki.eclipse.org/Bndtools_Support_for_Remote_Services_Development Workspace using the Remote Services template], it's now possible to use Bndtools project templates to create a new remote service API project, create an implementation of this remote service, create a consumer of the remote service, and run/test the implementation and consumer.
+
HelloImpl service implementation
 +
<hr>
 +
<source lang="java">
 +
@Component(immediate=true,enabled=false,property = { "service.exported.interfaces=*",
 +
"service.exported.configs=ecf.py4j.host",
 +
"osgi.basic.timeout:Long=50000",
 +
"service.intents=osgi.async"}) // osgi.async intent to get the async rs behavior
 +
public class HelloImpl implements IHello {
  
==Create a Remote Service API Project==
+
    @Override
 +
    public String sayHello(String from, String message) {
 +
        System.out.println("Java.sayHello called by "+from+" with message: '"+message+"'");
 +
        return "Java says: Hi "+from + ", nice to see you";
 +
    }
 +
    @Override
 +
    public CompletableFuture<String> sayHelloAsync(String from, String message) {
 +
        System.out.println("Java.sayHelloAsync called by "+from+" with message: '"+message+"'");
 +
        CompletableFuture<String> result = new CompletableFuture<String>();
 +
        result.complete("JavaAsync says: Hi "+from + ", nice to see you");
 +
        return result;
 +
    }
 +
    @Override
 +
    public Promise<String> sayHelloPromise(String from, String message) {
 +
        System.out.println("Java.sayHelloPromise called by "+from+" with message: '"+message+"'");
 +
        Deferred<String> deferred = new Deferred<String>();
 +
        deferred.resolve("JavaPromise says: Hi "+from + ", nice to see you");
 +
        return deferred.getPromise();
 +
    }
 +
}
 +
</source>
 +
<hr>
 +
[https://github.com/ECF/Py4j-RemoteServicesProvider/blob/master/examples/org.eclipse.ecf.examples.hello.javahost/src/org/eclipse/ecf/examples/hello/javahost/HelloImpl.java the full HelloImpl source with documentation].
  
In the new workspace there is a Remote Services API Project template to help create a Remote Service API projectTo use this template, select '''File->New->Bnd OSGi Project'''
+
Note the remote service properties specified in the @Component annotation. '''service.exported.interfaces=*''' is an OSGi standard property indicating that this service should be exported as a remote serviceThe '''service.exported.configs=ecf.py4j.host''' is another standard property indicating that this service should be exported via the Python.Java distribution provider. 
  
[[File:Bndtools.2.png]]
+
'''osgi.basic.timeout=Long:50000''' indicates that the remote method invocation for all methods in this interface should timeout after 50000ms/50s. This timeout can be set to any desired value and defaults to 30000ms (30s).
  
Select '''Remote Service API Project->Next'''
+
The '''service.intents=osgi.async''' indicates that the service methods with Promise and CompletableFuture  ([https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html#d0e1407 or Future or CompletionStage]) are Async Remote Services and so do not block.
  
Project Name:  '''org.example.remoteservice.api'''
+
==Launching via Bndtools Project Template==
  
Note:  this is a suggested name for the example project, when you use this template for creating your own remote service you can specify an appropriate project/bundle/package name.
+
With the ECF Photon/3.14.0 release, support has been added for using Bndtools to do remote service development.  Before doing the below please use [https://wiki.eclipse.org/Bndtools_Support_for_Remote_Services_Development these instructions for setting up a workspace using the ECF/bndtools.workspace template].
  
Choose '''Next->Finish'''. This will create a new project in your workspace named '''org.example.remoteservice.api'''
+
1. Create an Empty Bndtools Project in the workspace (of any name).
  
==Create a Remote Service Impl Project==
+
2. Choose File->New->Run Descriptor File (.bndrun) and select the **Python.Java Hello Example**
  
Select '''File->Next->Bnd OSGi Project->Remote Service Impl Project''' template
+
[[File:pyjavahello1.png]]
  
Project Name:  '''org.example.remoteservice.impl'''
+
3. Choose Next> and give some filename for the .bndrun file
  
Select '''Next'''. Under '''Template Parameters''' for the '''apipackage''' parameter specify the name of the API project created above (e.g. '''org.example.remoteservice.api''') and '''Next->Finish'''.
+
4. Open the created filename.bndrun file.
  
==Create a Remote Service Consumer Project==
+
5. Click the **Resolve** button on the lower right of the bndrun editor underneath the Run Requirements list.
  
Similar to the Impl project above, create a consumer project by selecting the '''Remote Service Consumer Project''' template.
+
6. Click Finish on the resolve window presented.
  
Once all three (API, Impl, Consumer) projects are created, the workspace should look something like this
+
7. Click the 'Debug OSGi' link in the upper right of the bndrun editor to start the example.
  
[[File:Bndtools.3.png]]
+
This should result in some console output similar to
 
+
==Create and Use Bnd Run Descriptor for Impl and Consumer==
+
 
+
In the Package Explorer select the impl project (e.g. '''org.example.remoteservice.impl'''), and then '''File->New->Run Descriptor File (.bndrun)'''.  Select the '''ECF Generic Distribution Provider''' template->Next, and give an appropriate File Name...e.g. '''impl''' and Finish.  Click '''Resolve''' under the '''Run Requirements''' section and then choose the '''Run OSGi''' or '''Debug OSGi''' icons in the upper right of the Resolve/Run.  This should result in a Console opening and output similar to the following in the console
+
  
 
<pre>
 
<pre>
____________________________
+
osgi> SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
Welcome to Apache Felix Gogo
+
SLF4J: Defaulting to no-operation (NOP) logger implementation
 
+
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
g! 14:05:38.659;EXPORT_REGISTRATION;exportedSR=[org.example.remoteservice.api.ExampleRemoteService];cID=StringID[ecftcp://slewis-lenovo:54390/server];rsId=1
+
Jul 09, 2018 5:06:56 PM py4j.GatewayServer fireServerStarted
 +
INFO: Gateway Server Started
 +
osgi> 17:07:48.611;EXPORT_REGISTRATION;exportedSR={org.eclipse.ecf.examples.hello.IHello}={service.intents=osgi.async, service.exported.configs=ecf.py4j.host, service.id=84, service.bundleid=4, service.scope=bundle, osgi.basic.timeout=50000, component.name=org.eclipse.ecf.examples.hello.javahost.HelloImpl, service.exported.interfaces=*, component.id=6};cID=URIID [uri=py4j://127.0.0.1:25333/java];rsId=1
 
--Endpoint Description---
 
--Endpoint Description---
 
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
 
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
 
   <endpoint-description>
 
   <endpoint-description>
    <property name="ecf.endpoint.id" value-type="String" value="ecftcp://slewis-lenovo:54390/server"/>
+
.. the rest of the endpoint description
    <property name="ecf.endpoint.id.ns" value-type="String" value="org.eclipse.ecf.core.identity.StringID"/>
+
    <property name="ecf.endpoint.ts" value-type="Long" value="1524171938628"/>
+
    <property name="ecf.rsvc.id" value-type="Long" value="1"/>
+
    <property name="endpoint.framework.uuid" value-type="String" value="45a4a861-3487-4089-a940-be622466a7bc"/>
+
    <property name="endpoint.id" value-type="String" value="937b3136-0864-4e3b-bf87-0462502eb1a5"/>
+
    <property name="endpoint.package.version.org.example.remoteservice.api" value-type="String" value="1.0.0"/>
+
    <property name="endpoint.service.id" value-type="Long" value="64"/>
+
    <property name="objectClass" value-type="String">
+
      <array>
+
        <value>org.example.remoteservice.api.ExampleRemoteService</value>
+
      </array>
+
    </property>
+
    <property name="remote.configs.supported" value-type="String">
+
      <array>
+
        <value>ecf.generic.server</value>
+
      </array>
+
    </property>
+
    <property name="remote.intents.supported" value-type="String">
+
      <array>
+
        <value>osgi.basic</value>
+
        <value>osgi.async</value>
+
        <value>osgi.private</value>
+
        <value>passByValue</value>
+
        <value>exactlyOnce</value>
+
        <value>ordered</value>
+
      </array>
+
    </property>
+
    <property name="service.imported" value-type="String" value="true"/>
+
    <property name="service.imported.configs" value-type="String">
+
      <array>
+
        <value>ecf.generic.server</value>
+
      </array>
+
    </property>
+
    <property name="service.intents" value-type="String" value="osgi.basic"/>
+
  </endpoint-description>
+
</endpoint-descriptions>
+
---End Endpoint Description
+
 
</pre>
 
</pre>
  
This debug output indicates that the ExampleRemoteServiceImpl was exported by the ECF RSA implementation and is ready to be used by a consumer.
+
==Launching via Apache Karaf==
  
===Consumer===
+
Using Karaf 4.2+ [https://wiki.eclipse.org/EIG:Install_into_Apache_Karaf see this page to install ECF Photon into Karaf].
  
Similar to the Impl described above, create a Bnd Run Descriptor for the consumer project, then resolve and Run/Debug OSGi.
+
1.  Install the Python.Java distribution provider and the Hello example:
 
+
If the Zeroconf discovery is enabled on your LAN, after a few seconds the following output should appear on the consumer's console
+
  
 
<pre>
 
<pre>
Welcome to Apache Felix Gogo
+
karaf@root()>feature:repo-add ecf
 +
karaf@root()>feature:repo-refresh ecf
 +
karaf@root()>feature:install -v ecf-rs-examples-python.java-hello
 +
</pre>
  
g! service responds=Hello ExampleRemoteServiceConsumer
+
This should result in some console output similar to
14:08:52.185;IMPORT_REGISTRATION;importedSR=[org.example.remoteservice.api.ExampleRemoteService];cID=StringID[ecftcp://slewis-lenovo:54390/server];rsId=1
+
 
 +
<pre>
 +
osgi> SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
 +
SLF4J: Defaulting to no-operation (NOP) logger implementation
 +
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
 +
Jul 09, 2018 5:06:56 PM py4j.GatewayServer fireServerStarted
 +
INFO: Gateway Server Started
 +
osgi> 17:07:48.611;EXPORT_REGISTRATION;exportedSR={org.eclipse.ecf.examples.hello.IHello}={service.intents=osgi.async, service.exported.configs=ecf.py4j.host, service.id=84, service.bundleid=4, service.scope=bundle, osgi.basic.timeout=50000, component.name=org.eclipse.ecf.examples.hello.javahost.HelloImpl, service.exported.interfaces=*, component.id=6};cID=URIID [uri=py4j://127.0.0.1:25333/java];rsId=1
 
--Endpoint Description---
 
--Endpoint Description---
 
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
 
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
 
   <endpoint-description>
 
   <endpoint-description>
    <property name="ecf.endpoint.id" value-type="String" value="ecftcp://slewis-lenovo:54390/server"/>
+
.. the rest of the endpoint description
    <property name="ecf.endpoint.id.ns" value-type="String" value="org.eclipse.ecf.core.identity.StringID"/>
+
    <property name="ecf.endpoint.ts" value-type="Long" value="1524171938628"/>
+
    <property name="ecf.rsvc.id" value-type="Long" value="1"/>
+
    <property name="endpoint.framework.uuid" value-type="String" value="45a4a861-3487-4089-a940-be622466a7bc"/>
+
    <property name="endpoint.id" value-type="String" value="937b3136-0864-4e3b-bf87-0462502eb1a5"/>
+
    <property name="endpoint.package.version.org.example.remoteservice.api" value-type="String" value="1.0.0"/>
+
    <property name="endpoint.service.id" value-type="Long" value="64"/>
+
    <property name="objectClass" value-type="String">
+
      <array>
+
        <value>org.example.remoteservice.api.ExampleRemoteService</value>
+
      </array>
+
    </property>
+
    <property name="remote.configs.supported" value-type="String">
+
      <array>
+
        <value>ecf.generic.server</value>
+
      </array>
+
    </property>
+
    <property name="remote.intents.supported" value-type="String">
+
      <array>
+
        <value>osgi.basic</value>
+
        <value>osgi.async</value>
+
        <value>osgi.private</value>
+
        <value>passByValue</value>
+
        <value>exactlyOnce</value>
+
        <value>ordered</value>
+
      </array>
+
    </property>
+
    <property name="service.imported.configs" value-type="String">
+
      <array>
+
        <value>ecf.generic.client</value>
+
      </array>
+
    </property>
+
    <property name="service.intents" value-type="String" value="osgi.basic"/>
+
  </endpoint-description>
+
</endpoint-descriptions>
+
---End Endpoint Description
+
 
</pre>
 
</pre>
  
Note the line in the output:
+
This output indicates that the HelloImpl service has been registered and exported for remote access from Python.
 
+
<pre>
+
g! service responds=Hello ExampleRemoteServiceConsumer
+
</pre>
+
  
This indicates that the remote service was discovered, the endpoint description imported, and the proxy injected into the ExampleRemoteServiceConsumer.  Then the ExampleRemoteServiceConsumer.activated method was called by DS, which is implemented with a call to the ExampleRemoteService.hello remote service method. 
+
==Launching Python Framework==
  
Breakpoints can be set in the Impl, and/or Consumer projects to inspect what's happening at runtime. The example code can also be refactored/renamed/modified.
+
See [https://ipopo.readthedocs.io/en/1.0.1/tutorials/rsa_pythonjava.html this page from the iPOPO documentation] for starting the Python-side sample code.

Latest revision as of 15:07, 27 January 2021

Introduction

OSGi Remote Services have traditionally been declared, implemented, and consumed in Java. For example this tutorial. ECF's Photon release, however, includes a new distribution provider for connecting Java/OSGi and Python runtimes.

In addition, a Python implementation of OSGi R7 RSA has recently been contributed to the iPOPO framework. iPOPO is a pure Python implementation of much of OSGi, and iPOPO 0.8.0+ includes a pure-Python implementation of RSA.

This tutorial shows the use of OSGi R7 Remote Services and Python.Java Distribution Provider to expose OSGi remote services both from Java->Python, and Python->Java. The tutorial presents a sample remote service, but developers can use the same mechanisms to expose and consume arbitrary services between Python and Java.

Java Service Declaration

IHello service declaration:


import java.util.concurrent.CompletableFuture;
import org.osgi.util.promise.Promise;
 
public interface IHello {
 
    String sayHello(String from, String message);
 
    CompletableFuture<String> sayHelloAsync(String from, String message);
 
    Promise<String> sayHelloPromise(String from, String message);
}

IHello source with documentation.

This interface defines one synchronous method sayHello(String from, String message) and two async methods: sayHelloAsync, and sayHelloPromise. These are OSGi R7 asynchronous methods strictly because of the CompletableFuture and Promise return types and the presence of the osgi.async service intent in the Component properties. As per the Async Remote Services specification, return types are interpreted by the distribution provider as async methods, and so will not block the calling thread even if the underlying communication is blocked or fails.

Java Service Implementation

HelloImpl service implementation


@Component(immediate=true,enabled=false,property = { "service.exported.interfaces=*",
"service.exported.configs=ecf.py4j.host",
"osgi.basic.timeout:Long=50000",
"service.intents=osgi.async"}) // osgi.async intent to get the async rs behavior
public class HelloImpl implements IHello {
 
    @Override
    public String sayHello(String from, String message) {
        System.out.println("Java.sayHello called by "+from+" with message: '"+message+"'");
        return "Java says: Hi "+from + ", nice to see you";
    }
    @Override
    public CompletableFuture<String> sayHelloAsync(String from, String message) {
        System.out.println("Java.sayHelloAsync called by "+from+" with message: '"+message+"'");
        CompletableFuture<String> result = new CompletableFuture<String>();
        result.complete("JavaAsync says: Hi "+from + ", nice to see you");
        return result;
    }
    @Override
    public Promise<String> sayHelloPromise(String from, String message) {
        System.out.println("Java.sayHelloPromise called by "+from+" with message: '"+message+"'");
        Deferred<String> deferred = new Deferred<String>();
        deferred.resolve("JavaPromise says: Hi "+from + ", nice to see you");
        return deferred.getPromise();
    }
}

the full HelloImpl source with documentation.

Note the remote service properties specified in the @Component annotation. service.exported.interfaces=* is an OSGi standard property indicating that this service should be exported as a remote service. The service.exported.configs=ecf.py4j.host is another standard property indicating that this service should be exported via the Python.Java distribution provider.

osgi.basic.timeout=Long:50000 indicates that the remote method invocation for all methods in this interface should timeout after 50000ms/50s. This timeout can be set to any desired value and defaults to 30000ms (30s).

The service.intents=osgi.async indicates that the service methods with Promise and CompletableFuture (or Future or CompletionStage) are Async Remote Services and so do not block.

Launching via Bndtools Project Template

With the ECF Photon/3.14.0 release, support has been added for using Bndtools to do remote service development. Before doing the below please use these instructions for setting up a workspace using the ECF/bndtools.workspace template.

1. Create an Empty Bndtools Project in the workspace (of any name).

2. Choose File->New->Run Descriptor File (.bndrun) and select the **Python.Java Hello Example**

Pyjavahello1.png

3. Choose Next> and give some filename for the .bndrun file

4. Open the created filename.bndrun file.

5. Click the **Resolve** button on the lower right of the bndrun editor underneath the Run Requirements list.

6. Click Finish on the resolve window presented.

7. Click the 'Debug OSGi' link in the upper right of the bndrun editor to start the example.

This should result in some console output similar to

osgi> SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Jul 09, 2018 5:06:56 PM py4j.GatewayServer fireServerStarted
INFO: Gateway Server Started
osgi> 17:07:48.611;EXPORT_REGISTRATION;exportedSR={org.eclipse.ecf.examples.hello.IHello}={service.intents=osgi.async, service.exported.configs=ecf.py4j.host, service.id=84, service.bundleid=4, service.scope=bundle, osgi.basic.timeout=50000, component.name=org.eclipse.ecf.examples.hello.javahost.HelloImpl, service.exported.interfaces=*, component.id=6};cID=URIID [uri=py4j://127.0.0.1:25333/java];rsId=1
--Endpoint Description---
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
  <endpoint-description>
.. the rest of the endpoint description

Launching via Apache Karaf

Using Karaf 4.2+ see this page to install ECF Photon into Karaf.

1. Install the Python.Java distribution provider and the Hello example:

karaf@root()>feature:repo-add ecf
karaf@root()>feature:repo-refresh ecf
karaf@root()>feature:install -v ecf-rs-examples-python.java-hello

This should result in some console output similar to

osgi> SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Jul 09, 2018 5:06:56 PM py4j.GatewayServer fireServerStarted
INFO: Gateway Server Started
osgi> 17:07:48.611;EXPORT_REGISTRATION;exportedSR={org.eclipse.ecf.examples.hello.IHello}={service.intents=osgi.async, service.exported.configs=ecf.py4j.host, service.id=84, service.bundleid=4, service.scope=bundle, osgi.basic.timeout=50000, component.name=org.eclipse.ecf.examples.hello.javahost.HelloImpl, service.exported.interfaces=*, component.id=6};cID=URIID [uri=py4j://127.0.0.1:25333/java];rsId=1
--Endpoint Description---
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
  <endpoint-description>
.. the rest of the endpoint description

This output indicates that the HelloImpl service has been registered and exported for remote access from Python.

Launching Python Framework

See this page from the iPOPO documentation for starting the Python-side sample code.

Back to the top