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;
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
*/
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;
/**
* 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.";
/**
* 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) {
/**
* 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) {
/**
* 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,
/**
* 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);
+ }
}
/**