2009-04-30 26 views
5

Tôi đang làm việc với một chút thành phần kế thừa trong đó chúng ta tương tác với một dịch vụ web SOAP (một công nghệ tuyệt đối), sử dụng mã máy khách được xây dựng bằng cách sử dụng thư viện JAXRPC-RI (tham khảo).Cách đặt thời gian chờ kết nối khi sử dụng ứng dụng dịch vụ web JAXRPC-RI?

Tôi quan tâm đến việc có thể đặt thời gian chờ bằng các dấu sao để trong trường hợp máy chủ dịch vụ web không trả lời trong vòng X giây, ứng dụng không được đặt ở đó mãi mãi chờ phản hồi.

Tôi đang sử dụng để làm việc với khách hàng/sơ khai được tạo bởi Apache Axis, trong đó bạn có thể chỉ cần sử dụng org.apache.axis.client.Stub.setTimeout() để đặt thời gian chờ.

Đối với cuộc sống của tôi, tôi không thể tìm ra cách để thiết lập một thời gian chờ khi sử dụng Ống tạo ra với JAXRPC-RI:

  • Lớp cổng Tôi instantiating kéo dài com.sun.xml.rpc.client.StubBase và thực hiện javax.xml.rpc.Stubcom.sun.xml.rpc.spi.runtime.StubBase.
  • JavaDocs không có lớp nào trong số này đề cập đến bất kỳ loại thời gian chờ hoặc phương pháp nào để thực hiện việc này.
  • Cố mã như stub._setProperty("axis.connection.timeout", 1000); kết quả trong một ngoại lệ trong thời gian chạy: javax.xml.rpc.JAXRPCException: Stub does not recognize property: axis.connection.timeout

Có ai có bất kỳ ý tưởng về làm thế nào để thiết lập/thực thi một thời gian chờ khi sử dụng một khách hàng JAXRPC-RI? Thậm chí có thể không?

Trả lời

0

Tôi sẽ cố gắng gặt hái tiền thưởng, vì vậy đừng bắn tôi nếu tôi hoàn toàn theo dõi sai :) Nếu ứng dụng của bạn "đặt ở đó mãi mãi chờ đợi phản hồi" hơn bạn có thể làm yêu cầu trong một chủ đề riêng biệt và sau khi sinh sản của bạn requestThread bạn chỉ có thể nói requestThread.join(max_time_to_wait); cuộc gọi tiếp theo sẽ kiểm tra xem requestThread vẫn còn sống và nếu nó sau đó cố gắng để giết nó.

Bạn ứng dụng sẽ chuyển sau một thời gian chờ và nó không phải là giải pháp thanh nha nhất ...

+0

Đây là một tùy chọn, nhưng tôi thực sự muốn làm điều đó trong giới hạn của mã máy khách dịch vụ web/API chính nó, nếu có thể. Cảm ơn bạn. –

4

Bạn có thể thiết lập các thuộc may mắn như sun.net.client.defaultConnectTimeout hay sun.net.client.defaultReadTimeout, dù rằng sau đó sẽ giới thiệu một thời gian chờ trên toàn hệ thống .

Trong mã các thuộc tính giá trị này được thiết lập sử dụng Strings:

System.setProperty("sun.net.client.defaultConnectTimeout", "1000"); 
System.setProperty("sun.net.client.defaultReadTimeout", "1000"); 

Đối với một thử nghiệm nhanh, nó có thể được dễ dàng hơn để thiết lập các biến môi trường JAVA_OPTS hoặc sử dụng các dòng lệnh:

java -Dsun.net.client.defaultConnectTimeout="1000" ... 
+0

Bất kỳ ý tưởng nào nếu điều này không chỉ ảnh hưởng đến các kết nối gửi đi mà còn ảnh hưởng đến kết nối đến? –

+0

