cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Eirik Bjørsnøs <eir...@gmail.com>
Subject What is the proper way of implementing try/catch semantics using CXF Interceptors?
Date Tue, 07 Apr 2015 14:14:00 GMT
Hello,

We have implemented a set of interceptors for limiting the number of
concurrent invocations to each remote service.

The idea is that each remote service (be it JaxWS dispatchers or SEI
ports) should be invoked by at most N threads concurrently. If the
remote service has more than N active invocations, we should instead
return a soap fault with a message saying that the system is over
capacity. (We want to limit the load to a the number of requests we
know we can serve)

If this was to implement this using servlet filters, I would have
written a Filter.doFilter method like this::

    int current = counter.incrementAndGet();
    try {
        if(current > limit) {
            throw new ServletException("System is over capacity");
        }
        chain.doFilter(request, response);
    } finally {
        counter.decrementAndGet();
    }

However, CXF's interceptor design doesn't lend itself to use Java's
try/catch syntax.

What is the proper way of implementing try/catch semantics using CXF
Interceptors on a Client?

What we currently do:

1) We're adding a QosBeforeInterceptor early in the Client's out
interceptor chain. This implements handleMessage. We increment the
counter. If it is larger than N we throw a SoapFault. In this case
handleFault gets called (by CXF), where we decrement the counter.

2) We're adding a QosAfterInterceptor early in the Client's in
interceptor chain. This implements handleMessage where we decrement
the counter.

So by design the counter is always incremented by
QoSBeforeInterceptor.handleMessage. It should always be decremented by
either QoSBeforeInterceptor.handleFault OR by
QoSAfterInterceptor.handleMessage.

We are seeing reports from production indicating that in some cases
the counter might have been incremented, but not decremented for a
message, leading to a "leak" of counts. This causes the service to be
blocked for access indefinitely when it reaches N.

I have not been able to reproduce this "leak" situation offline,
experiementing with various exception and timeout scenarios. So I'm
not 100% sure our design is broken.

Still I would very much like some feedback on my try / catch semantics
implementation and the assumtions it is based on:

A) When a SoapFault is thrown from my interceptor's handleMessage, it
will always lead to handleFault being invoked on the same interceptor?
B) When a SoapFault is thrown from handleMessage by some later
interceptor, this always leads to handleFault being called on all
earlier interceptors in the same chain?
C) If handleFault is not called on the outgoing chain of a Client,
then handleMessage will always be called on an interceptor on the
Client's incoming chain?

I am trying to investigate reasons for the counter being incremented,
but not decremented. That is, cases where handleMessage is called on
the out chain, but neither outgoing handleFault nor incoming
handleMessage is called.

Assuming I can't be the first to implement try/catch semantics using
interceptors, maybe someone can spot a weakness in my design?

Cheers,
Eirik.

Mime
View raw message