HttpURLConnection Invalid HTTP method: PATCH

If the project is on Spring/Gradle; the following solution will workout.

For the build.gradle, add the following dependency;

compile('org.apache.httpcomponents:httpclient:4.5.2')

And define the following bean in your @SpringBootApplication class inside the com.company.project;

 @Bean
 public RestTemplate restTemplate() {
  HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
  requestFactory.setReadTimeout(600000);
  requestFactory.setConnectTimeout(600000);
  return new RestTemplate(requestFactory);
 }

This solutions worked for me.


There are a lot of good answers, so here is mine (not work in jdk12):

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;

public class SupportPatch {
    public static void main(String... args) throws IOException {
        allowMethods("PATCH");

        HttpURLConnection conn = (HttpURLConnection) new URL("http://example.com").openConnection();
        conn.setRequestMethod("PATCH");
    }

    private static void allowMethods(String... methods) {
        try {
            Field methodsField = HttpURLConnection.class.getDeclaredField("methods");

            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            modifiersField.setInt(methodsField, methodsField.getModifiers() & ~Modifier.FINAL);

            methodsField.setAccessible(true);

            String[] oldMethods = (String[]) methodsField.get(null);
            Set<String> methodsSet = new LinkedHashSet<>(Arrays.asList(oldMethods));
            methodsSet.addAll(Arrays.asList(methods));
            String[] newMethods = methodsSet.toArray(new String[0]);

            methodsField.set(null/*static field*/, newMethods);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new IllegalStateException(e);
        }
    }
}

It also uses reflection, but instead of hacking into every connection object we're hacking HttpURLConnection#methods static field which is used in the checks internally.


Yes there is workaround for this. Use

X-HTTP-Method-Override

. This header can be used in a POST request to “fake” other HTTP methods. Simply set the value of the X-HTTP-Method-Override header to the HTTP method you would like to actually perform. So use following code.

conn.setRequestProperty("X-HTTP-Method-Override", "PATCH");
conn.setRequestMethod("POST");

There is a Won't Fix bug in OpenJDK for this: https://bugs.openjdk.java.net/browse/JDK-7016595

However, with Apache Http-Components Client 4.2+ this is possible. It has a custom networking implementation, thus using all standard HTTP methods like PATCH is possible. It even has a HttpPatch class supporting the patch method.

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPatch httpPatch = new HttpPatch(new URI("http://example.com"));
CloseableHttpResponse response = httpClient.execute(httpPatch);

Maven Coordinates:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.2+</version>
</dependency>