Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Riena/Getting started with Remote Services
{{#eclipseproject:rt.riena}}
The Idea of Remote Services in Riena
Equinox and OSGi already have an established simple way for registering Java components as OSGi services. These services maintain their own lifecycle. They can be looked up in the central OSGi service registry. Afterwards, a method on the service can be invoked as on any other Java instance.
Riena makes OSGi services available outside the current JVM by publishing them as a web-service endpoint. This is as simple as adding new properties when registering the OSGi service.
On the client wanting to access such a service remotely, a proxy is registered as an OSGi service in the client JVM. The component on the client that wants to use the remote OSGi service then calls the OSGi service in the local (client) JVM, and the proxy transports the request and response between client and server. These client OSGi services with the embedded proxy are either created through an API (RemoteServiceFactory) or through Declarative Service (RemoteServiceBuilder).
Publishing an OSGi Service as Web Service
This example of a bundle activator shows how an OSGi service becomes a Web Service in Riena communication:
// org.eclipse.riena.communication.sample.pingpong.server public class Activator implements BundleActivator { private ServiceRegistration pingPongReg; public void start(BundleContext context) throws Exception { PingPong pingPong = new PingPong(); Hashtable<String, String> properties = new Hashtable<String, String>(3); properties.put("riena.remote", "true"); properties.put("riena.remote.protocol", "hessian"); properties.put("riena.remote.path", "/PingPongWS"); pingPongReg = context.registerService(IPingPong.ID, pingPong, properties); } public void stop(BundleContext context) throws Exception { pingPongReg.unregister(); pingPongReg = null; } }
Riena Communication tracks all services as they are published (and unpublished). If it finds a property riena.remote=true, then it tries to publish this OSGi service as a web service.
In this case the PingPongService is made available under the URL "http://localhost/hessian/PingPongWS". If, for some reason, the Activator's stop method is called and the service is unregistered, then the web service endpoint is also unpublished and therefore is no longer available.
Here is a picture that illustrates the process:
Accessing the remote OSGi Service
For the client to access an OSGi Service running on the server, we have to create the corresponding web-service proxy on the client and register it as an OSGi service:
// org.eclipse.riena.communication.sample.pingpong.client.config public class Activator implements BundleActivator { private IRemoteServiceRegistration pingPongReg; public void start(BundleContext context) throws Exception { RemoteServiceFactory rsf = new RemoteServiceFactory(); String url = "http://localhost/hessian/PingPongWS"; String protocol = "hessian"; pingPongReg = rsf.createAndRegisterProxy(IPingPong.class, url, protocol); } public void stop(BundleContext context) throws Exception { if (pingPongReg != null) { pingPongReg.unregister(); pingPongReg = null; } } }
A fixed URL is bound to a protocol and an interface. RemoteServiceFactory creates the proxy and registers the OSGi Service.
Once you have done that, calling is as simple as calling a local OSGi Service:
// org.eclipse.riena.communication.sample.pingpong.client public class Activator implements BundleActivator { public void start(BundleContext context) throws Exception { ServiceReference pingPongRef = context.getServiceReference(IPingPong.ID); if (pingPongRef = null) { return; } try { IPingPong pingPong = (IPingPong) context.getService(pingPongRef); if (pingPong = null) { return; } Ping ping = new Ping(); ping.setText("I ping you and you pong me"); Pong pong = pingPong.ping(ping); System.out.println("PingPong::Client:: " + pong); } finally { context.ungetService(pingPongRef); } } public void stop(BundleContext context) throws Exception { } }
Here is a picture that illustrates what happens behind the scenes:
Starting / Stopping OSGi Services
Starting
Riena communication publishes an OSGi service as a Web Service Endpoint as soon as the bundle containing the services is started.
Say you have three bundles: client, common and server. The common bundle contains your service interface. In order to get a Riena example running you need to do the following steps:
- add a dependency to the org.eclipse.riena.communication.core bundle in the common's bundle MANIFEST (add this bundle to the "Required Plug-ins" section)
- configure your server side osgi launch configuration. Add -Dorg.eclipse.equinox.http.jetty.http.port=8080 to the VM arguments and add the bundle org.eclipse.equinox.http.jetty to your launch configuration. Press add required bundles and start you server.
- Important: we use hessian to serialize the classes being transfered between client and server. To avoid the "IInterface is not visible from class loader" exception and make this work properly, you must add the next two things to the bundle containing the common data model:
- Eclipse-RegisterBuddy: org.eclipse.riena.communication.core to the MANIFEST.MF (buddy loading details)
- a dependency to org.eclipse.riena.communication.core
Say you use the sample as described above. Then the status of the started bundles looks like this:
ss Framework is launched. id State Bundle 0 ACTIVE org.eclipse.osgi_3.3.0.v20070530 1 ACTIVE org.eclipse.core.contenttype_3.2.100.v20070319 2 ACTIVE org.eclipse.riena.communication.console_1.0.0.M1 3 ACTIVE org.eclipse.equinox.common_3.3.0.v20070426 4 ACTIVE org.eclipse.equinox.registry_3.3.0.v20070522 5 ACTIVE org.eclipse.core.jobs_3.3.0.v20070423 6 ACTIVE org.eclipse.riena.communication.core_1.0.0.M1 7 ACTIVE org.eclipse.osgi.services_3.1.200.v20070605 8 ACTIVE org.eclipse.riena.communication.publisher.hessian_1.0.0.M1 9 ACTIVE org.eclipse.equinox.cm_1.0.0.qualifier 10 ACTIVE org.apache.commons.logging_1.0.4.v200706111724 11 ACTIVE com.caucho.hessian_3.1.3 12 ACTIVE org.eclipse.equinox.http.registry_1.0.0.v20070608 13 ACTIVE org.apache.log4j_1.2.8.qualifier 14 ACTIVE org.eclipse.equinox.http.jetty_1.0.0.v20070607 15 ACTIVE org.eclipse.riena.communication.sample.pingpong.common_1.0.0.M1 16 ACTIVE org.eclipse.riena.communication.sample.pingpong.server_1.0.0.M1 17 ACTIVE org.eclipse.equinox.log_1.1.0.qualifier 18 ACTIVE javax.servlet_2.4.0.v200706111738 19 ACTIVE org.eclipse.riena.communication.publisher_1.0.0.M1 20 ACTIVE org.eclipse.core.runtime_3.3.100.v20070530 21 ACTIVE org.eclipse.riena.core_1.0.0.M1 22 ACTIVE org.eclipse.equinox.http.servlet_1.0.0.v20070606 23 ACTIVE org.mortbay.jetty_5.1.11.v200706111724 24 ACTIVE org.eclipse.core.runtime.compatibility.auth_3.2.100.v20070502 25 ACTIVE org.eclipse.equinox.preferences_3.2.100.v20070522 26 ACTIVE org.eclipse.equinox.app_1.0.0.v20070606
Starting one of the published OSGi services triggered this debug message in the console:
Riena::ServicePublishEventDispatcher:: DEBUG: service endpoints count: 1 Riena:Communication::HessianRemoteServicePublisher:: DEBUG: published web service. protocol=hessian, url=http://localhost/hessian/PingPongWS, interface=org.eclipse.riena.communication.sample.pingpong.common.IPingPong
So clicking on this link http://localhost/hessian/PingPongWS will open a page in the browser that says something like this:
calls protocol=hessian, url=http://192.168.14.51/hessian/PingPongWS, interface=org.eclipse.riena.communication.sample.pingpong.common.IPingPong
which is the default message if a Web Service Endpoint (hessian) is opened in the browser.
Note: And before you ask. It only displays the interface if client and server are on the same machine. We don't want to expose that kind of information in a production environment
Note: There is a problem in the current implementation that the URL displayed in the console does not show the webservice port. So http://localhost/hessian/PingPongWS might also mean you have to enter http://localhost:8080/hessian/PingPongWS into your browser's url address field.
Stopping
Say you stop the bundle that started the OSGi service for this Web Service Endpoint:
osgi> stop 16
stops the OSGi service and Riena communication automatically unpublishes the Web Service Endpoint
Riena:communication::HessianRemoteServicePublisher:: DEBUG: unpublished web service. protocol=hessian, url=http://localhost/hessian/PingPongWS, interface=org.eclipse.riena.communication.sample.pingpong.common.IPingPong Riena:communication::HessianRemoteServicePublisher:: DEBUG: web service count: 1 Riena::ServicePublisherHessian:: DEBUG: service endpoints count: 1
> ss
... 16 RESOLVED org.eclipse.riena.communication.sample.pingpong.server_1.0.0.M1 ...
Clicking on http://localhost/hessian/PingPongWS http://localhost/hessian/PingPongWS again shows:
call received from browser, no remote service registered with this URL
No Web Service Endpoint for this URL.