From: Robert Varga Date: Sun, 20 Jan 2019 15:05:22 +0000 (+0100) Subject: Fix adapters retaining state X-Git-Tag: release/neon~24 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=netconf.git;a=commitdiff_plain;h=2c69dd7eb97b9e5a8cc7fd17d12bf792e9113ce0 Fix adapters retaining state Storing notifications in a field causes them to be retained for longer than needed. Pass them as arguments, fixing the leak and making the adapters stateless. Change-Id: I3977a912280740a83a3209aadf2c190336fabe1e Signed-off-by: Robert Varga --- diff --git a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerAdapter.java b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerAdapter.java index 653e0bfbc1..f3193e7993 100644 --- a/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerAdapter.java +++ b/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerAdapter.java @@ -21,7 +21,6 @@ import org.opendaylight.mdsal.dom.api.DOMNotification; import org.opendaylight.mdsal.dom.api.DOMNotificationListener; import org.opendaylight.netconf.sal.restconf.impl.ControllerContext; import org.opendaylight.restconf.common.errors.RestconfDocumentedException; -import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier; @@ -49,9 +48,6 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem private final SchemaPath path; private final String outputType; - private SchemaContext schemaContext; - private DOMNotification notification; - /** * Set path of listener and stream name, register event bus. * @@ -83,14 +79,11 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem } @Override - @SuppressWarnings("checkstyle:hiddenField") public void onNotification(final DOMNotification notification) { - this.schemaContext = controllerContext.getGlobalSchema(); - this.notification = notification; - - final String xml = prepareXml(); + final SchemaContext schemaContext = controllerContext.getGlobalSchema(); + final String xml = prepareXml(schemaContext, notification); if (checkQueryParams(xml, this)) { - prepareAndPostData(xml); + prepareAndPostData(outputType.equals("JSON") ? prepareJson(schemaContext, notification) : xml); } } @@ -116,15 +109,11 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem /** * Prepare data of notification and data to client. * - * @param xml data + * @param data data */ - private void prepareAndPostData(final String xml) { + private void prepareAndPostData(final String data) { final Event event = new Event(EventType.NOTIFY); - if (this.outputType.equals("JSON")) { - event.setData(prepareJson()); - } else { - event.setData(xml); - } + event.setData(data); post(event); } @@ -134,32 +123,22 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem * @return json as {@link String} */ @VisibleForTesting - String prepareJson() { + String prepareJson(final SchemaContext schemaContext, final DOMNotification notification) { final JsonParser jsonParser = new JsonParser(); final JsonObject json = new JsonObject(); - json.add("ietf-restconf:notification", jsonParser.parse(writeBodyToString())); + json.add("ietf-restconf:notification", jsonParser.parse(writeBodyToString(schemaContext, notification))); json.addProperty("event-time", ListenerAdapter.toRFC3339(Instant.now())); return json.toString(); } - @VisibleForTesting - void setNotification(final DOMNotification notification) { - this.notification = Preconditions.checkNotNull(notification); - } - - @VisibleForTesting - void setSchemaContext(final SchemaContext schemaContext) { - this.schemaContext = Preconditions.checkNotNull(schemaContext); - } - - private String writeBodyToString() { + private static String writeBodyToString(final SchemaContext schemaContext, final DOMNotification notification) { final Writer writer = new StringWriter(); final NormalizedNodeStreamWriter jsonStream = JSONNormalizedNodeStreamWriter.createExclusiveWriter( - JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(this.schemaContext), - this.notification.getType(), null, JsonWriterFactory.createJsonWriter(writer)); + JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(schemaContext), + notification.getType(), null, JsonWriterFactory.createJsonWriter(writer)); final NormalizedNodeWriter nodeWriter = NormalizedNodeWriter.forStreamWriter(jsonStream); try { - nodeWriter.write(this.notification.getBody()); + nodeWriter.write(notification.getBody()); nodeWriter.close(); } catch (final IOException e) { throw new RestconfDocumentedException("Problem while writing body of notification to JSON. ", e); @@ -167,23 +146,23 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem return writer.toString(); } - private String prepareXml() { + private String prepareXml(final SchemaContext schemaContext, final DOMNotification notification) { final Document doc = createDocument(); final Element notificationElement = basePartDoc(doc); final Element notificationEventElement = doc.createElementNS( "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote", "create-notification-stream"); - addValuesToNotificationEventElement(doc, notificationEventElement); + addValuesToNotificationEventElement(doc, notificationEventElement, schemaContext, notification); notificationElement.appendChild(notificationEventElement); return transformDoc(doc); } - private void addValuesToNotificationEventElement(final Document doc, final Element element) { - final ContainerNode body = notification.getBody(); + private void addValuesToNotificationEventElement(final Document doc, final Element element, + final SchemaContext schemaContext, final DOMNotification notification) { try { - final DOMResult domResult = writeNormalizedNode(body, schemaContext, this.path); + final DOMResult domResult = writeNormalizedNode(notification.getBody(), schemaContext, this.path); final Node result = doc.importNode(domResult.getNode().getFirstChild(), true); final Element dataElement = doc.createElement("notification"); dataElement.appendChild(result); diff --git a/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerTest.java b/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerTest.java index ac45de8a74..079f14f71f 100644 --- a/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerTest.java +++ b/restconf/restconf-nb-bierman02/src/test/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerTest.java @@ -234,9 +234,7 @@ public class NotificationListenerTest { Notificator.createNotificationListener(paths, "stream-name", NotificationOutputType.JSON.toString(), controllerContext); final NotificationListenerAdapter notifi = listNotifi.get(0); - notifi.setNotification(notificationData); - notifi.setSchemaContext(schemaContext); - final String result = notifi.prepareJson(); + final String result = notifi.prepareJson(schemaContext, notificationData); return Preconditions.checkNotNull(result); } } diff --git a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerAdapter.java b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerAdapter.java index 1a3e1e2093..14a345a209 100644 --- a/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerAdapter.java +++ b/restconf/restconf-nb-rfc8040/src/main/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerAdapter.java @@ -20,7 +20,6 @@ import javax.xml.transform.dom.DOMResult; import org.opendaylight.mdsal.dom.api.DOMNotification; import org.opendaylight.mdsal.dom.api.DOMNotificationListener; import org.opendaylight.restconf.common.errors.RestconfDocumentedException; -import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter; import org.opendaylight.yangtools.yang.data.codec.gson.JSONCodecFactorySupplier; @@ -47,9 +46,6 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem private final SchemaPath path; private final String outputType; - private SchemaContext schemaContext; - private DOMNotification notification; - /** * Set path of listener and stream name, register event bus. * @@ -81,14 +77,11 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem } @Override - @SuppressWarnings("checkstyle:hiddenField") public void onNotification(final DOMNotification notification) { - this.schemaContext = schemaHandler.get(); - this.notification = notification; - - final String xml = prepareXml(); + final SchemaContext schemaContext = schemaHandler.get(); + final String xml = prepareXml(schemaContext, notification); if (checkQueryParams(xml, this)) { - prepareAndPostData(xml); + prepareAndPostData(outputType.equals("JSON") ? prepareJson(schemaContext, notification) : xml); } } @@ -114,15 +107,11 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem /** * Prepare data of notification and data to client. * - * @param xml data + * @param data data */ - private void prepareAndPostData(final String xml) { + private void prepareAndPostData(final String data) { final Event event = new Event(EventType.NOTIFY); - if (this.outputType.equals("JSON")) { - event.setData(prepareJson()); - } else { - event.setData(xml); - } + event.setData(data); post(event); } @@ -132,32 +121,22 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem * @return json as {@link String} */ @VisibleForTesting - String prepareJson() { + String prepareJson(final SchemaContext schemaContext, final DOMNotification notification) { final JsonParser jsonParser = new JsonParser(); final JsonObject json = new JsonObject(); - json.add("ietf-restconf:notification", jsonParser.parse(writeBodyToString())); + json.add("ietf-restconf:notification", jsonParser.parse(writeBodyToString(schemaContext, notification))); json.addProperty("event-time", ListenerAdapter.toRFC3339(Instant.now())); return json.toString(); } - @VisibleForTesting - void setNotification(final DOMNotification notification) { - this.notification = Preconditions.checkNotNull(notification); - } - - @VisibleForTesting - void setSchemaContext(final SchemaContext schemaContext) { - this.schemaContext = Preconditions.checkNotNull(schemaContext); - } - - private String writeBodyToString() { + private static String writeBodyToString(final SchemaContext schemaContext, final DOMNotification notification) { final Writer writer = new StringWriter(); final NormalizedNodeStreamWriter jsonStream = JSONNormalizedNodeStreamWriter.createExclusiveWriter( - JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(this.schemaContext), - this.notification.getType(), null, JsonWriterFactory.createJsonWriter(writer)); + JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(schemaContext), notification.getType(), + null, JsonWriterFactory.createJsonWriter(writer)); final NormalizedNodeWriter nodeWriter = NormalizedNodeWriter.forStreamWriter(jsonStream); try { - nodeWriter.write(this.notification.getBody()); + nodeWriter.write(notification.getBody()); nodeWriter.close(); } catch (final IOException e) { throw new RestconfDocumentedException("Problem while writing body of notification to JSON. ", e); @@ -165,27 +144,23 @@ public class NotificationListenerAdapter extends AbstractCommonSubscriber implem return writer.toString(); } - private String prepareXml() { + private String prepareXml(final SchemaContext schemaContext, final DOMNotification notification) { final Document doc = createDocument(); final Element notificationElement = basePartDoc(doc); final Element notificationEventElement = doc.createElementNS( "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote", "create-notification-stream"); - addValuesToNotificationEventElement(doc, notificationEventElement); + addValuesToNotificationEventElement(doc, notificationEventElement, schemaContext, notification); notificationElement.appendChild(notificationEventElement); return transformDoc(doc); } - private void addValuesToNotificationEventElement(final Document doc, final Element element) { - if (notification == null) { - return; - } - - final ContainerNode body = notification.getBody(); + private void addValuesToNotificationEventElement(final Document doc, final Element element, + final SchemaContext schemaContext, final DOMNotification notification) { try { - final DOMResult domResult = writeNormalizedNode(body, schemaContext, this.path); + final DOMResult domResult = writeNormalizedNode(notification.getBody(), schemaContext, this.path); final Node result = doc.importNode(domResult.getNode().getFirstChild(), true); final Element dataElement = doc.createElement("notification"); dataElement.appendChild(result); diff --git a/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerTest.java b/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerTest.java index 0fb8f3b4ab..33328bc2d1 100644 --- a/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerTest.java +++ b/restconf/restconf-nb-rfc8040/src/test/java/org/opendaylight/restconf/nb/rfc8040/streams/listeners/NotificationListenerTest.java @@ -222,9 +222,7 @@ public class NotificationListenerTest { final List listNotifi = Notificator.createNotificationListener(paths, "stream-name", NotificationOutputType.JSON.toString()); final NotificationListenerAdapter notifi = listNotifi.get(0); - notifi.setNotification(notificationData); - notifi.setSchemaContext(this.schmeaCtx); - final String result = notifi.prepareJson(); + final String result = notifi.prepareJson(schmeaCtx, notificationData); return Preconditions.checkNotNull(result); } }