Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 6 của 6
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Cách sử dụng đối tượng trong Webservice java?

    Mình có 1 cái webservice như sau:

    Mã:
    package com.nqd.download.ws; import java.io.IOException;import java.io.InputStream;import javax.jws.WebMethod;import javax.jws.WebService;import javax.jws.soap.SOAPBinding;import javax.jws.soap.SOAPBinding.Style;@WebService(serviceName = "FileServer")@SOAPBinding(style = Style.RPC)public interface FileServer {    @WebMethod    public void downloadFile(String fileURL) throws IOException;    @WebMethod    public void disconnect() throws IOException;    @WebMethod    public String getFileName();    @WebMethod    public int getContentLength();    @WebMethod    public InputStream getInputStream();}
    Mã:
    package com.nqd.download.ws; import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL; import javax.jws.WebService;import javax.xml.ws.soap.MTOM; @MTOM@WebService(endpointInterface = "com.nqd.download.ws.FileServer")public class FileServerImpl implements FileServer {    private HttpURLConnection httpConn;    private InputStream inputStream;    private String fileName;    private int contentLength;     @Override    public void downloadFile(String fileURL) throws IOException {        URL url = new URL(fileURL);        httpConn = (HttpURLConnection) url.openConnection();        int responseCode = httpConn.getResponseCode();         // always check HTTP response code first        if (responseCode == HttpURLConnection.HTTP_OK) {            String disposition = httpConn.getHeaderField("Content-Disposition");            String contentType = httpConn.getContentType();            contentLength = httpConn.getContentLength();             if (disposition != null) {                // extracts file name from header field                int index = disposition.indexOf("filename=");                if (index > 0) {                    fileName = disposition.substring(index + 10,                            disposition.length() - 1);                }            } else {                // extracts file name from URL                fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,                        fileURL.length());            }             // output for debugging purpose only            System.out.println("Content-Type = " + contentType);            System.out.println("Content-Disposition = " + disposition);            System.out.println("Content-Length = " + contentLength);            System.out.println("fileName = " + fileName);             // opens input stream from the HTTP connection            inputStream = httpConn.getInputStream();         } else {            throw new IOException(                    "No file to download. Server replied HTTP code: "                            + responseCode);        }     }     @Override    public void disconnect() throws IOException {        inputStream.close();        httpConn.disconnect();    }     @Override    public String getFileName() {        return this.fileName;    }     @Override    public int getContentLength() {        return this.contentLength;    }     @Override    public InputStream getInputStream() {        return this.inputStream;    } }
    Mã:
    package com.nqd.download.ws; import javax.xml.ws.Endpoint; public class FilePublisher {    public static void main(String[] args) {        Endpoint.publish("http://localhost:9899/ws/FileServer", new FileServerImpl());        System.out.println("Server is published!");    }}
    Vấn đề của mình gặp phải ở đây là cái phương thức getContentLeght,getFileName thì hoạt động bình thường còn phương thức getInputStream thì không hoạt động được.Có bạn nào giúp mình với !

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Sao bạn Wazi Armstrong lại có ý định giải thích cho Kevin Hoang về Serializable nhỉ? Mình có đọc và thấy là bạn viết rất lý thuyết và có phần tương đối là 'bác học'. [IMG]images/smilies/biggrin.png[/IMG]

    Mình có một câu hỏi mong bạn Wazi Armstrong giúp đỡ: Theo những gì bạn đã viết ở trên, bạn sẽ Serializable đối tượng InputStream như thế nào? Nếu có ví dụ thì có lẽ là tốt biết nhường nào.

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi Admin
    Sao bạn Wazi Armstrong lại có ý định giải thích cho Kevin Hoang về Serializable nhỉ? Mình có đọc và thấy là bạn viết rất lý thuyết và có phần tương đối là 'bác học'. [IMG]images/smilies/biggrin.png[/IMG]

    Mình có một câu hỏi mong bạn Wazi Armstrong giúp đỡ: Theo những gì bạn đã viết ở trên, bạn sẽ Serializable đối tượng InputStream như thế nào? Nếu có ví dụ thì có lẽ là tốt biết nhường nào.
    Trả lời câu hỏi nhanh của bác: Đối tượng InputStream sẽ serialize được. Nhưng theo như Kevin đã đề cập, nó sẽ ko mang lại những gì bạn mong đợi (đọc thông tin từ một stream).

    Về cái java.io.Serializable em xin lỗi là em nhầm lẫn với cơ chế serialize của thằng GWT. Thằng này cũng serial object nhưng không phải ra xml mà là ra 1 chuỗi bình thường (debug thì thấy nó ra 1 chuỗi loằng ngoằng theo cách riêng của nó). Những điều kiện để thằng GWT này serialize được Object như em đã đề cập.
    Còn về việc serialize object ra XML: Nói đơn giản là bạn không thể nhồi vào XML những thông tin ngoài khả năng biểu diễn của XML. Vì thế khi serialize 1 đối tượng InputStream, khi client invoke webservice đối tượng trả ra sẽ không có các phương thức như mong đợi, mà chỉ còn các property (get/set, các field public).

    Lấy một ví dụ cho dễ hiểu, mình tận dụng luôn câu hỏi của chủ thớt:


    Mã:
    @WebMethod(operationName="foo")    public MyInputStream foo() {        try {            return new MyInputStream("/Users/wazi/test.txt");        } catch (FileNotFoundException e) {            e.printStackTrace();            return null;        }    }        public static class MyInputStream extends FileInputStream {         public String xxx;                public int getBar() {                    return 0;        }                public void setBar(int bar) {            //do nothing        }                public int calcBar() {            return 1+3;        }         public MyInputStream(String name) throws FileNotFoundException {             super(name);        }    }
    Sau khi serialize thì kiểu MyInputStream sẽ được biểu diễn như sau


    Mã:
     <xs:complexType name="myInputStream"><xs:complexContent><xs:extension base="tns:fileInputStream"><xs:sequence><xs:element name="xxx" type="xs:string" minOccurs="0"></xs:element><xs:element name="bar" type="xs:int"></xs:element></xs:sequence></xs:extension></xs:complexContent></xs:complexType> <xs:complexType name="fileInputStream"><xs:complexContent><xs:extension base="tns:inputStream"><xs:sequence></xs:sequence></xs:extension></xs:complexContent></xs:complexType> <xs:complexType name="inputStream" abstract="true"><xs:sequence></xs:sequence></xs:complexType>
    Ta có thể thấy property bar (cặp get/set) tạo nên element bar trong xml (dù lớp MyInputStream không có field nào tên là bar). Bên cạnh đó field String xxx cũng được thể hiện trong schema vì nó là public (nhìn thấy được từ bên ngoài). Cũng theo như schema trên ta có thể thấy rằng FileInputStream hay InputStream chẳng có thông tin gì, đơn giản vì nó ko có property nào public để serialize (từ đây xin gọi chung public field và cặp set/get là property).

    Một điểm nữa là Client hoàn toàn không biết gì về cấu trúc cái class mà bạn định nghĩa trong Java Code, cái nó biết duy nhất là wsdl. Dựa vào thông tin schema cung cấp client sẽ tạo ra những class tương ứng để phục vụ việc lập trình của bạn dễ dàng hơn (Điều này là không bắt buộc vì bạn hoàn toàn có thể gọi webservice mà chẳng cần phải sinh ra cái class nào, tất cả chỉ là xml). Để minh chứng cho ý này, đặc biệt là câu đầu tiên của đoạn này, mình gen code client bằng Axis 2. Kết quả như sau:


    Mã:
         public static class MyInputStream extends FileInputStream implements org.apache.axis2.databinding.ADBBean {         protected java.lang.String localXxx;        protected boolean localXxxTracker = false;        public boolean isXxxSpecified() {            return localXxxTracker;        }        public java.lang.String getXxx() {            return localXxx;        }        public void setXxx(java.lang.String param) {            localXxxTracker = param != null;            this.localXxx = param;        }        protected int localBar;        public int getBar() {            return localBar;        }        public void setBar(int param) {            this.localBar = param;        }             //....}
    Chúng ta có thể thấy lớp MyInputStream tạo ở client không hoàn toàn giống như lớp MyInputStream ở phía server (web service). Đơn giản vì client đâu có biết lớp này [IMG]images/smilies/biggrin.png[/IMG] Nếu view code sâu hơn các bạn có thể thấy các lớp InputStream, FileInputStream cũng được sinh ra, hoàn toàn dựa theo schema nên không phải thuộc gói java.io, và tất nhiên là chúng chẳng có những phương thức như mong đợi (readByte, read...).

    Sau ví dụ này mọi thứ có vẻ đã khá rõ ràng, mình sẽ không kết luận gì nữa.

    Bổ sung thêm 1 xíu là trên cách serialize (Data Binding) trên đây là hoàn toàn tự động. Bạn hoàn toàn có thể dùng các config (annotation) của JAXB để điều chỉnh sao cho schema đầu ra như mong muốn.

    PS: Lâu rồi mình không code, chỉ làm ở mức design nên bạn Admin nói mình lý thuyết cũng có phần nào đúng.

  4. #4
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Bạn cần hiểu rằng mọi thứ thông qua webservice phải là những thứ có thể serialize theo cách mà webservice hiểu. Vì thế, bạn không thể pass đối tượng InputStream qua HTTP Webservice được, bởi vì stream không được serialize (nếu có thì cũng chẳng có dữ liệu). Bạn có thể tạo HttpEntity, sau đó sử dụng JSON hoặc một kiểu serialize nào đó để xử lý vấn đề này.

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Vậy Kevin Hoang ở trên đã trả lời đúng vấn đề, và mình thấy bạn đã cố gắng giải thích bằng lý thuyết nên mình hỏi thôi [IMG]images/smilies/biggrin.png[/IMG]. Mình nghĩ là có lẽ lúc đấy bạn hiểu lầm ý này, còn để giải quyết vấn đề của chủ thớt thì cách của bạn hoàn toàn không được như mong muốn.

    Nếu chủ thớt không dùng webservice mà dùng RMI thì vấn đề được giải quyết, nhưng vấn đề là RMI hạn chế bởi ngôn ngữ, và để giải quyết vấn đề hạn chế ngôn ngữ thì cần rất nhiều công xây cầu. [IMG]images/smilies/biggrin.png[/IMG]

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi Kevin Hoang
    Bạn cần hiểu rằng mọi thứ thông qua webservice phải là những thứ có thể serialize theo cách mà webservice hiểu. Vì thế, bạn không thể pass đối tượng InputStream qua HTTP Webservice được, bởi vì stream không được serialize (nếu có thì cũng chẳng có dữ liệu). Bạn có thể tạo HttpEntity, sau đó sử dụng JSON hoặc một kiểu serialize nào đó để xử lý vấn đề này.
    Để cho dễ hiểu hơn về khái niệm Serializable (java.io) thì mình xin giải thích rõ hơn như sau.
    Trong Web service SOAP, quá trình gửi 1 message thông qua 2 bước gọi là Mashalling và Unmashalling như hình dưới đây


    Hiểu đơn giản thì Mashalling biến Object thành XML còn Unmashalling thì ngược lại. (Trong Java họ dùng Java API for XML Binding - JAXB)
    Nếu một object là Serializable nếu và chỉ nếu:
    - Nó implement java.io.Serializable
    - Các properties của nó cũng Serializable
    2 điều kiện này nhằm đảm bảo cho quá trình convert ngược xuôi (như trên) được thực hiện nhất quán, không gây mất thông tin.
    Ví dụ tất cả các object implement java.util.List<primitiveType> (đã implements java.io.Serializable, primitiveType mặc định là serializable) như ArrayList, LinkedList..., khi convert (mashalling) sẽ chuyển thành 1 xml element đại loại như

    Mã:
    <list>    <el>a</el>    <el>b</el>    <el>c</el>    <el>ksdjfk</el></list>
    Nói túm lại là bạn tìm được 1 cách biểu diễn cái object cần gửi ra text sao cho bên nhận có thể tái tạo lại toàn bộ thông tin được là ok. Thường thì nó là những object được tạo nên bằng việc kết hợp của các kiểu nguyên thủy. Ví dụ: có các properties là kiểu nguyên thủy, có các đối tượng là một nhóm các kiểu nguyên thủy hợp thành như Map, List. Những object này đóng vai trò vận chuyển thông tin thay vì thực hiện logic (POJO)

    Happy Coding! [IMG]images/smilies/biggrin.png[/IMG]

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •