Pawel,
the best DS alternative would be using two components:
one EntityManager whiteboard listening for EntityManager services
and one PersonRepository registry managing the PersonRepository services.
A untested but compiling code example replacing EntityManager with
DataSourceFactory and PersonRepository with DataSource yields:
For the registry:
@Component(service=DataSourceRegistry.class)
public class DataSourceRegistry {
private volatile BundleContext context;
private final Map<DataSourceFactory,
ServiceRegistration<DataSource>> register = new ConcurrentHashMap<>();
@Activate
public void activate(BundleContext context) {
this.context = context;
}
public void register(DataSourceFactory dataSourceFactory) throws
SQLException {
DataSource dataSource =
dataSourceFactory.createDataSource(getProps());
ServiceRegistration<DataSource> reference =
context.registerService(DataSource.class, dataSource, null);
register.put(dataSourceFactory, reference);
}
public void unregister(DataSourceFactory dataSourceFactory) {
ServiceRegistration<DataSource> registration =
register.remove(dataSourceFactory);
if (registration != null) {
registration.unregister();
}
}
private Properties getProps() {
// TO DO
return new Properties();
}
}
For the whiteboard
@Component
public class DataSourceFactoryWhiteboard {
private volatile DataSourceRegistry registry;
@Reference
public void setRegistry(DataSourceRegistry registry) {
this.registry = registry;
}
@Reference(name = "zDataSourceFactory", cardinality =
ReferenceCardinality.MULTIPLE , policy = ReferencePolicy.DYNAMIC)
public void addDataSourceFactory(DataSourceFactory factory) throws
SQLException {
registry.register(factory);
}
public void removeDataSourceFactory(DataSourceFactory factory) {
registry.unregister(factory);
}
}
Probably a matter of taste if you prefer this over the ServicTracker code.
Some remarks:
- For the whiteboard using zDataSourceFactory for the name of the
dynamic reference ensures that no addDataSourceFactory methods are
invoked before the static reference method setRegistry has been called
- The main reason you need two components is that you cannot control
the sequencing between a dynamic reference and the activate method.
Using one component you would need the BundleContext from the activate
method in the addDataSourceFactory method. This would lead to ugly code
accumulating all DataSources in a thread safe list untill the activate
method has been called. In short if you use ReferencePolicy.DYNAMIC you
do not want an activate method on your component.
regards,
Karel
On 24/04/2015 22:01, Pawel Pogorzelski wrote:
Neil, David, thank you. I'll go for a ServiceTracker hosted in a DS
component.
Pawel
On Fri, Apr 24, 2015 at 7:33 PM, Neil Bartlett <[email protected]> wrote:
Hi David, yes I agree. Additionally, using a DS component as the entry
point would allow for ease of configuration through Config Admin.
The blog post also needs to be updated for Java Generics…
Regards,
Neil
On 24 Apr 2015, at 17:21, David Jencks <[email protected]>
wrote:
It looks to me like your article leaves out an important detail, namely
what is supposed to cause the service tracker extensions to get set up in
the first place. I'd suggest that the ideal answer is…. a DS component.
If your per-service objects need other "constant" service references (i.e.
they get the same ref for each per-service instance) then these can be
provided as DS references in this DS component.
I agree that using ServiceTracker in this way is reasonable and simpler
than only using DS.
thanks
david jencks
On Apr 24, 2015, at 12:05 PM, Neil Bartlett <[email protected]>
wrote:
Service tracker really is better for this. See my (very old) blog post:
http://njbartlett.name/2010/08/05/when-servicetrackers-trump-ds.html
In your case I recommend returning the ServiceRegistration object from
addingService().
Neil
--
Neil Bartlett
On Friday, 24 April 2015 at 16:53, Pawel Pogorzelski wrote:
Guys,
what's the standard approach for registering a DS component/OSGi
service in
response to a service appearing in the container? Is ServiceTracker
the way
to go? I'm using Declarative Services and would like stick to DS if
possible. Explanation of what I'm trying to accomplish below.
I'm using Felix with Gemini JPA which registers EntityManagerFactory as
OSGi service per each persistence unit configuration. Since I need to
open
connections to multiple DBs with the same schema I end up having
multiple
EntityManagerFactories in the container. I'd like to map them to DAL
classes one-by-one. So, assuming I have PersonReposity in DAL I'd like
to
have as many instances of it as EntityManagerFactories for the given
schema. Is SCR able to do it?
Cheers,
Pawel
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]