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 javax.ejb.CreateException;
  19. import javax.ejb.EJBLocalObject;
  20. import javax.naming.NamingException;
  21. import org.aopalliance.aop.AspectException;
  22. import org.aopalliance.intercept.MethodInvocation;
  23. /**
  24. * <p>Invoker for a local Stateless Session Bean.
  25. * Caches the home object. A local EJB home can never go stale.
  26. *
  27. * <p>See {@link org.springframework.jndi.AbstractJndiLocator} for info on
  28. * how to specify the JNDI location of the target EJB.
  29. *
  30. * <p>In a bean container, this class is normally best used as a singleton. However,
  31. * if that bean container pre-instantiates singletons (as do the XML ApplicationContext
  32. * variants) you may have a problem if the bean container is loaded before the EJB
  33. * container loads the target EJB. That is because the JNDI lookup will be performed in
  34. * the init method of this class and cached, but the EJB will not have been bound at the
  35. * target location yet. The solution is to not pre-instantiate this factory object, but
  36. * allow it to be created on first use. In the XML containers, this is controlled via
  37. * the "lazy-init" attribute.
  38. *
  39. * @author Rod Johnson
  40. * @version $Id: LocalSlsbInvokerInterceptor.java,v 1.11 2004/05/18 07:54:00 jhoeller Exp $
  41. */
  42. public class LocalSlsbInvokerInterceptor extends AbstractSlsbInvokerInterceptor {
  43. /**
  44. * Return a new instance of the stateless session bean.
  45. * Can be overridden to change the algorithm.
  46. */
  47. protected EJBLocalObject newSessionBeanInstance() throws NamingException, InvocationTargetException {
  48. if (logger.isDebugEnabled()) {
  49. logger.debug("Trying to create reference to local EJB");
  50. }
  51. // call superclass to invoke the EJB create method on the cached home
  52. EJBLocalObject session = (EJBLocalObject) create();
  53. if (logger.isDebugEnabled()) {
  54. logger.debug("Obtained reference to local EJB: " + session);
  55. }
  56. return session;
  57. }
  58. /**
  59. * This is the last invoker in the chain: invoke the EJB.
  60. */
  61. public Object invoke(MethodInvocation invocation) throws Throwable {
  62. EJBLocalObject ejb = null;
  63. try {
  64. ejb = newSessionBeanInstance();
  65. return invocation.getMethod().invoke(ejb, invocation.getArguments());
  66. }
  67. catch (InvocationTargetException ex) {
  68. Throwable targetException = ex.getTargetException();
  69. logger.info("Method of local EJB [" + getJndiName() + "] threw exception", targetException);
  70. if (targetException instanceof CreateException) {
  71. throw new AspectException("Could not create local EJB [" + getJndiName() + "]", targetException);
  72. }
  73. else {
  74. throw targetException;
  75. }
  76. }
  77. catch (Throwable ex) {
  78. throw new AspectException("Failed to invoke local EJB [" + getJndiName() + "]", ex);
  79. }
  80. finally {
  81. if (ejb != null) {
  82. try {
  83. ejb.remove();
  84. }
  85. catch (Throwable ex) {
  86. logger.warn("Could not invoker 'remove' on Stateless Session Bean proxy", ex);
  87. }
  88. }
  89. }
  90. }
  91. }