[jboss-user] [JBoss Seam] - @PersistenceContext

msystems do-not-reply at jboss.com
Fri Feb 1 18:21:31 EST 2008


I have a hard time to understand why a seam-managed persistence context (SMPC) @PersistenceContext behaves differently from a non-managed persistence context @PersistenceContext.

I know I have to use @In to use the SMPC entitymanger - but it looks like Seam also changes the behaviour for @PersistenceContext when SMPC is enabled.

Example - non-managed (expected behaviour):


  | @Stateful
  | @Name("authenticatorService")
  | @Scope(ScopeType.SESSION)
  | public class AuthenticatorBean implements AuthenticatorLocal {
  |     private static final String CONTEXT_PARAMETER_MAX_ATTEMPTS = "sine.login.max.attempts";
  |     private static final String CONTEXT_PARAMETER_TIME_LOCK = "sine.login.time.lock";
  | 
  |     @Logger
  |     private Log log;
  | 
  |     @PersistenceContext
  |     private EntityManager em;
  | 
  |     @In
  |     FacesMessages facesMessages;
  | 
  |     @EJB
  |     private UserLocal userService;
  | 
  |     @In(create = false, required = false)
  |     @Out(required = false)
  |     private User userDomain;
  | 
  |     @Out(required = false)
  |     private User loggedInUserDomain;
  | 
  |     private boolean authenticateError;
  |     private HashMap<String, Integer>loginAttempts = new HashMap<String, Integer>();
  | 
  |     public boolean authenticate() {
  |         authenticateError = false;
  | 
  |         userDomain = userService.getUserByUsername(Identity.instance().getUsername());
  |         if (userDomain != null) {
  |             if (userDomain.isTimeLocked()) {
  |                 if (System.currentTimeMillis() - userDomain.getTimeLock().getTime()
  |                         > (Long.parseLong(Util.getContextParameter(CONTEXT_PARAMETER_TIME_LOCK)) * 60000)) {
  |                     loginAttempts.put(userDomain.getUsername(), 0);
  |                     userDomain.setTimeLock(null);
  |                 } else {
  |                     facesMessages.addToControlFromResourceBundle("username", FacesMessage.SEVERITY_ERROR,
  |                             "loginTimeLocked");
  | 
  |                     authenticateError = true;
  |                     return false;
  |                 }
  |             }
  | 
  |             if (userDomain.getPassword()
  |                     .equals(Password.encodePasswordMD5(Identity.instance().getPassword(), userDomain.getId()))) {
  |                 if (!userDomain.isLocked()) {
  |                     for (Role role : userDomain.getRoles()) {
  |                         Identity.instance().addRole(role.getName());
  |                     }
  | 
  |                     loginAttempts.put(userDomain.getUsername(), 0);
  |                     loggedInUserDomain = userDomain; // Store userDomain in Session
  | 
  |                     return true;
  |                 }
  |             }
  |         } else {
  |             log.info("Login error - user don't exist: {0}", Identity.instance().getUsername());
  |         }
  | 
  |         facesMessages.addToControlFromResourceBundle("username", FacesMessage.SEVERITY_ERROR, "loginError");
  | 
  |         authenticateError = true;
  |         return false;
  |     }
  | 
  |     @Observer(value = Identity.EVENT_LOGIN_FAILED, create = false)
  |     public void failedLoginEvent() {
  |         if ((userDomain != null) && !userDomain.isTimeLocked()) {
  |             int attempts = loginAttempts.containsKey(userDomain.getUsername())
  |                     ? loginAttempts.get(userDomain.getUsername()) : 0;
  | 
  |             if (++attempts >= Integer.parseInt(Util.getContextParameter(CONTEXT_PARAMETER_MAX_ATTEMPTS))) {
  |                 userDomain.setTimeLock(new Date());
  |                 em.merge(userDomain); // I need to merge because entity is detached *************************** ATTENTION ***********
  |                 em.flush();
  |                 log.info("Time lock on user: {0}", userDomain.getUsername());
  |             } else {
  |                 loginAttempts.put(userDomain.getUsername(), attempts);
  |             }            
  |         }
  |     }
  | 
  |     public boolean isAuthenticateError() {
  |         return authenticateError;
  |     }
  | 
  |     @Remove // Seam needs this one for stateful beans
  |     public void destroy() {
  |     }
  | }
  | 