Tôi đoán lần đầu tiên chỉ có thể áp dụng cho các yêu cầu gửi đi, trừ khi bất kỳ bắt tay nào cũng sẽ được tính đến. Và với tên "net.client", tôi cho rằng cả hai thuộc tính chỉ ảnh hưởng đến outgoing, cho thuộc tính thứ hai được hỗ trợ bởi định nghĩa của nó "[..] chỉ định timeout (tính bằng mili giây) khi đọc từ luồng đầu vào khi kết nối được thiết lập một tài nguyên. " Thật vậy, điều này làm cho người ta tự hỏi nếu có những thuộc tính tương tự cho các ổ cắm đã chấp nhận một kết nối đến, nhưng tôi không thể nhanh chóng tìm thấy chúng. – Arjan

+0

Và, "Các thuộc tính này chỉ định kết nối mặc định và thời gian chờ đọc (resp.) Cho trình xử lý giao thức được java.net.URLConnection sử dụng". Vì vậy, chỉ gửi đi chắc chắn. http://java.sun.com/javase/6/docs/technotes/guides/net/properties.html – Arjan

2

tôi không chắc chắn lý do tại sao việc triển khai JAXRPC cụ thể này không hoạt động để gây khó khăn trong việc đặt thời gian chờ. Có lẽ, có lý do chính đáng cho nó. Các triển khai khác như Axis và, tôi tin JAX-WS, cho phép bạn chỉ cần gọi phương thức setTimeout() trên Stub. Sau một số cơn đau, tôi đã có thể đưa ra giải pháp này. Hy vọng rằng, nó sẽ rất hữu ích. Bạn sẽ cần thực hiện các bước sau để đặt thời gian chờ trên URLConnect cơ bản:

  1. Tạo lớp ClientTransport mới. Nó sẽ mở rộng lớp com.sun.xml.rpc.client.http.HttpClientTransport. Ghi đè phương thức createHttpConnection (String, SOAPMessageContext). Gọi super.createHttpConnection() sẽ trả về đối tượng HttpURLConnection. Trên đối tượng HttpURLConnection, bạn có thể gọi setReadTimeout() sẽ buộc thời gian chờ phía máy khách trong X số mili giây.Khi đã xong, hãy trả về đối tượng HttpURLConnection đã sửa đổi.
  2. Mở rộng lớp Stub phía máy khách bằng chính bạn. Ghi đè phương thức _getTransport() để trả về một cá thể mới của lớp ClientTransport mà bạn đã tạo ở bước (1).
  3. Mở rộng lớp _Impl phía máy khách bằng chính bạn. Ghi đè lên phương thức Port ... để nó sử dụng Stub mà bạn đã tạo ở bước (2) thay vì tạo ra nó.
  4. Sửa đổi mã máy khách mà bạn đã viết để gọi Dịch vụ Web để nó sử dụng phần Gốc bạn đã tạo ở bước (2) và _Impl mà bạn đã tạo ở bước (3).

Lưu ý: Đảm bảo rằng mọi thứ bạn đang gọi để tạo Sơ khai qua wscompile (kịch bản lệnh Ant?) Không ghi đè 3 lớp Java bạn vừa tạo/sửa đổi. Nó có thể làm cho tinh thần để di chuyển chúng đến một gói khác nhau để họ không kết thúc được ghi đè.

1

Câu trả lời của Yevgeniy Treyvus rất tốt, nhưng kết quả trong một HTTPUrlConnection mới được tạo cho mỗi cuộc gọi SOAP. Tôi phát hiện ra trong khi thử nghiệm phương pháp tiếp cận của mình, người ta có thể thiết lập một ClientTransportFactory. Bây giờ tôi sử dụng CustomClientTransportFactory và đặt nó trên Stub (đưa nó vào StubBase). Sau đó, người ta không cần bước 2 và 3.

Trong bước 4 một sau đó đặt ClientTransportFactory mới của mình như sau: ((StubBase) myPort) ._ setTransportFactory (CustomClientTransportFactory mới());

0

Ray,

