【トラブル】【Java】Webサービスでのクライアント側の例外について

【プロキシ】プロキシ認証が実装されていない場合

エラー内容

javax.xml.ws.WebServiceException:
   ... 略 ...
Caused by: java.io.IOException: Server returned HTTP response code: 407 for URL: http://...
   ... 略 ...

解決策

 * プロキシ認証が実装する。詳細は、以下の関連記事を参照のこと。
https://blogs.yahoo.co.jp/dk521123/36966230.html
より

Authenticator.setDefault(new Authenticator() {
  @Override
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication("【ユーザ名】", "【パスワード】".toCharArray());
  }
});

【プロキシ】認証情報に誤りがあった場合

エラー内容

javax.xml.ws.WebServiceException:
   ... 略 ...
Caused by: java.net.ProtocolException: Server redirected too many  times (20)
   ... 略 ...

解決策

 * プロキシ認証に正しい値を設定する

参考文献

http://x68000.q-e-d.net/~68user/net/java-http-url-connection-2.html

SSL】証明書に誤りがある場合 ~その1~

エラー内容

javax.xml.ws.WebServiceException: 次の場所でWSDLへのアクセスに失敗しました: 
   ... 略 ...
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present
   ... 略 ...
Caused by: java.security.cert.CertificateException: No subject alternative names present
   ... 略 ...

解決策

 * 証明書作成時に「Subject Alternative Name」を付加する
 * kettoolの場合、「-ext san=ip:【IPアドレス】」又は「-ext san=dns:【ホスト名】」

【例】
keytool -genkey -alias tomcat -keyalg RSA -keystore demo.keystore -validity 3650 -ext san=ip:192.168.233.144

参考文献

https://stackoverflow.com/questions/8443081/how-are-ssl-certificate-server-names-resolved-can-i-add-alternative-names-using/8444863#8444863
より抜粋

If you're using keytool, as of Java 7, keytool has an option to include a Subject Alternative Name
 (see the table in the documentation for -ext):
 you could use -ext san=dns:www.example.com or -ext san=ip:10.0.0.1.

SSL】自己証明書/オレオレ証明書を使用している場合

エラー内容

javax.xml.ws.WebServiceException: 次の場所でWSDLへのアクセスに失敗しました:    ... 略 ...
   sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target。
   ... 略 ...
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
   ... 略 ...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
   ... 略 ...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
   ... 略 ...

解決策

 * オレオレ証明書を受け入れるように証明書チェックを行わない
 * オレオレ証明書の公開鍵をクライアント側のキーストアにインポートする

【その他通信】タイムアウトした場合

エラー内容

com.sun.xml.internal.ws.client.ClientTransportException:
   ... 略 ...
Caused by: java.net.SocketTimeoutException: connect timed out
   ... 略 ...

解決策

 * 接続情報(ホスト名やポート)に正しい値を設定する

【その他通信】URLに誤りがある場合

エラー内容

com.sun.xml.internal.ws.wsdl.parser.InaccessibleWSDLException: 2 counts of InaccessibleWSDLException.
java.io.FileNotFoundException: http://... 略 ...

解決策

 * 正しいURL値を設定する

URL url = new URL("【WSDLのURL】");

【その他通信】URLのポートに誤りがある場合

エラー内容

javax.xml.ws.WebServiceException: 次の場所でWSDLへのアクセスに失敗しました:
   ... 略 ...
Caused by: java.io.IOException: Server returned HTTP response code: 503 for URL: http://... 略 ...

解決策

 * 正しいURLのポート値を設定する

■ 例外ハンドリング

 * 上記を踏まえて、例外をハンドリングを行う
 * サーバは、以下の関連記事を参照のこと。
https://blogs.yahoo.co.jp/dk521123/36139336.html

サンプル

もっといい方法ないかな...
import java.io.IOException;
import java.net.Authenticator;
import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.ProtocolException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Map;

import javax.net.ssl.SSLHandshakeException;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.WebServiceException;

public class Main {
  public static void main(String[] args) {
    System.out.println("Start!");
    try {
      System.setProperty("java.net.useSystemProxies", "true");
      System.setProperty("http.proxyHost", "XXX.XXX.XXX.XXX");
      System.setProperty("http.proxyPort", "3128");
      System.setProperty("https.proxyHost", "XXX.XXX.XXX.XXX");
      System.setProperty("https.proxyPort", "3128");

      Authenticator.setDefault(new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
          return new PasswordAuthentication("dkAdmin", "password".toCharArray());
        }
      });

      URL url = new URL("https://XXX.XXX.XXX.XXX:8443/SampleWebService/services/SampleWebService.ws?wsdl");
      SampleWebServiceService service = new SampleWebServiceService(url);
      SampleWebService proxy = service.getSampleWebServicePort();

      Map<String, Object> context = ((BindingProvider) proxy).getRequestContext();
      // コネクションを確立するまでの時間[ミリ秒]
      context.put("com.sun.xml.internal.ws.request.timeout", 10000);
      // レスポンスを受け取るまでの時間[ミリ秒]
      context.put("com.sun.xml.internal.ws.connect.timeout", 10000);

      long start = System.currentTimeMillis();
      String result = proxy.sayYourAge("Ken", 11L);
      long end = System.currentTimeMillis();
      System.out.println((end - start) + "ms");

      System.out.println("Result : " + result);
    } catch (WebServiceException ex) {
      Throwable causeEx = ex.getCause();
      ex.printStackTrace();
      if (causeEx == null) {
        ex.printStackTrace();
      } else if (causeEx instanceof SSLHandshakeException) {
        System.out.println("SSL証明書エラー");
      } else if (causeEx instanceof SocketTimeoutException) {
        System.out.println("タイムアウト");
      } else if (causeEx instanceof ConnectException) {
        System.out.println("接続エラー");
      } else if (causeEx instanceof ProtocolException) {
        System.out.println("認証データミス?");
      } else if (causeEx instanceof IOException) {
        String error = causeEx.getMessage();
        if (error != null && error.contains(" 407 ")) {
          System.out.println("認証エラー?");
        } else {
          System.out.println("その他のエラー");
        }
      } else {
        ex.printStackTrace();
      }
    } catch (MalformedURLException ex) {
      ex.printStackTrace();
    } catch (Exception ex) {
      ex.printStackTrace();
    }

    System.out.println("Done");
  }
}


関連記事

Javaで、プロキシサーバ経由で接続する

https://blogs.yahoo.co.jp/dk521123/36966230.html

TomcatTomcat 8.5 で SSL通信 ~簡易版~

https://blogs.yahoo.co.jp/dk521123/36513426.html

Java】【JAX-WSWebサービス / Metro [1] ~入門編 / サーバサイドの構築 ~

https://blogs.yahoo.co.jp/dk521123/36139336.html

Java】【JAX-WSWebサービス / Metro [2] ~入門編 / クライアントサイドの構築 ~

https://blogs.yahoo.co.jp/dk521123/36140561.html