I wanted to avoid having to do matrixParams.getList().get(0) when all
I wanted was matrixParams.get(0)... :)
That's the only reason, really...

I thought if I have to convert partially in my class, I can just do
all of the conversion in my class, and not use cxf's facility at all.
And I thought it would work. I'm pretty sure I saw REST URLs in the
past that used ;range=10,90 for example - so I was sure cxf would
support it somehow... :)

Cheers,

Christian

On Thu, Oct 6, 2016 at 2:58 PM, Sergey Beryozkin <[email protected]> wrote:
> Hi, why would you not have
>
> class MatrixParams {
>     List<String> list;
> }
>
> @MatrixParam("a") MatrixParams
>
> Sergey
>
>
> On 06/10/16 14:23, Christian Balzer wrote:
>>
>> Hello,
>>
>> Well, you just pointed out that the converters are only supposed to
>> work on an individual element of a collection, and cxf' code is
>> looking at the param type to see if it is dealing with a collection
>> target type (which it will create at runtime, as you pointed out), to
>> which it needs to add these elements. So it basically gets confused
>> because I've defined my own collection type. It assumes it needs to
>> create a collection to add elements to, but the elements I create are
>> my own collection. That's how I end up with
>> Collection<Collection<Enum>>. Short of cxf checking the actual type of
>> the target parameter instead of whether it implements the Collection
>> interface, I don't think there is any way around it?
>>
>> In other words, what I wanted to do won't work in cxf. :/
>>
>> Regards,
>>
>> Christian
>>
>> On Thu, Oct 6, 2016 at 1:41 PM, Sergey Beryozkin <[email protected]>
>> wrote:
>>>
>>> Hi
>>>
>>> Looks like a linking issue,
>>>
>>> Sergey
>>>
>>> On 06/10/16 13:24, Christian Balzer wrote:
>>>>
>>>>
>>>> Hi all,
>>>>
>>>> So, I played around a bit more, and I now have a semi-working
>>>> solution. Semi-working, because I do get a List of enums back, which
>>>> is what I was actually after.
>>>> Not fully working, because it now blows up in the bowels of cxf (3.1.6).
>>>>
>>>> Here is the mehtod signature - as a reminder, I'm trying to call
>>>> /foo;d=2016-10-06;f=a,b,c - and the LocalDate conversion works just
>>>> fine...
>>>> @GET
>>>> @Path("foo")
>>>> public Response foo(@MatrixParam("d") LocalDate date,
>>>> @MatrixParam("f") Foo foos) {
>>>> //...
>>>>
>>>> Here is my ParamConverterProvider - it is registered and gets called
>>>> for matrix parameter f - yay!
>>>> public class StringListHandler implements ParamConverterProvider{
>>>>     @Override
>>>>     public <T> ParamConverter<T> getConverter(final Class<T> rawType,
>>>> Type genericType, Annotation[] annotations) {
>>>>         if(rawType == CommaSeparatedList.class) {
>>>>             return (ParamConverter<T>) new
>>>> ParamConverter<CommaSeparatedList>() {
>>>>                 @Override
>>>>                 public CommaSeparatedList fromString(String value) {
>>>>                     CommaSeparatedList list = new
>>>> CommaSeparatedList(value);
>>>>                     return list;
>>>>                 }
>>>>                 @Override
>>>>                 public String toString(CommaSeparatedList value) {
>>>>                     return value.toString();
>>>>                 }
>>>>             };
>>>>         }
>>>>         return null;
>>>>     }
>>>> }
>>>>
>>>> Here is my target type. It extends ArrayList - and I think that is now
>>>> the problem...
>>>> public class CommaSeparatedList extends ArrayList<Foo> {
>>>>     public CommaSeparatedList(String value) {
>>>>         List<String> list = Arrays.asList(value.split("\\s*,\\s*"));
>>>>         List<Foo> foos = new ArrayList<>(list.size());
>>>>         for (String element : list) {
>>>>             foos.add(Foo.valueOf(element.toUpperCase()));
>>>>         }
>>>>         addAll(foos);
>>>>     }
>>>> }
>>>>
>>>> Here is the enum I'm using:
>>>> public enum Foo {
>>>>     A, B, C
>>>> }
>>>>
>>>> And here are the Exception and StackTrace cxf now throws at me after I
>>>> return my CommaSeparatedList , i.e. ArrayList<Foo> (extending
>>>> Collection):
>>>> java.lang.IllegalArgumentException: argument type mismatch
>>>> argument type mismatch while invoking public javax.ws.rs.core.Response
>>>>
>>>>
>>>> com.example.rs.MyEndpoint.foo(org.joda.time.LocalDate,com.example.common.CommaSeparatedList)
>>>> with params [2016-10-06, [[A, B, C]]].
>>>> 0 = {StackTraceElement@3424}
>>>>
>>>>
>>>> "org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:166)"
>>>> 1 = {StackTraceElement@3425}
>>>>
>>>>
>>>> "org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:140)"
>>>> 2 = {StackTraceElement@3426}
>>>> "org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:189)"
>>>> 3 = {StackTraceElement@3427}
>>>> "org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:99)"
>>>> 4 = {StackTraceElement@3428}
>>>>
>>>>
>>>> "org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59)"
>>>> 5 = {StackTraceElement@3429}
>>>>
>>>>
>>>> "org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:96)"
>>>> 6 = {StackTraceElement@3430}
>>>>
>>>>
>>>> "org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)"
>>>> 7 = {StackTraceElement@3431}
>>>>
>>>>
>>>> "org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)"
>>>> 8 = {StackTraceElement@3432}
>>>>
>>>>
>>>> "org.apache.cxf.transport.local.LocalConduit.dispatchDirect(LocalConduit.java:191)"
>>>> 9 = {StackTraceElement@3433}
>>>>
>>>> "org.apache.cxf.transport.local.LocalConduit.close(LocalConduit.java:156)"
>>>> 10 = {StackTraceElement@3434}
>>>>
>>>>
>>>> "org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)"
>>>> 11 = {StackTraceElement@3435}
>>>>
>>>>
>>>> "org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)"
>>>> 12 = {StackTraceElement@3436}
>>>>
>>>>
>>>> "org.apache.cxf.jaxrs.client.AbstractClient.doRunInterceptorChain(AbstractClient.java:652)"
>>>> 13 = {StackTraceElement@3437}
>>>>
>>>>
>>>> "org.apache.cxf.jaxrs.client.WebClient.doChainedInvocation(WebClient.java:1097)"
>>>> 14 = {StackTraceElement@3438}
>>>> "org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:894)"
>>>> 15 = {StackTraceElement@3439}
>>>> "org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:865)"
>>>> 16 = {StackTraceElement@3440}
>>>> "org.apache.cxf.jaxrs.client.WebClient.invoke(WebClient.java:331)"
>>>> 17 = {StackTraceElement@3441}
>>>> "org.apache.cxf.jaxrs.client.WebClient.get(WebClient.java:357)"
>>>>
>>>> I think the problem is in
>>>> AbstractInvoker.performInvocation(performInvocation.java:172) - mainly
>>>> because my debugger output at that position looks like this:
>>>> paramArray: Object[]  = {Object[2]@3320}
>>>>   0 = {LocalDate@3270} "2016-10-06"
>>>>   1 = {ArrayList@3295}  size = 1
>>>>     0 = {CommaSeparatedList@3294}  size = 3
>>>>
>>>> I think what I'd actually need - to conform with the method signature
>>>> of my foo() method in my endpoint from above - is something that looks
>>>> a bit more like this (i.e. without the extra ArrayList layer):
>>>> paramArray: Object[]  = {Object[2]}
>>>> 0 = {LocalDate}
>>>> 1 =  {CommaSeparatedLis}  size = 3
>>>>
>>>> Any idea how I can get that sorted, please?
>>>>
>>>> Again, the goal is to convert ;f=a,b,c into List<Foo>[3] with elements
>>>> A, B, and C...
>>>>
>>>> Kind regards,
>>>> Christian
>>>>
>>>> On Thu, Oct 6, 2016 at 12:20 AM, Christian Balzer
>>>> <[email protected]> wrote:
>>>>>
>>>>>
>>>>> Hi all,
>>>>>
>>>>> We are using cxf with Spring at work, and I have a newbie question...
>>>>>
>>>>> This is my method signature:
>>>>>
>>>>> @GET
>>>>> @Path("foo")
>>>>> public Response foo(@MatrixParam("l") List<String> myList) {
>>>>>
>>>>> From that, I want to get a list back with the initial input String (to
>>>>> my matrix parameter l) being split into list elements at any comma,
>>>>> i.e. I want e.g. ";l=a,b,c" to turn into a list of three elements: a,
>>>>> b and c.
>>>>>
>>>>> My converter below is registered (a breakpoint in it is triggered for
>>>>> myList), but instead of passing rawType as List, I get rawType as
>>>>> String (so it doesn’t do anything).
>>>>>
>>>>> public class StringListHandler implements ParamConverterProvider {
>>>>>     @Override
>>>>>     public <T> ParamConverter<T> getConverter(final Class<T> rawType,
>>>>> Type genericType, Annotation[] annotations) {
>>>>>         if(rawType == List.class) {
>>>>>             return new ParamConverter<T>() {
>>>>>                 @Override
>>>>>                 public T fromString(String value) {
>>>>>                     return
>>>>> rawType.cast(Arrays.asList(value.split("\\s*,\\s*")));
>>>>>                 }
>>>>>
>>>>>                 @Override
>>>>>                 public String toString(T value) {
>>>>>                     return value.toString();
>>>>>                 }
>>>>>             };
>>>>>         }
>>>>>         return null;
>>>>>     }
>>>>> }
>>>>>
>>>>>
>>>>> Interestingly enough, I do get a list back. But instead of three
>>>>> elements a, b and c, it only seems to have one: a,b,c
>>>>>
>>>>> What piece of JAX-RS/cxf voodoo am I missing to make this work? ;-)
>>>>>
>>>>> Is it maybe because cxf comes with a default implementation for a
>>>>> List<String> converter so it can turn a URL like foo?l=a&l=b&l=c into
>>>>> a List<String> ? Does that also get called for foo;l=a;l=b;l=c ? (I
>>>>> thought that c would overwrite a in that situation?)
>>>>>
>>>>> Do I have to use a custom class with a List<String> property, like
>>>>> class MyContainer {
>>>>>   public List<List> l;
>>>>> }
>>>>>
>>>>> and change the method signature from above to
>>>>> public Response foo(@MatrixParam("l") MyContainer myContainer) {
>>>>>
>>>>> then check for MyContainer.class in ParamConverterProvider and change
>>>>> the fromString() method to
>>>>> public T fromString(String value) {
>>>>>   MyContainer mC = new MyContainer();
>>>>>   mc.l = Arrays.asList(value.split("\\s*,\\s*"));
>>>>>   return rawType.cast(mc);
>>>>> }
>>>>>
>>>>> Or should I create a custom argument annotation, say @CommaSeparated,
>>>>> and have ParamConverterProvider check for that (and
>>>>> rawType==String.class)?
>>>>> But if I do that, won't I get a List<List<String>> back?
>>>>>
>>>>> Any help much appreciated!
>>>>>
>>>>> Kind regards,
>>>>>
>>>>> Christian
>>>
>>>
>>>
>>>
>>> --
>>> Sergey Beryozkin
>>>
>>> Talend Community Coders
>>> http://coders.talend.com/
>
>

Reply via email to