001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.ejb.access;
018:
019: import javax.naming.NamingException;
020:
021: import org.springframework.aop.framework.ProxyFactory;
022: import org.springframework.beans.factory.BeanClassLoaderAware;
023: import org.springframework.beans.factory.FactoryBean;
024: import org.springframework.util.ClassUtils;
025:
026: /**
027: * <p>Convenient factory for remote SLSB proxies.
028: * If you want control over interceptor chaining, use an AOP ProxyFactoryBean
029: * with SimpleRemoteSlsbInvokerInterceptor rather than rely on this class.</p>
030: *
031: * <p>See {@link org.springframework.jndi.JndiObjectLocator} for info on
032: * how to specify the JNDI location of the target EJB.</p>
033: *
034: * <p>In a bean container, this class is normally best used as a singleton. However,
035: * if that bean container pre-instantiates singletons (as do the XML ApplicationContext
036: * variants) you may have a problem if the bean container is loaded before the EJB
037: * container loads the target EJB. That is because by default the JNDI lookup will be
038: * performed in the init method of this class and cached, but the EJB will not have been
039: * bound at the target location yet. The best solution is to set the lookupHomeOnStartup
040: * property to false, in which case the home will be fetched on first access to the EJB.
041: * (This flag is only true by default for backwards compatibility reasons).</p>
042: *
043: * <p>This proxy factory is typically used with an RMI business interface, which serves
044: * as super-interface of the EJB component interface. Alternatively, this factory
045: * can also proxy a remote SLSB with a matching non-RMI business interface, i.e. an
046: * interface that mirrors the EJB business methods but does not declare RemoteExceptions.
047: * In the latter case, RemoteExceptions thrown by the EJB stub will automatically get
048: * converted to Spring's unchecked RemoteAccessException.</p>
049: *
050: * @author Rod Johnson
051: * @author Colin Sampaleanu
052: * @author Juergen Hoeller
053: * @since 09.05.2003
054: * @see org.springframework.remoting.RemoteAccessException
055: * @see AbstractSlsbInvokerInterceptor#setLookupHomeOnStartup
056: * @see AbstractSlsbInvokerInterceptor#setCacheHome
057: * @see AbstractRemoteSlsbInvokerInterceptor#setRefreshHomeOnConnectFailure
058: */
059: public class SimpleRemoteStatelessSessionProxyFactoryBean extends
060: SimpleRemoteSlsbInvokerInterceptor implements FactoryBean,
061: BeanClassLoaderAware {
062:
063: /** The business interface of the EJB we're proxying */
064: private Class businessInterface;
065:
066: private ClassLoader beanClassLoader = ClassUtils
067: .getDefaultClassLoader();
068:
069: /** EJBObject */
070: private Object proxy;
071:
072: /**
073: * Set the business interface of the EJB we're proxying.
074: * This will normally be a super-interface of the EJB remote component interface.
075: * Using a business methods interface is a best practice when implementing EJBs.
076: * <p>You can also specify a matching non-RMI business interface, i.e. an interface
077: * that mirrors the EJB business methods but does not declare RemoteExceptions.
078: * In this case, RemoteExceptions thrown by the EJB stub will automatically get
079: * converted to Spring's generic RemoteAccessException.
080: * @param businessInterface the business interface of the EJB
081: */
082: public void setBusinessInterface(Class businessInterface) {
083: this .businessInterface = businessInterface;
084: }
085:
086: /**
087: * Return the business interface of the EJB we're proxying.
088: */
089: public Class getBusinessInterface() {
090: return this .businessInterface;
091: }
092:
093: public void setBeanClassLoader(ClassLoader classLoader) {
094: this .beanClassLoader = classLoader;
095: }
096:
097: public void afterPropertiesSet() throws NamingException {
098: super .afterPropertiesSet();
099: if (this .businessInterface == null) {
100: throw new IllegalArgumentException(
101: "businessInterface is required");
102: }
103: this .proxy = new ProxyFactory(this .businessInterface, this )
104: .getProxy(this .beanClassLoader);
105: }
106:
107: public Object getObject() {
108: return this .proxy;
109: }
110:
111: public Class getObjectType() {
112: return this .businessInterface;
113: }
114:
115: public boolean isSingleton() {
116: return true;
117: }
118:
119: }
|