I've been working on an enhancement to Jini servce lookup in my reef project over on jini.org. I've still got more work to do before getting to the proposal stage. Here's where I'm at.
The Jini service lookup specification and implementation present in the ServiceRegistrar presents some interesting issues for large numbers of services, all of which might be of interest to desktop environments.
method returns a ServiceMatches object that then provides access to an array of
ServiceItem Objects. The ServiceItem class has no accessor methods, and just provides fields with access to the unmarshalled form of the service registration data values, namely the ServiceID, an Entry and service object.
What happens with this implementation is that if a ServiceTemplate matches more than just a couple of services, a whole bunch of code downloads can occur and a lot of time can elapse while the service code is downloaded and the service registration objects are instantiated. This API doesn't provide any real flexibility in controlling when unmarshalling occurs or which values are unmarshalled.
Over on my reef project at jini.org, I'm trying to deal with a number of things related to service lookup.
I have a collection of about 12 services that are ran simultaneously as part of a larger application framework. In a recent customer deployment, we would have 4 of machines running this 12 services. Each of the services have 2 or more serviceUIs that are advertised. One for managing the service's Jini configuration (an AdminUI) and one for the MainUI. This results in about 25 total UI instances per machine. There are about 15 distinct jar files associated with these 12 services that would need to be downloaded too.
With 4 machines, that means about 100 serviceUIs and about 60 download requests using ServiceRegistrar to lookup these services. The kicker is that some of the users of these clients connect with a cellphone dialup or similar low bandwidth connection to access the mainUI for some of these services.
I was confronted with a real need to greatly reduce and explicitly control the moment of downloading code. The client computers are not big computers either, so I really need to control the total number of live objects too.
Some Background on Service Lookup Variations
An intesting collection of discussions have happened on the jini-users mailing list over the years regarding variations on service lookup. Over the years a number of different people have asked about controlling service lookup more explicitly with pattern matching and other requests. The standing theme of many of the replies has always been, "Create a service which does what you need, and have the client use that service to do the lookups."
This is largely a valid response from a number of perspectives, but it doesn't make it any easier to get the results one might really need. It is an architecture which uses existing functionality and extends it to be more useful. The fact that there is some additional work involved in creating and deploying another service creates some barries however.
The Issues I'd Like to Resolve
There are a number of barries that ServiceRegistrar presents to the user. Some of these are part of past implementation details. Some of the barriers are only in place now because of new additions to Jini, such as JERI. Here's my view on the important things.
In the world of RMI, object passed between JVMs are marshalled implicitly through serialization or explicitly as MarshalledObject instances into a network transportable form. On the other end, they must be unmarshalled and instantiated back into live objects. Serialization doesn't carry codebase information with the object. So, if both ends don't know about the same version (serial version id) of the class, there
will be problems. The java.rmi.MarshalledObject class provides support for use of a codebase annotation that allows the receiving JVM to download code to have the correct version of the class active. In the typical deployment, the contract of use between two JVMs will be manifested in an interface. The downloaded class is just the implementation of the interface(s).
One of the issues with the service lookup/matching specification is that it doesn't demand marshalling it just says that lookup comparisons must be equivalent to MarshalledObject.equals() behavior. There are some interesting reasons why one might choose to not specify the required implementation. But, this, to me, leaves the door opened for lookup service implementations that won't use marshalling, and thus won't provide the client the opportunity to control the unmarshalling.
The Jini Extensible Remote Invocation (JERI) stack implemented in Jini2.0 provides a nice, plugable stack of remote method invocation control. You can start at the bottom with endpoints that provide transport control. Next up the stack, the invocation layer provides a way to translate between invocation paradigms on each end. This allows native java objects on one end to be translated into XML based messaging for instance. Next up the stack is the Exporter (service end) and Proxy Preparer (client end). These two objects present the final remote call transport contract to each end.
The BasicILFactory class provides the ability to supply MethodConstraints
to dictate what types of criteria the transport, invocation and client environments must meet to use the service. There are some interesting interactions here from the perspective that you can tell the invocation layer that your service needs to have a secure transport, with the endpoint implementation providing this guarentee. There are some interactions through the layers that make it possible for the question of "is this constraint met?" to be answered. This happens through a number of paths of execution from both the client side (proxy preparation) and the service side (proxy verification and invocation layer validation during inbound calls).
I'd like for service lookup results to allow the client software to query the service for its requirements so that a first time use of a service could allow the client to assert the required constraint implementations through dialogs or wizards that would help users understand more about the service requirements. Currently, these implementation details are manually managed and the deployment environment is assumed to be managed by well trained people who most likely already know the requirements that need to be met.
Login identities for authentication and authorization are one barrier, but there are other constraints that the user can meet with explicit control of their environment.
One of the common question about using service lookup on the jini-users mailing list has involved more sophisticated filtering of returned results. In particular, partial string matches as well as "and" vs "or" matching logic of the ServiceTemplate fields has been discussed.
This basic filtering request has come up in the Javaspaces realm too. There are a wide
diversity of potential needs for matching/discovering/filtering in the real world. There
needs to be some more flexibility in matching. One of the problems is that matching in
the server to control returned results is going to be limited because of the desires to keep user supplied code out of the lookup service to manage integrity and reliability issues.
The current ServiceTemplate provides exact matching using simple equals() comparisons.
I'd like to extend this ability to include some more explicit control over the results of matching to better control bandwidth based performance. It would be nice to get 1 result efficiently (getting access to a single well known service), but not be burdened by the API when 100 results (all services that provide a serviceUI) would make sense as well.
One of the primary concerns that I've sensed from others is that changing service lookup APIs at a basic level is problematic, because it will affect the interworking of services and clients. My plan of action is to manage this issue by creating a new ServiceDiscovery Manager like API that wraps both the ServiceRegistrar interface use and my ServiceLookup interface use, under the covers, into a new API for service lookup. This API will make ServiceRegistrar implementations and ServiceLookup implementations usable with the same, new API. There will be a few issues that need to be worked through though.
I'll be trying to put together a buildable version of reggie with ServiceLookup extensions in it next. Tearing apart the existing build and breaking it down into just building reggie will take a bit of time for the disection of the ant files. Once I have the build working outside of the JTSK build, then I'll be ready to start supporting a trial version that will be more consumable then what is currently in CVS.
I agree with the sentiment. I think the whole "active server" side of Jini, filtering, searching, batch ops etc is an interesting area for exploration/expansion. For some operations, more powerful accounting methods will be needed (eg limiting CPU/actual time used).
Sorry but I am just starting on all of this, so some of what you sad whent over my head. But I have always wandered about the dependency to RMI imposed by java.rmi.MarshalledObject. And as I understand the sun implementation of the lookup server (and the registrar) requires RMI.
Since you are deploying to small devices I beleive that RMI should be a big problem.
Shouldn't we have a "standard" lightweight lookup mechanism with no RMI (the registrar should not use RMI also). This is not a proposal for a protocol especification, however I see no alternative until a registrar is delivered a protocol is the only way.
> Sorry but I am just starting on all of this, so some of > what you sad whent over my head. But I have always > wandered about the dependency to RMI imposed by > java.rmi.MarshalledObject. > And as I understand the sun implementation of the lookup > server (and the registrar) requires RMI.
The dependency on RMI is simply the fact that Jini capitalizes on mobile code. This is a difference that many people don't seem to get. The point of Jini is that services can evolve independently from the clients. The clients download the implementation of the services "interface" and use that to access the service.
There are of course many other RPC and messaging technologies which don't use RMI. The JERI stack provided in Jini2.0 is a way to eliminate the outward use of RMI. There are a world of possibilities in this regard. For instance, you might deploy a java class, as a service, which is downloaded by the client, but which uses modbus to communicate with a small RTU. The client sees a java method invocation interface, and has no knowledge that modbus is the underlying transport. It's also possible to do this with other protocols such as SOAP.
> Since you are deploying to small devices I beleive that > RMI should be a big problem.
J2ME CLDC and CDC platforms don't have support for code downloading. But, that doesn't mean that they can't support pseudo serialization by transporting the field values of well known classes which are already available on the small devices, ready for instantiation. This would require a custom/proprietary invocation layer (in the JERI nomenclature). This is where a lot of people don't get Jini and the power of JERI.
It is possible for larger java platforms, which support serialization, to provide dynamic downloading of code. But, where that is not possible, its also possible to have dynamically created instances of well known classes. The biggest issue, from my perspective, is that there is no attempt of standardization going on in this space.
> Shouldn't we have a "standard" lightweight lookup > mechanism with no RMI (the registrar should not use RMI > also). This is not a proposal for a protocol > especification, however I see no alternative until a > registrar is delivered a protocol is the only way.
There are already tons of "discovery" protocols that are standardized and which exist without the use of RMI or dynamic code downloading. You should use one of those if you need such a thing. The Jini model for service lookup that is encapsulated in the standards, involves the exploit of dynamic code downloading. If you don't need that, then you can use something else to "find" what you need to use. The issue, is that then you have a completely different programming model, typically, because there is no dynamic classloading going on.
Data only models, such as SOAP, then require you to have object mapping models that turn the data into objects that will allow the method based java programming model to integrate with the data only models.
But, this is another topic that we might want to discuss in another thread.