org.apache.beehive.controls.system.ejb.EntityEJBControlImpl Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Header:$
*/
package org.apache.beehive.controls.system.ejb;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.util.Collection;
import java.util.Iterator;
import javax.ejb.EJBLocalObject;
import javax.ejb.EJBObject;
import org.apache.beehive.controls.api.ControlException;
import org.apache.beehive.controls.api.bean.ControlImplementation;
/**
* The EntityEJBControlImpl class is the control implementation class for
* Entity EJBs.
*/
@ControlImplementation(assembler = EJBControlAssembler.class)
public class EntityEJBControlImpl
extends EJBControlImpl
implements EntityEJBControl, java.io.Serializable {
static final long serialVersionUID = 1L;
//
// Implements auto-find semantics for entity beans
//
protected Object resolveBeanInstance() {
// Already resolved and cached
if (_beanInstance != null)
return _beanInstance;
// Attempt to resolve from a cached handle
_beanInstance = resolveBeanInstanceFromHandle();
if (_beanInstance != null)
return _beanInstance;
// Attempt to resolve bean instance from cached primary key
if (_lastKey == null)
throw new ControlException("Unable to locate a target bean instance, because a successful create or finder method has not been executed.");
Class [] findArgType = new Class[]{_lastKey.getClass()};
try {
Method finder = _homeInterface.getMethod("findByPrimaryKey", findArgType);
return finder.invoke(_homeInstance, new Object []{_lastKey});
}
catch (NoSuchMethodException nsme) {
throw new ControlException("Unable to locate findByPrimaryKey method on home interface", nsme);
}
catch (InvocationTargetException ite) {
_lastException = ite.getTargetException();
throw new ControlException("Failure to locate entity instance associated with the last primary key", _lastException);
}
catch (Exception e) {
throw new ControlException("Unexpected exception in auto-find", e);
}
}
protected boolean saveBeanInstance() {
//
// First, delegate to parent (handle-based persistence)
//
if (super.saveBeanInstance())
return true;
//
// Fall back to persistence using a saved primary key value
//
try {
if (_beanInstance instanceof EJBObject)
_lastKey = (Serializable) ((EJBObject) _beanInstance).getPrimaryKey();
else
_lastKey = (Serializable) ((EJBLocalObject) _beanInstance).getPrimaryKey();
}
catch (RemoteException re) {
throw new ControlException("Unable to save bean instance", re);
}
return true;
}
//
// Release the bean instance. Entity bean instances are *never* removed, except via
// direct client calls to the remove method.
//
protected void releaseBeanInstance(boolean alreadyRemoved) {
super.releaseBeanInstance(alreadyRemoved);
// Release any cached primary key value
_lastKey = null;
}
private boolean isMultiSelectorMethod(Method m) {
return isFinderMethod(m) && m.getReturnType().isAssignableFrom(Collection.class);
}
//
// This method wraps the base EJBControlImpl invoke, doing the additional
// work to maintain the primary key cache for methods which alter the
// target bean instance.
//
public Object invoke(Method m, Object [] args) throws Throwable {
Throwable invokeException = null;
Object retval = null;
Object currentBeanInstance = _beanInstance;
try {
retval = super.invoke(m, args);
}
catch (Exception t) {
// a tasty treat, but I'll throw up later
invokeException = t;
}
if (isControlBeanMethod(m)) {
m = mapControlBeanMethodToEJB(m);
}
if (isMultiSelectorMethod(m)) {
releaseBeanInstance(false);
Collection collection = (Collection) retval;
if (collection != null && !collection.isEmpty()) {
_colIter = collection.iterator();
_beanInstance = beanNarrow(_colIter.next());
}
else releaseBeanInstance(false);
}
else if (isSelectorMethod(m)) {
// Release collection results if a single select method is called.
_colIter = null;
}
if (invokeException != null)
throw invokeException;
return retval;
}
/**
* EntityEJBControl.getEJBNextBeanInstance()
*/
public Object getEJBNextBeanInstance() {
if (_colIter == null)
return null;
if (!_colIter.hasNext()) {
releaseBeanInstance(false);
return null;
}
_beanInstance = beanNarrow(_colIter.next());
return _beanInstance;
}
//
// Override the onCreate event handler that was already defined in EJBControlImpl to
// add additional processing.
//
public void onCreate() {
super.onCreate();
if (_beanType != EJBControlImpl.ENTITY_BEAN) {
throw new ControlException("Attempting to use a entity bean control with a bean that is not a entity bean");
}
}
//
// Override the onReset event handler that was already defined in EJBControlImpl to
// add additional processing.
//
public void onReset() {
super.onReset();
_lastKey = null;
_colIter = null;
}
private Serializable _lastKey; // primary key of the selected instance
private transient Iterator _colIter; // multi-finder result iterator
}