You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by "Muller, Anthony" <an...@sap.com> on 2012/07/05 12:17:11 UTC

JAX-RS services - Interceptor

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...)

Can you help ?

Thanks and regards,
Anthony

RE: JAX-RS services - Interceptor

Posted by "Muller, Anthony" <an...@sap.com>.
Hi Sergey,

We are using CXF 2.3.8 and I can confirm that uriInfo.getPathParameters() return an empty map.

Effectivelly, we are using CXFNonSpringJaxrsServlet. Great you will add "jaxrs:invoker" extension asap :)

Thanks and regards,
Anthony



-----Original Message-----
From: Sergey Beryozkin [mailto:sberyozkin@gmail.com] 
Sent: jeudi 5 juillet 2012 14:17
To: Muller, Anthony
Cc: users@cxf.apache.org
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:sberyozkin@gmail.com]
> Sent: jeudi 5 juillet 2012 12:49
> To: users@cxf.apache.org
> 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
>>
>



Re: JAX-RS services - Interceptor

Posted by Sergey Beryozkin <sb...@gmail.com>.
FYI:
http://svn.apache.org/viewvc?rev=1359298&view=rev

Sergey
On 09/07/12 18:27, Sergey Beryozkin wrote:
> Actually, I forgot to commit the actual changes to the test filter,
> sorry about it, will be merging now :-)
>
> Sergey
> On 09/07/12 13:20, Sergey Beryozkin wrote:
>> Hi Anthony
>> On 05/07/12 21:53, Muller, Anthony wrote:
>>> Thanks for all these informations Sergey, your help is very appreciated!
>>>
>>
>> No problems :-), please see some comments below
>>
>>> Anthony
>>>
>>> Envoyé de mon iPad
>>>
>>> Le 5 juil. 2012 à 17:37, "Sergey Beryozkin"<sb...@gmail.com> 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,
>> that is supported with "jaxrs.invoker" and "jaxrs.outFaultInterceptors",
>> starting from CXF 2.4.9-SNAPSHOT
>>
>>> and check why UriInfo.getPathParameters
>>>> does not return the parameters as expected
>>
>> That actually works for me, please see the update to the test filter
>> from the revision history at
>> https://issues.apache.org/jira/browse/CXF-4413
>>
>> For UriInfo.getPathParameters to return a non-empty map (either from
>> within the filter code or the actual resource method code), there has to
>> be a *matching* resource method available, with its @Path having at
>> least one template variable. May be there are some issues to do with
>> getting the path parameters from UriInfo in CXF 2.3.8, but things work
>> as expected in later versions
>>
>> Cheers, Sergey
>>
>>
>>>>
>>>>> Anthony
>>>>>
>
>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: JAX-RS services - Interceptor

Posted by "Muller, Anthony" <an...@sap.com>.
Great, thanks again Sergey!

Envoyé de mon iPad

Le 9 juil. 2012 à 19:27, "Sergey Beryozkin" <sb...@gmail.com> a écrit :

> Actually, I forgot to commit the actual changes to the test filter, 
> sorry about it, will be merging now :-)
> 
> Sergey
> On 09/07/12 13:20, Sergey Beryozkin wrote:
>> Hi Anthony
>> On 05/07/12 21:53, Muller, Anthony wrote:
>>> Thanks for all these informations Sergey, your help is very appreciated!
>>> 
>> 
>> No problems :-), please see some comments below
>> 
>>> Anthony
>>> 
>>> Envoyé de mon iPad
>>> 
>>> Le 5 juil. 2012 à 17:37, "Sergey Beryozkin"<sb...@gmail.com> 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,
>> that is supported with "jaxrs.invoker" and "jaxrs.outFaultInterceptors",
>> starting from CXF 2.4.9-SNAPSHOT
>> 
>>> and check why UriInfo.getPathParameters
>>>> does not return the parameters as expected
>> 
>> That actually works for me, please see the update to the test filter
>> from the revision history at
>> https://issues.apache.org/jira/browse/CXF-4413
>> 
>> For UriInfo.getPathParameters to return a non-empty map (either from
>> within the filter code or the actual resource method code), there has to
>> be a *matching* resource method available, with its @Path having at
>> least one template variable. May be there are some issues to do with
>> getting the path parameters from UriInfo in CXF 2.3.8, but things work
>> as expected in later versions
>> 
>> Cheers, Sergey
>> 
>> 
>>>> 
>>>>> Anthony
>>>>> 
> 
> 
> -- 
> Sergey Beryozkin
> 
> Talend Community Coders
> http://coders.talend.com/
> 
> Blog: http://sberyozkin.blogspot.com

Re: JAX-RS services - Interceptor

Posted by Sergey Beryozkin <sb...@gmail.com>.
Actually, I forgot to commit the actual changes to the test filter, 
sorry about it, will be merging now :-)

