I'm trying to consume a WebService Soap from dynamics Nav 2015 with Java SpringBoot ! this WebService asks for Credentials (username,password,domain). when i called my service SoapClientService to call the method TestConnection() in dynamics nav server:
@Service
public class SoapClientService extends WebServiceGatewaySupport {
@Value("${soap.service.url}")
private String serviceUrl;
@Value("${nav.user}")
private String navUser;
@Value("${nav.password}")
private String navPassword;
@Value("${nav.domain}")
private String navDomain;
public String testConnection() {
// Create request object
TestConnection request = new TestConnection();
// Add SOAP headers for authentication
getWebServiceTemplate().setInterceptors(new ClientInterceptor[] {
new ClientInterceptor() {
@Override
public boolean handleRequest(MessageContext messageContext) {
TransportContext context = TransportContextHolder.getTransportContext();
WebServiceMessage message = messageContext.getRequest();
SoapHeader header = ((SoapMessage) message).getSoapHeader();
QName navUserHeader = new QName("urn:microsoft-dynamics-schemas/codeunit/ControlePreparation", "NavUser");
QName navPassHeader = new QName("urn:microsoft-dynamics-schemas/codeunit/ControlePreparation", "NavPass");
QName navDomainHeader = new QName("urn:microsoft-dynamics-schemas/codeunit/ControlePreparation", "NavDomain");
header.addHeaderElement(navUserHeader).setText(navUser);
header.addHeaderElement(navPassHeader).setText(navPassword);
header.addHeaderElement(navDomainHeader).setText(navDomain);
return true;
}
@Override
public boolean handleResponse(MessageContext messageContext) {
// Handle response if needed
return true;
}
@Override
public boolean handleFault(MessageContext messageContext) {
// Handle fault if needed
return true;
}
@Override
public void afterCompletion(MessageContext messageContext, Exception ex) {
// Clean up resources if needed
}
}
});
// Make SOAP call and receive response
TestConnectionResult response = (TestConnectionResult) getWebServiceTemplate().marshalSendAndReceive(serviceUrl, request,
new SoapActionCallback(
"urn:microsoft-dynamics-schemas/codeunit/ControlePreparation:TestConnection"
));
// Process response
if (response != null) {
return response.getReturnValue();
} else {
return null; // Or handle null response as needed
}
}
}
with my restController:
@RestController
@RequestMapping("/api")
public class SoapController {
@Autowired
private SoapClientService soapClientService;
@GetMapping("/test-connection")
public ResponseEntity<String> testConnection() {
try {
String response = soapClientService.testConnection();
if (response != null) {
return ResponseEntity.ok(response);
} else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Failed to retrieve test connection response.");
}
} catch (HttpClientErrorException e) {
return ResponseEntity.status(e.getStatusCode()).body("HTTP error occurred: " + e.getMessage());
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("An error occurred while processing the request: " + e.getMessage());
}
}
}
then when I send the request
http://localhost:9090/api/test-connection I got: An error occurred while processing the request:
Unknown JAXB exception
The Problem that i couldn't distanguish if the javax exception is caused by xml/marshalSendAndReceive method or is caused by the inability to authenticate to the URL itself...
I generated my Java classes from the ControlePreparation.wsdl file which i placed it in ressources/wsdl.
injecting the dependency:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version> <!-- Version peut ĂȘtre diffĂ©rente -->
</dependency>
and the plugin:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.15.3</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<generatePackage>com.ticop.demo.soapApi</generatePackage>
<generateDirectory>${project.basedir}/src/main/java</generateDirectory>
<schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory>
<schemaIncludes>
<include>*.wsdl</include>
</schemaIncludes>
<args>
<arg>-wsdl</arg>
</args>
</configuration>
</plugin>
the method TestConnection() of dynamics Nav server i want to call was illustrated on two JAVA classes:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
@XmlRootElement(name = "TestConnection")
public class TestConnection {
}
and
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"returnValue"
})
@XmlRootElement(name = "TestConnection_Result")
public class TestConnectionResult {
@XmlElement(name = "return_value", required = true)
protected String returnValue;
/**
* Gets the value of the returnValue property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getReturnValue() {
return returnValue;
}
/**
* Sets the value of the returnValue property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setReturnValue(String value) {
this.returnValue = value;
}
}
then i created my WebServiceConfig.java Class :
@Configuration
public class WebServiceConfig {
@Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
// this package must match the package in the <generatePackage> specified in
// pom.xml
marshaller.setContextPath("com.ticop.demo.soapApi");
return marshaller;
}
@Bean
public SoapClientService soapClientService(Jaxb2Marshaller marshaller) {
SoapClientService client = new SoapClientService();
client.setDefaultUri("http://172.16.8.191:7047/DynamicsNAV80/WS/FAD2014/Codeunit/ControlePreparation");
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
return client;
}
}