Configuring an OSGi managed service via the configuration admin API - osgi

Consider a managed service registered on SERVICE_PID "a.b.c".
I need to have two different bits of code specify the configuration for a particular factory PID.
ConfigurationAdmin.createFactoryConfiguration() takes just the factory PID, not the instance PID. So, how do I acquire the configuration dictionary for a particular item? For example, felix fileinstall parses a file name like PID-FACTORYPID, and then throws away the FACTORYPID and calls createFactoryConfiguration just on the PID.
If I do likewise, the results flow into the 'updated' method with a PID with a unique string on the end. So I can't come up with the same string later to improve it by calling 'update'.

If you create a factory configuration then you can only define the factory pid. The individual config pid is chosen by the config admin impl.
The best way to find such a configuration later is by using a filter for one or some of the properties it has. You can for example give it a property myid=1 and later find it with the filter (myid=1).

The answer to this question has changed with OSGi R7. There are two new methods in ConfigurationAdmin that allow you to create a factory configuration with a predictable PID.
Configuration getFactoryConfiguration(String factoryPid, String name, String location)
Configuration getFactoryConfiguration(String factoryPid, String name)
The resulting PID is constructed by concatenating factoryPid and name with the tilde character ~ as a separator.

Related

How to map service factory PIDs to their `ObjectClassDefinition`

In OSGi R6 I desire to programmatically validate user-supplied String configuration properties plus a service factory PID against what is supported by whatever configurable #Component (or ManagedServiceFactory) that declares it configures this PID, e.g. #Component(configurationPid=some.service.factory.pid, ...). Additionally, I want to somehow convert valid String properties to their appropriate property types. Looking through the OSGi Compendium, it seems the Metatype Service is what I'm looking for.
If that's correct, given the following:
Applicable components uses component property types to specify their configuration
Component property types are annotated with #ObjectClassDefinition
Components are annotated with #Designate, mapping it to the applicable #ObjectClassDefinition
Is this the most straightfoward way to map factory PIDs to their ObjectClassDefinition:
Call BundleContext.getBundles(). For each bundle, call MetaTypeService.getMetaTypeInformation(Bundle).
For each returned MetaTypeInformation call MetaTypeInformation.getFactoryPids() and filter on the factory PIDs I care about.
For applicable MetaTypeInformation, call MetaTypeInformation.getObjectClassDefinition(String, String) to obtain the ObjectClassDefinition, using either a default or specific locale.
(Tangential, the above seems expensive to perform each time, so caching bundle IDs, mapping them to associated factory PIDs, and keeping the cache up-to-date somehow seems appropriate.)
Or, is there some other OSGi magic that can be programmatically queried with a service factory PID, which returns something that gets to some ObjectClassDefinition quicker than the above process?
Update 1
Stepping back, I'm writing a CRUD-wrapper around ConfigurationAdmin for each of my configurable components. I'm trying to avoid createFoo, deleteFoo, updateFoo, createBar, ... My application happens to be amenable to URIs. So my working approach was to use Metatype Service, pass in a parsed URI query (Map<String, List<String>>), and then utilize Metatype Service to validate and reconstruct these values, circling back to the OP. (On the side, seems like a not-pretty hack to me.)
Another approach was to use aQute.bnd.annotations.metatype.Configurable.createConfigurable(Class, Map), which I preferred more! Until I saw this bnd GitHub comment:
The bnd metatype annotations are deprecated in bnd 3.2 and will be removed in bnd 4.0. These annotations are replaced by the OSGi metatype annotations.
So I didn't want to rely on that package if it's going away soon. I looked at what Felix does and didn't want to use their equivalent Configurable class. I'm all ears on different approaches!
Update 2
Reducing this more, I'd like to validate potentially user-supplied key/values configuration properties to ensure they're applicable for some configuration pid, prior to calling ConfigurationAdmin.createFactoryConfig. Maybe this is overkill?
I once created a class that takes the configuration class, creates a proxy, and then uses this proxy to get the name of the method and the type. It was used something like this:
ConfigHelper<Config> helper = new ConfigHelper( Config.class, "my.pid");
int port = helper.get().port(); // get the configuration
helper.set( helper.get().port(), 1000);
helper.update();
The proxy you get from the get would record the method when one of the methods is called. On the set method it would use the last called proxy method to identify the property. It would then convert the given value to the property type based on the method's return value. The bnd converter is ideal for this but I think Felix now has a standard OSGi converter. (Which is based on the ideas of the bnd converter.)
The method name is then used as the property. The name mangling necessary is defined in an OSGi spec. This allows you to use underscores, Java keywords, and dotted names.
So this would allow you to roundtrip configurations. No worry about the types, they will automatically fall in their place.
Updated This is updated after I understood the question better
Updated 2 Added an example at https://github.com/aQute-os/biz.aQute.osgi.util/tree/master/biz.aQute.osgi.configuration.util

Returning an object from a Spring Batch job / processor

