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

Alex Sviridov ooo_saturn7 at mail.ru
Wed Aug 30 05:10:27 EDT 2017


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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/weld-dev/attachments/20170830/714edc35/attachment-0001.html 


More information about the weld-dev mailing list