提交 55901e67 编写于 作者: J Juergen Hoeller

Removed EJB 2.x implementation class hierarchy (ejb.support package)

上级 30a9dad5
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.ejb.support;
import javax.ejb.EnterpriseBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.context.access.ContextJndiBeanFactoryLocator;
import org.springframework.util.WeakReferenceMonitor;
/**
* Base class for Spring-based EJB 2.x beans. Not intended for direct subclassing:
* Extend {@link AbstractStatelessSessionBean}, {@link AbstractStatefulSessionBean}
* or {@link AbstractMessageDrivenBean} instead.
*
* <p>Provides a standard way of loading a Spring BeanFactory. Subclasses act as a
* facade, with the business logic deferred to beans in the BeanFactory. Default
* is to use a {@link org.springframework.context.access.ContextJndiBeanFactoryLocator},
* which will initialize an XML ApplicationContext from the class path (based on a JNDI
* name specified). For a different locator strategy, {@code setBeanFactoryLocator}
* may be called (<i>before</i> your EJB's {@code ejbCreate} method is invoked,
* e.g. in {@code setSessionContext}). For use of a shared ApplicationContext between
* multiple EJBs, where the container class loader setup supports this visibility, you may
* instead use a {@link org.springframework.context.access.ContextSingletonBeanFactoryLocator}.
* Alternatively, {@link #setBeanFactoryLocator} may be called with a custom implementation
* of the {@link org.springframework.beans.factory.access.BeanFactoryLocator} interface.
*
* <p>Note that we cannot use {@code final} for our implementation of EJB lifecycle
* methods, as this would violate the EJB specification.
*
* @author Rod Johnson
* @author Colin Sampaleanu
* @author Juergen Hoeller
* @see org.springframework.context.access.ContextJndiBeanFactoryLocator
* @see org.springframework.context.access.ContextSingletonBeanFactoryLocator
* @deprecated as of Spring 3.2, in favor of implementing EJBs in EJB 3 style
*/
@Deprecated
@SuppressWarnings("serial")
public abstract class AbstractEnterpriseBean implements EnterpriseBean {
public static final String BEAN_FACTORY_PATH_ENVIRONMENT_KEY = "java:comp/env/ejb/BeanFactoryPath";
/**
* Helper strategy that knows how to locate a Spring BeanFactory (or
* ApplicationContext).
*/
private BeanFactoryLocator beanFactoryLocator;
/** factoryKey to be used with BeanFactoryLocator */
private String beanFactoryLocatorKey;
/** Spring BeanFactory that provides the namespace for this EJB */
private BeanFactoryReference beanFactoryReference;
/**
* Set the BeanFactoryLocator to use for this EJB. Default is a
* ContextJndiBeanFactoryLocator.
* <p>Can be invoked before loadBeanFactory, for example in constructor or
* setSessionContext if you want to override the default locator.
* <p>Note that the BeanFactory is automatically loaded by the {@code ejbCreate}
* implementations of AbstractStatelessSessionBean and
* AbstractMessageDriverBean but needs to be explicitly loaded in custom
* AbstractStatefulSessionBean {@code ejbCreate} methods.
* @see AbstractStatelessSessionBean#ejbCreate
* @see AbstractMessageDrivenBean#ejbCreate
* @see AbstractStatefulSessionBean#loadBeanFactory
* @see org.springframework.context.access.ContextJndiBeanFactoryLocator
*/
public void setBeanFactoryLocator(BeanFactoryLocator beanFactoryLocator) {
this.beanFactoryLocator = beanFactoryLocator;
}
/**
* Set the bean factory locator key.
* <p>In case of the default BeanFactoryLocator implementation,
* ContextJndiBeanFactoryLocator, this is the JNDI path. The default value
* of this property is "java:comp/env/ejb/BeanFactoryPath".
* <p>Can be invoked before {@link #loadBeanFactory}, for example in the constructor
* or {@code setSessionContext} if you want to override the default locator key.
* @see #BEAN_FACTORY_PATH_ENVIRONMENT_KEY
*/
public void setBeanFactoryLocatorKey(String factoryKey) {
this.beanFactoryLocatorKey = factoryKey;
}
/**
* Load a Spring BeanFactory namespace. Subclasses must invoke this method.
* <p>Package-visible as it shouldn't be called directly by user-created
* subclasses.
* @see org.springframework.ejb.support.AbstractStatelessSessionBean#ejbCreate()
*/
void loadBeanFactory() throws BeansException {
if (this.beanFactoryLocator == null) {
this.beanFactoryLocator = new ContextJndiBeanFactoryLocator();
}
if (this.beanFactoryLocatorKey == null) {
this.beanFactoryLocatorKey = BEAN_FACTORY_PATH_ENVIRONMENT_KEY;
}
this.beanFactoryReference = this.beanFactoryLocator.useBeanFactory(this.beanFactoryLocatorKey);
// We cannot rely on the container to call ejbRemove() (it's skipped in
// the case of system exceptions), so ensure the the bean factory
// reference is eventually released.
WeakReferenceMonitor.monitor(this, new BeanFactoryReferenceReleaseListener(this.beanFactoryReference));
}
/**
* Unload the Spring BeanFactory instance. The default {@link #ejbRemove()}
* method invokes this method, but subclasses which override {@code ejbRemove()}
* must invoke this method themselves.
* <p>Package-visible as it shouldn't be called directly by user-created
* subclasses.
*/
void unloadBeanFactory() throws FatalBeanException {
// We will not ever get here if the container skips calling ejbRemove(),
// but the WeakReferenceMonitor will still clean up (later) in that case.
if (this.beanFactoryReference != null) {
this.beanFactoryReference.release();
this.beanFactoryReference = null;
}
}
/**
* May be called after {@code ejbCreate()}.
* @return the bean factory
*/
protected BeanFactory getBeanFactory() {
return this.beanFactoryReference.getFactory();
}
/**
* EJB lifecycle method, implemented to invoke {@code onEjbRemove()}
* and unload the BeanFactory afterwards.
* <p>Don't override it (although it can't be made final): code your shutdown
* in {@link #onEjbRemove()}.
*/
public void ejbRemove() {
onEjbRemove();
unloadBeanFactory();
}
/**
* Subclasses must implement this method to do any initialization they would
* otherwise have done in an {@code ejbRemove()} method.
* The BeanFactory will be unloaded afterwards.
* <p>This implementation is empty, to be overridden in subclasses.
* The same restrictions apply to the work of this method as to an
* {@code ejbRemove()} method.
*/
protected void onEjbRemove() {
// empty
}
/**
* Implementation of WeakReferenceMonitor's ReleaseListener callback interface.
* Release the given BeanFactoryReference if the monitor detects that there
* are no strong references to the handle anymore.
*/
private static class BeanFactoryReferenceReleaseListener implements WeakReferenceMonitor.ReleaseListener {
private final BeanFactoryReference beanFactoryReference;
public BeanFactoryReferenceReleaseListener(BeanFactoryReference beanFactoryReference) {
this.beanFactoryReference = beanFactoryReference;
}
public void released() {
this.beanFactoryReference.release();
}
}
}
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.ejb.support;
import javax.jms.MessageListener;
/**
* Convenient base class for JMS-based EJB 2.x MDBs. Requires subclasses
* to implement the JMS {@code javax.jms.MessageListener} interface.
*
* @author Rod Johnson
* @deprecated as of Spring 3.2, in favor of implementing EJBs in EJB 3 style
*/
@Deprecated
@SuppressWarnings("serial")
public abstract class AbstractJmsMessageDrivenBean extends AbstractMessageDrivenBean implements MessageListener {
// Empty: The purpose of this class is to ensure
// that subclasses implement {@code javax.jms.MessageListener}.
}
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.ejb.support;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Convenient base class for EJB 2.x MDBs.
* Doesn't require JMS, as EJB 2.1 MDBs are no longer JMS-specific;
* see the {@link AbstractJmsMessageDrivenBean} subclass.
*
* <p>This class ensures that subclasses have access to the
* MessageDrivenContext provided by the EJB container, and implement
* a no-arg {@code ejbCreate()} method as required by the EJB
* specification. This {@code ejbCreate()} method loads a BeanFactory,
* before invoking the {@code onEjbCreate()} method, which is
* supposed to contain subclass-specific initialization.
*
* <p>NB: We cannot use final methods to implement EJB API methods,
* as this violates the EJB specification. However, there should be
* no need to override the {@code setMessageDrivenContext} or
* {@code ejbCreate()} methods.
*
* @author Rod Johnson
* @deprecated as of Spring 3.2, in favor of implementing EJBs in EJB 3 style
*/
@Deprecated
@SuppressWarnings("serial")
public abstract class AbstractMessageDrivenBean extends AbstractEnterpriseBean
implements MessageDrivenBean {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private MessageDrivenContext messageDrivenContext;
/**
* Required lifecycle method. Sets the MessageDriven context.
* @param messageDrivenContext MessageDrivenContext
*/
public void setMessageDrivenContext(MessageDrivenContext messageDrivenContext) {
this.messageDrivenContext = messageDrivenContext;
}
/**
* Convenience method for subclasses to use.
* @return the MessageDrivenContext passed to this EJB by the EJB container
*/
protected final MessageDrivenContext getMessageDrivenContext() {
return this.messageDrivenContext;
}
/**
* Lifecycle method required by the EJB specification but not the
* MessageDrivenBean interface. This implementation loads the BeanFactory.
* <p>Don't override it (although it can't be made final): code initialization
* in onEjbCreate(), which is called when the BeanFactory is available.
* <p>Unfortunately we can't load the BeanFactory in setSessionContext(),
* as resource manager access isn't permitted and the BeanFactory may require it.
*/
public void ejbCreate() {
loadBeanFactory();
onEjbCreate();
}
/**
* Subclasses must implement this method to do any initialization they would
* otherwise have done in an {@code ejbCreate()} method. In contrast
* to {@code ejbCreate()}, the BeanFactory will have been loaded here.
* <p>The same restrictions apply to the work of this method as
* to an {@code ejbCreate()} method.
*/
protected abstract void onEjbCreate();
}
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.ejb.support;
import javax.ejb.SessionContext;
/**
* Base class for Spring-based EJB 2.x session beans. Not intended for direct
* subclassing: Extend {@link AbstractStatelessSessionBean} or
* {@link AbstractStatefulSessionBean} instead.
*
* <p>This class saves the session context provided by the EJB container in an
* instance variable and exposes it through the {@link SmartSessionBean} interface.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @deprecated as of Spring 3.2, in favor of implementing EJBs in EJB 3 style
*/
@Deprecated
@SuppressWarnings("serial")
public abstract class AbstractSessionBean extends AbstractEnterpriseBean implements SmartSessionBean {
/** The SessionContext passed to this EJB */
private SessionContext sessionContext;
/**
* Set the session context for this EJB.
* <p><b>When overriding this method, be sure to invoke this form of it first.</b>
*/
public void setSessionContext(SessionContext sessionContext) {
this.sessionContext = sessionContext;
}
/**
* Convenience method for subclasses, returning the EJB session context
* saved on initialization ({@link #setSessionContext}).
*/
public final SessionContext getSessionContext() {
return this.sessionContext;
}
}
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.ejb.support;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
/**
* Convenient base class for EJB 2.x stateful session beans (SFSBs).
* SFSBs should extend this class, leaving them to implement the
* {@code ejbActivate()} and {@code ejbPassivate()} lifecycle
* methods to comply with the requirements of the EJB specification.
*
* <p><b>Note: Subclasses should invoke the {@code loadBeanFactory()}
* method in their custom {@code ejbCreate()} and {@code ejbActivate()}
* methods, and should invoke the {@code unloadBeanFactory()} method in
* their {@code ejbPassivate} method.</b>
*
* <p><b>Note: The default BeanFactoryLocator used by this class's superclass
* (ContextJndiBeanFactoryLocator) is <b>not</b> serializable. Therefore,
* when using the default BeanFactoryLocator, or another variant which is
* not serializable, subclasses must call {@code setBeanFactoryLocator(null)}
* in {@code ejbPassivate()}, with a corresponding call to
* {@code setBeanFactoryLocator(xxx)} in {@code ejbActivate()}
* unless relying on the default locator.
*
* @author Rod Johnson
* @author Colin Sampaleanu
* @see org.springframework.context.access.ContextJndiBeanFactoryLocator
* @deprecated as of Spring 3.2, in favor of implementing EJBs in EJB 3 style
*/
@Deprecated
@SuppressWarnings("serial")
public abstract class AbstractStatefulSessionBean extends AbstractSessionBean {
/**
* Load a Spring BeanFactory namespace. Exposed for subclasses
* to load a BeanFactory in their {@code ejbCreate()} methods.
* Those callers would normally want to catch BeansException and
* rethrow it as {@link javax.ejb.CreateException}. Unless the
* BeanFactory is known to be serializable, this method must also
* be called from {@code ejbActivate()}, to reload a context
* removed via a call to {@code unloadBeanFactory()} from
* the {@code ejbPassivate()} implementation.
*/
@Override
protected void loadBeanFactory() throws BeansException {
super.loadBeanFactory();
}
/**
* Unload the Spring BeanFactory instance. The default {@code ejbRemove()}
* method invokes this method, but subclasses which override
* {@code ejbRemove()} must invoke this method themselves.
* <p>Unless the BeanFactory is known to be serializable, this method
* must also be called from {@code ejbPassivate()}, with a corresponding
* call to {@code loadBeanFactory()} from {@code ejbActivate()}.
*/
@Override
protected void unloadBeanFactory() throws FatalBeanException {
super.unloadBeanFactory();
}
}
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.ejb.support;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Convenient base class for EJB 2.x stateless session beans (SLSBs),
* minimizing the work involved in implementing an SLSB and preventing
* common errors. <b>Note that SLSBs are the most useful kind of EJB.</b>
*
* <p>As the ejbActivate() and ejbPassivate() methods cannot be invoked
* on SLSBs, these methods are implemented to throw an exception and should
* not be overriden by subclasses. (Unfortunately the EJB specification
* forbids enforcing this by making EJB lifecycle methods final.)
*
* <p>There should be no need to override the {@code setSessionContext()}
* or {@code ejbCreate()} lifecycle methods.
*
* <p>Subclasses are left to implement the {@code onEjbCreate()} method
* to do whatever initialization they wish to do after their BeanFactory has
* already been loaded, and is available from the {@code getBeanFactory()}
* method.
*
* <p>This class provides the no-arg {@code ejbCreate()} method required
* by the EJB specification, but not the SessionBean interface, eliminating
* a common cause of EJB deployment failure.
*
* @author Rod Johnson
* @deprecated as of Spring 3.2, in favor of implementing EJBs in EJB 3 style
*/
@Deprecated
@SuppressWarnings("serial")
public abstract class AbstractStatelessSessionBean extends AbstractSessionBean {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
/**
* This implementation loads the BeanFactory. A BeansException thrown by
* loadBeanFactory will simply get propagated, as it is a runtime exception.
* <p>Don't override it (although it can't be made final): code your own
* initialization in onEjbCreate(), which is called when the BeanFactory
* is available.
* <p>Unfortunately we can't load the BeanFactory in setSessionContext(),
* as resource manager access isn't permitted there - but the BeanFactory
* may require it.
*/
public void ejbCreate() throws CreateException {
loadBeanFactory();
onEjbCreate();
}
/**
* Subclasses must implement this method to do any initialization
* they would otherwise have done in an {@code ejbCreate()} method.
* In contrast to {@code ejbCreate}, the BeanFactory will have been loaded here.
* <p>The same restrictions apply to the work of this method as
* to an {@code ejbCreate()} method.
* @throws CreateException
*/
protected abstract void onEjbCreate() throws CreateException;
/**
* This method always throws an exception, as it should not be invoked by the EJB container.
* @see javax.ejb.SessionBean#ejbActivate()
*/
public void ejbActivate() throws EJBException {
throw new IllegalStateException("ejbActivate must not be invoked on a stateless session bean");
}
/**
* This method always throws an exception, as it should not be invoked by the EJB container.
* @see javax.ejb.SessionBean#ejbPassivate()
*/
public void ejbPassivate() throws EJBException {
throw new IllegalStateException("ejbPassivate must not be invoked on a stateless session bean");
}
}
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed 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.
*/
package org.springframework.ejb.support;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
/**
* Interface to be implemented by Session Beans that want
* to expose important state to cooperating classes.
*
* <p>Implemented by Spring's AbstractSessionBean class and hence by
* all of Spring's specific Session Bean support classes, such as
* {@link AbstractStatelessSessionBean} and {@link AbstractStatefulSessionBean}.
*
* @author Juergen Hoeller
* @since 1.2
* @see AbstractStatelessSessionBean
* @see AbstractStatefulSessionBean
* @deprecated as of Spring 3.2, in favor of implementing EJBs in EJB 3 style
*/
@Deprecated
public interface SmartSessionBean extends SessionBean {
/**
* Return the SessionContext that was passed to the Session Bean
* by the EJB container. Can be used by cooperating infrastructure
* code to get access to the user credentials, for example.
*/
SessionContext getSessionContext();
}
/**
*
* <p>Base classes to make implementing EJB 2.x beans simpler and less error-prone,
* as well as guaranteeing a Spring BeanFactory is available to such EJBs.
* This promotes good EJB practice, with EJB services used for transaction
* management, thread management, and (possibly) remoting, while
* business logic is implemented in easily testable POJOs.</p>
*
* <p>In this model, the EJB is a facade, with as many POJO helpers
* behind the BeanFactory as required.</p>
*
* <p>Note that the default behavior is to look for an EJB environment variable
* with name {@code ejb/BeanFactoryPath} that specifies the
* location <i>on the classpath</i> of an XML bean factory definition
* file (such as {@code /com/mycom/mypackage/mybeans.xml}).
* If this JNDI key is missing, your EJB subclass won't successfully
* initialize in the container.</p>
*
* <p><b>Check out the {@code org.springframework.ejb.interceptor}
* package for equivalent support for the EJB 3 component model</b>,
* providing annotation-based autowiring using an EJB 3 interceptor.</p>
*
*/
package org.springframework.ejb.support;
......@@ -265,136 +265,6 @@ public void setMyComponent(MyComponent myComponent) {
<section xml:id="ejb-implementation">
<title>Using Spring's EJB implementation support classes</title>
<section xml:id="ejb-implementation-ejb2">
<title>EJB 2.x base classes</title>
<para>
Spring provides convenience classes to help you implement EJBs.
These are designed to encourage the good practice of putting business
logic behind EJBs in POJOs, leaving EJBs responsible for transaction
demarcation and (optionally) remoting.
</para>
<para>
To implement a Stateless or Stateful session bean, or a Message Driven
bean, you need only derive your implementation class from
<classname>AbstractStatelessSessionBean</classname>,
<classname>AbstractStatefulSessionBean</classname>, and
<classname>AbstractMessageDrivenBean</classname>/<classname>AbstractJmsMessageDrivenBean</classname>,
respectively.
</para>
<para>
Consider an example Stateless Session bean which actually delegates
the implementation to a plain java service object. We have the business
interface:
</para>
<programlisting language="java"><![CDATA[public interface MyComponent {
public void myMethod(...);
...
}]]></programlisting>
<para>We also have the plain Java implementation object:</para>
<programlisting language="java"><![CDATA[public class MyComponentImpl implements MyComponent {
public String myMethod(...) {
...
}
...
}]]></programlisting>
<para>And finally the Stateless Session Bean itself:</para>
<programlisting language="java"><![CDATA[public class MyFacadeEJB extends AbstractStatelessSessionBean
implements MyFacadeLocal {
private MyComponent myComp;
/**
* Obtain our POJO service object from the BeanFactory/ApplicationContext
* @see org.springframework.ejb.support.AbstractStatelessSessionBean#onEjbCreate()
*/
protected void onEjbCreate() throws CreateException {
myComp = (MyComponent) getBeanFactory().getBean(
ServicesConstants.CONTEXT_MYCOMP_ID);
}
// for business method, delegate to POJO service impl.
public String myFacadeMethod(...) {
return myComp.myMethod(...);
}
...
}]]></programlisting>
<para>
The Spring EJB support base classes will by default create and load
a Spring IoC container as part of their lifecycle, which is then available
to the EJB (for example, as used in the code above to obtain the POJO
service object). The loading is done via a strategy object which is a subclass of
<classname>BeanFactoryLocator</classname>. The actual implementation of
<classname>BeanFactoryLocator</classname> used by default is
<classname>ContextJndiBeanFactoryLocator</classname>, which creates the
ApplicationContext from a resource locations specified as a JNDI
environment variable (in the case of the EJB classes, at
<literal>java:comp/env/ejb/BeanFactoryPath</literal>). If there is a need
to change the BeanFactory/ApplicationContext loading strategy, the default
<classname>BeanFactoryLocator</classname> implementation used may be overridden
by calling the <literal>setBeanFactoryLocator()</literal> method, either
in <literal>setSessionContext()</literal>, or in the actual constructor of
the EJB. Please see the Javadocs for more details.
</para>
<para>
As described in the Javadocs, Stateful Session beans expecting to be
passivated and reactivated as part of their lifecycle, and which use a
non-serializable container instance (which is the normal case) will have
to manually call <literal>unloadBeanFactory()</literal> and
<literal>loadBeanFactory()</literal> from <literal>ejbPassivate()</literal>
and <literal>ejbActivate()</literal>, respectively, to unload and reload the
BeanFactory on passivation and activation, since it can not be saved by
the EJB container.
</para>
<para>
The default behavior of the
<classname>ContextJndiBeanFactoryLocator</classname> class is to load an
<classname>ApplicationContext</classname> for use by an EJB, and is
adequate for some situations. However, it is problematic when the
<classname>ApplicationContext</classname> is loading a number of beans,
or the initialization of those beans is time consuming or memory
intensive (such as a Hibernate <classname>SessionFactory</classname>
initialization, for example), since every EJB will have their own copy.
In this case, the user may want to override the default
<classname>ContextJndiBeanFactoryLocator</classname> usage and use
another <classname>BeanFactoryLocator</classname> variant, such as the
<classname>ContextSingletonBeanFactoryLocator</classname> which can load
and use a shared container to be used by multiple EJBs or other clients.
Doing this is relatively simple, by adding code similar to this to the
EJB:
</para>
<programlisting language="java"><![CDATA[ /**
* Override default BeanFactoryLocator implementation
* @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)
*/
public void setSessionContext(SessionContext sessionContext) {
super.setSessionContext(sessionContext);
setBeanFactoryLocator(ContextSingletonBeanFactoryLocator.getInstance());
setBeanFactoryLocatorKey(ServicesConstants.PRIMARY_CONTEXT_ID);
}]]></programlisting>
<para>
You would then need to create a bean definition file named <literal>beanRefContext.xml</literal>.
This file defines all bean factories (usually in the form of application contexts) that may be used
in the EJB. In many cases, this file will only contain a single bean definition such as this (where
<literal>businessApplicationContext.xml</literal> contains the bean definitions for all business
service POJOs):
</para>
<programlisting language="xml"><![CDATA[<beans>
<bean id="businessBeanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg value="businessApplicationContext.xml" />
</bean>
</beans>]]></programlisting>
<para>
In the above example, the <literal>ServicesConstants.PRIMARY_CONTEXT_ID</literal> constant
would be defined as follows:
</para>
<programlisting language="java"><![CDATA[public static final String ServicesConstants.PRIMARY_CONTEXT_ID = "businessBeanFactory";]]></programlisting>
<para>
Please see the respective Javadocs for the <classname>BeanFactoryLocator</classname> and
<classname>ContextSingletonBeanFactoryLocator</classname> classes for more information on
their usage.
</para>
</section>
<section xml:id="ejb-implementation-ejb3">
<title>EJB 3 injection interceptor</title>
<para>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册