OSGi Remoting over EJB remoting
The purpose of this project is allowing to call remote EJBs from within any OSGi container. The EJB service interfaces will be presented as (remote) OSGi services. This project does not implement any remoting protocol, instead it delegates to the corresponding, vendor dependent EJB client library.
At its core the what this project does is setting the thread context classloader (TCCL) to an appropriate classloader during
- method calls on service proxies retrieved trough the above JNDI look up (EJB service calls)
This makes it possible to run any EJB client library that builds on top of JNDI.
The TCCL is set to a custom classloader that contains:
- the classloader of the ejb-client JAR
- the classloader of the EJB client library bundles
To support an EJB client library only two things have to be provided
- the environment used to create the
- the bundle symbolic names of the bundles that make up the EJB client library
In addition the ejb-client JARs have to be OSGi bundles with correct dependencies (minus the EJB client library) and OSGi Remoting service.xml files that map the service interfaces to JNDI names.
This project includes the following components:
- core, sever independent library that switches the TCCL and registers the OSGi services
- Java 6, 7 and 8 annotation processors that generate the required service.xml files for the ejb-client JARs
- sample integration for JBoss
- sample JBoss EJB client library bundle
- sample EJB
- sample EAR
- sample client
The provided JBoss integration is just a sample (eg. only supports localhost) and can be replaced by one that fits custom needs.
The advantages of this project are:
- supports dynamic starting and stopping of EJB client bundles at run time
- supports any OSGi runtime
- with little effort support every EJB client library that uses JNDI can be supported
- remote EJBs can be injected using OSGi Declarative Services
- remote EJBs can be injected using Eclipse 4 Dependency Injection
- client code has no dependencies on EJB libraries
- the look up of service proxies (can involve network access) is in its own thread to reduce impact on framework start up
- unobtrusive on build process, just an additonal xml that can be placed flexibly
In addition the following «OSGi smells» are avoided:
- buddy classloading
- dependencies from the ejb-client JARs to the EJB client library
- one huge bundle containing all ejb-client JARs
- using fragments to make classes available to a bundle
Only one EJB client library is supported at runtime — starting, stopping and restarting this library is not supported.
A Java 6, 7 and 8 annotation processor are provided that generate OSGi Remoting service.xml files that follow Java EE 6 portable JNDI syntax
To use the processor
- a dependency on
providedhas to be specified in the EJB project
- the processor argument
javax.ejb.module.namehas to be set to the module name
- the processor argument
javax.ejb.application.namehas to be set to the application name
In addition when the argument
org.jboss.distinct.name is set (can be empty) then JBoss proprietary EJB names are generated
A concrete example can be found in osgi-remoting-ejb-sample-ejb.
As OSGi Remoting does not cover authentication no API for authentication is provided. Authentication has to be done through the proprietary EJB client library API.
There is support for starting with unauthenticated calls first, logging in and from then on performing only authenticated calls. The following steps have to be taken
- make unauthenticated calls
- authenticate through client library (proprietary EJB client library API)
- look up
- wait for method call to return
- no need to re-lookup OSGi services, they stay valid and use authenticated calls now
Design Decisions/Trade Offs
To enable dynamic starting and stopping of ejb-client JARs an
InitialContext per bundle is created (and closed). This adds a small overhead.
#toString() are not intercepted by the OSGi service but instead forwarded to the EJB client proxy.
3.4.7 Session Object Identity
A client can test two EJB 3.x Remote/Local view references for identity by means of the
When deploying care has to be taken that that
- the bundle
osgi-remoting-ejb-clientis started automatically
- an implementation of
osgi-remoting-ejb-jboss) is registered (eg. through Dynamic Services / Service Component Runtime)
Sample Client on Equinox
When deploying the sample client on Equinox the bundles
org.eclipse.equinox.util have to be deployed. In addition it's recommended to deploy the bundles
org.apache.gogo.shell. In addition
osgi-remoting-ejb-client has to be auto stared.
To make the JBoss client libraries provided with this project work the following steps have to be taken:
- the following VM argument has to be set
- the following bundles have to be deployed:
- the client library (
osgi-remoting-ejb-jboss-client) has to be deployed unpacked
OSGi Service Lookup
When looking up the EJB service proxies though OSGi "manually"
BundleContext#getAllServiceReferences have to be used.
(service.imported=*) can be used to ensure only imported remote services are found.
ejb-client JARs deployed in OSGi have to meet the following requirements
- valid OSGi bundles with (direct) dependencies specified through
- no dependencies on EJB client libraries
- when running in Equinox the bundle header
Bundle-ActivationPolicy: lazyhas to be set
- an OSGi remote service.xml in
OSGI-INF/remote-serviceor a different location specified through the
Remote-Servicebundle header. The easiest way to do this is through the included annotation processor.
This project requires at least Java 6.
You must not make any service calls from an OSGi callback thread (
You should not make any service calls from the UI thread.
Service proxies can only be registered once the sole
InitialContextService is registered because it's required for defining proper class loader.
The sample does work only with JBoss remote EJB, not with remote JNDI. The sample EJB does only work with JBoss to make it work with other servers
<Aorg.jboss.distinct.name /> has to be commented out.
To add custom features like call logging or exception handling implementing a
ServiceListener and wrapping the services is recommended.
GlassFish client library is not yet implemented.
Geronimo client library depends on TOMEE-903 being fixed.
An ESA (Enterprise Subsystem Archive) would be nice http://coderthoughts.blogspot.ch/2013/04/osgi-subsystems.html http://svn.apache.org/repos/asf/aries/trunk/esa-maven-plugin/pom.xml