예제 #1
0
  /** {@inheritDoc} */
  public ConnectionListener getConnection(
      Transaction trackByTransaction, Subject subject, ConnectionRequestInfo cri)
      throws ResourceException {
    ConnectionListener cl = null;
    boolean separateNoTx = false;

    if (noTxSeparatePools) {
      separateNoTx = clf.isTransactional();
    }

    // Get specific managed connection pool key
    Object key = getKey(subject, cri, separateNoTx);

    // Get managed connection pool
    ManagedConnectionPool mcp = getManagedConnectionPool(key, subject, cri);

    // Are we doing track by transaction ?
    TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
    Object transactionKey = tsr != null ? tsr.getTransactionKey() : null;

    if (trackByTransaction == null || transactionKey == null) {
      return getSimpleConnection(subject, cri, mcp);
    }

    // Transaction old connections
    cl = getTransactionOldConnection(trackByTransaction, mcp);

    // Creates a new connection with given transaction
    if (cl == null) {
      cl = getTransactionNewConnection(trackByTransaction, mcp, subject, cri);
    }

    return cl;
  }
예제 #2
0
  /**
   * Gets connection listener instance associated with transaction. This method is package protected
   * beacause it is intended only for test case use. Please don't use it in your production code.
   *
   * @param trackByTransaction transaction instance
   * @param mcp the managed connection pool associated with the desired connection listener
   * @return connection listener instance
   * @throws ResourceException Thrown if an error occurs
   */
  ConnectionListener getTransactionOldConnection(
      Transaction trackByTransaction, ManagedConnectionPool mcp) throws ResourceException {
    TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
    Lock lock = getLock();

    try {
      lock.lockInterruptibly();
    } catch (InterruptedException ie) {
      Thread.interrupted();

      throw new ResourceException(bundle.unableObtainLock(), ie);
    }
    try {
      // Already got one
      ConnectionListener cl = (ConnectionListener) tsr.getResource(mcp);
      if (cl != null) {
        if (trace)
          log.tracef("Previous connection tracked by transaction=%s tx=%s", cl, trackByTransaction);
        return cl;
      }

      return null;
    } finally {
      lock.unlock();
    }
  }
예제 #3
0
 private void addWaitingOnTxCompletionTimer(final TimerImpl timer) {
   Map<String, TimerImpl> timers =
       (Map<String, TimerImpl>) tsr.getResource(waitingOnTxCompletionKey);
   if (timers == null) {
     tsr.putResource(waitingOnTxCompletionKey, timers = new HashMap<String, TimerImpl>());
   }
   timers.put(timer.getId(), timer);
 }
 @TransactionAttribute(TransactionAttributeType.MANDATORY)
 public void sameTransaction(boolean first) throws RemoteException {
   if (first) {
     transactionKey = transactionSynchronizationRegistry.getTransactionKey();
   } else {
     if (!transactionKey.equals(transactionSynchronizationRegistry.getTransactionKey())) {
       throw new RemoteException("Transaction on second call was not the same as on first call");
     }
   }
 }
예제 #5
0
  /**
   * Gets new connection listener if necessary instance with transaction. This method is package
   * protected beacause it is intended only for test case use. Please don't use it in your
   * production code.
   *
   * @param trackByTransaction transaction instance
   * @param mcp pool instance
   * @param subject subject instance
   * @param cri connection request info
   * @return connection listener instance
   * @throws ResourceException ResourceException
   */
  ConnectionListener getTransactionNewConnection(
      Transaction trackByTransaction,
      ManagedConnectionPool mcp,
      Subject subject,
      ConnectionRequestInfo cri)
      throws ResourceException {
    // Need a new one for this transaction
    // This must be done outside the tx local lock, otherwise
    // the tx timeout won't work and get connection can do a lot of other work
    // with many opportunities for deadlocks.
    // Instead we do a double check after we got the transaction to see
    // whether another thread beat us to the punch.
    ConnectionListener cl = mcp.getConnection(subject, cri);
    if (trace)
      log.tracef(
          "Got connection from pool tracked by transaction=%s tx=%s", cl, trackByTransaction);

    TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
    Lock lock = getLock();
    try {
      lock.lockInterruptibly();
    } catch (InterruptedException ie) {
      Thread.interrupted();

      throw new ResourceException(bundle.unableObtainLock(), ie);
    }
    try {
      // Check we weren't racing with another transaction
      ConnectionListener other = (ConnectionListener) tsr.getResource(mcp);

      if (other != null) {
        mcp.returnConnection(cl, false);

        if (trace)
          log.tracef(
              "Another thread already got a connection tracked by transaction=%s tx=%s",
              other, trackByTransaction);

        cl = other;
      }

      // This is the connection for this transaction
      cl.setTrackByTx(true);
      tsr.putResource(mcp, cl);

      if (trace)
        log.tracef(
            "Using connection from pool tracked by transaction=%s tx=%s", cl, trackByTransaction);

      return cl;
    } finally {
      lock.unlock();
    }
  }
