Hi Diego
Hope you've had enough time to recover before a new working day :-)
Here are the reasons I won't agree with it before either JAX-RS 2.1 or
future TCK will force CXF to do it:
1. Minor:
IMHO it is wrong to expect a custom param converter to guarantee it
parses all of the query component string correctly.
And what about @MatrixParam List<A> where a given matrix parameter can
be expected to be spread across multiple path segments, should the
runtime pass all the relative request URI for the custom converter to
parse it all, I don't think it makes sense. Can you try '/a;m=1/b;m=2'
with Jersey where 'm' has two values, 1 and 2 ?
2. Major:
The service code which types List<A> *must* see all the multiple values
from a standard HTTP multi-value query. It is completely wrong for the
runtime to depend on the user provider to guarantee it. If the runtime
can not guarantee it it just breaks JAX-RS in a little way.
And from what I've understood, having List<A> will simply not work for a
standard multi-value query in Jersey even with its current undocumented
and undiscussed (on the specs list) algorithm where it simply drops all
but a first value which it passes to ParamConverter<List<A>>.
The reason it fails is because when you have
?a=1&a=2
@GET
public Response get(@QueryParam("a") List<A> list) {}
where 'A' is a custom class which can be initialized only with the help
of ParamConverter<A>
then as we already know Jersey drops 'a=2', but without
ParamConverter<A> the runtime will be unable to convert 'a' values to A.
Even if you have '@QueryParam("a") List<String> list' where '1' & '2'
values require some decoration, it won't work with Jersey.
The last thing JAX-RS needs is a 'feature' like this one, in addition to
some of the selection algorithm issues.
So, in Jersey, when a service expects List<SomeType> and a user
registers ParamConverter<List<SomeType>>
- it works if a query is typed '?a=1,2' where '1,2' is a single query
property value but fails if it is a typical multi-value property
'?a=1&a=2' or even '?a=1,2&a=3' (i.e the service code loses the 2nd/etc
values - not acceptable)
in CXF, when a service expects List<SomeType> and a user registers
ParamConverter<SomeType>
- it works if a query is typed as a typical multi-value property
'?a=1&a=2' but does not for 'a=1,2' *unless* a property (which you
mentioned earlier) is set up requiring the runtime to treat 'a=1,2' as a
multi-value property.
Even if you look at say
https://jax-rs-spec.java.net/nonav/2.0-rev-a/apidocs/javax/ws/rs/QueryParam.html,
note
a point "5. Be List<T>, Set<T>, SortedSet<T> where *T* satisfies 2, 3,
4' where '4' is about having a ParamConverterProvider for *T*, not
List<T>/Set<T>
I recommend you to open a Jersey bug. Unless it works correctly for
'a=1&a=2' if you only have ParamConverter<A> with the service expecting
List<A> ?
Thanks, Sergey
On 23/10/16 23:44, Diego Ruotolo wrote:
I have to say that I don't understand your objection (in my defense: here
is almost 1:00 AM... :-) ), could you please clarify?
Probably the best solution will be to have a kinda
MultipleParamConverter<T> interface in JAX-RS 2.1 specs defining two
methods:
T fromStrings(String[] values);
String[] toStrings(T value);
The fromStrings() method will build the object used as argument in the
requested resource method.
But I'll let people more expert than me discuss on this.
Thanks,
Diego
2016-10-24 0:30 GMT+02:00 Sergey Beryozkin <sberyoz...@gmail.com>:
I can't agree to this. So a user registering a custom List provider breaks
the runtime ensuring the service code sees all the multiple values.
I can try and work with spec leads on clarifying it for JAX-RS 2.1.
Thanks, Sergey
On 23/10/16 23:27, Diego Ruotolo wrote:
Hi,
- when using multiple-value parameters passed in the URI in an HTTP
compliant-way (PARAM=V1&PARAM=V2&PARAM=V3), the ParamConverter takes only
the first value, hence if the ParamConverter builds a list, it will be a
list of only one value
Are you saying this loses V2 & V3 ?
Yes, in this case it loses V2 & V3. AFAIK the only way in Jersey to get a
correct parsing of a multiple-valued query parameter is not to write a
custom ParamConverter.
Cheers,
Diego
Thanks, Sergey
- when not using a custom ParamConverter, the multiple-value parameter
parsing (the example above) works correctly
Therefore what I am trying to achieve (CSV query parameter) can be done
on
Jersey by developing a custom ParamConverter, without explicitly write
an
Jersey extension, because it is a single value that generates a List
that
will be passed as a whole as argument of the requested resource method.
Hope that this clarify,
cheers,
Diego
2016-10-17 17:37 GMT+02:00 Sergey Beryozkin <sberyoz...@gmail.com>:
Hi
In the JAX-RS users thread which I referred to below I did ask about
and
I
don't think I got a +1 from one the spec leads on having
ParamConverterProvider supporting List, please check the archives.
And as I said IMHO the converters should not deal with interpreting for
ex
the whole query component value.
But can you investigate please how Jersey handles it ?
In Pre-match you can figure out if a given CSV value is a multi-value
or
not based on the current request URI (the relative parts), I agree it
will
be less safe compared to the use of annotations
Cheers, Sergey
On 17/10/16 15:56, Diego Ruotolo wrote:
Hi Sergey,
I think you are definitively right when you say you don't want to
introduce
a CXF specific extension at a standard JAX-RS interface level. But
taking
a
look at the JAX-RS specs it is not specified that ParamConverter
should
handle just single values in a collection and not the whole
collection:
I
think that both interpretations are valid, but maybe I am missinig
something.
Regarding the use of a @PreMatch filter, I don't think it is
possible: I
can't read annotations on a method parameter in a @PreMatch filter
since
the server resource is not bound yet, and I can't change parameter
values
in a post-match filter since it is impossible to change the URI (by
specs).
Furthermore, in a post-match filter the server resource is bound but
not
yet "filled" with values.
Thanks,
Diego
diego.ruot...@gmail.com
2016-10-17 16:28 GMT+02:00 Sergey Beryozkin <sberyoz...@gmail.com>:
Hi Diego
But that would introduce a CXF specific extension at a standard
JAX-RS
interface level. In general I'm quite open to adding new extensions
but
I'd rather not to in this case...Besides, IMHO, it really should be
the
job for the JAX-RS runtime, to parse the multivalued query/matrix
properties.
What you might want to experiment with is to add a prematch request
filter
which will reset a query string if needed to have List<String>
working
for
either a=1&a=2 or a=1,2, etc
Thanks, Sergey
On 17/10/16 12:46, Diego Ruotolo wrote:
Hi Sergey,
thanks for your answer.
I think a good solution could be to pass the ParamConverter a string
containing all the values of a multi-valued query parameter, and let
the
user build the collection object.
So, if I have a query string like:
MY_PARAM=VALUE_1&FOO=BAR&MY_PARAM=VALUE_2, the ParamConvert should
receive
the string MY_PARAM=VALUE_1&MY_PARAM=VALUE_2, and the user should
build
the
collection in in the fromString() method. In this way the user can
deal
with both the whole collection and its single values.
I also suggest this behaviour should be activated through a property
in
order not to break backward compatibility.
What do you think?
Thanks,
Diego
2016-10-17 11:47 GMT+02:00 Sergey Beryozkin <sberyoz...@gmail.com>:
Hi
Thanks for this query, let me redirect to the CXF users list.
FYI, CXF JAX-RS runtime prepares a List itself and only expects
ParamConverters if any to convert individual values.
I believe RI (Jersey) will also act the same way - but I may be
wrong
now.
You can check a "ParamConverter and Collections" thread on the
jaxrs
users
list. My understanding there was no any agreement reached.
Cheers, Sergey
On 16/10/16 23:48, Diego Ruotolo wrote:
Hi everybody,
this is my first post to this mailing list.
I am using Apache CXF and I have the following problem: I need to
read a
multiple-value query parameter that is written in a
comma-separated-values (CSV) format, hence non standard HTTP way.
I know that this will be fixed in versions 3.1.8 and 3.2.0 with
the
contextual property "parse.query.value.as.collection", as written
here:
https://issues.apache.org/jira/browse/CXF-6941
but the above solution works for ALL query parameters, I want to
be
selective, for instance I just want query parameters annotated
with
@MyAnnotation to be parsed as CSV collection, other query
parameters
may
accept commas as a value.
Therefore I've written a ParamConverter provided by a
ParamConverterProvider: the latter reads the annotation and
returns
the
appriopriate ParamConverter that converts a String into a List.
But
this
is not working since the returned List is used as first element of
the
linked method parameter, so in the end I have a List of List.
Example:
Query parameter: MY_PARAM=VALUE_1,VALUE_2,VALUE_3
Method parameter: List<?> myParam; // Here I put "?" instead of
"String"
as generic type in order to explain this example
ParamConverter fromString() method: return
Arrays.asList(value.split(",")); //returns a List<String>
Expected result: myParam is a List<String>, a list of 3 elements
(VALUE_1, VALUE_2, VALUE_3)
Actual result: myParam is a List<List<String>>, a list with one
element,
this single element is a list of 3 elements (VALUE_1, VALUE_2,
VALUE_3)
It seems that when used in conjuction with a List (a Collection?)
method
parameter, a ParamConverter works per-element, not for the whole
list.
Is this the correct behaviour? Do you know some work-around that I
could
use without writing an Apache CXF Interceptor (I don't want to be
bound
to an implementation of JAX-RS) ?
I've noticed that Jersey has a similar issue too:
https://java.net/jira/browse/JERSEY-2763
Thanks in advice,
best regards
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/