Discussion:
Problem with annotation injection in abstract classes
Jonathan Ariel
2008-11-25 19:57:36 UTC
Permalink
Hi! I'm trying to do something like this without good results. Am I doing
something wrong?

public abstract class A {
@Inject
protected C c;

}

public class B extends A {
}

public class C {
}



MutablePicoContainer container = new
PicoBuilder().withAnnotatedFieldInjection().build();
container.addComponent(C.class);
container.addComponent(B.class);

and finally in when I do:

B b = container.getComponent(B.class);

in b the field c is null. I think the expected behavior is c being injected
with an instance of C.

What do you think?

Thanks,

Jonathan
Putrycz, Erik
2008-11-25 21:36:00 UTC
Permalink
IMO, Guice 2 does a much better job with the injection... Pico is not very injection friendly...
Pico doesn't currently handle inheritance with the injection. I asked for that feature long ago...

Erik.

________________________________________
From: Jonathan Ariel [mailto:ionathan-***@public.gmane.org]
Sent: November 25, 2008 2:58 PM
To: user-qxt/k92ZUMzOYGyH7mwfjrEhcVWVsK+***@public.gmane.org
Subject: [picocontainer-user] Problem with annotation injection in abstract classes

Hi! I'm trying to do something like this without good results. Am I doing something wrong?

public abstract class A {
  @Inject
  protected C c;

}

public class B extends A {
}

public class C {
}



MutablePicoContainer container = new PicoBuilder().withAnnotatedFieldInjection().build();
container.addComponent(C.class);
container.addComponent(B.class);

and finally in when I do:

B b = container.getComponent(B.class);

in b the field c is null. I think the expected behavior is c being injected with an instance of C.

What do you think?

Thanks,

Jonathan

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Paul Hammant
2008-11-26 00:14:35 UTC
Permalink
Jonathan,

Fixed in revision 5083 for PicoContainer 2.7, thanks for reporting this.

If you can, you should really use Constructor Injection. Even the
Guice team recommends this :-)

I've emailed you a snapshot jar separately.

Regards,

- Paul
Post by Jonathan Ariel
Hi! I'm trying to do something like this without good results. Am I
doing something wrong?
public abstract class A {
@Inject
protected C c;
}
public class B extends A {
}
public class C {
}
MutablePicoContainer container = new
PicoBuilder().withAnnotatedFieldInjection().build();
container.addComponent(C.class);
container.addComponent(B.class);
B b = container.getComponent(B.class);
in b the field c is null. I think the expected behavior is c being
injected with an instance of C.
What do you think?
Thanks,
Jonathan
---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Jonathan Ariel
2008-11-26 00:23:53 UTC
Permalink
Thank you very much! Really great job!
I understand that using constructor injection is better, but I don't like it
when I have lots of dependencies (I mean 4 or 5 or even more). because that
mean lots of parameters on every constructor of every subclass. If I
discover that I need a new parameter in the super class constructor, I'll
have to go and change every subclass constructor.
Do you think there is a better way to do that?

BTW really good job with PicoContainer. Good documentation also!
Post by Paul Hammant
Jonathan,
Fixed in revision 5083 for PicoContainer 2.7, thanks for reporting this.
If you can, you should really use Constructor Injection. Even the Guice
team recommends this :-)
I've emailed you a snapshot jar separately.
Regards,
- Paul
Hi! I'm trying to do something like this without good results. Am I doing
Post by Jonathan Ariel
something wrong?
public abstract class A {
@Inject
protected C c;
}
public class B extends A {
}
public class C {
}
MutablePicoContainer container = new
PicoBuilder().withAnnotatedFieldInjection().build();
container.addComponent(C.class);
container.addComponent(B.class);
B b = container.getComponent(B.class);
in b the field c is null. I think the expected behavior is c being
injected with an instance of C.
What do you think?
Thanks,
Jonathan
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
Paul Hammant
2008-11-26 07:50:42 UTC
Permalink
Jonathan,
Post by Jonathan Ariel
Thank you very much! Really great job!
I understand that using constructor injection is better, but I don't
like it when I have lots of dependencies (I mean 4 or 5 or even
more). because that mean lots of parameters on every constructor of
every subclass. If I discover that I need a new parameter in the
super class constructor, I'll have to go and change every subclass
constructor.
Do you think there is a better way to do that?
Well five is a bit borderline, yes. Firstly, if you're using IDEA for
looking after your component set, then using the refactoring
"introduce parameter" can help lots - it you do that in the super
class, all subclasses will get it too. Then there's "Change method
signature" which IDEA and Eclipse have.

