हमने थोड़े अलग व्यवहार के साथ एक ही समस्या का सामना किया है। बाकी कॉल करने के लिए हम अपाचे cxf लाइब्रेरी का उपयोग कर रहे थे। हमारे लिए, 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 विधि परिभाषित नहीं है इसलिए त्रुटि हुई। हमने बहुत सी अलग-अलग चीजों की कोशिश की और स्टैक ओवरफ्लो देखा। एकमात्र उचित उत्तर एक और मूल्य "पैटच" को इंजेक्ट करने के लिए तरीकों के चर को संशोधित करने के लिए प्रतिबिंब का उपयोग करना था। लेकिन किसी भी तरह से हम इसका उपयोग करने के लिए आश्वस्त नहीं थे क्योंकि समाधान हैक की तरह था और बहुत अधिक काम है और इसका प्रभाव हो सकता है क्योंकि हमारे पास सभी कनेक्शन बनाने और इन REST कॉल करने के लिए सामान्य पुस्तकालय था।
लेकिन तब हमें एहसास हुआ कि cxf लाइब्रेरी खुद अपवाद को संभाल रही है और प्रतिबिंब का उपयोग करके लापता विधि को जोड़ने के लिए कैच ब्लॉक में कोड लिखा है।
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 बना सकते हैं और हमारा काम वैसा ही होगा जैसा कि डिफ़ॉल्ट रूप से होगा। नीचे दिए गए कोड के कारण गलत को सौंपा गया
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 लाइब्रेरी से ही है।
आशा है कि यह उत्तर कुछ मदद करता है।