Powered by SmartDoc

The cdl.rmi option

The cdl.rmi option generates an RMI component from the RCDL or RIDL definition.

Parameters

The cdl.rmi option takes one of the following values as a parameter.

true
Generates an RMI component.
false
Does not generate an RMI component.

The default configuration is false. If there is no parameter, it implies that the parameter is true.

Artifact

The cdl.rmi option generates an RMI component from the RCDL or RIDL definition.

The cdl option generates the following base classes:

In addition to these base classes, the cdl.rmi option related classes shown below are generated.

The RMIINTERFACE and the RMIINTERFACEServer are important for programmars.

The RMIINTERFACE is a JavaBeans that acts as a front end against an application program. Because of this the RMIINTERFACE implements the API interface IINTERFACE. Application programs uses the RMIINTERFACE immdiately.

The RMIINTERFACEServer is an RMI server. This object is executed as the RMI server.

The INTERFACERemote, the INTERFACEClientProxy, The INTERFACEClient are used internally.

The IINTERFACERemote is a java interface to be used as an RMI interface. For this purpose, the IINTERFACERemote extends java.rmi.Remote.

The INTERFACEClientProxy is a client-side proxy object. The RMIINTERFACEClient is an another client-side proxy object.

The cdl.rmi option adds no additional methods to Relaxer objects or Relaxer table objects.

Example

List 18.3.3.1[cdlRmi.rcdl] is a sample RCDL definition, and List 18.3.3.2[cdlRmi.rng] is a sample RELAX NG schema used by the RCDL definition.

cdlRmi.rcdl
<component xmlns="http://www.relaxer.org/xmlns/cdl"
           namespace="http://example.com/account"
           name="backOffice">
  <interface namespace="http://example.com/account" name="accountManager">
    <grammar namespace="http://example.com/account" location="cdlRmi.rng"/>
    <operation name="findAccount">
      <in name="accountNo" type="token"/>
      <out label="account"/>
    </operation>
  </interface>
</component>
cdlRmi.rng
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
         datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
  <start>
    <ref name="account"/>
  </start>
  <define name="account">
    <element name="account">
      <attribute name="accountNo">
        <data type="token"/>
      </attribute>
      <element name="balance">
        <data type="int"/>
      </element>
      <element name="owner">
        <data type="token"/>
      </element>
      <ref name="address"/>
      <zeroOrMore>
        <ref name="phone"/>
      </zeroOrMore>
    </element>
  </define>
  <define name="address">
    <element name="address">
      <attribute name="zip">
        <data type="token"/>
      </attribute>
      <text/>
    </element>
  </define>
  <define name="phone">
    <element name="phone">
      <attribute name="area">
        <data type="token"/>
      </attribute>
      <data type="token"/>
    </element>
  </define>
</grammar>

Execution of Relaxer with the cdl.rmi option is as follows. The cdl option must be used together.

$ relaxer -cdl -cdl.rmi cdlRmi.rcdl

As a result, Relaxer generates 22 files:

List 18.3.3.3[IAccountManager.java] is the IAccountManager which is a Java interface to be used as an API.

IAccountManager.java
import java.rmi.*;

public interface IAccountManager extends Remote {
    /**
     * Application interface of the operation findAccount.
     *
     * @param accountNo
     * @exception RemoteException
     * @return Account
     */
    Account findAccount(String accountNo) throws RemoteException;
}

List 18.3.3.4[IAccountManagerService.java] is the IAccountManagerService which is a Java interface to be used as an SPI.

IAccountManagerService.java
import java.rmi.*;

public interface IAccountManagerService extends IAccountManager {
}

To complete this process, you must develop a service provider. For this purpose, Relaxer generates a prototype of the service provider. In the example, the AccountManagerService shown in List 18.3.3.5[AccountManagerService.java.AccountManager] is the prototype for the service provider. The AccountManagerService extends the AbstractAccountManagerService which is the abstract base class for the service provider. Therefore, the AccountManagerService implicitly implements the SPI IAccountManagerService.

AccountManagerService.java.AccountManager
import java.rmi.RemoteException;

public class AccountManagerService extends AbstractAccountManagerService {

    /**
     * Implementation of a operation findAccount.
     *
     * @param accountNo
     * @exception RemoteException
     * @return Account
     */
    public Account findAccount(String accountNo) throws RemoteException {
        throw (new UnsupportedOperationException());
    }
}

Copy the file "AccountManagerService.java" and create a findAccount method. The service provider AccountManagerService is shown in List 18.3.3.6[AccountManagerService.java].

AccountManagerService.java
import java.rmi.RemoteException;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;

public class AccountManagerService extends AbstractAccountManagerService {

    /**
     * Implementation of a operation findAccount.
     *
     * @param accountNo
     * @exception RemoteException
     * @return Account
     */
    public Account findAccount(String accountNo) throws RemoteException {
	try {
	    Account account = new Account();
	    account.setAccountNo(accountNo);
	    account.setBalance(10000);
	    account.setOwner("XML Taro");
	    account.setAddress(
		new Address("<address zip='123'>Yokohama</address>")
	    );
	    Phone phone1 = new Phone();
	    phone1.setArea("123");
	    phone1.setContent("456-7890");
	    account.addPhone(phone1);
	    Phone phone2 = new Phone("<phone area='090'>123-4567</phone>");
	    account.addPhone(phone2);
	    return (account);
	} catch (IOException e) {
	    throw (new RemoteException(e.getMessage(), e));
	} catch (SAXException e) {
	    throw (new RemoteException(e.getMessage(), e));
	} catch (ParserConfigurationException e) {
	    throw (new RemoteException(e.getMessage(), e));
	}
    }
}

You must compile both client side and server side programs. The client side program is the AccountManagerCommand and the server side program is the RMIAccountManagerServer.

Compilation of AccountManagerCommand and the RMIAccountManagerServer are shown below. No special compile options are needed.

$ javac AccountManagerCommand.java
$ javac RMIAccountManagerServer.java

Next, you must execute the rmic to generate RMI stub codes. In the example, the RMI server RMIAccountManagerServer is specified as a parameter.

$ rmic RMIAccountManagerServer &

There are three steps to execute the RMI component.

First, prepare the RMI name server rmiregistry.

$ rmiregistry &

Second, start the RMI server for the RMI component as follows. In this case, an RMI name accountManager is bound with the RMI server RMIAccountManagerServer.

$ java RMIAccountManagerServer accountManager &

Finally, execute the client command AccountManagerCommand.

$ java AccountManagerCommand --rmi accountManager -findAccount \
    a12345
<account accountNo="a12345"><balance>10000</balance><owner>XML \
    Taro</owner><address zip="123">Yokohama</address><phone \
    area="123">456-7890</phone><phone \
    area="090">123-4567</phone></account>

The --rmi option specifies RMI to access the target component. accountManager, which follows --rmi is the RMI name for the target RMI component.

The -findAccount followed by a12345 means invoking a findAccount method with the parameter a12345.

As a result, the command outputs an XML document which is sent back from the component via RMI transport.