use of javax.ejb.EntityBean in project tomee by apache.
the class JpaCmpEngine method executeSelectQuery.
private List<Object> executeSelectQuery(final Query query, Object[] args) {
// process args
if (args == null) {
args = NO_ARGS;
}
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
// ejb proxies need to be swapped out for real instance classes
if (arg instanceof EJBObject) {
arg = Cmp2Util.getEntityBean((EJBObject) arg);
}
if (arg instanceof EJBLocalObject) {
arg = Cmp2Util.getEntityBean((EJBLocalObject) arg);
}
try {
query.getParameter(i + 1);
} catch (final IllegalArgumentException e) {
// specified position does not exist
continue;
}
query.setParameter(i + 1, arg);
}
// todo results should not be iterated over, but should instead
// perform all work in a wrapper list on demand by the application code
final List results = query.getResultList();
for (final Object value : results) {
if (value instanceof EntityBean) {
// todo don't activate beans already activated
final EntityBean entity = (EntityBean) value;
cmpCallback.setEntityContext(entity);
cmpCallback.ejbActivate(entity);
}
}
// noinspection unchecked
return results;
}
use of javax.ejb.EntityBean in project tomee by apache.
the class EntityContainer method invoke.
protected Object invoke(final InterfaceType type, final Method callMethod, final Method runMethod, final Object[] args, final ThreadContext callContext) throws OpenEJBException {
final BeanContext beanContext = callContext.getBeanContext();
final TransactionPolicy txPolicy = createTransactionPolicy(beanContext.getTransactionType(callMethod, type), callContext);
EntityBean bean = null;
Object returnValue = null;
entrancyTracker.enter(callContext.getBeanContext(), callContext.getPrimaryKey());
try {
bean = instanceManager.obtainInstance(callContext);
ejbLoad_If_No_Transaction(callContext, bean);
returnValue = runMethod.invoke(bean, args);
ejbStore_If_No_Transaction(callContext, bean);
instanceManager.poolInstance(callContext, bean, callContext.getPrimaryKey());
} catch (final Throwable e) {
handleException(txPolicy, e, callContext, bean);
} finally {
entrancyTracker.exit(callContext.getBeanContext(), callContext.getPrimaryKey());
afterInvoke(txPolicy, callContext);
}
return returnValue;
}
use of javax.ejb.EntityBean in project tomee by apache.
the class EntityInstanceManager method obtainInstance.
public EntityBean obtainInstance(final ThreadContext callContext) throws OpenEJBException {
// primary key is null if its a servicing a home methods (create, find, ejbHome)
final Object primaryKey = callContext.getPrimaryKey();
final TransactionPolicy txPolicy = callContext.getTransactionPolicy();
if (callContext.getPrimaryKey() != null && txPolicy != null && txPolicy.isTransactionActive()) {
final Key key = new Key(callContext.getBeanContext().getDeploymentID(), primaryKey);
SynchronizationWrapper wrapper = (SynchronizationWrapper) txPolicy.getResource(key);
if (wrapper != null) {
if (!wrapper.isAssociated()) {
/*
* If the bean identity was removed (via ejbRemove()) within the same transaction,
* then it's SynchronizationWrapper will be in the txReady pool but marked as disassociated.
* This allows us to prevent a condition where the caller removes the bean and then attempts to
* call a business method on that bean within the same transaction. After a bean is removed any
* subsequent invocations on that bean with the same transaction should throw a NoSuchEntityException.
* its likely that the application server would have already made the reference invalid, but this bit of
* code is an extra precaution.
*/
throw new InvalidateReferenceException(new NoSuchObjectException("Entity not found: " + primaryKey));
} else if (callContext.getCurrentOperation() == Operation.REMOVE) {
/*
* To avoid calling ejbStore( ) on a bean that after its removed, we can not delegate
* the wrapper is marked as disassociated from the transaction to avoid processing the
* beforeCompletion( ) method on the SynchronizationWrapper object.
*/
wrapper.disassociate();
}
if (wrapper.isAvailable() || wrapper.primaryKey.equals(primaryKey)) {
return wrapper.getEntityBean();
} else {
// its simpler to implement.
return wrapper.getEntityBean();
}
} else {
/*
* If no synchronized wrapper for the key exists
* Then the bean entity is being access by this transaction for the first time,
* so it needs to be enrolled in the transaction.
*/
final EntityBean bean = getPooledInstance(callContext);
wrapper = new SynchronizationWrapper(callContext.getBeanContext(), primaryKey, bean, false, key, txPolicy);
if (callContext.getCurrentOperation() == Operation.REMOVE) {
/*
* To avoid calling ejbStore( ) on a bean that after its removed, we can not delegate
* the wrapper is marked as disassociated from the transaction to avoid processing the
* beforeCompletion( ) method on the SynchronizationWrapper object.
*
* We have to still use a wrapper so we can detect when a business method is called after
* a ejbRemove() and act to prevent it from being processed.
*/
wrapper.disassociate();
}
txPolicy.registerSynchronization(wrapper);
loadingBean(bean, callContext);
final Operation orginalOperation = callContext.getCurrentOperation();
callContext.setCurrentOperation(Operation.LOAD);
try {
bean.ejbLoad();
} catch (final NoSuchEntityException e) {
wrapper.disassociate();
throw new InvalidateReferenceException(new NoSuchObjectException("Entity not found: " + primaryKey, e));
} catch (final Exception e) {
logger.error("Exception encountered during ejbLoad():", e);
// djencks not sure about this dissociate call
wrapper.disassociate();
throw new OpenEJBException(e);
} finally {
callContext.setCurrentOperation(orginalOperation);
}
txPolicy.putResource(key, wrapper);
return bean;
}
} else {
// returned to the pool -- depending on if the tx is a client initiated or container initiated.
return getPooledInstance(callContext);
}
}
use of javax.ejb.EntityBean in project tomee by apache.
the class EntityInstanceManager method getPooledInstance.
protected EntityBean getPooledInstance(final ThreadContext callContext) throws OpenEJBException {
final BeanContext beanContext = callContext.getBeanContext();
final Stack methodReadyPool = poolMap.get(beanContext.getDeploymentID());
if (methodReadyPool == null) {
throw new SystemException("Invalid deployment id " + beanContext.getDeploymentID() + " for this container");
}
EntityBean bean = (EntityBean) methodReadyPool.pop();
if (bean == null) {
try {
bean = (EntityBean) beanContext.getBeanClass().newInstance();
} catch (final Exception e) {
logger.error("Bean instantiation failed for class " + beanContext.getBeanClass(), e);
throw new SystemException(e);
}
final Operation currentOp = callContext.getCurrentOperation();
callContext.setCurrentOperation(Operation.SET_CONTEXT);
try {
/*
* setEntityContext executes in an unspecified transactional context. In this case we choose to
* allow it to have what every transaction context is current. Better then suspending it
* unnecessarily.
*
* We also chose not to invoke EntityContainer.invoke( ) method, which duplicate the exception handling
* logic but also attempt to manage the begining and end of a transaction. It its a container managed transaciton
* we don't want the TransactionScopeHandler commiting the transaction in afterInvoke() which is what it would attempt
* to do.
*/
bean.setEntityContext(createEntityContext());
} catch (final Exception e) {
/*
* The EJB 1.1 specification does not specify how exceptions thrown by setEntityContext impact the
* transaction, if there is one. In this case we choose the least disruptive operation, throwing an
* application exception and NOT automatically marking the transaciton for rollback.
*/
logger.error("Bean callback method failed ", e);
throw new ApplicationException(e);
} finally {
callContext.setCurrentOperation(currentOp);
}
} else {
reusingBean(bean, callContext);
}
if (callContext.getCurrentOperation() == Operation.BUSINESS || callContext.getCurrentOperation() == Operation.REMOVE) {
/*
* When a bean is retrieved from the bean pool to service a client's business method request it must be
* notified that its about to enter service by invoking its ejbActivate( ) method. A bean instance
* does not have its ejbActivate() invoked when:
* 1. Its being retreived to service an ejbCreate()/ejbPostCreate().
* 2. Its being retrieved to service an ejbFind method.
* 3. Its being retrieved to service an ejbRemove() method.
* See section 9.1.4 of the EJB 1.1 specification.
*/
final Operation currentOp = callContext.getCurrentOperation();
callContext.setCurrentOperation(Operation.ACTIVATE);
try {
/*
In the event of an exception, OpenEJB is required to log the exception, evict the instance,
and mark the transaction for rollback. If there is a transaction to rollback, then the a
javax.transaction.TransactionRolledbackException must be throw to the client.
See EJB 1.1 specification, section 12.3.2
*/
bean.ejbActivate();
} catch (final Throwable e) {
logger.error("Encountered exception during call to ejbActivate()", e);
final TransactionPolicy txPolicy = callContext.getTransactionPolicy();
if (txPolicy != null && txPolicy.isTransactionActive()) {
txPolicy.setRollbackOnly(e);
throw new ApplicationException(new TransactionRolledbackException("Reflection exception thrown while attempting to call ejbActivate() on the instance", e));
}
throw new ApplicationException(new RemoteException("Exception thrown while attempting to call ejbActivate() on the instance. Exception message = " + e.getMessage(), e));
} finally {
callContext.setCurrentOperation(currentOp);
}
}
return bean;
}
use of javax.ejb.EntityBean in project tomee by apache.
the class CmpContainer method createEJBObject.
private ProxyInfo createEJBObject(final Method callMethod, final Object[] args, final ThreadContext callContext, final InterfaceType interfaceType) throws OpenEJBException {
final BeanContext beanContext = callContext.getBeanContext();
final TransactionPolicy txPolicy = createTransactionPolicy(beanContext.getTransactionType(callMethod, interfaceType), callContext);
final EntityBean bean;
Object primaryKey = null;
try {
// Obtain a bean instance from the method ready pool
bean = createNewInstance(callContext);
// set the entity context
setEntityContext(bean);
// Obtain the proper ejbCreate() method
final Method ejbCreateMethod = beanContext.getMatchingBeanMethod(callMethod);
// Set current operation for allowed operations
callContext.setCurrentOperation(Operation.CREATE);
// Invoke the proper ejbCreate() method on the instance
ejbCreateMethod.invoke(bean, args);
// create the new bean
primaryKey = cmpEngine.createBean(bean, callContext);
// determine post create callback method
final Method ejbPostCreateMethod = beanContext.getMatchingPostCreateMethod(ejbCreateMethod);
// create a new context containing the pk for the post create call
final ThreadContext postCreateContext = new ThreadContext(beanContext, primaryKey);
postCreateContext.setCurrentOperation(Operation.POST_CREATE);
final ThreadContext oldContext = ThreadContext.enter(postCreateContext);
try {
// Invoke the ejbPostCreate method on the bean instance
ejbPostCreateMethod.invoke(bean, args);
// According to section 9.1.5.1 of the EJB 1.1 specification, the "ejbPostCreate(...)
// method executes in the same transaction context as the previous ejbCreate(...) method."
//
// The bean is first insterted using db.create( ) and then after ejbPostCreate( ) its
// updated using db.update(). This protocol allows for visablity of the bean after ejbCreate
// within the current trasnaction.
} finally {
ThreadContext.exit(oldContext);
}
// when there is not transaction, merge the data from the bean back into the cmp engine
cmpEngine.storeBeanIfNoTx(callContext, bean);
} catch (Throwable e) {
if (e instanceof InvocationTargetException) {
e = ((InvocationTargetException) e).getTargetException();
}
final ExceptionType type = callContext.getBeanContext().getExceptionType(e);
if (type == ExceptionType.SYSTEM) {
/* System Exception ****************************/
handleSystemException(txPolicy, e, callContext);
} else {
/* Application Exception ***********************/
handleApplicationException(txPolicy, e, type == ExceptionType.APPLICATION_ROLLBACK);
}
} finally {
afterInvoke(txPolicy, callContext);
}
return new ProxyInfo(beanContext, primaryKey);
}
Aggregations