I'm designing an application whose functionality need to be the same in different contexts. Let refer to the picture below:
+----+ +----+ +----+
|B1 +--->-----+B2 +-->----+B3 |
|ctx1| use |ctx1| use |ctx1|
+----+ service +----+service+----+
+-------+ +----+ +----+ +----+
|Context| |B1 +--->-----+B2 +-->----+B3 |
|Manager| |ctx2| use |ctx2| use |ctx2|
| | +----+ service +----+service+----+
| | : : :
+-------+ : : :
+----+ +----+ +----+
|B1 +--->-----+B2 +-->----+B3 |
|ctxN| use |ctxN| use |ctxN|
+----+ service +----+service+----+
There are 4 bundles:
Context Manager
B1
B2
B3
Context Manager is the bundle that is in charge of knowing when a new context is available and to instantiate a new version of B1, B2 and B3. The services offered by B2 and B3 are exactly the same across contexts, just i want to add a property on the service to distinguish in which context it's running (ctx1 vs ctxN for example).
Now this is the theory of what i want to achieve, i thought i could easily implement it via Declarative Services, in fact i made B1 *B2* and B3 to be ComponentFactory by specifying the component.factory property in the component header, and i set B1 to refer to a service provided by B2, also i set B2 to refer to a service provided by B3.
These are the challenges i faced:
Context Manager learns about the ComponentFactory service provided only by B3, the first time, as long as B1 and B2 are not yet satisfied, they don't register the ComponentFactory service in the service registry. As long as this is the case B1 and B2 don't get instantiated for the first context.
B1 and B2 once created, gets an arbitrary service from other contexts, i was thinking to set the reference.target parameter to only pick the service from the same context but it doesn't seem there is any way to declarative do this, seems like the only way to select a service from the same context is by setting a reference with cardinality 0..n and to provide a "bind" method that select based on the current context, this means that every component has to replicate the same selection logic which instead i was thinking could be provided by the Context manager when a newInstance is called. In fact if during the call ComponentFactory.newtInstance(props); i could provide a property like .target=(context=mycontext) then this could be achieved, but I don't know all the reference the component is actually using.
At this point i'm thinking to actually avoid using Declarative Service and to have the per-context bundle extend a base class i will provide which will basically implement the dependency tracking similar to org.apache.felicy.dependencymanager but such that the developer of the per-context component don't have to worry to know in which context the code sits. However i hate to revert to this solution, i feel i'm just replicating logic may exist already in the OSGi specification and so my question is:
What is the best way to create bundles that can run on a per-context base in OSGi, such that the bundles can describe in a declarative way the dependency, without having to explicitly mention the context in which they are running?
There is some confusing terminology in here. You talk about bundles B1, B2 and B3. And you also talk about instantiating new versions of B1, B2 and B3. Do you mean updating the bundles B1, B2 and B3? Or do you mean bundles B1, B2 and B3 offer services S1, S2 and S3, respectively?
Answering my own, question. As long as i was in a need for a solution, thanks to the help of the Apache Felix DependencyManager i have replaced the Declarative Services and for each context,bundle (Container in the source code below) i create a new instance of dependency manager which helps to track the services on a per-context base.
For code reference please look at:
OpenDayLight ComponentActivatorAbstractBase
For managing dependencies and ensure they are in the same context a special ServiceDependency is created, for reference look at: OpenDayLight ServiceDependency
For example on how the activator is actually used refer to: OpenDayLight sample activator
Hope this can be of use to others too.
Related
I have some misunderstanding of OSGI fragment,
Suppose I have deployed a bundle "B" with two classes "com.company.C1" and "com.company.C2" where C1 use C2.
And then, I deployed a fragment "F" for the host bundle "B" where F contains only one class "com.company.C2" (with a little change in the code of the first class)
Now, if the class "com.company.C1" is being executed, which class (file) "com.company.C2" will be used, from "B" or from "F" ?
Can the presence of the same class C2 twice in the same class-loader cause runtime errors (same version & differents versions)?
Read chapter "3.9.4 Overall Search Order" of OSGi Core specification and everything will be clear.
In short: The classes in the bundle are checked first and than the fragment bundle. If you have a class in the bundle and in the fragment bundle, the one in the fragment bundle will never be used.
Suppose there are two exported versions of an object, where both have property x but new one introduces a new property y.
How can I create bundle that can accept both versions of an object? Let's assume it will not clone objects, compare them, put into collections etc. Its interaction with object could be as simple as testing whether x != null.
Can serialization be avoided?
Osgi classloading rules are only active at classloading time. If your bundle for example publishs a service that takes an Object as parameter you can give it any instance. Even ones that come from package it does not import.
Christian is correct. To add to that, this is exactly why you should not share your objects directly, but share interfaces. Whilst that still won't make both versions of the interface available to a consumer, at least it will then try to do the right thing and choose the interface that both x and y are compatible with. In such cases, it would have to pick the lowest common denominator.
I develop similar calculation packages for different clients (Bob, Rick, Sue, Eve). The calculation packages consist of several calculation modules (A, B, C, D, ...), which are organized in a "Chain of responsibility" pattern. Assembly is done with Abstract factory.
As a lot of code is shared between the calculation modules of different clients, they are organized in an hierarchy:
ICalcA
|
AbstrCalcA
| |
AbstrCalcAMale AbstrCalcAFemale
| | | |
CalcABob CalcARick CalcASue CalcAEve
(same hierarchy for B, C, D, ...).
Now release management dictates, that I organize the source code per inheritance level:
Project: CalcCommon
[CalcA]
ICalcA.cs
AbstrCalcA.cs
[CalcB]
ICalcB.cs
AbstrCalcB.cs
[CalcC]
...
Project: CalcMale
[CalcA]
AbstrCalcAMale.cs
[CalcB]
AbstrCalcBMale.cs
[CalcC]
....
Project: CalcBob
[CalcA]
CalcABob.cs
[CalcB]
CalcBBob.cs
[CalcC]
....
Project: CalcFemale
....
For Bob, I release CommonCalc.dll, CalcMale.dll and CalcBob.dll.
Now this is all good, but with many modules, helper classes, and so on, it is very cumbersome to work within the same module hierarchy. Closely related classes (e.g. ICalcA and CalcABob) are far away in the solution explorer. No one on my teams seems to find anything without searching for the class name -- if he can remember it. Features tend to get implemented in wrong or multiple hierarchy levels.
How can I improve the situation?
I was thinking of creating one project per Module and hierarchy level (Projects: CalcCommonA, CalcMaleA, CalcBobA, CalcRickA, CalcCommonB, CalcMaleB, ...), and grouping them via solution folders.
I just found out that the new search bar on top of the solution explorer comes in handy for this.
Step 1: Make sure all classes related to Feature A contain "FeatureA" in their class name.
Step 2: If working in the FeatureA hierarchy, enter "FeatureA" into the search/filter bar.
This will display just to the classes of this particular hierarchy, just as required.
I would like to use ServiceTracker in order to consume the services published by our company.
Instead of creating new ServiceTracker for each service I want to consume I thought it would be better to create just one with a filter and then get the services from it:
Filter filter = ctx.createFilter("(" + Constants.OBJECTCLASS + "=com.mycomp*)");
tracker = new ServiceTracker(ctx, filter, null);
The problem with this approach is that I then need to iterate over the service references the tracker had found examine their objectClass property and see if I can assign it to the service object which is very cumbersome and error prone due to casting that is required.
Any other ideas how to cunsume multiple services using more elegant way?
I think it is the wrong question :-) From the question I infer that you have a method that takes a service from your company and you want that method called. That is, somewhere in your code you need to be informed about a specific type com.mycomp.X, that is, you're not interested in general services from your company, you have a clear type dependency. In your question you assume that they need to be dispatched centrally which is usually not robust, error prone, and a maintenance hotspot; every time you have a new company service you need to update the dispatch method.
A MUCH better solution seems to be to use Declarative services and use bndtools with annotations. In that model, each place where you need service:
#Component public class SomeMyCompComponent {
...
#Reference
void foo( com.mycomp.X x ) { ... }
...
}
In this model, you do not need to centrally maintain a dispatcher, any class can get the services it needs when they need it. This model also accurately handles multiple dependencies and lots more goodies.
Maybe I do not understand the problem correctly because I inferred the problem from the solution you required. However, I think you try to abuse the Service Tracker for a task it was not intended to do.
Unfortunately, DS is not build into the framework as we should have done :-(
You could subclass ServiceTracker and add methods to provide direct access to the service types in which you are interested. For example, you could store the services in a typesafe heterogeneous container [1]. Then you would be able to call method on your ServiceTracker subclass which take the type of the service you are interested in and they could be easily looked up in the typesafe heterogeneous container.
[1] Effective Java, 2nd Ed., Item 29.
Can anyone provide me with a web link that shows a correct approach of n-Layered design with example source-code in VS2005 and C#?
I am confused in one point, If I am creating layers like the following:
UI
|
Business Logic
|
Data Access
then how can I achieve true OOP?
Coz In OOP all activities should be encapsulated within an Object.
According to my thought, this should be layered like this:
UI
|
Business Objects
|
Business Logics
|
Data Access
But when trying to design layers like this I experienced Circular Reference Problem.
One of my buddy told me that, he solved this problem with Reflection.
So what is the industry-standard approach in separating a c# application into layers?
And a burning question is, which layer hosts the OR-Mapping?
alt text http://amrelgarhy.com/files/uploads/9-1-2009%208-58-14%20PM.png
And Some times goes like this:
alt text http://amrelgarhy.com/files/uploads/9-1-2009%208-59-14%20PM.png
So as you see in the 2 previous diagrams, the ORM located in the data access layer