Posted by ddevore
on April 26, 2006 at 1:51 PM PDT
I have created an object to pass dynamic data to and from Web Services. I am blogging it because I want to know how others feel about this type of object.
Versioning of Web Services is difficult with many different factors to consider, which is beyond the scope of this blog. Lets say it is safe to say that you need to make Web Services backwards compatible for as long as possible. To do this you cannot change an existing operation, parameter, or return object. Also, you want to keep a concise operation list. So if you had an operation named getXYZ() which returns an object which you are certian will change to meet the business needs how do you do this?
I considered a couple of different options. Some listed below.
- Empty Fields
- Array of Strings
- An array of String with the attribute, name, and value delimited within it
- 2D Array
- 2 Arrays of String
- SDO (JSR-235 )
Each didn't work for one reason or another.
Empty Fields - How many do you add and what do you name them because they will never be the name of the data you will need. Besides that it's just a bad idea.
Array of Strings - They would always have to be in the same order and there is the possibility of getting an index out of bounds exception, I don't like exceptions.
An array of String with the attribute, name, and value delimited within it - What do you use as a delimiter that you know for a fact will never show up in a String representation of an object.
2D Array - Same as above but doubled and not supported by JAX-RPC.
Collection - Not supported by JAX-RPC.
SDO - Too much overhead and didn't like it.
Self Describing Data Object (SDDO)
This object uses a Map, HashMap to be exact, to hold the data and an array of KVData (Key Value Data) Objects which is used to fake out the XML parser to think that the data is an array. In the get method for the data array it converts the values in the Map to KVData objects and puts them into an array and returns them. In the set method for the data array it simply puts the data back into the Map for easier data access.
The KVData object is a simple object which only holds 3 Strings key, value, and dataType. The key is the key name for the data, the value is the data value, and the dataType is the value.getClass().getName(). To instantiate the data on the other side I use reflection to create the object and set the data using the getDeclaredConstructor(String.class) method. Using this method you can recreate any object that can be created with the same String value the object returns from the toString() method. Since Calendar and Date are JAX-RPC data objects and they do not have a String constructor I had to treat these as special cases.
To insure proper operations and to avoid null pointers I choose to return a blank String if a requested key value is not found. This allows you to even remove data from the object without worrying about this object getting null pointers. This is a safe guard for the unexpected. We have created a Web Service Contract which all Web Services must abide by.
"A Web Service cannot remove or change existing operations. A Web Service cannot remove or change parameters, or return values."
Considering that the SDDO is not changed and the attributes within the SDDO are only added to making an addition to the SDDO attributes does not break this contract.
We also create Web Service Clients for our Web Services for use internally. With the SDDO a client will operate correctly as long as the contract is adhered to. In fact with a little care the client will operate correctly even if attributes are removed from the SDDO.
This object solves a couple of difficult problems with Web Services without versioning the service.
- You can dynamically add data to Web Service parameters or return values.
- You can remove data from a Web Service parameter or return value. This is dangerous though because you don't know what the clients are doing with this data.
- Client code does not have to be changed to account for additional attributes added to the SDDO if the client does not care about the additional data.
- This eases versioning changes due to data changes when the SDDO is used.
- You can create wrappers for the SDDO for a set of attributes, such as an account, and have it still look like a pojo.
- A wrapper can act as the attribute documentation of the SDDO.
With all good there is the bad.
- XML size is close to trippled for the SDDO because the need of passing the key and dataType values.
- An SDDO without an clearly defined set of attributes will be very difficult to understand, this is a design issue though.
- If you use a wrapper to make the SDDO look like a pojo it will take some extra work, using an IDE such as NetBeans though you can minimize that work.
This object is not meant to be used with a set of data such as an address. An address has a clearly defined set of fields which do not change and therefor does not need a dynamic object such as this. An SDDO is not meant to be a replacement for good object design.
Voice your opinion
Please voice your opinion by commenting to this topic. If there is enough interest in seeing the source I will post it also.