6 Replies Latest reply on Feb 3, 2010 10:31 AM by andy.miller

    Context Lookup vs. Injection

    andy.miller

      I was playing around with the UUIDKeyGeneratorFactory in an EJB 3 application, to generate a primary key.  Hibernate actually supports its own annotations for this (non-JPA standard), but I was wondering about using the KeyGeneratorFactory directly as an alternative.  I can definitely just create an IntialContext, and lookup "UUIDKeyGeneratorFactory", and that works as expected, and that's been in the application server since 3.2.x.

       

      Is there a way to use EJB 3 @Resource annotation to inject the UUIDKeyGeneratorFactory.  I tried it in the code, but it didn't work, but maybe I missed something, or maybe the @Resource annotation isn't generalized to lookup anything in JNDI.

       

      Anyway, if someone could shed some light on the subject that would be helpful.

       

      Thanks.

        • 1. Re: Context Lookup vs. Injection
          jaikiran

          How about:

           

          @Resource(mappedName="jndiNameOfUUIDKeyGeneratorFactory")
          • 2. Re: Context Lookup vs. Injection
            andy.miller

            jaikiran wrote:

             

            How about:

             

            @Resource(mappedName="jndiNameOfUUIDKeyGeneratorFactory")
            

            I tried that, but it didn't work.  Just get a NullPointerException when I try to reference the factory. Specifically, the following wiki shows how to do it the old way:

             

            http://community.jboss.org/wiki/KeyGenerator

             

            InitialContext ctx = new InitialContext();
               KeyGeneratorFactory kgf = (KeyGeneratorFactory) ctx.lookup("UUIDKeyGeneratorFactory");
               KeyGenerator kg = kgf.getKeyGenerator();
               Object uuid = kg.generateKey();

             

            Which works just fine.  So, I tried the following:

             

            @Resource(mappedName="UUIDKeyGeneratorFactory")

             

            I tried other things as well, such as java:comp/env/UUIDKeyGeneratorFactory, and java:/UUIDKeyGeneratorFactory, and others, but none of them worked.  Unfortunately, I couldn't find anything in the console that showed its JNDI name either.

            • 3. Re: Context Lookup vs. Injection
              jaikiran

              Sorry, forgot about this discussion.

               


              andy.miller@jboss.com wrote:

               

              I tried that, but it didn't work.  Just get a NullPointerException when I try to reference the factory. Specifically, the following wiki shows how to do it the old way:

               

              http://community.jboss.org/wiki/KeyGenerator

               

               

              I tried this today and it worked fine for me. Here's the EJB3 SLSB into which i am injecting this as a @Resource:

               

              public interface KeyGenerator
              {
                 Object generateKey();
              }
              
              

               

              @Stateless
              @Remote(KeyGenerator.class)
              @RemoteBinding(jndiBinding = SimpleSLSB.JNDI_NAME)
              public class SimpleSLSB implements KeyGenerator
              {
              
                 public static final String JNDI_NAME = "KeyGeneratorFactoryInjectionTestBean";
                 
                 @Resource (mappedName="UUIDKeyGeneratorFactory")
                 private KeyGeneratorFactory keygenFactory;
              
                 public Object generateKey()
                 {
                    if (this.keygenFactory == null)
                    {
                       throw new RuntimeException("Key generator factory was not injected");
                    }
                    try
                    {
                       return this.keygenFactory.getKeyGenerator().generateKey();
                    }
                    catch (Exception e)
                    {
                       throw new RuntimeException("Could not generate key: ", e);
                    }
              
                 }
              
              }
              

               

              And then a testcase which invokes on this bean, which then internally uses the keygenfactory to create a keygen and then the key:

               

              public class KeyGeneratorFactoryInjectionTestCase extends JBossTestCase
              {
              
                 private static Logger logger = Logger.getLogger(KeyGeneratorFactoryInjectionTestCase.class);
                 
                 public KeyGeneratorFactoryInjectionTestCase(String name)
                 {
                    super(name);
                 }
                 
                 public static Test suite() throws Exception
                 {
                    return getDeploySetup(KeyGeneratorFactoryInjectionTestCase.class, "keygenfactory-injection.jar");
                 }
              
                 public void testKeyGeneration() throws Exception
                 {
                    KeyGenerator keyGenerator = (KeyGenerator) this.getInitialContext().lookup(SimpleSLSB.JNDI_NAME);
                    Object key = keyGenerator.generateKey();
                    logger.info("Generated key: " + key);
                    assertNotNull("Key generator generated a null key", key);
                 }
              }
              

               

               

              Passes:

               [junit] Running org.jboss.test.ejb3.keygenfactory.injection.unit.KeyGeneratorFactoryInjectionTestCase
                  [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 1.178 sec
              
              

               

              And here's the generated key:

               

              2010-02-03 18:31:59,388 INFO  [org.jboss.test.ejb3.keygenfactory.injection.unit.KeyGeneratorFactoryInjectionTestCase] Generated key: 93EC42DA7F00000101C47F7C5549F6EB
              
              
              • 4. Re: Context Lookup vs. Injection
                andy.miller

                Okay, so it works from a stateless session bean.  I am trying to use it in an entity for the primary key, which today looks like this:

                 

                @Id
                @GeneratedValue(generator="system-uuid")
                @GenericGenerator(name = "system-uuid", strategy = "uuid")
                public String getOrderId () {
                       
                    return orderId;
                       
                }

                 

                These are the Hibernate specific annotation (non-JPA) that do what I want.  I tried to replace those by injecting the key generator factory and using it in the default constructor of the entity.

                 

                So, code that looks like this:

                 

                @Entity
                public class Order implements Serializable {
                   
                    /**
                    *
                    */
                    private static final long serialVersionUID = -5721274468042182248L;
                    private String orderId;
                    private long customerId;
                    private Address shippingAddress;
                    private BigDecimal totalOrderAmount;
                    private List<OrderLine> orderLines;
                    private Customer customer;

                 

                   @Resource(mappedName="UUIDKeyGeneratorFactory")

                   KeyGeneratorFactory keyGeneratorFactory;
                   
                    public Order() {

                 

                        shippingAddress  = new Address();
                        totalOrderAmount = new BigDecimal(0);

                 

                        orderId = (String) keyGeneratoryFactory.getKeyGenerator().generateKey();
                       
                    }
                   
                    @Id
                    public String getOrderId () {
                       
                        return orderId;
                       
                    }

                 

                Is there a difference in @Resource in a stateless session bean and an entity?

                • 5. Re: Context Lookup vs. Injection
                  jaikiran

                  andy.miller@jboss.com wrote:

                   


                  Is there a difference in @Resource in a stateless session bean and an entity?

                  JPA entities don't support injection.

                  • 6. Re: Context Lookup vs. Injection
                    andy.miller

                    jaikiran wrote:

                     

                    andy.miller@jboss.com wrote:

                     


                    Is there a difference in @Resource in a stateless session bean and an entity?

                    JPA entities don't support injection.

                    Well, that explains it.  I will have to do what you did, which is inject the resource into a stateless session bean, and then pass the generated key to the constructor instead.  Thanks.