[ovirt-devel] Some ideas on oVirt Java SDK

Vojtech Szocs vszocs at redhat.com
Mon Dec 1 15:01:01 UTC 2014


Hey Michael!

good to hear from you, please see my comments below.


----- Original Message -----
> From: "Michael Pasternak" <mishka8520 at yahoo.com>
> To: "Vojtech Szocs" <vszocs at redhat.com>, devel at ovirt.org
> Cc: "Juan Antonio Hernandez Fernandez" <jhernand at redhat.com>
> Sent: Sunday, November 30, 2014 12:26:06 PM
> Subject: Re: [ovirt-devel] Some ideas on oVirt Java SDK
> 
> Hey Vojtech,
> 
> How are you?, please see my reply inline.
> 
> 
> 
> 
>       On Friday, November 28, 2014 5:26 PM, Vojtech Szocs <vszocs at redhat.com>
>       wrote:
>    
> 
>  Hi guys,
> 
> since the initial (small, working & well-tested) version of oVirtJS
> JavaScript SDK is finished [*], I've started working on GWT wrapper
> for oVirtJS.
> 
> While analyzing/reverse-engineering oVirt Java SDK, some thoughts
> came to my mind, and I wanted to share them with you.
> 
> [*] TODO(vszocs) upload new patchset with all recent changes
> 
> First, the way XJC (JAXB binding compiler that generates Java beans
> out of REST XSD schema) is invoked looks a bit weird to me, as Java
> SDK's XsdCodegen does this:
> 
>   Runtime.getRuntime().exec(command)
> 
> Why not simply use existing Maven plugins to invoke XJC?
> - either: https://github.com/highsource/maven-jaxb2-plugin
> 
> 
> [MP] sdk was using jaxb to begin with, it was replaced with XJC just
> recently,

OK, so if I get this correctly: before XJC was used (to generate
Java beans from XSD), Java SDK contained hand-maintained Java beans
and used JAXB RI (runtime implementation) to load objects from XSD?

(And same hand-maintained Java beans were, as you wrote below, also
used in REST API backend webapp, i.e. that part of code was shared?)

> btw Juan, what was the motivation behind this?
> (REST api uses jaxb as well so we used to have 1x1 mappings)
>  
> - or: http://mojo.codehaus.org/jaxb2-maven-plugin/
> 
> 
> [MP] same.
> 
> 
> 
> Second, and most importantly, what's the point of having "group"
> entities? I'll give an example - api.xsd contains this:
> 
>   <xs:complexType name="DataCenters">
>     <xs:complexContent>
>       <xs:extension base="BaseResources">
>         <xs:sequence>
>           <xs:annotation>
>             <xs:appinfo>
>                 <jaxb:property name="DataCenters"/>
>             </xs:appinfo>
>           </xs:annotation>
>           <xs:element ref="data_center" minOccurs="0" maxOccurs="unbounded"/>
>         </xs:sequence>
>       </xs:extension>
>     </xs:complexContent>
>   </xs:complexType>
> 
> (Same as above for Hosts, Clusters, VMs, etc.)
> 
> This results in following (IMHO rather meaningless) Java class
> being generated by XJC:
> 
> public class DataCenters extends BaseResources {
> 
>     @XmlElement(name = "data_center")
>     protected List<DataCenter> dataCenters;
> 
>     public List<DataCenter> getDataCenters() {
>         if (dataCenters == null) {
>             dataCenters = new ArrayList<DataCenter>();
>         }
>         return this.dataCenters;
>     }
> 
>     public boolean isSetDataCenters() {
>         return ((this.dataCenters!= null)&&(!this.dataCenters.isEmpty()));
>     }
> 
>     public void unsetDataCenters() {
>         this.dataCenters = null;
>     }
> 
> }
> 
> Instead, we could use @XmlElementWrapper as described in [1]
> to avoid generating "group" entities altogether.
> 
> [1] https://github.com/dmak/jaxb-xew-plugin
> 
> The fact that Java SDK provides decorator for each specific
> resource collection (like DataCenters), instead of having ONE
> resource collection type, greatly complicates overall design
> and code-gen aspect.
> 
> 
> [MP] Well, i guess now is speaking JS constraints ghost, am i right?,
> in any case, the reasons for having decorator per collection are:
> 
> 1. compliance with REST API (all SDKs and REST api are sharing same well know
> architecture)
> 2. "decorator" is a well known and commonly used java design pattern
> 3. having one resource type serving all collections would create a bottleneck
> (well it might depend on how you implementing it, but still in my view it's
> less convenient/readable
> than dedicated collection with own context, verbs and behavior),

I agree with your points. What I wanted to say is that all existing
resource collection decorator classes aren't too different from each
other - each collection has well-known API like list(), get(id) etc.

Sure, there are small differences, i.e. root collections have some
extra methods with extra params like Bookmarks.list() having params
like "query", "caseSensitive", "max" etc.

I guess the reason of generating per-collection decorator are above
mentioned differences. Perhaps later when oVirtJS GWT wrapper will
be more mature, we'll end up with per-collection class too, but for
now, we'll keep things simple and have single collection class with
well-known API like list(), get(id) etc.

