Hi Martin,

Although not specifically designed for such use you can in some cases
use SPI-Fly for this purpose.
The general pattern that SPI Fly addresses is for ServiceLoader.load()
and similar APIs but if you look at it in detail you'll see that it
can set the TCCL for the duration of any static method.

So for example, if you had this in your bundle:
  class Foo {
    static void doit() throws Exception {
      URL r = 
Thread.currentThread().getContextClassLoader().getResource("/somewhere/blah.txt");
      System.out.println("*** Found resource: " + r);
    }
  }
where another bundle contains the /somewhere/blah.txt resource. You
can get this to work by adding the following to the manifests of these
bundles...

In the consumer bundle you tell SPI Fly that the Foo.doit() method
needs to be woven to have its TCCL set. This is done with this header:
  SPI-Consumer: org.apache.aries.spifly.example.resource.client.Foo#doit()

While we're not really obtaining a service from META-INF/services,
this will set the TCCL to all the bundles providing the Foo service
for the duration of the doit() method.
Then we tell SPI Fly that the bundle that contains your resource
provides the Foo service so that its classloader will be visible via
the TCCL during the invocation of Foo.doit(), by adding the following
to its manifest:
  SPI-Provider: org.apache.aries.spifly.example.resource.client.Foo

I've added a little demo to the SPI Fly codebase that shows this in
action. See [1] for a bundle containing the Foo class as above and [2]
for a bundle containing the resource.

The only limitation really is that it only works with static methods
as that's what SPI mechanisms (such as ServiceLoader) use. If you need
to use it with instance methods it would require some enhancements to
the SPI Fly weaving code...

Cheers,

David

[1] 
http://svn.apache.org/repos/asf/aries/trunk/spi-fly/spi-fly-examples/spi-fly-example-resource-client-bundle
[2] 
http://svn.apache.org/repos/asf/aries/trunk/spi-fly/spi-fly-examples/spi-fly-example-resource-provider-bundle

On 12 September 2012 20:50, Martin Lichtin <[email protected]> wrote:
> Hi David
>
> You're right, this looks doable.
>
> However, looking further into my non-OSGified library, I see code like
>
> Thread.currentThread().getContextClassLoader().getResourceAsStream(..)
>
> :-( This won't find the resource in the bundle classpath, as far as I can
> see.
> It seems non-trivial to develop a library that works both in JEE and OSGi.
>
>
> Martin
>
> -------- Original Message --------
> Subject: Re: How to make java.util.ServiceLoader work?
> From: David Bosschaert <[email protected]>
> To: [email protected]
> Date: Sun, 9 Sep 2012 18:39:16 +0100
>>
>> Hi Martin,
>>
>> If you use the static weaving with SPI Fly it should be of very low
>> impact. It will basically create you a modified bundle that works in
>> OSGi. It has a dependency the SPI Fly static bundle, but you should be
>> able to merge those classes in...
>>
>> Cheers,
>>
>> David
>>
>> On 8 September 2012 20:01, Martin Lichtin <[email protected]> wrote:
>>>
>>> Hi David
>>>
>>> Thanks! I actually came across SPI-Fly before posting, but it seemed like
>>> a "big thing" to introduce at the current situation with my project.
>>>
>>> What I would like in the short term is to inline the library (2
>>> artifacts)
>>> and "fix" some of the classes, ie. provide my own code for them.
>>> I think it can be achieved with
>>>
>>>
>>> <Embed-Dependency>scope=compile|runtime;artifactId=a1|a2;inline=true;inline=!**/SP.class;inline=!**/RP*.class</Embed-Dependency>
>>>
>>> However, the instruction
>>>
>>> inline=!**/SP.class;inline=!**/RP*.class
>>>
>>> to exclude a total of four classes does not work quite right.
>>> I also tried
>>>
>>> inline=!**/SP.class|**/RP*.class
>>>
>>> without any luck.
>>>
>>> Martin
>>>
>>>
>>>
>>> -------- Original Message --------
>>> Subject: Re: How to make java.util.ServiceLoader work?
>>> From: David Bosschaert <[email protected]>
>>> To: [email protected], Martin Lichtin <[email protected]>
>>> Date: 9/7/2012 4:42 PM
>>>
>>>> Hi Martin,
>>>>
>>>> You may want to take a look at the SPI Fly component in Apache Aries:
>>>> http://aries.apache.org/modules/spi-fly.html - this allows you to do
>>>> this relatively easily.
>>>> Additionally, the OSGi Enterprise Spec 5 chapter 133 covers this [1].
>>>>
>>>> Cheers,
>>>>
>>>> David
>>>>
>>>> [1] www.osgi.org/Download/Release5
>>>>
>>>> On 7 September 2012 14:50, Martin Lichtin <[email protected]> wrote:
>>>>>
>>>>> Hi
>>>>>
>>>>>   From an OSGi bundle I need to call a library that itself uses
>>>>> ServiceLoader to lookup/load a service provider class.
>>>>>
>>>>> This does not seem to work, however.
>>>>> java.util.ServiceLoader.load(x.api.z) returns no providers.
>>>>>
>>>>> I embedded the library, so both file META-INF/services/x.api.z and
>>>>> class
>>>>> x.spi.z are part of my bundle JAR.
>>>>> I thought this would be enough to get ServiceLoader to work, but no :-(
>>>>>
>>>>> Any ideas?
>>>>>
>>>>>
>>>>> I already tried
>>>>>
>>>>>            ClassLoader thread =
>>>>> Thread.currentThread().getContextClassLoader();
>>>>>
>>>>>
>>>>> Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
>>>>>            <call-library>
>>>>>            Thread.currentThread().setContextClassLoader(thread);
>>>>>
>>>>>
>>>>> in case TCCL would be the problem, but that didn't help.
>>>>>
>>>>> Martin
>>>
>>>
>>> ---------------------------------------------------------------------
>>> 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]

Reply via email to