Factor out MdsalDatabindProvider 05/110805/2
authorRobert Varga <robert.varga@pantheon.tech>
Sun, 17 Mar 2024 08:06:34 +0000 (09:06 +0100)
committerRobert Varga <nite@hq.sk>
Sun, 17 Mar 2024 09:00:38 +0000 (09:00 +0000)
RpcImplementations require an instance of DatabindProvider, which is
provided by MdsalRestconfServer, which in turn takes RpcImplementations.
This leads to circular dependency during component activation.

Break this cycle by introducing MdsalDatabindProvider, which acts as a
common intermediary and update the component wiring accordingly.

JIRA: NETCONF-1236
Change-Id: Iec6e8dba67785b920274825d70c2a7171edef6e2
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/mdsal/MdsalDatabindProvider.java [new file with mode: 0644]
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/mdsal/MdsalRestconfServer.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/mdsal/streams/dtcl/CreateDataChangeEventSubscriptionRpc.java
restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/mdsal/streams/notif/CreateNotificationStreamRpc.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/jaxrs/AbstractRestconfTest.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/jaxrs/Netconf799Test.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/jaxrs/RestconfSchemaServiceMountTest.java
restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/jaxrs/RestconfSchemaServiceTest.java

diff --git a/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/mdsal/MdsalDatabindProvider.java b/restconf/restconf-nb/src/main/java/org/opendaylight/restconf/server/mdsal/MdsalDatabindProvider.java
new file mode 100644 (file)
index 0000000..2e6d5ce
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o. 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.server.mdsal;
+
+import static com.google.common.base.Verify.verifyNotNull;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import javax.annotation.PreDestroy;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService.YangTextSourceExtension;
+import org.opendaylight.restconf.server.api.DatabindContext;
+import org.opendaylight.restconf.server.spi.DatabindProvider;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * A {@link DatabindProvider} tracking a {@link DOMSchemaService}.
+ */
+@Singleton
+@Component(service = { DatabindProvider.class, MdsalDatabindProvider.class })
+public final class MdsalDatabindProvider implements DatabindProvider, AutoCloseable {
+    private static final VarHandle CURRENT_DATABIND;
+
+    static {
+        try {
+            CURRENT_DATABIND = MethodHandles.lookup()
+                .findVarHandle(MdsalDatabindProvider.class, "currentDatabind", DatabindContext.class);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    private final @Nullable YangTextSourceExtension sourceProvider;
+    private final Registration reg;
+
+    @SuppressFBWarnings(value = "URF_UNREAD_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
+    private volatile DatabindContext currentDatabind;
+
+    @Inject
+    @Activate
+    public MdsalDatabindProvider(@Reference final DOMSchemaService schemaService) {
+        sourceProvider = schemaService.extension(YangTextSourceExtension.class);
+        currentDatabind = DatabindContext.ofModel(schemaService.getGlobalContext());
+        reg = schemaService.registerSchemaContextListener(this::onModelContextUpdated);
+    }
+
+    @PreDestroy
+    @Deactivate
+    @Override
+    public void close() {
+        reg.close();
+    }
+
+    @Override
+    public DatabindContext currentDatabind() {
+        return verifyNotNull((@NonNull DatabindContext) CURRENT_DATABIND.getAcquire(this));
+    }
+
+    @Nullable YangTextSourceExtension sourceProvider() {
+        return sourceProvider;
+    }
+
+    private void onModelContextUpdated(final EffectiveModelContext newModelContext) {
+        final var local = currentDatabind;
+        if (!newModelContext.equals(local.modelContext())) {
+            CURRENT_DATABIND.setRelease(this, DatabindContext.ofModel(newModelContext));
+        }
+    }
+}
index 2621ac83d685299b31b5c2bf3625f6874c9b8d74..c2acb5e60f5a18f64d735fd45ecbcb9c9f009084 100644 (file)
@@ -29,8 +29,6 @@ import org.opendaylight.mdsal.dom.api.DOMActionService;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
 import org.opendaylight.mdsal.dom.api.DOMRpcService;
-import org.opendaylight.mdsal.dom.api.DOMSchemaService;
-import org.opendaylight.mdsal.dom.api.DOMSchemaService.YangTextSourceExtension;
 import org.opendaylight.restconf.api.ApiPath;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
 import org.opendaylight.restconf.common.errors.RestconfFuture;
@@ -55,11 +53,9 @@ import org.opendaylight.restconf.server.api.OperationsPostResult;
 import org.opendaylight.restconf.server.api.PatchBody;
 import org.opendaylight.restconf.server.api.ResourceBody;
 import org.opendaylight.restconf.server.api.RestconfServer;
-import org.opendaylight.restconf.server.spi.DatabindProvider;
 import org.opendaylight.restconf.server.spi.RpcImplementation;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev170126.YangApi;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev170126.restconf.Restconf;
-import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
@@ -67,7 +63,6 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.common.YangNames;
 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.source.SourceRepresentation;
 import org.opendaylight.yangtools.yang.model.api.source.YangTextSource;
@@ -77,13 +72,14 @@ import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
 
 /**
  * A RESTCONF server implemented on top of MD-SAL.
  */
 @Singleton
-@Component(service = { RestconfServer.class, DatabindProvider.class })
-public final class MdsalRestconfServer implements RestconfServer, DatabindProvider, AutoCloseable {
+@Component(service = RestconfServer.class)
+public final class MdsalRestconfServer implements RestconfServer, AutoCloseable {
     private static final QName YANG_LIBRARY_VERSION = QName.create(Restconf.QNAME, "yang-library-version").intern();
     private static final VarHandle LOCAL_STRATEGY;
 
@@ -98,67 +94,58 @@ public final class MdsalRestconfServer implements RestconfServer, DatabindProvid
 
     private final @NonNull ImmutableMap<QName, RpcImplementation> localRpcs;
     private final @NonNull DOMMountPointService mountPointService;
+    private final @NonNull MdsalDatabindProvider databindProvider;
     private final @NonNull DOMDataBroker dataBroker;
     private final @Nullable DOMRpcService rpcService;
     private final @Nullable DOMActionService actionService;
-    private final @Nullable YangTextSourceExtension sourceProvider;
 
-    private final Registration reg;
-
-    @SuppressWarnings("unused")
     @SuppressFBWarnings(value = "URF_UNREAD_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
     private volatile MdsalRestconfStrategy localStrategy;
 
     @Inject
     @Activate
-    public MdsalRestconfServer(@Reference final DOMSchemaService schemaService,
+    public MdsalRestconfServer(@Reference final MdsalDatabindProvider databindProvider,
             @Reference final DOMDataBroker dataBroker, @Reference final DOMRpcService rpcService,
             @Reference final DOMActionService actionService,
             @Reference final DOMMountPointService mountPointService,
-            @Reference final List<RpcImplementation> localRpcs) {
+            @Reference(policyOption = ReferencePolicyOption.GREEDY) final List<RpcImplementation> localRpcs) {
+        this.databindProvider = requireNonNull(databindProvider);
         this.dataBroker = requireNonNull(dataBroker);
         this.rpcService = requireNonNull(rpcService);
         this.actionService = requireNonNull(actionService);
         this.mountPointService = requireNonNull(mountPointService);
-        this.localRpcs = Maps.uniqueIndex(localRpcs, RpcImplementation::qname);
-        sourceProvider = schemaService.extension(YangTextSourceExtension.class);
 
-        localStrategy = createLocalStrategy(schemaService.getGlobalContext());
-        reg = schemaService.registerSchemaContextListener(this::onModelContextUpdated);
+        this.localRpcs = Maps.uniqueIndex(localRpcs, RpcImplementation::qname);
+        localStrategy = createLocalStrategy(databindProvider.currentDatabind());
     }
 
-    public MdsalRestconfServer(final DOMSchemaService schemaService, final DOMDataBroker dataBroker,
+    public MdsalRestconfServer(final MdsalDatabindProvider databindProvider, final DOMDataBroker dataBroker,
             final DOMRpcService rpcService, final DOMActionService actionService,
             final DOMMountPointService mountPointService, final RpcImplementation... localRpcs) {
-        this(schemaService, dataBroker, rpcService, actionService, mountPointService, List.of(localRpcs));
+        this(databindProvider, dataBroker, rpcService, actionService, mountPointService, List.of(localRpcs));
     }
 
-    @Override
-    public DatabindContext currentDatabind() {
-        return localStrategy().databind();
+    private @NonNull MdsalRestconfStrategy createLocalStrategy(final DatabindContext databind) {
+        return new MdsalRestconfStrategy(databind, dataBroker, rpcService, actionService,
+            databindProvider.sourceProvider(), mountPointService, localRpcs);
     }
 
-    private void onModelContextUpdated(final EffectiveModelContext newModelContext) {
-        final var local = localStrategy();
-        if (!newModelContext.equals(local.modelContext())) {
-            LOCAL_STRATEGY.setRelease(this, createLocalStrategy(newModelContext));
-        }
-    }
-
-    private @NonNull MdsalRestconfStrategy createLocalStrategy(final EffectiveModelContext modelContext) {
-        return new MdsalRestconfStrategy(DatabindContext.ofModel(modelContext), dataBroker, rpcService, actionService,
-            sourceProvider, mountPointService, localRpcs);
+    private @NonNull MdsalRestconfStrategy localStrategy() {
+        final var strategy = verifyNotNull((@NonNull MdsalRestconfStrategy) LOCAL_STRATEGY.getAcquire(this));
+        final var databind = databindProvider.currentDatabind();
+        return databind.equals(strategy.databind()) ? strategy : updateLocalStrategy(databind);
     }
 
-    private @NonNull MdsalRestconfStrategy localStrategy() {
-        return verifyNotNull((MdsalRestconfStrategy) LOCAL_STRATEGY.getAcquire(this));
+    private @NonNull MdsalRestconfStrategy updateLocalStrategy(final DatabindContext databind) {
+        final var strategy = createLocalStrategy(databind);
+        localStrategy = strategy;
+        return strategy;
     }
 
     @PreDestroy
     @Deactivate
     @Override
     public void close() {
-        reg.close();
         localStrategy = null;
     }
 
index 1ad6d691c7c2c5a3e5890c0147fb16f55cba06a8..9c98f4143cea897866891b21d6442068943d4c76 100644 (file)
@@ -42,7 +42,7 @@ import org.osgi.service.component.annotations.Reference;
  * RESTCONF implementation of {@link CreateDataChangeEventSubscription}.
  */
 @Singleton
-@Component
+@Component(service = RpcImplementation.class)
 public final class CreateDataChangeEventSubscriptionRpc extends RpcImplementation {
     private static final @NonNull NodeIdentifier DATASTORE_NODEID = NodeIdentifier.create(
         QName.create(CreateDataChangeEventSubscriptionInput1.QNAME, "datastore").intern());
index 08c402cb80366a78634908cb96488b07a5c7031d..af3ba4a7a6809b8fc3df6a334baf37446f722310 100644 (file)
@@ -40,7 +40,7 @@ import org.osgi.service.component.annotations.Reference;
  * RESTCONF implementation of {@link CreateNotificationStream}.
  */
 @Singleton
-@Component
+@Component(service = RpcImplementation.class)
 public final class CreateNotificationStreamRpc extends RpcImplementation {
     private static final NodeIdentifier SAL_REMOTE_OUTPUT_NODEID =
         NodeIdentifier.create(CreateDataChangeEventSubscriptionOutput.QNAME);
index 48842c66a6e04a94ae26bb7cca5b9788f4e0da85..f5eff3718990270e08546a525f884459afcef7ac 100644 (file)
@@ -46,6 +46,7 @@ import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
 import org.opendaylight.restconf.nb.rfc8040.jersey.providers.JsonNormalizedNodeBodyWriter;
 import org.opendaylight.restconf.nb.rfc8040.jersey.providers.XmlNormalizedNodeBodyWriter;
 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
+import org.opendaylight.restconf.server.mdsal.MdsalDatabindProvider;
 import org.opendaylight.restconf.server.mdsal.MdsalRestconfServer;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
@@ -71,8 +72,9 @@ abstract class AbstractRestconfTest extends AbstractJukeboxTest {
 
     @BeforeEach
     final void setupRestconf() {
-        restconf = new JaxRsRestconf(new MdsalRestconfServer(new FixedDOMSchemaService(modelContext()), dataBroker,
-            rpcService, actionService, mountPointService));
+        restconf = new JaxRsRestconf(new MdsalRestconfServer(
+            new MdsalDatabindProvider(new FixedDOMSchemaService(modelContext())), dataBroker, rpcService, actionService,
+            mountPointService));
     }
 
     EffectiveModelContext modelContext() {
index c2b5155f8a801197a9dc550733130cd2e7505bb4..672b6e19f530105d7dbe1f2631864142124cfd77 100644 (file)
@@ -34,6 +34,7 @@ import org.opendaylight.mdsal.dom.spi.SimpleDOMActionResult;
 import org.opendaylight.restconf.api.ApiPath;
 import org.opendaylight.restconf.nb.rfc8040.AbstractInstanceIdentifierTest;
 import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
+import org.opendaylight.restconf.server.mdsal.MdsalDatabindProvider;
 import org.opendaylight.restconf.server.mdsal.MdsalRestconfServer;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
@@ -67,8 +68,9 @@ class Netconf799Test extends AbstractInstanceIdentifierTest {
             .build())))
             .when(actionService).invokeAction(eq(RESET_PATH), any(), any());
 
-        final var restconf = new JaxRsRestconf(new MdsalRestconfServer(new FixedDOMSchemaService(IID_SCHEMA),
-            dataBroker, rpcService, actionService, mountPointService));
+        final var restconf = new JaxRsRestconf(new MdsalRestconfServer(
+            new MdsalDatabindProvider(new FixedDOMSchemaService(IID_SCHEMA)), dataBroker, rpcService, actionService,
+            mountPointService));
         doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
         doReturn(true).when(asyncResponse).resume(captor.capture());
         restconf.postDataJSON(ApiPath.parse("instance-identifier-module:cont/cont1/reset"),
@@ -91,8 +93,9 @@ class Netconf799Test extends AbstractInstanceIdentifierTest {
             .build())))
             .when(actionService).invokeAction(eq(RESET_PATH), any(), any());
 
-        final var restconf = new JaxRsRestconf(new MdsalRestconfServer(new FixedDOMSchemaService(IID_SCHEMA),
-            dataBroker, rpcService, actionService, mountPointService));
+        final var restconf = new JaxRsRestconf(new MdsalRestconfServer(
+            new MdsalDatabindProvider(new FixedDOMSchemaService(IID_SCHEMA)), dataBroker, rpcService, actionService,
+            mountPointService));
         doReturn(new MultivaluedHashMap<>()).when(uriInfo).getQueryParameters();
         doReturn(true).when(asyncResponse).resume(captor.capture());
         restconf.postDataJSON(ApiPath.parse("instance-identifier-module:cont/cont1/reset"),
index a99c000ab634069f034ddb0689e09247d3e41584..36f8d96964ff45b9f43fda706d00e6ede39b67fa 100644 (file)
@@ -8,15 +8,11 @@
 package org.opendaylight.restconf.nb.jaxrs;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doCallRealMethod;
-import static org.mockito.Mockito.doReturn;
 import static org.opendaylight.restconf.nb.jaxrs.AbstractRestconfTest.assertEntity;
 import static org.opendaylight.restconf.nb.jaxrs.AbstractRestconfTest.assertError;
 
 import com.google.common.io.CharStreams;
 import java.io.Reader;
-import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -26,11 +22,11 @@ import org.opendaylight.mdsal.dom.api.DOMActionService;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMRpcService;
 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
-import org.opendaylight.mdsal.dom.api.DOMSchemaService.YangTextSourceExtension;
 import org.opendaylight.mdsal.dom.broker.DOMMountPointServiceImpl;
 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
 import org.opendaylight.restconf.api.ApiPath;
 import org.opendaylight.restconf.nb.rfc8040.legacy.ErrorTags;
+import org.opendaylight.restconf.server.mdsal.MdsalDatabindProvider;
 import org.opendaylight.restconf.server.mdsal.MdsalRestconfServer;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
@@ -59,10 +55,6 @@ public class RestconfSchemaServiceMountTest {
 
     // handlers
     @Mock
-    private DOMSchemaService schemaService;
-    @Mock
-    private YangTextSourceExtension sourceProvider;
-    @Mock
     private DOMDataBroker dataBroker;
     @Mock
     private DOMActionService actionService;
@@ -89,12 +81,9 @@ public class RestconfSchemaServiceMountTest {
                 .createMountPoint(YangInstanceIdentifier.of(QName.create("mount:point:2", "2016-01-01", "cont")))
                 .register();
 
-        doCallRealMethod().when(schemaService).extension(any());
-        doReturn(List.of(sourceProvider)).when(schemaService).supportedExtensions();
-        doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext();
-
-        restconf = new JaxRsRestconf(new MdsalRestconfServer(schemaService, dataBroker, rpcService, actionService,
-            mountPointService));
+        restconf = new JaxRsRestconf(new MdsalRestconfServer(
+            new MdsalDatabindProvider(new FixedDOMSchemaService(SCHEMA_CONTEXT_WITH_MOUNT_POINTS)), dataBroker,
+            rpcService, actionService, mountPointService));
     }
 
     /**
index 160dc08ee8609f7a12d7f948a9699b4e2fed9725..5bd3a28de41befa1545ae006a63efad55b555248 100644 (file)
@@ -9,8 +9,6 @@ package org.opendaylight.restconf.nb.jaxrs;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doReturn;
 import static org.opendaylight.restconf.nb.jaxrs.AbstractRestconfTest.assertEntity;
 import static org.opendaylight.restconf.nb.jaxrs.AbstractRestconfTest.assertError;
@@ -18,7 +16,6 @@ import static org.opendaylight.restconf.nb.jaxrs.AbstractRestconfTest.assertErro
 import com.google.common.util.concurrent.Futures;
 import java.io.IOException;
 import java.io.Reader;
-import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -28,8 +25,9 @@ import org.opendaylight.mdsal.dom.api.DOMActionService;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
 import org.opendaylight.mdsal.dom.api.DOMRpcService;
-import org.opendaylight.mdsal.dom.api.DOMSchemaService;
 import org.opendaylight.mdsal.dom.api.DOMSchemaService.YangTextSourceExtension;
+import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
+import org.opendaylight.restconf.server.mdsal.MdsalDatabindProvider;
 import org.opendaylight.restconf.server.mdsal.MdsalRestconfServer;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
@@ -45,11 +43,9 @@ import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
 @RunWith(MockitoJUnitRunner.StrictStubs.class)
 public class RestconfSchemaServiceTest {
     // schema context with modules
-    private static final EffectiveModelContext SCHEMA_CONTEXT =
+    private static final EffectiveModelContext MODEL_CONTEXT =
         YangParserTestUtils.parseYangResourceDirectory("/modules");
 
-    @Mock
-    private DOMSchemaService schemaService;
     @Mock
     private YangTextSourceExtension sourceProvider;
     @Mock
@@ -70,12 +66,9 @@ public class RestconfSchemaServiceTest {
 
     @Before
     public void setup() throws Exception {
-        doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext();
-        doCallRealMethod().when(schemaService).extension(any());
-        doReturn(List.of(sourceProvider)).when(schemaService).supportedExtensions();
-
-        restconf = new JaxRsRestconf(new MdsalRestconfServer(schemaService, dataBroker, rpcService, actionService,
-            mountPointService));
+        restconf = new JaxRsRestconf(new MdsalRestconfServer(
+            new MdsalDatabindProvider(new FixedDOMSchemaService(() -> MODEL_CONTEXT, sourceProvider)), dataBroker,
+            rpcService, actionService, mountPointService));
     }
 
     /**