2

I'm trying to connect Twinfield logon api through Java. The code I tried is

import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.MimeHeaders;
import java.io.ByteArrayInputStream;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class SoapTest {

    public static void main(String[] args) {
        try {
            SOAPConnectionFactory sfc = SOAPConnectionFactory.newInstance();
            SOAPConnection connection = sfc.createConnection();

            MessageFactory mf = MessageFactory.newInstance();
            SOAPMessage sm = mf.createMessage();

            SOAPHeader sh = sm.getSOAPHeader();
            SOAPBody sb = sm.getSOAPBody();
            //sh.detachNode();
            QName logonName = new QName("http://www.twinfield.com", "Logon");
            SOAPBodyElement logonElement = sb.addBodyElement(logonName);

            QName userTag = new QName("user");
            SOAPElement user = logonElement.addChildElement(userTag);
            user.addTextNode("myuser");

            QName passwordTag = new QName("password");
            SOAPElement password = logonElement.addChildElement(passwordTag);
            password.addTextNode("mypassword");

            QName organisationTag = new QName("organisation");
            SOAPElement organisation = logonElement.addChildElement(organisationTag);
            organisation.addTextNode("myorg");

            System.out.println("\n Soap Request:\n");
            sm.writeTo(System.out);
            System.out.println();

            URL endpoint = new URL("https://login.twinfield.com/webservices/session.asmx");
            SOAPMessage response = connection.call(sm, endpoint);

            connection.close();

            //System.out.println(response.getContentDescription());
            //System.out.println("--------------------------");

            // Reading response
            printSOAPResponse(response);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        Source sourceContent = soapResponse.getSOAPPart().getContent();
        System.out.print("\nResponse SOAP Message = ");
        StreamResult result = new StreamResult(System.out);
        transformer.transform(sourceContent, result);
    }   
}

It seems everything is correct but I regularly getting response <faultstring>Server did not recognize the value of HTTP Header SOAPAction: .</faultstring>. Full output of above program is as follow:

java SoapTest

 Soap Request:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <Logon xmlns="http://www.twinfield.com">
            <user>NLG001136</user>
            <password>qura976yj</password>
            <organisation>TWF-SAAS</organisation>
        </Logon>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Response SOAP Message = 
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <soap:Fault>
            <faultcode>soap:Client</faultcode>
            <faultstring>Server did not recognize the value of HTTP Header SOAPAction: .</faultstring>
            <detail/>
        </soap:Fault>
    </soap:Body>
</soap:Envelope>

Same request/credentials are working fine on Soapclient.com. Can someone please point out where my program is going wrong?

Kapil Sharma
  • 10,135
  • 8
  • 37
  • 66

2 Answers2

2

AS the fault code is Client, it is the soap message that you send is causing the issue. Try passing the same using SOAP UI, I tried the same to import the WSDL in to my SOAP UI but I got attached error...

Error loading [https://login.twinfield.com/webservices/session.asmx?wsdl]: org.apache.xmlbeans.XmlException: org.apache.xmlbeans.XmlException: error: does not close tag

As the webservice expopsed is Document/Literal wrapped, just try creating hte client side code with wsimport and you would have all needed files and would be easy to send the same request.

If you are just interested in SAAJ way then I would try passing the message created through SOAP UI.

Hope this helps.

Loks
  • 151
  • 2
  • 15
  • Awarded bounty as only answer. Although my issue is now solved and answer give me direction but its not a complete answer so not accepting the answer. – Kapil Sharma Dec 01 '14 at 10:44
1

It's better to use Twinfield Openid oAuth for authentication as recommended by Twinfield. To make the initial connection check the following link https://stackoverflow.com/a/54652064

Once you have the initial connection setup and have the access token, you can proceed with the getting the list of companies. When using Twinfield webservices in combination with access tokens, it is necessary to deliver a company id or company code in the request header. First of all generate the java code(stubs for twinfield) using https://accounting.twinfield.com/webservices/processxml.asmx?wsdl

You can use the following code to then make a request to get the list of companies

package example;

import com.user.defined.package.twinfield.Header;
import com.user.defined.package.twinfield.ObjectFactory;
import com.user.defined.package.twinfield.ProcessXml;
import com.user.defined.package.twinfield.ProcessXmlSoap;
import com.sun.xml.internal.ws.developer.WSBindingProvider;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.soap.SOAPException;


public class HelloWorldClient {
 public static void main(String[] argv) throws JAXBException, SOAPException {


     ProcessXml processXmlService = new ProcessXml();
     ProcessXmlSoap processXmlSoap = processXmlService.getProcessXmlSoap();


     WSBindingProvider bp = (WSBindingProvider)processXmlSoap;

     JAXBContext jaxbContext = JAXBContext.newInstance(Header.class);
     Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
     jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);


     ObjectFactory objectFactory = new ObjectFactory();
     Header header = new Header();
     //active access token
     header.setAccessToken("95cd6bb91a59751....................");

     JAXBElement<Header> jaxbElement = objectFactory.createHeader(header);

     //Just to check the soap header 
     jaxbMarshaller.marshal(jaxbElement, System.out);

     //Set it to the bindingprovider
     bp.setOutboundHeaders(
             jaxbElement
     );


     String xmlRequest = "<list><type>offices</type></list>";
     System.out.println(processXmlSoap.processXmlString(xmlRequest));
  }
}