Cảm ơn bạn đã nhập. Âm thanh như cách tiếp cận của bạn vượt trội vì nó sẽ tránh được một vài bước không liên quan. Tôi sẽ phải xem xét. Tuy nhiên, trừ khi tôi đang thiếu một cái gì đó tôi không tin một HttpConnection thêm đã được tạo ra như các YourClientTransport.createHttpConnection (String s, SOAPMessageContext ctx) nên ghi đè HttpClientTransport một:

public class YourClientTransport extends HttpClientTransport { 
    @Override 
    protected HttpUrlConnection createHttpConnection(String s, SOAPMessageContext ctx) throws IOException { 
     HttpURLConnection httpURLConnection = super.createHttpConnection(s, ctx); 
     httpURLConnection.setReadTimeout(1000); 
     httpURLConnection.setConnectTimeout(1000); 
     return httpURLConnection; 
    } 
} 
0

Tôi biết rằng bạn đang sử dụng Axis nhưng Tôi đã đấu tranh để tìm câu trả lời tương tự cho Weblogic và vì tiêu đề câu hỏi và thẻ của bạn là chung chung, đây là giải pháp của tôi.

Trong lớp khách hàng của tôi triển khai giao diện MyObject đã tạo, tôi đã điều chỉnh phương thức getServicePort() như sau (lưu ý rằng tôi cũng có bảo mật tại đây).

protected MyObject getServicePort() throws java.rmi.RemoteException { 
    if (port == null) { 
     synchronized(this) { 
      if (port == null) { 
       try { 
        final MyObject_Impl service = new MyObject_Impl(wsdlURL); 

        // using a local variable until the object is completelly initialized 
        final MyObject localPort = service.getMyObjectPort(); 

        // if username and password are provided: building a client which will include the 
        // username and token 
        if (username != null && pwd != null) { 
         Stub localStub = ((Stub) localPort); 

         // We have UsernameToken Authentication too 
         localStub._setProperty(
           WSSecurityContext.CREDENTIAL_PROVIDER_LIST, 
           Collections.singletonList(
             new ClientUNTCredentialProvider(username.getBytes(), pwd.getBytes()))); 

         if (timeout != null) { 
           log.debug("Setting timeout to " + timeout + " milliseconds"); 
          localStub._setProperty("weblogic.wsee.transport.read.timeout", timeout); 
          localStub._setProperty("weblogic.wsee.transport.connection.timeout", timeout); 
         } 
        } 

        port = localPort; 

       } catch (ServiceException e) { 
        throw new RemoteException("Could not initialize client to MyObject service", e); 
       } 
      } 
     } 
    } 
    return port; 
} 

Tài liệu Oracle có tại đây: http://docs.oracle.com/cd/E12840_01/wls/docs103/webserv_rpc/client.html#wp241849 nhưng không chính xác nói rằng thời gian chờ là tính bằng giây. Nó thực sự là trong mili giây!

-1

Bạn nên sử dụng:

import javax.xml.rpc.Stub; 

... 


int timeout = <number of milliseconds>; 

((Stub) port)._setProperty(
       "axis.connection.timeout", 
       timeout); 
0

Có lẽ một chút trễ cho câu hỏi này, nhưng tôi đã đến vấn đề này ngày hôm nay. Dựa trên một giải pháp bởi Yevgeniy Treyvus đề xuất (! Cảm ơn cho nó) tôi đã đưa ra như sau:

((com.sun.xml.rpc.client.StubBase)myRemoteStub)._setTransportFactory(new ClientTransportFactory() { 
    @Override 
    public ClientTransport create() { 
     return new HttpClientTransport() { 
      @Override 
      protected HttpURLConnection createHttpConnection(String endpoint, SOAPMessageContext context) throws IOException { 
       HttpURLConnection conn = super.createHttpConnection(endpoint, context); 
       conn.setConnectTimeout(2000); 
       conn.setReadTimeout(2000); 
       return conn; 
      } 
     }; 
    } 
}); 

Nó là cơ bản giống như Yevgeniy đề xuất nhưng với một chút trọng ít hơn (với sự giúp đỡ của một kết nối nhà máy).

Các vấn đề liên quan