I have a Spring Batch job that reads in a very large fixed length file and maps it just fine to an object. Validated all of the data in the associated processing task.
Being rather new to Spring and Spring Batch I am wondering if it is possible to get out of the job, a fully populated object to be used in a particular case when I am running the job as part of another process ( that I would like to have access to the data).
I realize that I could do the above without Batch, and it seems to be designed with scope limitations for its purpose.
I could serialize the objects in the processor and go that route but for my immediate satisfaction I am hoping there is a way to get around this.
Thanks
In my #configuration class for the batch processing, I created a class variable (it is a list of the object I want to get back) and instantiated with the no arg constructor.
My Step, ItemReader, LineMapper are setup to use a list for input. The custom FieldSetMapper takes that list instantiated from the constructor as a parameter and adds to the list as the file is read and mapped. Similarly my custom ItemProcessor takes the list as input and returns it.
Finally I created a ReturnObjectList bean that returns the populated list.
In my main I cast the AnnotationConfigApplicationContext getbean to the list of that object type. I am now able to use the list of objects generated from the fixed file in the scope of my main application.
Not sure if this is a healthy work around in terms of how Spring Java config is supposed to work, but it does give me what I need.

Application-wide process in SpringMVC

Suppose I have a certain operation that should be available to every process running in Spring MVC.
Say string normalization--
i need to run a method that normalizes the string fields before doing anything else on that form/data.
One thing specific to do is, to normalize the String fields on every input form before
they are dispatched to the back-end services. Likewise, that operation (normalization)
should be run on data from the back-end before it is dispatched to the view component.
One way of doing this that I can think of is:
Code a bean doing it-- the normalization. Then, define this bean somewhere at the top in
the context hierarchy of Spring-- ApplicationContext.xml or WebApplicationContext.xml(?),
so that it will be visible and can be used
accross all the processes/servlets in the application.
Then, Whenever and from wherever needed, invoke that method on the bean defined up there.
Or, inject it to the relevant fields in the bean definitions(?)
In this case, is there a way to call it before or during a HandlerMapping is running? if so, how?
Another i can come up with is:
Code a validator (implement Validator) to run that process and "validate" the String fields for you.
But i dont see how this would be of good help.
From what i know, a validator runs on specific object types. I can define that type generically(?)
but then I'm operating on the fields-- not objects as a whole each.
Coding validator(s) seems too costly to me for this use-- even if it is an option here.
I'm new to Spring. pls bear with me on this.

Spring bean new instance of varing type according to lookup

I have a servlet based application which currently uses an injected HashMap of command processors to process a user entered command. This works very well but I need to modify this so that each instance of the command processor is unique.
The new requirements comes from the need to "pipe" the output on one command into another so if the command processors remain a single instance "piping" a list into a list would be problematic.
I still need to be able to map the class that handles the command to the command text.
My first thought was the change the HashMap from mapping the command to an instance of the command processor to mapping it to the class name and using that to instantiate an instance of the class. But that does not work due to the need to configure some of the commands with for example a list of options.
I have looked at making the beans prototypes which would seam to do what I want regarding getting a new instance of the configured bean but I am confused as to how I can map this, was thinking I could use the bean ID.
I am now at the stage of complete confusion and cant think how to do this.
I am aware that the explanation is a little light but this is a reflection of my confusion and I suspect that the greatest help will come from request for clarification which will help to get the head in order.
You could use request-scoped beans:
#Component
#Scope(value=WebApplicationContext.SCOPE_REQUEST,proxyMode=ScopedProxyMode.TARGET_CLASS)
public class CommandProcessor {
}
You can just inject CommandProcessor in your code and Spring will make sure you get different instance for every user request. You also will need CGLIB on your classpath.
If I got your requirements right you either need a factory method in your command class, or a FactoryBean that creates the instances.

Can PropertiesPlaceholderConfigurer subclass detect active Spring profile?

We have a specific format for our config files, where instead of having multiple files - ie, dev.properties, uat.properties, prod.properties - we instead have all the values in one file, but separated by prefixes for each environment. For example:
SERVICE_PORT=9800
DEV_SERVICE_PORT=7800
UAT_SERVICE_PORT=6600
We have an existing class (subclass of PropertyPlaceholderConfigurer) that looks up these values, and decides what prefix to add inside resolvePlaceHolder() based on the IP address where it is executing, ie for a certain IP range, use DEV_ prefix, for another, use UAT_ prefix. These values then get passed on to other beans, in some cases using the context xml, and in some using the #Value${} annotation on some bean constructors. The use of the prefixes is transparent, so all other configs will use SERVICE_PORT (in the example)
We want to change this so that instead of using IPs, we will just detect the active Spring Profile. We have a custom ApplicationContextIniitalizer in our web.xml that detects a java System property that indicates our type of environment.
The problem I have is that at the time resolvePlaceHolder() gets called, there doesn't seem to be any Active Profiles yet! What I"m doing to detect the active profile is:
create an instance of StandardEnvironment
call getActiveProfiles()
(2) always seems to return an empty array. This implies that propertyplaceholder resolution occurs before any Spring profiles are activated. Is this correct??
When does the active profile get set, in relation to other events during Spring context loading, like creating the beans, loading property files, etc?
Is it possible to detect the active profile at the time that resolvePlaceHolder() is called? Should I be extending another class instead?
Beans managed within an ApplicationContext may register to be
EnvironmentAware or #Inject the Environment in order to query profile
state or resolve properties directly.
[Source: Environment javadocs ]
Don't create an instance of StandardEnvironment, inject it into your bean!

Resources