Skip to main content
Jump to: navigation, search

Difference between revisions of "Riena/Getting started with Remote Services"

m (Getting Started with Remote Service: fixed typos, put notes into boxes)
m (Nudged all sections up one level)
Line 1: Line 1:
[[Riena_Project | Riena Project]] > Getting Started with Remote Service
+
== The Idea of Remote Services in Riena ==
 
+
== Getting Started with Remote Service ==
+
 
+
=== 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.
 
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.
  
Line 12: Line 8:
 
These client OSGi services with the embedded proxy are either created through an API (RemoteServiceFactory) or through Declarative Service (RemoteServiceBuilder).
 
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 ===
+
== 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:
 
This example of a bundle activator shows how an OSGi service becomes a Web Service in Riena communication:
 
<pre>
 
<pre>
Line 46: Line 42:
 
The protocol property "hessian" is only indirectly translated into the path segment "/hessian". What really happens is that the Riena Communication Publisher asks the Hessian Publisher to publish the OSGi service. The Hessian Publisher chooses to add a path segment called /hessian before the actual Web Service URL. So it's not mandatory that the two values be the same or that a publisher add a path segment for that matter. However this behaviour makes URLs more unique, since it avoids conflicts between publishers.</small>
 
The protocol property "hessian" is only indirectly translated into the path segment "/hessian". What really happens is that the Riena Communication Publisher asks the Hessian Publisher to publish the OSGi service. The Hessian Publisher chooses to add a path segment called /hessian before the actual Web Service URL. So it's not mandatory that the two values be the same or that a publisher add a path segment for that matter. However this behaviour makes URLs more unique, since it avoids conflicts between publishers.</small>
  
=== Accessing the remote OSGi Service ===
+
== 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:
 
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:
  
Line 79: Line 75:
 
public void start(BundleContext context) throws Exception {
 
public void start(BundleContext context) throws Exception {
 
ServiceReference pingPongRef = context.getServiceReference(IPingPong.ID);
 
ServiceReference pingPongRef = context.getServiceReference(IPingPong.ID);
if (pingPongRef == null) {
+
if (pingPongRef = null) {
 
return;
 
return;
 
}
 
}
 
try {
 
try {
 
       IPingPong pingPong = (IPingPong) context.getService(pingPongRef);
 
       IPingPong pingPong = (IPingPong) context.getService(pingPongRef);
    if (pingPong == null) {
+
    if (pingPong = null) {
 
  return;
 
  return;
 
    }
 
    }
Line 111: Line 107:
 
In this example, IPingPong.ID is equivalent to IPingPong.class.getName().</small>
 
In this example, IPingPong.ID is equivalent to IPingPong.class.getName().</small>
  
=== Starting / Stoping OSGi Services ===
+
== Starting / Stoping OSGi Services ==
==== Starting ====
+
=== Starting ===
 
Riena communication publishes an OSGi service as a Web Service Endpoint as soon as the bundle containing the services is started. Say you use the sample as described above. Then the status of the started bundles looks like this:
 
Riena communication publishes an OSGi service as a Web Service Endpoint as soon as the bundle containing the services is started. Say you use the sample as described above. Then the status of the started bundles looks like this:
 
<pre>
 
<pre>
Line 169: Line 165:
  
  
==== Stopping ====
+
=== Stopping ===
 
Say you stop the bundle that started the OSGi service for this Web Service Endpoint:
 
Say you stop the bundle that started the OSGi service for this Web Service Endpoint:
 
<pre>
 
<pre>

Revision as of 09:45, 24 February 2009

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 web service endpoint. This is as simple as adding new properties when registering the OSGi service.

On the client that wants to remotely access such a service, 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:

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 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: Riena RemoteService on Server.png

Note: The protocol property "hessian" is only indirectly translated into the path segment "/hessian". What really happens is that the Riena Communication Publisher asks the Hessian Publisher to publish the OSGi service. The Hessian Publisher chooses to add a path segment called /hessian before the actual Web Service URL. So it's not mandatory that the two values be the same or that a publisher add a path segment for that matter. However this behaviour makes URLs more unique, since it avoids conflicts between publishers.

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:

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.

So once you have done that, calling is as simple as calling a local OSGi Service:

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: Riena RemoteService on Client.png

Note: In this example, IPingPong.ID is equivalent to IPingPong.class.getName().

Starting / Stoping 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 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 this link [http://localhost/hessian/PingPongWS] again shows:

call received from browser, no remote service registered with this URL

No Web Service Endpoint for this URL.

Back to the top