On 12/08/14 17:13, Sergey Beryozkin wrote:
Sorry, do not understand what you are trying to do.
Why do you use a single parameter (query, header, or may be form) to
send a JSON array ? This is typically sent as a message body, in which
case JAX-RS MessageBodyReader takes care of it.
Imagine this case:
?a=1-2-3&a=4-5-6
here we have 2 'a' query parameters, one with value "1-2-3" and another
- with "4-5-6"
and we have this signature:
Response get(@QueryParam("a") List<Integer> list);
In this case we convert each parameter to Integer (the converter would
remove '-'), the runtime takes case of creating a List.
If we expected the converter to convert a String to List<Integer> then
what would the runtime pass to the converter, "a=1-2-3&a=4-5-6" and
expect it to parse it manually ? Not sure it makes sense.
And given that ParamConverterProvider is expected to be reusable, what
would we do with
and a sequence like
/path;a=1-2-3;a=4-5-6
Response get(@MatrixParam("a") List<Integer> list);
the converter would have to parse both
"a=1-2-3&a=4-5-6" and "a=1-2-3;a=4-5-6"
IMHO it is not how it should work, but please do not hesitate to
investigate it further with Jersey
Cheers, Sergey
Can you investigate what Jersey does ? I'm pretty sure it was discussed,
specifically that the runtime should take care of dealing with the list
itself, but they might deal with it differently
Cheers, Sergey
On 12/08/14 16:45, Vassilis Virvilis wrote:
Aah,
So in order to make this work through CXF is to define an
EntitiesListWrapper class. Right? Then the ParamConverter will be called
with EntitiesListWrapper as argument and jackson will deserialize. Right?
Is there any other way to break the input of
final String entities_json = "[{\"name\":\"cca1\",
\"type\":\"GENE\"},{\"name\":\"cca2\", \"type\":\"GENE\"}]";
so the paramconverter will be called with the correct substring each
time?
This looks weird.
Vassilis
On 08/12/2014 06:22 PM, Sergey Beryozkin wrote:
Hi
AFAIK ParamConverterProvider is expected to be called once per every
entity in the list.
Thanks, Sergey
On 12/08/14 16:12, Vassilis Virvilis wrote:
Hi,
Some time before I have started a thread with jackson and form
parameters in cxf
http://mail-archives.apache.org/mod_mbox/cxf-users/201406.mbox/%[email protected]%3E
Sergey suggested that I should use ParamConverterProvider.
I tried it today and it worked. Great.
Now I am trying the next step which is to pass List<Entity> instead of
Entity in the input. The problem is that my ParamConverterProvider is
not called with the actual input class as specified in the interface
(List<Entity>) but with plain Entity as you can see from the logs. It
then fails because due to
*** Can not deserialize instance of
com.biovista.lib.datatype.Entity out of START_ARRAY token ****
INFO
com.biovista.ws.impl.jaxrs.JacksonJsonParamConverterProvider.getConverter(JacksonJsonParamConverterProvider.java:41):
**** called: arg0: class com.biovista.lib.datatype.Entity arg1: class
com.biovista.lib.datatype.Entity arg2:
[Ljava.lang.annotation.Annotation;@7f65ae66 providers:
org.apache.cxf.jaxrs.impl.tl.ThreadLocalProviders@63aea6a8
INFO
com.biovista.ws.impl.jaxrs.JacksonJsonParamConverterProvider.getConverter(JacksonJsonParamConverterProvider.java:44):
Annotation: @javax.ws.rs.FormParam(value=entities)
Here is my ParamConverterProvider
package com.biovista.ws.impl.jaxrs;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.Providers;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.codehaus.jackson.map.ObjectMapper;
@Provider
public class JacksonJsonParamConverterProvider implements
ParamConverterProvider {
private final Log log = LogFactory.getLog(getClass());
@Override
public <T> ParamConverter<T> getConverter(final Class<T> rawType,
final Type genericType, final Annotation[] annotations) {
log.info("**** called: arg0: " + rawType + " arg1: " +
genericType
+ " arg2: " + annotations + " providers: " +
providers);
for (final Annotation annotation : annotations) {
log.info("Annotation: " + annotation);
}
return new ParamConverter<T>() {
@Override
public T fromString(final String value) {
try {
log.info("Called for " + value);
return mapper.reader(rawType).readValue(value);
} catch(IOException e) {
throw new ProcessingException(e);
}
}
@Override
public String toString(final T value) {
try {
return mapper.writer().writeValueAsString(value);
} catch(Exception e) {
throw new ProcessingException(e);
}
}
};
}
}
How can I register different ParamConverterProvider for different input
types? Or is that List is handled specially? By jackson or CXF? In
jackson I just need to do
final List<Entity> entities = mapper.readValue(entities_json,
new TypeReference<List<Entity>>() {
});
but I don't know how to do this from inside CXF. I am using CXF 3.0
Thanks
--
Sergey Beryozkin
Talend Community Coders
http://coders.talend.com/
Blog: http://sberyozkin.blogspot.com