You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@felix.apache.org by Hynek Mlnařík <hm...@post.cz> on 2010/07/29 15:59:38 UTC

Component instances creation on demand

Hi,

I have two questions. To start with a simple one - is there a way to let iPOJO create default (empty) component instances on demand when requested by @Requested annotation? I only found a possibility of explicit instantiation via @Instantiate annotation explicitly but the on-demand one would be nice.

The second question might be linked to the previous one. I'd like to have a component (logger) that gets parametrized by requesting components. I found that a way to get it working might be using strategies like this:

@Component
@Provides(strategy="LoggerComponentStrategy")
class LoggerComponent implements LoggerComponentInterface {
 ...
}

public class LoggerComponentStrategy extends ConfigurableCreationStrategy implements ServiceObjectFactory {
    @Override
    protected ServiceObjectFactory getServiceFactory(final InstanceManager manager) {
        return this;
    }

    @Override
    public Object getService(final ComponentInstance instance) {
        final String name = instance.getInstanceDescription().getComponentDescription().getName();
        return safelyCreateLogger(name);
    }
  ...
}

@Component
@Instantiate
class B {
    @Requires LoggerComponentInterface l;
}

B gets only instantiated when the LoggerComponent class is annotated with @Instantiate annotation, ie. there already exists a Logger instance in iPOJO manager. That empty instance however is not used (and never will): the obtained instance of Logger injected into B must be parametrized with "B" name. Is there any way to have B initialize with the correct logger without the necessity of that useless empty Logger instance?

Thanks,

--Hynek

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


Re: Component instances creation on demand

Posted by clement escoffier <cl...@gmail.com>.
Hi,


2010/8/2 Hynek Mlnařík <hm...@post.cz>

> Thanks, now I see what's happening there.
>
> If the LoggerComponent had @Required fields and its instance was created
> via an explicit constructor, it wouldn't get an InstanceManager instance in
> __IM initialized: it is only initialized from iPOJO own constructor that
> wouldn't be called. Hence it also wouldn't evaluate any of the @Required
> fields. So if I understand it correctly, to make the @Required fields work:
>
> - Upon calling LoggerComponentStrategy.getServiceFactory(InstanceManager
> im), the strategy creates a new ServiceObjectFactory that is parametrized by
> im and returns it as its result.
> - This returned ServiceObjectFactory would implement
> getService(ComponentInstance) so that it invokes _setInstanceManager (via
> reflection as it is private) on the resulting iPOJO component instance,
> passing it the im instance manager as an argument. Then the @Required fields
> of the result would be able to provide correct values.
>

What about,in the LoggerComponentStrategy, calling
InstanceManager.createPojoObject() which call the correct constructor
(instead of new LoggerComponent). Then invoking a setName method to pass the
logger name ?

Calling InstanceManager.createPojoObject avoids to deal with the instance
manager injection as it injects it correctly.

Regards,

Clement



>
> --Hynek
>
> On 02.8.2010 13:51:27, clement escoffier wrote:
> > 2010/8/2 Hynek Mlnařík <hm...@post.cz>
> > > However the problem with calling a parameterless constructor remains.
> I've
> > > made a short research into the issue and created a test case which
> could be
> > > found at http://www.sendspace.com/file/imhlcx. It is a simple
> > > two-component sample (one component requires the other). The components
> are
> > > created programmatically (via IPOJOHelper class fragment taken from
> > > junit4osgi project). It correctly does not invoke a parameterless
> > > constructor of a.b.LoggerComponent when a.b.LoggerComponent class does
> not
> > > contain a @Validate annotated method. However, if such a method exists
> in
> > > the class, a parameterless constructor is invoked. This seems a bug to
> me.
> > > Could you please confirm it or let me know what I'm doing wrong?
> >
> > The @Validate callback will create the object using a parameterless
> > constructor. Indeed, to call the validate method, iPOJO needs to create
> an
> > object first. This object is created by using a parameterless argument or
> a
> > static factory method (@Component.factory_method). This method is also
> > called without parameters. If you want to set 'fields', just declare
> > properties and give the values in the instance configuration.
> >
> > But in your case, it will not help :-). You're using service object
> creation
> > strategy, so you can't use the @Validate annotation because both have
> > the responsibility to create the service objects. @Validate is called
> first
> > and immediately after the instance validation. The object is created
> using
> > the parameterless constructor. However, to get your code working
> correctly,
> > just call the method annotated with @Validate in the constructor and
> remove
> > the @Validate.
> > LoggerComponent(final String name) {
> >         this.name = name;
> >         System.out.println("constructor with parameter " + name);
> >         validateLoggerComponent(); // <-- Added
> > }
> >
> > Only the service providing strategy has the responsibility to create your
> > object. And so, it will call the correct constructor.
> >
> > Regards,
> >
> > Clement
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>
>