Alternatively, the purists may study the five components that are
dependencies and wonder if there is some separation of concerts. They
would try to look to see if there is some intermediate dependency that
could encompass the capabilities of, say, three of the components.
With the introduction of the intermediate component, you would see a
reduce number of deps going into the final one. Of course, that's
easy for me to say not having seen your set of components.

Are you using our @Inject annotation, or using your own one? You'd be
using your own one if you're aiming at having the least dependency on
PicoContainer's classbase.
Post by Jonathan Ariel
BTW really good job with PicoContainer. Good documentation also!
Thanks. We've been improving it over the last year or so :-)

Regards,

- Paul


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Daniel Wellman
2008-11-26 13:46:36 UTC
Permalink
Post by Paul Hammant
Well five is a bit borderline, yes. Firstly, if you're using IDEA for
looking after your component set, then using the refactoring "introduce
parameter" can help lots - it you do that in the super class, all subclasses
will get it too. Then there's "Change method signature" which IDEA and
Eclipse have.
Alternatively, the purists may study the five components that are
dependencies and wonder if there is some separation of concerts. They would
try to look to see if there is some intermediate dependency that could
encompass the capabilities of, say, three of the components. With the
introduction of the intermediate component, you would see a reduce number of
deps going into the final one. Of course, that's easy for me to say not
having seen your set of components.
I agree; I like Constructor Injection for a few reasons:

You know you always have all your dependencies when you get an instance of
your component from the container. You don't have to write any
"afterInitialized" method where you check that you really have all your
dependencies set -- Spring does this, I don't know about Guice. For testing
it's particularly nice because you know all your required dependencies by
looking at the constructor. With setter injection, it's up to the
programmer to look at all the bean properties and make sure they're all set
in the test.

Constructor injection is even more compelling when you are adding new
dependencies to existing classes -- the IDE will remind you that your test
objects are missing dependencies (because they are missing a constructor
parameter) whereas setter injection will probably cause the test to fail at
runtime with a NullPointerException.

Re: Too many dependencies

