[weld-dev] How to make method injection when bean subclass is required in Weld?

Matej Novotny manovotn at redhat.com
Wed Aug 30 07:17:26 EDT 2017


Hi,

yea you are right, I mis-read that. My bad.
Anyway, the ambiguous dep. problem still holds true and you have to use another approach.

Let us know if @Typed solves your problem or if we should try and find another solution.

Matej

----- Original Message -----
> From: "Alex Sviridov" <ooo_saturn7 at mail.ru>
> To: "weld-dev" <weld-dev at lists.jboss.org>
> Sent: Wednesday, August 30, 2017 11:55:11 AM
> Subject: Re: [weld-dev] How to make method injection when bean subclass is required in Weld?
> 
> Hi Matej
> 
> Thank you for your comment. However, note, that I wrote foo = newFoo() but
> not foo = new Foo();
> By other words foo is created in newFoo method, but not calling new operator.
> 
> Best regards, Alex
> 
> 
> 
> 
> Среда, 30 августа 2017, 12:45 +03:00 от Matej Novotny <manovotn at redhat.com>:
> 
> Hi Alex
> 
> What you suggest will inevitably fail for the reasons we mentioned
> previously.
> Both approaches will try to resolve a bean of type SimpleFoo which is
> ambiguous.
> 
> Furthermore, doing `foo = new Foo()` is like saying "goodbye CDI".
> If you do this, you control the lifecycle of such object, not CDI.
> Therefore, there will be no injection done into such object, neither will CDI
> be able to dispose of such object.
> 
> Matej
> 
> ----- Original Message -----
> > From: "Alex Sviridov" < ooo_saturn7 at mail.ru >
> > To: "weld-dev" < weld-dev at lists.jboss.org >
> > Sent: Wednesday, August 30, 2017 11:10:27 AM
> > Subject: Re: [weld-dev] How to make method injection when bean subclass is
> > required in Weld?
> > 
> > 
> > 
> > Hi Matej,
> > 
> > I meant the following (in previous example I had a mistake - called Parent
> > Child and Child Parent)
> > , now without this mistake:
> > 1)
> > public class Parent {
> > 
> > @Inject
> > private Instance<SimpleFoo> fooInstance;
> > 
> > private SimpleFoo foo;
> > 
> > protected SimpleFoo newFoo() {
> > return fooInstance.get();
> > }
> > 
> > @PostConstruct
> > private void doPostConstruct() {
> > foo = newFoo();
> > }
> > }
> > 
> > public class Child extends Parent {
> > 
> > @Inject
> > private Instance<AdvancedFoo> fooInstance;
> > 
> > @Override
> > protected AdvancedFoo newFoo() {
> > return fooInstance.get();
> > }
> > }
> > 
> > 
> > 2)
> > 
> > public class Parent {
> > 
> > @Inject
> > protected BeanManager beanManager;
> > 
> > private SimpleFoo foo;
> > 
> > protected SimpleFoo newFoo() {
> > SimpleFoo foo = constructing bean with BM;
> > return foo;
> > }
> > 
> > @PostConstruct
> > private void doPostConstruct() {
> > foo = newFoo();
> > }
> > }
> > 
> > public class Child extends Parent {
> > 
> > @Override
> > protected AdvancedFoo newFoo() {
> > AdvancedFoo foo = constructing bean with BM;
> > return foo;
> > }
> > }
> > 
> > Thank you for your explanation of Typed. I got it.
> > 
> > Best regards, Alex
> > 
> > 
> > Среда, 30 августа 2017, 10:51 +03:00 от Matej Novotny < manovotn at redhat.com
> > >:
> > 
> > 1) If you inject Instance<T>, you still have the ambiguous dependency issue
> > for any class which does have a subclass.
> > E.g. from your sample:
> > 
> > @Inject
> > Instance<SimpleFoo> instance;
> > 
> > //within some method
> > instance.get(); -> this will blow up because you have two beans which have
> > SimpleFoo type (SimpleFoo and AdvancedFoo)
> > 
> > 2) I don't understand what you mean by this. How does BM help here?
> > 
> > 
> > Sidenote:
> > You might want to try and use what Martin said - limiting the types of a
> > bean
> > with @Typed(MyClass.Foo).
> > That way you have control over the bean types and can further manupulate
> > the
> > injection.
> > Limit all your children to only the actual subclass type they have:
> > 
> > @Dependent
> > @Typed(AdvancedFoo.class)
> > public class AdvancedFoo extends SimpleFoo {
> > // this ben now only has a bean of AdvancedFoo, e.g. it does not fit into
> > injection point for SimpleFoo
> > }
> > 
> > And then override the initializer methods like this:
> > 
> > @Dependent
> > public class Parent extends Child {
> > 
> > @Inject
> > @Override
> > protected void setFoo(AdvancedFoo foo) {
> > this.foo = foo; // assuming foo is a protected field
> > }
> > }
> > 
> > Matej
> > 
> > 
> > ----- Original Message -----
> > > From: "Alex Sviridov" < ooo_saturn7 at mail.ru >
> > > To: "weld-dev" < weld-dev at lists.jboss.org >
> > > Sent: Tuesday, August 29, 2017 8:54:47 PM
> > > Subject: Re: [weld-dev] How to make method injection when bean subclass
> > > is
> > > required in Weld?
> > > 
> > > I thought here, and would like to share my ideas hoping to get comments
> > > from
> > > more experienced people.
> > > 
> > > First of all I came to conclusion that CDI works badly with cases when we
> > > need
> > > to change field values in super classes. If there is a lot of inheritance
> > > as
> > > in my case:
> > > ParentA, ChildA0, ChildA1.., ParentB, ChildB0, ChildB1..,... then
> > > situation
> > > is
> > > becoming very bad. Maybe in future there will be other solutions in CDI
> > > specs.
> > > 
> > > I found two additional ways that can be used. 1) Inject not beans but
> > > instances,
> > > + method SimpleFoo newFoo {return Instance<SimpleFoo>.get} + overriding.
> > > 2) Inject BeanManager + method SimpleFoo newFoo() {beanManager...} +
> > > overriding.
> > > 
> > > Maybe such ways can be named lazy/postponed initialization with
> > > overriding
> > > support....
> > > 
> > > Best regards, Alex
> > > 
> > > 
> > > 
> > > 
> > > Вторник, 29 августа 2017, 18:22 +03:00 от Martin Kouba <
> > > mkouba at redhat.com
> > > >:
> > > 
> > > Hi Alex,
> > > 
> > > that's an interesting question. Indeed, qualifiers are the way to go if
> > > you need to keep the method signature.
> > > 
> > > Another way could be to override the setFoo() method so that the Child
> > > initializer is ignored and add a new method to inject AdvancedFoo:
> > > 
> > > @Override
> > > protected void setFoo(SimpleFoo foo) { // Do nothing }
> > > 
> > > @Inject
> > > void setAdvancedFoo(AdvancedFoo foo) {
> > > super.setFoo(foo);
> > > }
> > > 
> > > However, note that right now there are the following beans:
> > > 
> > > SimpleFoo with bean types Object, SimpleFoo
> > > AdvancedFoo -> Object, SimpleFoo, AdvancedFoo
> > > 
> > > So if you do @Inject SimpleFoo you get ambiguous dependency exception
> > > because both SimpleFoo and AdvancedFoo are eligible for injection.
> > > 
> > > To resolve this you need to use qualifiers or restrict the bean types of
> > > AdvancedFoo:
> > > 
> > > @Typed(AdvancedFoo.class)
> > > class AdvancedFoo extends SimpleFoo {}
> > > 
> > > HTH
> > > 
> > > Martin
> > > 
> > > 
> > > Dne 29.8.2017 v 15:09 Matej Novotny napsal(a):
> > > > Hi Alex,
> > > > 
> > > > no need to be sorry, you have come to the right place :)
> > > > As for your question, the simplest thing is probably to use qualifiers.
> > > > 
> > > > Create your own like this:
> > > > 
> > > > @Qualifier
> > > > @Retention(RetentionPolicy.RUNTIME)
> > > > @Target({ ElementType.TYPE, ElementType.PARAMETER, ElementType.FIELD,
> > > > ElementType.METHOD })
> > > > public @interface MyQualifier {}
> > > > 
> > > > 
> > > > And then change your AdvancedFoo class to use the qualifier:
> > > > 
> > > > @Dependent
> > > > @MyQualifier
> > > > public class AdvancedFoo extends SimpleFoo {
> > > > }
> > > > 
> > > > And accordingly, the init method which uses injection should then look
> > > > like
> > > > this:
> > > > 
> > > > @Dependent
> > > > public class Parent extends Child {
> > > > 
> > > > @Inject
> > > > @Override
> > > > protected void setFoo(@MyQualifier SimpleFoo foo) {
> > > > super.setFoo(foo);
> > > > }
> > > > }
> > > > 
> > > > Does this answer your question?
> > > > 
> > > > Matej
> > > > 
> > > > ----- Original Message -----
> > > >> From: "Alex Sviridov" < ooo_saturn7 at mail.ru >
> > > >> To: "weld-dev" < weld-dev at lists.jboss.org >
> > > >> Sent: Tuesday, August 29, 2017 1:46:23 PM
> > > >> Subject: [weld-dev] How to make method injection when bean subclass is
> > > >> required in Weld?
> > > >> 
> > > >> Hi all,
> > > >> 
> > > >> I am really sorry for writing to this mailing list, but I checked all
> > > >> user
> > > >> forums and chats and saw that they are very old.
> > > >> 
> > > >> I would be very thankful if someone gives suggestion for solving the
> > > >> following problem.
> > > >> I have a child and parent class. Child has SimpleFoo, Parent needs
> > > >> Advaced
> > > >> foo. So,
> > > >> 
> > > >> @Dependent
> > > >> public class SimpleFoo {
> > > >> }
> > > >> 
> > > >> @Dependent
> > > >> public class AdvancedFoo extends SimpleFoo {
> > > >> }
> > > >> 
> > > >> @Dependent
> > > >> public class Child {
> > > >> 
> > > >> private SimpleFoo foo;
> > > >> 
> > > >> @Inject
> > > >> protected void setFoo(SimpleFoo foo) {
> > > >> this.foo = foo;
> > > >> }
> > > >> }
> > > >> 
> > > >> @Dependent
> > > >> public class Parent extends Child {
> > > >> 
> > > >> @Inject
> > > >> @Override
> > > >> protected void setFoo(SimpleFoo foo) { //How to inject here
> > > >> AdvancedFoo?
> > > >> super.setFoo(foo);
> > > >> }
> > > >> }
> > > >> 
> > > >> How to inject in Parent AdvancedFoo? I know that I can do it via
> > > >> constructor
> > > >> injection
> > > >> but I need method injection. How to do it? Can it be done without
> > > >> using
> > > >> names
> > > >> (like MyBean1)
> > > >> but only using classes (AdvancedFoo)?
> > > >> 
> > > >> Best regards, Alex
> > > >> 
> > > >> 
> > > >> 
> > > >> 
> > > >> 
> > > >> --
> > > >> Alex Sviridov
> > > >> 
> > > >> _______________________________________________
> > > >> weld-dev mailing list
> > > >> weld-dev at lists.jboss.org
> > > >> https://lists.jboss.org/mailman/listinfo/weld-dev
> > > > _______________________________________________
> > > > weld-dev mailing list
> > > > weld-dev at lists.jboss.org
> > > > https://lists.jboss.org/mailman/listinfo/weld-dev
> > > > 
> > > 
> > > --
> > > Martin Kouba
> > > Senior Software Engineer
> > > Red Hat, Czech Republic
> > > 
> > > 
> > > _______________________________________________
> > > weld-dev mailing list
> > > weld-dev at lists.jboss.org
> > > https://lists.jboss.org/mailman/listinfo/weld-dev
> > 
> > 
> > _______________________________________________
> > weld-dev mailing list
> > weld-dev at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/weld-dev
> 
> 
> _______________________________________________
> weld-dev mailing list
> weld-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/weld-dev



More information about the weld-dev mailing list