1 2 Previous Next 26 Replies Latest reply on Jan 26, 2010 5:20 PM by pmuir

    Error when using @SessionScoped and @Entity Annotation

    janey

      Hey all,


      i am trying to implement a simple WELD example with a jsf page to add a new account to the dateabase. My Problem is that as soon as I use a scope-annotation e.g. @SessionScoped and a @Entity Annotation I get following error when I try to perist the Account Object:


      20:47:15,700 ERROR Faces Servlet Servlet.service() for servlet Faces Servlet threw exception
       java.lang.IllegalArgumentException: Unknown entity: bankgroupServer.Account_$$_javassist_23
             at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:311)
             at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
             at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)




      The head of my Account.java looks like this:


      @SessionScoped
       @Named
       @Entity
       @Table(name = "tbl_Account")
       public class Account implements Serializable
       {    
              private static final long serialVersionUID = 1L;
              
              @Id
              @GeneratedValue(strategy = GenerationType.AUTO)
              private int accountNumber;
              
              private float amount = 0;
       [...]
       }



      My jsf-page looks like:


      <h:form id="account" styleClass="edit">
      
              <rich:panel>
                  <f:facet name="header">#{account.managed ? 'Edit' : 'Add'} Account</f:facet>            
                  Amount:
                  <h:inputText id="amountId" required="true" value="#{account.amount}" />                
              </rich:panel>
      
              <div class="actionButtons">
      
                  <h:commandButton id="save"
                                value="Save"
                               action="#{accountManager.createAccount}"
                             rendered="#{!account.managed}"/>
              </div>
          </h:form>
      



      My AccountBean.java looks like:


      @Named("accountManager")
      @SessionScoped
      @Stateful
      public class AccountBean implements Serializable, IAccountBeanLocal 
      {
              private static final long serialVersionUID = 1L;
              @Inject Account account;
              @Inject @BankDatabase EntityManager database;
              
          /**
           * Default constructor. 
           */
          public AccountBean() {
              // TODO Auto-generated constructor stub
          }
      
          /**
           * 
           */
          public void createAccount()
          {
              System.out.println(account.getAmount()); // --> Test if injection was correct
              database.persist(account); // --> Error occurs
          }
          
          @Remove
          public void destroy()
          {
          }
      }
      



      If I leave out the @SessionSyoped annotation in Account.java, I am able to persist the Account object without errors, but the account object I filled with the amount-value from the jsf page won't be injected but a new one will be created.


      Am I doing something principally wrong? Am I not able to use @Entity's with a scope??? Why can't the Entity be found if I define a scope?


      I guess if I use two diffenrent classes, one for the entity to persist and one for the bean that takes the values from the jsf page. I would need to copy the values from the one class to the entity class and then call persist. I guess that would work but do I really need 2 classes for one purpose????


      If you need the persistent.xml or anything else please just ask me to and I will post it.


      I can't get rid of the error above an I cant guess of working solution.  I need your help :)

        • 1. Re: Error when using @SessionScoped and @Entity Annotation
          alin.heyoulin.qq.com

          Scoped managed bean is javassist proxy. So you persist a javassist proxy rather than the entity. You can try @SessionScoped @Produces

          • 2. Re: Error when using @SessionScoped and @Entity Annotation
            gavin.king

            Right, we recommend against using scope annotations on entities.

            • 3. Re: Error when using @SessionScoped and @Entity Annotation
              janey

              Thank you for your quick replies.


              Sorry, but I am not sure if I understand you right.... where exactely do I habe to use the @SessionScoped @Produces? Should I completely delete the @SessionScoped annotation from the entity?

              • 4. Re: Error when using @SessionScoped and @Entity Annotation
                alin.heyoulin.qq.com

                @Entity
                 @Table(name = "tbl_Account")
                 public class Account implements Serializable
                 {    
                        private static final long serialVersionUID = 1L;
                        
                        @Id
                        @GeneratedValue(strategy = GenerationType.AUTO)
                        private int accountNumber;
                        
                        private float amount = 0;
                 [...]
                 }
                
                
                @Named("accountManager")
                @SessionScoped
                @Stateful
                public class AccountBean implements Serializable, IAccountBeanLocal 
                {
                        private static final long serialVersionUID = 1L;
                        @Inject Account account;
                        @Inject @BankDatabase EntityManager database;
                        
                    /**
                     * Default constructor. 
                     */
                    public AccountBean() {
                        // TODO Auto-generated constructor stub
                    }
                
                    /**
                     * 
                     */
                    public void createAccount()
                    {
                        System.out.println(account.getAmount()); // --> Test if injection was correct
                        database.persist(account); // --> Error occurs
                    }
                    
                    @Remove
                    public void destroy()
                    {
                    }
                    
                    
                    @SessionScoped @Produces
                    Account getAccount()
                    {
                       return new Account();
                    }
                
                }
                


                • 5. Re: Error when using @SessionScoped and @Entity Annotation
                  janey
                  Thanks he youlin.

                  I tried to use the @Produces @SessionScoped annotation within the AccountBean class. I changed the Account entity as you showed. When I use the classes as posted I am getting an "ambiguous dependencies" error (WELD wants a decision between Account() constructor and AccountBean.getAccount() ). To resolve the error I added a new qualifier @Preferred:

                  `
                  @Named("accountManager")
                  @SessionScoped
                  @Stateful
                  public class AccountBean implements Serializable, IAccountBeanLocal
                  {
                      /**
                       *
                       */
                      private static final long serialVersionUID = 1L;

                      /**
                       *
                       */
                      @Inject @Preferred Account account;

                      [...]

                      /**
                       *
                       */
                      public void createAccount()
                      {
                           System.out.println(account.getAmount());
                           database.persist(account);
                      }
                     
                      /**
                       *
                       * @return
                       */
                      @Produces @SessionScoped @Preferred
                      public Account getAccount()
                      {
                         return new Account();
                      }
                  }
                  `

                  But it still doesn't work. The Account object is not available in EL and in the AccountEdit.xhml. I am getting the Error:

                  '16:03:18,377 WARNING [lifecycle] /AccountEdit.xhtml @19,84 value="#{account.amount}": Target Unreachable, identifier 'account' resolved to null'

                  I thought this is because the @Named annotation is missing and added @Named to the getAccount() Method.

                  '    /**
                       *
                       * @return
                       */
                      @Produces @SessionScoped @Preferred @Named
                      public Account getAccount()
                      {
                         return new Account();
                      }
                  '

                  But this leads me again to the error of my first post:

                  '16:09:56,593 SEVERE [application] java.lang.RuntimeException: Error invoking method createAccount on interface bankgroupServer.IAccountBeanLocal
                  javax.faces.el.EvaluationException: java.lang.RuntimeException: Error invoking method createAccount on interface bankgroupServer.IAccountBeanLocal
                       at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
                       at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
                       at javax.faces.component.UICommand.broadcast(UICommand.java:315)
                  [...]
                  Caused by: javax.ejb.EJBException: java.lang.IllegalArgumentException: Unknown entity: bankgroupServer.Account_$$_javassist_23
                       at org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:77)
                       at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:83)
                       at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:190)

                  '

                  What is still wrong? I just want to open an xhtml page, create an account and persist it using a persistent entity.

                  I really want to understand WELD, but I don't get the point. I still need your help. Please :)

                  • 6. Re: Error when using @SessionScoped and @Entity Annotation
                    alin.heyoulin.qq.com
                    
                    Sorry. I just show you how to use @Produces. I know it doesn't work. I just think you understood @Produces.
                    
                    @Produces generally in individual class. So you can use as
                    
                    
                    public class someclass{
                    @Produces @SessionScoped @Named("account")
                        public Account getAccount()
                        {
                           return new Account();
                        }
                    }
                    If you use it in el. You can add @Name("something")
                    


                    • 7. Re: Error when using @SessionScoped and @Entity Annotation
                      janey

                      Thanks for your answer.


                      Did you read my complete post? I did what you just said but it still doesn't work. I know how to use @Produces. But it seems, that this still does not solve my problem. As I posted before, when I add @Named or @Named(account) (what both should be the same) I am facing again the same problem as described in my very first post. So the use of a @Produces method finally did not change anything.



                      Scoped managed bean is javassist proxy. So you persist a javassist proxy rather than the entity. You can try @SessionScoped @Produces

                      I principially understand that. But maybe I am too stupid to implement it in the right way.


                      Any other suggestions?

                      • 8. Re: Error when using @SessionScoped and @Entity Annotation
                        alin.heyoulin.qq.com
                        
                        Sounds Scoped Produces is proxy object too. I test as:
                        
                        public class someclass{
                        @Produces @SessionScoped @Named("account")
                            public Account getAccount()
                            {
                               return new Account();
                            }
                        }
                        
                        
                        @Named("accountManager")
                        @SessionScoped
                        @Stateful
                        public class AccountBean implements Serializable, IAccountBeanLocal 
                        {
                                private static final long serialVersionUID = 1L;
                                @Inject @Named("account") Account account;
                                @Inject @BankDatabase EntityManager database;
                                
                            /**
                             * Default constructor. 
                             */
                            public AccountBean() {
                                // TODO Auto-generated constructor stub
                            }
                        
                            /**
                             * 
                             */
                            public void createAccount()
                            {
                                System.out.println(account.getAmount()); // --> Test if injection was correct
                                database.persist(account); // --> Error occurs
                            }
                            
                            @Remove
                            public void destroy()
                            {
                            }
                          }
                        
                        throw Unknown entity. 
                        
                        I have no idea. :)
                        
                        
                        


                        • 9. Re: Error when using @SessionScoped and @Entity Annotation
                          meetoblivion

                          And it should...


                          You have to think about why you need a producer method.  All it does is wraps your beans in some potential BL that maybe executed - and is probably best used with objects that you don't control.  You're still doing the same thing in both cases. 


                          You can try to produce a dependent scoped object, or you can use it as a member of an object.

                          • 10. Re: Error when using @SessionScoped and @Entity Annotation
                            janey

                            Finally it makes sense that the same error occures. Sometimes you need to do it step by step to understand a thing.


                            As a dependend scope it works, but i need a scope unlike dependend to inject the object into my account bean keeping its values.


                            So is there no way to use a persistent entity in an EL context and persist it afterwards? Do I really need 2 classes? One as javassist proxy and one as entity class to persist?

                            • 11. Re: Error when using @SessionScoped and @Entity Annotation
                              meetoblivion

                              You could use a facade




                              @Stateful
                              @SessionScoped
                              @Named("something")
                              public class MyEntityFacade {
                                 private MyEntity myEntity;
                                 //put in code that inits your entity
                                 public void save() { /* do your save logic */ }
                                 public MyEntity getMyEntity() { return myEntity; }
                              
                              }



                              best I can think of.

                              • 12. Re: Error when using @SessionScoped and @Entity Annotation
                                gavin.king

                                Janey Masters wrote on Jan 09, 2010 20:09:


                                So is there no way to use a persistent entity in an EL context and persist it afterwards? Do I really need 2 classes? One as javassist proxy and one as entity class to persist?


                                This is definitely a way. You instantiate the entity inside another bean (with whatever scope is appropriate), and expose it to EL using @Produces. For example:



                                @RequestScoped @Named
                                public class NewUserAction {
                                   @Inject EntityManager em;
                                
                                   @Produces @Named
                                   private User newUser = new User();
                                
                                   public persist() {
                                      em.persist(newUser);
                                   }
                                }



                                Now you can refer to the User as #{newUser} in EL, and persist it using #{newUserAction.persist}. Easy!


                                Note that I'm going to write a portable extension to automagically register EntityHome beans for all beans in the application, so that you don't have to write code like this. Not sure of the details yet, I have to find time to think about it.

                                • 13. Re: Error when using @SessionScoped and @Entity Annotation
                                  alin.heyoulin.qq.com

                                  So is the newUser RequestScoped ?

                                  • 14. Re: Error when using @SessionScoped and @Entity Annotation
                                    janey

                                    Thank you all for your replies :)


                                    I will try your example Gavin. Thanks for posting!


                                    You helped me out of my black hole :)

                                    1 2 Previous Next