Upload/POST XML data or XML data object to an URL (i.e Web Service URL) through HTTP POST Request in Java

This is about how we can post XML data or data object to an URL( webservice URL or any other URL which can accept these POST request.)

Common Scenario: Lets say we are having data in some tables and we want to post /send these data in the form of xml request to some external URL( which can be a web service URL). We will convert each of these row data in to xml data object and will send this xml data object with the help  marshalling/de-marshalling functionality and will do a POST request to the external URL.

Below is the XML data object used for carrying XML data .

TransactionXMLData Class:

package com.abc.xyz.xml.model;
import java.util.Date;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Transaction")
public class TransactionXMLData {

@XmlElement(name = "TransactionId")
private long transactionId;
@XmlElement(name = "DCCode")
private String dcCode;
@XmlElement(name = "TransactionType")
private String transactionType;
@XmlElement(name = "TransactionDate")
private Date transactionDate;
@XmlElement(name = "SourceLicensePlateNo")
private String sourceLicensePlateNo;
@XmlElement(name = "DestLicensePlateNo")
private String destLicensePlateNo;
@XmlElement(name = "ProductId")
private String productId;
@XmlElement(name = "PerformedBy")
private String performedBy;
@XmlElement(name = "OrderId")
private String orderId;
@XmlElement(name = "OrderType")
private String orderType;
@XmlElement(name = "OrderLineNo")
private String orderLineNo;

public long getTransactionIdValue() {
return transactionId;
}
public void setTransactionId(long transactionId) {
this.transactionId = transactionId;
}
public String getDcCodeValue() {
return dcCode;
}
public void setDcCode(String dcCode) {
this.dcCode = dcCode;
}
public String getTransactionTypeValue() {
return transactionType;
}
public void setTransactionType(String transactionType) {
this.transactionType = transactionType;
}
public Date getTransactionDateValue() {
return transactionDate;
}
public void setTransactionDate(Date transactionDate) {
this.transactionDate = transactionDate;
}
public String getSourceLicensePlateNoValue() {
return sourceLicensePlateNo;
}
public void setSourceLicensePlateNo(String sourceLicensePlateNo) {
this.sourceLicensePlateNo = sourceLicensePlateNo;
}
public String getDestLicensePlateNoValue() {
return destLicensePlateNo;
}
public void setDestLicensePlateNo(String destLicensePlateNo) {
this.destLicensePlateNo = destLicensePlateNo;
}
public String getProductIdValue() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getPerformedByValue() {
return performedBy;
}
public void setPerformedBy(String performedBy) {
this.performedBy = performedBy;
}
public String getOrderIdValue() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getOrderTypeValue() {
return orderType;
}
public void setOrderType(String orderType) {
this.orderType = orderType;
}
public String getOrderLineNoValue() {
return orderLineNo;
}
public void setOrderLineNo(String orderLineNo) {
this.orderLineNo = orderLineNo;
}
}

WebServiceUploadConfig Class:

package com.abc.xyz;
public class WebServiceUploadConfig {
private String url;
private String username;
private String password;

public WebServiceUploadConfig(String url) {
super();
this.url = url;
}
public WebServiceUploadConfig(String url, String username, String password) {
super();
this.url = url;
this.username = username;
this.password = password;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}

}

 

WebServiceUploadException Class:


package com.abc.xyz.exception;

public class WebServiceUploadException extends Exception {

private static final long serialVersionUID = 1L;

public WebServiceUploadException(String msg) {
super(msg);
}

public WebServiceUploadException(Throwable t) {
super(t);
}

public WebServiceUploadException(String msg, Throwable t) {
super(msg, t);
}
}

WebServiceUploadAudit Class:


package com.abc.xyz.model.dataobjects;
import java.util.Date;

