3
\$\begingroup\$

I am able to send requests to the web service using javax.xml.soap.*. I would like to convert the code to use webServiceTemplate.

  • I am struggling with creating request and result objects. (sample I've found is related to xml not SOAP)
  • I am also wondering whether there are advantages to using webServiceTemplate over java.xml.soap. If there is not, am I doing it correctly? Given that I need to get connected to 20 web services.

The only service it has is findEvents as follows:

<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>

My code is as follows:

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();
}

New Code

 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;
 }
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jul 3, 2015 at 2:13
\$\endgroup\$
8
  • \$\begingroup\$ Does the new code work as expected? \$\endgroup\$ Commented Jul 3, 2015 at 2:25
  • \$\begingroup\$ I'm voting for reopening. Besides the title, I can't see why this code should be broken. It may do what's needed and the "complete conversion" (whatever it means) can be seen as code improvement. Daniel: You may want to reformulate your question to fit better with the site policy. It's also not exactly clear what you need. \$\endgroup\$ Commented Jul 3, 2015 at 6:59
  • \$\begingroup\$ @Mat'sMug no it does not \$\endgroup\$ Commented Jul 6, 2015 at 22:47
  • \$\begingroup\$ @maaartinus I do not get what you mean by its not clear what I mean. Please read the bullet points. \$\endgroup\$ Commented Jul 6, 2015 at 22:48
  • \$\begingroup\$ @DanielNewtown I can't see how you can be "creating request and result objects". What about just calling the constructors and setters you've written. I'm seeing sendSourceAndReceiveToResult for the first time, but what else should it need? The point of WebServiceTemplate is to use objects and to forget about XML, so just call it and see what happens. \$\endgroup\$ Commented Jul 6, 2015 at 23:06

1 Answer 1

2
+50
\$\begingroup\$

Since you have generated DTO classes with Jaxb annotation you can create a marshaller ,unmarshaller and create objects of the DTO classes (SortTicket, Request, FindEvents) and send the objects directly instead of using the xml request

webServiceTemplate.marshalSendAndReceive(findEvents);

Something like this you'll have to configure.

Create a marshaller

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

create web service template

<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>

and in some class's method where you want to send soap request inject webServiceTemplate using @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 message uses the Jaxb marshaller to convert your objects (marked with JaxB annotation)to xml.So above your findEvents object will be converted to its xml from. Advantage of using this is that you will be getting rid of creating xml elements manually.

Regarding your second point advantages of using webServiceTemplate over java.xml.soap. : you don't have to create those SOAPElements manually you just create an object and send it instead of big code for manually handling it. Since you'll have to connect to 20 different webservices it will be much easier for you to create DTO objects and send them directly.You may need to modify my above samples a little. Remove the deault uri

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

and while sending request give the URI request

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

For sending it to multiple server

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

uri1 and uri2 can be different soap service and if you don't have the wsdl you can send xml with this method

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

Sending a uri in the send method over rides the default URI

For example check this also check the api doc

Heslacher
50.8k5 gold badges83 silver badges177 bronze badges
answered Jul 13, 2015 at 4:32
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.