[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