Do not use FutureCallbackTx for RPCs and Actions 82/97482/6
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 13 Sep 2021 20:58:59 +0000 (22:58 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 13 Sep 2021 22:31:32 +0000 (00:31 +0200)
FutureCallbackTx is on its way out, use a simple Future.catching() to
peel off the RPC/Action caller's use case. This allows us to move
completion handling closer to JAX-RS without the tangle which is
FutureDataFactory.

JIRA: NETCONF-718
Change-Id: Ie891cef7e33b54d608c15a09a10e75c3fc19de9c
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ActionResultFactory.java [deleted file]
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/FutureCallbackTx.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/RestconfInvokeOperationsUtil.java
restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/RpcResultFactory.java [deleted file]

diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ActionResultFactory.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/ActionResultFactory.java
deleted file mode 100644 (file)
index eda8181..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2019 Ericsson Software Technology AB. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.restconf.nb.rfc8040.rests.utils;
-
-import org.opendaylight.mdsal.dom.api.DOMActionResult;
-import org.opendaylight.yangtools.concepts.Builder;
-
-/**
- * Implementation of {@link ActionResultFactory}.
- */
-public class ActionResultFactory extends FutureDataFactory<DOMActionResult> implements Builder<DOMActionResult> {
-
-    @Override
-    public DOMActionResult build() throws IllegalArgumentException {
-        return this.result;
-    }
-}
index 5d011735147121858783ab03004c74da946ab3d1..5ce8435a8b0d478a2e49d95951fb2477f598e769 100644 (file)
@@ -8,23 +8,16 @@
 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
 
 import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
 import com.google.common.util.concurrent.ListenableFuture;
 import java.util.List;
 import java.util.concurrent.ExecutionException;
 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
-import org.opendaylight.mdsal.dom.api.DOMActionException;
-import org.opendaylight.mdsal.dom.api.DOMRpcException;
-import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
-import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
 import org.opendaylight.netconf.api.DocumentedException;
 import org.opendaylight.netconf.api.NetconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfError;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
-import org.opendaylight.yangtools.yang.common.RpcError;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -87,13 +80,7 @@ final class FutureCallbackTx {
             LOG.warn("Transaction({}) FAILED!", txType, e);
 
             final Throwable cause = e.getCause();
-            if (cause instanceof DOMRpcException) {
-                dataFactory.setResult((T) new DefaultDOMRpcResult(ImmutableList.of(
-                    RpcResultBuilder.newError(RpcError.ErrorType.RPC, "operation-failed", cause.getMessage()))));
-            } else if (cause instanceof DOMActionException) {
-                dataFactory.setResult((T) new SimpleDOMActionResult(ImmutableList.of(
-                    RpcResultBuilder.newError(RpcError.ErrorType.RPC, "operation-failed", cause.getMessage()))));
-            } else if (cause instanceof TransactionCommitFailedException) {
+            if (cause instanceof TransactionCommitFailedException) {
                 /* If device send some error message we want this message to get to client
                    and not just to throw it away or override it with new generic message.
                    We search for NetconfDocumentedException that was send from netconfSB
index 71a5333b924e52b9e749aed8d204703aa8b2b0ba..f9f255d211932c046324b45775b8963b0df033fd 100644 (file)
@@ -7,20 +7,31 @@
  */
 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
 
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMActionException;
 import org.opendaylight.mdsal.dom.api.DOMActionResult;
 import org.opendaylight.mdsal.dom.api.DOMActionService;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
+import org.opendaylight.mdsal.dom.api.DOMRpcException;
 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
 import org.opendaylight.mdsal.dom.api.DOMRpcService;
+import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
+import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.opendaylight.yangtools.yang.common.YangConstants;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
@@ -43,14 +54,12 @@ public final class RestconfInvokeOperationsUtil {
     /**
      * Invoking rpc via mount point.
      *
-     * @param mountPoint
-     *             mount point
-     * @param data
-     *             input data
-     * @param rpc
-     *             RPC type
+     * @param mountPoint mount point
+     * @param data input data
+     * @param rpc RPC type
      * @return {@link DOMRpcResult}
      */
+    // FIXME: NETCONF-718: we should be returning a future here
     public static DOMRpcResult invokeRpc(final NormalizedNode data, final QName rpc, final DOMMountPoint mountPoint) {
         return invokeRpc(data, rpc, mountPoint.getService(DOMRpcService.class).orElseThrow(() -> {
             final String errmsg = "RPC service is missing.";
@@ -62,19 +71,18 @@ public final class RestconfInvokeOperationsUtil {
     /**
      * Invoke rpc.
      *
-     * @param data
-     *             input data
-     * @param rpc
-     *             RPC type
-     * @param rpcService
-     *             rpc service to invoke rpc
+     * @param data input data
+     * @param rpc RPC type
+     * @param rpcService rpc service to invoke rpc
      * @return {@link DOMRpcResult}
      */
+    // FIXME: NETCONF-718: we should be returning a future here
     public static DOMRpcResult invokeRpc(final NormalizedNode data, final QName rpc, final DOMRpcService rpcService) {
-        final ListenableFuture<? extends DOMRpcResult> future = rpcService.invokeRpc(rpc, nonnullInput(rpc, data));
-        final RpcResultFactory dataFactory = new RpcResultFactory();
-        FutureCallbackTx.addCallback(future, PostDataTransactionUtil.POST_TX_TYPE, dataFactory);
-        return dataFactory.build();
+        return checkedGet(Futures.catching(
+            rpcService.invokeRpc(rpc, nonnullInput(rpc, data)), DOMRpcException.class,
+            cause -> new DefaultDOMRpcResult(ImmutableList.of(RpcResultBuilder.newError(
+                RpcError.ErrorType.RPC, "operation-failed", cause.getMessage()))),
+            MoreExecutors.directExecutor()));
     }
 
     private static @NonNull NormalizedNode nonnullInput(final QName type, final NormalizedNode input) {
@@ -85,8 +93,7 @@ public final class RestconfInvokeOperationsUtil {
     /**
      * Check the validity of the result.
      *
-     * @param response
-     *             response of rpc
+     * @param response response of rpc
      * @return {@link DOMRpcResult} result
      */
     public static DOMRpcResult checkResponse(final DOMRpcResult response) {
@@ -109,12 +116,9 @@ public final class RestconfInvokeOperationsUtil {
     /**
      * Invoking Action via mount point.
      *
-     * @param mountPoint
-     *             mount point
-     * @param data
-     *             input data
-     * @param schemaPath
-     *             schema path of data
+     * @param mountPoint mount point
+     * @param data input data
+     * @param schemaPath schema path of data
      * @return {@link DOMActionResult}
      */
     public static DOMActionResult invokeAction(final ContainerNode data,
@@ -126,21 +130,34 @@ public final class RestconfInvokeOperationsUtil {
     /**
      * Invoke Action via ActionServiceHandler.
      *
-     * @param data
-     *             input data
-     * @param schemaPath
-     *             schema path of data
-     * @param actionService
-     *             action service to invoke action
+     * @param data input data
+     * @param yangIId invocation context
+     * @param schemaPath schema path of data
+     * @param actionService action service to invoke action
      * @return {@link DOMActionResult}
      */
+    // FIXME: NETCONF-718: we should be returning a future here
     public static DOMActionResult invokeAction(final ContainerNode data, final Absolute schemaPath,
             final YangInstanceIdentifier yangIId, final DOMActionService actionService) {
-        final ListenableFuture<? extends DOMActionResult> future = actionService.invokeAction(schemaPath,
-            new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, yangIId.getParent()), data);
-        final ActionResultFactory dataFactory = new ActionResultFactory();
-        FutureCallbackTx.addCallback(future, PostDataTransactionUtil.POST_TX_TYPE, dataFactory);
-        return dataFactory.build();
+        return checkedGet(Futures.catching(actionService.invokeAction(
+            schemaPath, new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, yangIId.getParent()), data),
+            DOMActionException.class,
+            cause -> new SimpleDOMActionResult(ImmutableList.of(RpcResultBuilder.newError(
+                RpcError.ErrorType.RPC, "operation-failed", cause.getMessage()))),
+            MoreExecutors.directExecutor()));
+    }
+
+    @Deprecated
+    private static <T> T checkedGet(final ListenableFuture<T> future) {
+        try {
+            return future.get();
+        } catch (InterruptedException e) {
+            throw new RestconfDocumentedException("Interrupted while waiting for result of invocation", e);
+        } catch (ExecutionException e) {
+            final Throwable cause = e.getCause();
+            Throwables.throwIfInstanceOf(cause, RestconfDocumentedException.class);
+            throw new RestconfDocumentedException("Invocation failed", e);
+        }
     }
 
     /**
diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/RpcResultFactory.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/rests/utils/RpcResultFactory.java
deleted file mode 100644 (file)
index c5a6f48..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.restconf.nb.rfc8040.rests.utils;
-
-import org.opendaylight.mdsal.dom.api.DOMRpcResult;
-import org.opendaylight.yangtools.concepts.Builder;
-
-public class RpcResultFactory extends FutureDataFactory<DOMRpcResult> implements Builder<DOMRpcResult> {
-    @Override
-    public DOMRpcResult build() {
-        return this.result;
-    }
-}