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/
