Announcement Announcement Module
No announcement yet.
FailoverProxyFactoryBean Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • FailoverProxyFactoryBean


    In our current project we need to provide a simple (stand alone POJO) service
    with high availability guarantees. The simplest way (for us) is to install it
    on multiple servers and build a failover mechanism into the clients.
    I was pleasantly surprised by how easy it is to achieve a transparent failover
    using Spring, and I thought that this could be useful for others too.

    Our first version below, is very basic: it always tries the first service
    provider in the list, and if an exception is thrown, the next one is tried,
    Possible improvements are:
    - first try the provider that previously worked
    - use round robin for basic load balancing

    All comments are welcome,


    <bean id="highAvailabilityBean"
              <property name="serviceInterface" value="com.x.MyInterface" />
              <property name="serviceProviders">
                      <!-- service beans are typically proxies to remote services  -->
                              <ref bean="primaryServiceProvider"/>
                              <ref bean="fallBackServiceProvider"/>
    import java.lang.reflect.InvocationTargetException;
    import java.util.Iterator;
    import java.util.List;
    import org.aopalliance.intercept.MethodInterceptor;
    import org.aopalliance.intercept.MethodInvocation;
    import org.springframework.aop.framework.ProxyFactory;
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.beans.factory.InitializingBean;
     * Factory bean for proxies to redundant services. Behaves like the proxied
     * service when used as bean reference, exposing the specified service
     * interface, but with transparent fail-over. All call to the proxy are
     * delegated to the first object in the list of service providers (@see
     * #setServiceProviders(List)). When this delegated call fails, the next
     * provider in the list will be called, etc.
     * @author be324288
    public class FailoverProxyFactoryBean extends RemoteAccessor implements
            InitializingBean, FactoryBean {
        private Object serviceProxy;
        private List serviceProviders;
         * The list of (redundant) objects that implement the interface specified
         * with {@link RemoteAccessor#setServiceInterface(java.lang.Class)}
         * @return
        public List getServiceProviders() {
            return serviceProviders;
         * @param serviceProviders
        public void setServiceProviders(List serviceProviders) {
            this.serviceProviders = serviceProviders;
        public void afterPropertiesSet() throws Exception {
            if (getServiceInterface() == null) {
                throw new IllegalArgumentException("serviceInterface is required");
            if (serviceProviders == null || serviceProviders.isEmpty()) {
                throw new IllegalArgumentException("serviceBeans is required");
            for (Object o : serviceProviders) {
                if (!getServiceInterface().isInstance(o)) {
                    throw new IllegalArgumentException(o.getClass()
                            + " does not implement the serviceInterface: " +
            this.serviceProxy = ProxyFactory.getProxy(getServiceInterface(), this);
        public Object getObject() {
            return this.serviceProxy;
        public Class getObjectType() {
            return getServiceInterface();
        public boolean isSingleton() {
            return true;
        public Object invoke(MethodInvocation mi) throws Throwable {
            Iterator iter = serviceProviders.iterator();
            while (iter.hasNext()) {
                Object bean =;
                try {
                    return bean.getClass().getMethod(mi.getMethod().getName(),
                } catch (InvocationTargetException e) {
                    // try next bean or throw exception if this is the last bean
                    if (!iter.hasNext()) {
                        throw e.getCause();
            return null;