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 <christian.at....@gmail.com> 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