2011-12-29 18 views
0

ユーザーがログインするJSF 2.0ページがあり、ログアウトするオプションがあります(驚くほど)。私のJBossサーバー構成では最大7つのスレッド(接続)が可能です。私は1回のユーザーで複数回ページングをテストし、7回目の試行後にはTransaction not activeを取得します。これは、ログアウト後に接続がプールに戻らずに開いていることを意味する可能性があります。プールへの接続を返します

Q:スレッドプール内のスレッドをログアウトして返す方法は何ですか?この質問は私を長い間苦しめています。助けてください。

<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(); 

} 

EDITでのログアウト方法:ここで

は、接続を制限し、データソースのための私のJBoss standalone.xmlで設定されているここでユーザがログインする方法です。 お役に立てれば。

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を使用してデータベースにアクセスしていますか? –

+0

それ以外の場合は、ログアウトコードが正常に見えます。ここでスレッドを気にしたり、何かを返すべきではありません。 –

+0

遅れて申し訳ありません。私はあなたを最も助けてくれるものを見せつけようとしました。これがあなたが意味するものなのかどうか教えてください。 – nyxz

答えて

4

logUser()がある

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(); 
    } 
} 

。コンテナ管理のエンティティマネージャには、@PersistenceContext注釈とトランザクション管理のためにEJBを挿入して使用してください。それははるかに簡単になり、エラーを起こしにくくなります。 EJB内のすべてのメソッドがトランザクションデフォルトで

@Stateless 
public class UserDAO { 

    @PersistenceContext 
    private EntityManager entityManager; 

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

:ここ

は、単純なDAOです。 @TransactionAttribute注釈を使用してきめ細かな制御を実現できます。それは本当に簡単です。

+0

あなたの答え(弓)の追加に感謝 – nyxz

+0

あなたは歓迎です:) –

+1

+1この素晴らしい答えのために:) –