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

Alex Sviridov ooo_saturn7 at mail.ru
Thu Aug 31 06:12:02 EDT 2017


Hi Martin

Thank you very much for your comment and suggestion about improving.

Best regards, Alex


>Четверг, 31 августа 2017, 12:50 +03:00 от Martin Kouba <mkouba at redhat.com>:
>
>Hi Alex,
>
>1) should work but looks a little bit cumbersome. WRT 2) you should 
>avoid using BeanManager to create a bean instance whenever possible. And 
>in this particular case, if SimpleFoo is @Dependent it wouldn't be 
>destroyed correctly (@PreDestroy) when Parent or Child is destroyed.
>
>The following should also work (no need to have two Instance IPs):
>
>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 {
>
>       @Override
>       protected AdvancedFoo newFoo() {
>             return fooInstance.select(AdvancedFoo.class).get();
>       }
>  }
>
>
>Martin
>
>Dne 31.8.2017 v 11:07 Alex Sviridov napsal(a):
>> Hi Martin,
>> 
>> 
>> Could you comment the following solutions?
>> 
>> 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;
>>      }
>> }
>> 
>> 
>> Best regards, Alex
>> 
>>     Среда, 30 августа 2017, 10:51 +03:00 от Matej Novotny
>>     < manovotn at redhat.com <mailto: 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
>>     <mailto: ooo_saturn7 at mail.ru >>
>>      > To: "weld-dev" < weld-dev at lists.jboss.org
>>     <mailto: 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 <mailto: 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
>>     <mailto: ooo_saturn7 at mail.ru > >
>>      > >> To: "weld-dev" <  weld-dev at lists.jboss.org
>>     <mailto: 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 <mailto: weld-dev at lists.jboss.org >
>>      > >>  https://lists.jboss.org/mailman/listinfo/weld-dev
>>      > > _______________________________________________
>>      > > weld-dev mailing list
>>      > >  weld-dev at lists.jboss.org <mailto: 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 <mailto: weld-dev at lists.jboss.org >
>>      >  https://lists.jboss.org/mailman/listinfo/weld-dev
>> 
>> 
>> 
>> ------------------------------------------------------------------------
>> 
>> -- 
>> Alex Sviridov
>
>-- 
>Martin Kouba
>Senior Software Engineer
>Red Hat, Czech Republic


-- 
Alex Sviridov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/weld-dev/attachments/20170831/a3211b44/attachment-0001.html 


More information about the weld-dev mailing list