Above example works fine and the database is updated correctly.

Example - SMPC (I don't need the merge anymore - looks like @PersistenceContext is extended, but why?):


  | @Stateful
  | @Name("authenticatorService")
  | @Scope(ScopeType.SESSION)
  | public class AuthenticatorBean implements AuthenticatorLocal {
  |     private static final String CONTEXT_PARAMETER_MAX_ATTEMPTS = "sine.login.max.attempts";
  |     private static final String CONTEXT_PARAMETER_TIME_LOCK = "sine.login.time.lock";
  | 
  |     @Logger
  |     private Log log;
  | 
  |     @PersistenceContext
  |     private EntityManager em;
  | 
  |     @In
  |     FacesMessages facesMessages;
  | 
  |     @EJB
  |     private UserLocal userService;
  | 
  |     @In(create = false, required = false)
  |     @Out(required = false)
  |     private User userDomain;
  | 
  |     @Out(required = false)
  |     private User loggedInUserDomain;
  | 
  |     private boolean authenticateError;
  |     private HashMap<String, Integer>loginAttempts = new HashMap<String, Integer>();
  | 
  |     public boolean authenticate() {
  |         authenticateError = false;
  | 
  |         userDomain = userService.getUserByUsername(Identity.instance().getUsername());
  |         if (userDomain != null) {
  |             if (userDomain.isTimeLocked()) {
  |                 if (System.currentTimeMillis() - userDomain.getTimeLock().getTime()
  |                         > (Long.parseLong(Util.getContextParameter(CONTEXT_PARAMETER_TIME_LOCK)) * 60000)) {
  |                     loginAttempts.put(userDomain.getUsername(), 0);
  |                     userDomain.setTimeLock(null);
  |                 } else {
  |                     facesMessages.addToControlFromResourceBundle("username", FacesMessage.SEVERITY_ERROR,
  |                             "loginTimeLocked");
  | 
  |                     authenticateError = true;
  |                     return false;
  |                 }
  |             }
  | 
  |             if (userDomain.getPassword()
  |                     .equals(Password.encodePasswordMD5(Identity.instance().getPassword(), userDomain.getId()))) {
  |                 if (!userDomain.isLocked()) {
  |                     for (Role role : userDomain.getRoles()) {
  |                         Identity.instance().addRole(role.getName());
  |                     }
  | 
  |                     loginAttempts.put(userDomain.getUsername(), 0);
  |                     loggedInUserDomain = userDomain; // Store userDomain in Session
  | 
  |                     return true;
  |                 }
  |             }
  |         } else {
  |             log.info("Login error - user don't exist: {0}", Identity.instance().getUsername());
  |         }
  | 
  |         facesMessages.addToControlFromResourceBundle("username", FacesMessage.SEVERITY_ERROR, "loginError");
  | 
  |         authenticateError = true;
  |         return false;
  |     }
  | 
  |     @Observer(value = Identity.EVENT_LOGIN_FAILED, create = false)
  |     public void failedLoginEvent() {
  |         if ((userDomain != null) && !userDomain.isTimeLocked()) {
  |             int attempts = loginAttempts.containsKey(userDomain.getUsername())
  |                     ? loginAttempts.get(userDomain.getUsername()) : 0;
  | 
  |             if (++attempts >= Integer.parseInt(Util.getContextParameter(CONTEXT_PARAMETER_MAX_ATTEMPTS))) {
  |                 userDomain.setTimeLock(new Date());
  |                 em.flush();
  |                 log.info("Time lock on user: {0}", userDomain.getUsername());
  |             } else {
  |                 loginAttempts.put(userDomain.getUsername(), attempts);
  |             }            
  |         }
  |     }
  | 
  |     public boolean isAuthenticateError() {
  |         return authenticateError;
  |     }
  | 
  |     @Remove // Seam needs this one for stateful beans
  |     public void destroy() {
  |     }
  | }
  | 

Above example works fine and the database is updated correctly, but I don't need to merge anymore - looks like @PersistenceContext is extended when running under SMPC.

Could someone explain why @PersistenceContext behaves differently under a SMPC?

Thanks.


View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4125702#4125702

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4125702



More information about the jboss-user mailing list