Re: Component instances creation on demand

Posted by Hynek Mlnařík <hm...@post.cz>.
Thanks, now I see what's happening there.

If the LoggerComponent had @Required fields and its instance was created via an explicit constructor, it wouldn't get an InstanceManager instance in __IM initialized: it is only initialized from iPOJO own constructor that wouldn't be called. Hence it also wouldn't evaluate any of the @Required fields. So if I understand it correctly, to make the @Required fields work:

- Upon calling LoggerComponentStrategy.getServiceFactory(InstanceManager im), the strategy creates a new ServiceObjectFactory that is parametrized by im and returns it as its result.
- This returned ServiceObjectFactory would implement getService(ComponentInstance) so that it invokes _setInstanceManager (via reflection as it is private) on the resulting iPOJO component instance, passing it the im instance manager as an argument. Then the @Required fields of the result would be able to provide correct values.

Is that correct?

--Hynek

On 02.8.2010 13:51:27, clement escoffier wrote:
> 2010/8/2 Hynek Mlnařík <hm...@post.cz>
> > However the problem with calling a parameterless constructor remains. I've
> > made a short research into the issue and created a test case which could be
> > found at http://www.sendspace.com/file/imhlcx. It is a simple
> > two-component sample (one component requires the other). The components are
> > created programmatically (via IPOJOHelper class fragment taken from
> > junit4osgi project). It correctly does not invoke a parameterless
> > constructor of a.b.LoggerComponent when a.b.LoggerComponent class does not
> > contain a @Validate annotated method. However, if such a method exists in
> > the class, a parameterless constructor is invoked. This seems a bug to me.
> > Could you please confirm it or let me know what I'm doing wrong?
> 
> The @Validate callback will create the object using a parameterless
> constructor. Indeed, to call the validate method, iPOJO needs to create an
> object first. This object is created by using a parameterless argument or a
> static factory method (@Component.factory_method). This method is also
> called without parameters. If you want to set 'fields', just declare
> properties and give the values in the instance configuration.
> 
> But in your case, it will not help :-). You're using service object creation
> strategy, so you can't use the @Validate annotation because both have
> the responsibility to create the service objects. @Validate is called first
> and immediately after the instance validation. The object is created using
> the parameterless constructor. However, to get your code working correctly,
> just call the method annotated with @Validate in the constructor and remove
> the @Validate.
> LoggerComponent(final String name) {
>         this.name = name;
>         System.out.println("constructor with parameter " + name);
>         validateLoggerComponent(); // <-- Added
> }
> 
> Only the service providing strategy has the responsibility to create your
> object. And so, it will call the correct constructor.
> 
> Regards,
> 
> Clement

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


Re: Component instances creation on demand

Posted by clement escoffier <cl...@gmail.com>.
Hi,


2010/8/2 Hynek Mlnařík <hm...@post.cz>

> Hi,
>
> thanks a lot for your explanations. Now I understand the desired iPOJO
> behaviour regarding instantiation much better.
>
> However the problem with calling a parameterless constructor remains. I've
> made a short research into the issue and created a test case which could be
> found at http://www.sendspace.com/file/imhlcx. It is a simple
> two-component sample (one component requires the other). The components are
> created programmatically (via IPOJOHelper class fragment taken from
> junit4osgi project). It correctly does not invoke a parameterless
> constructor of a.b.LoggerComponent when a.b.LoggerComponent class does not
> contain a @Validate annotated method. However, if such a method exists in
> the class, a parameterless constructor is invoked. This seems a bug to me.
> Could you please confirm it or let me know what I'm doing wrong?
>

The @Validate callback will create the object using a parameterless
constructor. Indeed, to call the validate method, iPOJO needs to create an
object first. This object is created by using a parameterless argument or a
static factory method (@Component.factory_method). This method is also
called without parameters. If you want to set 'fields', just declare
properties and give the values in the instance configuration.

