Thanks for all these informations Sergey, your help is very appreciated!

Anthony

Envoyé de mon iPad

Le 5 juil. 2012 à 17:37, "Sergey Beryozkin" <[email protected]> a écrit :

> Hi Anthony
> 
> Sorry for a delay
> On 05/07/12 15:50, Muller, Anthony wrote:
>> Sergey,
>> 
>> More particularly, could you confirm handleRequest ans handleResponse will 
>> still be called before and after any REST calls?
>> 
>> I don't like to have a lock never removed! :)
>> 
> As it happens at the moment, if the exception is thrown during a call to 
> the resource method, then the out filters (ResponseHandler) are not 
> called so effectively a lock will stay where it is at the moment.
> 
> It appears things are not going to easy for you :-).
> Few options are still available but given the fact you can not use 
> Spring and that CXF 2.3.x has been made obsolete makes it a bit tricky 
> to plan for a best approach.
> 
> First of all, regarding that missing path parameter. I'll write a test 
> later on and fix if needed, but your custom approach to do with parsing 
> the URI looks OK.
> 
> Now, using the custom invoker would be perfect in this case because the 
> exceptions will be caught early. But the fix I will apply to get 
> CXFNonSpringJAXRSServlet accept custom invokers won't make it to 2.3.8.
> 
> Next is the possible workaround where your resource method makes sure 
> that no exception ever escapes it: returning Response which will have a 
> proper status code set will be the easiest way to achieve it
> 
> Next option is to have your composite filter also implement CXF 
> OutFaultInterceptor, example:
> http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomOutFaultInterceptor.java
> 
> and register it as jaxrs:outFaultInterceptors, however I can see 
> CXFNonSpringJAXRSServlet does only recognizes in/out interceptors but 
> not fault ones.
> 
> So I think right now the best approach, given that you can not use 
> Spring/Blueprint, is to have the resource method which is being locked 
> ensure that no exception escapes and use the current filter implementation.
> 
> I'll take care of fixing CXFNonSpringJaxrsServlet to recognize custom 
> invokers and fault interceptors, and check why UriInfo.getPathParameters 
> does not return the parameters as expected
> 
> Thanks, Sergey
> 
>> Anthony
>> 
>> 
>> -----Original Message-----
>> From: Muller, Anthony
>> Sent: jeudi 5 juillet 2012 16:23
>> To: 'Sergey Beryozkin'
>> Cc: [email protected]
>> Subject: RE: JAX-RS services - Interceptor
>> 
>> Sergey,
>> 
>> What do you think about this implementation?
>> 
>> Anthony
>> 
>> 
>> public final class BookHandler implements RequestHandler, ResponseHandler {
>> 
>>    private static final String KEY = "/books/";
>> 
>>    private static final ConcurrentMap<String, Lock>  BOOK_LOCKS = new 
>> ConcurrentHashMap<String, Lock>();
>> 
>>    public BookHandler() {}
>> 
>>    @Context
>>    private UriInfo uriInfo;
>> 
>>    @Override
>>    public Response handleRequest(final Message m, final ClassResourceInfo 
>> resourceClass)
>>    {
>>        final String bookId = getBookId();
>> 
>>        if (bookId != null) {
>>            BOOK_LOCKS.putIfAbsent(bookId, new ReentrantLock());
>>            BOOK_LOCKS.get(bookId).lock();
>>            System.out.println("lock: " + bookId);
>>        }
>> 
>>        return null;
>>    }
>> 
>>    @Override
>>    public Response handleResponse(final Message m, final 
>> OperationResourceInfo ori, final Response response)
>>    {
>>        final String bookId = getBookId();
>> 
>>        if(bookId != null) {
>>            BOOK_LOCKS.get(bookId).unlock();
>>            System.out.println("unlock: " + bookId);
>>        }
>> 
>>        return null;
>>    }
>> 
>>    private String getBookId() {
>>        String bookId = null;
>>        int startIndex = uriInfo.getPath().indexOf(KEY);
>>        startIndex += KEY.length();
>>        if (startIndex>= 0) {
>>            final int lastIndex = uriInfo.getPath().indexOf("/", startIndex);
>>            bookId = uriInfo.getPath().substring(startIndex, lastIndex);
>>        }
>>        return bookId;
>>    }
>> }
>> 
>> 
>> 
>> -----Original Message-----
>> From: Sergey Beryozkin [mailto:[email protected]]
>> Sent: jeudi 5 juillet 2012 14:17
>> To: Muller, Anthony
>> Cc: [email protected]
>> Subject: Re: JAX-RS services - Interceptor
>> 
>> Hi Anthony
>> On 05/07/12 12:50, Muller, Anthony wrote:
>>> Thx Sergey, that seems fine!
>>> 
>>> I'm trying using UriInfo injection and I'm trying to detect the case where 
>>> I must lock my resource.
>>> 
>>> I hope to get the {bookId} easily, but there is nothing into path 
>>> parameters... Normal?
>>> 
>>> I wrote something like:
>>> 
>>> @Override
>>> public Response handleRequest(final Message m, final ClassResourceInfo 
>>> resourceClass) {
>>>    System.out.println("BookHandler.handleRequest: " + uriInfo.getPath());
>>>    
>>>    if(uriInfo.getPath().contains("/books/")) {
>>>        final MultivaluedMap<String, String>   pathParameters = 
>>> uriInfo.getPathParameters();
>>>        final Set<String>   pathParameterNames = pathParameters.keySet();
>>>        for (final String pathParameterName : pathParameterNames) {
>>>            System.out.println(pathParameterName + " : " + 
>>> pathParameters.getFirst(pathParameterName));
>>>        }    
>>>    }
>>>    
>>>    return null;
>>> }
>>> 
>> 
>> I'm looking at the CXF code and I can confirm that the operation
>> matching is attempted before the filters are run. So if you have a
>> method such as
>> 
>> @POST
>> @Path("{index}")
>> public void addBook(@PathParam("index") int index, Book book) {}
>> 
>> and a request URI ending with something like /books/123
>> 
>> then UriInfo should return an "index":123 pair
>> 
>> Can you confirm please that in your above case the request URI is
>> expected to match a method with @PathParam annotations ?
>> 
>> By the way, perhaps there's one option for this case.
>> Instead of doing the filters, consider creating a custom invoker which
>> gets the control immediately before and after the matched method is
>> invoked. For example:
>> 
>> http://svn.apache.org/repos/asf/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/CustomJAXRSInvoker.java
>> 
>> Custom invokers are registered using a jaxrs:invoker extension. However,
>> I recall you might be using CXFNonSpringJaxrsServlet - so is not
>> possible to register invokers from this servlet yet unless you extend
>> the servlet class and set the invoker on JAXRSServerFactoryBean. I'll
>> get this specific issue fixed,
>> 
>> But using the filters should also do OK
>> 
>> Sergey
>> 
>> 
>>> 
>>> 
>>> -----Original Message-----
>>> From: Sergey Beryozkin [mailto:[email protected]]
>>> Sent: jeudi 5 juillet 2012 12:49
>>> To: [email protected]
>>> Cc: Muller, Anthony
>>> Subject: Re: JAX-RS services - Interceptor
>>> 
>>> Hi Anthony
>>> On 05/07/12 11:17, Muller, Anthony wrote:
>>>> Hello,
>>>> 
>>>> I have a use case when I need to intercept some REST calls to lock a used 
>>>> resource (underlying code doesn't support concurrent access). I wish to 
>>>> use an CXF interceptor to implement the lock mechanism (something else can 
>>>> help ?)
>>>> 
>>>> Example of concurrent calls:
>>>> Client 1 : [POST]<baseurl>/books/1234/chapters/ -->    Book<   1234>   
>>>> must be locked to avoid concurrent modifications
>>>> Client 2 : [POST]<baseurl>/books/1234/chapters/56/paragraph -->    
>>>> Webservice must wait because book<   1234>   is currently locked
>>>> 
>>>> So, I wish to add a CXF interceptor on URL starting by<   
>>>> /books/{bookId}/...>, but I don't see how can I do...
>>>> 
>>>> (In my case, I can not use Servlet API...)
>>>> 
>>> 
>>> I think the simplest way is to create a class implementing both
>>> RequestHandler and ResponseHandler interfaces and have a '@Context
>>> UriInfo' injected (which is thread safe).
>>> 
>>> You can use UriInfo.getPath() method to get values like
>>> 'books/1234/chapters', etc.  Perhaps, even simpler, is to do
>>> RequestHandler'message.get(Message.REQUEST_URI)', where 'message' is of
>>> type Message and is available as a method parameter.
>>> 
>>> This implementation will 'lock' by updating the concurrent cache of some
>>> sort (Colm done few Ehcache based implementations in CXF for example) in
>>> its handleRequest method and 'unlock' in its handleResponse if it is
>>> 'books/1234/chapters'. It can be registered as a jaxrs:provider
>>> 
>>> 
>>> 
>>> Hope that helps :-)
>>> 
>>> Sergey
>>> 
>>>> Can you help ?
>>>> 
>>>> Thanks and regards,
>>>> Anthony
>>>> 
>>> 
>> 
>> 
> 
> 
> -- 
> Sergey Beryozkin
> 
> Talend Community Coders
> http://coders.talend.com/
> 
> Blog: http://sberyozkin.blogspot.com

Reply via email to