001/* 002 * Copyright 2002-2012 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 * https://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 017package org.springframework.remoting.rmi; 018 019import org.springframework.aop.framework.ProxyFactory; 020import org.springframework.beans.factory.BeanClassLoaderAware; 021import org.springframework.beans.factory.FactoryBean; 022 023/** 024 * {@link FactoryBean} for RMI proxies, supporting both conventional RMI services 025 * and RMI invokers. Exposes the proxied service for use as a bean reference, 026 * using the specified service interface. Proxies will throw Spring's unchecked 027 * RemoteAccessException on remote invocation failure instead of RMI's RemoteException. 028 * 029 * <p>The service URL must be a valid RMI URL like "rmi://localhost:1099/myservice". 030 * RMI invokers work at the RmiInvocationHandler level, using the same invoker stub 031 * for any service. Service interfaces do not have to extend {@code java.rmi.Remote} 032 * or throw {@code java.rmi.RemoteException}. Of course, in and out parameters 033 * have to be serializable. 034 * 035 * <p>With conventional RMI services, this proxy factory is typically used with the 036 * RMI service interface. Alternatively, this factory can also proxy a remote RMI 037 * service with a matching non-RMI business interface, i.e. an interface that mirrors 038 * the RMI service methods but does not declare RemoteExceptions. In the latter case, 039 * RemoteExceptions thrown by the RMI stub will automatically get converted to 040 * Spring's unchecked RemoteAccessException. 041 * 042 * <p>The major advantage of RMI, compared to Hessian and Burlap, is serialization. 043 * Effectively, any serializable Java object can be transported without hassle. 044 * Hessian and Burlap have their own (de-)serialization mechanisms, but are 045 * HTTP-based and thus much easier to setup than RMI. Alternatively, consider 046 * Spring's HTTP invoker to combine Java serialization with HTTP-based transport. 047 * 048 * @author Juergen Hoeller 049 * @since 13.05.2003 050 * @see #setServiceInterface 051 * @see #setServiceUrl 052 * @see RmiClientInterceptor 053 * @see RmiServiceExporter 054 * @see java.rmi.Remote 055 * @see java.rmi.RemoteException 056 * @see org.springframework.remoting.RemoteAccessException 057 * @see org.springframework.remoting.caucho.HessianProxyFactoryBean 058 * @see org.springframework.remoting.caucho.BurlapProxyFactoryBean 059 * @see org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean 060 */ 061public class RmiProxyFactoryBean extends RmiClientInterceptor implements FactoryBean<Object>, BeanClassLoaderAware { 062 063 private Object serviceProxy; 064 065 066 @Override 067 public void afterPropertiesSet() { 068 super.afterPropertiesSet(); 069 if (getServiceInterface() == null) { 070 throw new IllegalArgumentException("Property 'serviceInterface' is required"); 071 } 072 this.serviceProxy = new ProxyFactory(getServiceInterface(), this).getProxy(getBeanClassLoader()); 073 } 074 075 076 @Override 077 public Object getObject() { 078 return this.serviceProxy; 079 } 080 081 @Override 082 public Class<?> getObjectType() { 083 return getServiceInterface(); 084 } 085 086 @Override 087 public boolean isSingleton() { 088 return true; 089 } 090 091}