Вернуть соединение в пул - PullRequest
       14

Вернуть соединение в пул

0 голосов
/ 29 декабря 2011

У меня есть страница JSF 2.0, на которой пользователь входит в систему, и у него есть возможность выйти (неожиданно).Моя конфигурация сервера JBoss допускает максимум 7 потоков (соединений).Я тестирую страницу входа в систему несколько раз с одним пользователем, и после 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();
    }
}

1 Ответ

5 голосов
/ 29 декабря 2011

Вы заново изобретаете колесо.Пожалуйста, используйте диспетчер управляемых сущностей контейнеров, добавив в него аннотацию @PersistenceContext и EJB для управления транзакциями.Это будет намного проще и менее подвержено ошибкам.

Вот простой DAO:

@Stateless
public class UserDAO {

   @PersistenceContext
   private EntityManager entityManager;

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

По умолчанию каждый метод в EJB является транзакционным.Вы можете добиться точного контроля, используя аннотацию @TransactionAttribute.Это действительно просто.

...