How does the isolation work in iPOJO Composite? - osgi

iPOJO provides a mechanism to create composites that contain instances of primitive type components. I am interested in understanding the mechanism in which iPOJO provides an isolation for the services provided by the composite sub-instances from being accessed from outside the composite.
For exmaple, assume I have the following composition (Using iPOJO API):
PrimitiveComponentType prov = createAProvider(); // Create a primitive type
PrimitiveComponentType cons = createAConsumer(); // Create another primitive type
CompositeComponentType type = new CompositeComponentType()
.setBundleContext(context)
.setComponentTypeName("comp1")
.addInstance(new Instance(prov.getFactory().getName())) // Create an instance in the composite
.addInstance(new Instance(cons.getFactory().getName()));
ComponentInstance ci = type.createInstance();
Let's say that the component "prov" implements a service interface called HelloService. What does it mean that this service is isolated?
Does it mean that if I tried to access the service from an external bundle (not part of the composite) by having a service reference:
ServiceReference ref =
context.getServiceReference(HelloService.class.getName());
Is this reference really going to fail because its scope is outside the composite?
What if a component inside the composite contains a reference to a service published outside the composite? Is this reference also going to fail?
Note: I am not interested in the imported or exported services for the moment.

iPOJO composite relies on the iPOJO Service Context. In iPOJO the regular OSGi bundle context is composed by two parts: the bundle-centric part responsible for a class loading activities and the service-centric part responsible for all service interactions (publication, lookup, binding...).
When an instance runs inside a composite it as a 'local' service context, using a local service registry (the one from the composite). So services registered from inside the composite are not accessible from from outside as they are using two different service registries: the composite's one and the one from the OSGi framework.

Related

Why do we need the Abstract Factory pattern?

I am reading the chapter 11 page number 90 of clean architecture.
I agree with author that we should use interfaces instead of depending upon the volatile concrete classes to avoid the source code dependency on the concrete class to make our code more modular. He mentions the below pattern to handle the volatile dependency in the code.
In the above image author suggest to use the FactoryServiceImpl to create the instance of the ConcreteImpl.
What's the advantage we get in using the FactoryService? Anyway in the main method we will have to create the instance of FactoryServiceImpl and pass to the Application. Instead we can directly create the instance of the ConcreteImpl and pass it to the Application?
What's the advantage we get in using the FactoryService?
The application does not depend on FactoryServiceImpl nor ConcreteImpl. The advantage is that if you want to test the application class you can easily mock the FactoryService just by providing a test/mock implementation.
Since the application class does not depent on the concrete implentations, it is also not dependent on the dependencies of those classes. E.g. the FactoryServiceImpl might contain a dependency to an external service that it passes to the ConcreteImpl when it creates it - could also be a database. Maybe the FactoryServiceImpl uses a fancy framework that you don't want the application to "indirectly" depent upon.
Anyway in the main method we will have to create the instance of FactoryServiceImpl and pass to the Application. Instead we can directly create the instance of the ConcreteImpl and pass it to the Application?
Yes you could create a ConcreteImpl and pass it to the application, BUT Uncle Bob talks about volatile objects in chapter 11. This means that the application creates ConcreteImpl on the fly when it needs it. Maybe a ConcreteImpl is stateful and belongs to a user request. It might also be possible that the factory takes arguments that it uses to create a ConcreteImpl and this arguments change depending on the application state. Thus the application must create a new ConcreteImpl whenever the this state changes. Thus you can not create one instance in the "main" method.

Prism use of discovered service

Suppose a Prism version 8 WPF module has a ViewModel which needs to call on a service.
the service implements IService, but there exists a number of implementations of this service. Each implementation is a file (class library), possibly as a IModule (see below).
The user shall be able to configure which file to use either by configuration or by a folder's content.
Obviously(?) I am thus thinking of Module discovery by creating the right type of ModuleCatalog while "bootstrapping" the application and the service could thus be contained in this module.
If the call is a void call ("fire-and-forget") I guess I could simply use EventAggregator (implementing the service as an observer), however the call returns a value.
What is the best approach solving this?
(I would like to avoid writing my own assembly "discovering/loading" of some kind of a swappable service implementation dll file)
If you can inject IEventAggregator, you can inject IService, can't you?
If no module registered an implementation, you'll get an exception. If more than one module did, the last one wins (with unity as container, at least).

Create A Service And Allow Only One Bundle To Hold That Service At any Time

