Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagecpp
linenumberstrue
#include <xmlentity.idl> 
#include <acscomponent.idl>
#pragma prefix "alma"

module demo
{
       typedef xmlentity::XmlEntityStruct ObsProposal;
       typedef xmlentity::XmlEntityStruct SchedBlock;
       typedef sequence <SchedBlock> SchedBlockSeq;

       exception XmlComponentException {}; 

       struct ObsProjectTree
       {
              ObsProposal prop;
              SchedBlockSeq schedBlocks;
       };

       interface XmlComponent : ACS::ACSComponent
       {
              long dumbMethod(in string somevalue);                 
              ObsProposal createObsProposal();
              SchedBlockSeq getAllSchedBlocks();
              void xmlInOutMethod(in ObsProposal opsPropIn, 
                                      out SchedBlock schedBlockOut);                                
              ObsProjectTree getEntireTreeInAStruct();                
              void exceptionMethod() raises (XmlComponentException);
       };
};


A1

xmlentity.idl comes from define/idl and declares the CORBA struct XmlEntityStruct which is used to transport serialized XML together with some meta data. It must be included whenever xml entity objects are used (see I-K). The developer does usually not have to know the details of that struct.

B3

The prefix pragma must come after the include statements; this restriction might be lifted in the future, but for now the TAO IFR would have a problem otherwise.

C5

We use the same module as for the HelloDemo component

D7

Typedefs for xml entity classes. The interface methods that use entity classes as parameters or return types (see H-K) must use these named typedefs like 'ObsProposal' instead of 'XmlEntityStruct'. This not only makes the interface more readable, but is also required for the automatic use of Java binding classes.
Notice that the defined names are used to match the XML entity (IDL struct) with its corresponding binding class. For instance, "ObsProposal" will be matched to the Java class alma.xmljbind.test.obsproposal.ObsProposal.

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="cfccb5d4-5e6c-4cef-9301-f6acc082b3e5"><ac:plain-text-body><![CDATA[

E11

Declaration of an exception. (How to use the ACS Error System [6] instead of plain CORBA exceptions may be demonstrated in a future version of this document.)

]]></ac:plain-text-body></ac:structured-macro>

F13

A struct that contains XML entities.

G19

Interface declaration for the XmlComponent

H21

Just to have something dumb in here

I22

Method that returns an xml entity object (as a struct that contains the xml data as a string if the component is accessed as a plain CORBA object, see below.)

J23

Demonstrates the use of a sequence (~array) of xml entity objects

K24

Demonstrates the use of xml entity objects as an OUT parameter

L26

Uses the ObsProjectTree struct, with entities inside

27

