Фасад, чтобы скрыть детали аутентификации от веб-сервиса Java - PullRequest
0 голосов
/ 31 июля 2011

Я создаю UI-клиент, который использует сервисный API, который за сценой использует веб-сервисы.Одна из служб API выглядит следующим образом:

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;
}

loggedInUser - это пользователь, от имени которого вызывается метод.AuthenticationFault является проверенным исключением.Там около 20 таких сервисных интерфейсов.То, что я хотел бы сделать, это реализовать фасад, который скрывает параметры loggedInUser и исключения AuthenticationFault.Реализация фасада вызовет эти методы у пользователя, который в данный момент зарегистрирован в клиенте.

Я также хотел бы провести некоторую очистку с другими проверенными исключениями.Как вы можете видеть, есть исключение InvalidIndexFault, которое выдается, когда клиент пытается получить страницу -1, но это ошибка программиста, и я не хочу, чтобы это было проверенное исключение.

В настоящее время то, что я 'Мы сделали это, всегда перебрасываем RuntimeException для исключений, которые мне не нравятся, но если я потом передумаю, это будет большая работа, чтобы изменить это позже.Это также похоже на дублирование кода.Другие программисты только что проглотили исключения и записали их в журнал, что совершенно ужасно.В большинстве случаев, если есть исключение, я хочу добавить его в обработчик ошибок в пользовательском интерфейсе, который отображает ошибку.

Мне пришло в голову несколько решений:

  1. Динамический прокси-сервер Java
  2. Генерация кода

Я не удосужился опробовать эти решения и решил, что с таким же успехом могу спросить здесь в первую очередь.Как вы предлагаете мне это реализовать?Среда - Java 6, а инструмент сборки - Maven 3, если это помогает.

PS.Если вы ответите на это, пожалуйста, скажите больше, чем «выберите номер 2» :) Любые советы и другие детали реализации приветствуются.

В качестве пояснения, получение текущего зарегистрированного пользователя не является проблемой, поэтому вы не понимаетене должен помочь мне с этим.Я в настоящее время скрываю это за интерфейсом и использую IoC, чтобы внедрить это вокруг.За кулисами он использует ThreadLocals

1 Ответ

1 голос
/ 31 июля 2011

Я думаю, это был бы идеальный вариант использования для

  1. Java Dynamic Proxys
  2. Локальные потоки

Чтобы объяснить:

Сначала создайте свой интерфейс фасада:

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

Затем вы реализуете 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
       ....
    }
}

Затем вы создаете объект Proxy следующим образом:

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

Первый аргумент - загрузчик классов, второй - список интерфейсов, которые прокси должен подтвердить, а третий - объект-обработчик

Теперь вопрос в том, как получить дескриптор для вашего loggedinUser.Вот тут и приходит ThreadLocal .

Создайте статическую переменную ThreadLocal, которая будет содержать зарегистрированного пользователя.Затем установите текущего пользователя в ThreadLocal перед вызовом прокси

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

Извлеките пользователя из ThreadLocal внутри функции вызова обработчика.Теперь внутри обработчика у вас есть доступ как к loggedinUser (используя loggedinUser.get()), так и к объекту службы пользователя (вы передали объект службы в конструктор вашего обработчика)

Насколько вы обрабатываетеЧто касается исключений, то, что я хотел бы сделать, это, как правило, продолжать бросать подкласс RuntimeExceptions.Затем поймайте их на периферийном уровне вашего приложения.Под периферийным слоем я имею в виду точку входа в ваше приложение / библиотеку.Если бы вы разрабатывали webbApp, это был бы ваш сервлет.

...