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@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@mail.ru>
> To: "weld-dev" <weld-dev@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@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@mail.ru >
> >> To: "weld-dev" < weld-dev@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@lists.jboss.org
> >> https://lists.jboss.org/mailman/listinfo/weld-dev
> > _______________________________________________
> > weld-dev mailing list
> > weld-dev@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@lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/weld-dev