01: /*
02: * Copyright 2002-2007 the original author or authors.
03: *
04: * Licensed under the Apache License, Version 2.0 (the "License");
05: * you may not use this file except in compliance with the License.
06: * You may obtain a copy of the License at
07: *
08: * http://www.apache.org/licenses/LICENSE-2.0
09: *
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:
17: package org.springframework.remoting.rmi;
18:
19: import org.springframework.aop.framework.ProxyFactory;
20: import org.springframework.beans.factory.BeanClassLoaderAware;
21: import org.springframework.beans.factory.FactoryBean;
22: import org.springframework.util.ClassUtils;
23:
24: /**
25: * FactoryBean for RMI proxies, supporting both conventional RMI services and
26: * RMI invokers. Exposes the proxied service for use as a bean reference,
27: * using the specified service interface. Proxies will throw Spring's unchecked
28: * RemoteAccessException on remote invocation failure instead of RMI's RemoteException.
29: *
30: * <p>The service URL must be a valid RMI URL like "rmi://localhost:1099/myservice".
31: * RMI invokers work at the RmiInvocationHandler level, using the same invoker stub
32: * for any service. Service interfaces do not have to extend <code>java.rmi.Remote</code>
33: * or throw <code>java.rmi.RemoteException</code>. Of course, in and out parameters
34: * have to be serializable.
35: *
36: * <p>With conventional RMI services, this proxy factory is typically used with the
37: * RMI service interface. Alternatively, this factory can also proxy a remote RMI
38: * service with a matching non-RMI business interface, i.e. an interface that mirrors
39: * the RMI service methods but does not declare RemoteExceptions. In the latter case,
40: * RemoteExceptions thrown by the RMI stub will automatically get converted to
41: * Spring's unchecked RemoteAccessException.
42: *
43: * <p>The major advantage of RMI, compared to Hessian and Burlap, is serialization.
44: * Effectively, any serializable Java object can be transported without hassle.
45: * Hessian and Burlap have their own (de-)serialization mechanisms, but are
46: * HTTP-based and thus much easier to setup than RMI. Alternatively, consider
47: * Spring's HTTP invoker to combine Java serialization with HTTP-based transport.
48: *
49: * @author Juergen Hoeller
50: * @since 13.05.2003
51: * @see #setServiceInterface
52: * @see #setServiceUrl
53: * @see RmiClientInterceptor
54: * @see RmiServiceExporter
55: * @see java.rmi.Remote
56: * @see java.rmi.RemoteException
57: * @see org.springframework.remoting.RemoteAccessException
58: * @see org.springframework.remoting.caucho.HessianProxyFactoryBean
59: * @see org.springframework.remoting.caucho.BurlapProxyFactoryBean
60: * @see org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean
61: */
62: public class RmiProxyFactoryBean extends RmiClientInterceptor implements
63: FactoryBean, BeanClassLoaderAware {
64:
65: private ClassLoader beanClassLoader = ClassUtils
66: .getDefaultClassLoader();
67:
68: private Object serviceProxy;
69:
70: public void setBeanClassLoader(ClassLoader classLoader) {
71: this .beanClassLoader = classLoader;
72: }
73:
74: public void afterPropertiesSet() {
75: super .afterPropertiesSet();
76: if (getServiceInterface() == null) {
77: throw new IllegalArgumentException(
78: "Property 'serviceInterface' is required");
79: }
80: this .serviceProxy = new ProxyFactory(getServiceInterface(),
81: this ).getProxy(this .beanClassLoader);
82: }
83:
84: public Object getObject() {
85: return this .serviceProxy;
86: }
87:
88: public Class getObjectType() {
89: return getServiceInterface();
90: }
91:
92: public boolean isSingleton() {
93: return true;
94: }
95:
96: }
|