[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:55:11 EDT 2017


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

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


More information about the weld-dev mailing list