You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@sling.apache.org by Nicola Cisternino <nc...@cointa.it> on 2020/12/11 15:16:11 UTC

Datasource selection

Hi all

I'm using Sling Datasource Bundle (org.apache.sling.datasource) and I 
configured two entries named (datasource.name property): *source1* and 
*source2*.
I can select single datasource using DS annotations:

@Reference(target = 
"(&(objectclass=javax.sql.DataSource)(datasource.name=*source1*))")
private DataSource dataSource;

But ... how can I select single datasource programmatically ?

Thanks a lot.
Regards.

Re: Datasource selection

Posted by Bertrand Delacretaz <bd...@apache.org>.
Hi,

On Fri, Dec 11, 2020 at 4:16 PM Nicola Cisternino <nc...@cointa.it> wrote:
> ...I can select single datasource using DS annotations:
> @Reference(target =
> "(&(objectclass=javax.sql.DataSource)(datasource.name=*source1*))")
> private DataSource dataSource;
>
> But ... how can I select single datasource programmatically ?

The BundleContext.getServiceReferences(java.lang.Class<S> clazz,
java.lang.String filter) method [1] takes an OSGi LDAP-style filter
with the same syntax quoted above, that's probably what you need.
There are a number of examples using it in the Sling codebase.

-Bertrand

[1] https://docs.osgi.org/javadoc/osgi.core/7.0.0/org/osgi/framework/BundleContext.html#getServiceReferences-java.lang.Class-java.lang.String-

Re: Datasource selection

Posted by Nicola Cisternino <nc...@cointa.it>.
Il 12/15/20 6:34 PM, Eric Norman ha scritto:
> For simplicity, you could probably let the framework do a bit more work for
> you and remove the need for the BundleContext field by using the reference
> bind method technique that sends you the service instance + the properties.
>
> For example, something like this:
>
> private Map<String, DataSource> dataSources = new ConcurrentHashMap<>();
>
> @Reference(service=DataSource.class, policy = DYNAMIC, cardinality=MULTIPLE)
> void bindDataSource(DataSource ds, Map<String, Object> properties) {
>      dataSources.put((String) properties.getProperty("datasource.name"), ds);
> }
>
> void unbindDataSource(DataSource ds, Map<String, Object> properties) {
>      dataSources.remove((String) properties.getProperty("datasource.name"),
> ds);
> }
>
>
> On Tue, Dec 15, 2020 at 8:13 AM Bertrand Delacretaz <bd...@apache.org>
> wrote:
>
>> On Tue, Dec 15, 2020 at 4:58 PM Robert Munteanu <ro...@apache.org>
>> wrote:
>>> ...This way you get the datasources injected and via SCR and you get to
>>> use the datasource.name as a key...
>> sounds good and it's certainly more efficient than what I suggested.
>>
>> -Bertrand
>>
Thank you Bertrand and Eric !
Your solution works fine !


-- 
Nicola Cisternino
CTO - Ergon Project Manager - IT Architect
Cointa s.r.l.
Tel. +39 080 9371015
ncister@cointa.it
http://www.cointa.it

Re: Datasource selection

Posted by Eric Norman <en...@apache.org>.
For simplicity, you could probably let the framework do a bit more work for
you and remove the need for the BundleContext field by using the reference
bind method technique that sends you the service instance + the properties.

For example, something like this:

private Map<String, DataSource> dataSources = new ConcurrentHashMap<>();

@Reference(service=DataSource.class, policy = DYNAMIC, cardinality=MULTIPLE)
void bindDataSource(DataSource ds, Map<String, Object> properties) {
    dataSources.put((String) properties.getProperty("datasource.name"), ds);
}

void unbindDataSource(DataSource ds, Map<String, Object> properties) {
    dataSources.remove((String) properties.getProperty("datasource.name"),
ds);
}


On Tue, Dec 15, 2020 at 8:13 AM Bertrand Delacretaz <bd...@apache.org>
wrote:

> On Tue, Dec 15, 2020 at 4:58 PM Robert Munteanu <ro...@apache.org>
> wrote:
> > ...This way you get the datasources injected and via SCR and you get to
> > use the datasource.name as a key...
>
> sounds good and it's certainly more efficient than what I suggested.
>
> -Bertrand
>

Re: Datasource selection

Posted by Bertrand Delacretaz <bd...@apache.org>.
On Tue, Dec 15, 2020 at 4:58 PM Robert Munteanu <ro...@apache.org> wrote:
> ...This way you get the datasources injected and via SCR and you get to
> use the datasource.name as a key...

