<div style="color:#000; background-color:#fff; font-family:HelveticaNeue-Light, Helvetica Neue Light, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif;font-size:16px"><div id="yui_3_16_0_1_1417345481659_9805"><span></span></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9941">Hey <font face="Arial" class="" style="">Vojtech,<br class="" style=""><br class="" style=""></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9944"><font face="Arial" class="" style="" id="yui_3_16_0_1_1417345481659_9943">How are you?, please see my reply inline.<br class="" style=""></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9922"><div class="" style="" id="yui_3_16_0_1_1417345481659_9921"><span class="" style="" id="yui_3_16_0_1_1417345481659_9938"><br class="" style=""><blockquote class="" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" id="yui_3_16_0_1_1417345481659_9937"><div style="font-family: HelveticaNeue, 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;" class="" id="yui_3_16_0_1_1417345481659_9936"><div class="" style=""></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9942"><br class="" style=""><br class="" style=""></div>  <div class="" style="" id="yui_3_16_0_1_1417345481659_9935"> <div class="" style="" id="yui_3_16_0_1_1417345481659_9934"> <div class="" style="" id="yui_3_16_0_1_1417345481659_9933"> <div dir="ltr" class="" style="" id="yui_3_16_0_1_1417345481659_9940"> <font face="Arial" class="" style="" id="yui_3_16_0_1_1417345481659_9939"> On Friday, November 28, 2014 5:26 PM, Vojtech Szocs &lt;<a href="mailto:vszocs@redhat.com" target="_blank" class="" style="">vszocs@redhat.com</a>&gt; wrote:<br class="" style=""> </font> </div>  <br class="" style=""><br class="" style=""> <div class="" style="" id="yui_3_16_0_1_1417345481659_9932">Hi guys,<br class="" style=""><br class="" style="">since the initial (small, working &amp; well-tested) version of oVirtJS<br class="" style="">JavaScript SDK is finished [*], I've started working on GWT wrapper<br class="" style="">for oVirtJS.<br class="" style=""><br class="" style="">While analyzing/reverse-engineering oVirt Java SDK, some thoughts<br class="" style="">came to my mind, and I wanted to share them with you.<br class="" style=""><br class="" style="">[*] TODO(vszocs) upload new patchset with all recent changes<br class="" style=""><br class="" style="">First, the way XJC (JAXB binding compiler that generates Java beans<br class="" style="">out of REST XSD schema) is invoked looks a bit weird to me, as Java<br class="" style="">SDK's XsdCodegen does this:<br class="" style=""><br class="" style="">&nbsp; Runtime.getRuntime().exec(<wbr class="" style="">command)<br class="" style=""><br class="" style="">Why not simply use existing Maven plugins to invoke XJC?<br class="" style="">- either: <a href="https://github.com/highsource/maven-jaxb2-plugin" target="_blank" class="" style="" id="yui_3_16_0_1_1417345481659_9931">https://github.com/highsource/<wbr class="" style="">maven-jaxb2-plugin</a><br class="" style=""></div></div></div></div></div></blockquote><div class="" style="" id="yui_3_16_0_1_1417345481659_10278"><br class="" style=""></div></span><div class="" style="" id="yui_3_16_0_1_1417345481659_9930" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_9929">[MP] sdk was using jaxb to begin with, it was replaced with XJC just recently,<br class="" style=""></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9928"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_9927">btw Juan, what was the motivation behind this? <br class="" style="">(REST api uses jaxb as well so we used to have 1x1 mappings)</font><br class="" style=""></div><div class="" style="" id="yui_3_16_0_1_1417345481659_10277">&nbsp;</div><blockquote class="" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" id="yui_3_16_0_1_1417345481659_9920"><div style="font-family: HelveticaNeue, 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;" class="" id="yui_3_16_0_1_1417345481659_9919">- or: <a href="http://mojo.codehaus.org/jaxb2-maven-plugin/" target="_blank" class="" style="" id="yui_3_16_0_1_1417345481659_9918">http://mojo.codehaus.org/<wbr class="" style="">jaxb2-maven-plugin/</a><br class="" style=""></div></blockquote><div class="" style="" id="yui_3_16_0_1_1417345481659_9923"><br class="" style=""></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9924"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_10290">[MP]&nbsp;same.</font><br class="" style=""></div><div class="" style=""><div class="" style=""><div id="q_14a003ec78624219_3" class="" style=""><div class="" style=""></div></div></div></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9926"><br></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9926"><div class="" style="" id="yui_3_16_0_1_1417345481659_14459"><div class="" style="" id="yui_3_16_0_1_1417345481659_14458"><blockquote class="" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" id="yui_3_16_0_1_1417345481659_14457"><div style="font-family: HelveticaNeue, 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;" class="" id="yui_3_16_0_1_1417345481659_14456"><br class="" style="">Second, and most importantly, what's the point of having "group"<br class="" style="">entities? I'll give an example - api.xsd contains this:<br class="" style=""><br class="" style="">&nbsp; &lt;xs:complexType name="DataCenters"&gt;<br class="" style="">&nbsp; &nbsp; &lt;xs:complexContent&gt;<br class="" style="">&nbsp; &nbsp; &nbsp; &lt;xs:extension base="BaseResources"&gt;<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; &lt;xs:sequence&gt;<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;xs:annotation&gt;<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;xs:appinfo&gt;<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;jaxb:property name="DataCenters"/&gt;<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/xs:appinfo&gt;<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/xs:annotation&gt;<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;xs:element ref="data_center" minOccurs="0" maxOccurs="unbounded"/&gt;<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; &lt;/xs:sequence&gt;<br class="" style="">&nbsp; &nbsp; &nbsp; &lt;/xs:extension&gt;<br class="" style="">&nbsp; &nbsp; &lt;/xs:complexContent&gt;<br class="" style="">&nbsp; &lt;/xs:complexType&gt;<br class="" style=""><br class="" style="">(Same as above for Hosts, Clusters, VMs, etc.)<br class="" style=""><br class="" style="">This results in following (IMHO rather meaningless) Java class<br class="" style="">being generated by XJC:<br class="" style=""><br class="" style="">public class DataCenters extends BaseResources {<br class="" style=""><br class="" style="">&nbsp; &nbsp; @XmlElement(name = "data_center")<br class="" style="">&nbsp; &nbsp; protected List&lt;DataCenter&gt; dataCenters;<br class="" style=""><br class="" style="">&nbsp; &nbsp; public List&lt;DataCenter&gt; getDataCenters() {<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; if (dataCenters == null) {<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dataCenters = new ArrayList&lt;DataCenter&gt;();<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; }<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; return this.dataCenters;<br class="" style="">&nbsp; &nbsp; }<br class="" style=""><br class="" style="">&nbsp; &nbsp; public boolean isSetDataCenters() {<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; return ((this.dataCenters!= null)&amp;&amp;(!this.dataCenters.<wbr class="" style="">isEmpty()));<br class="" style="">&nbsp; &nbsp; }<br class="" style=""><br class="" style="">&nbsp; &nbsp; public void unsetDataCenters() {<br class="" style="">&nbsp; &nbsp; &nbsp; &nbsp; this.dataCenters = null;<br class="" style="">&nbsp; &nbsp; }<br class="" style=""><br class="" style="">}<br class="" style=""><br class="" style="">Instead, we could use @XmlElementWrapper as described in [1]<br class="" style="">to avoid generating "group" entities altogether.<br class="" style=""><br class="" style="">[1] <a href="https://github.com/dmak/jaxb-xew-plugin" target="_blank" class="" style="" id="yui_3_16_0_1_1417345481659_14463">https://github.com/dmak/jaxb-<wbr class="" style="">xew-plugin</a><br class="" style=""><br class="" style="">The fact that Java SDK provides decorator for each specific<br class="" style="">resource collection (like DataCenters), instead of having ONE<br class="" style="">resource collection type, greatly complicates overall design<br class="" style="">and code-gen aspect.<br class="" style=""></div></blockquote><div class="" style="" id="yui_3_16_0_1_1417345481659_14464"><br class="" style=""></div></div></div><div class="" style="" id="yui_3_16_0_1_1417345481659_14466"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_14465">[MP]&nbsp;Well, i guess now is speaking JS constraints ghost, am i right?</font>,<br class="" style=""></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12513"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_12514">in any case, the reasons for having decorator per collection are:<br class="" style=""><br class="" style=""></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12512"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_12511">1. compliance with REST API (all SDKs and REST api are sharing same well know architecture)<br class="" style=""></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12510"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_12509">2. "decorator" is a well known and commonly used java design pattern<br class="" style=""></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12508"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_12507">3. having one resource type serving all collections would create a bottleneck<br class="" style=""></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_12505">(well it might depend on how you implementing it, but still in my view it's less convenient/readable<br class="" style="">than dedicated collection with own context, verbs and behavior),&nbsp;</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506"><font size="4" class="" style=""><br></font></div><font size="4" class="" id="yui_3_16_0_1_1417345481659_12521" style="">after all the purpose of sdk is being java client serving application in "Java" way</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9926" dir="ltr"><font size="4" class="" style="">(i.e type-safe + well bounded interface),&nbsp;</font><font size="4" class="" id="yui_3_16_0_1_1417345481659_12521" style="font-size: large;">while JS use-cases &amp; paradigms are totally</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9926" dir="ltr"><font size="4" class="" style="font-size: large;">different</font><span class="" id="yui_3_16_0_1_1417345481659_16206">,&nbsp;</span><span style="font-size: large;">just consider:</span><div class="" style="" id="yui_3_16_0_1_1417345481659_12506"><font size="4" class="" style=""><br></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_16215">[1] java-sdk stile</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style=""><br></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_12981">Disk snapshotDisk = api.getVms().get('my-vm').getSnapshots().get('my-snapshot').getDisks().get('my-disk')</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style=""><br></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_12991">[2] JS style you propose</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style=""><br></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_12988">Disk snapshotDisk = getCollections().get(new Params[] { Disk.class, 'my-vm', 'my-snapshot', 'my-disk'})<br></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style=""><br></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_13000">notice:&nbsp;</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="">=====</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style=""><br></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_13698">in [2] you have a bunch of parameters disconnected form any context where order</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_13001">is *important* (other way you heuristic guesses what user meaning by these params won't work),</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_14446">obviously it's fragile and error prone,</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style=""><br></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_13697">while [1] is readable, well bounded, defending it's consumers from potentials errors</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_18064">(exactly what SDK should look like),</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style=""><br></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style="" id="yui_3_16_0_1_1417345481659_17133">hope it helps.</font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12506" dir="ltr"><font size="4" class="" style=""><br></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12520"><font size="4" class="" style=""><br class="" style=""></font></div><div class="" style="" id="yui_3_16_0_1_1417345481659_12522"><br><div class="" style="" id="yui_3_16_0_1_1417345481659_12976"><div data-tooltip="Hide expanded content" aria-label="Hide expanded content" id=":g8" class="" role="button" tabindex="0" style=""><img class="" src="https://ssl.gstatic.com/ui/v1/icons/mail/images/cleardot.gif" style="" data-id="cc22cabd-7587-31ae-35b3-0bad76861607"></div></div></div></div><div class="" style="" id="yui_3_16_0_1_1417345481659_9926"><br class="" style=""></div></div></div> <div class="qtdSeparateBR"><br><br></div><div class="yahoo_quoted" style="display: block;"> <div style="font-family: HelveticaNeue-Light, Helvetica Neue Light, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif; font-size: 16px;"> <div style="font-family: HelveticaNeue, Helvetica Neue, Helvetica, Arial, Lucida Grande, sans-serif; font-size: 16px;"> <div dir="ltr"> <font size="2" face="Arial"> On Friday, November 28, 2014 5:26 PM, Vojtech Szocs &lt;vszocs@redhat.com&gt; wrote:<br> </font> </div>  <br><br> <div class="y_msg_container">Hi guys,<br><br>since the initial (small, working &amp; well-tested) version of oVirtJS<br>JavaScript SDK is finished [*], I've started working on GWT wrapper<br>for oVirtJS.<br><br>While analyzing/reverse-engineering oVirt Java SDK, some thoughts<br>came to my mind, and I wanted to share them with you.<br><br>[*] TODO(vszocs) upload new patchset with all recent changes<br><br>First, the way XJC (JAXB binding compiler that generates Java beans<br>out of REST XSD schema) is invoked looks a bit weird to me, as Java<br>SDK's XsdCodegen does this:<br><br>&nbsp; Runtime.getRuntime().exec(command)<br><br>Why not simply use existing Maven plugins to invoke XJC?<br>- either: <a href="https://github.com/highsource/maven-jaxb2-plugin" target="_blank">https://github.com/highsource/maven-jaxb2-plugin</a><br>- or: <a href="http://mojo.codehaus.org/jaxb2-maven-plugin/" target="_blank">http://mojo.codehaus.org/jaxb2-maven-plugin/</a><br><br>Second, and most importantly, what's the point of having "group"<br>entities? I'll give an example - api.xsd contains this:<br><br>&nbsp; &lt;xs:complexType name="DataCenters"&gt;<br>&nbsp; &nbsp; &lt;xs:complexContent&gt;<br>&nbsp; &nbsp; &nbsp; &lt;xs:extension base="BaseResources"&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &lt;xs:sequence&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;xs:annotation&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;xs:appinfo&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;jaxb:property name="DataCenters"/&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/xs:appinfo&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/xs:annotation&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;xs:element ref="data_center" minOccurs="0" maxOccurs="unbounded"/&gt;<br>&nbsp; &nbsp; &nbsp; &nbsp; &lt;/xs:sequence&gt;<br>&nbsp; &nbsp; &nbsp; &lt;/xs:extension&gt;<br>&nbsp; &nbsp; &lt;/xs:complexContent&gt;<br>&nbsp; &lt;/xs:complexType&gt;<br><br>(Same as above for Hosts, Clusters, VMs, etc.)<br><br>This results in following (IMHO rather meaningless) Java class<br>being generated by XJC:<br><br>public class DataCenters extends BaseResources {<br><br>&nbsp; &nbsp; @XmlElement(name = "data_center")<br>&nbsp; &nbsp; protected List&lt;DataCenter&gt; dataCenters;<br><br>&nbsp; &nbsp; public List&lt;DataCenter&gt; getDataCenters() {<br>&nbsp; &nbsp; &nbsp; &nbsp; if (dataCenters == null) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dataCenters = new ArrayList&lt;DataCenter&gt;();<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; return this.dataCenters;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; public boolean isSetDataCenters() {<br>&nbsp; &nbsp; &nbsp; &nbsp; return ((this.dataCenters!= null)&amp;&amp;(!this.dataCenters.isEmpty()));<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; public void unsetDataCenters() {<br>&nbsp; &nbsp; &nbsp; &nbsp; this.dataCenters = null;<br>&nbsp; &nbsp; }<br><br>}<br><br>Instead, we could use @XmlElementWrapper as described in [1]<br>to avoid generating "group" entities altogether.<br><br>[1] <a href="https://github.com/dmak/jaxb-xew-plugin" target="_blank">https://github.com/dmak/jaxb-xew-plugin</a><br><br>The fact that Java SDK provides decorator for each specific<br>resource collection (like DataCenters), instead of having ONE<br>resource collection type, greatly complicates overall design<br>and code-gen aspect.<br><br>In oVirtJS GWT wrapper, we'll avoid above complication through<br>single resource collection type (having common methods like<br>get(id), list() etc) for all resources.<br><br>Regards,<br>Vojtech<br>_______________________________________________<br>Devel mailing list<br><a ymailto="mailto:Devel@ovirt.org" href="mailto:Devel@ovirt.org">Devel@ovirt.org</a><br><a href="http://lists.ovirt.org/mailman/listinfo/devel" target="_blank">http://lists.ovirt.org/mailman/listinfo/devel</a><br><br><br></div>  </div> </div>  </div> </div>