At poken, we use jaxb to generate java classes for xsd.
I have coded a @Provider
This code is
- incomplete: Many cases are missing. (Like get functions with
annotations).
- totally free to use: Do what you want with it.
- Not really tested but it works great for us.
- Works with jersey 1.1.2, doesn't work with jersey 1.1.1, not tested on
other versions.
- Based on annotation in Java domain objects
Check in you logs that you have something similar to
INFO: Provider classes found:
class ch.poken.api.rest.v081.resources.server.JAXBFixJSONArrayProvider
--
package ch.poken.api.rest.v081.resources.server;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.annotation.XmlElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sun.jersey.api.json.JSONConfiguration;
import com.sun.jersey.api.json.JSONJAXBContext;
@Provider
public class JAXBFixJSONArrayProvider implements
ContextResolver<JAXBContext> {
// Logs
static final Logger logger = LoggerFactory
.getLogger(JAXBContextResolver.class);
/**
* This map store all jaxb context once processed by the parser.
*/
private static Map<Class<? extends Object>, JAXBContext> jaxbContexts =
Collections
.synchronizedMap(new HashMap<Class<? extends Object>,
JAXBContext>());
/**
* Get the jaxb context, generate this context if it doesn't exists
yet.
*
* @param the
* class used to generate the JAXB context
* @return JAXB context
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws NoSuchMethodException
* @throws IllegalArgumentException
* @throws SecurityException
*/
private static JAXBContext getJAXBContext(Class<? extends Object>
class1)
throws Exception {
// Get from cache
JAXBContext context = jaxbContexts.get(class1);
if (context != null) {
return context;
}
// Parse all jaxb nodes
Map<Class<? extends Object>, Object> mapClassIterated = new
HashMap<Class<? extends Object>, Object>();
Map<String, Object> mapFieldsList = new HashMap<String, Object>();
parseJAXBContext(class1, mapClassIterated, mapFieldsList);
String[] fields = mapFieldsList.keySet().toArray(new String[0]);
// Create the JAXB Context
context = new JSONJAXBContext(JSONConfiguration.mapped()
.rootUnwrapping(true).arrays(fields).build(), class1);
// Add this context to cache.
jaxbContexts.put(class1, context);
return context;
}
/**
* Parse a jaxb context, add the element in mapFields.
*
* @param class1
* is the name of the class to be parser
* @param mapClassIterated
* is the map of iterated classes
* @param mapFieldsList
* is the map of fields that have been extracted
* @throws NoSuchMethodException
* @throws SecurityException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
private static void parseJAXBContext(Class<? extends Object> class1,
Map<Class<? extends Object>, Object> mapClassIterated,
Map<String, Object> mapFieldsList) throws SecurityException,
NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
// We have already processed this class
if (mapClassIterated.containsKey(class1)) {
return;
}
mapClassIterated.put(class1, Boolean.TRUE);
// Extract from parameters
for (Field f : class1.getDeclaredFields()) {
Annotation a = f.getAnnotation(XmlElement.class);
String name = null;
if (a != null) {
Method m = a.getClass().getMethod("name");
name = (String) m.invoke(a);
}
if (name == null || "##default".equals(name)) {
name = f.getName();
}
{
// Is it a list
if (f.getType() == List.class) {
mapFieldsList.put(name, Boolean.TRUE);
ParameterizedType aType = (ParameterizedType) f
.getGenericType();
Type[] fieldArgTypes = aType.getActualTypeArguments();
for (Type fieldArgType : fieldArgTypes) {
parseJAXBContext((Class<?>) fieldArgType,
mapClassIterated, mapFieldsList);
}
} else {
parseJAXBContext(f.getType(), mapClassIterated,
mapFieldsList);
}
}
}
// TODO: Extract from methods
// for (Method m : class1.getMethods()) {
// }
}
/**
* Get the JAXB context
*/
public JAXBContext getContext(Class<?> objectType) {
try {
return getJAXBContext(objectType);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
}
###**###**###**###**###**###**###**###**###
Gabriel Klein
CSA / Poken SA
Please Poken with me for more information.