Search code examples
javafacade

A facade to hide authentication details from Java web service


I'm building an UI client that uses a service API that behind the scene uses Web services. One of the API services looks like this:

interface UserService {
    List<User> findUsers(User loggedInUser, UserSearchParameters searchParameters, PagingParameters pagingParameters) throws AuthenticationFault, InvalidIndexFault;
    void removeUser(User loggedInUser, User userToRemove) throws AutheticationFault;
    void addUser(User loggedInUser, User newUser) throws AuthenticationFault;
}

The loggedInUser is the user on who's behalf the method is called. AuthenticationFault is a checked exception. There's like 20 of these service interfaces. What I would like to do is implement a facade that hides the loggedInUser parameters and AuthenticationFault exceptions. The facade implementation would call these methods with the user that is currently logged in the client.

I would also like to do some cleaning with the other checked exceptions too. As you can see there is a InvalidIndexFault exception that is thrown when client tries to retrieve page -1 but that is a programmer error and I don't want to have it as a checked exception.

Currently what I've done is always rethrow a RuntimeException for exceptions that I don't like, but if I later change my mind it's a lot of work changing that later. This also feels like code duplication. Other programmers have just swallowed exceptions and logged them which is totally horrible. Most of the time if there is an exception I want to bubble it up to error handler in the ui that displays an error.

There's been a few solutions that have come to my mind:

  1. Java dynamic proxy
  2. Code generation

I haven't gotten around to try out those solutions and figured I might as well ask here first. How do you suggest I would implement this? The environment is Java 6 and build tool is Maven 3 if that helps.

PS. If you answer this, please say more than "pick number 2" :) Any tips and other implementation details are welcome.

As a clarification retrieving the currently logged in user is not an issue so you don't have to help me with it. I currently hide it behind an interface and use IoC to inject it around. Behind the scenes it uses ThreadLocals


Solution

  • I guess this would be the perfect use case for

    1. Java Dynamic Proxys
    2. Thread locals

    To elucidate:

    First, create your Facade Interface :

    interface UserServiceFacede {
        List findUsers(UserSearchParameters searchParameters, PagingParameters pagingParameters) throws AuthenticationFault, InvalidIndexFault;
        void removeUser(User userToRemove) throws AutheticationFault;
        void addUser(User newUser) throws AuthenticationFault;
    }
    

    Next you implement your InvocationHandler :

    public class UserHandler implements InvocationHandler{
        private final UserService service;
    
        public UserHandler(UserService service) {
           this.service = service;
        }
    
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
           ....
           // Based on the method argument, call the appropriate function on the actual service
           // object
           ....
        }
    }
    

    You then create the Proxy object like so :

      UserServiceFacade uProxy = (UserServiceFacade)Proxy.newProxyInstance(UserHandler.class.getClassLoader(), 
                                            new Class[] { UserServiceFacade.class},
                                            new UserHandler(userService));
    

    The first argument is the classloader, the second is the list of interfaces the Proxy must confirm to and the third is the handler object

    Now the question is how do you get a handle onto your loggedinUser. This is where ThreadLocal comes in.

    Create a ThreadLocal static variable that holds the loggedin user. Then set the current user into the ThreadLocal before invoking the proxy

         private static final ThreadLocal loggedinUser = ...;
         ...
         ...
         loggedinUser.set(currentUser);
         // Create a user Proxy object as mentioned above.. 
         uProxy.findUser(searchParams, ..);
         ...
    

    Retrieve the User from the ThreadLocal inside the invoke function of the handler. Now inside the handler, you have access to both the loggedinUser (using loggedinUser.get()) as well as the user service object (You have passed in the service object into your handler's constructor)

    As far as how you handle exceptions are concerned, WHat I would do is generally keep throwing a subclass of RuntimeExceptions. Then catch these at the periphery layer of your app. By periphery layer I mean, entry point into your app/library. If you were developing a webbApp this would be your Servlet.