約1か月前に同じ問題に直面しました。
WebサービスクライアントクラスはApacheCXFを使用して生成され、WebサービスはHTTPステータス307を返しました。これにより、同じ例外が発生しました。
Follow Redirects
プロパティがに設定されたsoapUIを使用した同じWebサービスメソッドの呼び出しtrue
は成功し、必要なデータが返されました。
しばらくグーグルした後、このためにJAX-WSで次のリダイレクトを有効にするプロパティがないように見えました。
したがって、以下は現在機能しているコードですが、どの標準にも準拠しているかどうかはわかりません。
生成されたクライアントクラスが次のようになっていると仮定します。
// generated service class
public class MyWebServiceClient extends javax.xml.ws.Service {
// ...
private final QName portName = "...";
// ...
public RetrieveMyObjects getRetrieveMyObjects() {
return super.getPort(portName, RetrieveMyObject.class);
}
// ...
}
// generated port interface
// annotations here
public interface RetrieveMyObjects {
// annotations here
List<MyObject> getAll();
}
さて、次のコードを実行すると:
MyWebServiceClient wsClient = new MyWebServiceClient("wsdl/location/url/here.wsdl");
RetrieveMyObjectsPort retrieveMyObjectsPort = wsClient.getRetrieveMyObjects();
wsClient
RetrieveMyObjects
&javax.xml.ws.BindingProvider
interfacesのインスタンスであるインスタンスを返す必要があります。JAX-WSの表面には何も記載されていませんが、多くのコードがその事実に基づいているようです。次のようなことを実行することで、自分自身を安心させることができます。
if(!(retrieveMyObjectsPort instanceof javax.xml.ws.BindingProvider)) {
throw new RuntimeException("retrieveMyObjectsPort is not instance of " + BindingProvider.class + ". Redirect following as well as authentication is not possible");
}
retrieveMyObjectsPort
さて、それがインスタンスであることが確実な場合はjavax.xml.ws.BindingProvider
、SOAPリクエストをシミュレートしてプレーンなHTTP POSTリクエストを送信できます(ただし、これは非常に不正確で醜いように見えますが、私の場合は機能し、グーグル中にこれ以上良いものは見つかりませんでした)。 Webサービスがリダイレクトステータスを応答として送信するかどうかを確認します。
// defined somewhere before
private static void checkRedirect(final Logger logger, final BindingProvider bindingProvider) {
try {
final URL url = new URL((String) bindingProvider.getRequestContext().get(ENDPOINT_ADDRESS_PROPERTY));
logger.trace("Checking WS redirect: sending plain POST request to {}", url);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "text/html; charset='UTF-8'");
connection.setDoOutput(true);
if(connection.getResponseCode() == 307) {
final String redirectToUrl = connection.getHeaderField("location");
logger.trace("Checking WS redirect: setting new endpoint url, plain POST request was redirected with status {} to {}", connection.getResponseCode(), redirectToUrl);
bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, redirectToUrl);
}
} catch(final Exception e) {
logger.warn("Checking WS redirect: failed", e);
}
}
// somewhere at the application start
checkRedirect(logger, (BindingProvider) retrieveMyObjectsPort);
さて、このメソッドが行うことは次BindingProvider.ENDPOINT_ACCESS_PROPERTY
のとおりです。retrieveMyObjectsPort
つまり、このポートメソッドがSOAPリクエストを送信するURLを取得し、上記のようにプレーンなHTTPPOSTリクエストを送信します。次に、応答ステータスがであるかどうかをチェックし307 - Temporary Redirect
(302や301などの他のステータスも含まれる場合があります)、そうである場合は、WebサービスがリダイレクトしているURLを取得し、指定されたポートに新しいエンドポイントを設定します。
私の場合、このcheckRedirect
メソッドはWebサービスポートインターフェイスごとに1回呼び出され、すべてが正常に機能しているように見えます。
- リダイレクトは次のようなURLでチェックされます
http://example.com:50678/restOfUrl
- Webサービスは次のようなURLにリダイレクトします
https://example.com:43578/restOfUrl
(Webサービスクライアント認証が存在することに注意してください)-ポートのエンドポイントはそのURLに設定されます
- そのポートを介して実行された次のWebサービス要求は成功します
免責事項:私はWebサービスにまったく慣れていません。これは、この質問に対する解決策がないために何とか達成できたものです。ここで問題が発生した場合は、修正してください。
お役に立てれば