Web service and polymorphism

This page present several options to define a web service interface that uses polymorphism on list of objects. It compares various possible web service interface definition.

My preferred pattern is #5. It was used in one of our web service and works nice.

See also http://www.ibm.com/developerworks/webservices/library/ws-tip-xsdchoice.html

Wrapper with two collections

1
Name Wrapper with two collections
Description Declaration of two list to hold each kind of filters
Java definition
Class FilterClause
{
 @XmlElement(name="termFilter")
 List<TermFilter> termFilers;
 @XmlElement(name="fullTextFilter")
 List<FullTextFilter>   ftFilters;
}
Distinction between null or empty list Yes – if lists are empty, filterClause tag is still there
Expected SOAP request <filterClause>
<termFilter>
<name>edoc:Date</name>
<operator>=</operator><value>2005-10-10</value>
</termFilter>
</filterClause>
Pro
  • Simple
Cons
  • Not extensibility: a new subtype require a new list and to re-generate the stub on the client side
  • To add a new subtype, a new list must be added in the class
  • Not very Object-oriented

Wrapper with polymorphism on tag name

2
Name Wrapper with polymorphism on tag name (xsd :choice)
Description Declaration of one list with xsd:choice to distinguish the type of the elements and change the tag accordingly
Java definition
public class FilterClause
{ @XmlElements({
@XmlElement(name="termFilter", type=TermFilter.class),
@XmlElement(name="fullTextFilter",type=FullTextFilter.class)
})private Listfilter; }
Distinction between null or empty list Yes – if lists are empty, filterClause tag is still there
Expected SOAP request <filterClause>
<termFilter>
<name>edoc:Date</name>
<operator>=</operator><value>2005-10-10</value>
</termFilter>
</filterClause>
Pro
  • Extensibility to new subtype without the need to re-generate the stub on the client side
  • XML is easily readable
Cons
  • To add a new subtype  a new @XmlElement entry must be added manually

Wrapper with polymorphism with xsi:type

3
Name Wrapper with polymorphism with xsi:type
Description Usage of a wrapper with the declaration of one list using base type – polymorphism is detected automatically by JAXB & .NET
Java definition
public class FilterClause
{@XmlElement(name="filter")private Listfilters;}
Distinction between null or empty list Yes – if lists are empty, filterClause tag is still there
Expected SOAP request <filterClause>
<filter xmlns:q1=”http://www.imtf.com/hypersuite/hydra&#8221; xsi:type=”q1:termFilter”>
<name>edoc:Date</name>
<operator>=</operator>
<value>2005-10-10</value>
</filter>
</filterClause>
Pro
  • Extensibility to new subtype without the need to re-generate the stub on the client side
  • XML is easily readable because of the wrapper tag
Cons
  • To add a new subtype  a new @XmlElement entry must be added manually
  • Wrapper tag is useless except for readability

Polymorphic list on tag name

4
Name Polymorphic list on tag name (xsd :choice)
Description Same as 2 without wrapper
Java definition Can not be defined in Java, because @XmlElement can not be applied on the parameter of a method signature
Distinction between null or empty list No – if list is empty or null not tags are written
Expected SOAP request <termFilter>
<name>edoc:Date</name>
<operator>=</operator><value>2005-10-10</value>
</termFilter>
Pro See comment in Java definition
Cons See comment in Java definition

Polymorphic list with xsi:type

5
Name Polymorphic list with xsi:type
Description Same as 3 without wrapper
Java definition
 @XmlSeeAlso({FullTextFilter.class,TermFilter.class})
public class XXXX
{
@WebParam(name="filter")
List<Filter> filters;
Distinction between null or empty list No – if list is empty or null not tags are written
Expected SOAP request <filter xmlns:q1=”http://www.imtf.com/hypersuite/hydra&#8221; xsi:type=”q1:termFilter”>
<name>edoc:Date</name>
<operator>=</operator>
<value>2005-10-10</value>
</filter>
Pro
  • Extensibility to new subtype without the need to re-generate the stub on the client side
  • All subtypes can be defined in a secondary XSD that is imported in the WSDL
Cons
  • To add a new subtype  a new @XmlSeeAlso entry must be added manually

Fun with iTune Shuffle and Probabilities

I recently tagged and imported all my mp3 into iTune. I noticed then that there were lots of albums that I had only partially listened to and I decided to use the feature “Party Shuffle” to listen to my library randomly and eventually hear all the songs.

After a couple of weeks, I observed that some songs would reappear in the playlist and were picked twice. Over the weeks the frequency of “re-entry” songs increased with the direct consequence that new music was played less and less. Even though I had already realized that it would not be possible to hear all the songs with approach, I was still surprised by the “re-entry” rate, which I would have intuitively expected to be much lower.

I turned to probability to better understand the situation.

Let’s n be the size of my library. After t songs played randomly, the probability that a given song was played at least once is:

P( song played at least once ) = t / n.

Absolutely not! This probability can be computed with 1 – probability that the song was never played. This gives:

      P( song played at least once ) = 1 – (( n-1 )/ n)  ^ t

More generally, the probability of a song having been played x times is given by the function

P( x ) = (1/n)^x * ( (n-1) / n )^(t-x) * C ( n, x  )

Where C(n,x) is the number of possible permutation. The expanded

P( x ) = (1/n)^x * ( (n-1) / n )^(t-x) *  n! / (n-x) ! x!

Note that the probability that the song was never played (x=0) is still (( n-1 )/ n)  ^ t.

After t songs, the sum P(0) + P(1) + … + P(t) = 1, which proves that the formula is correct.

The average number of songs played in the library after t songs, can be computed with

Avg. played

 = n * P( song played at least once )

= n * ( 1 – ((n-1)/n)^t ) = n – (n-1)^t  / n^(t-1)

The “re-entry” rate, or the probability of hearing a new song can be computed with (n- avg. played) / n which is equivalent to the probability that a given song was never played P(x=0).

The graph bellows shows the probability that a song was never played for a library of 500 songs, after 0, 50, 100, etc. songs. It’s interesting to notice that the probability of new songs fall below 50% after about 300 songs.

iTune_probability

More:

Spotify noticed this as well 🙂

Spotify Updates Shuffle to Keep Your Playlists Feeling Fresh

Database independent SQL: a checklist

Pure SQL data layers tend to disappear in favour of O/R mapper which embed they own query language. The languages of today’s O/R mapper (e.g: Hibernate, JPA, etc.) is still close to the underlying target SQL syntax. Actually, some keywords in Hibernate will be taken as-is form HQL to SQL which means that using an O/R mapper does not provide 100% database independence necessary. There are also frequently a few native queries here and there to perform data-intensive operation that are easily realized with pure SQL, and do not match well with the object approach. Therefore it is still relevant to think about SQL-92 convention and to keep the SQL and HQL the more independent as possible. Below is a checklist I wrote a few years back when I was involved in the migration of a project from Informix to Oracle.

  • Outer join & inner join
    Review the syntax of your joins.
  • AS keyword
    There is no need of a special keyword to alias a column.
  • Function (SQL92 or not)
    Try to avoid using database function. If it’s absolutely necessary prefer the SQL92 subset and make your code easily portable.
  • Operator ==
    The SQL92 standard uses = for equality.
  • Case type: num vs char
    Complex SQL using case statement can be rewritten to be SQL92 compliant
  • lock columm name (reserved words)
    Each RDMS has a list of reserved keywords. Try to avoid such name to make your SQL portable.
  • No usage of *
    Do never use * to return rows with select. The order of your column is part of the physical database model and your code should work with the logical database model. Chances are, that the column order with change over time due to migration, or extension of the database model.