But in your case, it will not help :-). You're using service object creation
strategy, so you can't use the @Validate annotation because both have
the responsibility to create the service objects. @Validate is called first
and immediately after the instance validation. The object is created using
the parameterless constructor. However, to get your code working correctly,
just call the method annotated with @Validate in the constructor and remove
the @Validate.
LoggerComponent(final String name) {
        this.name = name;
        System.out.println("constructor with parameter " + name);
        validateLoggerComponent(); // <-- Added
}

Only the service providing strategy has the responsibility to create your
object. And so, it will call the correct constructor.

Regards,

Clement


>
> Thanks,
>
> --Hynek
>
> On 30.7.2010, Clement Escoffier wrote:
> > Hi
> >
> > On 29.07.2010, at 15:59, Hynek Mlnařík wrote:
> >
> > > Hi,
> > >
> > > I have two questions. To start with a simple one - is there a way to
> let iPOJO
> > create default (empty) component instances on demand when requested by
> > @Requested annotation? I only found a possibility of explicit
> instantiation via
> > @Instantiate annotation explicitly but the on-demand one would be nice.
> >
> > No there is not @Requested annotation. The @Instantiate annotation
> declares an
> > instance. However:
> > - @Instantiate declares the instance BUT does not create the POJO object
> > (service object), which is created lazily. So, it's an empty shell until
> the
> > service object is required (if the component is not configure to be
> immediate).
> > - You can create iPOJO instances using the Factory service (exposed by
> all
> > 'public' component types). If you need to handle lazy instance
> declarations, you
> > can still use this API to create instances on the fly.
> >
> >
> > >
> > > The second question might be linked to the previous one. I'd like to
> have a
> > component (logger) that gets parametrized by requesting components. I
> found that
> > a way to get it working might be using strategies like this:
> > >
> > > @Component
> > > @Provides(strategy="LoggerComponentStrategy")
> > > class LoggerComponent implements LoggerComponentInterface {
> > > ...
> > > }
> > >
> > > public class LoggerComponentStrategy extends
> ConfigurableCreationStrategy
> > implements ServiceObjectFactory {
> > >    @Override
> > >    protected ServiceObjectFactory getServiceFactory(final
> InstanceManager
> > manager) {
> > >        return this;
> > >    }
> > >
> > >    @Override
> > >    public Object getService(final ComponentInstance instance) {
> > >        final String name =
> > instance.getInstanceDescription().getComponentDescription().getName();
> > >        return safelyCreateLogger(name);
> > >    }
> > >  ...
> > > }
> > >
> > > @Component
> > > @Instantiate
> > > class B {
> > >    @Requires LoggerComponentInterface l;
> > > }
> > >
> > > B gets only instantiated when the LoggerComponent class is annotated
> with
> > @Instantiate annotation, ie. there already exists a Logger instance in
> iPOJO
> > manager. That empty instance however is not used (and never will): the
> obtained
> > instance of Logger injected into B must be parametrized with "B" name. Is
> there
> > any way to have B initialize with the correct logger without the
> necessity of
> > that useless empty Logger instance?
> >
> > The LoggerComponent instance should not be created until B is really
> requiring
> > the logger. So, the 'getService' method should not be called before 'l'
> is
> > accessed.
> > Did you see a different behavior ?
> >
> >
> > Regards,
> >
> > Clement
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>
>

Re: Component instances creation on demand

Posted by Hynek Mlnařík <hm...@post.cz>.
Hi,

thanks a lot for your explanations. Now I understand the desired iPOJO behaviour regarding instantiation much better.

However the problem with calling a parameterless constructor remains. I've made a short research into the issue and created a test case which could be found at http://www.sendspace.com/file/imhlcx. It is a simple two-component sample (one component requires the other). The components are created programmatically (via IPOJOHelper class fragment taken from junit4osgi project). It correctly does not invoke a parameterless constructor of a.b.LoggerComponent when a.b.LoggerComponent class does not contain a @Validate annotated method. However, if such a method exists in the class, a parameterless constructor is invoked. This seems a bug to me. Could you please confirm it or let me know what I'm doing wrong?

Thanks,

--Hynek

