Merge lp:~tjoneslo/akiban-server/fix-bug-1163967 into lp:~akiban-technologies/akiban-server/trunk

Proposed by Thomas Jones-Low
Status: Merged
Approved by: Nathan Williams
Approved revision: 2610
Merged at revision: 2609
Proposed branch: lp:~tjoneslo/akiban-server/fix-bug-1163967
Merge into: lp:~akiban-technologies/akiban-server/trunk
Diff against target: 187 lines (+54/-24)
10 files modified
src/main/java/com/akiban/rest/RestResponseBuilder.java (+11/-3)
src/main/java/com/akiban/rest/resources/BuilderResource.java (+10/-10)
src/main/java/com/akiban/rest/resources/EntityResource.java (+9/-9)
src/main/java/com/akiban/server/service/restdml/RestDMLService.java (+1/-1)
src/main/java/com/akiban/server/service/restdml/RestDMLServiceImpl.java (+1/-1)
src/test/java/com/akiban/rest/RestServiceFilesIT.java (+16/-0)
src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.delete (+1/-0)
src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.expected (+1/-0)
src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.expected_header (+2/-0)
src/test/resources/com/akiban/rest/caoi/delete-c1.expected_header (+2/-0)
To merge this branch: bzr merge lp:~tjoneslo/akiban-server/fix-bug-1163967
Reviewer Review Type Date Requested Status
Nathan Williams Approve
Thomas Jones-Low Needs Resubmitting
Review via email: mp+156904@code.launchpad.net

Description of the change

Fix bug 1163967 - Update the delete processing for both the entity and the builder to return no body and a 204 (no content) status code.

Exposed the RestResponseBuilder#wrapException() method to allow the Delete processing to correctly and consistently return errors when they occur.

To post a comment you must log in.
Revision history for this message
Nathan Williams (nwilliams) wrote :

RestResponseBuilder already has some handling for NO_CONTENT, but just not enough. Additionally, it will do jsonp automatically.

Perhaps just tweaking build() and/or createStreamingOutput() would be sufficient?

Revision history for this message
Thomas Jones-Low (tjoneslo) wrote :

Unfortunately, not quite that simple. The call Response.ResponseBuilder#entity() helpfully resets the response code from 204 to 200, even if the entity is an empty string. So we need to have a second code path for executing the rest response (i.e. the delete) if we expect the response to really read 204.

Update the RestServiceFilesIT to read through and compare header and response codes to verify the delete is returning correct response.

Fix the RestResponseBuilder to correctly handle the NO_CONTENT case, and handle jsonp settings for delete.

review: Needs Resubmitting
Revision history for this message
Nathan Williams (nwilliams) wrote :

How nice of it.

Was there a new .expected_header you added to one of the DELETE tests?

Revision history for this message
Thomas Jones-Low (tjoneslo) wrote :

Yes now adding new test (delete with jsonp) and header for existing test.

review: Needs Resubmitting
Revision history for this message
Nathan Williams (nwilliams) wrote :

