From: Jakub Toth Date: Thu, 4 Aug 2016 14:32:19 +0000 (+0200) Subject: Bug 6325 - Fix for draft15 update X-Git-Tag: release/carbon~240^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=55fd821685e69826789b9658bd32ec0db1726625;p=netconf.git Bug 6325 - Fix for draft15 update - transaction chain must be updated in transaction handler - adapt utility methods to reset transaction chain Change-Id: I20578f97c9a8d002c0ebcc6b8a89a152c1e1c47a Signed-off-by: Ivan Hrasko Signed-off-by: Jakub Toth --- diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestConnectorProvider.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestConnectorProvider.java index 7c7ae377e1..8205eba6ad 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestConnectorProvider.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/RestConnectorProvider.java @@ -5,6 +5,7 @@ * 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; import com.google.common.base.Preconditions; @@ -16,7 +17,6 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListen import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService; import org.opendaylight.controller.md.sal.dom.api.DOMRpcService; -import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; import org.opendaylight.controller.sal.core.api.Provider; import org.opendaylight.controller.sal.core.api.model.SchemaService; @@ -57,8 +57,8 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose }; private ListenerRegistration listenerRegistration; + private static TransactionChainHandler transactionChainHandler; private static DOMDataBroker dataBroker; - private static DOMTransactionChain transactionChain; @Override public void onSessionInitiated(final ProviderSession session) { @@ -72,30 +72,32 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose final DOMMountPointServiceHandler domMountPointServiceHandler = new DOMMountPointServiceHandler( session.getService(DOMMountPointService.class)); - dataBroker = session.getService(DOMDataBroker.class); - final DOMDataBrokerHandler brokerHandler = new DOMDataBrokerHandler(dataBroker); + RestConnectorProvider.dataBroker = session.getService(DOMDataBroker.class); + final DOMDataBrokerHandler brokerHandler = new DOMDataBrokerHandler(RestConnectorProvider.dataBroker); - transactionChain = dataBroker.createTransactionChain(transactionListener); - final TransactionChainHandler transactionChainHandler = new TransactionChainHandler(transactionChain); + RestConnectorProvider.transactionChainHandler = new TransactionChainHandler(RestConnectorProvider.dataBroker + .createTransactionChain(RestConnectorProvider.transactionListener)); final DOMRpcService rpcService = session.getService(DOMRpcService.class); final RpcServiceHandler rpcServiceHandler = new RpcServiceHandler(rpcService); - wrapperServices.setHandlers(schemaCtxHandler, domMountPointServiceHandler, transactionChainHandler, - brokerHandler, rpcServiceHandler); + wrapperServices.setHandlers(schemaCtxHandler, domMountPointServiceHandler, + RestConnectorProvider.transactionChainHandler, brokerHandler, rpcServiceHandler); } /** - * After {@link TransactionChain} failed, this is creating new transaction - * with listener. + * After {@link TransactionChain} failed, this updates {@link TransactionChainHandler} with new transaction chain. * * @param chain * - old {@link TransactionChain} */ public static void resetTransactionChainForAdapaters(final TransactionChain chain) { - LOG.trace("Resetting TransactionChain({}) to {}", chain, transactionChain); + LOG.trace("Resetting TransactionChain({})", chain); chain.close(); - transactionChain = Preconditions.checkNotNull(dataBroker).createTransactionChain(transactionListener); + RestConnectorProvider.transactionChainHandler.update( + Preconditions.checkNotNull(RestConnectorProvider.dataBroker).createTransactionChain( + RestConnectorProvider.transactionListener) + ); } @Override @@ -105,11 +107,14 @@ public class RestConnectorProvider implements Provider, RestConnector, AutoClose @Override public void close() throws Exception { + // close registration if (this.listenerRegistration != null) { this.listenerRegistration.close(); } - if (transactionChain != null) { - transactionChain.close(); + + // close transaction chain + if (RestConnectorProvider.transactionChainHandler != null) { + RestConnectorProvider.transactionChainHandler.get().close(); } } } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/Handler.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/Handler.java index 69c2276e13..ceece0ffdd 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/Handler.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/Handler.java @@ -5,9 +5,8 @@ * 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.handlers; -import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; +package org.opendaylight.restconf.handlers; /** * Handler for handling object prepared by provider for Restconf services @@ -20,7 +19,15 @@ interface Handler { /** * Get prepared object * - * @return {@link DOMTransactionChain} + * @return T */ T get(); + + /** + * Update object + * + * @param object + * - new object to update old object + */ + default void update(T object) {} } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/TransactionChainHandler.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/TransactionChainHandler.java index 450a8ed2b6..7cceef1dcd 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/TransactionChainHandler.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/handlers/TransactionChainHandler.java @@ -5,6 +5,7 @@ * 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.handlers; import com.google.common.base.Preconditions; @@ -17,7 +18,7 @@ import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; */ public class TransactionChainHandler implements Handler { - private final DOMTransactionChain transactionChain; + private DOMTransactionChain transactionChain; /** * Prepare transaction chain service for Restconf services @@ -29,6 +30,12 @@ public class TransactionChainHandler implements Handler { this.transactionChain = transactionChain; } + @Override + public void update(final DOMTransactionChain transactionChain) { + Preconditions.checkNotNull(transactionChain); + this.transactionChain = transactionChain; + } + @Override public DOMTransactionChain get() { return this.transactionChain; diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java index 15d1f1c95d..15ce3f7660 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtil.java @@ -12,6 +12,7 @@ import javax.ws.rs.core.Response; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; @@ -34,7 +35,7 @@ public final class DeleteDataTransactionUtil { */ public static Response deleteData(final TransactionVarsWrapper transactionNode) { final CheckedFuture future = submitData( - transactionNode.getTransactionChain().newReadWriteTransaction(), + transactionNode.getTransactionChain(), transactionNode.getTransactionChain().newReadWriteTransaction(), transactionNode.getInstanceIdentifier().getInstanceIdentifier()); final ResponseFactory response = new ResponseFactory(); FutureCallbackTx.addCallback(future, RestconfDataServiceConstant.DeleteData.DELETE_TX_TYPE, response); @@ -44,6 +45,8 @@ public final class DeleteDataTransactionUtil { /** * Delete data via transaction. Return error if data to delete does not exist. * + * @param transactionChain + * - transaction chain * @param readWriteTx * - read and write transaction * @param path @@ -51,8 +54,9 @@ public final class DeleteDataTransactionUtil { * @return {@link CheckedFuture} */ private static CheckedFuture submitData( - final DOMDataReadWriteTransaction readWriteTx, final YangInstanceIdentifier path) { - TransactionUtil.checkItemExists(readWriteTx, LogicalDatastoreType.CONFIGURATION, path, + final DOMTransactionChain transactionChain, final DOMDataReadWriteTransaction readWriteTx, + final YangInstanceIdentifier path) { + TransactionUtil.checkItemExists(transactionChain, readWriteTx, LogicalDatastoreType.CONFIGURATION, path, RestconfDataServiceConstant.DeleteData.DELETE_TX_TYPE); readWriteTx.delete(LogicalDatastoreType.CONFIGURATION, path); return readWriteTx.submit(); diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PatchDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PatchDataTransactionUtil.java index 0b350a7667..4741592977 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PatchDataTransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PatchDataTransactionUtil.java @@ -14,6 +14,7 @@ import com.google.common.util.concurrent.CheckedFuture; import java.util.ArrayList; import java.util.List; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; @@ -185,7 +186,7 @@ public final class PatchDataTransactionUtil { final YangInstanceIdentifier path, final DOMDataReadWriteTransaction readWriteTransaction) { LOG.trace("Delete {} within Restconf PATCH: {}", dataStore.name(), path); - TransactionUtil.checkItemExists(readWriteTransaction, dataStore, path, PatchData.PATCH_TX_TYPE); + checkItemExistsWithinTransaction(readWriteTransaction, dataStore, path); readWriteTransaction.delete(dataStore, path); } @@ -264,20 +265,62 @@ public final class PatchDataTransactionUtil { final YangInstanceIdentifier childPath = path.node(child.getIdentifier()); if (errorIfExists) { - TransactionUtil.checkItemDoesNotExists( - rWTransaction, dataStore, childPath, PatchData.PATCH_TX_TYPE); + checkItemDoesNotExistsWithinTransaction(rWTransaction, dataStore, childPath); } rWTransaction.put(dataStore, childPath, child); } } else { if (errorIfExists) { - TransactionUtil.checkItemDoesNotExists( - rWTransaction, dataStore, path, PatchData.PATCH_TX_TYPE); + checkItemDoesNotExistsWithinTransaction(rWTransaction, dataStore, path); } TransactionUtil.ensureParentsByMerge(path, schemaContext, rWTransaction); rWTransaction.put(dataStore, path, payload); } } + + /** + * Check if items already exists at specified {@code path}. Throws {@link RestconfDocumentedException} if + * data does NOT already exists. + * @param rWTransaction Transaction + * @param store Datastore + * @param path Path to be checked + */ + public static void checkItemExistsWithinTransaction(final DOMDataReadWriteTransaction rWTransaction, + final LogicalDatastoreType store, final YangInstanceIdentifier path) { + final CheckedFuture future = rWTransaction.exists(store, path); + final FutureDataFactory response = new FutureDataFactory<>(); + + FutureCallbackTx.addCallback(future, PatchData.PATCH_TX_TYPE, response); + + if (!response.result) { + final String errMsg = "Operation via Restconf was not executed because data does not exist"; + LOG.trace("{}:{}", errMsg, path); + throw new RestconfDocumentedException( + "Data does not exist", ErrorType.PROTOCOL, ErrorTag.DATA_MISSING, path); + } + } + + /** + * Check if items do NOT already exists at specified {@code path}. Throws {@link RestconfDocumentedException} if + * data already exists. + * @param rWTransaction Transaction + * @param store Datastore + * @param path Path to be checked + */ + public static void checkItemDoesNotExistsWithinTransaction(final DOMDataReadWriteTransaction rWTransaction, + final LogicalDatastoreType store, final YangInstanceIdentifier path) { + final CheckedFuture future = rWTransaction.exists(store, path); + final FutureDataFactory response = new FutureDataFactory<>(); + + FutureCallbackTx.addCallback(future, PatchData.PATCH_TX_TYPE, response); + + if (response.result) { + final String errMsg = "Operation via Restconf was not executed because data already exists"; + LOG.trace("{}:{}", errMsg, path); + throw new RestconfDocumentedException( + "Data already exists", ErrorType.PROTOCOL, ErrorTag.DATA_EXISTS, path); + } + } } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java index bc464069e0..f507837630 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/PostDataTransactionUtil.java @@ -15,6 +15,7 @@ import javax.ws.rs.core.UriInfo; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; import org.opendaylight.netconf.sal.restconf.impl.NormalizedNodeContext; import org.opendaylight.restconf.common.references.SchemaContextRef; import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper; @@ -89,32 +90,34 @@ public final class PostDataTransactionUtil { private static CheckedFuture submitData(final YangInstanceIdentifier path, final NormalizedNode data, final TransactionVarsWrapper transactionNode, final SchemaContext schemaContext) { - final DOMDataReadWriteTransaction transaction = transactionNode.getTransactionChain().newReadWriteTransaction(); + final DOMTransactionChain transactionChain = transactionNode.getTransactionChain(); + final DOMDataReadWriteTransaction transaction = transactionChain.newReadWriteTransaction(); final NormalizedNode node = ImmutableNodes.fromInstanceId(schemaContext, path); transaction.put(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.create(node.getIdentifier()), node); TransactionUtil.ensureParentsByMerge(path, schemaContext, transaction); if (data instanceof MapNode) { for (final MapEntryNode child : ((MapNode) data).getValue()) { - putChild(child, transaction, path); + putChild(child, transactionChain, transaction, path); } } else if (data instanceof AugmentationNode) { for (final DataContainerChild child : ((AugmentationNode) data).getValue()) { - putChild(child, transaction, path); + putChild(child, transactionChain, transaction, path); } } else if (data instanceof ChoiceNode) { for (final DataContainerChild child : ((ChoiceNode) data).getValue()) { - putChild(child, transaction, path); + putChild(child, transactionChain, transaction, path); } } else if (data instanceof LeafSetNode) { for (final LeafSetEntryNode child : ((LeafSetNode) data).getValue()) { - putChild(child, transaction, path); + putChild(child, transactionChain, transaction, path); } } else if (data instanceof ContainerNode) { for (final DataContainerChild child : ((ContainerNode) data).getValue()) { - putChild(child, transaction, path); + putChild(child, transactionChain, transaction, path); } } + return transaction.submit(); } @@ -123,15 +126,18 @@ public final class PostDataTransactionUtil { * * @param child * - data + * @param transactionChain + * - transaction chain * @param readWriteTx * - transaction * @param path * - path to data */ - private static void putChild(final NormalizedNode child, final DOMDataReadWriteTransaction readWriteTx, - final YangInstanceIdentifier path) { + private static void putChild(final NormalizedNode child, final DOMTransactionChain transactionChain, + final DOMDataReadWriteTransaction readWriteTx, final YangInstanceIdentifier path) { final YangInstanceIdentifier childPath = path.node(child.getIdentifier()); - TransactionUtil.checkItemDoesNotExists(readWriteTx, LogicalDatastoreType.CONFIGURATION, childPath, + TransactionUtil.checkItemDoesNotExists( + transactionChain, readWriteTx, LogicalDatastoreType.CONFIGURATION, childPath, RestconfDataServiceConstant.PostData.POST_TX_TYPE); readWriteTx.put(LogicalDatastoreType.CONFIGURATION, childPath, child); } diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/TransactionUtil.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/TransactionUtil.java index 6f63088d50..2cd6899e32 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/TransactionUtil.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/restconf/restful/utils/TransactionUtil.java @@ -5,6 +5,7 @@ * 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.restful.utils; import com.google.common.base.Preconditions; @@ -16,9 +17,11 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction; +import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag; import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType; +import org.opendaylight.restconf.RestConnectorProvider; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; @@ -88,12 +91,14 @@ public final class TransactionUtil { /** * Check if items already exists at specified {@code path}. Throws {@link RestconfDocumentedException} if * data does NOT already exists. + * @param transactionChain Transaction chain * @param rWTransaction Transaction * @param store Datastore * @param path Path to be checked * @param operationType Type of operation (READ, POST, PUT, DELETE...) */ - public static void checkItemExists(final DOMDataReadWriteTransaction rWTransaction, + public static void checkItemExists(final DOMTransactionChain transactionChain, + final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType store, final YangInstanceIdentifier path, final String operationType) { final CheckedFuture future = rWTransaction.exists(store, path); @@ -102,6 +107,11 @@ public final class TransactionUtil { FutureCallbackTx.addCallback(future, operationType, response); if (!response.result) { + // close transaction and reset transaction chain + rWTransaction.cancel(); + RestConnectorProvider.resetTransactionChainForAdapaters(transactionChain); + + // throw error final String errMsg = "Operation via Restconf was not executed because data does not exist"; LOG.trace("{}:{}", errMsg, path); throw new RestconfDocumentedException( @@ -112,12 +122,14 @@ public final class TransactionUtil { /** * Check if items do NOT already exists at specified {@code path}. Throws {@link RestconfDocumentedException} if * data already exists. + * @param transactionChain Transaction chain * @param rWTransaction Transaction * @param store Datastore * @param path Path to be checked * @param operationType Type of operation (READ, POST, PUT, DELETE...) */ - public static void checkItemDoesNotExists(final DOMDataReadWriteTransaction rWTransaction, + public static void checkItemDoesNotExists(final DOMTransactionChain transactionChain, + final DOMDataReadWriteTransaction rWTransaction, final LogicalDatastoreType store, final YangInstanceIdentifier path, final String operationType) { final CheckedFuture future = rWTransaction.exists(store, path); @@ -126,6 +138,11 @@ public final class TransactionUtil { FutureCallbackTx.addCallback(future, operationType, response); if (response.result) { + // close transaction and reset transaction chain + rWTransaction.cancel(); + RestConnectorProvider.resetTransactionChainForAdapaters(transactionChain); + + // throw error final String errMsg = "Operation via Restconf was not executed because data already exists"; LOG.trace("{}:{}", errMsg, path); throw new RestconfDocumentedException( diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/RestConnectorProviderTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/RestConnectorProviderTest.java index 9b3b450b74..f2ade260ef 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/RestConnectorProviderTest.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/RestConnectorProviderTest.java @@ -171,5 +171,6 @@ public class RestConnectorProviderTest { // verify interaction verify(this.mockRegistration, times(1)).close(); + verify(mockTransactionChain, times(1)).close(); } } diff --git a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java index f38923d952..38db430eab 100644 --- a/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java +++ b/restconf/sal-rest-connector/src/test/java/org/opendaylight/restconf/restful/utils/DeleteDataTransactionUtilTest.java @@ -10,21 +10,29 @@ package org.opendaylight.restconf.restful.utils; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; + import com.google.common.util.concurrent.Futures; +import java.lang.reflect.Field; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction; import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain; import org.opendaylight.netconf.sal.restconf.impl.InstanceIdentifierContext; import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag; import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType; +import org.opendaylight.restconf.RestConnectorProvider; +import org.opendaylight.restconf.handlers.TransactionChainHandler; import org.opendaylight.restconf.restful.transaction.TransactionVarsWrapper; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; @@ -36,6 +44,31 @@ public class DeleteDataTransactionUtilTest { @Mock private DOMDataReadWriteTransaction readWrite; + // Fields used when delete operation fails to reset transaction chain + private static Field handler; + private static Field broker; + + @BeforeClass + public static void setup() throws Exception { + DeleteDataTransactionUtilTest.handler = RestConnectorProvider.class.getDeclaredField("transactionChainHandler"); + DeleteDataTransactionUtilTest.broker = RestConnectorProvider.class.getDeclaredField("dataBroker"); + + DeleteDataTransactionUtilTest.handler.setAccessible(true); + DeleteDataTransactionUtilTest.handler.set(RestConnectorProvider.class, mock(TransactionChainHandler.class)); + + DeleteDataTransactionUtilTest.broker.setAccessible(true); + DeleteDataTransactionUtilTest.broker.set(RestConnectorProvider.class, mock(DOMDataBroker.class)); + } + + @AfterClass + public static void clean() throws Exception { + DeleteDataTransactionUtilTest.handler.set(RestConnectorProvider.class, null); + DeleteDataTransactionUtilTest.handler.setAccessible(false); + + DeleteDataTransactionUtilTest.broker.set(RestConnectorProvider.class, null); + DeleteDataTransactionUtilTest.broker.setAccessible(false); + } + @Before public void init() throws Exception { MockitoAnnotations.initMocks(this);