You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@river.apache.org by Peter Firmstone <pe...@zeus.net.au> on 2019/09/01 09:47:37 UTC

Maven Build and OSGi Platform Support

As most are probably aware, we are progressing with the Maven build of 
River, all packages have been moved and now it's time to commence moving 
the junit tests to their maven modules.

The maven build structure is based on the work we've done in JGDMS, but 
there's no java code coming in from JGDMS at this time, just the module 
structure.    At this time, it seems to make sense to also make maven 
modules OSGi bundles.  However it is important to realise that making 
the modules into bundles isn't sufficient in iteself to support OSGi.  
This is due to a number of ServiceLoader Provider services being 
utilised within River.  It's also an option to delay making these 
modules bundles until OSGi can be supported fully.

I've recently got to the point where JGDMS supports OSGi, so maven 
modules are also OSGi bundles, but in addition all service loader 
services are now also OSGi services and either the service loader or 
OSGi service registry can be used to load them.

River has two custom implementations of the service loader mechanism, 
one is org.apache.river.resources.Service the other 
net.jini.config.ConfigurationProvider.   
org.apache.river.resources.Service was practically identical to 
java.util.ServiceLoader up until Java 8, and service implementations 
must provide a zero argument constructor. ConfigurationProvider requires 
implementations to have constructors that have one or two arguments.   
For OSGi we needed a level of indirection to get around the constructor 
arguments, for this I have provided another interface that has a method 
that accepts the constructor arguments, Configuration providers 
implement this, consumers continue to use 
ConfigurationProvider::getConfiguration, even those using OSGi.

For Java 9 and later, if we decide to make our River modules jpms 
modules as well, we will need to convert these providers to use 
ServiceLoader for module visibility.

Long term I think it makes sense to have 
org.apache.river.resources.Service use ServiceLoader internally, rather 
than the current implementation, also it has been very useful as a 
common mechanism to consume service provider or osgi based services and 
leave the decision which to use to the developer.

Note that I am not making any attempts to register Remote Jini Services 
as OSGi services.

Anyone willing to assist with testing OSGi or writing some tests for it 
would be greatly appreciated.

The OSGi platform recommends avoiding the thread context ClassLoader, 
this can be avoided by following advice below.

Jini service implementations using the OSGi platform:

   1. Must be configured to use net.jini.jeri.AtomicILFactory
      https://pfirmstone.github.io/JGDMS/jgdms-jeri/apidocs/net/jini/jeri/AtomicILFactory.html
          * AtomicILFactory requires a class argument in its
            Configuration, the ClassLoader of this class will be used
            for deserialization.
          * Codebase strings are not annotated in the stream by default.
   2. Jini Services must implement the following:
          * ProxyAccessor
            https://pfirmstone.github.io/JGDMS/jgdms-platform/apidocs/net/jini/export/ProxyAccessor.html
          * CodebaseAccessor
            https://pfirmstone.github.io/JGDMS/jgdms-platform/apidocs/net/jini/export/CodebaseAccessor.html
          * Service parameters or any classes that will be serialized
            must implement AtomicSerial. 
            https://pfirmstone.github.io/JGDMS/jgdms-platform/apidocs/org/apache/river/api/io/AtomicSerial.html
   3. The net.jini.loader.ProxyCodebaseSpi implementation must be loaded
      (one is provided, it will be discovered from the OSGi service
      registry).
   4. Proxy codebase URI Strings provided by CodebaseAccessor, must be
      bundles, they may be resolved using a provisioning URI mechanism.
          * In secure environments bundles should be signed.
          * The client need not trust the bundle certificates, these may
            be self signed, instead the service should be authenticated
            and the client trust the server certificates.  Once the
            server is authenticated, the ProxyCodebaseSpi implementation
            will dynamically grant DeSerializationPermission to
            codebases signed with the certificates and URL's in the
            codebase annotation.
   5. Once the bundle has been resolved, the service proxy will be
      deserialized into the bundle's ClassLoader, this bundle should be
      identical to that at the server endpoint, so that both endpoints
      have identical class visibility.   This is the service proxy
      bundle, the service implementation at the server will depend on it
      and all serialized object classes will be contained within the
      service proxy bundle or one of its dependencies.
   6. Note that it is advisable to sign proxy bundles.

To avoid the overhead of NP Complete dependency provisioning, 
ServiceDiscoveryManager should be utilised.

See also https://github.com/pfirmstone/JGDMS/wiki/OSGi-and-JGDMS

Note this is separate to River, the integration of these features into 
River is dependant on community review and acceptance.

Regards,

Peter.