1. /*
  2. * Copyright 2002-2004 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.ejb.support;
  17. import javax.ejb.EnterpriseBean;
  18. import org.springframework.beans.BeansException;
  19. import org.springframework.beans.FatalBeanException;
  20. import org.springframework.beans.factory.BeanFactory;
  21. import org.springframework.beans.factory.access.BeanFactoryLocator;
  22. import org.springframework.beans.factory.access.BeanFactoryReference;
  23. import org.springframework.context.access.ContextJndiBeanFactoryLocator;
  24. /**
  25. * Superclass for all EJBs. Package-visible: not intended for direct
  26. * subclassing. Provides a standard way of loading a BeanFactory.
  27. * Subclasses act as a facade, with the business logic deferred to
  28. * beans in the BeanFactory.
  29. *
  30. * <p>Default is to use a ContextJndiBeanFactoryLocator, which will
  31. * initialize an XML ApplicationContext from the classpath (based
  32. * on a JNDI name specified). For a lighter weight implementation when
  33. * ApplicationContext usage is not required, setBeanFactoryLocator may
  34. * be called (<i>before</i> your EJB's ejbCreate method is invoked,
  35. * for example, in setSessionContext) with a JndiBeanFactoryLocator,
  36. * which will load an XML BeanFactory from the classpath. Alternately,
  37. * setBeanFactoryLocator may be called with a completely custom
  38. * implementation of BeanFactoryLocator.
  39. *
  40. * <p>Note that we cannot use final for our implementation of
  41. * EJB lifecycle methods, as this violates the EJB specification.
  42. *
  43. * @author Rod Johnson
  44. * @author Colin Sampaleanu
  45. * @version $Id: AbstractEnterpriseBean.java,v 1.12 2004/03/19 18:34:38 jhoeller Exp $
  46. * @see #setBeanFactoryLocator
  47. * @see org.springframework.context.access.ContextJndiBeanFactoryLocator
  48. * @see org.springframework.beans.factory.access.JndiBeanFactoryLocator
  49. */
  50. abstract class AbstractEnterpriseBean implements EnterpriseBean {
  51. public static final String BEAN_FACTORY_PATH_ENVIRONMENT_KEY = "java:comp/env/ejb/BeanFactoryPath";
  52. /**
  53. * Helper strategy that knows how to locate a Spring BeanFactory
  54. * (or ApplicationContext).
  55. */
  56. private BeanFactoryLocator beanFactoryLocator;
  57. /** factoryKey to be used with BeanFactoryLocator */
  58. private String beanFactoryLocatorKey;
  59. /** Spring BeanFactory that provides the namespace for this EJB */
  60. private BeanFactoryReference beanFactoryReference;
  61. /**
  62. * Set the BeanFactoryLocator to use for this EJB.
  63. * Default is a ContextJndiBeanFactoryLocator.
  64. * <p>Can be invoked before loadBeanFactory, for example in constructor
  65. * or setSessionContext if you want to override the default locator.
  66. * <p>Note that the BeanFactory is automatically loaded by the
  67. * ejbCreate implementations of AbstractStatelessSessionBean and
  68. * AbstractMessageDriverBean but needs to be explicitly loaded in
  69. * custom AbstractStatefulSessionBean ejbCreate methods.
  70. * @see AbstractStatelessSessionBean#ejbCreate
  71. * @see AbstractMessageDrivenBean#ejbCreate
  72. * @see AbstractStatefulSessionBean#loadBeanFactory
  73. * @see org.springframework.context.access.ContextJndiBeanFactoryLocator
  74. * @see org.springframework.beans.factory.access.JndiBeanFactoryLocator
  75. */
  76. public void setBeanFactoryLocator(BeanFactoryLocator beanFactoryLocator) {
  77. this.beanFactoryLocator = beanFactoryLocator;
  78. }
  79. /**
  80. * Set the bean factory locator key.
  81. * <p>In case of the default BeanFactoryLocator implementation,
  82. * ContextJndiBeanFactoryLocator, this is the JNDI path. The default
  83. * value of this property is "java:comp/env/ejb/BeanFactoryPath".
  84. * <p>Can be invoked before loadBeanFactory, for example in constructor
  85. * or setSessionContext if you want to override the default locator key.
  86. * @see #BEAN_FACTORY_PATH_ENVIRONMENT_KEY
  87. */
  88. public void setBeanFactoryLocatorKey(String factoryKey) {
  89. this.beanFactoryLocatorKey = factoryKey;
  90. }
  91. /**
  92. * Load a Spring BeanFactory namespace.
  93. * Subclasses must invoke this method.
  94. * <p>Package-visible as it shouldn't be called directly by
  95. * user-created subclasses.
  96. * @see org.springframework.ejb.support.AbstractStatelessSessionBean#ejbCreate()
  97. */
  98. void loadBeanFactory() throws BeansException {
  99. if (this.beanFactoryLocator == null) {
  100. this.beanFactoryLocator = new ContextJndiBeanFactoryLocator();
  101. }
  102. if (this.beanFactoryLocatorKey == null) {
  103. this.beanFactoryLocatorKey = BEAN_FACTORY_PATH_ENVIRONMENT_KEY;
  104. }
  105. this.beanFactoryReference = this.beanFactoryLocator.useBeanFactory(this.beanFactoryLocatorKey);
  106. }
  107. /**
  108. * Unload the Spring BeanFactory instance.
  109. * The default ejbRemove method invokes this method, but subclasses
  110. * which override ejbRemove must invoke this method themselves.
  111. * <p>Package-visible as it shouldn't be called directly by
  112. * user-created subclasses.
  113. */
  114. void unloadBeanFactory() throws FatalBeanException {
  115. if (this.beanFactoryReference != null) {
  116. this.beanFactoryReference.release();
  117. this.beanFactoryReference = null;
  118. }
  119. }
  120. /**
  121. * May be called after ejbCreate().
  122. * @return the bean factory
  123. */
  124. protected BeanFactory getBeanFactory() {
  125. return this.beanFactoryReference.getFactory();
  126. }
  127. /**
  128. * EJB lifecycle method, implemented to invoke onEjbRemote and
  129. * unload the BeanFactory afterwards.
  130. * <p>Don't override it (although it can't be made final):
  131. * code your shutdown in onEjbRemove.
  132. * @see #onEjbRemove
  133. */
  134. public void ejbRemove() {
  135. onEjbRemove();
  136. unloadBeanFactory();
  137. }
  138. /**
  139. * Subclasses must implement this method to do any initialization
  140. * they would otherwise have done in an ejbRemove() method.
  141. * The BeanFactory will be unloaded afterwards.
  142. * <p>This implementation is empty, to be overridden in subclasses.
  143. * The same restrictions apply to the work of this method as to
  144. * an ejbRemove() method.
  145. */
  146. protected void onEjbRemove() {
  147. // empty
  148. }
  149. }