== Using own concete types == [http://delight.opendfki.de/wiki/ExampleUsingOwnConceteTypes#UsingowntypesinCollectionsandMaps Special case: Using own types in Collections and Maps.] Java's type erasure in action! === Server side === We want to use the type {{{Param}}} in our API. Normally, this will cause an error message. See how we can make this type XML-RPC compliant with only a few lines of code: {{{ public interface Api { Param returnParam(); void passAsParameter( Param p ); } public class Impl implements Api { public Param returnParam() { return createParam( ... ); } void passAsParameter( Param p ) { doSomethingWith( p ); } } }}} To use type Param, we have to make it XML-RPC compliant. We use java annotations and user-defined conversion operations to do this. - the @!XmlRpc annotation declares that type Param uses XML-RPC type ARRAY as transport representation - The interface {{{Convertable}} declares what specific java type is used for transfer via XML-RPC - toXmlRpc converts an instance of type Param into its XML-RPC representation - the constructor creates an instance of type Param back from it's XML-RPC representation {{{ @XmlRpc( type=Type.ARRAY ) public class Param implements Convertable> { public Param( Collection xmlRpcRepresentation ) { ... } public Collection toXmlRpc() { return ... } } }}} Now our type ist XML-RPC compliant! We can register the implementation as usual... {{{ WebServer xmlRpcServer = new WebServer( port ); xmlRpcServer.addHandler( "handlerId", XmlRpcHandlerFactory.createHandlerFor( new Impl() ); xmlRpcServer.start(); }}} === Client Side === Our client can be used without any extra statements: {{{ Api remote_api = XmlRpc.createClient( Api.class, "handlerId", host, port ); Param p = remote_api.returnParam(); Param asParam = ...; remote_api.passAsParameter( asParam ); ... }}} == Using own types in Collections and Maps == When turning generics into thier class representation, java runs a so called type erasure, reducing a Collection to a simple Collection. Thus, the XML-RPC runtime system cannot determine the content type of this collection unless the user places an extra hint using the @Contains annotation. {{{ // DOES NOT WORK: Map will be reduced to Map, Collection will be reduced to Collection public interface Api { Map returnMyParamInMap(); void passManyParams( Collection params ); } }}} Place a @Contains in front of the method to annotate a return type. Place it before a formal parameter to annotate method parameters. {{{ // WORKS! public interface Api { @Contains(Param.class) Map returnMyParamInMap(); void passManyParams( @Contains(Param.class) Collection params ); } }}} == Client Side == Now remote clients can also use Collections and Maps containing own types: {{{ Api remote_api = XmlRpc.createClient( Api.class, "handlerId", host, port ); Map map = remote_api.returnMyParamInMap(); for( Param p : map.values() ) { ... } remote_api.passManyParams( Collections.asList( new Param[]{new Param(), new Param()} ) ); ... }}}