Uses an exception (again, later the

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="685d4215-19d0-490c-9384-82793378ebad"><ac:plain-text-body><![CDATA[

M

Uses an exception (again, later the mechanism described in [6] will be used.)

]]></ac:plain-text-body></ac:structured-macro>

...

Compiling IDL

We have to add the new IDL file to jcontexmpl/src/Makefile:

 IDL_FILES = HelloDemo XmlComponent 

In addition to running this file through the standard CORBA IDL compiler, it is also fed into the "ACS IDL compiler". This tool gets started by the build process, so you never have to see it; the interested reader can find it in the CVS module directory ACS/…/XmlIdl. The ACS IDL compiler creates additional Java classes which the CORBA IDL compiler would not create. They are used for working with Java XML binding classes instead of plain XML strings, see 5.1.1.
In the Makefile, the line

 XML_IDL = "ObsProposal=alma.xmljbind.test.obsproposal.ObsProposal; \
SchedBlock=alma.xmljbind.test.schedblock.SchedBlock"

provides the mapping from IDL typedefs (see lines 6-8) to Java binding classes (conceptually: to the schema that defines the entities).
The Java files that are produced from XmlComponent.idl are

...

The classes shown in normal print are mandated by CORBA standards and generated by the CORBA IDL compiler, while the italicized classes are required by the ACS framework and are generated by the ACS IDL compiler.

...

Component implementation

In section 5.2, we saw the IDL file with the typedefs for the entity classes, and their use in the methods of the XmlComponent interface.
The following two functional interfaces have been generated for XmlComponent. The component implementation must implement one of them:

  • XmlComponentOperations uses serialized XML; if the component implemented this interface, it would have to parse and serialize the xml entity objects "manually".
  • XmlComponentJ uses Java binding classes; the container will offer transparent parsing and serialization of XML.

Anchor
_Ref29884687
_Ref29884687
Anchor
_Ref32215045
_Ref32215045
Anchor
_Toc64798226
_Toc64798226
Component Helper Classes

For each component class, a corresponding helper Naming convention: For the component of an interface "xxx", the helper file is named as "xxxComponentHelper". This should not be so easily confused with the IDL-generated "xxxHelper". class is needed. In most cases this helper class will be used only by the framework, which means that the component developer will not have to look at it much.
The framework uses the helper class to

  • instantiate the component implementation class
  • get information about the component's interface(s)
  • get the CORBA POA Tie skeleton class for the component

We will choose the convenience and type-safety offered when implementing XmlComponentJ. The interface generated by the ACS IDL compiler is listed below (Javadoc lines omitted).

Code Block
languagejava
package alma.demo;

/**
 * XML binding class aware ACS component interface XmlComponentJ */
public interface XmlComponentJ extends alma.ACS.ACSComponentOperations
{
    public int dumbMethod(String somevalue);

    public alma.xmljbind.test.obsproposal.ObsProposal createObsProposal();

    public 
Wiki Markup
\\
We will choose the convenience and type-safety offered when implementing XmlComponentJ. The interface generated by the ACS IDL compiler is listed below (Javadoc lines omitted).
\\
<span style="color: #808080">01</span> <span style="color: #7f0055"><strong>package </strong></span>alma.demo; <span style="color: #808080">02</span>  <span style="color: #808080">03</span> <span style="color: #3f5fbf">/**</span> <span style="color: #808080">04</span> <span style="color: #ffffff"> </span><span style="color: #3f5fbf"><strong> XML binding class aware ACS component interface XmlComponentJ </strong>/</span> <span style="color: #808080">05</span> <span style="color: #7f0055"><strong>public interface </strong></span>XmlComponentJ <span style="color: #7f0055"><strong>extends </strong></span>alma.ACS.ACSComponentOperations <span style="color: #808080">06</span> \{ <span style="color: #808080">10</span> <span style="color: #ffffff">    </span><span style="color: #7f0055"><strong>public int </strong></span>dumbMethod(String somevalue); <span style="color: #808080">11</span>  <span style="color: #808080">15</span> <span style="color: #ffffff">    </span><span style="color: #7f0055"><strong>public </strong></span>alma.xmljbind.test.obsproposal.ObsProposal createObsProposal(); <span style="color: #808080">16</span>  <span style="color: #808080">25</span> <span style="color: #ffffff">    </span><span style="color: #7f0055"><strong>public </strong></span>alma.xmljbind.test.schedblock.SchedBlock\[\] getAllSchedBlocks(); <span style="color: #808080">26</span>  <span style="color: #808080">30</span> <span style="color: #ffffff">    </span><span style="color: #7f0055"><strong>public void </strong></span>addNewSchedBlocks(
                    alma.xmljbind.test.schedblock.SchedBlock\[\] newSchedBlocks); <span style="color: #808080">31</span>  <span style="color: #808080">35</span> <span style="color: #ffffff">    </span><span style="color: #7f0055"><strong>public void </strong></span>xmlInOutMethod(
                    alma.xmljbind.test.obsproposal.ObsProposal opsPropIn, 
                    alma.demo.SchedBlockHolder schedBlockOut); <span style="color: #808080">36</span>  <span style="color: #808080">40</span> <span style="color: #ffffff">    </span><span style="color: #7f0055"><strong>public </strong></span>alma.demo.ObsProjectTreeJ getEntireTreeInAStruct(); <span style="color: #808080">41</span>  <span style="color: #808080">50</span> <span style="color: #ffffff">    </span><span style="color: #7f0055"><strong>public void </strong></span>exceptionMethod() <span style="color: #808080">51</span> <span style="color: #ffffff">        </span><span style="color: #7f0055"><strong>throws </strong></span>alma.demo.XmlComponentException; <span style="color: #808080">53</span> \}
\\
Comparing this with the IDL definition, we see that binding classes like alma.xmljbind.test.schedblock.SchedBlock are used whenever the IDL contained a typedef'd entity struct. In addition to this direct substitution, the ACS IDL compiler created the class ObsProjectTreeJ which contains binding classes, thus substituting the IDL struct ObsProjectTree as the return type of the method getEntireTreeInAStruct();
\\
Let's look at the implementation of the method createObsProposal().
\\
<span style="color: #808080">121</span> <span style="color: #ffffff">  </span><span style="color: #7f0055"><strong>public </strong></span>ObsProposal createObsProposal() <span style="color: #808080">122</span> <span style="color: #ffffff">  </span>\{ <span style="color: #808080">123</span> <span style="color: #ffffff">    </span>ObsProposal obsProp = <span style="color: #7f0055"><strong>new </strong></span>ObsProposal(); <span style="color: #808080">124</span> <span style="color: #ffffff">    </span> <span style="color: #808080">125</span> <span style="color: #ffffff">    </span><span style="color: #7f0055"><strong>try</strong></span> <span style="color: #808080">126</span> <span style="color: #ffffff">    </span>\{ <span style="color: #808080">127</span> <span style="color: #ffffff">      </span>ObsProposalEntityT entity = <span style="color: #7f0055"><strong>new </strong></span>ObsProposalEntityT(); <span style="color: #808080">128</span> <span style="color: #ffffff">      </span>m_containerServices.assignUniqueEntityId(entity); <span style="color: #808080">129</span> <span style="color: #ffffff">      </span>obsProp.setObsProposalEntity(entity); <span style="color: #808080">130</span> <span style="color: #ffffff">      </span> <span style="color: #808080">131</span> <span style="color: #ffffff">      </span>obsProp.setPerformanceGoals(
                 <span style="color: #2a00ff">"peak performance enduring a 24-7-365 schedule."</span>); <span style="color: #808080">132</span> <span style="color: #ffffff">    </span>\} <span style="color: #808080">133</span> <span style="color: #ffffff">    </span><span style="color: #7f0055"><strong>catch </strong></span>(ContainerException e) <span style="color: #808080">134</span> <span style="color: #ffffff">    </span>\{ <span style="color: #808080">135</span> <span style="color: #ffffff">      </span>m_logger.log(Level.SEVERE, <span style="color: #2a00ff">"failed to create ObsProposal. "</span>, e); <span style="color: #808080">136</span> <span style="color: #ffffff">    </span>\} <span style="color: #808080">137</span> <span style="color: #ffffff">    </span> <span style="color: #808080">138</span> <span style="color: #ffffff">    </span><span style="color: #7f0055"><strong>return </strong></span>obsProp; <span style="color: #808080">139</span> <span style="color: #ffffff">  </span>\}
\\
We see that the Java class ObsProposal has type-safe methods like "setPerformanceGoals" or "setObsProposalEntity". 
The latter takes an object of type ObsProposalEntityT, also generated by the binding framework. It is used to store administrational information about the ObsProposal object, most important the object ID. 
\\
For a new entity object, a valid and unique object ID can be obtained conveniently through a call to ContainerServices#assignUniqueEntityId, for which the container collaborates with the archive. If the archive is not present, it defaults to using random numbers which should be almost always unique (2^64).
\\
Our method implementation simply returns the top-level Java object for the ObsProposal. The container framework will then automatically serialize it to XML, embed the string in the XmlEntity CORBA struct, and send it to the client using CORBA. If the client is another Java component, its container will automatically create an ObsProposal class and fill it with the data from the serialized XML. 
\\
To keep the size of this tutorial small, the implementations of the other methods are not listed here. They are meant to serve as more detailed examples, for which the source code of the module jcontexmpl should be retrieved anyway. 
Alternatively, the code listing can be found online at the ACS documentation site:
[[] getAllSchedBlocks();

    public void addNewSchedBlocks(
                 alma.xmljbind.test.schedblock.SchedBlock[] newSchedBlocks);

    public void xmlInOutMethod(
                 alma.xmljbind.test.obsproposal.ObsProposal opsPropIn, 
                 alma.demo.SchedBlockHolder schedBlockOut);

    public alma.demo.ObsProjectTreeJ getEntireTreeInAStruct();

    public void exceptionMethod()
        throws alma.demo.XmlComponentException;
}

Comparing this with the IDL definition, we see that binding classes like alma.xmljbind.test.schedblock.SchedBlockare used whenever the IDL contained a typedef’d entity struct. In addition to this direct substitution, the ACS IDL compiler created the class ObsProjectTreeJwhich contains binding classes, thus substituting the IDL struct ObsProjectTreeas the return type of the method getEntireTreeInAStruct();

Let’s look at the implementation of the method createObsProposal().

Code Block
languagejava
public ObsProposal createObsProposal()
{
  ObsProposal obsProp = new ObsProposal();
  
  try
  {
    ObsProposalEntityT entity = new ObsProposalEntityT();
    m_containerServices.assignUniqueEntityId(entity);
    obsProp.setObsProposalEntity(entity);
    
    obsProp.setPerformanceGoals(
           "peak performance enduring a 24-7-365 schedule.");
  }
  catch (ContainerException e)
  {
    m_logger.log(Level.SEVERE, "failed to create ObsProposal. ", e);
  }
  
  return obsProp;
}

We see that the Java class ObsProposal has type-safe methods like “setPerformanceGoals” or “setObsProposalEntity”. 

The latter takes an object of type ObsProposalEntityT, also generated by the binding framework. It is used to store administrational information about the ObsProposal object, most important the object ID. 

For a new entity object, a valid and unique object ID can be obtained conveniently through a call to ContainerServices#assignUniqueEntityId, for which the container collaborates with the archive. If the archive is not present, it defaults to using random numbers which should be almost always unique (2^64).

Our method implementation simply returns the top-level Java object for the ObsProposal. The container framework will then automatically serialize it to XML, embed the string in the XmlEntity CORBA struct, and send it to the client using CORBA. If the client is another Java component, its container will automatically create an ObsProposal class and fill it with the data from the serialized XML. 

To keep the size of this tutorial small, the implementations of the other methods are not listed here. They are meant to serve as more detailed examples, for which the source code of the module jcontexmpl should be retrieved anyway. 

Alternatively, the code listing can be found online at the ACS documentation site:

http://www.eso.org/projects/alma/develop/acs/OnlineDocs/jcontexmpl/doc/html/XmlComponentImpl_8java-source.html

...

To see how the code would look like if the component would implement XmlComponentOperations, take a look at the inner class XmlComponentHelper::IFTranslator.

...

Component Helper Classes

For each component class, a corresponding helper Naming convention: For [1]class is needed. In most cases this helper class will be used only by the framework, which means that the component developer will not have to look at it much. 

...

[1]Naming convention: For the component of an interface "xxx", the helper file is named as "xxxComponentHelper". This should not be so easily confused with the IDL-generated "xxxHelper". class is needed. In most cases this helper class will be used only by the framework, which means that the component developer will not have to look at it muchshould not be so easily confused with the IDL-generated "xxxHelper".

The framework uses the helper class toto 

  • instantiate the component implementation class
  • get information about the component's component’s interface(s)
  • get the CORBA POA Tie skeleton class for the component

A template for the helper class gets generated automatically by the build system if the Makefile contains the line

COMPONENT_HELPERS=on

The template has a file ending .java.tpl to ensure that no edited .java helper class gets overwritten. It is meant as a convenience for the component developer who will normally just have to remove the .tpl ending and then treat that Java file like his/her own, which requires checking it into CVSGIT.

For our HelloDemo component, the helper class does not need to be changed (some Javadoc lines stripped from the listing):
23 package 

Code Block
languagejava
package alma.demo.HelloDemoImpl;

...



import java.util.logging.Logger;

...



import alma.acs.component.ComponentLifecycle;

...


import alma.acs.container.ComponentHelper;

...


import alma.demo.HelloDemoOperations;

...


import alma.demo.HelloDemoPOATie;

...


import alma.demo.HelloDemoImpl.HelloDemoImpl;

...



/**
 * To create an entry for your component in the Configuration Database, 
 * copy the line below into a new entry in the file $ACS_CDB/MACI/Components/Components.

...

xml 
 * and modify the instance name of the component and the container: 
 * Name="HELLODEMO1"

...

 Code="alma.demo.HelloDemoImpl.HelloDemoComponentHelper"

...

 Type="IDL:alma/demo/HelloDemo:1.0"

...

 Container="frodoContainer"

...


 */
public class HelloDemoComponentHelper extends ComponentHelper
{
  public HelloDemoComponentHelper(Logger containerLogger)
  {
    super(containerLogger);

...


  }

  protected ComponentLifecycle _createComponentImpl()

...


  {
    return new HelloDemoImpl();

...


  }

  protected Class _getPOATieClass()

...


  {
    return HelloDemoPOATie.class;

...


  }

  protected Class _getOperationsInterface()

...


  {
    return HelloDemoOperations.class;

...


  }

}

Only in special situations, when a Java component chooses to sometimes use Java binding classes, but other times send or receive serialized XML instead, then the helper class must be modified. This goes beyond the scope of this tutorial and will be described in a more specialized document.

An example for this can be found in alma.demo.XmlComponentImpl.XmlComponentComponentHelper from jcontexmpl/src/.

...

Configuration Database

The ACS configuration database contains information about which components are deployed on the different machines. It assists the ACS Manager to locate components at runtime. All the runtime action is hidden from the programmer by the container.

There are two different types of components: 

  • static components whose instances are fixed at deployment time. These typically represent (abstracted) hardware devices, or service components for which we choose a fixed number of instances. One component can be deployed many times under different names, like "Pipeline1", "Pipeline2".
    Wiki Markup
    dynamic components whose type (and optionally container location) is fixed at deployment time, whereas the number and names of instances is determined only at runtime. For more details on this, refer to \[3\], topic "FAQGeneralCompDynamic".
    “Pipeline1”, ”Pipeline2”.
  • dynamic components whose type (and optionally container location) is fixed at deployment time, whereas the number and names of instances is determined only at runtime. For more details on this, refer to [3], topic “FAQGeneralCompDynamic”.

Let’s Let's make HelloDemo a static component. We create a new line in the file CDB/MACI/Components/ Components.xml with

  • The instance name ("Name"“Name”), which has the format of an ACS CURL, and is used by a client to get access to the component. We call it HELLODEMO1.
  • The component helper class ("Code"“Code”, see section 6section 6)
  • The CORBA interface repository ID of the component ("Type" “Type” – remember that to CORBA a component is just a servant).
  • The name of the Java container that will be asked by the ACS Manager at runtime to instantiate our components – called "frodoContainer" “frodoContainer” in the examples.

Note that the generated component helper class contains these values in a comment (code listing above, line 42). This facilitates adding the CDB entry using copy and paste.

The CDB file Components.xml then looks similar to

Code Block
languagexml
<?xml version="1.0" encoding="utf-8"?>

...


<Components xmlns="urn:schemas-cosylab-com:Components:1.0"

...


      xmlns:cdb="urn:schemas-cosylab-com:CDB:1.0"

...

 
      xmlns:baci="urn:schemas-cosylab-com:BACI:1.0"

...

 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

...


 
<_ Name="TEST_PS_1"    Code="acsexmplPowerSupplyImpl"

...


     Type="IDL:alma/PS/PowerSupply:1.0" Container="bilboContainer"/>

...


         <_ Name="HELLODEMO1" Code="alma.demo.HelloDemoImpl.HelloDemoHelper"

...


    Type="IDL:alma/demo/HelloDemo:1.0" Container="frodoContainer" />

...


         <_ Name="XMLCOMP1" Code="alma.demo.XmlComponentImpl.XmlComponentHelper"

...


    Type="IDL:alma/demo/XmlComponent:1.0" Container="frodoContainer" />

...


<_ Name="LAMP1" Code="acsexmplLamp" Type="IDL:ALMA/PS/Lamp:1.0" Container="bilboContainer"/>

...


         <_ Name="OPERATIONAL_ARCHIVE" Code="alma.archive.components.OperationalHelper"

...

 
    Type="IDL:alma/xmlstore/Operational:1.0" Container="frodoContainer" />

...


 
</Components>

ACS ships with a default CDB that contains the entries for the demo components. 

You'll You’ll have to add entries for your own components, or create a new CDB structure and reset the ACS_CDB environment variable.

...

...

Clients

A component can have different kinds of clients which we'll discuss separately:

...

Generic Client: ObjectExplorer


We can use the ACS tool ObjectExplorer as a generic client for all components. Run it with

 objexp

and you should find your Java components (e.g. XmlComponent) and their instances (e.g. XMLCOMP1) listed on the dialog, together with C++ components (e.g. Lamp).

At first, you see only a visualization of the information in the CDB, as opposed to actually loaded components. When you click on a component instance, the Manager will tell the Container to activate the component with the given instance name.

The screenshot shows the output after XMLCOMP1 has been loaded and the method getBestSchedBlock has been called (with View → Expand result data checked in ObjectExplorer.)

...

Client Component

We've We’ve seen the example of a Java component accessing a C++ Component in 4in 4.2, and a Java component accessing another Java component without transparent XML binding support referenced in 5in 5.1.

To use support for xml binding classes on the client side of a call, we first obtain the other component (here: XMLCOMP1)
XmlComponent xmlComp

Code Block
languagejava
XmlComponentxmlComp=alma.demo.XmlComponentHelper.narrow(

...


	getComponent("XMLCOMP1"));

and then ask the container to wrap it with the more convenient interface that uses XML binding classes, provided in the ContainerServices interface

Code Block
languagejava
XmlComponentJ xmlCompJ=

...

 
(XmlComponentJ)m_containerServices

...

.createXmlBindingWrapper(
XmlComponentJ.class,
                  xmlComp,
                  XmlComponentOperations.class);

Now we can keep working with xmlCompJ, and the framework will delegate all calls to xmlComp, translating between XML binding classes and serialized XML presentation in between.

...

JUnit Test Client


To facilitate the writing of JUnit test clients, ACS (module jcont) offers the class alma

 alma.acs.component.client.ComponentClientTestCase

which is a subclass of JUnit's JUnit’s TestCase that does the talking with ACS Manager. It provides most of the functionality that ContainerServices provides for components.  

A JUnit test that gets a reference to the XmlComponent component and runs some tests on it is is 

jcontexmpl/src/alma.demo.client.XmlComponentClient 020 package 

Code Block
languagejava
package alma.demo.client;

...


import alma.acs.component.client.ComponentClientTestCase;

...


import alma.demo.SchedBlockHolder;

...


import alma.demo.XmlComponent;

...


import alma.demo.XmlComponentException;

...


import alma.demo.XmlComponentJ;

...


import alma.demo.XmlComponentOperations;

...


import alma.entities.commonentity.EntityT;

...


import alma.xmljbind.test.obsproposal.ObsProposal;

...


import alma.xmljbind.test.schedblock.SchedBlock;

...



public class XmlComponentClient extends ComponentClientTestCase
{
  private XmlComponentJ m_xmlCompJ;

  public XmlComponentClient() throws Exception {
    super("XmlComponentClient");

...


  }

  protected void setUp() throws Exception {
    super.setUp();

...



    org.omg.CORBA

...

.Object compObj = getContainerServices().getComponent(

...


        "XMLCOMP1");

...


    assertNotNull(compObj);

...


    XmlComponent xmlComp = alma.demo.XmlComponentHelper.narrow(compObj);

...



    m_

...

xmlCompJ =

...

 (XmlComponentJ)

...

 getContainerServices()

...


        .getTransparentXmlComponent(XmlComponentJ.class,

...

 xmlComp,
            XmlComponentOperations.class);

...



    assertNotNull(m_xmlCompJ);

...


  }

  public void testSayHelloUsingHelloDemoComponent()

...

 {
    String reply = m_xmlCompJ.sayHello();

...


    assertNotNull(reply);

...


    System.out.println("

...

received reply " + reply);
    assertEquals("reply must be 'hello'",

...

 "hello",

...

 reply);

...


  }

  public void testCreateObsProposal()

...

 {
    ObsProposal obsProp = m_xmlCompJ.createObsProposal()

...

;
    assertNotNull(obsProp);

...



    EntityT ent = obsProp.getObsProposalEntity();

...


    assertNotNull(ent);

...



    String id = ent.getEntityId();

...


    assertNotNull(id);

...



    System.out.println("

...

received ObsProposal with id " + id);
  }

  public void testXmlInOutMethod() {
    ObsProposal obsProp = m_xmlCompJ.createObsProposal();

...


    assertNotNull(obsProp);

...


    SchedBlockHolder sbh = new SchedBlockHolder();

...



    m_xmlCompJ.xmlInOutMethod(obsProp,

...

 sbh);

    SchedBlock schedBlock = sbh.value;
    assertNotNull(schedBlock);

...



    EntityT ent = schedBlock.getSchedBlockEntity();

...


    assertNotNull(ent);

...


    String id = ent.getEntityId();

...


    assertNotNull(id);

...



    System.out.println("

...

received out-param SchedBlock with id " + id);
  }

  public void testException() throws Exception {
    boolean gotException = false;

    try {
      m_xmlCompJ.exceptionMethod();

...


    }
    catch (XmlComponentException e) {
      gotException = true;
      System.out.println("

...

received XmlComponentException as intended.");

...


    }

    assertTrue("

...

must receive XmlComponentException",

...

 gotException);

...


  }
}

The constructor must call the constructor of the base class

...

with a name to be used for this client (here:

...

“XmlComponentClient”). If you override the setup() method,

...

it’s necessary there to call super.setUp() first

...

.

JUnit will call all methods that start with

...

“test” in their name, such as testException().

In the Eclipse Java Perspective, you can run such a class with JUnit. Open the class in the editor, then choose

Menu Run → Run As → JUnit Test. It will display the results.