Reputation: 11
I have been using for a few years the webservices exposed by the italian ERP Mago4 by Microarea, from my java programs.
I am trying to extend the use, but a WSDL seems to have problems.
In detail, calling:
wsimport http://localhost:10000/Framework.TbGes.TbGes?wsdl -XdisableAuthenticator -generateJWS -XadditionalHeaders -keep -Xnocompile -extension -d generated
returns a long list of errors, but basically are 2 kinds. Here an extract:
[WARNING] Ignoring operation "RunBatchInUnattendedMode": more than one part bound to body
line 1 of http://virtual-1:10000/Framework.TbGes.TbGes?wsdl
[WARNING] Ignoring operation "RunReportInUnattendedMode": more than one part bound to body
line 1 of http://virtual-1:10000/Framework.TbGes.TbGes?wsdl
[WARNING] Non unique body parts! In a port, as per BP 1.1 R2710 operations must have unique operation signature on the wire for successful dispatch. In port TbGesSoap, Operations "GetApplicationDate" and "ClearCache" have the same request body block . Method dispatching may fail, runtime will try to dispatch using SOAPAction
line 1 of http://virtual-1:10000/Framework.TbGes.TbGes?wsdl
[WARNING] Non unique body parts! In a port, as per BP 1.1 R2710 operations must have unique operation signature on the wire for successful dispatch. In port TbGesSoap, Operations "GetApplicationYear" and "ClearCache" have the same request body block . Method dispatching may fail, runtime will try to dispatch using SOAPAction
line 1 of http://virtual-1:10000/Framework.TbGes.TbGes?wsdl
[WARNING] Ignoring operation "RunReport": more than one part bound to body
line 1 of http://virtual-1:10000/Framework.TbGes.TbGes?wsdl
The methods mentioned in each warning do not get generated, and that's a serious problem because I need to invoke them.
Here below are, for example, the portions of WSDL regarding RunReport:
<xsd:import schemaLocation="http://virtual-1:10000/Framework.TbGes.TbGes?xsd=xsd53" namespace="urn:Microarea.Web.Services.RunReport"/>
<wsdl:message name="RunReportIn">
<wsdl:part xmlns:q170="urn:Microarea.Web.Services.RunReport" name="reportNamespace" element="q170:reportNamespace"/>
<wsdl:part xmlns:q171="urn:Microarea.Web.Services.RunReport" name="arguments" element="q171:arguments"/>
</wsdl:message>
<wsdl:message name="RunReportIn_Headers">
<wsdl:part name="HeaderInfo" element="tns:HeaderInfo"/>
</wsdl:message>
<wsdl:message name="RunReportOut">
<wsdl:part xmlns:q172="urn:Microarea.Web.Services.RunReport" name="return" element="q172:return"/>
</wsdl:message>
<wsdl:operation name="RunReport">
<soap:operation soapAction="#RunReport" style="document"/>
<wsdl:input name="RunReportIn">
<soap:header message="tns:RunReportIn_Headers" part="HeaderInfo" use="literal"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="RunReportOut">
<soap:header message="tns:RunReportOut_Headers" part="HeaderInfo" use="literal"/>
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="TBSoapFaultFault">
<soap:fault name="TBSoapFaultFault" use="literal"/>
</wsdl:fault>
</wsdl:operation>
and
<wsdl:operation name="RunReport">
<soap:operation soapAction="#RunReport" style="document"/>
<wsdl:input name="RunReportIn">
<soap:header message="tns:RunReportIn_Headers" part="HeaderInfo" use="literal"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="RunReportOut">
<soap:header message="tns:RunReportOut_Headers" part="HeaderInfo" use="literal"/>
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="TBSoapFaultFault">
<soap:fault name="TBSoapFaultFault" use="literal"/>
</wsdl:fault>
</wsdl:operation>
Are there any workarounds ?
Microarea local assistance is very reluctant to address the problem, replying something like "but in C sharp we do not have the issue"
thank you
I tried to use different options (-XdisableAuthenticator -XadditionalHeaders etc) but it did not solve.
Upvotes: 0
Views: 106
Reputation: 11
Solution for generating the Java Artifacts: instead of Glassfish, use Apache CXF and CloseableHttpClient.
Some details:
Previously I changed from CXF to Glassfish because of the faster speed at runtime (which, during debug, can be quite time-wasting).
Anyhow, one of the Mago ERP WSDL is coded in a way that Glassfish can not fully handle, and many methods get igonerd.
So, I am reverting back to Apache CXF. Anyhow, searching for any other Framework, I came across the use of the Apache HttpClient (!). It is not at all a framework to manage WebService, but you can create the SOAP XML envelope by "hand", and send it to the WebService server via HttpClient.
I wrote the code to use Apache HttpClient and I checked on the CXF log files how to write the XML Soap.
The use of Apache HTTPClient results in a 4 times faster execution compared to Glassfish.
Here the code to call the WebService:
// Create HttpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
// Prepare the SOAP request
String soapRequest = buildSoapRequest(strUserName, strCompanyName, strPassword, strAskingProcess);
// Prepare the HTTP POST request
HttpPost httpPost = new HttpPost(strWsdlLocationMicroareaLoginManager);
httpPost.setHeader("Content-Type", "text/xml");
//httpPost.setHeader("SOAPAction", ""); // Specifica l'azione SOAP se necessario
httpPost.setHeader("Accept", "*/*"); // Specifica l'azione SOAP se necessario
httpPost.setHeader("SOAPAction", "\"http://microarea.it/LoginManager/LoginCompact\""); // Specifica l'azione SOAP se necessario
System.out.println(httpPost.toString());
StringEntity requestEntity = new StringEntity(soapRequest);
httpPost.setEntity(requestEntity);
String responseString = null;
// Execute the request
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
responseString = EntityUtils.toString(response.getEntity());
System.out.println("Response: " + responseString);
// Handle the response (puoi usare una libreria per il parsing XML se necessario)
}
strAuthenticationToken = getAuthToken(responseString);
here the code to prepare the XML SOAP:
// ID: 1
// Address: http://virtual-1/mago4/LoginManager/LoginManager.asmx
// Encoding: UTF-8
// Http-Method: POST
// Content-Type: text/xml
// Headers: {Accept=[*/*], SOAPAction=["http://microarea.it/LoginManager/LoginCompact"]}
// Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><LoginCompact xmlns="http://microarea.it/LoginManager/"><userName>skynet</userName><companyName>yesterday-italchair srl</companyName><password>skynet1</password><askingProcess>com.met.mago.MagoWebService/cxf</askingProcess><overWriteLogin>false</overWriteLogin></LoginCompact></soap:Body></soap:Envelope>
private static String buildSoapRequest(String userName, String companyName, String password, String askingProcess) {
return
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><LoginCompact xmlns=\"http://microarea.it/LoginManager/\">"
+ "<userName>skynet</userName><companyName>yesterday-italchair srl</companyName><password>skynet1</password>"
+ "<askingProcess>com.met.mago.MagoWebService/cxf</askingProcess><overWriteLogin>false</overWriteLogin></LoginCompact></soap:Body></soap:Envelope>";
}
here the code to parse the answer:
public static String getAuthToken (String strXml) throws Throwable {
// Parse the XML
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(strXml));
Document doc = builder.parse(is);
// Create XPath
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
// Define XPath expression to retrieve authenticationToken
XPathExpression expr = xpath.compile("//authenticationToken/text()");
// Evaluate XPath expression against parsed XML document
String strAuthenticationToken = (String) expr.evaluate(doc, XPathConstants.STRING);
return strAuthenticationToken;
}
And here the code, when using CXF, that makes CXF to show the messages before sending to the server (very useful to see how to write them)
JAXWSSpringClientProxyFactoryBean proxyFactory_1 = new JAXWSSpringClientProxyFactoryBean();
proxyFactory_1.setServiceClass(com.italchair.opensource.microarea.cxf.TbGes.it.microarea.loginmanager.MicroareaLoginManager.class);
javax.xml.namespace.QName SERVICE_NAME_1 = new javax.xml.namespace.QName("http://microarea.it/LoginManager/", "MicroareaLoginManager");
proxyFactory_1.setServiceName(SERVICE_NAME_1);
proxyFactory_1.setWsdlLocation(strWsdlLocationMicroareaLoginManager);
proxyFactory_1.getInInterceptors().add(new LoggingInInterceptor());
proxyFactory_1.getOutInterceptors().add(new LoggingOutInterceptor());
Upvotes: 0