[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