river-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Apache Wiki <wikidi...@apache.org>
Subject [River Wiki] Update of "AutomaticServiceReplacement" by TomHobbs
Date Tue, 09 Feb 2010 10:15:54 GMT
Dear Wiki user,

You have subscribed to a wiki page or wiki category on "River Wiki" for change notification.

The "AutomaticServiceReplacement" page has been changed by TomHobbs.
http://wiki.apache.org/river/AutomaticServiceReplacement

--------------------------------------------------

New page:
= Automatic Service Replacement =

This page describes how to use Java reflection to wrap a River service to provide automatic
fail over and replacements.  The exact fail over behaviour, including the number of retries,
is completely customisable.  The code offered here is simply for demonstration only.

== The River Service ==

The River service consists of a very simple interface;
{{{
package org.apache.river.samples.wrapper;

import java.rmi.RemoteException;

public interface HelloService {

    String sayHello() throws RemoteException;

}
}}}

And a very simple implementation;
{{{
package org.apache.river.samples.wrapper;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class HelloServiceImpl implements HelloService, Serializable {

    private static final long serialVersionUID = 944525970032024164L;

    private static final Logger logger = Logger.getLogger(HelloServiceImpl.class.getSimpleName());

    public String sayHello() throws RemoteException {
        logger.log(Level.FINE, "Proxy is saying hello");
        return "Hello";
    }

}
}}}

== Providing Fail Over ==

The following uses standard Java reflection to provide lazy service discovery and the fail
over strategy.  The "invoke" method below is very simple and is obviously tied to the !HelloService
implementation.  An implementation fit for real world use would obviously be generic enough
to allow it's use with any given service interface (and also use real service discovery mechanisms).
{{{
package org.apache.river.samples.wrapper;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.util.logging.Logger;
import net.jini.core.lookup.ServiceTemplate;

public class ServiceWrapper implements InvocationHandler {

    private static final Logger logger = Logger.getLogger(ServiceWrapper.class.getSimpleName());

    private Object serviceProxy;
    private ServiceTemplate template;

    public ServiceWrapper(ServiceTemplate template) {
        this.template = template;
    }

    private boolean hasService() {
        return null != this.serviceProxy;
    }

    private void findService() throws RemoteException {
        /*
         *  user supplied serviceType and template to River-lookup a new service
         *  this needs to be clever enough to *not* find any "broken" service
         *  that we're trying to replace
         * 
         *  e.g. return MyStaticServiceLookuper.lookup(template);
         */

        //dummy code which "finds" a Rivers service
        this.serviceProxy = new HelloServiceImpl();
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        logger.fine("InvocationHandler: invoking method on a proxy");

        if(!hasService()) {
            //might throw RE if no service can be found, allow this to bubble up to caller
            findService();
        }

        try {
            return ((HelloService)this.serviceProxy).sayHello();
        } catch (RemoteException re) {
            //service threw an exception, maybe it's ill?  Let's try again.
            this.serviceProxy = null;
            findService();
            return ((HelloService)this.serviceProxy).sayHello();
            /*
             * if we throw a second exception from sayHello(), then we could opt
             * to keep looking a set number of times, or let subsequent exceptions
             * bubble back to the caller
             */
        }
    }

}
}}}

== Putting It All Together ==

A simple main which puts it all together;
{{{
package org.apache.river.samples.wrapper;

import java.lang.reflect.Proxy;
import java.rmi.RemoteException;
import java.util.logging.Logger;

public class Main {

    private static final Logger logger = Logger.getLogger(Main.class.getSimpleName());

    /**
     * @param args
     * @throws RemoteException
     */
    public static void main(String[] args) throws RemoteException {

        HelloService service = (HelloService) Proxy.newProxyInstance(HelloService.class.getClassLoader(),
                new Class[] { HelloService.class },
                new ServiceWrapper());

        logger.fine("calling service: "+service.sayHello());

        System.exit(0);
    }

}
}}}

Executing this gives the output;
{{{
InvocationHandler: invoking method on a proxy
Proxy is saying hello
calling service: Hello
}}}

Mime
View raw message