Interesting. And never let me stop you from using this in OSGi! That said, let me explain what my favorite model is today.
I use DTOs. These are simple Java objects (String, primitives and their wrappers), collections, maps, arrays, and objects but only public fields. No inheritance, limited generics (no type variables). i also support objects that have a string constructor and a toString() that can be used as input for the String constructor. I allow the sender side and the receiver side to use different types. All the DTO types can easily be serialized to JSON, but loose the oh so important type information. The receiver type has a matching type but it does not have to be the same as the sender’s type. The only requirement is that the receiver’s type is a proper template of the incoming JSON stream. This nicely decouples the sender and the receiver, actually, in many cases the sender and receiver are written in different languages. All this without loosing the all importance aspect that both my sender and receiver work in type safe Java using all the goodies of Java with specific collection types, maps, and generics. Clearly since there is no authority between the sender and receiver managing the same scheme between sender and receiver you can get mismatches. I address this with versions in the DTOs (normal field) and on deserialization taking advantage of a magic Map<String,Object> field in the DTO (__extra). When the deserializer sees a field it does not recognize it puts it in __extra map. (If it does not exist it fails.) Since the deserializer has built in rules for converting JSON to Object the receiver can figure out what went wrong. I find this a very nice balance between having the goodies of type safety when writing code and decoupling of the sender and receiver. I’ve worked a lot with Javascript and this model gives you basically the same advantages of high productivity and loose coupling you get in Javascript without giving up the goodies of Java’s type system. Kind regards, Peter Kriens > On 21 Feb 2017, at 12:29, Peter <j...@zeus.net.au> wrote: > > Christian, > > I will investigate it, if I can navigate a path through the serialization > issues. It is actually looking quite positive. > > Peter, > > Well, I wouldn't jump to conclusions too soon, it's still worth a look, a lot > of the features will look familiar to OSGi devs. > > The discovery protocols support IPv6 Multicast. Preparations have been made > for protocol extensibility (other than Java Seriailization), such as the case > with MarshalledInstance, and you'll also notice it's get method allows a > ClassLoader to be passed in: > > https://github.com/pfirmstone/JGDMS/blob/Maven_build/modularize/JGDMS/jgdms-platform/src/main/java/net/jini/io/MarshalledInstance.java > > > MarshalledInstance.get(final ClassLoader defaultLoader, > final boolean verifyCodebaseIntegrity, > final ClassLoader verifierLoader, > final Collection context) > throws IOException, ClassNotFoundException > > MarshalInputStream's constructor also accepts a ClassLoader to use for > deserialization. > > https://github.com/pfirmstone/JGDMS/blob/Maven_build/modularize/JGDMS/jgdms-platform/src/main/java/net/jini/io/MarshalInputStream.java > > AtomicMarshalInputStream has a similar constructor. > > RMI's MarshalInputStream doesn't accept a ClassLoader argument and neither > does ObjectInputStream. > > JERI, which stands for Jini Extensible Remote Invocation, is not Java RMI. > It's been updated to support TLSv1.2, using the latest secure cyphers with > perfect forward secrecy. HTTPS and Kerberos are also supported transport > protocols. JSON over HTTPS would be an obvious future enhancement. > > I've also restructured the project into bundles, and created proxy bundles so > we've got the same bundle at each Endpoint, I'm currently working on a > ModularExporter interface method that accepts a ClassLoader argument, > allowing the developer to determine the ClassLoader where deserialization > will occur on the server side. All provided services will use this when > available. > > For example, if I have a service implementation, I use an exporter to create > a proxy that implements remote interfaces and uses the underlying JERI > transport, the ClassLoader argument allows me to direct the ClassLoader in > which the java.lang.reflect.Proxy will be loaded to perform the back end > communications, I can give it the ClassLoader of the Smart Proxy bundle, > ensuring that the same bundle is loaded at each endpoint, so that all the > private objects in the Smart Proxy bundle can be found, that will form the > parameter arguments invoked on the service implementation back end. > > Some of the warts around Entry classes (Entry extends Serializable, all > fields are public they're the DTO's your talking about I guess) is that these > are sensitive to change, for example adding a field to an existing Entry with > a subclass will break the subclass, so versioning will assist greatly with > these. Entry's are of course used in the ServiceRegistrar and JavaSpaces. > The ServiceRegistrar doesn't deserialize, it matches on serial form, this > could be changed to other protocols, but currently its java serialized form > for each field in an Entry, the Entry itself is generally not intended to be > Serialized. > > However many classes aren't Serializable at all, such as this strictly > RFC3986 compliant immutable URI (where strict compliance allows bitshift > operations for string normalization, this one is lightening fast), it also > has an implies method that replicates the functionality of > CodeSource.implies(), but magnitudes faster: > > https://github.com/pfirmstone/JGDMS/blob/Maven_build/modularize/JGDMS/jgdms-platform/src/main/java/org/apache/river/api/net/Uri.java > > Why Serialize an object when you can just send a string and parse it back at > the other end? > > Hundreds of bugs identified by findbugs have been fixed in recent years as > have numerous race conditions, the codes a lot cleaner and maintainable than > it used to be. > > I think it's worth the experiment, it still has a few good features, and may > provide a migration path for some. > > Cheers, > > Peter. > > On 21/02/2017 6:04 PM, Peter Kriens wrote: >> My personal expectation is that Jini is entrenched on the Java serialization >> quagmire that you probably have to work around a lot more problems than the >> myriad of discovery and transport protocols that are currently available in >> Java? >> >> It is a pity because Jini and OSGi started in the same time and we had >> discussions together. >> >> Kind regards, >> >> Peter Kriens >> >>> On 21 Feb 2017, at 07:25, Christian Schneider <ch...@die-schneider.net >>> <mailto:ch...@die-schneider.net>> wrote: >>> >>> Have you thought about implementing the jini support as a discovery and >>> transport for Remote Service Admin? >>> I am not sure if it fully matches as jini is special in some aspects but I >>> see many similarities. >>> >>> Christian >>> >>> 2017-02-21 0:56 GMT+01:00 Peter <j...@zeus.net.au >>> <mailto:j...@zeus.net.au>>: >>> >>> Sounds like you've been burnt. >>> >>> Modular or die, no hacked compromises, won't support unworkable >>> complex non-modular cases, only support what works. >>> >>> For updates: >>> 1. Server module advises proxy's of graceful shutdown, proxy's >>> unregister services with OSGi registrar (or just stop working in >>> hard shut or disconnection, in which case they are discarded). >>> 2. Server unregisters from Jini service registrar and unexports. >>> 3. Server performs upgrades >>> 4. Server exports and reregisters with jini service registrar >>> 5. Service is dynamically discovered by ServiceDiscoveryManager >>> in clients, smart proxy's are provisioned and registered with >>> local OSGi registrar. >>> 6. Clients notified of service availability. >>> >>> The smart proxy bundle must be of identical version at both >>> endpoints, connection must be refused if this is not the case. >>> >>> Service api bundles are separate from smart proxy bundles. >>> >>> Clients don't import packages from smart proxy. >>> >>> The smart proxy contains the api for communication between proxy >>> and remote service only. Only service implementation imports >>> packages from smart proxy. Communication method and >>> communication api is a private implementation concern. >>> >>> The services smart proxy imports the service api packages, as >>> does the client. Service api is compatibility layer between >>> smart proxy and client. The smart proxy is a provider of the >>> service api, the client is the consumer. >>> >>> Service api update is client responsibility, not likely to update >>> often. Prefer to add mixin interfaces or replace api (new >>> service type) over breaking change. Smart proxy needs to >>> deregister when service api is updated (should listen for event >>> notifications). >>> >>> Service will only be rediscovered if it is compatible. >>> >>> As the smart proxy needs to be resourced and provisioned it is >>> this stage of the process where it may not be found api >>> compatible with the client, in which case it will not be >>> discovered by the client... >>> >>> The service can advertise its requirements (incl packages and >>> versions) via the Jini service registrar, services that are not >>> api compatible will be filtered out. >>> >>> The server / service remains responsible for maintaining >>> compatibility. >>> >>> Discovery is dynamic. >>> >>> We've had some discussion on river-dev, one user wanted much >>> wider support scope including remote objects with code download >>> that are not services, also wanted to use codebase annotations >>> and non osgi URLClassLoaders with bundle ClassLoaders as parents, >>> using Context ClassLoader to find bundle ClassLoader. Agree >>> that's an unworkable scenario due to complexity. >>> >>> I want to keep this as simple as possible for obvious reasons. Force >>> communication method to be an implementation concern, >>> allowing it to be replaced in future. >>> >>> Regards, >>> >>> Peter. >>> >>> Sent from my Samsung device. >>> ---- Original message ---- >>> From: Peter Kriens <peter.kri...@aqute.biz >>> <mailto:peter.kri...@aqute.biz>> >>> Sent: 21/02/2017 12:24:39 am >>> To: OSGi Developer Mail List <osgi-dev@mail.osgi.org >>> <mailto:osgi-dev@mail.osgi.org>> >>> Subject: Re: [osgi-dev] OSGifying an existing application >>> >>> The problem is that in all distributed I’ve been involved in >>> there were rolling updates. This implies that you cannot >>> guarantee that each server runs the same bundle. And clusters >>> that do not do rolling updates seem kind of useless because they >>> introduce a huge failure point. So I have a hard time >>> understanding how you can guarantee that invariant? Yes, it works >>> most of the time but when I learned to work with computers that >>> tended not be good enough. >>> >>> Now I do understand ( and sympathise) that you cannot change the >>> app. I’ve been there. >>> >>> You indicate you have the same bundle on both sides. So the class >>> graph on both sides is equal. This implies that if you ensure >>> that the API interface is in the same bundle as the >>> implementation classes then you’re safe as long as you use the >>> interface’s class loader as the root loader for classes you find. >>> This is of course highly not modular but then you’re not anyway >>> under the covers :-) You could also make the API bundle import >>> the implementation bundles, that should work as well. >>> >>> As long as you make sure OSGi has the proper dependency >>> information things tend to work out of the box. >>> >>> Kind regards, >>> >>> Peter Kriens >>> >>> >>>> On 20 Feb 2017, at 11:47, Peter <j...@zeus.net.au >>>> <mailto:j...@zeus.net.au>> wrote: >>>> >>>> Thanks Pete, good to hear from you again, I must admit it's been >>>> too long. We last spoke when I was refactoring a class >>>> dependency tool to use ASM instead of the jdk's tools.jar. You >>>> once asked, how do you find a dependency for calls to Class.forName? >>>> >>>> The reasons you've stated are also why I've chosen to support a >>>> very narrow use case, in which you may have already noted that >>>> the serialized connection is between two identical bundles, in >>>> separate jvm's with compatible package imports. >>>> >>>> There’s no intent to support transferring any classes outside of >>>> the Service Now API and that includes overriding classes. What >>>> you describe about data hiding reminds me of Entry's, which have >>>> public fields. >>>> >>>> I'll be the first to admit there are significant issues with the >>>> design of Java's Serialization's extralinguistic api. >>>> Ironically though the wire protocol is reasonably well thought >>>> out, with regards to evolution. >>>> >>>> As an exercise to fix security issues, I have reimplemented Java >>>> serialization with input validation using a public api, it has >>>> backward compatible serial form, but only supports a subset of >>>> Java serialization, it doesn't support circular object graphs >>>> for example as this would compromise security. It performs >>>> input validation, sets resource limits and expects periodic >>>> stream resets to avoid DOS and gadget attacks. The problem is >>>> there's a lot of existing software that utilises java >>>> Serialization, that's going to need support for some time. >>>> Things like Serialization and Remote method invocation are >>>> damaged by attempts to implement too much functionality, when a >>>> more rigid subset would avoid a number of issues. But I guess >>>> no one was thinking of modularity and versioning when they >>>> created these frameworks either. >>>> >>>> James Gosling said something once about why Generics weren't >>>> included in Java from the outset, which was because at the time >>>> they didn't know how to do it properly, it's better leaving it >>>> out until you do. >>>> >>>> JBoss has a nice web page with some graphics that illustrate >>>> some major issues with implementation hiding you've mentioned >>>> with Serialization and modular frameworks here: >>>> https://developer.jboss.org/wiki/ModularSerialization >>>> <https://developer.jboss.org/wiki/ModularSerialization> >>>> >>>> It's worth noting Service API of the smart proxy bundle doesn't >>>> need to be Serializable, instead it's relegated to a >>>> communication means between two identical bundles in different >>>> JVM's. It's also important to recognise that it doesn't need >>>> to be the communcation mechanism either. These bundles have an >>>> identical class namespace, although there may be variances in >>>> package import versions. >>>> >>>> Yes we are also looking at moving away from java serialization. >>>> >>>> Also over time, because this is a service interface, at some >>>> point down the track, serialization can be replaced, without >>>> impacting the public api. So yes the underlying protocols can >>>> be stripped out to data and message passing if that's more >>>> satisfactory. >>>> >>>> So yes java serialization is an existing part of our application >>>> and it has it's warts. >>>> >>>> But we've also had a number of users over the years who have >>>> requested support for OSGi. >>>> >>>> This is not a greenfields project, I'm hoping that I'm not going >>>> to be told that no, the chasm is too wide you can't cross over >>>> to OSGi, rewrite or start again, there's just too many LOC. >>>> >>>> So you have raised some important questions. Some of our users >>>> have had a lot of success with Maven (recognising there a pro's >>>> and cons's with module based versioning and transitive >>>> dependencies), where versioning on a module level allows >>>> codebase annotations to be utilised in remote invocation, >>>> avoiding class visibility issues by mapping module ClassLoader's >>>> directly to a URI based identity. However with OSGi there's a >>>> mismatch between different jvm's and how bundles and packages >>>> imports will be resolved will end up being wired, so we can't >>>> rely on codebase annotations for OSGi. >>>> >>>> Jvm's using OSGi frameworks are quite likely to have different >>>> dependency graphs (wires) between bundles and their package imports. >>>> >>>> While I don't expect to solve the worlds problems or boil the >>>> ocean, I'm looking for the most workable compromise, one that >>>> doesn't promise the world and is easier to explain what users >>>> can and can't expect to do. I'm relatively pragmatic. To me it >>>> would seem logical that a subset where two identical bundles >>>> (that should have resolved similar package import versions) >>>> should be a good place to start. >>>> >>>> Hence my post on this list, as I realise many of you have >>>> already spent a lot of time bumping into these issues. >>>> >>>> Cheers, >>>> >>>> Peter. >>>> >>>> On 20/02/2017 6:38 PM, Peter Kriens wrote: >>>>> After working in this area for too many years I’ve come to the >>>>> conclusion that objects cannot be really transferred to other >>>>> systems in a reliable way, only self typed data can. JPA, RMI, >>>>> and many other systems promise heaven to the programmer that >>>>> they can use their objects local and remote transparently. The >>>>> consequence of this dream is a huge amount of complexity that >>>>> far outweighs any gains in programmer friendliness. Few things >>>>> have caused so much trauma in the software world as ORM. >>>>> (Persistence is communications to a future process.) >>>>> >>>>> The reason objects are so complex to use in communications is >>>>> that it is in direct violation of the goal of OO to hide your >>>>> data. However, once you expose the internal data on the wire >>>>> you have effectively made it public but too many people they >>>>> can still have the advantages of abstract data types. OSGi is a >>>>> bitch in this case because it tells you that you’re trying to >>>>> do something wrong by refusing to cooperate. In this case, it >>>>> balks at you because you create an invisible dependency between >>>>> the sender and the receiver. Though this is a good thing too >>>>> often the receivers of this message blame the messenger. >>>>> >>>>> You can handle this dependency but you’ll find out is that it >>>>> is a hugely complex task that introduces a lot of frailty in >>>>> the overall system. Having tried this several times I can >>>>> assure you that any gains in programmer friendliness are >>>>> dwarfed by the complexity of creating this facade. >>>>> >>>>> The best solution I found is to give up on data hiding. The >>>>> fact your objects is on the wire means that that wire format is >>>>> public. I therefore use Data Transfer Objects, in my case >>>>> objects with public fields. On both sides I have my own objects >>>>> to provide behavior to this data with methods and classes but >>>>> this data record is at the core of my code. Since this data is >>>>> public because it goes over the wire it is better to wrap you >>>>> code around that ‘standardized public’ object than to try you >>>>> internal object data. >>>>> >>>>> If you look at the OSGi specifications of the past 5 year then >>>>> you will notice that all applicable APIs have been designed to >>>>> be useful with Distributed OSGi. Calls do not pass objects but >>>>> they pass DTOs back and forth. They do not rely that the >>>>> receiver and sender have exactly the same type and version. In >>>>> this model it is easy to replace an endpoint using another >>>>> language, which is a really good sign. >>>>> >>>>> For Java developers this is often an unpleasant message, and >>>>> quite often OSGi get the blame. However, the fact OSGi gives >>>>> you these problems means that you’re trying to do something >>>>> that has hidden dependencies. >>>>> >>>>> Distributed computing has 7 well known fallacies[1] but I >>>>> strongly believe that there is an eighth: ’One can communicate >>>>> objects over a network’. >>>>> >>>>> Now your question. Yes, you could run a resolve and load the >>>>> proper bundles but you introduce a huge amount of error cases >>>>> and a large amount of complexity and you won’t solve the >>>>> fundamental problem >>>>> >>>>> Kind regards, >>>>> >>>>> Peter Kriens >>>>> >>>>> [1]: >>>>> https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing >>>>> <https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing> >>>>> >>>>> >>>>>> On 20 Feb 2017, at 05:13, Peter <j...@zeus.net.au >>>>>> <mailto:j...@zeus.net.au><mailto:j...@zeus.net.au >>>>>> <mailto:j...@zeus.net.au>>> wrote: >>>>>> >>>>>> Hello, >>>>>> >>>>>> I'm currently working on converting an existing application to >>>>>> OSGi. >>>>>> >>>>>> This application has a network service architecture based on >>>>>> java interfaces. I've broken the application into modules, >>>>>> using a Maven build, which uses bnd and bndtools to create >>>>>> bundle manifests. Some of these modules are ServiceLoader >>>>>> provider's, so I've used annotations to ensure these are >>>>>> loaded into the OSGi service registry using the Service Loader >>>>>> Mediator. >>>>>> >>>>>> The main issue that I face is this application is a networked >>>>>> application and has it's own Remote Invocation protocols >>>>>> (which currently utilise Java Serialization, but not Java >>>>>> RMI). As you'll appreciate, class visiblity is a little >>>>>> different in OSGi. :) >>>>>> >>>>>> The services mentioned above are remote services, these remote >>>>>> services have a proxy which implements the service interface, >>>>>> these services are discovered and installed at the client. There >>>>>> are two types of proxy's, one, called a smart proxy, >>>>>> requires a codebase from which to retrieve a jar or jar files >>>>>> that are downloaded and installed at the cleint (traditionally >>>>>> during deserialization), the other type of proxy is called a >>>>>> dynamic proxy (it's basically just an instance of >>>>>> java.lang.reflect.Proxy), which is dynamically generated at >>>>>> the client. >>>>>> >>>>>> The Service implementation is broken up into three components: >>>>>> >>>>>> 1. The service api >>>>>> 2. The smart proxy (resolved and provisioned into in client jvm). >>>>>> 3. The server >>>>>> >>>>>> The server bundle imports packages from the smart proxy >>>>>> bundle, while the smart proxy imports packages from the >>>>>> service api as well as exporting it's own packages, as >>>>>> required by the server bundle. >>>>>> >>>>>> The server that provides the remote service has three bundles >>>>>> loaded; server-impl, smart-proxy & service-api. >>>>>> >>>>>> The client only has the service api bundle installed at >>>>>> deployment and the smart proxy is resolved and provisioned >>>>>> before the service is made available via the local OSGi >>>>>> service registry, where the client will learn of it's >>>>>> existence using ServiceTracker. >>>>>> >>>>>> At first glance only the smart proxy bundle needs to be >>>>>> provisioned at the client, however for cases where a dynamic >>>>>> proxy is required to implement interfaces from different >>>>>> packages, where class visibility issues may exist, it may be >>>>>> beneficial in these cases to utilise and provision a proxy >>>>>> bundle that imports all these interfaces, one might do that by >>>>>> taking advantage of java's interface multiple inheritance; >>>>>> create a bundle that contains one interface (annotated with >>>>>> @ProviderType) which extends all interfaces, which the bundle >>>>>> doesn't export, so we ensure that the dynamic proxy has a >>>>>> proper bundle manifest with all package imports and version >>>>>> ranges correctly defined. >>>>>> >>>>>> The inbuilt remote invocation protocol has server and client >>>>>> endpoints, the protocol is extensible and has a number of >>>>>> implementations (for example https, http, tls, kerberos, tcp). >>>>>> Each endpoint is assigned a ClassLoader when it's created. >>>>>> >>>>>> For classes installed at the client, these are typically >>>>>> installed in a URLClassLoader, typically with the Application >>>>>> loader as parent loader. In an OSGi environment however, the >>>>>> smart proxy bundle will be installed at the client, it's >>>>>> ClassLoader utilised by the client endpoint, the smart proxy >>>>>> bundle will also be installed at the server and it's >>>>>> ClassLoader utilised by the server endpoint. In this case >>>>>> the visibility of the bundles at each endpoint will be >>>>>> utilised to resolve serializable classes. Private smart >>>>>> proxy serializable classes will be resolvable at each end, but >>>>>> only public classes from imported packages will be >>>>>> deserializable, since the client interacts using the Service >>>>>> API, all serializable classes in the Service API packages will >>>>>> need to be exported and public and imported by the client and >>>>>> smart proxy. >>>>>> >>>>>> Once a bundle has been provisioned its ClassLoader will be >>>>>> given to the client endpoint and the marshalled state of the >>>>>> proxy unmarshalled into it. At this point the service that >>>>>> the proxy provides would be registered with the OSGi service >>>>>> registry for the client to discover and consume. The smart >>>>>> proxy communicates with it's server via an internal dynamic >>>>>> proxy (java.lang.reflect.Proxy), it's used to invoke methods >>>>>> on the server. >>>>>> >>>>>> While the existing protocol uses Java serialization, it >>>>>> doesn't use Java serialization's method of resolving classes >>>>>> Java Serialization walks the stack and finds the first non >>>>>> system classloader (looking for the application ClassLoader). >>>>>> The existing class resolution method isn't suitable for >>>>>> OSGi, however the mechanism is extensible, so can be replaced >>>>>> with something suitable. >>>>>> >>>>>> >>>>>> >>>>>> Does anyone have any advise or experience utilising the OSGi >>>>>> Enterprise Resolver Service Specification (chapter 136) and >>>>>> the OSGi Enterprise Repository Service Specification (chapter >>>>>> 132) to resolve and provision a bundle for the smart proxy at >>>>>> the client? >>>>>> >>>>>> >>>>>> >>>>>> The intent here is the bundle manifests at each endpoint will >>>>>> be used to determine class visiblity, so the resolution and >>>>>> provisioning process will be of critical importance. >>>>>> >>>>>> For anyone curios, the application is a fork of Apache River / >>>>>> Jini and I'm experimenting with support for OSGi. I'm also a >>>>>> committer and PMC member of Apache River. This isn't the old >>>>>> Jini we all know and love however, there are some additional >>>>>> features that allow provisioning to occur using a feature >>>>>> called delayed unmarshalling, so we can avoid the need for >>>>>> codebase annotations and URLClassLoaders. >>>>>> >>>>>> The work in progress can be found here, for anyone who's curious: >>>>>> >>>>>> https://github.com/pfirmstone/JGDMS/tree/Maven_build/modularize/JGDMS >>>>>> >>>>>> <https://github.com/pfirmstone/JGDMS/tree/Maven_build/modularize/JGDMS> >>>>>> >>>>>> Regards, >>>>>> >>>>>> Peter. >>>>>> >>>>>> _______________________________________________ >>>>>> OSGi Developer Mail List >>>>>> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org> >>>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev >>>>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev> >>>>> >>>>> >>>>> _______________________________________________ >>>>> OSGi Developer Mail List >>>>> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org> >>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev >>>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev> >>>> >>>> _______________________________________________ >>>> OSGi Developer Mail List >>>> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org> >>>> https://mail.osgi.org/mailman/listinfo/osgi-dev >>>> <https://mail.osgi.org/mailman/listinfo/osgi-dev> >>> >>> >>> >>> >>> _______________________________________________ >>> OSGi Developer Mail List >>> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org> >>> https://mail.osgi.org/mailman/listinfo/osgi-dev >>> <https://mail.osgi.org/mailman/listinfo/osgi-dev> >>> >>> >>> >>> >>> -- >>> -- >>> Christian Schneider >>> http://www.liquid-reality.de >>> <https://owa.talend.com/owa/redir.aspx?C=3aa4083e0c744ae1ba52bd062c5a7e46&URL=http%3a%2f%2fwww.liquid-reality.de> >>> >>> Open Source Architect >>> http://www.talend.com >>> <https://owa.talend.com/owa/redir.aspx?C=3aa4083e0c744ae1ba52bd062c5a7e46&URL=http%3a%2f%2fwww.talend.com> >>> _______________________________________________ >>> OSGi Developer Mail List >>> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org> >>> https://mail.osgi.org/mailman/listinfo/osgi-dev >> >> >> _______________________________________________ >> OSGi Developer Mail List >> osgi-dev@mail.osgi.org >> https://mail.osgi.org/mailman/listinfo/osgi-dev > > _______________________________________________ > OSGi Developer Mail List > osgi-dev@mail.osgi.org > https://mail.osgi.org/mailman/listinfo/osgi-dev _______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev