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.access;
  17. import java.lang.reflect.InvocationTargetException;
  18. import java.lang.reflect.Method;
  19. import javax.naming.NamingException;
  20. import org.aopalliance.aop.AspectException;
  21. import org.aopalliance.intercept.MethodInterceptor;
  22. import org.springframework.beans.FatalBeanException;
  23. import org.springframework.jndi.AbstractJndiLocator;
  24. /**
  25. * Superclass for AOP interceptors invoking remote or local Stateless Session Beans.
  26. *
  27. * <p>Such an interceptor must be the last interceptor in the advice chain.
  28. * In this case, there is no target object.
  29. *
  30. * @author Rod Johnson
  31. * @version $Id: AbstractSlsbInvokerInterceptor.java,v 1.11 2004/05/18 07:54:00 jhoeller Exp $
  32. */
  33. public abstract class AbstractSlsbInvokerInterceptor extends AbstractJndiLocator
  34. implements MethodInterceptor {
  35. private boolean cacheHome = true;
  36. /**
  37. * The EJB's home interface.
  38. * The type must be Object as it could be either EJBHome or EJBLocalHome.
  39. */
  40. private Object cachedHome;
  41. /**
  42. * The no-arg create() method required on EJB homes,
  43. * but not part of EJBLocalHome. We cache this in the located() method.
  44. */
  45. private Method createMethod;
  46. /**
  47. * Set whether to cache the EJB home object. Default is true.
  48. * <p>Can be turned off to allow for hot redeploy of the target EJB
  49. * respectively restart of the EJB container.
  50. */
  51. public void setCacheHome(boolean cacheHome) {
  52. this.cacheHome = cacheHome;
  53. }
  54. /**
  55. * Implementation of AbstractJndiLocator's callback, to cache the home wrapper.
  56. * Invokes afterLocated() after execution.
  57. * @see #afterLocated
  58. */
  59. protected void located(Object jndiObject) {
  60. // cache the home object
  61. this.cachedHome = jndiObject;
  62. try {
  63. // cache the EJB create() method that must be declared on the home interface
  64. this.createMethod = this.cachedHome.getClass().getMethod("create", null);
  65. }
  66. catch (NoSuchMethodException ex) {
  67. throw new FatalBeanException("Cannot create EJB proxy: EJB home [" + this.cachedHome +
  68. "] has no no-arg create() method");
  69. }
  70. // invoke any subclass initialization behavior
  71. afterLocated();
  72. }
  73. /**
  74. * Initialization hook after the AbstractJndiLocator's located callback.
  75. * This implementation does nothing.
  76. * @see #located
  77. */
  78. protected void afterLocated() {
  79. }
  80. /**
  81. * Return the cached home object.
  82. */
  83. protected Object getCachedEjbHome() {
  84. return cachedHome;
  85. }
  86. /**
  87. * Invoke the create() method on the cached EJB home.
  88. * @return a new EJBObject or EJBLocalObject
  89. */
  90. protected Object create() throws NamingException, InvocationTargetException {
  91. if (!this.cacheHome) {
  92. lookup();
  93. }
  94. try {
  95. return this.createMethod.invoke(this.cachedHome, null);
  96. }
  97. catch (IllegalArgumentException ex) {
  98. // can't happen
  99. throw new AspectException("Inconsistent state: could not call ejbCreate() method without arguments", ex);
  100. }
  101. catch (IllegalAccessException ex) {
  102. throw new AspectException("Could not access ejbCreate() method", ex);
  103. }
  104. }
  105. }