動作が少し異なる同じ問題に直面しました。残りの呼び出しを行うためにapachecxfライブラリを使用していました。私たちにとって、PATCHは、http上で機能している偽のサービスと話し合うまでは正常に機能していました。実際のシステム(https経由)と統合した瞬間、次のスタックトレースで同じ問題に直面し始めました。
java.net.ProtocolException: Invalid HTTP method: PATCH at java.net.HttpURLConnection.setRequestMethod(HttpURLConnection.java:428) ~[na:1.7.0_51] at sun.net.www.protocol.https.HttpsURLConnectionImpl.setRequestMethod(HttpsURLConnectionImpl.java:374) ~[na:1.7.0_51] at org.apache.cxf.transport.http.URLConnectionHTTPConduit.setupConnection(URLConnectionHTTPConduit.java:149) ~[cxf-rt-transports-http-3.1.14.jar:3.1.14]
このコード行で問題が発生していました
connection.setRequestMethod(httpRequestMethod); in URLConnectionHTTPConduit class of cxf library
今、失敗の本当の理由はそれです
java.net.HttpURLConnection contains a methods variable which looks like below
private static final String[] methods = {
"GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
};
そして、PATCHメソッドが定義されていないため、エラーが理にかなっていることがわかります。私たちはさまざまなことを試し、スタックオーバーフローを調べました。唯一の合理的な答えは、リフレクションを使用してメソッド変数を変更し、別の値「PATCH」を挿入することでした。しかし、どういうわけか、ソリューションは一種のハックであり、作業が多すぎて、すべての接続を確立してこれらのREST呼び出しを実行するための共通ライブラリがあるため、影響を与える可能性があるため、それを使用することを確信できませんでした。
しかし、その後、cxfライブラリ自体が例外を処理しており、リフレクションを使用して欠落しているメソッドを追加するためのコードがcatchブロックに記述されていることに気付きました。
try {
connection.setRequestMethod(httpRequestMethod);
} catch (java.net.ProtocolException ex) {
Object o = message.getContextualProperty(HTTPURL_CONNECTION_METHOD_REFLECTION);
boolean b = DEFAULT_USE_REFLECTION;
if (o != null) {
b = MessageUtils.isTrue(o);
}
if (b) {
try {
java.lang.reflect.Field f = ReflectionUtil.getDeclaredField(HttpURLConnection.class, "method");
if (connection instanceof HttpsURLConnection) {
try {
java.lang.reflect.Field f2 = ReflectionUtil.getDeclaredField(connection.getClass(),
"delegate");
Object c = ReflectionUtil.setAccessible(f2).get(connection);
if (c instanceof HttpURLConnection) {
ReflectionUtil.setAccessible(f).set(c, httpRequestMethod);
}
f2 = ReflectionUtil.getDeclaredField(c.getClass(), "httpsURLConnection");
HttpsURLConnection c2 = (HttpsURLConnection)ReflectionUtil.setAccessible(f2)
.get(c);
ReflectionUtil.setAccessible(f).set(c2, httpRequestMethod);
} catch (Throwable t) {
logStackTrace(t);
}
}
ReflectionUtil.setAccessible(f).set(connection, httpRequestMethod);
message.put(HTTPURL_CONNECTION_METHOD_REFLECTION, true);
} catch (Throwable t) {
logStackTrace(t);
throw ex;
}
}
これでいくつかの希望が得られたので、コードを読むのに時間を費やし、URLConnectionHTTPConduit.HTTPURL_CONNECTION_METHOD_REFLECTIONのプロパティを指定すると、cxfで例外ハンドラーを実行できることがわかりました。デフォルトでは、変数は次のようになります。以下のコードのためにfalseに割り当てられました
DEFAULT_USE_REFLECTION =
Boolean.valueOf(SystemPropertyAction.getProperty(HTTPURL_CONNECTION_METHOD_REFLECTION, "false"));
これが、この作業を行うために私たちがしなければならなかったことです
WebClient.getConfig(client).getRequestContext().put("use.httpurlconnection.method.reflection", true);
または
WebClient.getConfig(client).getRequestContext().put(HTTPURL_CONNECTION_METHOD_REFLECTION, true);
WebClientはcxfライブラリ自体からのものです。
この答えが誰かを助けることを願っています。