I'm trying to create a service such that once it is created it only allows itself to be held by a single consumer/bundle at any one time. (If this is against the philosophy/specification of OSGi then that obviously provides a quick answer but reference to the OSGi specs. stating this would be appreciated.)
To implement such a requirement I implemented the ServiceFactory interface thinking that whenever there was a requirement for the service the getService(Bundle bundle, ServiceRegistration<S> registration) method would be called and it would be where I could determine if the Bundle was a new consumer or not and act accordingly.
It appears that this is not the case in the scenario I have tested this in.
Using a Apache Karaf and instantiating a consumer of the Service via Blueprint it would seem that the getService method is never called. Instead the consumer's binding method for the service is called directly but injecting a proxy service object.
While I understand that Blueprint uses proxies surely there is still the obligation of the ServiceFactory contract to fulfil even if it's a proxy object consuming the service?
Why do I want to do this?
I am attempting to wrap JavaFX and the Stage class and because JavaFX isn't OSGi friendly I am attempting to co-ordinate access to the Stage object. I'm aware that there are frameworks such as Drombler but a brief look at them made me think that it doesn't suit my use case. They appear too restrictive for my needs e.g. I don't necessarily wish to layout an application in the manner Drombler uses.
It depends what you mean by a consumer. ServiceFactory does give you the chance to create a separate instance of a service per bundle that calls getService on your service. It's not clear from your question but I suspect you weren't seeing the getService invoked multiple times because you were fetching the service from the same consumer bundle. In this case, ServiceFactory simply returns the same object repeatedly.
As for your general question about restricting access to a single consumer, no that really goes against the OSGi philosophy. I'm sorry I don't have a spec reference for you but the clue is in the name: it's a service that is available to all.
I'm aware that there are frameworks such as Drombler but a brief look at them made me think that it doesn't suit my use case. They appear too restrictive for my needs e.g. I don't necessarily wish to layout an application in the manner Drombler uses.
Please note that the layout of Drombler FX applications is pluggable so you can provide your own implementation tailored to your needs. This allows you to get the most out of Drombler FX and JavaFX.
While this feature is available for some time, there is now a new tutorial trail explaining it in more detail.

Single instance of an object per transaction

I have a use case, that theoretically seems to me as it would be a solved problem. But i'm not able to find a sure fired implementation.
I've created a RESTful API, using Apache CXF, Spring and Hibernate
This application encompasses a standard Service-Proxy-DAO layered structure
I need to instantiate a custom logger object at my service (or pre-service) layer and initialize a bunch of parameters which will remain constant, for the most part through every call that goes through my application layers and back.
How can i, for every individual service call, initialize this logger object once, and use it across all my layers without having to instantiate it everytime. Either i inject the initialized object in every class i need or something on those lines.
I don't want to use static blocks, or pass the object in method signatures.
Is there anything that i can use as a part of the Spring, CXF or other java framework that allows me to implement this use-case.
EDIT: I would define a transaction as a single call to a web service endpoint, from invocation to response.
ThreadLocal would be an ideal candidate to solve your problem.
UPDATE:
Creating a thread local that is available in all the places where this "shared" reference is required will give all these contexts access to this resource without having to pass the reference around.
see http://www.appneta.com/blog/introduction-to-javas-threadlocal-storage/ - looks like a good explanation of how to use thread local and also deals with your problem space.

Do published OSGI services need to have their packages exported?

Do the packages that contain OSGI services need to be exported in order to publish to the service registry? Or does publishing to the service registry get round the need to export the package?
Short answers; 1st question = no, 2nd question = no, there's no "workaround"
The principle of "Design by contract" comes into play. Basically we provide an interface for consumers to depend on and providers to implement - this decouples our consumer code for the implementation details of our implementors. See http://www.osgi.org/blog/2011/08/package-as-contract.html for a good overview and http://en.wikipedia.org/wiki/Design_by_contract.
Given the interface (the API we wish to use) and the implementation (the concrete implementation of the API interface) and the consumer (code wishing to use an implementation of the interface), with OSGi you have a number of options.
A bundle can provide both interface and implementation, but it must export the interface if this service is to be used outside of the bundle itself
Having a separate bundle for the interface (which it exports) and other bundle(s) for the implementation(s) - the implementing bundles must import the interface's package but need not reveal their own implementation.
The advantages of number 2 include allowing multiple providers (OSGi uses LDAP filters that can be used to specify metadata matching on the registered services' properties), and leveraging the dynamic binding nature of OSGi (i.e. you can change implementation provider at runtime).
One thing to bear in mind, is that the consumer and provider must use the same classes as defined by the package version and exporting bundle (in other words the bundle classloader that loads the API classes must be the same for both consumer and provider).
The types of the service should be in exported packages. Services are typed and build upon the type sharing of the module layer. So you need to make sure that the provider of the service and the consumers of the service can all share the same type. So some bundle must export the package containing the type so that the provider and the consumers can import the package. This allows the framework to verify type safety of the service.

Resources