cxf-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sergey Beryozkin <sberyoz...@gmail.com>
Subject Re: REST Method selection for different QueryParam's
Date Tue, 04 Dec 2012 15:57:10 GMT
Hi Jan -

I've modified the wiki as per the last email:

https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Basics#JAX-RSBasics-Customselectionbetweenmultipleresources

Hope you are OK with us restricting it to the query parameters only :-).
It's definitely can be enhanced to tackle more involved combinations - 
please feel free to experiment and provide the feedback, but at the 
moment it feels like we'll better off limiting the scope of such a 
custom comparator a bit :-),
Let it sit there at the wiki a bit and I guess we can eventually add it 
to CXF if there is some demand for it.

By the way the rate algo is quite cool :-)

Thanks, Sergey


On 29/11/12 19:26, Sergey Beryozkin wrote:
> Hi Jan
>
> OK, thanks...
>
> To be honest I'd just limit it to checking query parameters only.
> As I said, there may be so many variations there, a different
> combination of query, header, form, matrix, parameters, in a single
> method, or say one method accepting 2 query params, another - two header
> params, or one method - 1 query and 2 header while second method 1 query
> and 2 header params and so forth and it just not possible IMHO to write
> a generic provider which will meaningfully work for different users...
>
> Note it makes the JAX-RS code unportable too, which may not be not a
> major issue, why would anyone want to migrate from CXF ? (:-)) but it is
> a major concern for many users - to make sure they can write a portable
> code...
>
> Yes, I think it is been quite a few times when users asked about the
> query parameters affecting the selection, and it seems like a
> possibility to expect that it can be tricky to convert some existing
> code when say expects two query parameters to JAX-RS and get it
> selected, so I'm open to having a utility comparator dedicated
> specifically to taking Query params into the consideration but that is
> as far as its capabilities are concerned...
>
> Would you agree ? If yes - please give it another try, drop the support
> for headers, and also, try JAXRSUtils.getStructuredParams, it will
> return a properly populated multivalued map which will help with
> removing your own custom parsing code
>
> Thanks, Sergey
>
>
> On 29/11/12 19:09, janb wrote:
>> Hi Sergey,
>>
>> I think we are getting close to a real solution ;-)
>>
>> Your advice was very helpful, to optimize the code. I now also added
>> support for headers, so they will also be relevant for the rating.
>>
>> Here is my code:
>>
>> package org.apache.syncope.core.rest;
>>
>> import java.io.UnsupportedEncodingException;
>> import java.net.URLDecoder;
>> import java.util.HashSet;
>> import java.util.List;
>> import java.util.Set;
>>
>> import org.apache.cxf.jaxrs.ext.ResourceComparator;
>> import org.apache.cxf.jaxrs.model.ClassResourceInfo;
>> import org.apache.cxf.jaxrs.model.OperationResourceInfo;
>> import org.apache.cxf.jaxrs.model.OperationResourceInfoComparator;
>> import org.apache.cxf.jaxrs.model.Parameter;
>> import org.apache.cxf.message.Message;
>>
>> public class QueryResourceInfoComperator extends
>> OperationResourceInfoComparator implements
>> ResourceComparator {
>>
>> public QueryResourceInfoComperator() {
>> super(null, null);
>> }
>>
>> @Override
>> public int compare(ClassResourceInfo cri1, ClassResourceInfo cri2,
>> Message message) {
>> // Leave Class selection to CXF
>> return 0;
>> }
>>
>> @Override
>> public int compare(OperationResourceInfo oper1, OperationResourceInfo
>> oper2, Message message) {
>>
>> // Check if CXF can make a decision
>> int cxfResult = super.compare(oper1, oper2);
>> if (cxfResult != 0)
>> return cxfResult;
>>
>> int op1Counter = getMatchingRate(oper1, message);
>> int op2Counter = getMatchingRate(oper2, message);
>>
>> return op1Counter == op2Counter
>> ? 0
>> : op1Counter< op2Counter
>> ? 1
>> : -1;
>> }
>>
>> /**
>> * This method calculates a number indicating a good or bad match between
>> * values provided within the request and expected method parameters. A
>> * higher number means a better match.
>> *
>> * @param operation
>> * The operation to be rated, based on contained parameterInfo
>> * values.
>> * @param message
>> * A message containing query and header values from user request
>> * @return A positive or negative number, indicating a good match between
>> * query and method
>> */
>> protected int getMatchingRate(OperationResourceInfo operation, Message
>> message) {
>>
>> List<Parameter> params = operation.getParameters();
>> if (params == null || params.size() == 0)
>> return 0;
>>
>> // Get Request QueryParams
>> Set<String> qParams = getParams((String)
>> message.get(Message.QUERY_STRING));
>> // Get Request Headers
>> java.util.Map<String, String> qHeader = (java.util.Map<String,
>> String>) message
>> .get(Message.PROTOCOL_HEADERS);
>>
>> int rate = 0;
>> for (Parameter p : params) {
>> switch (p.getType()) {
>> case QUERY:
>> if (qParams.contains(p.getName()))
>> rate += 2;
>> else if (p.getDefaultValue() == null)
>> rate -= 1;
>> break;
>> case HEADER:
>> if (qHeader.containsKey(p.getName()))
>> rate += 2;
>> else if (p.getDefaultValue() == null)
>> rate -= 1;
>> break;
>> default:
>> break;
>> }
>> }
>> return rate;
>> }
>>
>> /**
>> * @param query
>> * URL Query Example: 'key=value&key2=value2'
>> * @return A Set of all keys, contained within query.
>> */
>> protected Set<String> getParams(String query) {
>> Set<String> params = new HashSet<String>();
>> if (query == null || query.length() == 0)
>> return params;
>>
>> try {
>> for (String param : query.split("&")) {
>> String pair[] = param.split("=");
>> String key = URLDecoder.decode(pair[0], "UTF-8");
>> params.add(key);
>> }
>> } catch (UnsupportedEncodingException e) {
>> e.printStackTrace();
>> }
>> return params;
>> }
>> }
>>
>>
>> I guess it would be nice, if CXF could provide the query params in a
>> Map instead of a String, then my getParams(String query) method would
>> be obsolete.
>>
>> Regards.
>> Jan
>>
>> From: Sergey Beryozkin-5 [via CXF]
>> [mailto:ml-node+s547215n5719465h66@n5.nabble.com]
>> Sent: Donnerstag, 29. November 2012 19:02
>> To: Jan Bernhardt
>> Subject: Re: REST Method selection for different QueryParam's
>>
>> On 29/11/12 17:58, Sergey Beryozkin wrote:
>>> Hi Jan
>>>
>>> OK, thanks for all the info, looks promising...
>>> It just occurred to me, you do not have to check the annotations,
>>> OperationResourceInfo has it all cached, get the list of parameters, and
>>> check parameter types (can be query. matrix, etc), this will be much
>>> faster too, please give it a try...The parameter will have an index into
>>> an array of the Method parameter array, Method can be found from
>>> ori.getMethodToInvoke()
>>
>> Actually, you don't even need a method. Parameter will have name,
>> default value, and parameter type
>>
>> Sergey
>>
>>>
>>> Cheers, Sergey
>>>
>>>
>>>
>>> On 29/11/12 17:23, janb wrote:
>>>> Hi Sergey,
>>>>
>>>> my Comperator is not simply checking the number of parameters, but
>>>> rather the matching of a query parameter name!
>>>>
>>>> Here are a couple an examples related to the sample code on the
>>>> mentioned wiki page:
>>>>
>>>> Query:
>>>> http://localhost:8080/paramTest?foo=Hello
>>>>
>>>> Rating:
>>>>
>>>> +2 : getFoo(@QueryParam("foo") String foo)
>>>>
>>>> +1 : getFooBar(@QueryParam("foo") String foo, @QueryParam("bar")
>>>> String bar)
>>>>
>>>> // Some addition samples
>>>>
>>>> 0 : getFooBar()
>>>>
>>>> -1 : getFooBar(@QueryParam("bar") String bar)
>>>>
>>>>
>>>>
>>>> So the first method would be selected.
>>>>
>>>>
>>>> Query:
>>>> http://localhost:8080/paramTest?bar=Hello
>>>>
>>>> Rating:
>>>>
>>>> -1 : getFoo(@QueryParam("foo") String foo)
>>>>
>>>> +1 : getFooBar(@QueryParam("foo") String foo, @QueryParam("bar")
>>>> String bar)
>>>>
>>>> // Some addition samples
>>>>
>>>> 0 : getFooBar()
>>>>
>>>> +2 : getFooBar(@QueryParam("bar") String bar)
>>>>
>>>>
>>>> As you can see form the number, the last one is the perfect match,
>>>> hence it would be selected. If this method would not exist the second
>>>> would still be the second best match, and so forth...
>>>>
>>>> Query:
>>>> http://localhost:8080/paramTest?something=Hello
>>>>
>>>> Rating:
>>>>
>>>> -1 : getFoo(@QueryParam("foo") String foo)
>>>>
>>>> -2 : getFooBar(@QueryParam("foo") String foo, @QueryParam("bar")
>>>> String bar)
>>>>
>>>> // Some addition samples
>>>>
>>>> 0 : getFooBar()
>>>>
>>>> -1 : getFooBar(@QueryParam("bar") String bar)
>>>>
>>>>
>>>> Parameter something is not in any of the methods, therefore
>>>> getFooBar()would be the best choice.
>>>>
>>>> Query:
>>>> http://localhost:8080/paramTest
>>>>
>>>> Rating:
>>>>
>>>> -1 : getFoo(@QueryParam("foo") String foo)
>>>>
>>>> -2 : getFooBar(@QueryParam("foo") String foo, @QueryParam("bar")
>>>> String bar)
>>>>
>>>> // Some addition samples
>>>>
>>>> 0 : getFooBar()
>>>>
>>>> -1 : getFooBar(@QueryParam("bar") String bar)
>>>>
>>>>
>>>> If no parameters are provided, all method expecting parameters will
>>>> get a negative rating, hence getFooBar() will be selected, which would
>>>> be the perfect match.
>>>>
>>>> So from my understanding, this selection algorithm always provides the
>>>> best choice, in cases where several methods match the same path and
>>>> type. And I think headers could also be handled in the same way. If a
>>>> header is present in a method signature, but this header is not
>>>> provided within the request, this method will get -1 in the rating,
>>>> otherwise if a header is requested and also provided in a request the
>>>> rating will get +2. At the end the method with the highest score will
>>>> be selected, since it has most matches and fewest mismatches compared
>>>> to all other available methods.
>>>>
>>>> WDYT?
>>>>
>>>> By the way, I updated some parts of the code, since they did not
>>>> handle Annotations within an Interface. Here is the refactored code to
>>>> update the wiki page:
>>>>
>>>> package org.apache.syncope.core.rest;
>>>>
>>>> import java.io.UnsupportedEncodingException;
>>>> import java.lang.annotation.Annotation;
>>>> import java.net.URLDecoder;
>>>> import java.util.HashMap;
>>>> import java.util.HashSet;
>>>> import java.util.Map;
>>>> import java.util.Set;
>>>>
>>>> import javax.ws.rs.DefaultValue;
>>>> import javax.ws.rs.QueryParam;
>>>>
>>>> import org.apache.cxf.jaxrs.ext.ResourceComparator;
>>>> import org.apache.cxf.jaxrs.model.ClassResourceInfo;
>>>> import org.apache.cxf.jaxrs.model.OperationResourceInfo;
>>>> import org.apache.cxf.jaxrs.model.OperationResourceInfoComparator;
>>>> import org.apache.cxf.message.Message;
>>>>
>>>> public class QueryResourceInfoComperator extends
>>>> OperationResourceInfoComparator implements
>>>> ResourceComparator {
>>>>
>>>> public QueryResourceInfoComperator() {
>>>> super(null, null);
>>>> }
>>>>
>>>> @Override
>>>> public int compare(ClassResourceInfo cri1, ClassResourceInfo cri2,
>>>> Message message) {
>>>> // Leave Class selection to CXF
>>>> return 0;
>>>> }
>>>>
>>>> @Override
>>>> public int compare(OperationResourceInfo oper1, OperationResourceInfo
>>>> oper2, Message message) {
>>>>
>>>> // Check if CXF can make a decision
>>>> int cxfResult = super.compare(oper1, oper2);
>>>> if (cxfResult != 0)
>>>> return cxfResult;
>>>>
>>>> // Compare QueryParam annotations
>>>> Set<String> qParams = getParams((String)
>>>> message.get(Message.QUERY_STRING));
>>>> Map<String, Boolean> op1Annos = getAnnotations(oper1);
>>>> Map<String, Boolean> op2Annos = getAnnotations(oper2);
>>>>
>>>> int op1Counter = getMatchingRate(op1Annos, qParams);
>>>> int op2Counter = getMatchingRate(op2Annos, qParams);
>>>>
>>>> return op1Counter == op2Counter
>>>> ? 0
>>>> : op1Counter< op2Counter
>>>> ? 1
>>>> : -1;
>>>> }
>>>>
>>>> /**
>>>> * This method calculates a number indicating a good or bad match
>>>> between
>>>> * queryParams from request and annotated method parameters. A higher
>>>> number
>>>> * means a better match.
>>>> *
>>>> * @param annotations
>>>> * Map contains name of QueryParam method parameters as a key and
>>>> * a Boolean value indicating an existing default value for this
>>>> * parameter.
>>>> * @param queryParams
>>>> * A Set of query parameters provided within the request
>>>> * @return A positive or negative number, indicating a good match
>>>> between
>>>> * query and method
>>>> */
>>>> protected int getMatchingRate(Map<String, Boolean> annotations,
>>>> Set<String> queryParams) {
>>>> int rate = 0;
>>>> for (String anno : annotations.keySet()) {
>>>> if (queryParams.contains(anno)) {
>>>> // URL query matches one method parameter
>>>> rate += 2;
>>>> } else if (!annotations.get(anno).booleanValue()) {
>>>> // No default value exists for method parameter
>>>> rate -= 1;
>>>> }
>>>> }
>>>> return rate;
>>>> }
>>>>
>>>> /**
>>>> * @param opInfo
>>>> * OperationInfo to check for parameter annotations
>>>> * @return Key in Map is QueryParam name, and Value indicates if a
>>>> default
>>>> * value is present.
>>>> */
>>>> protected Map<String, Boolean> getAnnotations(OperationResourceInfo
>>>> opInfo) {
>>>> Map<String, Boolean> opAnnos = new HashMap<String, Boolean>();
>>>> opAnnos.putAll(getAnnotations(opInfo.getAnnotatedMethod().getParameterAnnotations()));
>>>>
>>>>
>>>> opAnnos.putAll(getAnnotations(opInfo.getMethodToInvoke().getParameterAnnotations()));
>>>>
>>>>
>>>> return opAnnos;
>>>> }
>>>>
>>>> /**
>>>> * @param opParamAnnos
>>>> * Array containing all annotations for all method parameters
>>>> * @return Key in Map is QueryParam name, and Value indicates if a
>>>> default
>>>> * value is present.
>>>> */
>>>> protected Map<String, Boolean> getAnnotations(Annotation[][]
>>>> opParamAnnos) {
>>>> Map<String, Boolean> parameterAnnos = new HashMap<String, Boolean>();
>>>>
>>>> if (opParamAnnos.length == 0)
>>>> return parameterAnnos;
>>>>
>>>> for (Annotation[] pAnnos : opParamAnnos) {
>>>> if (pAnnos.length> 0) {
>>>> QueryParam qParam = null;
>>>> DefaultValue dValue = null;
>>>> for (Annotation anno : pAnnos) {
>>>> if (anno instanceof QueryParam)
>>>> qParam = (QueryParam) anno;
>>>> if (anno instanceof DefaultValue)
>>>> dValue = (DefaultValue) anno;
>>>> }
>>>> parameterAnnos.put(qParam.value(), Boolean.valueOf((dValue != null)));
>>>> }
>>>> }
>>>> return parameterAnnos;
>>>> }
>>>>
>>>> /**
>>>> * @param query
>>>> * URL Query
>>>> * @return A Set of all keys, contained within query.
>>>> */
>>>> protected Set<String> getParams(String query) {
>>>> Set<String> params = new HashSet<String>();
>>>> if (query == null || query.length() == 0)
>>>> return params;
>>>>
>>>> try {
>>>> for (String param : query.split("&")) {
>>>> String pair[] = param.split("=");
>>>> String key = URLDecoder.decode(pair[0], "UTF-8");
>>>> params.add(key);
>>>> }
>>>> } catch (UnsupportedEncodingException e) {
>>>> e.printStackTrace();
>>>> }
>>>> return params;
>>>> }
>>>> }
>>>>
>>>>
>>>> Best regards
>>>> Jan
>>>>
>>>> From: Sergey Beryozkin-5 [via CXF]
>>>> [mailto:[hidden email]</user/SendEmail.jtp?type=node&node=5719465&i=0>]
>>>> Sent: Donnerstag, 29. November 2012 17:51
>>>> To: Jan Bernhardt
>>>> Subject: Re: REST Method selection for different QueryParam's
>>>>
>>>> Hi Jan
>>>>
>>>> I've posted it to the
>>>> wiki:https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Basics#JAX-RSBasics-Customselectionbetweenmultipleresources
>>>>
>>>>
>>>>
>>>> I guess we might indeed can add a more general comparator which would
>>>> select the methods based on the number of optional parameters (of any
>>>> type such as query, header, and the combination, etc), be they
>>>> single or
>>>> repetitive.
>>>>
>>>> I'm just yet sure if that will work well or not, example,
>>>> what if we have a single query parameter but it has the name which is
>>>> not expected by a method expecting a single parameter, etc... May be we
>>>> will tune it in time :-)
>>>>
>>>> Thanks, Sergey
>>>>
>>>>
>>>>
>>>> On 27/11/12 16:40, Sergey Beryozkin wrote:
>>>>
>>>>> Hi Jan
>>>>>
>>>>> This looks very neat, more comments below
>>>>> On 27/11/12 15:25, janb wrote:
>>>>>> Hi Sergey,
>>>>>>
>>>>>> Thank you for your reply. If just developed a generic sample that
>>>>>> uses
>>>>>> CXF standard class and operation selection algorithms, but extends
it
>>>>>> with a QueryParam selection algorithm. If all other conditions in
CXF
>>>>>> match and hence CXF cannot decide which method to select best, my
>>>>>> QueryParam selection algorithm comes into place. This algorithm
>>>>>> chooses the method with most matches between provided parameters
in
>>>>>> query and matching QueryParam annotations within the method.
>>>>>> Additional (not matching) QueryParam annotations will decrease the
>>>>>> matching rate, while method parameters with a default value will
be
>>>>>> ignored (in the rating).
>>>>>>
>>>>>> If you think this code is of any value for CXF, please feel free
to
>>>>>> extend the current selection strategy with my QueryParam selection
>>>>>> algorithm. I guess the best place for my algorithm would be another
>>>>>> JAXRSUtils method, like
>>>>>> JAXRSUtils.compareQueryParams(...) to be called at the end of
>>>>>> OperationResourceInfoComparator.compare(...).
>>>>>>
>>>>>>
>>>>>> public class QueryResourceInfoComperator extends
>>>>>> OperationResourceInfoComparator implements
>>>>>> ResourceComparator {
>>>>>>
>>>>>> public QueryResourceInfoComperator() {
>>>>>> super(null, null);
>>>>>> }
>>>>>>
>>>>>> @Override
>>>>>> public int compare(ClassResourceInfo cri1, ClassResourceInfo cri2,
>>>>>> Message message) {
>>>>>> // Leave Class selection to CXF
>>>>>> return 0;
>>>>>> }
>>>>>>
>>>>>> @Override
>>>>>> public int compare(OperationResourceInfo oper1, OperationResourceInfo
>>>>>> oper2, Message message) {
>>>>>>
>>>>>> // Check if CXF can make a decision
>>>>>> int cxfResult = super.compare(oper1, oper2);
>>>>>> if (cxfResult != 0)
>>>>>> return cxfResult;
>>>>>>
>>>>>> // Compare QueryParam annotations
>>>>>> Set<String> qParams = getParams((String)
>>>>>> message.get(Message.QUERY_STRING));
>>>>>> int op1Counter =
>>>>>> getMatchingRate(getAnnotations(oper1.getMethodToInvoke().getParameterAnnotations()),
>>>>>>
>>>>>>
>>>>>>
>>>>>> qParams);
>>>>>> int op2Counter =
>>>>>> getMatchingRate(getAnnotations(oper2.getMethodToInvoke().getParameterAnnotations()),
>>>>>>
>>>>>>
>>>>>>
>>>>>> qParams);
>>>>>>
>>>>>> return op1Counter == op2Counter
>>>>>> ? 0
>>>>>> : op1Counter< op2Counter
>>>>>> ? 1
>>>>>> : -1;
>>>>>> }
>>>>>>
>>>>>> /**
>>>>>> * This method calculates a number indicating a good or bad match
>>>>>> between
>>>>>> * queryParams from request and annotated method parameters. A higher
>>>>>> number
>>>>>> * means a better match.
>>>>>> *
>>>>>> * @param annotations
>>>>>> * Map contains name of QueryParam method parameters as a key and
>>>>>> * a Boolean value indicating an existing default value for this
>>>>>> * parameter.
>>>>>> * @param queryParams
>>>>>> * A Set of query parameters provided within the request
>>>>>> * @return A positive or negative number, indicating a good match
>>>>>> between
>>>>>> * query and method
>>>>>> */
>>>>>> protected int getMatchingRate(Map<String, Boolean> annotations,
>>>>>> Set<String> queryParams) {
>>>>>> int rate = 0;
>>>>>> for (String anno : annotations.keySet()) {
>>>>>> if (queryParams.contains(anno)) {
>>>>>> // URL query matches one method parameter
>>>>>> rate += 2;
>>>>>> } else if (!annotations.get(anno).booleanValue()) {
>>>>>> // No default value exists for method parameter
>>>>>> rate -= 1;
>>>>>> }
>>>>>> }
>>>>>> return rate;
>>>>>> }
>>>>>>
>>>>>> /**
>>>>>> * @param opParamAnnos
>>>>>> * Array containing all annotations for all method parameters
>>>>>> * @return Key in Map is QueryParam name, and Value indicates if a
>>>>>> default
>>>>>> * value is present.
>>>>>> */
>>>>>> protected Map<String, Boolean> getAnnotations(Annotation[][]
>>>>>> opParamAnnos) {
>>>>>> Map<String, Boolean> parameterAnnos = new HashMap<String,
Boolean>();
>>>>>>
>>>>>> if (opParamAnnos.length == 0)
>>>>>> return parameterAnnos;
>>>>>>
>>>>>> for (Annotation[] pAnnos : opParamAnnos) {
>>>>>> QueryParam qParam = null;
>>>>>> DefaultValue dValue = null;
>>>>>> for (Annotation anno : pAnnos) {
>>>>>> if (anno instanceof QueryParam)
>>>>>> qParam = (QueryParam) anno;
>>>>>> if (anno instanceof DefaultValue)
>>>>>> dValue = (DefaultValue) anno;
>>>>>> }
>>>>>> parameterAnnos.put(qParam.value(), Boolean.valueOf((dValue !=
>>>>>> null)));
>>>>>> }
>>>>>>
>>>>>> return parameterAnnos;
>>>>>> }
>>>>>>
>>>>>> /**
>>>>>> * @param query
>>>>>> * URL Query
>>>>>> * @return A Set of all keys, contained within query.
>>>>>> */
>>>>>> protected Set<String> getParams(String query) {
>>>>>> Set<String> params = new HashSet<String>();
>>>>>> if (query == null || query.length() == 0)
>>>>>> return params;
>>>>>>
>>>>>> try {
>>>>>> for (String param : query.split("&")) {
>>>>>> String pair[] = param.split("=");
>>>>>> String key = URLDecoder.decode(pair[0], "UTF-8");
>>>>>> params.add(key);
>>>>>> }
>>>>>> } catch (UnsupportedEncodingException e) {
>>>>>> e.printStackTrace();
>>>>>> }
>>>>>> return params;
>>>>>> }
>>>>>> }
>>>>>>
>>>>>
>>>>> I think it is difficult to generalize given that another user may
>>>>> want a
>>>>> similar support for the selection based on matrix/header/form
>>>>> parameters, and the other complexity is that we can have repeating
>>>>> parameters, example, "a=1&a=2" query, etc.
>>>>>
>>>>> However it definitely makes sense to update the docs and show what
>>>>> does
>>>>> it mean to customize the selection algo, so what I will do is I will
>>>>> update the page and paste the code - lets see may be we can push
>>>>> some of
>>>>> the code to CXF eventually
>>>>>
>>>>> thanks, Sergey
>>>>>
>>>>>> Best regards.
>>>>>> Jan
>>>>>>
>>>>>> From: Sergey Beryozkin-5 [via CXF]
>>>>>> [mailto:[hidden
>>>>>> email]</user/SendEmail.jtp?type=node&node=5719454&i=0>]
>>>>>> Sent: Dienstag, 27. November 2012 11:31
>>>>>> To: Jan Bernhardt
>>>>>> Subject: Re: REST Method selection for different QueryParam's
>>>>>>
>>>>>> Hi Jan
>>>>>> On 27/11/12 10:12, janb wrote:
>>>>>>
>>>>>>> Hi @all,
>>>>>>>
>>>>>>> I'm wondering about the selection strategy in CXF for different
>>>>>>> Query
>>>>>>> Parameter. The documentation [1] does not cover this at all.
>>>>>>>
>>>>>>> A simple system-test provided the impression to me, that CXF
has no
>>>>>>> valid
>>>>>>> selection strategy in place for handling different query parameters.
>>>>>>> Is this
>>>>>>> assumption correct? Should I create a Jira ticket for a better
>>>>>>> support?
>>>>>>>
>>>>>>> Here is my sample code. No matter which parameter have been provided
>>>>>>> within
>>>>>>> my URL, only and always the first method was selected by CXF.
>>>>>>>
>>>>>>> @Path("/paramTest")
>>>>>>> public class MySimpleService {
>>>>>>>
>>>>>>> @GET
>>>>>>> public String getFoo(@QueryParam("foo") String foo){
>>>>>>> return "foo:" + foo;
>>>>>>> }
>>>>>>>
>>>>>>> @GET
>>>>>>> public String getFooBar(@QueryParam("foo") String foo,
>>>>>>> @QueryParam("bar") String bar){
>>>>>>> return "foo:" + foo + " bar:" + bar;
>>>>>>> }
>>>>>>>
>>>>>>> @GET
>>>>>>> public String getTest(@QueryParam("test") String test){
>>>>>>> return "test:" + test;
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> [1]
>>>>>>> http://cxf.apache.org/docs/jax-rs-basics.html#JAX-RSBasics-Overviewoftheselectionalgorithm.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>> Only URI path segment, HTTP method and in/out media types are taken
>>>>>> into
>>>>>> consideration when selecting the candidates. If you prefer to have
>>>>>> individual methods having the same HTTP Method/Uri Path/Media
>>>>>> Types but
>>>>>> with specific query parameters then the only way to get it managed
>>>>>> is to
>>>>>> use a CXF ResourceComparator where, in this case, you can affect
the
>>>>>> ordering of specific resource methods by checking the current
>>>>>> Message.QUERY_STRING available on the CXF Message
>>>>>>
>>>>>> A simpler alternative is to have a single method and work with
>>>>>> UriInfo, say
>>>>>>
>>>>>> @Context
>>>>>> private UriInfo ui;
>>>>>>
>>>>>> @GET
>>>>>> public String getFooOrBar() {
>>>>>> MultivaluedMap<String, String> params = ui.getQueryParameters();
>>>>>> String foo = params.getFirst("foo");
>>>>>> String bar = params.getFirst("foo");
>>>>>> // etc
>>>>>> }
>>>>>>
>>>>>> HTH, Sergey
>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> View this message in context:
>>>>>>> http://cxf.547215.n5.nabble.com/REST-Method-selection-for-different-QueryParam-s-tp5719187.html
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Sent from the cxf-user mailing list archive at Nabble.com.
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Sergey Beryozkin
>>>>>>
>>>>>> Talend Community Coders
>>>>>> http://coders.talend.com/
>>>>>>
>>>>>> Blog: http://sberyozkin.blogspot.com
>>>>>>
>>>>>> ________________________________
>>>>>> If you reply to this email, your message will be added to the
>>>>>> discussion below:
>>>>>> http://cxf.547215.n5.nabble.com/REST-Method-selection-for-different-QueryParam-s-tp5719187p5719190.html
>>>>>>
>>>>>>
>>>>>>
>>>>>> To unsubscribe from REST Method selection for different QueryParam's,
>>>>>> click
>>>>>> here<
>>>>>>
>>>>>> NAML<http://cxf.547215.n5.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> View this message in context:
>>>>>> http://cxf.547215.n5.nabble.com/REST-Method-selection-for-different-QueryParam-s-tp5719187p5719219.html
>>>>>>
>>>>>>
>>>>>>
>>>>>> Sent from the cxf-user mailing list archive at Nabble.com.
>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> Sergey Beryozkin
>>>>
>>>> Talend Community Coders
>>>> http://coders.talend.com/
>>>>
>>>> Blog: http://sberyozkin.blogspot.com
>>>>
>>>> ________________________________
>>>> If you reply to this email, your message will be added to the
>>>> discussion below:
>>>> http://cxf.547215.n5.nabble.com/REST-Method-selection-for-different-QueryParam-s-tp5719187p5719454.html
>>>>
>>>>
>>>> To unsubscribe from REST Method selection for different QueryParam's,
>>>> click
>>>> here<
>>>>
>>>> NAML<http://cxf.547215.n5.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> View this message in context:
>>>> http://cxf.547215.n5.nabble.com/REST-Method-selection-for-different-QueryParam-s-tp5719187p5719458.html
>>>>
>>>>
>>>> Sent from the cxf-user mailing list archive at Nabble.com.
>>>
>>>
>>
>>
>> --
>> Sergey Beryozkin
>>
>> Talend Community Coders
>> http://coders.talend.com/
>>
>> Blog: http://sberyozkin.blogspot.com
>>
>> ________________________________
>> If you reply to this email, your message will be added to the
>> discussion below:
>> http://cxf.547215.n5.nabble.com/REST-Method-selection-for-different-QueryParam-s-tp5719187p5719465.html
>>
>> To unsubscribe from REST Method selection for different QueryParam's,
>> click
>> here<http://cxf.547215.n5.nabble.com/template/NamlServlet.jtp?macro=unsubscribe_by_code&node=5719187&code=amJlcm5oYXJkdEB0YWxlbmQuY29tfDU3MTkxODd8LTEzMDQ4ODk1MjM=>.
>>
>> NAML<http://cxf.547215.n5.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>>
>>
>>
>>
>>
>> --
>> View this message in context:
>> http://cxf.547215.n5.nabble.com/REST-Method-selection-for-different-QueryParam-s-tp5719187p5719471.html
>>
>> Sent from the cxf-user mailing list archive at Nabble.com.
>
>


-- 
Sergey Beryozkin

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

Blog: http://sberyozkin.blogspot.com

Mime
View raw message