6 Replies Latest reply on Nov 20, 2009 6:11 PM by Arbi Sookazian

    Producer method - simple example

    Arbi Sookazian Master

      which of the below are valid producer method examples?


      @ApplicationScoped
      public class Foo {
           private String foo = "bar";
           @Produces @Named String getFoo() {
                return foo;
           }
      }



      @SessionScoped
      public class Foo {
           private String foo = "bar";
           @Produces String getFoo() {
                return foo;
           }
      }



      public class Foo {
           private String foo = "bar";
           @Produces @Named String getFoo() {
                return foo;
           }
      }



      What's the difference if the @Named is at the type level instead of method level?


      Also, in this example from the ref doc:


      @ApplicationScoped
      public class RandomNumberGenerator {
      private Random random = new Random(System.currentTimeMillis());
      @Produces @Named @Random int getRandomNumber() {
      return random.nextInt(100);
      }
      }



      then:


      @Inject @Random int randomNumber;



      so must it be randomNumber for the injected instance variable name?  So whatever the getter name is minus get prefix??


      and yes, I did read the producer fields section in the spec this time prior to posting.


      ok, how bout this one:


      public class Shop {
      @Produces PaymentProcessor getPaymentProcessor() { ... }
      @Produces List<Product> getProducts() { ... }
      }



      would be injected as such?


      @Inject PaymentProcessor paymentProcessor;



      and


      @Inject List<Product> products;



      So in this final example, which scope is involved in the production of the producer methods?


      How does producer field or method differ from outjection in Seam?

        • 1. Re: Producer method - simple example
          Gavin King Master

          which of the below are valid producer method examples?

          All three are valid beans. At least, Weld will not throw any exception. Of course, they don't do anything useful.



          so must it be randomNumber for the injected instance variable name? So whatever the getter name is minus "get" prefix??

          No! I don't think you've been paying much attention to what you're reading. This is typesafe injection. The name of the field is totally unimportant.

          • 2. Re: Producer method - simple example
            Arbi Sookazian Master

            Ok, so here's an example of typesafe injection vs. typeunsafe injection (or the EE 5 way):


            @Inject @CustomerDatabase EntityManager



            @PersistenceContext(unitName="CustomerDatabase") EntityManager



            So the concept here is that you could make a typo in unitName element which would not be caught by the compiler and would result in a deploytime or runtime exception.


            Is this the main advantage (or problem solved) by typesafe injection?  Possibly looks more concise as well.


            Also, I did not see the definition for @CustomerDatabase in the spec or ref doc.  Is that omission done on purpose or am I totally missing something?


            • 3. Re: Producer method - simple example
              Gavin King Master

              Is this the main advantage (or problem solved) by typesafe injection?

              Um. Sure.



              Also, I did not see the definition for @CustomerDatabase in the spec or ref doc. Is that omission done on purpose or am I totally missing something?

              Yes, you're totally missing the notion of qualifiers. It's a user-defined annotation.

              • 4. Re: Producer method - simple example
                Arbi Sookazian Master

                I had a feeling it's user-defined or custom (must be so if it's not in the API docs: http://docs.jboss.org/cdi/api/1.0/).


                So it seems to me that the code for the user-defined annotation of @CustomerDatabase should be included in the spec, no?  Just to be clear?


                Also, in section 2.3. Qualifiers of the spec, I don't see the code for @Synchronous or @Asynchronous and they're custom qualifiers b/c they're not in the API doc.


                So I sort of get the concept but it's more difficult when the examples are most totally flushed out in terms of showing the custom annotation definition code...


                and what if you wanted to override the qualifier annotations via XML for different envmts?  Is that possible?

                • 5. Re: Producer method - simple example
                  Arbi Sookazian Master

                  sorry! the definitions are here:


                  2.3.2. Defining new qualifier types


                  @Qualifier
                  @Retention(RUNTIME)
                  @Target({METHOD, FIELD, PARAMETER, TYPE})
                  public @interface Synchronous {}



                  @Qualifier
                  @Retention(RUNTIME)
                  @Target({METHOD, FIELD, PARAMETER, TYPE})
                  public @interface Asynchronous {}

                  • 6. Re: Producer method - simple example
                    Arbi Sookazian Master

                    ok, i think i got it now (this particular concept doesn't seem to be too difficult).


                    you use @Qualifier as a meta-annotation when you write a custom qualifier annotation @Foo@Foo is used at the type level for a class and at the field level when you need to inject an instance.  This way the container knows which implementation of the interface you actually want to inject.


                    would it be possible to use a custom qualifer for an interface instead of a class?


                    ex:


                    @Synchronous
                    pubilc interface SynchronousPaymentProcessor
                    extends PaymentProcessor {
                    ...
                    }



                    So I guess it's important to understand the advantage of this technique/strategy.  If you do this instead:


                    @Inject SynchronousPaymentProcessor paymentProcessor;


                    and you have this code in dozens of classes, then when you want to refactor to this (for all cases):


                    @Inject AsynchronousPaymentProcessor paymentProcessor;


                    Then you have to change multiple classes.


                    But if you use a qualifier, you still have to change all instances of @Synchronous to @Asynchronous in all the affected classes to affect the change for the refactor, no?


                    hmm...


                    unless you do this:


                    @Synchronous
                    class AsynchronousPaymentProcessor
                    implements PaymentProcessor {
                    ...
                    }



                    which obviously is not a good idea


                    the bottom line is that the container is dynamically plugging in the correct implementation for the interface as directed by the qualifier...