<!-- 
RSS generated by JIRA (8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d) at Wed Feb 07 20:16:17 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary append 'field=key&field=summary' to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>OpenDaylight JIRA</title>
    <link>https://jira.opendaylight.org</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>8.20.10</version>
        <build-number>820010</build-number>
        <build-date>22-06-2022</build-date>
    </build-info>


<item>
            <title>[NETCONF-938] Cannot generate API docs for Junos device</title>
                <link>https://jira.opendaylight.org/browse/NETCONF-938</link>
                <project id="10142" key="NETCONF">netconf</project>
                    <description>&lt;p&gt;When we have device that contains Junos [common models|&lt;a href=&quot;https://github.com/Juniper/yang/tree/master/22.3/22.3R1/common&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://github.com/Juniper/yang/tree/master/22.3/22.3R1/common&lt;/a&gt;] and [junos family models|&lt;a href=&quot;https://github.com/Juniper/yang/tree/master/22.3/22.3R1/junos&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://github.com/Juniper/yang/tree/master/22.3/22.3R1/junos&lt;/a&gt;] its not possible to access [its mount point documentation|&lt;a href=&quot;http://localhost:8181/apidoc/explorer/index.html?urls.primaryName=17830-sim-device%20resources%20-%20RestConf%20RFC%208040.&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;http://localhost:8181/apidoc/explorer/index.html?urls.primaryName=17830-sim-device%20resources%20-%20RestConf%20RFC%208040&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;The docs are never loaded and we can see that Java VM is out of heap space. After some time the running ODL instance is killed.&lt;/p&gt;</description>
                <environment></environment>
        <key id="36515">NETCONF-938</key>
            <summary>Cannot generate API docs for Junos device</summary>
                <type id="10104" iconUrl="https://jira.opendaylight.org/secure/viewavatar?size=xsmall&amp;avatarId=10303&amp;avatarType=issuetype">Bug</type>
                                            <priority id="1" iconUrl="https://jira.opendaylight.org/images/icons/priorities/blocker.svg">Highest</priority>
                        <status id="10001" iconUrl="https://jira.opendaylight.org/" description="">In Review</status>
                    <statusCategory id="4" key="indeterminate" colorName="yellow"/>
                                    <resolution id="-1">Unresolved</resolution>
                                        <assignee username="ivanhrasko">Ivan Hrasko</assignee>
                                    <reporter username="ivanhrasko">Ivan Hrasko</reporter>
                        <labels>
                            <label>pt</label>
                    </labels>
                <created>Thu, 5 Jan 2023 11:43:33 +0000</created>
                <updated>Thu, 1 Feb 2024 08:59:03 +0000</updated>
                                                            <fixVersion>7.0.0</fixVersion>
                                    <component>restconf-openapi</component>
                        <due></due>
                            <votes>0</votes>
                                    <watches>3</watches>
                                                                                                                                                            <comments>
                            <comment id="72053" author="petersuna" created="Wed, 15 Mar 2023 08:50:48 +0000"  >&lt;p&gt;The DefinitionGenerator class is encountering a heap space issue while processing the &lt;a href=&quot;https://git.opendaylight.org/gerrit/c/netconf/+/103968/7/restconf/sal-rest-docgen/src/test/resources/juniper/junos-conf-root%25402022-01-01.yang&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;&quot;junos-conf-root&quot;&lt;/a&gt; model.&lt;br/&gt;
This issue arises when processing JSON body examples. Despite not being particularly large, this model only creates 100 JSON body examples when a simple test is created with the &quot;junos-conf-root&quot; model and its two import models.&lt;/p&gt;

&lt;p&gt;The problem lies in the fact that other models create approximately 62 augmentations to the configuration container within the &quot;junos-conf-root&quot; model. This results in the creation of a large number of JSON body examples, around 1 million, which contain a total of 10 million JSON elements.&lt;/p&gt;

&lt;p&gt;The Swagger API docs process each model and append all examples from every model to an object called &quot;definition&quot; inside &lt;a href=&quot;https://github.com/opendaylight/netconf/blob/master/restconf/sal-rest-docgen/src/main/java/org/opendaylight/netconf/sal/rest/doc/swagger/SwaggerObject.java#L21&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;SwaggerObject&lt;/a&gt;. This involves appending 10 million elements, which can take up all available memory.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;It is likely that creating 1 million examples for augmentations is not correct and needs to be addressed to fix the issue.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Code in master branch after creating configuration containers.&lt;br/&gt;
&lt;span class=&quot;image-wrap&quot; style=&quot;&quot;&gt;&lt;img src=&quot;https://jira.opendaylight.org/secure/attachment/18609/18609_image-2023-03-15-09-23-20-869.png&quot; height=&quot;453&quot; width=&quot;811&quot; style=&quot;border: 0px solid black&quot; /&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;I have replaced ObjectNodes with DefinitionObjects and results in numbers for this model:&lt;br/&gt;
&lt;span class=&quot;image-wrap&quot; style=&quot;&quot;&gt;&lt;img src=&quot;https://jira.opendaylight.org/secure/attachment/18610/18610_image-2023-03-15-09-47-49-518.png&quot; height=&quot;392&quot; width=&quot;809&quot; style=&quot;border: 0px solid black&quot; /&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://git.opendaylight.org/gerrit/c/netconf/+/104878/2&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://git.opendaylight.org/gerrit/c/netconf/+/104878/2&lt;/a&gt;&lt;/p&gt;</comment>
                            <comment id="72301" author="ivanhrasko" created="Wed, 14 Jun 2023 07:51:50 +0000"  >&lt;p&gt;We assume that the high memory consumption is caused by:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Generating unnecessary schema objects, for _XML, _TOP, etc.&lt;/li&gt;
	&lt;li&gt;Unnecessary usage of many ArraNode(s) and ObjectNode(s).&lt;/li&gt;
	&lt;li&gt;Recursion.&lt;/li&gt;
&lt;/ol&gt;
</comment>
                            <comment id="72425" author="rovarga" created="Thu, 27 Jul 2023 21:09:36 +0000"  >&lt;p&gt;Right, but at the end of the day the core problem is how JSON serialization is implemented.&lt;/p&gt;

&lt;p&gt;What we have is:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
    @Override
    &lt;span class=&quot;code-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;code-keyword&quot;&gt;synchronized&lt;/span&gt; Response getAllModulesDoc(&lt;span class=&quot;code-keyword&quot;&gt;final&lt;/span&gt; UriInfo uriInfo) {
        &lt;span class=&quot;code-keyword&quot;&gt;final&lt;/span&gt; DefinitionNames definitionNames = &lt;span class=&quot;code-keyword&quot;&gt;new&lt;/span&gt; DefinitionNames();
        &lt;span class=&quot;code-keyword&quot;&gt;final&lt;/span&gt; OpenApiObject doc = openApiGeneratorRFC8040.getAllModulesDoc(uriInfo, definitionNames);
        &lt;span class=&quot;code-keyword&quot;&gt;return&lt;/span&gt; Response.ok(doc).build();
    }
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;which then routes to JaxbContextResolver, which then uses ObjectMapper to turn OpenApiObject into JSON (and uses reflection to determine how to do that).&lt;/p&gt;

&lt;p&gt;The problem is the fact OpenApiObject exists. It is the moral equivalent of doing Stream.collect() before doing further processing of the stream contents. You have to realize that on input there is EffectiveModelContext and on output there are bytes (which happen to represent a JSON a document).&lt;/p&gt;

&lt;p&gt;Response.ok(doc) does this:&lt;/p&gt;

&lt;div class=&quot;code panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;codeContent panelContent&quot;&gt;
&lt;pre class=&quot;code-java&quot;&gt;
    &lt;span class=&quot;code-keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;code-keyword&quot;&gt;static&lt;/span&gt; ResponseBuilder ok(&lt;span class=&quot;code-object&quot;&gt;Object&lt;/span&gt; entity) {
        ResponseBuilder b = ok();
        b.entity(entity);
        &lt;span class=&quot;code-keyword&quot;&gt;return&lt;/span&gt; b;
    }
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;and ResponseBuilder.entity() explicitly says:&lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;Note that the entity can be also set as an {@link java.io.InputStream input stream}.
&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So we really want to integrate at this level &amp;#8211; e.g. provide an InputStream whose bytes are the JSON representation of what OpenApiObject models. At the end of the day, BaseYangOpenApiGenerator, needs to return an OpenApiInputStream from getFilledDoc() &amp;#8211; the constructor of which just captures stuff from UriInfo and the EffectiveModelContext.&lt;/p&gt;

&lt;p&gt;As for the implementation of said OpenApiInputStream, think of it as a more complicated java.util.Iterator. Essentially it iterates over EffectiveModelContext (maybe multiple times) and each time it gets a piece of the JSON document, which it caches internally and gives out its bytes on InputStream.read(). Whenever it runs out of bytes to give out, it moves to the next bit of EffectiveModelContext, turns it into a JSON fragment, and hands that out &amp;#8211; until it runs out of EffectiveModelContext, at which point it reports -1 to indicate it is all done.&lt;/p&gt;

&lt;p&gt;I think the core interface here ends up being &lt;a href=&quot;https://www.javadoc.io/static/com.fasterxml.jackson.core/jackson-core/2.15.2/com/fasterxml/jackson/core/JsonGenerator.html&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://www.javadoc.io/static/com.fasterxml.jackson.core/jackson-core/2.15.2/com/fasterxml/jackson/core/JsonGenerator.html&lt;/a&gt;, where the generator is pointed to something that holds bytes for OpenApiInputStream to consume and the EffectiveModelContext-processing logic is provided with the JsonGenerator to use methods writeStartObject() and similar. This obviously needs further investigation, but the goal is clear I think.&lt;/p&gt;

&lt;p&gt;We already have stuff working on this general principle: see how &lt;a href=&quot;https://github.com/opendaylight/yangtools/blob/master/model/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/DeclaredStatementFormatter.java&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://github.com/opendaylight/yangtools/blob/master/model/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/DeclaredStatementFormatter.java&lt;/a&gt; works once it is configured. toYangTextSnippet() takes either a module, or a submodule and returns an Iterable &amp;#8211; and that in turn defers to &lt;a href=&quot;https://github.com/opendaylight/yangtools/blob/master/model/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/YangTextSnippetIterator.java&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://github.com/opendaylight/yangtools/blob/master/model/yang-model-export/src/main/java/org/opendaylight/yangtools/yang/model/export/YangTextSnippetIterator.java&lt;/a&gt; &amp;#8211; which converts a DeclaredStatement (and its subtree) to a sequence of Strings.&lt;/p&gt;

&lt;p&gt;We want to do a similar thing, except:&lt;/p&gt;
&lt;ul class=&quot;alternate&quot; type=&quot;square&quot;&gt;
	&lt;li&gt;it is not DeclaredStatement tree but an EffectiveModelContext tree on input&lt;/li&gt;
	&lt;li&gt;it is not YANG text snippets buts JSON snippet bytes on output&lt;/li&gt;
	&lt;li&gt;the machinery is driven by a request for a byte&lt;/li&gt;
	&lt;li&gt;there is Jackson in between&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Perhaps a critical thing to understand: OpenApiInputStream here is consumed by framework is a similar fashion that YangTextSnippet users consume it. InputStream should be viewed as Interator&amp;lt;Integer&amp;gt;, where &apos;int read()&apos; combines the function of hasNext() and next() (via the return of -1). Plus, obviously, it provides methods to consume bytes in bulk.&lt;/p&gt;

&lt;p&gt;At the end of the day, there must be no ObjectMapper or com.fasterxml.jackson.annotation in sight.&lt;/p&gt;

&lt;p&gt;Also, to drive this point home even more, think of EffectiveModelContext as a source of events (like &quot;we have a module&quot;, &quot;we have an RPC&quot;, &quot;we have an RPC input&quot;, &quot;we have a leaf&quot;, &quot;we ended the RPC input&quot;, &quot;we have ended the RPC&quot;, &quot;we have ended the module&quot;) and we are turning them into JSON events (like beginObject(), endObject(), etc.) and then turning them into bytes. This is &lt;a href=&quot;https://en.wikipedia.org/wiki/Stream_processing&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;stream processing&lt;/a&gt; at its &lt;a href=&quot;https://en.wikipedia.org/wiki/Dataflow_programming&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;purest&lt;/a&gt;.&lt;/p&gt;</comment>
                            <comment id="72426" author="rovarga" created="Mon, 31 Jul 2023 16:22:05 +0000"  >&lt;p&gt;Assuming JAX-RS, we can eliminate some of the complexity by shifing computation to a MessageBodyWriter, when we have the OutputStream available. &lt;a href=&quot;https://git.opendaylight.org/gerrit/c/netconf/+/107149&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://git.opendaylight.org/gerrit/c/netconf/+/107149&lt;/a&gt; provides the basic things, but it highlights we really should think about how the model is actually laid out (centered around OpenApiEntity and its specializations).&lt;/p&gt;</comment>
                            <comment id="73105" author="ivanhrasko" created="Wed, 17 Jan 2024 11:42:17 +0000"  >&lt;p&gt;With &lt;a href=&quot;https://git.opendaylight.org/gerrit/c/netconf/+/109803&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://git.opendaylight.org/gerrit/c/netconf/+/109803&lt;/a&gt; we can generate and download OpenAPI docs for junos device within 30 seconds with:&lt;/p&gt;
&lt;div class=&quot;preformatted panel&quot; style=&quot;border-width: 1px;&quot;&gt;&lt;div class=&quot;preformattedContent panelContent&quot;&gt;
&lt;pre&gt;curl -o /home/odl/Desktop/openapi.json --location &apos;http://localhost:8181/openapi/api/v3/mounts/1&apos; --header &apos;Authorization: Basic YWRtaW46YWRtaW4=&apos;&lt;/pre&gt;
&lt;/div&gt;&lt;/div&gt;</comment>
                            <comment id="73106" author="ivanhrasko" created="Wed, 17 Jan 2024 11:45:26 +0000"  >&lt;p&gt;Anyway the whole junos model (1.3 GiB) is not parsable by browsers. We wil try to handle this in &lt;a href=&quot;https://jira.opendaylight.org/browse/NETCONF-1225&quot; title=&quot;OpenAPI: implement paging&quot; class=&quot;issue-link&quot; data-issue-key=&quot;NETCONF-1225&quot;&gt;NETCONF-1225&lt;/a&gt;.&lt;/p&gt;</comment>
                    </comments>
                <issuelinks>
                            <issuelinktype id="10000">
                    <name>Blocks</name>
                                                                <inwardlinks description="is blocked by">
                                        <issuelink>
            <issuekey id="37941">NETCONF-1241</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="37942">NETCONF-1242</issuekey>
        </issuelink>
                            </inwardlinks>
                                    </issuelinktype>
                            <issuelinktype id="10002">
                    <name>Duplicate</name>
                                                                <inwardlinks description="is duplicated by">
                                        <issuelink>
            <issuekey id="28627">NETCONF-480</issuekey>
        </issuelink>
                            </inwardlinks>
                                    </issuelinktype>
                            <issuelinktype id="10003">
                    <name>Relates</name>
                                            <outwardlinks description="relates to">
                                        <issuelink>
            <issuekey id="37005">NETCONF-1054</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="37008">NETCONF-1056</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="37009">NETCONF-1057</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="37931">NETCONF-1234</issuekey>
        </issuelink>
                            </outwardlinks>
                                                                <inwardlinks description="relates to">
                                        <issuelink>
            <issuekey id="36752">NETCONF-982</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="36839">NETCONF-997</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="36917">NETCONF-1023</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="36918">NETCONF-1024</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="36919">NETCONF-1025</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="36943">NETCONF-1036</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="36950">NETCONF-1041</issuekey>
        </issuelink>
            <issuelink>
            <issuekey id="36973">NETCONF-1050</issuekey>
        </issuelink>
                            </inwardlinks>
                                    </issuelinktype>
                    </issuelinks>
                <attachments>
                            <attachment id="18405" name="Image Pasted at 2023-1-9 10-08.png" size="377727" author="rovarga" created="Tue, 10 Jan 2023 09:04:29 +0000"/>
                            <attachment id="18404" name="Image Pasted at 2023-1-9 10-09.png" size="258830" author="rovarga" created="Tue, 10 Jan 2023 09:04:29 +0000"/>
                            <attachment id="18403" name="Image Pasted at 2023-1-9 10-10.png" size="553666" author="rovarga" created="Tue, 10 Jan 2023 09:04:29 +0000"/>
                            <attachment id="18402" name="Image Pasted at 2023-1-9 10-11.png" size="452915" author="rovarga" created="Tue, 10 Jan 2023 09:04:29 +0000"/>
                            <attachment id="18400" name="Screenshot_2023-01-04_11-03-36.png" size="144297" author="ivanhrasko" created="Thu, 5 Jan 2023 11:49:12 +0000"/>
                            <attachment id="18609" name="image-2023-03-15-09-23-20-869.png" size="279211" author="PeterSuna" created="Wed, 15 Mar 2023 08:23:22 +0000"/>
                            <attachment id="18610" name="image-2023-03-15-09-47-49-518.png" size="278091" author="PeterSuna" created="Wed, 15 Mar 2023 08:47:50 +0000"/>
                    </attachments>
                <subtasks>
                            <subtask id="36516">NETCONF-939</subtask>
                            <subtask id="36752">NETCONF-982</subtask>
                    </subtasks>
                <customfields>
                                                                            <customfield id="customfield_11400" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                <customfield id="customfield_10000" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>0|i043wn:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                </customfields>
    </item>
</channel>
</rss>