4 Replies Latest reply on Nov 1, 2018 10:36 AM by javacoryd

    Injecting into an abstract type

    javacoryd

      We have a simple use case where we have this UI scenario:

       

      1) User logs in, a long running conversation is begun

      2) User enters in some information on a screen.

      3) Based on the information entered, the user is navigated to 1 of 4 "enter application" screens.  Each screen represents a type of "Application" and is backed by a concrete implementation of the abstract type "Application".  The concrete type is ConversationScoped.

      4) When the user is done filing out the application, they are navigated to a summary page to summarize the application.  All 4 screens will navigate to this summary screen.

       

      My question is, how do I @Inject the ConversationScoped "Application" into the abstract type in the summary screen?  Is this possible?

       

      Thanks!

       

      Cory.

        • 1. Re: Injecting into an abstract type
          manovotn

          Hello,

           

          you should be able to just @Inject Application there.

          What is the problem you are seeing, any exceptions?

          Can you show some code?

          • 2. Re: Injecting into an abstract type
            javacoryd

            So code sample:

             

            // Interface

             

            interface Application {

            }

             

            // Implementations

             

            @ConversationScoped

            class FixedApp implements Application {

            }

            @ConversationScoped

            class VariableApp implements Application {

            }

            @ConversationScoped

            class CustomApp implements Application {

            }

            @ConversationScoped

            class ExampleApp implements Application {

            }

             

            // Injection point

             

            @ConversationScoped

            class SomeClass {

             

            @Inject

            private Application someApp;

             

            }

             

            Upon deployment we get an "Ambiguous dependency" exception on the injection of "someApp".  At the injection point we don't care what implementation it is, we just want to deal with it via the "Application" interface.

             

            Thanks,

             

            Cory.

            • 3. Re: Injecting into an abstract type
              manovotn

              Alright, so I see no really simple solution for this. You currently have four valid beans of that type and qualifiers won't cut it, so we need to look for way around that.

               

              One way to solve it would be to create another @ConversationScoped bean, let's call it ApplicationHolder, and in this bean you would set the correct instance of Application implementation once you know it.

              You could have the 4 implementations differed by qualifiers and select the right one, or you could just instantiate the impl yourself assuming you don't need injection there.

              All access to Applicaiton would then have to be routed via ApplicationHolder which "knows" the correct instance.

               

              Another way would be to have all implementation of Application @Vetoed and then create a @Produces Application method. This method would return a @ConversationScoped bean picking one of the implementations based on some settings it can discern from current state (e.g. setting some value based on what information user enters on first screen?)

               

              Yet another solution coming to mind is a bit more hardcore-ish. You could leverage BeanManager and use it to grab the Context object (conversation context) - BeanManager#getContext().

              Then you could use Context#get(Contextual<T>) to grab the instance itself. To obtain Contextual<T> you could either @Inject Bean<T> (since Bean extends Contextual) or use some more methods from BM.

              • 4. Re: Injecting into an abstract type
                javacoryd

                Thanks Matej for your reply!

                 

                As you stated in your response I looked through all of the qualifier documentation and could find anything that would work for this use case as we don't  know the exact implementation at the injection point.

                 

                I ended up implementing your 1st solution and it works fine, I was just wondering if there was a better (more preferred) solution in CDI.

                 

                Thanks again for you time,

                 

                Cory.