SOAP Web service: Upload và Download file sử dụng MTOM trong JAX-WS

Trong bài này chúng ta sẽ cùng tìm hiểu cách sử dụng Message Transmission Optimization Mechanism (MTOM) và XML-Binary Optimized Packaging (XOP) để upload file lên Server và download file từ Server về Client.

1. Tạo WebService Server

DocumentService.java

package com.maixuanviet.ws.document;
 
import javax.activation.DataHandler;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
 
@WebService
@SOAPBinding(style = Style.RPC)
public interface DocumentService {
 
    @WebMethod
    DataHandler download(String name);
 
    @WebMethod
    String upload(DataHandler data);
}

DocumentServiceImpl.java

package com.maixuanviet.ws.document;
 
import javax.activation.DataHandler;
import javax.jws.WebService;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.soap.MTOM;
 
@MTOM
@WebService(endpointInterface = "com.maixuanviet.ws.document.DocumentService")
public class DocumentServiceImpl implements DocumentService {
 
    public static final String UPLOADED_FOLDER = "data/upload/";
 
    @Override
    public DataHandler download(String name) {
        return DocumentUtils.getFileAsDataHandler("data/" + name);
    }
 
    @Override
    public String upload(DataHandler dataHandler) {
        if (dataHandler != null) {
            String fileName = UPLOADED_FOLDER + "upload-" + System.currentTimeMillis() + ".docx";
            DocumentUtils.storeDataToFile(dataHandler, fileName);
            return "Uploaded Successful with name " + fileName;
        }
        throw new WebServiceException("Upload Failed!");
    }
}

Trong phần cài đặt trên, tôi sử dụng:
Sử dụng @MTOM : để enable sử dụng MTOM cho Web service.
DataHandler để có thể nhận được nhiều loại source, format từ Client gửi lên và tối ưu hơn về performance.

Lớp tiện ích hỗ trợ đọc/ ghi file từ DataHandler:
DocumentUtils.java

package com.maixuanviet.ws.document;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
 
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
 
public class DocumentUtils {
 
    private DocumentUtils() {
        super();
    }
 
    public static void storeDataToFile(DataHandler dataHandler, String fileName) {
        try {
            File file = new File(fileName);
            OutputStream os = new FileOutputStream(file);
            dataHandler.writeTo(os);
            os.flush();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    public static DataHandler getFileAsDataHandler(String fileName) {
        FileDataSource dataSource = new FileDataSource(fileName);
        return new DataHandler(dataSource);
    }
}

DocumentPublisher.java

package com.maixuanviet.ws.document;
 
import javax.xml.ws.Endpoint;
 
public class DocumentPublisher {
 
    public static final String WS_URL = "http://localhost:8080/ws/document";
 
    public static void main(String[] args) {
        Endpoint.publish(WS_URL, new DocumentServiceImpl());
        System.out.println("Server is published!");
    }
}

Chạy chương trình DocumentPublisher.

2. Tạo Client truy cập WS

Chúng ta cần chuẩn bị một số resource để hỗ trợ upload/ download file theo cấu trúc thư mục sau:

2.1. Ứng dụng Client, truy xuất WS upload file

DocumentClientDownload.java

package com.maixuanviet.ws.document;
 
import java.net.URL;
 
import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import javax.xml.ws.soap.SOAPBinding;
 
public class DocumentClientUpload {
 
    public static void main(String[] args) throws Exception {
 
        // Create URL of .wsdl file
        URL url = new URL(DocumentPublisher.WS_URL + "?wsdl");
 
        // Create a QName using targetNamespace and name
        QName qname = new QName("http://document.ws.maixuanviet.com/", "DocumentServiceImplService");
 
        // Creates a Service instance with the specified WSDL document location and
        // service qualified name
        Service service = Service.create(url, qname);
 
        // We need to pass interface and model beans to client
        DocumentService imageServer = service.getPort(DocumentService.class);
 
        // Enable MTOM in client
        BindingProvider bp = (BindingProvider) imageServer;
        SOAPBinding binding = (SOAPBinding) bp.getBinding();
        binding.setMTOMEnabled(true);
 
        // Prepare document for upload
        DataHandler dataHandler = DocumentUtils.getFileAsDataHandler("data/test.docx");
 
        // Perform upload document
        String status = imageServer.upload(dataHandler);
        System.out.println("upload() : " + status);
    }
}

Chạy chương trình trên, chúng ta có kết quả như sau:

upload() : Uploaded Successful with name data/upload/upload-1559229879163.docx

Ứng dụng Client, truy xuất WS download file

package com.maixuanviet.ws.document;
 
import java.net.URL;
 
import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
 
public class DocumentClientDownload {
 
    public static final String DOWNLOADED_FOLDER = "data/download/";
 
    public static void main(String[] args) throws Exception {
 
        // Create URL of .wsdl file
        URL url = new URL(DocumentPublisher.WS_URL + "?wsdl");
 
        // Create a QName using targetNamespace and name
        QName qname = new QName("http://document.ws.maixuanviet.com/", "DocumentServiceImplService");
 
        // Creates a Service instance with the specified WSDL document location and
        // service qualified name
        Service service = Service.create(url, qname);
 
        // We need to pass interface and model beans to client
        DocumentService imageServer = service.getPort(DocumentService.class);
 
        // Perform download document
        DataHandler dataHandler = imageServer.download("test.docx");
 
        // Save the result to file
        String fileName = DOWNLOADED_FOLDER + "dowload-" + System.currentTimeMillis() + ".docx";
        DocumentUtils.storeDataToFile(dataHandler, fileName);
        System.out.println("download() : Downloaded Successful with name " + fileName);
    }
}

Chạy chương trình trên, chúng ta có kết quả như sau:

download() : Downloaded Successful with name data/download/dowload-1559229893344.docx