Как создать SOAP-клиент в Spring?

Я могу отправлять запросы в веб-службу с помощью javax.xml.soap.*, я хотел бы скрывать код для использования webServiceTemplate.

  • Я борюсь с созданием объектов запроса и результата. (образец, найденный Ive связан с xml not SOAP)
  • Мне также интересно, есть ли какие-либо преимущества использования webServiceTemplate над java.xml.soap. Если я не делаю это правильно? Учитывая, что мне нужно подключиться к 20 веб-службам.

Единственное, что у него есть, это findEvents следующим образом:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://ticketmaster.productserve.com/v2/soap.php" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
   <soapenv:Header/>
   <soapenv:Body>
      <soap:findEvents soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <request xsi:type="soap:Request">
            <!--You may enter the following 7 items in any order-->
            <apiKey xsi:type="xsd:string">?</apiKey>
            <country xsi:type="xsd:string">?</country>
            <resultsPerPage xsi:type="xsd:int">?</resultsPerPage>
            <currentPage xsi:type="xsd:int">?</currentPage>
            <sort xsi:type="soap:Request_Sort">
               <!--You may enter the following 2 items in any order-->
               <field xsi:type="xsd:string">?</field>
               <order xsi:type="xsd:string">?</order>
            </sort>
            <filters xsi:type="soap:ArrayOfRequest_Filter" soapenc:arrayType="soap:Request_Filter[]"/>
            <updatedSince xsi:type="xsd:string">?</updatedSince>
         </request>
      </soap:findEvents>
   </soapenv:Body>
</soapenv:Envelope>

Мой код выглядит следующим образом:

try {
    SOAPConnectionFactory soapConnectionFactory =
            SOAPConnectionFactory.newInstance();
    SOAPConnection connection =
            soapConnectionFactory.createConnection();

    MessageFactory factory =
            MessageFactory.newInstance();

    SOAPMessage message = factory.createMessage();

    SOAPHeader header = message.getSOAPHeader();
    header.detachNode();

    SOAPBody body = message.getSOAPBody();

    SOAPFactory soapFactory =
            SOAPFactory.newInstance();

    Name bodyName;
    bodyName = soapFactory.createName("findEvents",
            "xsd", "http://ticketmaster.productserve.com/v2/soap.php");


    SOAPBodyElement getList =
            body.addBodyElement(bodyName);


    Name childName = soapFactory.createName("findEvents");
    SOAPElement eventRequest = getList.addChildElement(childName);

    childName = soapFactory.createName("apiKey");
    SOAPElement apiKey = eventRequest.addChildElement(childName);
    apiKey.addTextNode("MYAPI");

    childName = soapFactory.createName("country");
    SOAPElement cid = eventRequest.addChildElement(childName);
    cid.addTextNode("UK");
    message.writeTo(System.out); //show message details

    URL endpoint = new URL("http://ticketmaster.productserve.com/v2/soap.php");
    SOAPMessage response =
            connection.call(message, endpoint);

    connection.close();

    //SOAPBody soapBody = response.getSOAPBody();
    SOAPMessage sm = response;

    System.out.println("Response:");
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    sm.writeTo(out);


    String validSoap = "<?xml version=\"1.0\"?> " + out.toString();
    System.out.println("It is ValidSoap: " + validSoap);  //ValidSoap message

    SAXBuilder builder = new SAXBuilder();
    Reader in = new StringReader(validSoap);  //reading character stream
    Document doc = null; //empty jDom document is instantiated
    doc = builder.build(in); //build the jDom document

    Element root = doc.getRootElement(); //Envelope
    List allChildren = root.getChildren(); //list of all its child elements
    System.out.println("Root is:" + ((Element) allChildren.get(0)).getName());
   listChildren(root);

} catch (Exception ex) {
    ex.printStackTrace();
}

Новый код

  webServiceTemplate.sendSourceAndReceiveToResult
               ("http://ticketmaster.productserve.com/v2/soap.php",source, result);



@XmlRootElement
public class FindEvents {
    @XmlElement
    Request request;

    public Request getRequest() {
        return request;
    }

    public void setRequest(Request request) {
        this.request = request;
    }

}

