Package org.marketcetera.util.ws.stateful

Web services infrastructure.

Usage

See the test classes of the org.marketcetera.util.ws.sample package.

Limitations/Known issues

Below are limitations/known issues with the current implementation of web services. All limitations are due to the underlying third-party libraries used to implement web services (Apache CXF and JAXB).

  • Every class that needs to be marshalled must have an empty constructor. Any classes marshalled by an exception (e.g. as properties of an exception) must have a public empty constructor; for all other classes, that empty constructor can be private. For custom exceptions (custom replacements of RemoteException), a single-argument String constructor also works, and is supplied the fault message during unmarshalling. Property getters and setters must be public

  • A class C that needs to be marshalled and that has a type parameter T may not have T[] properties. Also, in certain instances, the marshaller can get confused when such classes are used in the context of arrays (e.g. use C[] instead of C<?>[] or C<Foo>[]) or nested generics (e.g. use Bar<C>[] instead of Bar<C<?>>[] or Bar<C<Foo>>[]).

  • Generally, be cautious about generics because the actual type to which T is bound is not available at run-time. For example, assume C has a property of type T, and T has a lower bound of, say, Map<?,?>. You can write code that binds T to a TreeMap<?,?>. However, as discussed below, the marshaller will always send across the wire a tree map as a hash map, and will only create a tree map again if the runtime introspection of C tells the marshaller that the property must be a tree map. But the runtime introspection will yield a Map<?,?> (the lower bound), and so you will get a hash map assigned to a variable which will now execute in the context of code that expects a tree map.

  • Extending the previous point, consider this pitfall as well: a service has an argument of type A<B> declared as A<T extends BaseT> (and thus B is a descendant of BaseT), then JAXB will not create a support class for B because run-time reflection of A will trigger the creation of a BaseT support class, not a B one. Hence marshalling will encounter problems unless there is some method (or property) anywhere within the same service interface that makes direct use of B which thereby forces JAXB to create a support class for B (this can be accomplished using the @XmlSeeAlso annotation, instead). Note that such errors will occur only at run-time and when the argument above is operated upon in such a manner that B comes into play.

  • @XmlTransient, unlike regular annotations, is inherited. This means that a parent class which has annotated a property as transient will prevent a child class from marshalling a property by the same name.

  • A class that needs to be marshalled may not have a property whose type is a non-static inner class.

  • If the marshaller marshals an object of type B (e.g. a class has a property of type B), then the unmarshalled object will always be of type B, even if the actual runtime type of the object originally supplied to the marshaller is of a class derived from B. To enable support of inherited classes, you need to add some method (or property) anywhere within the same service interface that makes direct use of each inherited class (or use the @XmlSeeAlso annotation).

  • The previous point also applies to exceptions thrown by service methods. However, for exceptions, it is possible to add multiple classes in the throws clause of a method, incl. classes which may be related by super/subclass relationships. In that case, the actual exception class will be unmarshalled if it is one of the classes in the clause. Unlike regular objects, adding an exception subclass D (extending B) in a different method of the same service interface (or using the @XmlSeeAlso annotation) will not enable marshalling of a D exception as a D within a method whose throws clause lists only B explicitly.

  • Character objects (meaning Character, not char primitives) are sometimes treated as integers, and hence are not marshalled properly; strings (provided they do not contain certain illegal characters like ) and char primitives (of all values) are properly marshalled. Specifically, Character objects as method arguments/results have problems when used in maps.

  • Date objects are sometimes treated as calendars, and hence are not marshalled properly. Specifically, Date objects as method arguments/results have problems when used in maps. Worse, even outside maps, JAXB does not marshall dates correctly in certain time zones, including GMT: it adds an hour to the marshalled date. Hence, wrap Date objects by a DateWrapper which remedies the above shortcomings.

  • Collections and maps undergo special handling during marshalling. When a set needs to get marshalled, it is always converted to a HashSet; a collection to an ArrayList; and a map to a HashMap. During unmarshalling, if the desired type is the generic collection/set/map interface, there is no need for further processing. However, if the desired type is, say, a tree set, then an empty tree set is created, and then stuffed with the elements of the transferred HashSet. A drawback of this process is that it is not possible to transfer sorted collections/maps of elements that do not implement Comparable because the comparator itself is not marshalled.

  • Maps (the Map interface or HashMap or TreeMap) cannot be used as method arguments or results; but they can be used as properties. To pass a map as a method argument/result, use MapWrapper.

Since:
1.0.0
Version:
$Id: package-info.java 16154 2012-07-14 16:34:05Z colin $
Author:
tlerios@marketcetera.com, anshul@marketcetera.com