> after all the purpose of sdk is being java client serving application in
> "Java" way(i.e type-safe + well bounded interface), while JS use-cases &
> paradigms are totallydifferent, just consider:
> [1] java-sdk stile
> Disk snapshotDisk =
> api.getVms().get('my-vm').getSnapshots().get('my-snapshot').getDisks().get('my-disk')

Above style is synchronous, which means this style is not applicable
to web application environment (it makes no sense to write blocking
JavaScript code). Also, REST HTTP web interface is asynchronous in
its very nature.

In oVirtJS GWT wrapper, accessing items of resource collection
is explicitly modeled as asynchronous operation, for example:

// notice we use 'ResourceOperation' instead of 'DataCenters'
ResourceOperation<DataCenter> op = api.getDataCenters().get('dc-id');
op.run(callback); // translates to HTTP GET request with given callback

> [2] JS style you propose
> Disk snapshotDisk = getCollections().get(new Params[] { Disk.class, 'my-vm',
> 'my-snapshot', 'my-disk'})

Not sure what you mean here, but above isn't what I had in mind :)

We'll still generate Java code for oVirtJS GWT wrapper, we'll also
use XJC (and most likely, write our own XJC plugin to adapt it more)
as well. However, there should be much clearer separation between
various concepts:

- resource (containing data + operations) vs. resource data itself
- resource collection containing uniform API
- explicit asynchronous API representing resource operations

Hope this helps to explain design we're trying to achieve.

> 
> notice: =====
> in [2] you have a bunch of parameters disconnected form any context where
> orderis *important* (other way you heuristic guesses what user meaning by
> these params won't work),obviously it's fragile and error prone,
> while [1] is readable, well bounded, defending it's consumers from potentials
> errors(exactly what SDK should look like),
> hope it helps.

I agree, but API style you wrote above in [2] isn't what I had in
mind - we'll still generate code that will resemble Java SDK code.

> 
> 
> 
>  
> 
>      On Friday, November 28, 2014 5:26 PM, Vojtech Szocs <vszocs at redhat.com>
>      wrote:
>    
> 
>  Hi guys,
> 
> since the initial (small, working & well-tested) version of oVirtJS
> JavaScript SDK is finished [*], I've started working on GWT wrapper
> for oVirtJS.
> 
> While analyzing/reverse-engineering oVirt Java SDK, some thoughts
> came to my mind, and I wanted to share them with you.
> 
> [*] TODO(vszocs) upload new patchset with all recent changes
> 
> First, the way XJC (JAXB binding compiler that generates Java beans
> out of REST XSD schema) is invoked looks a bit weird to me, as Java
> SDK's XsdCodegen does this:
> 
>   Runtime.getRuntime().exec(command)
> 
> Why not simply use existing Maven plugins to invoke XJC?
> - either: https://github.com/highsource/maven-jaxb2-plugin
> - or: http://mojo.codehaus.org/jaxb2-maven-plugin/
> 
> Second, and most importantly, what's the point of having "group"
> entities? I'll give an example - api.xsd contains this:
> 
>   <xs:complexType name="DataCenters">
>     <xs:complexContent>
>       <xs:extension base="BaseResources">
>         <xs:sequence>
>           <xs:annotation>
>             <xs:appinfo>
>                 <jaxb:property name="DataCenters"/>
>             </xs:appinfo>
>           </xs:annotation>
>           <xs:element ref="data_center" minOccurs="0" maxOccurs="unbounded"/>
>         </xs:sequence>
>       </xs:extension>
>     </xs:complexContent>
>   </xs:complexType>
> 
> (Same as above for Hosts, Clusters, VMs, etc.)
> 
> This results in following (IMHO rather meaningless) Java class
> being generated by XJC:
> 
> public class DataCenters extends BaseResources {
> 
>     @XmlElement(name = "data_center")
>     protected List<DataCenter> dataCenters;
> 
>     public List<DataCenter> getDataCenters() {
>         if (dataCenters == null) {
>             dataCenters = new ArrayList<DataCenter>();
>         }
>         return this.dataCenters;
>     }
> 
>     public boolean isSetDataCenters() {
>         return ((this.dataCenters!= null)&&(!this.dataCenters.isEmpty()));
>     }
> 
>     public void unsetDataCenters() {
>         this.dataCenters = null;
>     }
> 
> }
> 
> Instead, we could use @XmlElementWrapper as described in [1]
> to avoid generating "group" entities altogether.
> 
> [1] https://github.com/dmak/jaxb-xew-plugin
> 
> The fact that Java SDK provides decorator for each specific
> resource collection (like DataCenters), instead of having ONE
> resource collection type, greatly complicates overall design
> and code-gen aspect.
> 
> In oVirtJS GWT wrapper, we'll avoid above complication through
> single resource collection type (having common methods like
> get(id), list() etc) for all resources.
> 
> Regards,
> Vojtech
> _______________________________________________
> Devel mailing list
> Devel at ovirt.org
> http://lists.ovirt.org/mailman/listinfo/devel
> 
> 
> 



More information about the Devel mailing list