Osgi Declarative service conditional binding - osgi

I have this scenario, I have three declarative services that provide the same interface (say a reader interface and I have readerimpl1-database- readerimpl2-flat file- readerimpl3-memory). I want to have a consumer that binds only to the database implementation. In the component definition we give it a name so I am pretty sure that the name is in the registry so if I were to add an activate method I can lookup from the component context using the name.
I want to try to it via the bind/unbind though using the service name as the parameter. I am pretty sure that the "target" parameter in the component reference element can be used to do this but I have not found how to use it.
Has anyone else done this?
This would be similar to using
#Reference(mapped-name="foo")

Target is simply an OSGi filter. You can use it to filter by any service property. So, if your services have property named backend with values file or database, you can bind with the following target:
<scr:reference ... target="(backend=database)"/>
And the service with database backend itself will register as:
<scr:component ...>
...
<property name="backend" type="String" value="database"/>
</scr:component>

Related

How to make Drools KnowledgeAgent be dependant a custom component with Spring configuration?

I have my KnowledgeAgent setup as
<drools:kagent kbase="kbase" id="knowledgeAgent" new-instance="false" >
<drools:resources>
<drools:resource source="classpath:change-set.xml" type="CHANGE_SET" />
</drools:resources>
</drools:kagent>
So it scans the change-set.xml from classpath for resources. And I have another component which will dynamially generate the change-set.xml based on rulefiles found on disk. The spring configuration for this is
<bean id="changesetHandler" class="ChangesetHandler" autowire="byName" lazy-init="true" />
The problem here is that the change-set.xml is generated by my custom component, but I cannot set the Drools KnowledgeAgent component to be dependant on it as it follows it's own schema which does not seem to have depends-on attribute.
Given that a knowledge agent listens for changes, it should reload the knowledge base as soon as your bean generates the change set. Why not load a default empty change set initially and then load the dynamic change set when it has been generated?
Personally I avoid the Drools-Spring components. I find it easier to create a service within my application, which holds my knowledge base. I can then define whatever dependencies I like within that service and ensure that any initialisation has been completed.

WAS 8.5 - Can a blueprint managed OSGI service have a reference to a declarative services managed OSGI service?

