9 Replies Latest reply on Sep 2, 2011 4:03 PM by Jason Porter

    Seam 3 Security. Identitysession and transaction: when is my user saved in the Database

    Emeric Kwemou Newbie

      Hi all,
      my code is just a copy of the IDM Console example in seam.security
      1-i can successfully create a user
      2-but if i want to create a user, AND update the user password in the same SESSION, then i have an error because the user i just saved cannot be retrived for subsequent operations (see the code example below).


      Please can somebody tell me what i am missing here?


      This is the code i use:



      @Named
      @Transactional
      public class TUserAction implements Serializable {
           private static final long serialVersionUID = 5820385095080724087L;
      
           private static final String ATTRIBUTE_NAME_USER_ENABLED = "USER_ENABLED";
      
           @Inject
           private IdentitySession identitySession;
      
           @Transactional
           public void createUser(String username, String password)
                     throws IdentityException {
                PersistenceManager manager = identitySession.getPersistenceManager();
                User user = manager.createUser(username);
                       //If the method was just the lines of codes above, then i would not have any error, and i can see in the database that the user have been created.
                       //but it i add the next line, then:
                User user2 = manager.findUser(username);
                      assert user2 !=null; //This will throw an assertion error since user2 cannot be found. Here is my problem
                
                     identitySession.getAttributesManager().updatePassword(user, password);//This will throw an exception: javax.persistence.NoResultException: No User found emeric
           }



        • 1. Re: Seam 3 Security. Identitysession and transaction: when is my user saved in the Database
          Jason Porter Master

          I'm not all that familiar with Security code, hopefully Shane can answer with something better than mine, but here goes. My guess is that unless you do a flush on the underlying EntityManager it will not be put to the database until the transaction ends (which will be the end of the method). Why you get the exception could be something to do with the scoping of the EntityManager, or perhaps it's using another instance, not 100% sure there.

          • 2. Re: Seam 3 Security. Identitysession and transaction: when is my user saved in the Database
            Emeric Kwemou Newbie

            Thank you,
            First, i am using JPA Persistence Store.
            i think it is the same EntityManager since only one persistence.xml/datasource has been defined for my project.
            If the transaction end at the end of the method, then i expect that i should be able to query and retrieve objects alltought everything is only in the cache and i not flushed.


            Is it possible that the PersistenceManager and the AttributeManager uses differents instances of the JPA persistence unit? That are unaware from each other?
            The first store operation uses IdentitySession.PersistenceManager. The second uses IdentitySession.AttributeManager.


            But i really wonder since this code snippet is the same as in UserAction (seam)


            Please Help!!!
            Beat regards
            Emeric

            • 3. Re: Seam 3 Security. Identitysession and transaction: when is my user saved in the Database
              Shane Bryzak Master

              It should be using the same EntityManager, which must be provided by you via a producer method or field.  Have you tried Jason's suggestion of flushing the EM in between creating the user and updating their password?

              • 4. Re: Seam 3 Security. Identitysession and transaction: when is my user saved in the Database
                Emeric Kwemou Newbie

                Yes i tried it:
                first tried with: identitySession.save(); without sucess
                then also tried:
                em.flush();//em was injected first.
                The error is really fustrating me.
                May be you have other suggestions for me?
                Thank you in advance
                Emeric

                • 5. Re: Seam 3 Security. Identitysession and transaction: when is my user saved in the Database
                  Emeric Kwemou Newbie
                  I Think this error occurs with a postgres database when the identity type for USER is not defined.
                  the following query in org.jboss.seam.security.management.picketlink.JpaIdentityStore.findIdentityObject(IdentityStoreInvocationContext, String, IdentityObjectType):

                   

                  ` Object identity = getEntityManager(invocationContext).createQuery("select i from " +
                                identityClass.getName() + " i where i." +
                                modelProperties.get(PROPERTY_IDENTITY_NAME).getName() +
                                " = :name and i." + modelProperties.get(PROPERTY_IDENTITY_TYPE).getName() +
                                " = :type")
                                .setParameter("name", name)
                                .setParameter("type", identityType)             
                                .getSingleResult();`
                  will be translated to the following SQL Statement



                  select
                       identityob0_.id as id21_,
                       identityob0_.object_name as object2_21_,
                       identityob0_.IDENTITY_OBJECT_TYPE_ID as IDEN

                  from
                       telpay.IdentityObject identityob0_
                  where
                       identityob0_.object_name='emeric'
                       and identityob0.IDENTITY_OBJECT_TYPE_ID = null
                       limit 1


                  IDENTITY_OBJECT_TYPE_ID is null since Identity types are not defined in the database.

                  The SQL Statement return 0 rows with postgresSQL
                  We should instead use the foillowing SQL Statement IN THE CASE WHEN if identityType is null:


                  select
                       identityob0_.id as id21_,
                       identityob0_.object_name as object2_21_,
                       identityob0_.IDENTITY_OBJECT_TYPE_ID as IDEN

                  from
                       telpay.IdentityObject identityob0_
                  where
                       identityob0_.object_name='emeric'
                       and identityob0.IDENTITY_OBJECT_TYPE_ID is null
                       limit 1

                  But for the moment, my workaround is to make sure that the identitytypes are initialized in the database.
                  Best regards
                  Emeric
                  • 6. Re: Seam 3 Security. Identitysession and transaction: when is my user saved in the Database
                    Emeric Kwemou Newbie

                    Problem is now solved.
                    The solution is to make sure that the rigth IdentityObjectType are created in the database.
                    So i wrote the following lines in my SeedDataImport Bean.
                    But one can first make sure that the types does not exists before creating them again




                         private void createObjectTypes() {
                              IdentityObjectType userType = new IdentityObjectType();
                              userType.setName("USER");
                              em.persist(userType);
                              IdentityObjectType roleType = new IdentityObjectType();
                              roleType.setName("ROLE");
                              em.persist(roleType);
                              IdentityObjectType grpType = new IdentityObjectType();
                              grpType.setName("GROUP");
                              em.persist(grpType);
                              IdentityObjectCredentialType credentialType = new IdentityObjectCredentialType();
                              credentialType.setName("PASSWORD");
                              em.persist(credentialType);
                         }



                    • 7. Re: Seam 3 Security. Identitysession and transaction: when is my user saved in the Database
                      Jason Porter Master

                      I certainly want to do a bump on this one. This is a very big gotcha. I wasted four hours with this. Fortunately I remembered about this thread. Thank you very much for figuring this out Emeric. Hero in my book :)

                      • 8. Re: Seam 3 Security. Identitysession and transaction: when is my user saved in the Database
                        Richard Barabe Newbie

                        We can see an example of this in the identity management console in the class org.jboss.seam.security.examples.idmconsole.model.PopulateDatabase :




                        // Object types
                        IdentityObjectType USER = new IdentityObjectType();
                        USER.setName("USER");
                        entityManager.persist(USER);
                                
                        IdentityObjectType GROUP = new IdentityObjectType();
                        GROUP.setName("GROUP");
                        entityManager.persist(GROUP);



                        But, in that class we don't see any IdentityObjectType named ROLE as emeric suggested.  Is that used in seam-security ?

                        • 9. Re: Seam 3 Security. Identitysession and transaction: when is my user saved in the Database
                          Jason Porter Master

                          If you have a role class specified, then yes, it probably is used.