예제 #6
0
  /**
   * Get lock
   *
   * @return The lock
   */
  private Lock getLock() {
    Lock result = null;
    TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();

    if (tsr != null && tsr.getTransactionKey() != null) {
      result = (Lock) tsr.getResource(LockKey.INSTANCE);
      if (result == null) {
        result = initLock();
      }
    }

    return result;
  }
예제 #7
0
  /**
   * Init lock
   *
   * @return The lock
   */
  private synchronized Lock initLock() {
    TransactionSynchronizationRegistry tsr = getTransactionSynchronizationRegistry();
    if (tsr != null && tsr.getTransactionKey() != null) {
      if (tsr.getResource(LockKey.INSTANCE) == null) {
        Lock lock = new ReentrantLock(true);
        tsr.putResource(LockKey.INSTANCE, lock);
        return lock;
      } else {
        return (Lock) tsr.getResource(LockKey.INSTANCE);
      }
    }

    return null;
  }
예제 #8
0
  private void ejbLoad(final EntityBean entityBean) {
    if (entityBean == null) {
      throw new NullPointerException("entityBean is null");
    }

    final ThreadContext callContext = createThreadContext(entityBean);
    callContext.setCurrentOperation(Operation.LOAD);

    final ThreadContext oldCallContext = ThreadContext.enter(callContext);
    try {
      entityBean.ejbLoad();
    } catch (final RemoteException e) {
      throw new EJBException(e);
    } finally {
      ThreadContext.exit(oldCallContext);
    }

    // if we call load we must call store
    try {
      //noinspection unchecked
      Set<EntityBean> registeredEntities =
          (LinkedHashSet<EntityBean>) synchronizationRegistry.getResource(ENTITIES_TO_STORE);
      if (registeredEntities == null) {
        registeredEntities = new LinkedHashSet<EntityBean>();
        synchronizationRegistry.putResource(ENTITIES_TO_STORE, registeredEntities);
        synchronizationRegistry.registerInterposedSynchronization(
            new Synchronization() {
              @Override
              public void beforeCompletion() {
                //noinspection unchecked
                final Set<EntityBean> registeredEntities =
                    (LinkedHashSet<EntityBean>)
                        synchronizationRegistry.getResource(ENTITIES_TO_STORE);
                if (registeredEntities == null) {
                  return;
                }
                for (final EntityBean entityBean : registeredEntities) {
                  ejbStore(entityBean);
                }
              }

              @Override
              public void afterCompletion(final int i) {}
            });
      }
      registeredEntities.add(entityBean);
    } catch (final Exception e) {
      // no-op
    }
  }
예제 #9
0
  public void enlist(Transaction transaction, LocalTransaction localTransaction) {
    if (!localTransaction.isEnlisted()) {
      SynchronizationAdapter sync =
          new SynchronizationAdapter(
              localTransaction,
              txCoordinator,
              commandsFactory,
              rpcManager,
              this,
              clusteringLogic,
              configuration);
      if (transactionSynchronizationRegistry != null) {
        try {
          transactionSynchronizationRegistry.registerInterposedSynchronization(sync);
        } catch (Exception e) {
          log.failedSynchronizationRegistration(e);
          throw new CacheException(e);
        }

      } else {

        try {
          transaction.registerSynchronization(sync);
        } catch (Exception e) {
          log.failedSynchronizationRegistration(e);
          throw new CacheException(e);
        }
      }
      ((SyncLocalTransaction) localTransaction).setEnlisted(true);
    }
  }
