The cdl option enables Relaxer to generate a component implementation for Java defined by Relaxer Component Definition Language (RCDL).
The cdl option takes no parameters. Specifing the cdl option indicates that you want to use the CDL generator.
Relaxer generates various artifacts from the RCDL or RIDL defitions, as follows:
INTERFACE works with replaceable part of file names. This string is substituted with an interface name from the RCDL definition.
The URComponent
is a helper class for the Relaxer eomponent.
The IINTERFACE
is a java interface for the API of
the Relaxer component.
The IINTERFACEService
is a java interface
for the SPI of the Relaxer component.
The IINTERFACEFilter
is a Java interface for
filter objects.
The AbstractINTERFACEFilter
is an abstract base class
for filter objects.
The INTERFACEForwardProxy
and
the INTERFACEContainer
are classes used
by Relaxer internally at runtime.
The AbstractINTERFACEService
is an abstract base class
for service providers.
The INTERFACEService.java.INTERFACE
is
a prototype for the service provider.
The INTERFACEBean
is a JavaBeans to be used
by application programs.
The INTERFACECommand
is a front-end command
to be used by the end user.
List 18.2.3.1[cdl.rcdl] is a sample RCDL definition, and List 18.2.3.2[cdl.rng] is a sample RELAX NG schema used by the RCDL definition.
<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="cdl.rng"/> <operation name="findAccount"> <in name="accountNo" type="token"/> <out label="account"/> </operation> </interface> </component>
<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 the Relaxer with the cdl option is as follows:
$ relaxer -cdl cdl.rcdl
As a result, Relaxer generates 17 files, as follows:
List 18.2.3.3[IAccountManager.java] is the IAccountManager
which is a Java interface to be used as an API.
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.2.3.4[IAccountManagerService.java] is
the IAccountManagerService
which is a Java interface
to be used as an SPI.
import java.rmi.*; public interface IAccountManagerService extends IAccountManager { }
To complete the component creation,
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.2.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
.
Implementation of the method in the class throws
java.lang.UnsupportedOperationException
.
It is stub code that the souce code can be compile.
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 then create
a findAccount
method.
Finally, the service provider AccountManagerService
is implemented, as shown in List 18.2.3.6[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)); } } }
Compilation of AccountManagerCommand
is as follows.
No special compile options are needed.
$ javac AccountManagerCommand.java
Execution of AccountManagerCommand
is as shown here:
$ java AccountManagerCommand -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 -findAccount
, followed by a12345
, indicates
that you want to invoke a findAccount
method
with the parameter a12345
.
As a result, the command outputs an XML document produced by the service provider.