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
<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
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/