On 30.7.2010, Clement Escoffier wrote:
> Hi
> 
> On 29.07.2010, at 15:59, Hynek Mlnařík wrote:
> 
> > Hi,
> > 
> > I have two questions. To start with a simple one - is there a way to let iPOJO
> create default (empty) component instances on demand when requested by
> @Requested annotation? I only found a possibility of explicit instantiation via
> @Instantiate annotation explicitly but the on-demand one would be nice.
> 
> No there is not @Requested annotation. The @Instantiate annotation declares an
> instance. However:
> - @Instantiate declares the instance BUT does not create the POJO object
> (service object), which is created lazily. So, it's an empty shell until the
> service object is required (if the component is not configure to be immediate).
> - You can create iPOJO instances using the Factory service (exposed by all
> 'public' component types). If you need to handle lazy instance declarations, you
> can still use this API to create instances on the fly. 
> 
> 
> > 
> > The second question might be linked to the previous one. I'd like to have a
> component (logger) that gets parametrized by requesting components. I found that
> a way to get it working might be using strategies like this:
> > 
> > @Component
> > @Provides(strategy="LoggerComponentStrategy")
> > class LoggerComponent implements LoggerComponentInterface {
> > ...
> > }
> > 
> > public class LoggerComponentStrategy extends ConfigurableCreationStrategy
> implements ServiceObjectFactory {
> >    @Override
> >    protected ServiceObjectFactory getServiceFactory(final InstanceManager
> manager) {
> >        return this;
> >    }
> > 
> >    @Override
> >    public Object getService(final ComponentInstance instance) {
> >        final String name =
> instance.getInstanceDescription().getComponentDescription().getName();
> >        return safelyCreateLogger(name);
> >    }
> >  ...
> > }
> > 
> > @Component
> > @Instantiate
> > class B {
> >    @Requires LoggerComponentInterface l;
> > }
> > 
> > B gets only instantiated when the LoggerComponent class is annotated with
> @Instantiate annotation, ie. there already exists a Logger instance in iPOJO
> manager. That empty instance however is not used (and never will): the obtained
> instance of Logger injected into B must be parametrized with "B" name. Is there
> any way to have B initialize with the correct logger without the necessity of
> that useless empty Logger instance?
> 
> The LoggerComponent instance should not be created until B is really requiring
> the logger. So, the 'getService' method should not be called before 'l' is
> accessed. 
> Did you see a different behavior ?
> 
> 
> Regards,
> 
> Clement

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


Re: Component instances creation on demand

Posted by Clement Escoffier <cl...@gmail.com>.
Hi

On 29.07.2010, at 15:59, Hynek Mlnařík wrote:

> Hi,
> 
> I have two questions. To start with a simple one - is there a way to let iPOJO create default (empty) component instances on demand when requested by @Requested annotation? I only found a possibility of explicit instantiation via @Instantiate annotation explicitly but the on-demand one would be nice.

No there is not @Requested annotation. The @Instantiate annotation declares an instance. However:
- @Instantiate declares the instance BUT does not create the POJO object (service object), which is created lazily. So, it's an empty shell until the service object is required (if the component is not configure to be immediate).
- You can create iPOJO instances using the Factory service (exposed by all 'public' component types). If you need to handle lazy instance declarations, you can still use this API to create instances on the fly. 


> 
> The second question might be linked to the previous one. I'd like to have a component (logger) that gets parametrized by requesting components. I found that a way to get it working might be using strategies like this:
> 
> @Component
> @Provides(strategy="LoggerComponentStrategy")
> class LoggerComponent implements LoggerComponentInterface {
> ...
> }
> 
> public class LoggerComponentStrategy extends ConfigurableCreationStrategy implements ServiceObjectFactory {
>    @Override
>    protected ServiceObjectFactory getServiceFactory(final InstanceManager manager) {
>        return this;
>    }
> 
>    @Override
>    public Object getService(final ComponentInstance instance) {
>        final String name = instance.getInstanceDescription().getComponentDescription().getName();
>        return safelyCreateLogger(name);
>    }
>  ...
> }
> 
> @Component
> @Instantiate
> class B {
>    @Requires LoggerComponentInterface l;
> }
> 
> B gets only instantiated when the LoggerComponent class is annotated with @Instantiate annotation, ie. there already exists a Logger instance in iPOJO manager. That empty instance however is not used (and never will): the obtained instance of Logger injected into B must be parametrized with "B" name. Is there any way to have B initialize with the correct logger without the necessity of that useless empty Logger instance?

The LoggerComponent instance should not be created until B is really requiring the logger. So, the 'getService' method should not be called before 'l' is accessed. 
Did you see a different behavior ?


Regards,

Clement

> 
> Thanks,
> 
> --Hynek
> 
> ---------------------------------------------------------------------
> 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