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

Martin Kouba mkouba at redhat.com
Tue Sep 5 02:43:50 EDT 2017


This is expected. See also assignability rules [1].

You need to use TypeLiteral [2]:
instance.select(new TypeLiteral<Temp<Foo>>() {})

Martin

[1]
https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#assignable_parameters

[2]
https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#annotationliteral_typeliteral


Dne 4.9.2017 v 20:47 Alex Sviridov napsal(a):
> Hi Martin,
> 
> I am back with question about your solution. I have class Temp<Foo> and I
> create CDI bean using Instance.select(Temp.class).get().
> 
> However, I get Caused by: 
> org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: 
> Unsatisfied dependencies for type Temp with qualifiers @Default.
> 
> Could you say, how your solution can be used to create bean with generic?
> 
> 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>
>     <mailto: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>
>      > <mailto: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>
>      > <mailto: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>
>     <mailto: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>
>      > <mailto: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>
>      > <mailto: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>
>     <mailto: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>
>     <mailto: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>
>     <mailto: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

-- 
Martin Kouba
Senior Software Engineer
Red Hat, Czech Republic


More information about the weld-dev mailing list