예제 #10
0
 /**
  * Returns an unmodifiable view of timers in the current transaction that are waiting for the
  * transaction to finish
  */
 private Map<String, TimerImpl> getWaitingOnTxCompletionTimers() {
   Map<String, TimerImpl> timers = null;
   if (getTransaction() != null) {
     timers = (Map<String, TimerImpl>) tsr.getResource(waitingOnTxCompletionKey);
   }
   return timers == null ? Collections.<String, TimerImpl>emptyMap() : timers;
 }
  @Override
  @Asynchronous
  @AccessTimeout(value = 60000)
  @TransactionAttribute(REQUIRED)
  public void booksUnavailable(BooksUnavailableMessage booksUnavailableMessage) {
    String correlationId = getCorrelationId(booksUnavailableMessage);
    log.info("#### [seller]: BooksUnavailable response received: " + correlationId);
    SellerContext sellerContext = getContext(correlationId);

    try {
      sellerContext.validate(booksUnavailableMessage);
      sellerContext.fire_BooksUnavailable_response_received();

      if (sellerContext.isGlobalTransactionActive())
        enrollTransaction("bookReservation", sellerContext);

      sellerProcess.handle_BooksUnavailable_response(booksUnavailableMessage);

    } catch (Throwable e) {
      log.error("Error", e);
      e = ExceptionUtil.getRootCause(e);
      transactionSynchronizationRegistry.setRollbackOnly();
      sellerContext.fire_BooksUnavailable_incoming_response_aborted(e);
    }
  }
예제 #12
0
 @PreDestroy
 public void destroy() {
   System.out.println("In SingletonBean::destroy()");
   try {
     javax.transaction.TransactionSynchronizationRegistry r =
         (javax.transaction.TransactionSynchronizationRegistry)
             new InitialContext().lookup("java:comp/TransactionSynchronizationRegistry");
     if (r.getTransactionStatus() != javax.transaction.Status.STATUS_ACTIVE) {
       throw new IllegalStateException(
           "Transaction status is not STATUS_ACTIVE: " + r.getTransactionStatus());
     }
     FooEntity fe = new FooEntity("FOO");
     em.persist(fe);
   } catch (Exception e) {
     throw new EJBException(e);
   }
 }
예제 #13
0
  /**
   * Looks for a current Spring managed transaction and wraps/returns that as a Ebean transaction.
   *
   * <p>Returns null if there is no current spring transaction (lazy loading outside a spring txn
   * etc).
   */
  public Object getCurrentTransaction() {

    TransactionSynchronizationRegistry syncRegistry = getSyncRegistry();

    SpiTransaction t = (SpiTransaction) syncRegistry.getResource(EBEAN_TXN_RESOURCE);
    if (t != null) {
      // we have already seen this transaction
      return t;
    }

    // check current Ebean transaction
    SpiTransaction currentEbeanTransaction = DefaultTransactionThreadLocal.get(serverName);
    if (currentEbeanTransaction != null) {
      // NOT expecting this so log WARNING
      String msg =
          "JTA Transaction - no current txn BUT using current Ebean one "
              + currentEbeanTransaction.getId();
      logger.warn(msg);
      return currentEbeanTransaction;
    }

    UserTransaction ut = getUserTransaction();
    if (ut == null) {
      // no current JTA transaction
      if (logger.isDebugEnabled()) {
        logger.debug("JTA Transaction - no current txn");
      }
      return null;
    }

    // This is a transaction that Ebean has not seen before.

    // "wrap" it in a Ebean specific JtaTransaction
    String txnId = String.valueOf(System.currentTimeMillis());
    JtaTransaction newTrans = new JtaTransaction(txnId, true, ut, dataSource, transactionManager);

    // create and register transaction listener
    JtaTxnListener txnListener = createJtaTxnListener(newTrans);

    syncRegistry.putResource(EBEAN_TXN_RESOURCE, newTrans);
    syncRegistry.registerInterposedSynchronization(txnListener);

    // also put in Ebean ThreadLocal
    DefaultTransactionThreadLocal.set(serverName, newTrans);
    return newTrans;
  }
예제 #14
0
    private Map<Contextual<?>, BeanInstanceBag<?>> findMap() {
      final Object resource;
      try { // we can't call registry.getResource(KEY) in afterCompletion
        resource =
            context.geronimoTxMgr
                ? TransactionImpl.class
                    .cast(context.transactionManager.getTransaction())
                    .getResource(KEY)
                : registry.getResource(KEY);
      } catch (final SystemException e) {
        throw new IllegalStateException(e);
      }

      if (resource == null) {
        final Map<Contextual<?>, BeanInstanceBag<?>> map = new HashMap<>();
        registry.putResource(KEY, map);
        registry.registerInterposedSynchronization(context);
        return map;
      }
      return Map.class.cast(resource);
    }