I was not able to find a reference guide, but did manage to solve the configuration issue by some code spelunking and this mailing list thread from the archives.
For some reason, the suggestion from that mailing list thread didn't work (it was ignoring the custom JSONProvider from the web.xml
). I may have had other problems.
Ultimately, I moved away from the idea of web.xml
configuration since it was already used to provide a javax.ws.rs.Application
and (from looking @ CXF code), it appears that CXF ignore init-param
elements from web.xml
if it finds an Application.
Further, there doesn't seem be a way of expressing Map types in the web.xml
config. That's conjecture based on the thread and looking at the code, so I can't 100% confirm.
This is what my web.xml looks like (same before and after these changes):
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>my.javax-ws-rs.Application</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
It was in the my.javax-ws-rs.Application
class that I needed to make changes.
Simply added a new JSONProvider
to the list of singletons in there:
@Override
public Set< Object> getSingletons() {
final Set< Object> singletons = new HashSet<>();
// [SNIP -- existing singletons]
singletons.add( new my.provider.MyJSONProvider() );
return singletons;
}
The definition of my.provider.MyJSONProvider
is where the rest of the magic happens (yes, it's the "programmatic" configuration that I said I didn't have, but ultimately had to resort to):
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
@Provider
public class MyJSONProvider<T> extends JSONProvider<T> {
public AdministrationUtilisatuerJSONProvider() {
{
Map<String, String> newNamespaceMap = new ConcurrentHashMap<>();
XmlSchema resource1SchemaAnnotation = Resource1.class.getPackage().getAnnotation(javax.xml.bind.annotation.XmlSchema.class);
String resource1Namespace = resource1SchemaAnnotation.namespace();
newNamespaceMap.put( resource1Namespace, "resource1JsonPrefix" );
XmlSchema resource2SchemaAnnotation = Resource2.class.getPackage().getAnnotation(javax.xml.bind.annotation.XmlSchema.class);
String resource2Namespace = resource2SchemaAnnotation.namespace();
newNamespaceMap.put( resource2Namespace, "resource2JsonPrefix" );
setNamespaceMap(newNamespaceMap);
}
// Or set this to "true" to ignore all that namespace stuff
// setIgnoreNamespaces(true);
// Don't write namespace for default xsi-type elements.
setWriteXsiType(false);
// [SNIP] -- Other JSONProvider configuration.
// Check source from CXF, but few comments in code.
}
One final note about getting Jettison-based JSON working in CXF: you also need the cxf-rt-rs-extension-providers-X.Y.Z.jar
on your classpath. This isn't documented in the CXF WHICH_JARS
file, but is required.