Your numbers are impressive, but we are able to strike up those errors with far
less traffic... ;)
By the way, you were testing only read operations? I feel like those errors are
somehow indirectly caused by write operations (although not necessarily on
objects being modified -- don't ask...).
We are using session-in-view pattern. The most I can do here is show you our
code that handles Hibernate sessions and transactions. There are just a few
functions.
Whenever a Hibernate session is first requested within a request, we check the
UserTransaction and reset it if necessary:
private static final TransactionManager transactionManager;
| static {
| transactionManager = ((SessionFactoryImplementor)
GlobalContext.getHibernateSessionFactory()).getTransactionManager();
| }
|
| public static boolean resetUserTransaction() {
| if (transactionManager == null) return false;
| try {
| final int status = transactionManager.getStatus();
| switch (status) {
| case Status.STATUS_MARKED_ROLLBACK:
| case Status.STATUS_ACTIVE:
| case Status.STATUS_PREPARED:
| case Status.STATUS_PREPARING:
| transactionManager.rollback();
| return true;
| }
| } catch (SystemException e) {
| log.error("Error resetting UserTransaction.", e);
| }
| return false;
| }
Without this code, the UserTransaction sometimes gets left in a state which
makes it unusable during the next request.
After this is done, a new session is created and a transaction is started. This
is the entire method:
public static Session getHibernateSession() {
| final RequestContextInstance currentThreadContext =
getOrCreateThreadContext();
| SessionImpl session = currentThreadContext.hibernateSession;
| if ((session == null) || (!session.isOpen())) {
| resetUserTransaction();
| try {
| session = (SessionImpl)
GlobalContext.getHibernateSessionFactory().openSession(new
SubjectRoleInterceptor());
| session.setFlushMode(FlushMode.COMMIT);
| } catch (Exception e) {
| currentThreadContext.errorMessage = e.getMessage();
| throw new RuntimeException("Error opening Hibernate
session.", e);
| } finally {
| // Store the session in request context even in case of an
error,
| // so that it will try to be closed at the end of the
request.
| currentThreadContext.hibernateSession = session;
| }
| }
| final Transaction transaction = session.getTransaction();
| if (transaction == null || !transaction.isActive()) {
| try {
| session.beginTransaction();
| } catch (Exception e) {
| log.warn("Error starting transaction.");
| }
| }
| return session;
| }
The session is then kept in a threadlocal variable for the duration of the
request, after which it is closed and the transaction is committed if no errors
occured during the request:
public static boolean closeHibernateSession() {
| final RequestContextInstance currentThreadContext =
getThreadContext();
| if (currentThreadContext == null) return false;
| final SessionImpl session = currentThreadContext.hibernateSession;
| if (session == null) return false;
| currentThreadContext.hibernateSession = null;
| if (session.isOpen()) {
| try {
| if (session.isTransactionInProgress()) {
| try {
| final Transaction transaction =
session.getTransaction();
| transaction.rollback();
| } catch (HibernateException e) {
| log.error("Error during Hibernate transaction
rollback.", e);
| }
| }
| session.close();
| GlobalContext.getHibernateSessionFactory());
| } catch (Throwable t) {
| log.error("Error closing Hibernate session. Will try to
close the connection.", t);
| final Connection connection = session.connection();
| if (connection != null) {
| try {
| // At least close the connection if we could not
close the session.
| connection.close();
| } catch (SQLException e) {
| log.error("Error closing database connection after
unsuccessful attempt to close Hibernate session.", e);
| }
| }
| }
| resetUserTransaction();
| return true;
| } else {
| resetUserTransaction();
| return false;
| }
| }
This is mostly all of our session handling code, the rest of the application
code always just calls getHibernateSession() and gets a valid session. Most of
the time there is just one transaction within a request. In some rare cases we
flush the changes (= commit and reopen the transaction) in the middle of the
request and continue. This is the code that handles this:
public static boolean flushHibernateSession() {
| final RequestContextInstance currentThreadContext =
getThreadContext();
| if (currentThreadContext == null) return false;
| final SessionImpl session = currentThreadContext.hibernateSession;
| if (session == null || session.isClosed()) return true;
|
| // If there was no error during the request, flush
| // the updates, otherwise discard them.
| if (currentThreadContext.errorMessage == null) {
| // If there an active transaction is present,
| // commit it, otherwise do a simple flush.
| if (session.isTransactionInProgress()) { // returns true
when ACTIVE or MARKED_ROLLBACK
| try {
| final Transaction transaction =
session.getTransaction();
| if (transaction.isActive()) {
| transaction.commit();
| return true;
| } else { // must be MARKED_ROLLBACK
| log.info("Transaction is MARKED_ROLLBACK - doing
rollback instead of commit.");
| transaction.rollback();
| }
| } catch (HibernateException e) {
| currentThreadContext.errorMessage = e.getMessage();
| log.error("Error flushing Hibernate transaction. See
previous exception for details.");
| }
| } else {
| try {
| session.flush();
| return true;
| } catch (HibernateException e) {
| currentThreadContext.errorMessage = e.getMessage();
| log.error("Error flushing Hibernate session. See
previous exception for details.");
| }
| }
| } else {
| if (session.isTransactionInProgress()) {
| try {
| final Transaction transaction =
session.getTransaction();
| transaction.rollback();
| } catch (HibernateException e) {
| log.error("Error during Hibernate transaction
rollback.", e);
| }
| }
| session.clear();
| }
|
| // If no return true statement occured so far,
| // it means there must have been an error.
| return false;
| }
There, now this is really all we ever do, the rest is just regular Hibernate
use.
Seeing your last post: our database is PostgreSQL 8.0.
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=3946931#3946931
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=3946931
-------------------------------------------------------
All the advantages of Linux Managed Hosting--Without the Cost and Risk!
Fully trained technicians. The highest number of Red Hat certifications in
the hosting industry. Fanatical Support. Click to learn more
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=107521&bid=248729&dat=121642
_______________________________________________
JBoss-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jboss-user