I'm trying to consume some SOAP web services within a spring boot application. I've imported the ws's stubs and I've followed WebServiceTemplate, as explained here. Unfortunately, when making requests I get an exception:
2017-01-13 12:13:47.146 ERROR 1300 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.oxm.MarshallingFailureException: JAXB marshalling exception; nested exception is javax.xml.bind.MarshalException - with linked exception: [com.sun.istack.SAXException2: no se ha podido canalizar el tipo "com.dashboard.dto.ComprobarSolicitud" como un elemento, porque le falta una anotación @XmlRootElement]] with root cause
The "ComprobarSolicitud" class is the following one:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "comprobarSolicitud", propOrder = {
"username",
"passwd",
"nif",
"fechaDesde",
"fechaHasta",
"cantidad"
})
public class ComprobarSolicitud {
protected String username;
protected String passwd;
protected String nif;
protected String fechaDesde;
protected String fechaHasta;
protected int cantidad;
// ...getters and setters
WebServiceGatewaySupport class:
public class PerClient extends WebServiceGatewaySupport {
private static final Logger log = LoggerFactory.getLogger(PadronClient.class);
public ComprobarSolicitudResponse comprobarSolicitudes(String pNif, LocalDate pFechaInicio, LocalDate pFechaFin){
ComprobarSolicitud request = new ComprobarSolicitud();
// .. set operations to request
ComprobarSolicitudResponse response = (ComprobarSolicitudResponse) getWebServiceTemplate()
.marshalSendAndReceive(
"https://ws.dir.com:8444/PerExterno/perExterno",
request,
new SoapActionCallback("http://service.ws.per.company.com/ExternalWS/comprobarSolicitudResponse"));
return response;
}
}
Configuration class:
@Configuration
public class PerConfiguration {
@Bean
public Jaxb2Marshaller marshaller(){
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.dashboard.dto.per");
return marshaller;
}
@Bean
public PerClient padronClient(Jaxb2Marshaller marshaller){
PerClient client = new PerClient();
client.setDefaultUri("https://ws.dir.com:8444/PerExterno");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
}
Should I create a custom marshaller? But, how? I've found this, where it's said that in case @XmlRootElement annotation is missing, I should wrap it in an instance of JAXBElement.
Thank you
SOLUTION!
The exception was self-explanatory, and the solution was straightforward, as just PerClient class was necessary to be modified as follows:
public class PerClient extends WebServiceGatewaySupport {
private static final Logger log = LoggerFactory.getLogger(PadronClient.class);
public ComprobarSolicitudResponse comprobarSolicitudes(String pNif, LocalDate pFechaInicio, LocalDate pFechaFin){
ComprobarSolicitud request = new ComprobarSolicitud();
// .. set operations to request
ObjectFactory of = new ObjectFactory();
JAXBElement<ComprobarSolicitud> reqjaxb = of.createComprobarSolicitud(request);
@SuppressWarnings("unchecked")
JAXBElement<ComprobarSolicitudResponse> response = (ComprobarSolicitudResponse) getWebServiceTemplate()
.marshalSendAndReceive(
"https://ws.dir.com:8444/PerExterno/perExterno",
reqjaxb ,
new SoapActionCallback("http://service.ws.per.company.com/ExternalWS/comprobarSolicitudResponse"));
return response.getValue();
}
}