Повторите запрос CXF в случае ошибки

#java #web-services #cxf

#java #веб-сервисы #cxf

Вопрос:

У меня есть служба OSGi, которую я предоставил с помощью CXF как простой веб-сервис и для которой я создал клиент, который вызывает его методы. Методы этой службы принимают в качестве одного из своих аргументов подписанный билет, который идентифицирует клиента, выполняющего запрос. Чтобы внедрить этот билет во все запросы, поступающие от моего клиента, я создал перехватчик CXF out, который я привязал к фазе УСТАНОВКИ и который отвечает за внедрение билета в исходящее сообщение.

В случае, если срок действия билета, введенного моим перехватчиком, истек, служба выдаст исключение, которое я хотел бы иметь возможность перехватить, получить новый билет и повторить запрос с этим новым билетом, чтобы полностью абстрагировать функциональность управления билетами от остальной части моего кода. Поэтому я создал перехватчик ошибок in, который я привязал к предварительной ЛОГИЧЕСКОЙ фазе и в котором я могу определить, был ли выброшен конкретный тип исключения, который меня интересует. Однако я не уверен, как я могу повторить запрос и вернуть результат второго запроса вместо первого. Предлагает ли мне CXF способ сделать это?

Ответ №1:

Поскольку я не смог найти способ повторить запрос через перехватчик ошибок, я закончил тем, что использовал обработчик вызовов, чтобы позволить мне управлять запросом (эффективно оборачивая прокси, который я получаю от CXF, в другой прокси). В итоге я получил что-то вроде следующего:

 ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
// Configure factory
MyService serviceClient = (MyService) factory.create(MyService.class);
MyService  proxy = (MyService) Proxy.newProxyInstance(
        ServiceInvocationHandler.class.getClassLoader(), 
        new Class[] { MyService.class },
        new ServiceInvocationHandler(serviceClient));
  

Где ServiceInvocationHandler:

 public class ServiceInvocationHandler implements InvocationHandler {
    private final Object proxied;
    private SignedTicket ticket;

    public ServiceInvocationHandler(Object proxied) {
        this.proxied = proxied;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object retVal = null;
        try {
            // Generate a ticket if the one held locally by this class is null
            // and inject it in the method arguments
            retVal = method.invoke(proxied, args);
        } catch (Throwable t) {
            if (t.getCause() instanceof InvalidTicketException) {
                // Get a fresh ticket and inject it in the method arguments
                retVal = method.invoke(proxied, args);
            }
        }    
        return retVal;
    }
}