felix-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Richard S. Hall" <he...@ungoverned.org>
Subject Re: Dynamically change the bound service
Date Mon, 19 Dec 2011 16:13:48 GMT
Overall, it looks not unreasonable.

Are you starting a thread? If so, that could be an issue.

iPOJO does some sophisticated service reference management to simplify 
concurrency issues for you. My guess is that iPOJO cannot tell that the 
thread you've created ever exits the component, so it keeps a cached 
reference for the lifetime of the thread.

Try to modify your thread so that it performs it functionality via a 
method on the component itself invoked form its run() method...i.e., 
your thread should explicitly enter and exit a method block to use a 
service so that iPOJO can properly keep track of it for you, because 
iPOJO is likely caching the service reference while your thread runs in 
its run() method.

To provide a little more detail, when a thread enters a component 
method, if that method accesses a service field, then iPOJO will 
automatically cache the service reference for that thread for the entire 
time that it executes inside that method. This way the thread doesn't 
have to worry about its service changing in the middle of using it. (Of 
course, it could still get errors if the service goes away, but that is 
normal for OSGi.) In this case, I'm guessing your component has a run() 
method on the component that access a service, so iPOJO caches the 
services until the thread exits the run() method, which in your case 
doesn't happen.

-> richard

On 12/18/11 20:49 , Fabio Fonseca wrote:
> Hi Richard,
>
> Thanks for your response. I'd say that's definitely some basic mistake. As
> you'd said, it is basic behavior (and I was hoping to read that). The
> problem is that I can't find where my mistake is... Yes, I tried field
> injection and I also tried method injection using the bind and unbind
> methods in the consumer, but they weren't called when I thought they should
> be.
>
> The code that I have attached in my original post is my test with method
> injection. I was hoping anybody more experienced than me could find what I'm
> doing wrong.
>
> Anyway, in the following lines you can find some parts of the code. Perhaps
> there is something that I'm missing but that is obvious to you.
>
> . consumer.xml:
> <?xml version="1.0" encoding="UTF-8"?>
> <iPOJO>
>    <component classname="org.test.iPOJO.consumer.Consumer">
> 	<requires field="inter" id="Inter">
> 	  	<callback transition="bind" method="bindInter"/>
>    		<callback transition="unbind" method="unbindInter"/>
> 	</requires>
>    	<callback transition="validate" method="start"/>
>    	<callback transition="invalidate" method="stop"/>
>    </component>
>    <instance component="org.test.iPOJO.consumer.Consumer"/>
> </iPOJO>
>
> . consumer.java:
> public class Consumer
> implements Runnable
> {
> 	private InterfaceOne inter;
>
> 	public void start() {
> 		System.out.println("[Consumer] Validating");
> 		run();
> 	}
>
> 	public void stop()	{
> 		System.out.println("[Consumer] Invalidating");
> 		stopRequestReceiver();
> 	}
> 	
> 	// This was never called
> 	public synchronized void bindInter (InterfaceOne i) {
> 		System.out.println("[Consumer] Binding");
> 	}
> 	
> 	// This was never called
> 	public synchronized void unbindInter (InterfaceOne i) {
> 		System.out.println("[Consumer] Unbinding");		
> 	}
>
> 	(...)
> }
>
> . providerA.xml (providerB is similar):
> <?xml version="1.0" encoding="UTF-8"?>
> <iPOJO>
>    <component classname="org.test.iPOJO.providerA.ProviderA">
>    	<provides/>
>    	<callback transition="validate" method="start"/>
>    	<callback transition="invalidate" method="stop"/>
>    </component>
>
>    <instance component="org.test.iPOJO.providerA.ProviderA"/>
> </iPOJO>
>
> . providerA.java:
> public class ProviderA
> implements InterfaceOne
> {
> 	private int state = 1;
> 	
> 	public void start()
> 	{
> 		System.out.println("[ProviderA] Validating");
> 		state = 1;
> 	}
>
> 	public void stop()
> 	{
> 		System.out.println("[ProviderA] Invalidating");
> 		state = 0;
> 	}
>
> 	(...)
> }
>
> Thanks,
> Fabio Fonseca
>
>
> Richard S. Hall wrote:
>> That doesn't sound right. I'd say there is something else simple going
>> wrong. If you are using field injection in the consumer, you could look
>> to add method injection too to see if you are getting proper callbacks
>> when services come and go. Regardless, this sounds like pretty basic
>> behavior, so I have to assume there is a simple mistake.
>>
>> ->  richard
>>
>> On 12/18/11 5:38 PM, Fabio Fonseca wrote:
>>> Hello all,
>>>
>>> I'm starting to develop my master thesis and this is my first post to
>>> this
>>> forum. My research concerns the challenges of developing Self-Adaptable
>>> software (software that can change its behavior in response to a change
>>> in
>>> its operation context). Right now I'm doing an assessment aiming to find
>>> which technologies are available today that could help achieving a
>>> self-adaptable software.
>>>
>>> I'm using Apache Felix + iPOJO to develop a simple test. I have a
>>> consumer
>>> which wants to consume providers that implement a interface named
>>> InterfaceOne. I have two providers that fits this requirement (named
>>> ProviderA and ProviderB). They all do nothing useful, I am just trying to
>>> produce a self-adaptable behavior.
>>>
>>> I am using the launcher.jar which is provided with the code that comes
>>> with
>>> the great book "OSGi in Action". This launcher creates an instance of the
>>> Felix Framework and loads the bundles found in the bundles/ directory
>>> passed
>>> as a parameter when running the launcher.jar.
>>>
>>> So I have 4 bundles. Each one of them has an iPOJO component inside it,
>>> except the first one that just has the InterfaceOne interface:
>>> . services-1.0.jar
>>> . consumer-1.0.jar
>>> . providerA-1.0.jar
>>> . providerB-1.0.jar
>>>
>>> The consumer is a simple http listener that uses localhost port 8080 to
>>> listen to anything that may appear. When something access the port 8080,
>>> it
>>> calls the available provider.
>>>
>>> When I start the launcher, all bundles are active and OSGi chooses one of
>>> the providers and binds it to the consumer. Using the shell commands I'm
>>> able to stop the providers' bundles and when I do it, the consumer is
>>> invalidated (as per the iPOJO lifecycle).
>>>
>>> I concluded that when I start the consumer bundle the available provider
>>> is
>>> bound to the consumer and it remains bound even when I stop its bundle
>>> (in
>>> the OSGi lifecycle). The cenario is:
>>>
>>> - start ProviderA
>>> - start Consumer (consumer starts since its dependency is satisfied)
>>> - start ProviderB
>>> - stop ProviderA (consumer is still valid in the OSGI's lifecycle, since
>>> there is a provider (ProviderB) that satisfy its dependency)
>>>
>>> At this moment, if I call localhost:8080, the consumer uses ProviderA,
>>> even
>>> when ProviderA is not available anymore. I conclude that the binding
>>> between
>>> Consumer and its provider (which is in this case still the ProviderA)
>>> continues to exist even when I stop ProviderA. I read somewhere that
>>> iPOJO
>>> lifecycle takes over OSGi's lifecycle, but when I stop ProviderA, the
>>> component becames Invalidated (I know because I placed a method that is
>>> called when the provider is invalidated). So, even with the provider
>>> Invalidated, it is still called. I  also read somewhere that each
>>> component
>>> is implemented as a Singleton by default, and I have not changed its
>>> behavior. So, I'm lost here. I expected that, in the above cenario,
>>> ProviderB would be called instead of ProviderA.
>>>
>>> Anyone has a clue that could help me understand how this mechanism works?
>>> Attached you can find a file with all my source code and ant tasks I'm
>>> using
>>> to play with iPOJO and OSGi.
>>>
>>> http://old.nabble.com/file/p32999833/OIA%2BCode.zip OIA+Code.zip
>>>
>>> Thanks a lot in advance!
>>> Fabio Fonseca
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> For additional commands, e-mail: users-help@felix.apache.org
>>
>>
>>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Mime
View raw message