Sergey
On 09/07/12 13:20, Sergey Beryozkin wrote:
> Hi Anthony
> On 05/07/12 21:53, Muller, Anthony wrote:
>> Thanks for all these informations Sergey, your help is very appreciated!
>>
>
> No problems :-), please see some comments below
>
>> Anthony
>>
>> Envoyé de mon iPad
>>
>> Le 5 juil. 2012 à 17:37, "Sergey Beryozkin"<sb...@gmail.com> 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,
> that is supported with "jaxrs.invoker" and "jaxrs.outFaultInterceptors",
> starting from CXF 2.4.9-SNAPSHOT
>
>> and check why UriInfo.getPathParameters
>>> does not return the parameters as expected
>
> That actually works for me, please see the update to the test filter
> from the revision history at
> https://issues.apache.org/jira/browse/CXF-4413
>
> For UriInfo.getPathParameters to return a non-empty map (either from
> within the filter code or the actual resource method code), there has to
> be a *matching* resource method available, with its @Path having at
> least one template variable. May be there are some issues to do with
> getting the path parameters from UriInfo in CXF 2.3.8, but things work
> as expected in later versions
>
> Cheers, Sergey
>
>
>>>
>>>> Anthony
>>>>


-- 
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com

Re: JAX-RS services - Interceptor

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi Anthony
On 05/07/12 21:53, Muller, Anthony wrote:
> Thanks for all these informations Sergey, your help is very appreciated!
>

No problems :-), please see some comments below

> Anthony
>
> Envoyé de mon iPad
>
> Le 5 juil. 2012 à 17:37, "Sergey Beryozkin"<sb...@gmail.com>  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,
that is supported with "jaxrs.invoker" and "jaxrs.outFaultInterceptors", 
starting from CXF 2.4.9-SNAPSHOT

> and check why UriInfo.getPathParameters
>> does not return the parameters as expected

That actually works for me, please see the update to the test filter 
from the revision history at
https://issues.apache.org/jira/browse/CXF-4413

For UriInfo.getPathParameters to return a non-empty map (either from 
within the filter code or the actual resource method code), there has to 
be a *matching* resource method available, with its @Path having at 
least one template variable. May be there are some issues to do with 
getting the path parameters from UriInfo in CXF 2.3.8, but things work 
as expected in later versions

Cheers, Sergey


>>
>>> Anthony
>>>

Re: JAX-RS services - Interceptor

Posted by "Muller, Anthony" <an...@sap.com>.
Thanks for all these informations Sergey, your help is very appreciated!

Anthony

Envoyé de mon iPad

Le 5 juil. 2012 à 17:37, "Sergey Beryozkin" <sb...@gmail.com> 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: users@cxf.apache.org
>> 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:sberyozkin@gmail.com]
>> Sent: jeudi 5 juillet 2012 14:17
>> To: Muller, Anthony
>> Cc: users@cxf.apache.org
>> 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:sberyozkin@gmail.com]
>>> Sent: jeudi 5 juillet 2012 12:49
>>> To: users@cxf.apache.org
>>> 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

Re: JAX-RS services - Interceptor

Posted by Sergey Beryozkin <sb...@gmail.com>.
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: users@cxf.apache.org
> 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:sberyozkin@gmail.com]
> Sent: jeudi 5 juillet 2012 14:17
> To: Muller, Anthony
> Cc: users@cxf.apache.org
> 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:sberyozkin@gmail.com]
>> Sent: jeudi 5 juillet 2012 12:49
>> To: users@cxf.apache.org
>> 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

RE: JAX-RS services - Interceptor

Posted by "Muller, Anthony" <an...@sap.com>.
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! :)

Anthony


-----Original Message-----
From: Muller, Anthony 
Sent: jeudi 5 juillet 2012 16:23
To: 'Sergey Beryozkin'
Cc: users@cxf.apache.org
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:sberyozkin@gmail.com] 
Sent: jeudi 5 juillet 2012 14:17
To: Muller, Anthony
Cc: users@cxf.apache.org
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:sberyozkin@gmail.com]
> Sent: jeudi 5 juillet 2012 12:49
> To: users@cxf.apache.org
> 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
>>
>



RE: JAX-RS services - Interceptor

Posted by "Muller, Anthony" <an...@sap.com>.
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:sberyozkin@gmail.com] 
Sent: jeudi 5 juillet 2012 14:17
To: Muller, Anthony
Cc: users@cxf.apache.org
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:sberyozkin@gmail.com]
> Sent: jeudi 5 juillet 2012 12:49
> To: users@cxf.apache.org
> 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
>>
>



Re: JAX-RS services - Interceptor

Posted by Sergey Beryozkin <sb...@gmail.com>.
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:sberyozkin@gmail.com]
> Sent: jeudi 5 juillet 2012 12:49
> To: users@cxf.apache.org
> 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
>>
>



RE: JAX-RS services - Interceptor

Posted by "Muller, Anthony" <an...@sap.com>.
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;
}



-----Original Message-----
From: Sergey Beryozkin [mailto:sberyozkin@gmail.com] 
Sent: jeudi 5 juillet 2012 12:49
To: users@cxf.apache.org
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
>


Re: JAX-RS services - Interceptor

Posted by Sergey Beryozkin <sb...@gmail.com>.
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
>