2011-12-29 56 views
0

我有一个用户登录的JSF 2.0页面,他有一个注销选项(令人惊讶)。我的JBoss服务器配置允许最多7个线程(连接)。我用一个用户测试多次登录页面,第七次尝试后我得到Transaction not active这可能意味着注销后连接不会回到池中并保持打开状态。返回连接池

问:注销并返回线程池中线程的方式是什么?这个问题折磨了我很长一段时间。请帮忙。

下面是在我的JBoss standalone.xml为数据源限制所述连接的配置:

<subsystem xmlns="urn:jboss:domain:datasources:1.0"> 
      <datasources> 
       <datasource jndi-name="java:jboss/MyJndiDS" pool-name="MyPoolDS" enabled="true" jta="true" use-java-context="false" use-ccm="true"> 
        <connection-url> 
         jdbc:postgresql://192.168.2.125:5432/t_report 
        </connection-url> 
        <driver> 
         org.postgresql 
        </driver> 
        <transaction-isolation> 
         TRANSACTION_READ_COMMITTED 
        </transaction-isolation> 
        <pool> 
         <min-pool-size> 
          3 
         </min-pool-size> 
         <max-pool-size> 
          7 
         </max-pool-size> 
         <prefill> 
          true 
         </prefill> 
         <use-strict-min> 
          false 
         </use-strict-min> 
         <flush-strategy> 
          FailingConnectionOnly 
         </flush-strategy> 
        </pool> 
        <security> 
         <user-name> 
          my_user 
         </user-name> 
         <password> 
          my_pass 
         </password> 
        </security> 
        <statement> 
         <prepared-statement-cache-size> 
          32 
         </prepared-statement-cache-size> 
        </statement> 
       </datasource> 
... 
... 
      </datasources> 
</subsystem> 

和注销方法在@SessionScoped

import javax.faces.context.ExternalContext; 
... 
... 
@Inject ExternalContext ec; 

public void validateUserLogOut() { 

    HttpServletRequest request = (HttpServletRequest)ec.getRequest(); 
    request.getSession().invalidate(); 
    this.setUserLoggedIn(false); 
    navigation.logout(); 

} 

编辑:这里是用户在如何日志。 希望这可以帮助。

public void validateLogUser() { 
    ResourceBundle bundle = ResourceBundle.getBundle("internationalization.language", context.getViewRoot().getLocale()); 
    String validation = logUser(); 
    if((validation == null) || validation.isEmpty()) { 
     context.addMessage(null, 
      new FacesMessage(FacesMessage.SEVERITY_WARN, 
      bundle.getString("wrongUsername"),bundle.getString("wrongUsername"))); 
    } else if (validation == "welcome") { 
     this.setUserLoggedIn(true); 
     navigation.login(); 
    } 
} 

其中logUser()是:

public synchronized String logUser() { 

    try { 
     EntityManagerUtil.getEntityManager().getTransaction().begin(); 
     System.out.println(user); 
     if(user.getUsername().isEmpty() || (user.getUsername() == null)) { 
      return null; 
     } 
     String password = user.getPassword(); 
     user = (UserBean) EntityManagerUtil.getEntityManager().find(UserBean.class, user.getUsername()); 
     if(user == null) { 
      HttpServletRequest request = (HttpServletRequest)ec.getRequest(); 
      request.getSession().invalidate(); 
     } 
     if(user.getPassword().equals(password)) { 
      log.info("User: " + user.getUsername() + " logged successfully."); 
      return "welcome"; 
     } else { 
      HttpServletRequest request = (HttpServletRequest)ec.getRequest(); 
      request.getSession().invalidate(); 
      return null; 
     } 
    } catch (Exception e) { 
     log.error("Error while logging in : \n\t" + e); 
     EntityManagerUtil.getEntityManager().getTransaction().rollback(); 
     return null; 
    } finally { 
     EntityManagerUtil.close(); 
    } 
} 

这是怎么EntityManagerUtil.getEntityManager()作品:

/** 
* ThreadLocal instance that holds unique EntityManager per thread, 
* it means that every thread accessing this ThreadLocal will has it's own instance of EntityManager 
*/ 
private static final ThreadLocal<EntityManager> entitymanager = 
    new ThreadLocal<EntityManager>(); 

/** 
* @param persistenceUnit - String name of the persistece unit 
* to be used as declared inside persistence.xml 
* @return singleton instance of EntityManagerFactory 
*/ 
public synchronized static EntityManagerFactory initializeEntityManagerFactory(String persistenceUnit) { 
    if (entityManagerFactory == null) { 
     // Create the EntityManagerFactory 
     entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnit); 
    } 
    return entityManagerFactory; 
} 


/** 
* @return Singleton instance of EntityManager per Thread 
*/ 
public static EntityManager getEntityManager() { 
    initializeEntityManagerFactory("MyPersistenceUnit"); 
    EntityManager entityManager = entitymanager.get(); 

    // Create a new EntityManager 
    if (entityManager == null) { 
     entityManager = entityManagerFactory.createEntityManager(); 
     entitymanager.set(entityManager); 
    } 

    return entityManager; 
} 


/** 
* Close all ThreadLocals 
*/ 
public static void close() { 
    final EntityManager entityManager = entitymanager.get(); 
    entitymanager.set(null); 
    if (entityManager != null && entityManager.isOpen()) { 
     entityManager.close(); 
    } 
    if (entityManagerFactory != null && entityManagerFactory.isOpen()) { 
     entityManagerFactory.close(); 
    } 
} 
+2

请说明您如何管理登录过程?看起来你正在手动管理连接,并且你忘了关闭连接。您是否在使用JPA + EJB或纯JDBC来访问数据库? – 2011-12-29 15:02:35

+0

否则您的注销代码看起来很好。你不应该在乎线程或返回任何东西。 – 2011-12-29 15:09:02

+0

对不起,延误了。我试图展示可能对你最有帮助的事情。请让我知道这是你的意思。 – nyxz 2011-12-29 15:23:13

回答

4

你重新发明轮子。请使用容器管理实体管理器注入@PersistenceContext注释和EJB来管理事务。它会容易得多,而且容易出错。

下面是一个简单的DAO:

@Stateless 
public class UserDAO { 

    @PersistenceContext 
    private EntityManager entityManager; 

    public void insertUser(User user) { 
     entityManager.persist(user); 
    } 
} 

默认情况下,在每EJB方法是事务性的。您可以使用@TransactionAttribute注释实现精细控制。这非常简单。

+0

并感谢你的答案(弓) – nyxz 2011-12-29 15:46:26

+0

加上欢迎:) – 2011-12-29 15:52:08

+1

+1这个伟大的答案:) – 2011-12-29 16:04:11