@XmlSeeAlso(SortTicket.class)
public class Request {
    @XmlElement
    String apiKey;
    @XmlElement
    String country;
    @XmlElement
    int resultsPerPage;
    @XmlElement
    int currentPage;
    @XmlElement(name = "Sort")
    SortTicket sort;
    @XmlElement
    String[] filters;
    @XmlElement
    String updatedSince;

    public String getApiKey() {
        return apiKey;
    }

    public void setApiKey(String apiKey) {
        this.apiKey = apiKey;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public int getResultsPerPage() {
        return resultsPerPage;
    }

    public void setResultsPerPage(int resultsPerPage) {
        this.resultsPerPage = resultsPerPage;
    }

    public int getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(int currentPage) {
        this.currentPage = currentPage;
    }

    public SortTicket getSort() {
        return sort;
    }

    public void setSort(SortTicket sort) {
        this.sort = sort;
    }

    public String[] getFilters() {
        return filters;
    }

    public void setFilters(String[] filters) {
        this.filters = filters;
    }

    public String getUpdatedSince() {
        return updatedSince;
    }

    public void setUpdatedSince(String updatedSince) {
        this.updatedSince = updatedSince;
    }

}

public class SortTicket {
    @XmlElement
    String field;
    @XmlElement
    String order;

    public String getField() {
        return field;
    }

    public void setField(String field) {
        this.field = field;
    }

    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order;
    }

}

Ответ 1

Поскольку вы создали классы DTO с аннотацией Jaxb, вы можете создать маршаллер, unmarshaller и создать объекты классов DTO (SortTicket, Request, FindEvents) и отправить объекты напрямую, вместо использования запроса xml

webServiceTemplate.marshalSendAndReceive(findEvents);

Что-то вроде этого вам нужно будет настроить.

Создайте маршаллер

<oxm:jaxb2-marshaller id="marshaller" contextPath="com.yourcontextpath" />

создать шаблон веб-сервиса

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
    <property name="marshaller" ref="marshaller" />
    <property name="unmarshaller" ref="marshaller" />
    <property name="defaultUri"
        value="http://ticketmaster.productserve.com/v2/soap.php" />
</bean>

и в методе некоторого класса, где вы хотите отправить запрос на мыло webServiceTemplate с помощью @Autowired

@Autowired
private WebServiceTemplate webServiceTemplate;

public void sendSampleSoapRequest() {

   SortTicket sortTicket=new SortTicket();
   // set its values
   Request request=new Request();
   //set its values
   request.setSort(sortTicket);
   FindEvents findEvents=new FindEvents();
   setRequest(request)
   Object response=webServiceTemplate.marshalSendAndReceive(findEvents);
 }
В сообщении

marshalSendAndReceive используется маршаллер Jaxb для преобразования ваших объектов (помеченных аннотацией JaxB) в xml. Таким образом, над вашим объектом FindEvents будет преобразован его xml.

Что касается второго пункта Преимущества использования webServiceTemplate над java.xml.soap.: вам не нужно создавать эти SOAPElements вручную, вы просто создаете объект и отправляете его вместо большого кода для его ручной обработки. Поскольку вам нужно будет подключиться к 20 различным веб-службам, вам будет намного проще создавать объекты DTO и отправлять их напрямую. Возможно, вам придется немного изменить мои приведенные выше примеры. Удалите deido uri

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
    <property name="marshaller" ref="marshaller" />
    <property name="unmarshaller" ref="marshaller" />
</bean>

и при отправке запроса укажите запрос URI

Object response=webServiceTemplate.marshalSendAndReceive(uri,object);

Для отправки на несколько серверов

Object response1=webServiceTemplate.marshalSendAndReceive(uri1,object);
Object response1=webServiceTemplate.marshalSendAndReceive(uri2,object) 

uri1 и uri2 могут быть разными услугами мыла. И если у вас нет wsdl, вы можете отправить xml с помощью этого метода.

sendSourceAndReceiveToResult(uri1,source, result);
sendSourceAndReceiveToResult(uri2,source, result);

Отправка uri в методе отправки за пределы URI по умолчанию

Например, проверьте this и проверьте api doc