Riena Project > Riena Remote Services
Riena Remote Services
Riena has inside itself own Remote Services component that we encourage people to use when they are building applications based on Riena. Since there are also other projects that have their own Remote Services component, we sometimes confuse people what distinguishes our implementation from others and why we implemented our own.
This page intends to highlight the goals and reasons for what we are doing.
There are multiple goals that we indentified from past projects that we wanted to be able to do with a Remote Service layer in OSGI.
All components identify themselves by exposing an interface and registering in some kind of registry. That is true for local as well as for remote components. For local components that is pretty much what OSGi Services does. For remote components that is OSGi Services plus something more to do the remoting. Still local and remote components are Services.
We want to be able to access services no matter whether they are local or remote. We want to use the same APIs, the same way of getting a reference or making a call. The reason is that we want to be able to shift services from the remote to the local JVM without changing the code of the caller. A good example here is the use case is whether the Riena Client has an internet connection or not. If it has a connection call the remote service, if it hasnt call the local service. So a detection component could detect the availability of an internet connection and start/stop the required services. The calling components remain unchanged.
Riena is made for enterprise applications and it is highly likely that there are thousands of clients running at the same time. The Riena Client does not need to connect at starting time until it makes the first call that calls a Remote Service and it shouldnt. Open connections into the server infrastructur not only block ressources (i.e. threads) but they are also a danger for attackers (an attacker would open more and more connections) and for that reason normally a server farm will and should disconnect a caller after the call is finished.
That also allows you to hibernate your computer at work (with the Riena client running), and then bring it up again at home with a completely different network setup and continue in the client where you left. Since you have no standing connection you dont need to reconnect.
Since large applications will not only have quit a number of users they will also have a large number of Remote Services. 100 would be the absolut minimum, more likely 300 or more. While discovery is something we once considered and it is sure nice if a client gets its remote service proxy injected from life instances on the server, we felt this will not work well for us. Why discover 300 services every time you log in ? Would the discovery component itself require a lot of the bandwith that could already be minimal if the client uses GPRS ? If you have multiple hardware boxes that host your Remote Services how would you do that anyway ? So we wanted a communication layer that does not require us to use Discovery ?
State is a context that a called services holds that the caller can later refer to. Say you do a search, if the service that performs the search holds a state you can later refer to that search and page forward and get the next 10 records.
There is a little difference between calling a local and a remote service. While with a local service you always call that service directly (by getting the instance of the service) for a remote service you call the proxy which then calls the Remote Service. It turns out is most effective if you assume that you are not always getting the same remote service instance in each call. That is pretty much the paradigma that Webservices are following. Webservices are also often stateless and scale so well because they are stateless. Every call can go to a different instance of the Webservice.
On the first look that distinguishes remote services from local services but its more complicated than that. If you use a local service, since you access the service instance, you could assume it can hold a state. Because of the dynamic structure of OSGi the service could go down and be replace by another instance at anytime. Would you still call the original instance (which I is wrong) or would you then call the new service instance and then all the state is gone ? I think because of the dynamic structure of OSGi Service we often treat local OSGi Service as if they cannot hold a state. And that is good because it makes them more robust. Also since a service knows nothing about the caller what would it do about state if two components are doing a search ? For Remote Service it is good if they keep no state because than they can go down at any time and the remote service call is routed to another hardware box which also hosts this Remote Service.
Note: And of course there are ways to route client calls to the same Remote Service instance. Its just not a good idea because it make the system less robust. Thats why we wanted avoid them.
Transparent User Context
Riena use Equinox Security which uses JAAS and that way a Riena client can authenticate against a central authority. Now that makes it more complicated to have a transparent access to local and remote services because each service might want to find out for which user (Subject or Principal in Java) it is performing a call. This information becomes available when the client is logged on. On the client it is relativly easy because a local service supplies this information. Making a remote call this information has to be transferred too in a safe manner. Riena uses a sessionid for that. It gets the sessionid when it authenticates and all Remote Services are transferring this sessionid automatically. This is taken care off by the Remote Service component and does not require extra action from the programmer. So a Remote Service can also find out which user it is performing a method for and in the same way as a local component is doing it.
The same mechanisme is used for permissions. If a services needs to find out if a user has the permission to perform a certain service it can check the permissions. They are retrieved using the Subject by the underlying Riena framework.
From past experience we felt it to be very handy and useful if we can transport binary attachments as part of the business objects. Say you get a customer record with multiple properties and various objects and one of the objects is a JPG image with a picture of that person. Rather than using filetransfer or direct HTTP communication to retrieve this kind of data we wanted the binary files (JPGs, PDFs, Office documents) as part of the business object to which they belong.
A Riena Rich Client always gives the enduser the feeling he is accessing a local application (which he does) and the user forgets that the data is remote. This requires that if a Remote Service call takes longer (i.e. we transfer a large attachment) that we can supply feedback on what is happing. We wanted the ability to show a ProgressMonitor as data is transferred so the user can see that the application is not dead but transferring data and how far it got. This is important since transfer time can vary depending on how the client is connected to the network.
We tried a number of protocols to serialize Java objects for calling remote services and we also came accross the protocol Hessian from Caucho.com. It has a very small footprint (267 KB), it can serialize nearly (with some exceptions) every Java object (no Serializable needs to be implemented) and it does not require configuration like SOAP for the individual objects. The protocol itself is also very compact compared to SOAP and we have used it in the past for a real large enduser count (> 30000 enduser) and verified that it is a good choice in performance and bandwith for LAN,DSL,UMTS and GPRS. So that is something we feel confident will work and we choose it to be our prime protocol but not necessarily the only.
We plan to also have a second protocol (SOAP) that would not be a prime choice for client server communication but for communication from the server to third party services.
With the above goals in mind we decided to have our own implementation as part of Riena. Nothing stops any user of Riena to use a different Remote Service component (there are a number of them out there) but we think ours is best for the above goals. Others either dont have these goals or they have contradicting goals.
So just to be clear, no component (in or outside Riena) is bound to only work with Riena communication. All components of Riena that are using Remote Services are indeed calling local OSGi Services that contain the Remote Service Proxy. So any framework that could generate a proxy (and most do) could register that as a local OSGi Service and it should all work. However some the above Goals might not be fullfilled by a alternative solution. So for example Attachments, Monitoring transfers or Transparent user context are good candidates that might a little different with other communication layers. Possibly other communication layers could be enhanced to address missing goals.