Excellent. Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/main/java/com/akiban/rest/RestResponseBuilder.java'
--- src/main/java/com/akiban/rest/RestResponseBuilder.java 2013-03-22 20:05:57 +0000
+++ src/main/java/com/akiban/rest/RestResponseBuilder.java 2013-04-03 20:23:21 +0000
@@ -95,7 +95,16 @@
95 if(outputBody == null && outputGenerator == null && jsonp == null) {95 if(outputBody == null && outputGenerator == null && jsonp == null) {
96 status(Response.Status.NO_CONTENT);96 status(Response.Status.NO_CONTENT);
97 }97 }
98 Response.ResponseBuilder builder = Response.status(status).entity(createStreamingOutput());98 if (isJsonp) {
99 status(Response.Status.OK);
100 }
101 Response.ResponseBuilder builder;
102
103 if (this.status == Response.Status.NO_CONTENT.getStatusCode()) {
104 builder = Response.status(status);
105 } else {
106 builder = Response.status(status).entity(createStreamingOutput());
107 }
99 if(isJsonp) {108 if(isJsonp) {
100 builder.type(ResourceHelper.APPLICATION_JAVASCRIPT_TYPE);109 builder.type(ResourceHelper.APPLICATION_JAVASCRIPT_TYPE);
101 }110 }
@@ -125,7 +134,7 @@
125 return builder.toString();134 return builder.toString();
126 }135 }
127136
128 private WebApplicationException wrapException(Throwable e) {137 public WebApplicationException wrapException(Throwable e) {
129 final ErrorCode code;138 final ErrorCode code;
130 if(e instanceof InvalidOperationException) {139 if(e instanceof InvalidOperationException) {
131 code = ((InvalidOperationException)e).getCode();140 code = ((InvalidOperationException)e).getCode();
@@ -180,7 +189,6 @@
180 };189 };
181 }190 }
182191
183
184 private static Map<Class, Response.Status> buildExceptionStatusMap() {192 private static Map<Class, Response.Status> buildExceptionStatusMap() {
185 Map<Class, Response.Status> map = new HashMap<>();193 Map<Class, Response.Status> map = new HashMap<>();
186 map.put(NoSuchTableException.class, Response.Status.NOT_FOUND);194 map.put(NoSuchTableException.class, Response.Status.NOT_FOUND);
187195
=== modified file 'src/main/java/com/akiban/rest/resources/BuilderResource.java'
--- src/main/java/com/akiban/rest/resources/BuilderResource.java 2013-03-26 20:55:25 +0000
+++ src/main/java/com/akiban/rest/resources/BuilderResource.java 2013-04-03 20:23:21 +0000
@@ -151,16 +151,16 @@
151 @Context final UriInfo uri) {151 @Context final UriInfo uri) {
152 final TableName tableName = parseTableName(request, entityName);152 final TableName tableName = parseTableName(request, entityName);
153 checkTableAccessible(securityService, request, tableName);153 checkTableAccessible(securityService, request, tableName);
154 return RestResponseBuilder154 try {
155 .forRequest(request)155 modelBuilder.create(tableName);
156 .body(new RestResponseBuilder.BodyGenerator() {156 restDMLService.delete(tableName, getPKString(uri));
157 @Override157 return RestResponseBuilder
158 public void write(PrintWriter writer) throws Exception {158 .forRequest(request)
159 modelBuilder.create(tableName);159 .status(Response.Status.NO_CONTENT)
160 restDMLService.delete(writer, tableName, getPKString(uri));160 .build();
161 }161 } catch (Exception e) {
162 })162 throw RestResponseBuilder.forRequest(request).wrapException(e);
163 .build();163 }
164 }164 }
165165
166 @GET166 @GET
167167
=== modified file 'src/main/java/com/akiban/rest/resources/EntityResource.java'
--- src/main/java/com/akiban/rest/resources/EntityResource.java 2013-03-26 18:08:04 +0000
+++ src/main/java/com/akiban/rest/resources/EntityResource.java 2013-04-03 20:23:21 +0000
@@ -182,14 +182,14 @@
182 @Context final UriInfo uri) {182 @Context final UriInfo uri) {
183 final TableName tableName = parseTableName(request, entity);183 final TableName tableName = parseTableName(request, entity);
184 checkTableAccessible(reqs.securityService, request, tableName);184 checkTableAccessible(reqs.securityService, request, tableName);
185 return RestResponseBuilder185 try {
186 .forRequest(request)186 reqs.restDMLService.delete(tableName, getPKString(uri));
187 .body(new RestResponseBuilder.BodyGenerator() {187 return RestResponseBuilder
188 @Override188 .forRequest(request)
189 public void write(PrintWriter writer) throws Exception {189 .status(Response.Status.NO_CONTENT)
190 reqs.restDMLService.delete(writer, tableName, getPKString(uri));190 .build();
191 }191 } catch (Exception e) {
192 })192 throw RestResponseBuilder.forRequest(request).wrapException(e);
193 .build();193 }
194 }194 }
195}195}
196196
=== modified file 'src/main/java/com/akiban/server/service/restdml/RestDMLService.java'
--- src/main/java/com/akiban/server/service/restdml/RestDMLService.java 2013-03-25 22:52:39 +0000
+++ src/main/java/com/akiban/server/service/restdml/RestDMLService.java 2013-04-03 20:23:21 +0000
@@ -33,7 +33,7 @@
33 public void getAllEntities(PrintWriter writer, TableName tableName, Integer depth);33 public void getAllEntities(PrintWriter writer, TableName tableName, Integer depth);
34 public void getEntities(PrintWriter writer, TableName tableName, Integer depth, String pks);34 public void getEntities(PrintWriter writer, TableName tableName, Integer depth, String pks);
35 public void insert(PrintWriter writer, TableName tableName, JsonNode node);35 public void insert(PrintWriter writer, TableName tableName, JsonNode node);
36 public void delete(PrintWriter writer, TableName tableName, String pks);36 public void delete(TableName tableName, String pks);
37 public void update(PrintWriter writer, TableName tableName, String values, JsonNode node);37 public void update(PrintWriter writer, TableName tableName, String values, JsonNode node);
3838
39 public void insertNoTxn(Session session, PrintWriter writer, TableName tableName, JsonNode node);39 public void insertNoTxn(Session session, PrintWriter writer, TableName tableName, JsonNode node);
4040
=== modified file 'src/main/java/com/akiban/server/service/restdml/RestDMLServiceImpl.java'
--- src/main/java/com/akiban/server/service/restdml/RestDMLServiceImpl.java 2013-03-25 22:52:39 +0000
+++ src/main/java/com/akiban/server/service/restdml/RestDMLServiceImpl.java 2013-04-03 20:23:21 +0000
@@ -182,7 +182,7 @@
182 }182 }
183183
184 @Override184 @Override
185 public void delete(PrintWriter writer, TableName tableName, String identifier) {185 public void delete(TableName tableName, String identifier) {
186 try (Session session = sessionService.createSession();186 try (Session session = sessionService.createSession();
187 CloseableTransaction txn = transactionService.beginCloseableTransaction(session)) {187 CloseableTransaction txn = transactionService.beginCloseableTransaction(session)) {
188 AkibanInformationSchema ais = dxlService.ddlFunctions().getAIS(session);188 AkibanInformationSchema ais = dxlService.ddlFunctions().getAIS(session);
189189
=== modified file 'src/test/java/com/akiban/rest/RestServiceFilesIT.java'
--- src/test/java/com/akiban/rest/RestServiceFilesIT.java 2013-03-26 18:24:46 +0000
+++ src/test/java/com/akiban/rest/RestServiceFilesIT.java 2013-04-03 20:23:21 +0000
@@ -253,6 +253,9 @@
253 if(!caseParams.expectedIgnore) {253 if(!caseParams.expectedIgnore) {
254 compareExpected(caseParams.requestMethod + " response", caseParams.expectedResponse, actual);254 compareExpected(caseParams.requestMethod + " response", caseParams.expectedResponse, actual);
255 }255 }
256 if (caseParams.expectedHeader != null) {
257 compareHeaders(httpConn, caseParams.expectedHeader);
258 }
256 } finally {259 } finally {
257 fullyDisconnect(httpConn);260 fullyDisconnect(httpConn);
258 }261 }
@@ -305,6 +308,19 @@
305 assertEquals(assertMsg, expectedNode, actualNode);308 assertEquals(assertMsg, expectedNode, actualNode);
306 }309 }
307 }310 }
311
312 private void compareHeaders (HttpURLConnection httpConn, String checkHeaders) throws Exception {
313 String[] headerList = checkHeaders.split (Strings.NL);
314 for (String header : headerList) {
315 String[] nameValue = header.split(":", 2);
316
317 if (nameValue[0].equals("responseCode")) {
318 assertEquals ("Headers Response", Integer.parseInt(nameValue[1].trim()), httpConn.getResponseCode());
319 } else {
320 assertEquals ("Headers check", nameValue[1].trim(), httpConn.getHeaderField(nameValue[0]));
321 }
322 }
323 }
308324
309 private void fullyDisconnect(HttpURLConnection httpConn) {325 private void fullyDisconnect(HttpURLConnection httpConn) {
310 // If there is a failure, leaving junk in any of the streams can cause cascading issues.326 // If there is a failure, leaving junk in any of the streams can cause cascading issues.
311327
=== added file 'src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.delete'
--- src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.delete 1970-01-01 00:00:00 +0000
+++ src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.delete 2013-04-03 20:23:21 +0000
@@ -0,0 +1,1 @@
1/entity/test.customers/1?callback=delete
0\ No newline at end of file2\ No newline at end of file
13
=== added file 'src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.expected'
--- src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.expected 1970-01-01 00:00:00 +0000
+++ src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.expected 2013-04-03 20:23:21 +0000
@@ -0,0 +1,1 @@
1delete()
0\ No newline at end of file2\ No newline at end of file
13
=== added file 'src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.expected_header'
--- src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.expected_header 1970-01-01 00:00:00 +0000
+++ src/test/resources/com/akiban/rest/caoi/delete-c1-jsonp.expected_header 2013-04-03 20:23:21 +0000
@@ -0,0 +1,2 @@
1responseCode: 200
2Content-Type: application/javascript
0\ No newline at end of file3\ No newline at end of file
14
=== added file 'src/test/resources/com/akiban/rest/caoi/delete-c1.expected_header'
--- src/test/resources/com/akiban/rest/caoi/delete-c1.expected_header 1970-01-01 00:00:00 +0000
+++ src/test/resources/com/akiban/rest/caoi/delete-c1.expected_header 2013-04-03 20:23:21 +0000
@@ -0,0 +1,2 @@
1responseCode: 204
2Content-Type: application/json
0\ No newline at end of file3\ No newline at end of file

Subscribers

People subscribed via source and target branches