OK, I have an initial patch for this ready. I can commit it myself,
but I wanted to post it as a warning as it has a few unresolved issues.
I have implemented the JSR77 state model in Component and AbstractComponent
For start and stop this was simple. But I have also removed the
create and destroy methods for now. I moved any create operations
I found to the start() (or doStart()) methods.
I have left destroy methods in the code, but noted that they are
currently not supported by the lifecycle. I think they do contain
good cleanup code - but we could just rely on java finalize mechanism?
Or we could move the code into doStop to be symmetric with doStart.
I have implemented startRecursive in ContainerImpl - however, I really
think that we need an AbstractContainer class for this. But this
would need a method for iterating over children in the Container interface.
As this is not there - I have not done this... more reading of JSR77 spec
required to support their container naming and methods I think?
In JSR77 there is no stopRecursive method - so ContainerImpl.stop is
actually recursive (which I think is the correct thing to do?) Again
this should be in AbstactContainer.
I'll give this a few hours for "DON'T DO IT" reponses and if I don't
get them I'll do the commit and we can work on the remaining issues.
--
Greg Wilkins<[EMAIL PROTECTED]> Phone/fax: +44 7092063462
Mort Bay Consulting Australia and UK. http://www.mortbay.com
Index: modules/core/src/java/org/apache/geronimo/common/AbstractComponent.java
===================================================================
RCS file:
/home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/common/AbstractComponent.java,v
retrieving revision 1.2
diff -r1.2 AbstractComponent.java
58d57
<
68,69c67,70
< public class AbstractComponent implements Component {
< private State state = State.NOT_CREATED;
---
> public class AbstractComponent implements Component
> {
> private State state= State.STOPPED;
> private long startTime;
71c72
< protected Log log = LogFactory.getLog(getClass());
---
> protected Log log= LogFactory.getLog(getClass());
73c74,75
< public State getState() {
---
> public State getState()
> {
77,91c79,178
< public final Container getContainer() {
< return container;
< }
<
< public final void setContainer(Container container) {
< if (state != State.NOT_CREATED && state != State.DESTROYED) {
< throw new IllegalStateException("Set container can only be called
while in the not-created or destroyed states: state=" + state);
< }
< if (state == State.NOT_CREATED && container == null) {
< throw new IllegalArgumentException("Interceptor has not been
created; container must be NOT null.");
< }
< if (state == State.DESTROYED && container != null) {
< throw new IllegalArgumentException("Interceptor has been
destroyed; container must be null.");
< }
< this.container = container;
---
> /**
> * Set the Component state.
> * @param newState
> * @throws IllegalStateException Thrown if the transition is not
> supported by the JSR77 lifecycle.
> */
> protected void setState(State newState) throws IllegalStateException
> {
> switch (state.getIndex())
> {
> case State.STOPPED_INDEX :
> {
> switch (state.getIndex())
> {
> case State.STARTING_INDEX :
> break;
> case State.STOPPED_INDEX :
> case State.RUNNING_INDEX :
> case State.STOPPING_INDEX :
> case State.FAILED_INDEX :
> throw new IllegalStateException(
> "Can not transition to " + newState + " state
> from " + state);
> }
> break;
> }
>
> case State.STARTING_INDEX :
> {
> switch (state.getIndex())
> {
> case State.RUNNING_INDEX :
> case State.FAILED_INDEX :
> case State.STOPPING_INDEX :
> break;
> case State.STOPPED_INDEX :
> case State.STARTING_INDEX :
> throw new IllegalStateException(
> "Can not transition to " + newState + " state
> from " + state);
> }
> break;
> }
>
> case State.RUNNING_INDEX :
> {
> switch (state.getIndex())
> {
> case State.STOPPING_INDEX :
> case State.FAILED_INDEX :
> break;
> case State.STOPPED_INDEX :
> case State.STARTING_INDEX :
> case State.RUNNING_INDEX :
> throw new IllegalStateException(
> "Can not transition to " + newState + " state
> from " + state);
>
> }
> break;
> }
>
> case State.STOPPING_INDEX :
> {
> switch (state.getIndex())
> {
> case State.STOPPED_INDEX :
> case State.FAILED_INDEX :
> break;
> case State.STARTING_INDEX :
> case State.RUNNING_INDEX :
> case State.STOPPING_INDEX :
> throw new IllegalStateException(
> "Can not transition to " + newState + " state
> from " + state);
> }
> break;
> }
>
> case State.FAILED_INDEX :
> {
> switch (state.getIndex())
> {
> case State.STARTING_INDEX :
> case State.STOPPING_INDEX :
> break;
> case State.STOPPED_INDEX :
> case State.RUNNING_INDEX :
> case State.FAILED_INDEX :
> throw new IllegalStateException(
> "Can not transition to " + newState + " state
> from " + state);
> }
> break;
> }
> }
> log.debug("State changed from " + state + " to " + newState);
> if (newState==State.RUNNING)
> startTime= System.currentTimeMillis();
> state= newState;
>
> }
>
> public long getStartTime()
> {
> return startTime;
94,98c181,183
< public void create() throws Exception {
< if (state != State.NOT_CREATED) {
< throw new IllegalStateException("Can not transition to created
state from " + state);
< }
< state = State.STOPPED;
---
> public final Container getContainer()
> {
> return container;
101,105c186,249
< public void start() throws Exception {
< if (state != State.STOPPED) {
< throw new IllegalStateException("Can not transition to started
state from " + state);
< }
< state = State.STARTED;
---
> public final void setContainer(Container container)
> {
> if (state != State.STOPPED)
> {
> throw new IllegalStateException(
> "Set container can only be called while in the stopped state:
> state=" + state);
> }
> this.container= container;
> }
>
> public void start() throws Exception
> {
> try
> {
> setState(State.STARTING);
> doStart();
> setState(State.RUNNING);
> }
> finally
> {
> if (state != State.RUNNING)
> setState(State.FAILED);
> }
> }
>
> public void startRecursive() throws Exception
> {
> start();
> }
>
> /**
> * Do the start tasks for the component. Called in the STARTING state by
> * the start() and startRecursive() methods to perform the tasks required
> to
> * start the component. The default implementation does nothing.
> * @throws Exception
> */
> public void doStart() throws Exception
> {
> }
>
> public void stop()
> {
> // Do the actual stop tasks
> try
> {
> setState(State.STOPPING);
> doStop();
> setState(State.STOPPED);
> }
> catch (Exception e)
> {
> log.warn("Stop failed", e);
> setState(State.FAILED);
> }
> }
>
> /**
> * Do the stop tasks for the component. Called in the STOPPING state by
> the stop()
> * method to perform the tasks required to stop the component.
> * This implementation does nothing.
> * @throws Exception
> */
> public void doStop() throws Exception
> {
108,122d251
< public void stop() {
< if (state == State.NOT_CREATED || state == State.DESTROYED) {
< throw new IllegalStateException("Can not transition to started
state from " + state);
< } else if (state == State.STOPPED) {
< log.warn("Stop called on an already stopped component; no
exception will be thrown but this is a programming error.");
< }
< state = State.STOPPED;
< }
<
< public void destroy() {
< if (state != State.STOPPED) {
< log.warn("Destroy called on an component in the " + state + "
state; no exception will be thrown but this is a programming error.");
< }
< state = State.DESTROYED;
< }
Index: modules/core/src/java/org/apache/geronimo/common/AbstractInterceptor.java
===================================================================
RCS file:
/home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/common/AbstractInterceptor.java,v
retrieving revision 1.2
diff -r1.2 AbstractInterceptor.java
73,80c73,74
< if (state != State.NOT_CREATED && state != State.DESTROYED) {
< throw new IllegalStateException("setNext can only be called while
in the not-created or destroyed states: state=" + state);
< }
< if (state == State.NOT_CREATED && nextInterceptor == null) {
< throw new IllegalArgumentException("Interceptor has not been
created; nextInterceptor must be NOT null.");
< }
< if (state == State.DESTROYED && nextInterceptor != null) {
< throw new IllegalArgumentException("Interceptor has been
destroyed; nextInterceptor must be null.");
---
> if (state != State.STOPPED) {
> throw new IllegalStateException("setNext can only be called while
> in the stopped state: state=" + state);
Index: modules/core/src/java/org/apache/geronimo/common/Component.java
===================================================================
RCS file:
/home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/common/Component.java,v
retrieving revision 1.2
diff -r1.2 Component.java
60c60
< *
---
> * Implements the JSR 77 state model
71a72,77
> /**
> * Gets the start time of this component
> * @return time in milliseonds since epoch that this component was
> started.
> */
> long getStartTime();
>
90,103c96
< * Transitions the component to the stopped state. This method has
access to the
< * container. Once an component has been created setContainer() will
throw IllegalStateException.
< *
< * Normally a component uses this to acquire references to other
componets of the container. The
< * components will all have been registered at this stage, but not
necessarily
< * created so methods should not be invoked on the reference until the
start method.
< *
< * @throws java.lang.Exception if a problem occurs during the transition
< * @throws java.lang.IllegalStateException if this interceptor is not in
the not-created state
< */
< void create() throws Exception, IllegalStateException;
<
< /**
< * Transitions the component to the started state. This method has
access to the
---
> * Transitions the component to the starting state. This method has
> access to the
111c104
< * @throws java.lang.IllegalStateException if this interceptor is not in
the stopped state
---
> * @throws java.lang.IllegalStateException if this interceptor is not in
> the stopped or failed state
114a108,122
> /**
> * Transitions the component to the starting state. This method has
> access to the
> * container.
> *
> * If this Component is a Container, then startRecursive is called on
> all child Components
> * that are in the STOPPED or FAILED state.
> * Normally a component uses this to cache data from other components.
> The other components will
> * have been created at this stage, but not necessairly started and may
> not be ready to have methods
> * invoked on them.
> *
> * @throws java.lang.Exception if a problem occurs during the transition
> * @throws java.lang.IllegalStateException if this interceptor is not
> in the STOPPED or FAILED state
> */
> void startRecursive() throws Exception, IllegalStateException;
>
116c124
< * Transitions the component to the stopped state. This method has
access to the
---
> * Transitions the component to the stopping state. This method has
> access to the
118a127,129
> * If this is Component is a Container, then all its child components
> must be in the
> * STOPPED or FAILED State.
> *
123c134,136
< void stop();
---
> void stop() throws IllegalStateException;
>
>
125,135d137
< /**
< * Transitions the component to the destroyed state. This method has
access to the
< * container. Once a component has been destroyed, it can not be
recreated with the i
< * create method. If the create method is called on an destroyed
component an
< * IllegalStateException will be thrown.
< *
< * Normally a component uses this to drop references to components cached
in the create method.
< * The other components will not necessairly have been destroyed at this
stage, but may have been
< * stopped somethods should not be called on other components.
< */
< void destroy();
Index: modules/core/src/java/org/apache/geronimo/common/State.java
===================================================================
RCS file:
/home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/common/State.java,v
retrieving revision 1.2
diff -r1.2 State.java
65,69c65,77
< public static final State NOT_CREATED = new State("not-created");
< public static final State STOPPED = new State("stopped");
< public static final State STARTED = new State("started");
< public static final State DESTROYED = new State("destroyed");
<
---
>
> public static final int STARTING_INDEX=0;
> public static final int RUNNING_INDEX=1;
> public static final int STOPPING_INDEX=2;
> public static final int STOPPED_INDEX=3;
> public static final int FAILED_INDEX=4;
>
> public static final State STARTING = new State("starting",STARTING_INDEX);
> public static final State RUNNING = new State("running",RUNNING_INDEX);
> public static final State STOPPING = new
> State("stopping",STOPPING_INDEX);
> public static final State STOPPED = new State("stopped",STOPPED_INDEX);
> public static final State FAILED = new State("failed",FAILED_INDEX);
>
71,72c79,81
<
< private State(String name) {
---
> private final int index;
>
> private State(String name, int index) {
73a83
> this.index = index;
75a86,89
> public int getIndex() {
> return index;
> }
>
Index: modules/core/src/java/org/apache/geronimo/ejb/EJBProxyFactoryManager.java
===================================================================
RCS file:
/home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/ejb/EJBProxyFactoryManager.java,v
retrieving revision 1.3
diff -r1.3 EJBProxyFactoryManager.java
76,87d75
< public void create() throws Exception {
< log.debug("Creating EJBProxyFactoryManager: ejbName=" +
EJBPlugins.getEJBMetadata(getContainer()).getName());
< super.create();
< for (Iterator iterator = proxies.keySet().iterator();
iterator.hasNext();) {
< String proxyName = (String) iterator.next();
< EJBProxyFactory ejbProxyFactory = getEJBProxyFactory(proxyName);
< // @todo uncomment this when the ejb proxy factories are rewriten
to be full components
< //ejbProxyFactory.setContainer(getContainer());
< log.debug("Creating EJBProxyFactory: proxyName=" + proxyName + "
ejbName=" + EJBPlugins.getEJBMetadata(getContainer()).getName());
< ejbProxyFactory.create();
< }
< }
89c77
< public void start() throws Exception {
---
> public void doStart() throws Exception {
91c79,80
< super.start();
---
>
> // @todo This should be handled by startRecursive()
100c89
< public void stop() {
---
> public void doStop() {
102c91,92
< super.stop();
---
>
> // @todo This will not work when this is a container, as children
> must be stopped before stop() is called.
110a101,104
>
> /**
> * @todo Currently not part of the Component lifecycle (due to jsr77)
> */
112,121d105
< log.debug("Destroying EJBProxyFactoryManager: ejbName=" +
EJBPlugins.getEJBMetadata(getContainer()).getName());
< super.destroy();
< for (Iterator iterator = proxies.keySet().iterator();
iterator.hasNext();) {
< String proxyName = (String) iterator.next();
< EJBProxyFactory ejbProxyFactory = getEJBProxyFactory(proxyName);
< log.debug("Destroying EJBProxyFactory: proxyName=" + proxyName +
" ejbName=" + EJBPlugins.getEJBMetadata(getContainer()).getName());
< ejbProxyFactory.destroy();
< // @todo uncomment this when the ejb proxy factories are rewriten
to be full components
< //ejbProxyFactory.setContainer(null);
< }
Index:
modules/core/src/java/org/apache/geronimo/ejb/cache/EnterpriseContextInstancePool.java
===================================================================
RCS file:
/home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/ejb/cache/EnterpriseContextInstancePool.java,v
retrieving revision 1.3
diff -r1.3 EnterpriseContextInstancePool.java
82,89c82,87
< public void create() throws Exception {
< super.create();
< pool = new
SimpleInstancePool(EJBPlugins.getInstanceFactory(getContainer()), maxSize,
hardLimit);
< discardQueue = new DiscardQueue();
< }
<
< public void start() throws Exception {
< super.start();
---
> public void doStart() throws Exception {
> if (pool==null)
> pool = new
> SimpleInstancePool(EJBPlugins.getInstanceFactory(getContainer()), maxSize,
> hardLimit);
> if (discardQueue==null)
> discardQueue = new DiscardQueue();
>
92a91
> // @todo Destroy not part of jsr77 lifecycle
107,108d105
<
< super.destroy();
Index:
modules/core/src/java/org/apache/geronimo/ejb/container/ContainerImpl.java
===================================================================
RCS file:
/home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/ejb/container/ContainerImpl.java,v
retrieving revision 1.3
diff -r1.3 ContainerImpl.java
76c76,79
< *
---
> * @todo Currently this class implements the startRecursive method of
> * the JSR77 lifecycle. This should be moved to an AbstractContainer class
> * @todo The stop method is implemented as stopRecursive, which is not
> * supported by jsr77
101,109c104,118
< public void create() throws Exception {
< super.create();
< // Create all the interceptors in forward insertion order
< for (Iterator iterator = pluginObjects.values().iterator();
iterator.hasNext();) {
< Object object = iterator.next();
< if (object instanceof Component) {
< Component component = (Component) object;
< component.setContainer(this);
< component.create();
---
>
> public void startRecursive() throws Exception
> {
> try
> {
> // start this component
> setState(State.STARTING);
>
> // Start all the components in forward insertion order
> for (Iterator iterator = pluginObjects.values().iterator();
> iterator.hasNext();) {
> Object object = iterator.next();
> if (object instanceof Component) {
> Component component = (Component) object;
> component.startRecursive();
> }
111d119
< }
113,117c121,129
< // Create all the plugins in forward insertion order
< for (Iterator iterator = interceptors.iterator();
iterator.hasNext();) {
< Interceptor interceptor = (Interceptor) iterator.next();
< interceptor.setContainer(this);
< interceptor.create();
---
> // Start this component
> doStart();
>
> setState(State.RUNNING);
> }
> finally
> {
> if (getState() != State.RUNNING)
> setState(State.FAILED);
120,131c132,133
<
< public void start() throws Exception {
< super.start();
< // Start all the interceptors in forward insertion order
< for (Iterator iterator = pluginObjects.values().iterator();
iterator.hasNext();) {
< Object object = iterator.next();
< if (object instanceof Component) {
< Component component = (Component) object;
< component.start();
< }
< }
<
---
>
> public void doStart() throws Exception {
140,144d141
< // Stop all the interceptors in reverse insertion order
< for (ListIterator iterator =
interceptors.listIterator(interceptors.size()); iterator.hasPrevious();) {
< Interceptor interceptor = (Interceptor) iterator.previous();
< interceptor.stop();
< }
145a143,144
> // @todo this is actually a stopRecursive, which is not supported
> // by JSR77
158a158
> // Stop this component
160a161
>
162,163c163,164
< public void destroy() {
< // Destroy all the interceptors in reverse insertion order
---
> public void doStop() {
> // Stop all the interceptors in reverse insertion order
166,181c167
< interceptor.destroy();
< interceptor.setContainer(null);
< }
<
< // Destroy all the plugins in reverse insertion order
< LinkedList list = new LinkedList();
< for (Iterator iterator = pluginObjects.values().iterator();
iterator.hasNext();) {
< Object object = iterator.next();
< if (object instanceof Component) {
< list.addFirst(object);
< }
< }
< for (Iterator iterator = list.iterator(); iterator.hasNext();) {
< Component component = (Component) iterator.next();
< component.destroy();
< component.setContainer(null);
---
> interceptor.stop();
182a169
> }
183a171,173
> // @todo destroy not supported in JSR77 lifecycle, needs to be
> // integrated or removed.
> public void destroy() {
186d175
< super.destroy();
195,199c184,185
< if (state != State.NOT_CREATED && state != State.DESTROYED) {
< throw new IllegalStateException("putPluginObject can only be
called while in the not-created or destroyed states: state=" + state);
< }
< if (state == State.NOT_CREATED && objectName == null) {
< throw new IllegalArgumentException("Container has not been
created; objectName must be NOT null.");
---
> if (state != State.STOPPED) {
> throw new IllegalStateException("putPluginObject can only be
> called while in the stopped state: state=" + state);
201,204d186
< if (state == State.DESTROYED && objectName != null) {
< throw new IllegalArgumentException("Container has been destroyed;
objectName must be null.");
< }
<
214c196
< if (state != State.NOT_CREATED && state != State.DESTROYED) {
---
> if (state != State.STOPPED) {
217,223d198
< if (state == State.NOT_CREATED && plugin == null) {
< throw new IllegalArgumentException("Container has not been
created; plugin must be NOT null.");
< }
< if (state == State.DESTROYED && plugin != null) {
< throw new IllegalArgumentException("Container has been destroyed;
plugin must be null.");
< }
<
Index:
modules/core/src/java/org/apache/geronimo/ejb/context/TransactionInterceptor.java
===================================================================
RCS file:
/home/cvs/incubator-geronimo/modules/core/src/java/org/apache/geronimo/ejb/context/TransactionInterceptor.java,v
retrieving revision 1.3
diff -r1.3 TransactionInterceptor.java
80a81,84
> public long getStartTime(){
> return transactionInterceptor.getStartTime();
> }
>
97c101
< public void create() throws Exception {
---
> public void start() throws Exception {
106,109d109
< transactionInterceptor.create();
< }
<
< public void start() throws Exception {
111a112,115
>
> public void startRecursive() throws Exception {
> transactionInterceptor.startRecursive();
> }
116a121
> // @todo not supported by JSR77 lifecycle
118d122
< transactionInterceptor.destroy();