Wir haben das gleiche Problem mit leicht unterschiedlichem Verhalten konfrontiert. Wir haben die Apache-CXF-Bibliothek verwendet, um die restlichen Anrufe zu tätigen. Für uns funktionierte PATCH einwandfrei, bis wir mit unseren gefälschten Diensten sprachen, die über http funktionierten. In dem Moment, in dem wir uns in tatsächliche Systeme integriert haben (die über https lagen), hatten wir das gleiche Problem mit der folgenden Stapelverfolgung.
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]
In dieser Codezeile ist ein Problem aufgetreten
connection.setRequestMethod(httpRequestMethod); in URLConnectionHTTPConduit class of cxf library
Der wahre Grund für das Scheitern ist das
java.net.HttpURLConnection contains a methods variable which looks like below
private static final String[] methods = {
"GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
};
Und wir können sehen, dass keine PATCH-Methode definiert ist, daher machte der Fehler Sinn. Wir haben viele verschiedene Dinge ausprobiert und uns den Stapelüberlauf angesehen. Die einzig vernünftige Antwort bestand darin, die Methodenvariable mithilfe der Reflexion zu ändern, um einen weiteren Wert "PATCH" einzufügen. Aber irgendwie waren wir nicht davon überzeugt, dies zu verwenden, da die Lösung eine Art Hack war und zu viel Arbeit ist und Auswirkungen haben könnte, da wir eine gemeinsame Bibliothek hatten, um alle Verbindungen herzustellen und diese REST-Aufrufe auszuführen.
Aber dann haben wir festgestellt, dass die cxf-Bibliothek selbst die Ausnahme behandelt und im catch-Block Code geschrieben ist, um die fehlende Methode mithilfe von Reflection hinzuzufügen.
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;
}
}
Dies gab uns einige Hoffnungen, so dass wir einige Zeit mit dem Lesen des Codes verbracht haben und festgestellt haben, dass wir, wenn wir eine Eigenschaft für URLConnectionHTTPConduit.HTTPURL_CONNECTION_METHOD_REFLECTION bereitstellen, cxf zum Ausführen des Ausnahmebehandlungsprogramms verwenden können und unsere Arbeit standardmäßig ausgeführt wird aufgrund des folgenden Codes false zugewiesen
DEFAULT_USE_REFLECTION =
Boolean.valueOf(SystemPropertyAction.getProperty(HTTPURL_CONNECTION_METHOD_REFLECTION, "false"));
Hier ist also, was wir tun mussten, damit dies funktioniert
WebClient.getConfig(client).getRequestContext().put("use.httpurlconnection.method.reflection", true);
oder
WebClient.getConfig(client).getRequestContext().put(HTTPURL_CONNECTION_METHOD_REFLECTION, true);
Wo WebClient aus der cxf-Bibliothek selbst stammt.
Hoffe diese Antwort hilft jemandem.