2015-04-04 12 views
14

Ich habe die folgende Definition für PersonDTO:RestTemplate PATCH Anfrage

public class PersonDTO 
{ 
    private String id 
    private String firstName; 
    private String lastName; 
    private String maritalStatus; 
} 

Hier ist ein Beispieldatensatz:

{ 
    "id": 1, 
    "firstName": "John", 
    "lastName": "Doe", 
    "maritalStatus": "married" 
} 

Nun, John Doe geschieden wird. Also brauche ich eine PATCH Anforderung an diese URL senden:

http://localhost:8080/people/1 

Mit dem folgenden Anfrage Körper:

{ 
    "maritalStatus": "divorced" 
} 

Ich kann nicht herausfinden, wie es zu tun. Hier ist, was ich bisher versucht:

// Create Person 
PersonDTO person = new PersonDTO(); 
person.setMaritalStatus("Divorced"); 

// Create HttpEntity 
final HttpEntity<ObjectNode> requestEntity = new HttpEntity<>(person); 

// Create URL (for eg: localhost:8080/people/1) 
final URI url = buildUri(id); 

ResponseEntity<Void> responseEntity = restTemplate.exchange(url, HttpMethod.PATCH, requestEntity, Void.class); 

Hier sind die Probleme mit dem oben:

1) Da ich nur MaritalStatus bin die Einrichtung, die anderen Felder alle null sein würde. Also, wenn ich aus dem Antrag drucken, wird es wie folgt aussehen:

{ 
    "id": null, 
    "firstName": "null", 
    "lastName": "null", 
    "maritalStatus": "married" // I only need to update this field. 
} 

das bedeutet, dass ich auf eine GET haben, bevor ich einen Patch zu tun?

2) Ich erhalte den folgenden Stack-Trace:

08:48:52.717 ERROR c.n.d.t.s.PersonServiceImpl - Unexpected Exception : 
org.springframework.web.client.ResourceAccessException: I/O error on PATCH request for "http://localhost:8080/people/1":Invalid HTTP method: PATCH; nested exception is java.net.ProtocolException: Invalid HTTP method: PATCH 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:580) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:545) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:466) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at com.sp.restclientexample..service.PersonServiceImpl.doPatch(PersonServiceImpl.java:75) ~[classes/:na] 
    at com.sp.restclientexample..service.PatchTitle.itDoPatch(PatchTitle.java:53) [test-classes/:na] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_20] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_20] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_20] 
    at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_20] 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) [junit-4.12.jar:4.12] 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12] 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) [junit-4.12.jar:4.12] 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.12.jar:4.12] 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:73) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12] 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:224) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12] 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12] 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12] 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12] 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12] 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12] 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163) [spring-test-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) [.cp/:na] 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) [.cp/:na] 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) [.cp/:na] 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) [.cp/:na] 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) [.cp/:na] 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) [.cp/:na] 
Caused by: java.net.ProtocolException: Invalid HTTP method: PATCH 
    at java.net.HttpURLConnection.setRequestMethod(HttpURLConnection.java:440) ~[na:1.8.0_20] 
    at sun.net.www.protocol.http.HttpURLConnection.setRequestMethod(HttpURLConnection.java:517) ~[na:1.8.0_20] 
    at org.springframework.http.client.SimpleClientHttpRequestFactory.prepareConnection(SimpleClientHttpRequestFactory.java:209) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:138) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.java:76) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:565) ~[spring-web-4.1.6.RELEASE.jar:4.1.6.RELEASE] 
    ... 33 common frames omitted 

Schätzen Sie alle Hinweise von Leuten, die Client-Anwendungen geschrieben hat eine Restful webservice mit Spring RestTemplate zu konsumieren.

Der Vollständigkeit halber möchte ich noch sagen, dass wir SpringDataRest für unsere Backend-Webservices verwenden.

SGB

Antwort

29

Ich löste dieses Problem nur eine neue HttpRequestFactory meiner restTemplate Instanz hinzufügen. Gefällt Ihnen dieses

RestTemplate restTemplate = new RestTemplate(); 

HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); 
requestFactory.setConnectTimeout(TIMEOUT); 
requestFactory.setReadTimeout(TIMEOUT); 

restTemplate.setRequestFactory(requestFactory); 

PS: In Kürze erhalten Sie benötigen Httpclient-Komponente in Ihrem Projekt hinzufügen

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

Um einige Zeilen zu speichern, können Sie die RestTemplate-Initialisierung in einer Zeile ausführen 'new RestTemplate (new HttpComponentsClientHttpRequestFactory())' – adebasi

+0

@adebasi Wissen Sie, warum dies erforderlich ist? – peterl

+1

Ich denke mit "das" meinen Sie die Tatsache, dass Sie die 'HttpComponentsClientHttpRequestFactory' einstellen müssen. Dieser Beitrag (https://jira.spring.io/browse/SPR-7985?focusedCommentId=80924&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-80924) beantwortet Ihre Frage. – adebasi

0

Für Fälle, in denen RestTemplate von einem RestTemplateBuilder gebaut wird, Konstruktor für die benutzerdefinierte RestClient kann geschrieben werden,

public PersonRestClient(RestTemplateBuilder restTemplateBuilder) { 
    this.restTemplate = restTemplateBuilder.requestFactory(new HttpComponentsClientHttpRequestFactory()).build(); 
} 

Auch die org.apache.httpcomponents.httpclient Abhängigkeit muss zu Pom hinzugefügt werden.

Verwandte Themen