ref_send API 2.17
defensive programming in Java

Package org.ref_send

A pass-by-construction interface.

See:
          Description

Interface Summary
Record A pass-by-construction object.
 

Annotation Types Summary
deserializer Marks the deserialization constructor.
name Provides a parameter's name.
 

Package org.ref_send Description

A pass-by-construction interface.

The ref_send API supports the design of interfaces that work well in a distributed application. One of the differences between a local application and a distributed application is the importance of pass-by-copy data. In a local application, the difference between accessing a variable versus calling a method may be negligible. In a distributed application, the difference may be significant since an additional network request may be required for the method invocation. This network request negatively impacts performance since an additional network round-trip is required. More importantly though, the additional network request complicates the client code since it must now cope with the timing issues and failure modes that come with doing a network request. Client code is often much simpler when all the data it needs can be provided as one bundle. To support creating such data bundles, this package defines an API for declaring a pass-by-construction class. When an object of such a class is sent in a method invocation, or return, its publicly accessible state is sent, instead of a remote reference. Similarly, such an object can be reconstructed when its state is received as part of a method invocation.

A class can be made pass-by-construction simply by declaring it to be so and annotating one of its public constructors with information mapping the class' public fields to its constructor parameters. For example:

 package org.example.membership;
 
 import org.joe_e.Struct;
 import org.ref_send.deserializer;
 import org.ref_send.name;
 import org.ref_send.Record;
 
 import java.io.Serializable;
 
 /**
  * Information about a club member.
  */
 public class
 LoyaltyCard extends Struct implements Record, Serializable {
     static private final long serialVersionUID = 1L;
 
     /**
      * member's full name
      */
     public final String name;
 
     /**
      * year membership began
      */
     public final int year;
 
     /**
      * Is a premium member?
      */
     public final boolean premium;
 
     /**
      * Constructs an instance.
      * @param name    {@link #name}
      * @param year    {@link #year}
      * @param premium {@link #premium}
      */
     public @deserializer
     LoyaltyCard(@name("name") final String name,
                 @name("year") final int year,
                 @name("premium") final boolean premium) {
         this.name = name;
         this.year = year;
         this.premium = premium;
     }
 }
 

The Javadoc comments in the above example are purely optional. The important steps are:

When using the Waterken Server, a remote invocation whose sole argument is an instance of the class above results in an HTTP request with the following JSON data:

 [ {
   "class" : [ "org.example.membership.LoyaltyCard" ],
   "name" : "Tyler Close",
   "year" : 2008,
   "premium" : true
   } ]
 

The networking code in the Waterken Server automatically recognizes which invocation arguments are Record objects and produces the corresponding JSON data for them. You can create an arbitrarily large JSON document by constructing an arbitrarily deep tree of Record objects. For example, the class below adds an address and array of tags:

 package org.example.membership;
 
 import org.joe_e.array.PowerlessArray;
 import org.ref_send.deserializer;
 import org.ref_send.name;
 
 /**
  * Postal information about a club member.
  */
 public class
 MailingLoyaltyCard extends LoyaltyCard {
     static private final long serialVersionUID = 1L;
 
     /**
      * postal address
      */
     public final Address mailto;
 
     /**
      * a list of tags indicating mailing preferences
      */
     public final PowerlessArray<String> preferences;
 
     /**
      * Constructs an instance.
      * @param name        {@link #name}
      * @param year        {@link #year}
      * @param premium     {@link #premium}
      * @param mailto      {@link #mailto}
      * @param preferences {@link #preferences}
      */
     public @deserializer
     MailingLoyaltyCard(
           @name("name") final String name,
           @name("year") final int year,
           @name("premium") final boolean premium,
           @name("mailto") final Address mailto,
           @name("preferences") final PowerlessArray<String> preferences) {
         super(name, year, premium);
         this.mailto = mailto;
         this.preferences = preferences;
     }
 }
 

An instance of the above class would produce JSON like:

 {
   "class" : [ "org.example.membership.MailingLoyaltyCard", "org.example.membership.LoyaltyCard" ],
   "name" : "Tyler Close",
   "year" : 2008,
   "premium" : true,
   "mailto" : {
     "street" : "1501 Page Mill Road",
     "city" : "Palo Alto",
     "state" : "CA",
     "zip" : "94304"
   },
   "preferences" : [ "2-day-shipping", "monthly" ]
 }
 

The value of the "class" member is an array listing the name of every type implemented by the object, ordered from most specific to least. If the most specific type of an object is implied by the referring object, the type declaration is omitted. For example, the object referred to by the "mailto" member is not annotated with a "class" member, since the type org.example.membership.Address is implied by the referring object's type "org.example.membership.MailingLoyaltyCard".

By making effective use of Record objects, you can create distributed applications in the document-oriented messaging style. In such applications, clients and servers coordinate primarily based on the content of exchanged documents, rather than on expectations about remotely maintained state. Such designs can sometimes result in fewer dependencies between clients and servers and so facilitate the creation of interoperable software. When using the ref_send API, you define the structure of your exchanged documents by defining a set of Record types. Each exchanged document is then created by composing an object tree from these Record types.

See Also:
org.ref_send.scope

ref_send API 2.17
defensive programming in Java

Submit a bug or feature, or get help

Copyright 1998-2009 Waterken Inc. under the terms of the MIT X license.