As Paul said, if you have too many dependencies, there's probably some other
abstraction which is trying to come out. Just like testing with mock
objects can tell you if your interfaces need rethinking ("Why do I have to
mock all these calls to get my code to work?"), long constructor lists can
tell if you if you have too many or unusual dependencies.

And yes, a good IDE will help you deal with the mechanics of introducing new
parameters, moving them, etc.

Dan
Jonathan Ariel
2008-11-26 15:24:11 UTC
Permalink
I agree. I'll change my code. Thanks! Good reasons :)
Post by Daniel Wellman
Post by Paul Hammant
Well five is a bit borderline, yes. Firstly, if you're using IDEA for
looking after your component set, then using the refactoring "introduce
parameter" can help lots - it you do that in the super class, all subclasses
will get it too. Then there's "Change method signature" which IDEA and
Eclipse have.
Alternatively, the purists may study the five components that are
dependencies and wonder if there is some separation of concerts. They would
try to look to see if there is some intermediate dependency that could
encompass the capabilities of, say, three of the components. With the
introduction of the intermediate component, you would see a reduce number of
deps going into the final one. Of course, that's easy for me to say not
having seen your set of components.
You know you always have all your dependencies when you get an instance of
your component from the container. You don't have to write any
"afterInitialized" method where you check that you really have all your
dependencies set -- Spring does this, I don't know about Guice. For testing
it's particularly nice because you know all your required dependencies by
looking at the constructor. With setter injection, it's up to the
programmer to look at all the bean properties and make sure they're all set
in the test.
Constructor injection is even more compelling when you are adding new
dependencies to existing classes -- the IDE will remind you that your test
objects are missing dependencies (because they are missing a constructor
parameter) whereas setter injection will probably cause the test to fail at
runtime with a NullPointerException.
Re: Too many dependencies
As Paul said, if you have too many dependencies, there's probably some
other abstraction which is trying to come out. Just like testing with mock
objects can tell you if your interfaces need rethinking ("Why do I have to
mock all these calls to get my code to work?"), long constructor lists can
tell if you if you have too many or unusual dependencies.
And yes, a good IDE will help you deal with the mechanics of introducing
new parameters, moving them, etc.
Dan
Jonathan Ariel
2008-11-27 15:06:42 UTC
Permalink
I seems to still have problems with this... and it is when I have more than
one level of inheritance... for example:

C extends B that extends A

B and A are abstract

in A I'm injecting D

when getting an instance of C from the container, D is null.
Post by Jonathan Ariel
I agree. I'll change my code. Thanks! Good reasons :)
Post by Daniel Wellman
Post by Paul Hammant
Well five is a bit borderline, yes. Firstly, if you're using IDEA for
looking after your component set, then using the refactoring "introduce
parameter" can help lots - it you do that in the super class, all subclasses
will get it too. Then there's "Change method signature" which IDEA and
Eclipse have.
Alternatively, the purists may study the five components that are
dependencies and wonder if there is some separation of concerts. They would
try to look to see if there is some intermediate dependency that could
encompass the capabilities of, say, three of the components. With the
introduction of the intermediate component, you would see a reduce number of
deps going into the final one. Of course, that's easy for me to say not
having seen your set of components.
You know you always have all your dependencies when you get an instance of
your component from the container. You don't have to write any
"afterInitialized" method where you check that you really have all your
dependencies set -- Spring does this, I don't know about Guice. For testing
it's particularly nice because you know all your required dependencies by
looking at the constructor. With setter injection, it's up to the
programmer to look at all the bean properties and make sure they're all set
in the test.
Constructor injection is even more compelling when you are adding new
dependencies to existing classes -- the IDE will remind you that your test
objects are missing dependencies (because they are missing a constructor
parameter) whereas setter injection will probably cause the test to fail at
runtime with a NullPointerException.
Re: Too many dependencies
As Paul said, if you have too many dependencies, there's probably some
other abstraction which is trying to come out. Just like testing with mock
objects can tell you if your interfaces need rethinking ("Why do I have to
mock all these calls to get my code to work?"), long constructor lists can
tell if you if you have too many or unusual dependencies.
And yes, a good IDE will help you deal with the mechanics of introducing
new parameters, moving them, etc.
Dan
Paul Hammant
2008-11-29 14:01:42 UTC
Permalink
Jonathan.

I can't reproduce :-(

Is the following representative ...............

public static abstract class A2 {
@Inject
protected D2 d2;
}

public static abstract class B2 extends A2 {
}

public static class C2 extends B2 {
}

public static class D2 {
}


@Test
public void testThatEvenMoreSuperClassCanHaveAnnotatedFields() {
MutablePicoContainer container = new
PicoBuilder().withAnnotatedFieldInjection().build();
container.addComponent(D2.class);
container.addComponent(C2.class);

C2 c2 = container.getComponent(C2.class);
assertNotNull(c2);
assertNotNull(c2.d2);
}

Regards,

- Paul
Post by Jonathan Ariel
I seems to still have problems with this... and it is when I have
C extends B that extends A
B and A are abstract
in A I'm injecting D
when getting an instance of C from the container, D is null.
I agree. I'll change my code. Thanks! Good reasons :)
Well five is a bit borderline, yes. Firstly, if you're using IDEA
for looking after your component set, then using the refactoring
"introduce parameter" can help lots - it you do that in the super
class, all subclasses will get it too. Then there's "Change method
signature" which IDEA and Eclipse have.
Alternatively, the purists may study the five components that are
dependencies and wonder if there is some separation of concerts.
They would try to look to see if there is some intermediate
dependency that could encompass the capabilities of, say, three of
the components. With the introduction of the intermediate
component, you would see a reduce number of deps going into the
final one. Of course, that's easy for me to say not having seen
your set of components.
You know you always have all your dependencies when you get an
instance of your component from the container. You don't have to
write any "afterInitialized" method where you check that you really
have all your dependencies set -- Spring does this, I don't know
about Guice. For testing it's particularly nice because you know
all your required dependencies by looking at the constructor. With
setter injection, it's up to the programmer to look at all the bean
properties and make sure they're all set in the test.
Constructor injection is even more compelling when you are adding
new dependencies to existing classes -- the IDE will remind you that
your test objects are missing dependencies (because they are missing
a constructor parameter) whereas setter injection will probably
cause the test to fail at runtime with a NullPointerException.
Re: Too many dependencies
As Paul said, if you have too many dependencies, there's probably
some other abstraction which is trying to come out. Just like
testing with mock objects can tell you if your interfaces need
rethinking ("Why do I have to mock all these calls to get my code to
work?"), long constructor lists can tell if you if you have too many
or unusual dependencies.
And yes, a good IDE will help you deal with the mechanics of
introducing new parameters, moving them, etc.
Dan
Jonathan Ariel
2008-11-30 04:43:45 UTC
Permalink
You are right... it is working, the problem appears when you use
withAutomatic() instead of withAnnotatedFieldInjection().
In my case I need both annotation and constructor injection. Do you think
that it should work when using withAutomatic?
Post by Paul Hammant
Jonathan.
I can't reproduce :-(
Is the following representative ...............
public static abstract class A2 {
@Inject
protected D2 d2;
}
public static abstract class B2 extends A2 {
}
public static class C2 extends B2 {
}
public static class D2 {
}
@Test
public void testThatEvenMoreSuperClassCanHaveAnnotatedFields() {
MutablePicoContainer container = new
PicoBuilder().withAnnotatedFieldInjection().build();
container.addComponent(D2.class);
container.addComponent(C2.class);
C2 c2 = container.getComponent(C2.class);
assertNotNull(c2);
assertNotNull(c2.d2);
}
Regards,
- Paul
I seems to still have problems with this... and it is when I have more than
C extends B that extends A
B and A are abstract
in A I'm injecting D
when getting an instance of C from the container, D is null.
Post by Jonathan Ariel
I agree. I'll change my code. Thanks! Good reasons :)
Post by Daniel Wellman
Post by Paul Hammant
Well five is a bit borderline, yes. Firstly, if you're using IDEA for
looking after your component set, then using the refactoring "introduce
parameter" can help lots - it you do that in the super class, all subclasses
will get it too. Then there's "Change method signature" which IDEA and
Eclipse have.
Alternatively, the purists may study the five components that are
dependencies and wonder if there is some separation of concerts. They would
try to look to see if there is some intermediate dependency that could
encompass the capabilities of, say, three of the components. With the
introduction of the intermediate component, you would see a reduce number of
deps going into the final one. Of course, that's easy for me to say not
having seen your set of components.
You know you always have all your dependencies when you get an instance
of your component from the container. You don't have to write any
"afterInitialized" method where you check that you really have all your
dependencies set -- Spring does this, I don't know about Guice. For testing
it's particularly nice because you know all your required dependencies by
looking at the constructor. With setter injection, it's up to the
programmer to look at all the bean properties and make sure they're all set
in the test.
Constructor injection is even more compelling when you are adding new
dependencies to existing classes -- the IDE will remind you that your test
objects are missing dependencies (because they are missing a constructor
parameter) whereas setter injection will probably cause the test to fail at
runtime with a NullPointerException.
Re: Too many dependencies
As Paul said, if you have too many dependencies, there's probably some
other abstraction which is trying to come out. Just like testing with mock
objects can tell you if your interfaces need rethinking ("Why do I have to
mock all these calls to get my code to work?"), long constructor lists can
tell if you if you have too many or unusual dependencies.
And yes, a good IDE will help you deal with the mechanics of introducing
new parameters, moving them, etc.
Dan
Paul Hammant
2008-11-30 07:48:32 UTC
Permalink
Should do. I'll look into it.

Regards,

- Paul
Post by Jonathan Ariel
You are right... it is working, the problem appears when you use
withAutomatic() instead of withAnnotatedFieldInjection().
In my case I need both annotation and constructor injection. Do you
think that it should work when using withAutomatic?
Jonathan.
I can't reproduce :-(
Is the following representative ...............
public static abstract class A2 {
@Inject
protected D2 d2;
}
public static abstract class B2 extends A2 {
}
public static class C2 extends B2 {
}
public static class D2 {
}
@Test
public void testThatEvenMoreSuperClassCanHaveAnnotatedFields() {
MutablePicoContainer container = new
PicoBuilder().withAnnotatedFieldInjection().build();
container.addComponent(D2.class);
container.addComponent(C2.class);
C2 c2 = container.getComponent(C2.class);
assertNotNull(c2);
assertNotNull(c2.d2);
}
Regards,
- Paul
Post by Jonathan Ariel
I seems to still have problems with this... and it is when I have
C extends B that extends A
B and A are abstract
in A I'm injecting D
when getting an instance of C from the container, D is null.
On Wed, Nov 26, 2008 at 1:24 PM, Jonathan Ariel
I agree. I'll change my code. Thanks! Good reasons :)
Well five is a bit borderline, yes. Firstly, if you're using IDEA
for looking after your component set, then using the refactoring
"introduce parameter" can help lots - it you do that in the super
class, all subclasses will get it too. Then there's "Change method
signature" which IDEA and Eclipse have.
Alternatively, the purists may study the five components that are
dependencies and wonder if there is some separation of concerts.
They would try to look to see if there is some intermediate
dependency that could encompass the capabilities of, say, three of
the components. With the introduction of the intermediate
component, you would see a reduce number of deps going into the
final one. Of course, that's easy for me to say not having seen
your set of components.
You know you always have all your dependencies when you get an
instance of your component from the container. You don't have to
write any "afterInitialized" method where you check that you really
have all your dependencies set -- Spring does this, I don't know
about Guice. For testing it's particularly nice because you know
all your required dependencies by looking at the constructor. With
setter injection, it's up to the programmer to look at all the bean
properties and make sure they're all set in the test.
Constructor injection is even more compelling when you are adding
new dependencies to existing classes -- the IDE will remind you
that your test objects are missing dependencies (because they are
missing a constructor parameter) whereas setter injection will
probably cause the test to fail at runtime with a
NullPointerException.
Re: Too many dependencies
As Paul said, if you have too many dependencies, there's probably
some other abstraction which is trying to come out. Just like
testing with mock objects can tell you if your interfaces need
rethinking ("Why do I have to mock all these calls to get my code
to work?"), long constructor lists can tell if you if you have too
many or unusual dependencies.
And yes, a good IDE will help you deal with the mechanics of
introducing new parameters, moving them, etc.
Dan
Paul Hammant
2008-12-01 01:04:38 UTC
Permalink
Yeah, I can repro and have fixed. It was to do with AdaptingInjection
which has duplicate code for sniffing for the @Inject annotation.

- Paul
Post by Jonathan Ariel
You are right... it is working, the problem appears when you use
withAutomatic() instead of withAnnotatedFieldInjection().
In my case I need both annotation and constructor injection. Do you
think that it should work when using withAutomatic?
Jonathan.
I can't reproduce :-(
Is the following representative ...............
public static abstract class A2 {
@Inject
protected D2 d2;
}
public static abstract class B2 extends A2 {
}
public static class C2 extends B2 {
}
public static class D2 {
}
@Test
public void testThatEvenMoreSuperClassCanHaveAnnotatedFields() {
MutablePicoContainer container = new
PicoBuilder().withAnnotatedFieldInjection().build();
container.addComponent(D2.class);
container.addComponent(C2.class);
C2 c2 = container.getComponent(C2.class);
assertNotNull(c2);
assertNotNull(c2.d2);
}
Regards,
- Paul
Post by Jonathan Ariel
I seems to still have problems with this... and it is when I have
C extends B that extends A
B and A are abstract
in A I'm injecting D
when getting an instance of C from the container, D is null.
On Wed, Nov 26, 2008 at 1:24 PM, Jonathan Ariel
I agree. I'll change my code. Thanks! Good reasons :)
Well five is a bit borderline, yes. Firstly, if you're using IDEA
for looking after your component set, then using the refactoring
"introduce parameter" can help lots - it you do that in the super
class, all subclasses will get it too. Then there's "Change method
signature" which IDEA and Eclipse have.
Alternatively, the purists may study the five components that are
dependencies and wonder if there is some separation of concerts.
They would try to look to see if there is some intermediate
dependency that could encompass the capabilities of, say, three of
the components. With the introduction of the intermediate
component, you would see a reduce number of deps going into the
final one. Of course, that's easy for me to say not having seen
your set of components.
You know you always have all your dependencies when you get an
instance of your component from the container. You don't have to
write any "afterInitialized" method where you check that you really
have all your dependencies set -- Spring does this, I don't know
about Guice. For testing it's particularly nice because you know
all your required dependencies by looking at the constructor. With
setter injection, it's up to the programmer to look at all the bean
properties and make sure they're all set in the test.
Constructor injection is even more compelling when you are adding
new dependencies to existing classes -- the IDE will remind you
that your test objects are missing dependencies (because they are
missing a constructor parameter) whereas setter injection will
probably cause the test to fail at runtime with a
NullPointerException.
Re: Too many dependencies
As Paul said, if you have too many dependencies, there's probably
some other abstraction which is trying to come out. Just like
testing with mock objects can tell you if your interfaces need
rethinking ("Why do I have to mock all these calls to get my code
to work?"), long constructor lists can tell if you if you have too
many or unusual dependencies.
And yes, a good IDE will help you deal with the mechanics of
introducing new parameters, moving them, etc.
Dan
Loading...