Reputation: 4214
I get this exception when I try to call a .NET web service:
javax.xml.bind.JAXBException: class com.pixelware.mdv.tramites.TramiteXML nor any of its super class is known to this context.
The client is a Java library created with the CFX JAX-WS frontend (Classes precreated with WSDL)
The method I'm trying to call accepts (nested in another object) an Object (anyType in the WSDL)
Looks like the JAXB engine inside CXF is unable to marshall (serialize to XML) my class. That's because JAXB is unable to serialize a class if it is not registered in it's context and the class being passed it's part of the main program, not the client library.
The CXF documentation shows a lot of configuration options, and it looks like it can be done adding the property additionalContextClasses to the service properties. I can't add this property by configuration because my client is a separated library with the CFX generated classes.
I tried to add the property programmatically with this code:
Map<String, Object> ctx = (BindingProvider)ws.getWSSoap()).getRequestContext();
ctx.put("jaxb.additionalContextClasses", new Class[] {TramiteXML.class});
But it doesn't work. Looks like maybe this configuration has to be done before creating the client.
I've also found this post, whit the same (or very similar) problem, and the proposed solutions are far from easy.
Shouldn't it be much more simple? Maybe I'm missing something. Any suggestions?
Upvotes: 3
Views: 3355
Reputation: 4214
Well, I found it.
I got it to work using the "raw" DIspatcher API that CXF provides. I created a method like this:
public ReturnType registrar(RequestType request)
{
// That's the call that didn't worked. Registrar is the name of the method
// return serviceCLient.registrar(user, password, request);
try {
JAXBContext context = JAXBContext.newInstance(RequestType.class, ReturnType.class,
request.geGenericContent().getClass());
Dispatch<Object> registrarDispatch = service.createDispatch(
RegistroElectronico.RegistroElectronicoSoap, context, Mode.PAYLOAD);
registrarDispatch.getRequestContext().put(Dispatch.SOAPACTION_USE_PROPERTY, Boolean.TRUE );
registrarDispatch.getRequestContext().put(Dispatch.SOAPACTION_URI_PROPERTY, "http://pixelware.com/RegistroTelematico/Registrar" );
Registrar registrar = new Registrar();
registrar.setLogin(this.user);
registrar.setPassword(this.password);
registrar.setSolicitud(request);
RegistrarResponse response = (RegistrarResponse) registrarDispatch.invoke(registrar);
return response.getRegistrarResult();
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
Finally, the Dispatcher API was easier to use than I thought (Fortunately, there is a class for every web service method call).
The trick was to add my dynamic object type to the JAXBContext.
Anyway, I wonder why something like this couldn't be already done automatically by the CXF framework
Upvotes: 1