wiki:ExampleUsingOwnInterfaceTypes

Version 4 (modified by lauer, 16 years ago) (diff)

--

Using Interface Types and Abstract Classes

The API is defined the same way as in the preceeding use case.

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 ); }
}

Since Param is an interface, the runtime system cannot create instances of this type without further information. We use the concrete attribute of the @XmlRpc annotation to tell the Delight runtime-system what concrete type to use to create instances of type Param.

In this case we use the concete class ParamImpl to create instances of type Param (note that ParamImpl has to be a Convertable and also has to implement Param):

@XmlRpc( type=Type.STRING, 
         concrete=ParamImpl.class )
public interface Param
{
    public String printContent() { ... }
}

public class ParamImpl implements Param, 
                                    Convertable<String>
{
    public ParamImpl( String xmlRpcRepresentation ) { processXmlRpc( xmlRpcRepresentation ); }

    public String toXmlRpc() { return( createXmlRpcRep() ); }
}

Client side

The client can be created and used without further actions to take. No factories to register. No configuration files to load. Just like a lokal call to the API.

Api remote_api = XmlRpc.createClient( Api.class, "handlerId", host, port );

Param p = remote_api.returnParam();
System.out.println( p.printContent() );

Param asParam = new ParamImpl(...);
remote_api.passAsParameter( asParam );

...

Using XmlRpcBeans in you API

What are XmlRpcBeans??

Sometimes parameter conversion is a straight-forward task which can be handed over to the XML-RPC runtime system. When a java class fulfills certain conditions (roughly, being a java bean with compatible types) it can be turned into a XmlRpcBean by annotating it with the @XmlRpcBean annotation. It then can be used in every XML-RPC call without restriction.

A XmlRpcBean must have

  • a public constructor taking no arguments
  • like a java bean: for each property which is supposed to be transported over XML-RPC there has to exist a public getter and setter method
  • each property type has to be a XML-RPC compliant type, that is it has to have one of the follwoing properties:
    • it is a standard XML-RPC type
    • it is annotated with a @XmlRpc annotation and defines proper conversion methods
    • a conversion mapping for that type is put at the XmlRpcBean (which then acts as an API itself)
    • it is an XmlRpcBean (that is, XmlRpcBeans can be nested)
    • it is a Collection or Map containing a type which is XML-RPC compliant and is annotated with the @Contains annotation

Technically, an XmlRpcBean is converted into a XML-RPC STRUCT. The field names of the tranfered map are the property names derived from the bean class.

Lets look at an example XmlRpcBean (note that this bean also defines a converter mapping for type URL):

@XmlRpcBean
@ConverterMappings( @Mapping(type=URL.class,converter=URLConverter.class) )
public class CoffeeBean
{
    public URL getOrigin()
    {
        return mOrigin;
    }
    public void setOrigin( URL origin )
    {
        mOrigin = origin;
    }
    public String getType()
    {
        return mType;
    }
    public void setType( String type )
    {
        mType = type;
    }
    
    public String toString()
    {
        return( "CoffeeBean(" + getType() + ") comming from '" + getOrigin() + "'" );
    }
    private String mType;
    private URL mOrigin;
}

Client side

Again, the client has no restrictions using the bean class:

public interface Api
{
    @Contains(CoffeeBean.class)
    Collection<CoffeeBean> getAllBeans();
}

----

Api remote_api = XmlRpc.createClient( Api.class, "handlerId", host, port );

Collection<CoffeeBean> beans = remote_api.getAllBeans();

for( CoffeeBeans b: beans )
{
    System.out.println( "Bean of type " + b.getType() + " comes from " + b.getOrigin() );
}
...

See also How to use own types in Collections an Maps.

Examples in source code: http://delight.opendfki.de/repos/trunk/XmlRpcDelight/src/examples/de/dfki/util/xmlrpc/examples/interfaces/