From: Jaroslav Tóth Date: Wed, 27 Mar 2019 11:52:22 +0000 (+0100) Subject: Output-less RPCs should return 204 (new restconf) X-Git-Tag: release/sodium~91 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=751ee3722c8009fc6979bed8790d5f8d1d4d3ec4;p=netconf.git Output-less RPCs should return 204 (new restconf) - RFC-8040 (4.4.2 - Invoke Operation Mode): "If the POST request succeeds, a "200 OK" status-line is returned if there is a response message-body, and a "204 No Content" status-line is returned if there is no response message-body." The example in RFC confirms on specific RPC without output (also in section 4.4.2). - Restconf RFC 8040 RPC handler is modified so it is checked against empty data in output container. If there is no data child under otuput container, WebApplicationException with status code 204 is thrown. Change-Id: I3e9396db8096571719ad7947cb46f6196cc54532 JIRA: NETCONF-366 Signed-off-by: Jaroslav Tóth --- diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfInvokeOperationsServiceImpl.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfInvokeOperationsServiceImpl.java index deb3fd160f..55c6be3d8d 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfInvokeOperationsServiceImpl.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfInvokeOperationsServiceImpl.java @@ -9,6 +9,8 @@ package org.opendaylight.restconf.nb.rfc8040.rests.services.impl; import java.net.URI; import javax.ws.rs.Path; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.opendaylight.mdsal.dom.api.DOMMountPoint; import org.opendaylight.mdsal.dom.api.DOMRpcResult; @@ -24,6 +26,7 @@ import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfInvokeOpe import org.opendaylight.restconf.nb.rfc8040.rests.utils.CreateStreamUtil; import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfInvokeOperationsUtil; import org.opendaylight.restconf.nb.rfc8040.rests.utils.RestconfStreamsConstants; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaPath; @@ -92,7 +95,12 @@ public class RestconfInvokeOperationsServiceImpl implements RestconfInvokeOperat resultData = result.getResult(); resultNodeSchema = (RpcDefinition) payload.getInstanceIdentifierContext().getSchemaNode(); } - return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, resultNodeSchema, - mountPoint, schemaContextRef.get()), resultData); + + if (resultData != null && ((ContainerNode) resultData).getValue().isEmpty()) { + throw new WebApplicationException(Response.Status.NO_CONTENT); + } else { + return new NormalizedNodeContext(new InstanceIdentifierContext<>(null, resultNodeSchema, + mountPoint, schemaContextRef.get()), resultData); + } } } diff --git a/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfInvokeOperationsServiceImplTest.java b/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfInvokeOperationsServiceImplTest.java index 1508efaab0..31f6229957 100644 --- a/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfInvokeOperationsServiceImplTest.java +++ b/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/rests/services/impl/RestconfInvokeOperationsServiceImplTest.java @@ -13,7 +13,11 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture; +import java.util.Collections; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; @@ -32,6 +36,8 @@ import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler; import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler; import org.opendaylight.restconf.nb.rfc8040.references.SchemaContextRef; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.model.api.RpcDefinition; import org.opendaylight.yangtools.yang.model.api.SchemaPath; @@ -69,9 +75,12 @@ public class RestconfInvokeOperationsServiceImplTest { } @Test - public void testInvokeRpc() throws Exception { + public void testInvokeRpcWithNonEmptyOutput() { final String identifier = "invoke-rpc-module:rpcTest"; - final NormalizedNode result = mock(NormalizedNode.class); + final ContainerNode result = mock(ContainerNode.class); + final LeafNode outputChild = mock(LeafNode.class); + when(result.getValue()).thenReturn(Collections.singleton(outputChild)); + final NormalizedNodeContext payload = prepNNC(result); final UriInfo uriInfo = mock(UriInfo.class); @@ -79,6 +88,25 @@ public class RestconfInvokeOperationsServiceImplTest { assertEquals(result, rpc.getData()); } + @Test + public void testInvokeRpcWithEmptyOutput() { + final String identifier = "invoke-rpc-module:rpcTest"; + final ContainerNode result = mock(ContainerNode.class); + + final NormalizedNodeContext payload = prepNNC(result); + final UriInfo uriInfo = mock(UriInfo.class); + + WebApplicationException exceptionToBeThrown = null; + try { + this.invokeOperationsService.invokeRpc(identifier, payload, uriInfo); + } catch (final WebApplicationException exception) { + exceptionToBeThrown = exception; + + } + Assert.assertNotNull("WebApplicationException with status code 204 is expected.", exceptionToBeThrown); + Assert.assertEquals(Response.Status.NO_CONTENT.getStatusCode(), exceptionToBeThrown.getResponse().getStatus()); + } + private NormalizedNodeContext prepNNC(final NormalizedNode result) { final InstanceIdentifierContext context = mock(InstanceIdentifierContext.class); final RpcDefinition schemaNode = mock(RpcDefinition.class);