Updated Branches: refs/heads/master e5e5a7286 -> 38afedd2b
ISIS-233: fix url encoding handling on PUT. tried to always url decode, even for arguments that went in the body and so were not encoded. Project: http://git-wip-us.apache.org/repos/asf/isis/repo Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/38afedd2 Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/38afedd2 Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/38afedd2 Branch: refs/heads/master Commit: 38afedd2b7f27073dbe6ae7ed10ce70d6f8a1eac Parents: e5e5a72 Author: Dan Haywood <[email protected]> Authored: Tue May 7 19:13:29 2013 +0100 Committer: Dan Haywood <[email protected]> Committed: Tue May 7 19:13:29 2013 +0100 ---------------------------------------------------------------------- .../restfulobjects/server/ResourceContext.java | 8 ++ .../server/resources/DomainResourceHelper.java | 10 ++- .../resources/DomainTypeResourceServerside.java | 4 +- ...enRepresentation_doesNotContainSelfLink_ok.java | 15 +-- .../action/invoke/Put_whenStringArgs_then_ok.java | 89 +++++++++++++++ .../tck/dom/actions/ActionsEntityRepository.java | 8 ++ 6 files changed, 118 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/isis/blob/38afedd2/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/ResourceContext.java ---------------------------------------------------------------------- diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/ResourceContext.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/ResourceContext.java index bf2fd54..16edd2c 100644 --- a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/ResourceContext.java +++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/ResourceContext.java @@ -163,6 +163,14 @@ public class ResourceContext implements RendererContext { return httpHeaders; } + /** + * The {@link HttpServletRequest#getQueryString() query string}, cached + * after first call. + * + * <p> + * Note that this can return non-null for <tt>PUT</tt>s as well as <tt>GET</tt>s. + * It will only have been URL encoded for the latter; the caller should handle both cases. + */ public String getQueryString() { if(queryString != null) { return queryString; http://git-wip-us.apache.org/repos/asf/isis/blob/38afedd2/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java ---------------------------------------------------------------------- diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java index d965aea..33e8406 100644 --- a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java +++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java @@ -550,7 +550,15 @@ public final class DomainResourceHelper { if (queryStringTrimmed.isEmpty()) { return JsonRepresentation.newMap(); } - final String queryStringUrlDecoded = UrlEncodingUtils.urlDecode(queryStringTrimmed); + + String queryStringUrlDecoded; + try { + // this is a bit hacky... + queryStringUrlDecoded = UrlEncodingUtils.urlDecode(queryStringTrimmed); + } catch(Exception ex) { + queryStringUrlDecoded = queryStringTrimmed; + } + if (queryStringUrlDecoded.isEmpty()) { return JsonRepresentation.newMap(); } http://git-wip-us.apache.org/repos/asf/isis/blob/38afedd2/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainTypeResourceServerside.java ---------------------------------------------------------------------- diff --git a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainTypeResourceServerside.java b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainTypeResourceServerside.java index 1d2de44..5865857 100644 --- a/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainTypeResourceServerside.java +++ b/component/viewer/restfulobjects/server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainTypeResourceServerside.java @@ -28,6 +28,8 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import com.google.common.base.Strings; + import org.apache.isis.applib.annotation.Where; import org.apache.isis.core.metamodel.spec.ObjectSpecId; import org.apache.isis.core.metamodel.spec.ObjectSpecification; @@ -57,8 +59,6 @@ import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.TypeListReprR import org.apache.isis.viewer.restfulobjects.server.RestfulObjectsApplicationException; import org.apache.isis.viewer.restfulobjects.server.util.UrlParserUtils; -import com.google.common.base.Strings; - /** * Implementation note: it seems to be necessary to annotate the implementation * with {@link Path} rather than the interface (at least under RestEasy 1.0.2 http://git-wip-us.apache.org/repos/asf/isis/blob/38afedd2/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainobjectorservice/id/action/invoke/Put_thenRepresentation_doesNotContainSelfLink_ok.java ---------------------------------------------------------------------- diff --git a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainobjectorservice/id/action/invoke/Put_thenRepresentation_doesNotContainSelfLink_ok.java b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainobjectorservice/id/action/invoke/Put_thenRepresentation_doesNotContainSelfLink_ok.java index 70f09d2..c0f394b 100644 --- a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainobjectorservice/id/action/invoke/Put_thenRepresentation_doesNotContainSelfLink_ok.java +++ b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainobjectorservice/id/action/invoke/Put_thenRepresentation_doesNotContainSelfLink_ok.java @@ -1,34 +1,23 @@ package org.apache.isis.viewer.restfulobjects.tck.domainobjectorservice.id.action.invoke; -import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.assertThat; -import static org.apache.isis.viewer.restfulobjects.tck.RestfulMatchers.isLink; -import static org.hamcrest.CoreMatchers.*; -import static org.hamcrest.CoreMatchers.endsWith; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; -import java.io.IOException; -import java.io.InputStream; - import javax.ws.rs.core.Response; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.map.JsonMappingException; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation; import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation; -import org.apache.isis.viewer.restfulobjects.applib.Rel; -import org.apache.isis.viewer.restfulobjects.applib.RepresentationType; -import org.apache.isis.viewer.restfulobjects.applib.RestfulHttpMethod; import org.apache.isis.viewer.restfulobjects.applib.client.RestfulClient; import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse; import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation; import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainServiceResource; import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ObjectActionRepresentation; import org.apache.isis.viewer.restfulobjects.applib.util.JsonNodeUtils; -import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils; import org.apache.isis.viewer.restfulobjects.tck.IsisWebServerRule; import org.apache.isis.viewer.restfulobjects.tck.Util; http://git-wip-us.apache.org/repos/asf/isis/blob/38afedd2/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainobjectorservice/id/action/invoke/Put_whenStringArgs_then_ok.java ---------------------------------------------------------------------- diff --git a/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainobjectorservice/id/action/invoke/Put_whenStringArgs_then_ok.java b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainobjectorservice/id/action/invoke/Put_whenStringArgs_then_ok.java new file mode 100644 index 0000000..2e86969 --- /dev/null +++ b/component/viewer/restfulobjects/tck/src/test/java/org/apache/isis/viewer/restfulobjects/tck/domainobjectorservice/id/action/invoke/Put_whenStringArgs_then_ok.java @@ -0,0 +1,89 @@ +package org.apache.isis.viewer.restfulobjects.tck.domainobjectorservice.id.action.invoke; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +import javax.ws.rs.core.Response; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation; +import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation; +import org.apache.isis.viewer.restfulobjects.applib.client.RestfulClient; +import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse; +import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.HttpStatusCode; +import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ActionResultRepresentation; +import org.apache.isis.viewer.restfulobjects.applib.domainobjects.DomainServiceResource; +import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ObjectActionRepresentation; +import org.apache.isis.viewer.restfulobjects.applib.domainobjects.ScalarValueRepresentation; +import org.apache.isis.viewer.restfulobjects.applib.errors.ErrorRepresentation; +import org.apache.isis.viewer.restfulobjects.applib.util.JsonNodeUtils; +import org.apache.isis.viewer.restfulobjects.tck.IsisWebServerRule; +import org.apache.isis.viewer.restfulobjects.tck.Util; + +public class Put_whenStringArgs_then_ok { + + @Rule + public IsisWebServerRule webServerRule = new IsisWebServerRule(); + + private RestfulClient client; + + private DomainServiceResource serviceResource; + + @Before + public void setUp() throws Exception { + client = webServerRule.getClient(); + + serviceResource = client.getDomainServiceResource(); + } + + @Test + public void usingClientFollow() throws Exception { + + // given + final JsonRepresentation givenAction = Util.givenAction(client, "ActionsEntities", "concatenate"); + final ObjectActionRepresentation actionRepr = givenAction.as(ObjectActionRepresentation.class); + + final LinkRepresentation invokeLink = actionRepr.getInvoke(); + final JsonRepresentation args =invokeLink.getArguments(); + + // when + args.mapPut("str1.value", "IVA VENDITE 21%"); + args.mapPut("str2.value", "AAA"); + + // when + final RestfulResponse<ActionResultRepresentation> restfulResponse = client.followT(invokeLink, args); + + // then + then(restfulResponse); + } + + + + @Test + public void usingResourceProxy() throws Exception { + + // given, when + final JsonRepresentation args = JsonRepresentation.newMap(); + args.mapPut("str1.value", "IVA VENDITE 21%"); + args.mapPut("str2.value", "AAA"); + + final Response response = serviceResource.invokeActionIdempotent("ActionsEntities", "concatenate", JsonNodeUtils.asInputStream(args)); + final RestfulResponse<ActionResultRepresentation> restfulResponse = RestfulResponse.ofT(response); + + // then + then(restfulResponse); + } + + private void then(RestfulResponse<ActionResultRepresentation> restfulResponse) throws Exception { + assertThat(restfulResponse.getStatus(), is(HttpStatusCode.OK)); + final ActionResultRepresentation entity = restfulResponse.getEntity(); + final ScalarValueRepresentation svr = entity.getResult().as(ScalarValueRepresentation.class); + assertThat(svr.getValue().asString(), is("IVA VENDITE 21%AAA")); + } + +} http://git-wip-us.apache.org/repos/asf/isis/blob/38afedd2/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/actions/ActionsEntityRepository.java ---------------------------------------------------------------------- diff --git a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/actions/ActionsEntityRepository.java b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/actions/ActionsEntityRepository.java index 65c07f7..632abd1 100644 --- a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/actions/ActionsEntityRepository.java +++ b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/actions/ActionsEntityRepository.java @@ -119,4 +119,12 @@ public class ActionsEntityRepository extends AbstractEntityRepository<ActionsEnt private static int valueElseDefault(Integer value, int i) { return value != null? value: i; } + + @ActionSemantics(Of.IDEMPOTENT) + @MemberOrder(sequence = "90") + public String concatenate(@Named("str1") String str1, @Named("str2") String str2) { + return str1 + str2; + } + + }