public class WebServiceUploadAudit {
private long id;
private long transactionId;
private String transactionType;
private String remoteHost;
private String requestURL;
private String requestBody;
private Date sendDate;
private String responseHeader;
private String responseBody;
private String host;
private String userId;
private boolean success;
private String errorMessage;

public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getRemoteHost() {
return remoteHost;
}
public void setRemoteHost(String remoteHost) {
this.remoteHost = remoteHost;
}
public String getRequestURL() {
return requestURL;
}
public void setRequestURL(String requestURL) {
this.requestURL = requestURL;
}
public String getRequestBody() {
return requestBody;
}
public void setRequestBody(String requestBody) {
this.requestBody = requestBody;
}
public Date getSendDate() {
return sendDate;
}
public void setSendDate(Date sendDate) {
this.sendDate = sendDate;
}
public String getResponseHeader() {
return responseHeader;
}
public void setResponseHeader(String responseHeader) {
this.responseHeader = responseHeader;
}
public String getResponseBody() {
return responseBody;
}
public void setResponseBody(String responseBody) {
this.responseBody = responseBody;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public boolean getSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public long getTransactionId() {
return transactionId;
}
public void setTransactionId(long transactionId) {
this.transactionId = transactionId;
}
public String getTransactionType() {
return transactionType;
}
public void setTransactionType(String transactionType) {
this.transactionType = transactionType;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}

}

XMLConverter Class:


package com.abc.xyz;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.log4j.Logger;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;

public class XMLConverter {
Logger logger = Logger.getLogger(XMLConverter.class);
private Marshaller marshaller;
private Unmarshaller unmarshaller;

public Marshaller getMarshaller() {
return marshaller;
}
public void setMarshaller(Marshaller marshaller) {
this.marshaller = marshaller;
}
public Unmarshaller getUnmarshaller() {
return unmarshaller;
}
public void setUnmarshaller(Unmarshaller unmarshaller) {
this.unmarshaller = unmarshaller;
}

public void convertFromObjectToOutPutStream(Object object,OutputStream os)
throws IOException {
if (logger.isInfoEnabled()) {
logger.info("converting object to xml");
}
try {
getMarshaller().marshal(object, new StreamResult(os));
} finally {
if (os != null) {
os.close();
}
}
}

public Object convertFromXMLToObject(String xmlfile) throws IOException {
if (logger.isInfoEnabled()) {
logger.info("converting xml to object");
}

FileInputStream is = null;
try {
is = new FileInputStream(xmlfile);
return getUnmarshaller().unmarshal(new StreamSource(is));
} finally {
if (is != null) {
is.close();
}
}
}

}

WebServiceUploadAuditDAO Class:

package com.abc.xyz.dao;

import com.abc.xyz.model.dataobjects.WebServiceUploadAudit;

public interface WebServiceUploadAuditDAO {

public void save(WebServiceUploadAudit audit);

}

WebServiceUploadAuditDAOImpl Class:

package com.abc.xyz.dao;

import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;

import com..abc.xyz.model.dataobjects.WebServiceUploadAudit;

public class WebServiceUploadAuditDAOImpl implements WebServiceUploadAuditDAO {
Logger logger = Logger.getLogger(WebServiceUploadAuditDAOImpl.class);
private JdbcTemplate jdbcTemplate;

public void save(WebServiceUploadAudit audit) {
if (logger.isInfoEnabled()) {
logger.info("Inserting Data in WEBSERVICE_UPLOAD_LOG table");
}

String insertQuery = "INSERT INTO      WEBSERVICE_UPLOAD_LOG(ID,REMOTE_HOST,REQUEST_URL,SEND_DATE,HOST,USER_ID,SUCCESS_IND,ERROR_MESSAGE,TRANSACTION_ID,TRANSACTION_TYPE,REQUEST_BODY,RESPONSE_HEADER,RESPONSE_BODY)values(WEBSERVICE_UPLOAD_LOG_SEQ.nextval,?,?,?,?,?,?,?,?,?,?,?,?)";
jdbcTemplate.update(
insertQuery,
new Object[] { audit.getRemoteHost(), audit.getRequestURL(),
audit.getSendDate(), audit.getHost(),
audit.getUserId(), audit.getSuccess(),
audit.getErrorMessage(), audit.getTransactionId(),
audit.getTransactionType(), audit.getRequestBody(),
audit.getResponseHeader(), audit.getResponseBody() });
}

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}

 

XMLUploadBusinessProcessImpl Class: This is the class used for POST request of xml data to an URL.

 


package com.abc.xyz.businessprocess;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Transactional;

import com.abc.xyz.WebServiceUploadConfig;
import com.abc.xyz.XMLConverter;
import com.abc.xyz.dao.WebServiceUploadAuditDAO;
import com.abc.xyz.exception.WebServiceUploadException;
import com.abc.xyz.model.dataobjects.WebServiceUploadAudit;
import com.abc.xyz.xml.model.TransactionXMLData;

public class XMLUploadBusinessProcessImpl implements XMLUploadBusinessProcess {
private XMLConverter xmlConverter;

private WebServiceUploadAuditDAO webServiceUploadAuditDAO;
Logger logger = Logger.getLogger(XMLUploadBusinessProcessImpl.class);

public void processTransactionXMLObjectForUpload(
WebServiceUploadConfig webServiceUploadConfig,
TransactionXMLData transactionXMLData)
throws WebServiceUploadException {
if (webServiceUploadConfig == null)
throw new IllegalArgumentException("WebServiceUploadConfig is null");

WebServiceUploadAudit audit = new WebServiceUploadAudit();
HttpClient client = HttpClientBuilder.create().build();
try {

ByteArrayOutputStream baos = new ByteArrayOutputStream();
xmlConverter.convertFromObjectToOutPutStream(transactionXMLData,
baos);

HttpPost post = new HttpPost(webServiceUploadConfig.getUrl());

if (!StringUtils.isEmpty(webServiceUploadConfig.getUsername())) {

post.addHeader(new BasicScheme().authenticate(
new UsernamePasswordCredentials(webServiceUploadConfig
.getUsername(), webServiceUploadConfig
.getPassword()), null, null));
}
InputStreamEntity reqEntity = new InputStreamEntity(
new ByteArrayInputStream(baos.toByteArray()), -1);

post.addHeader("Content-Type", "application/xml");
post.setEntity(reqEntity);
String host = "hostname";
audit.setHost(host);
audit.setSuccess(true);
audit.setRequestURL(webServiceUploadConfig.getUrl());
audit.setUserId(webServiceUploadConfig.getUsername());

audit.setRequestBody(baos.toString());

audit.setSendDate(new Date());
audit.setTransactionId(transactionXMLData.getTransactionIdValue());
audit.setTransactionType(transactionXMLData
.getTransactionTypeValue());

HttpResponse response = client.execute(post);

// convert header to string
StringBuilder sb = new StringBuilder();

sb.append("HTTP Response Status: ");
sb.append(response.getStatusLine().toString());
// attach new line
sb.append("\n");

Header[] headers = response.getAllHeaders();

for (int i = 0; i < headers.length; i++) {
sb.append(headers[i].getName());
sb.append(":");
sb.append(headers[i].getValue());

// attach new line
sb.append("\n");
}

audit.setResponseHeader(sb.toString());

ByteArrayOutputStream responseBaos = new ByteArrayOutputStream();
response.getEntity().writeTo(responseBaos);

audit.setResponseBody(responseBaos.toString());

if (logger.isInfoEnabled()) {
logger.info("response" + response.getEntity().getContent()
+ "-" + response.getStatusLine());
}

if (response.getStatusLine().getStatusCode() != 200) {
audit.setSuccess(false);
audit.setErrorMessage("Status code is not success: "
+ response.getStatusLine());
throw new WebServiceUploadException(response.getStatusLine()
.toString());
}

} catch (Throwable t) {
logger.warn("Error response", t);
audit.setSuccess(false);
audit.setErrorMessage(t.getMessage());
throw new WebServiceUploadException(t);
} finally {
webServiceUploadAuditDAO.save(audit);
}

}

&nbsp;

 

So with the above approach, we can send XML data to an external URL (i.e Web service URL)

throgh http POST request.

XML validation with XSD(XML Schema Definition)

We use XML for storing/keeping some data. In most scenario it becomes very necessary  to check if the XML file is having valid data or not.We can validate a XML file by using a XSD file.XSD file is a kind of document which formally describes the structure of data in the XML file.

Below are the common simple scenario in which XML validation with XSD is useful.

1. If a Web Service(any API) is been created on system which consume/gets a XML request and respond back a success/failure(simple response data) after processing the request.We have to define the contract for incoming XML request  so that client send a valid XML(and so valid data) to the called web service and so that it be processed successfully. XSD will be agreement document between client and server.With this client can validate XML request with this XSD before sending it to Web Service and Web Service can validate the incoming XML request with XSD before processing further the request.

2. Similarly , same thing can be done for response as well, Say if  a web service generate lot of data in the response, we can send them in the form of XML.Now this XML content can also be validated before sending it to the client to make sure client is getting accurate data.In this case also, we can use a XSD file/document which will act as an contract for the response (between server client).

3. Third case can be to cover both of above two scenario.We will use one XSD document/file for incoming XML request  and second XSD document/file for validating response before sending it back to client.This will make sure data validity for both request and response.

 

Below is code which will verify a XML file with a XSD file by using a Java program:

 

XSD file is:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://xyz.com/abc" xmlns:abc="http://xyz.com/abc"
elementFormDefault="qualified">
<xs:element name="Transaction">
<xs:complexType>
<xs:sequence>
<xs:element name="AMCode" minOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1" />
<xs:maxLength value="10" />
</xs:restriction>
</xs:simpleType>
</xs:element>

<xs:element name="TransactionType" minOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="0" />
<xs:maxLength value="3" />
</xs:restriction>
</xs:simpleType>
</xs:element>

<xs:element name="TransactionDate" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:dateTime">
</xs:restriction>
</xs:simpleType>
</xs:element>

</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

XML file which needs to get validate with the above XSD file is :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Transaction xmlns="http://xyz.com/abc">
<AMCode>DCM</AMCode>
<TransactionType>GT2</TransactionType>
<TransactionDate>2013-09-18T13:31:34.681+05:30</TransactionDate>
</Transaction>

Java program which validate the above XML file with that of XSD file is :

package com.xyz.abc.validation;

import java.io.File;
import java.io.IOException;

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.log4j.Logger;
import org.xml.sax.SAXException;

public class XMLValidationMain {
private final Logger logger = Logger.getLogger(XMLValidationMain.class);
private static final String INPUT_TRANSACTION_XML_FILE_NAME = "example.xml";
private final static String INPUT_TRANSACTION__XSD_FILE_NAME = "example.xsd";

public static void main(String args[]) {
XMLValidationMain xmlValidationMain= new XMLValidationMain();
try {
xmlValidationMain.isXMLValid(INPUT_TRANSACTION_XML_FILE_NAME, INPUT_TRANSACTION__XSD_FILE_NAME);
} catch (IOException e) {
e.printStackTrace();
}
}

public boolean isXMLValid(String xmlFile, String xsdFile)
throws IOException {

Source xmlFileData = null;
try {
xmlFileData = new StreamSource(xmlFile);
SchemaFactory schemaFactory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
File inputXsdFile = new File(xsdFile);
Schema schema = schemaFactory.newSchema(inputXsdFile);
Validator validator = schema.newValidator();
validator.validate(xmlFileData);

if (logger.isInfoEnabled()) {
logger.info(xmlFileData.getSystemId() + " is valid");

}
} catch (IOException e) {
logger.error("Reason: " + e.getMessage());
return false;
} catch (SAXException e) {
logger.error(xmlFileData.getSystemId() + " is NOT valid");
logger.error("Reason: " + e.getMessage());
return false;
}
return true;
}

}

Now since the above XML file is having valid data w.r.t XSD .So output of the above program will be :


INFO  com.xyz.abc.validation.XMLValidationMain  - example.xml is valid

Now , lets us change xml file to make invalid data(Set the value of <AMCode></AMCode> empty and this can not be empty as per XSD ) in it w.r.t XSD.Changed XMl file is:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Transaction xmlns="http://xyz.com/abc">
<AMCode></AMCode>
<TransactionType>GT2</TransactionType>
<TransactionDate>2013-09-18T13:31:34.681+05:30</TransactionDate>
</Transaction>

So output of the java program(after changing above xml data) will be :

ERROR com.xyz.abc.validation.XMLValidationMain&amp;amp;nbsp; - example.xml is NOT valid
ERROR com.xyz.abc.validation.XMLValidationMain&amp;amp;nbsp; - Reason: cvc-minLength-valid:
Value '' with length = '0' is not facet-valid with respect to minLength '1' for type '#AnonType_AMCodeTransaction'.

That is it, So we have seen how we can validate a XML with the XSD.Let me know if you have any question about this.