We use WebSphere 8.5 (NON-Liberty Profile… just straight-up WAS) and we have a Spring 3.2 web app that is accessing an OSGI service which is using the blueprint component model via an SCA service bridge. We did this this way because to our understanding, this was the only way to be able to access the OSGI services layer from within our current architecture. If anyone might know of another/better way, I'm also all-ears on this as well.
From within this blueprint managed service, we'd like to have a reference to another service. This other service(and any service references within it) we'd like to have managed by the declarative services component model.
My question is… is this possible? Does anyone know if this mixing of these two component models from within WAS 8.5 is do-able in any way, shape, or form??
And if it is possible, might anyone be able to point me in the right direction on how to approach this?
Edit - Dec 5th
So the approach I decided to take was to first, build a small proof-of-concept application that uses three different OSGI bundles all using blueprint. Then once I have this working, take one of the blueprint managed services, and attempt to convert it to a ds managed service.
Here's what I've got so far:
I have ran through and created the tutorial located here. I currently have the CounterApp OSGI bundle Application containing the following bundles as application content:
CounterServiceBundle
CounterWebBundle
CounterWorldBundle
As is stated in the tutorial, all of the above are tied together using the blueprint component model via the blueprint.xml files.
So it all breaks down as follows:
From within the doGet method of the CounterWebBundle's CounterServlet I have a Greet service being used in the following manner:
Greet greet;
try {
InitialContext ic = new InitialContext();
greet = (Greet) ic.lookup("osgi:service/"+Greet.class.getName());
String greetText = greet.getText();
String output = "greet.getText()="+greetText;
response.getOutputStream().println(output);
} catch (NamingException e) {
e.printStackTrace(System.out);
}
This "greet" service is defined in the blueprint xml as "GreetBeanService". Now, within its implementation class it has references to two other services, "CounterBean" and "WorldRef".
Here is the blueprint.xml file to clarify:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="CounterBean" class="com.ibm.ws.eba.counter.CounterImpl"
init-method="init"></bean>
<service id="CounterBeanService" ref="CounterBean"
interface="com.ibm.ws.eba.counter.Counter" />
<bean id="GreetBean" class="com.ibm.ws.eba.counter.GreetImpl"
init-method="init">
<property name="counter" ref="CounterBean"/>
<property name="worldBean" ref="WorldRef"/>
</bean>
<service id="GreetBeanService" ref="GreetBean"
interface="com.ibm.ws.eba.counter.Greet" />
<reference id="WorldRef" interface="com.ibm.ws.eba.world.World" />
</blueprint>
So the thing is this:
I'm aiming to convert the "WorldRef" service to a DS managed service with a component.xml file and the following added to the MANIFEST.MF header Service-Component: OSGi-INF/component.xml of the implementation Class, not the API Class if I'm understanding correctly.
Would this be all I would need to do for the conversion? Or do I also need to add an Activator for the Class? Also, would I need to add 'activate' and 'deactivate' methods in the API implementation Class?
Also I'm of the understanding that I have to somehow include the service component runtime, as a separate bundle and include it in the "CounterApp" application, how exactly would I do this? Do I have to create a separate bundle project consisting of the following bundle/jars
org.eclipse.equinox.util
org.eclipse.equinox.ds
org.eclipse.osgi.services
where I would then re-export all of the exported interfaces from all of these jars?
Or do I have to define some sort of service to export that exposes the SCR?
Edit - Dec 6th
I went ahead and created a new DS OSGI bundle/jar containing all of the above mentioned jar files required to provide the equinox DS implementation, then just passed on the exports of each jar in this new bundle. I then added this DS bundle to my CounterApp application and imported each of these DS bundle exports into the bundle containing the WorldRef service.
This is where I appear to be getting hung up:
The OSGI framework is loading the bundle containing the WorldRef service but the service is not being added to the registry, which suggests that the component.xml file defining the service isn't being read, which, intern suggests that the SCR is not running because it is what reads that file to my understanding.
So still stuck on the ability to get the SCR running. I am under a very tight deadline (I know… who isn't, right?

Extended Properties for Spring Framework

Looking for a solution that will provide us more functionality within Spring properties such as:
nested structures
maps/lists
properties referencing other properties. Example:
city.name=Toronto
city.address=#{city.name}, 123 Ave SW
I tried EProperties (Google) and Commons Configurations (Apache) but doesn't seem to integrate very well with the Spring Framework.
Also, we're using Velocity to access properties using #springMessage("city.address"), so it needs to work for that.
Does anyone know how I can achieve the above by extending the default Properties capability?
With newest versions of Spring you can use the PropertySource mechanism. You register all your PropertySource and the order in which they are searched and then you don't have to do anything, except perhaps add this to your XML:
<context:property-placeholder />
As long as you declare only one of these without specifying local property files (the "old way"), you will be able to reference property A as the value of property B, even if they are not in the same property source.
For nested structures this may help if you don't like the properties readability:
https://stackoverflow.com/a/13470704/82609
For parsing problems you can easily handle lists and other stuff like that manually very easily:
Reading a List from properties file and load with spring annotation #Value

Spring - usage of alias vs names

I am confused on the usage of alias. I do understand what alias is and how it is being used but i don't see how it can be any different than using names on a bean definition.
<bean id="xyx" name="abc,def" .. />
<alias name="xyx" alias="pqr"/>
Why the alias when i can use abc or def?
In my mind bean aliasing can be helpful in large system, where you can not manipulate bean names. You have option to create your own name (alias) specific for your part of the system...
from Spring documentation (3.0.x)
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/
...it is sometimes desirable to give a single bean multiple names,
otherwise known as bean aliasing...
therefore creating multiple names or/and aliasing are the same thing.
A use case maybe when you want to customize some beans that are already defined somewhere in a modular application (each module is a spring project for example), the bean maybe defined by a third-party framework/API or even your team. In that case you want that only inside your spring project call the customized version without altering other modules (projects), to do that just add the alias in your spring configuration which is indeed a powerful feature:
<alias alias="globalBeanService" name="customizedBeanService" />
Hence, whenever spring find a call to the globalBeanService, it will inject customizedBeanService for you inside your specific module.
Without this feature, you should go through all classes and modify the bean manually!!
An aliased bean will always have higher priority over a non-aliased one, and in case of having different beans with the same alias then the last one declared will have the priority. In other words, the aliased bean will override the non-aliased beans.
This can be particularly useful when creating big projects or when you are building extensions to your project and don't want to touch the original bean definition.
Alias has a specific using scenario which multiple names don't have:
Imagine multiple config xml files in your project, most of which are authored by your colleagues, and you need to add your own config.xml file. Using you'll be able to refer to a bean defined in another config file with a different name that's maybe more meaningful to your config, without having to touch your colleagues' config files.
I recently found another use case where alias easily solved a problem.
When auto configuration is active, Spring Boot provides the bean serverProperties which can be used to access information about the server currently running the web app.
In integration tests (i.e. when #SpringBootTest annotation is present) the same bean is available under the name org.springframework.boot.autoconfigure.web.ServerProperties.
Of course it is possible to use a different profile for integration testing, but that would require manual change of configuration at multiple places. However, simply by adding
<alias name="serverProperties" alias="org.springframework.boot.autoconfigure.web.ServerProperties"/>
the same configuration files can be used for integration tests and in production.
This might be a bug in Spring Boot, however alias easily solve the problem without waiting for a new release. And most certainly I have no possibility to alter the Boot configuration myself.

Exposing multiple implementations of a interface as OSGI service

I have an interface that has two implementations. I want to expose both implementations as OSGi services, but when I am doing that one overrides the other. Please find the configuration that I am doing:
<bean id="formService" class="com.dbt.form.service.FormService"/>
<bean id="formAPIService" class="com.dbt.form.service.FormAPIService"/>
<osgi:service
ref="formAPIService"
interface="com.dbt.form.service.ifc.IFormService"/>
<osgi:service
ref="formService"
interface="com.dbt.form.service.ifc.IFormService" />
Here formService is overriden by formAPIService implementation.
Please help me on how to sort out this issue.
The second service does NOT override the first... both of these services will be published separately, and you can confirm this by typing the inpect cap service command in the OSGi Gogo shell.
What MAY happen is that your consumer code will only choose one of the available service instances. In this case you need to write your consumer to either bind to all instances, or use a combinations of rankings or target filters to determine which particular service you want. You should give more information on how you are using these services since that is where the problem lies (probably).
Read this page...Chapter 8. The Service Registry section 8.2.2.3.
You can use bean-name attribute of osgi reference tag. While importing a service bean-name refers to the id attribute of that service when its exported.

Resources