sounds good and it's certainly more efficient than what I suggested.

-Bertrand

Re: Datasource selection

Posted by Robert Munteanu <ro...@apache.org>.
On Tue, 2020-12-15 at 14:35 +0100, Nicola Cisternino wrote:
> Hi Robert.
> Declarative services are best way ... but i need to use different 
> datasources starting from a (request) payload attribute received from
> a 
> servlet ...
> So I decided to migrate (in a bundle service)  the custom pool engine
> that we used in the old webapp.

I would suggest trying the following (may need adjustment, typing out
of memory):

private Map<String, DataSource> dataSources = new
ConcurrentHashMap<>();

private BundleContext ctx;

@Activate
void activate(BundleContext ctx) {
  this.ctx = ctx;
}

@Reference(service=DataSource.class, policy = DYNAMIC,
cardinality=MULTIPLE)
void bindDataSource(ServiceReference<DataSource> ref) {
  dataSources.put((String) ref.getProperty("datasource.name"),
ctx.getServiceReference(ref));
}

void unbindDataSource(ServiceReference<DataSource> ref) {
  dataSources.remove((String) ref.getProperty("datasource.name"));
}

This way you get the datasources injected and via SCR and you get to
use the datasource.name as a key. There is probably more defensive
coding needed, but this is what I would use as a starting point.

Thanks,
Robert

> 
> Thanks.
> Nicola.
> 
> Il 12/14/20 12:55 PM, Robert Munteanu ha scritto:
> > Hi Nicola,
> > 
> > On Fri, 2020-12-11 at 16:16 +0100, Nicola Cisternino wrote:
> > > Hi all
> > > 
> > > I'm using Sling Datasource Bundle (org.apache.sling.datasource)
> > > and I
> > > configured two entries named (datasource.name property):
> > > *source1*
> > > and
> > > *source2*.
> > > I can select single datasource using DS annotations:
> > > 
> > > @Reference(target =
> > > "(&(objectclass=javax.sql.DataSource)(datasource.name=*source1*))
> > > ")
> > > private DataSource dataSource;
> > > 
> > > But ... how can I select single datasource programmatically ?
> > How do you select the datasources programatically now?
> > 
> > As a side note, I'd try to stick to declarative services as much as
> > possible as it makes things simpler to write and understand.
> > 
> > Thanks,
> > Robert
> > 
> 



Re: Datasource selection

Posted by Nicola Cisternino <nc...@cointa.it>.
Hi Robert.
Declarative services are best way ... but i need to use different 
datasources starting from a (request) payload attribute received from a 
servlet ...
So I decided to migrate (in a bundle service)  the custom pool engine 
that we used in the old webapp.

Thanks.
Nicola.

Il 12/14/20 12:55 PM, Robert Munteanu ha scritto:
> Hi Nicola,
>
> On Fri, 2020-12-11 at 16:16 +0100, Nicola Cisternino wrote:
>> Hi all
>>
>> I'm using Sling Datasource Bundle (org.apache.sling.datasource) and I
>> configured two entries named (datasource.name property): *source1*
>> and
>> *source2*.
>> I can select single datasource using DS annotations:
>>
>> @Reference(target =
>> "(&(objectclass=javax.sql.DataSource)(datasource.name=*source1*))")
>> private DataSource dataSource;
>>
>> But ... how can I select single datasource programmatically ?
> How do you select the datasources programatically now?
>
> As a side note, I'd try to stick to declarative services as much as
> possible as it makes things simpler to write and understand.
>
> Thanks,
> Robert
>


Re: Datasource selection

Posted by Robert Munteanu <ro...@apache.org>.
Hi Nicola,

On Fri, 2020-12-11 at 16:16 +0100, Nicola Cisternino wrote:
> Hi all
> 
> I'm using Sling Datasource Bundle (org.apache.sling.datasource) and I
> configured two entries named (datasource.name property): *source1*
> and 
> *source2*.
> I can select single datasource using DS annotations:
> 
> @Reference(target = 
> "(&(objectclass=javax.sql.DataSource)(datasource.name=*source1*))")
> private DataSource dataSource;
> 
> But ... how can I select single datasource programmatically ?

How do you select the datasources programatically now? 

As a side note, I'd try to stick to declarative services as much as
possible as it makes things simpler to write and understand.

Thanks,
Robert