5. CORBA in the gda

5.1. Introduction

This section describes how to create a new object and CORBA-enable it - that is, create the additional files, interfaces and classes needed for the clients to interact with the object remotely.

5.2. Writing the Java code

5.2.1. Create the Java interface for the object

External hyperlinks, like gda.device.detector.Phantom.

5.2.2. Write an implementation of your interface

For example gda.device.detector.phantom.PhantomV73.

Note that if the interface is some.package.Xxx, the implementation should be in some.package.xxx.SomeClass.

In the case of the Phantom, the PhantomV73 class fits into the Device/Scannable/Detector hierarchy, but an object implementing the IPhantomV73Controller interface is used to actually interact with the hardware (or a simulation of it).

5.3. Creating CORBA-specific files

5.3.1. Create an IDL that matches the Java interface

For example, phantom.idl

A few points:

  • Note that whereas the Java interface is called Phantom, the CORBA interface is called CorbaPhantom.
  • Java and CORBA types are different; for example, a Java int corresponds to a CORBA long.
  • Input parameters must be prefixed with in; for example: double getDemandVoltage(in long electrodeNumber) raises (device::corba::CorbaDeviceException);

5.3.2. Compile the IDL to create CORBA classes

(It is no longer necessary to add the IDL file to an Ant script; the make-corba-jar target automatically picks up all IDLs.)

From the root of the GDA project, type:

$ ant make-corba-jar

Or if this fails, try:

ant -f build-classic.xml make-corba-jar

which will create a new gda-corba.jar that will include new classes for your object. For Phantom these classes include:

  • CorbaPhantomOperations - interface containing the Phantom-specific operations (e.g. setupForCollection)
  • CorbaPhantom - interface representing the CORBA version of Phantom; extends CorbaPhantomOperations plus some other CORBA interfaces
  • _CorbaPhantomStub - implements CorbaPhantom and makes the CORBA remote requests
  • CorbaPhantomHelper - various utility methods for working with CorbaPhantom objects

5.3.3. Write the CORBA implementation/adapter classes

These classes must be located in the correct package so they are found.

  • The interface for the device will be in some.package.Xxx.

  • The ImplFactory requires the implementation class to be named some.package.xxx.corba.impl.XxxImpl.

  • The AdapterFactory

    AdapterFactory] requires the adapter class to be named some.package.xxx.corba.impl.XxxAdapter.

5.3.3.1. Implementation class

For Phantom, this is PhantomImpl.

The implementation class must extend your CORBA object’s POA class (for Phantom, this is called CorbaPhantomPOA).

  • The class needs two fields: * The real object - a Phantom in the case of the Phantom. * A POA field.
  • You need a 2-arg constructor which takes the “real” object and the POA. ImplFactory will use this constructor.
  • Each method that you implement should delegate to the “real” object; any exceptions must be converted into CORBA-specific exceptions (e.g. DeviceException to CorbaDeviceException). See PhantomImpl for examples of how to implement these methods.

5.3.3.2. Adapter class

For Phantom, this is PhantomAdapter.

The adapter class may extend other adapter classes but always needs to implement your Java interface (e.g. Phantom).

  • The class needs three fields: * A CORBA object (e.g. a CorbaPhantom for the Phantom). * A NetService. * The object’s name.
  • You need a 3-arg constructor which takes a CORBA object, the object’s name, and a NetService. AdapterFactory will use this constructor.
  • Each method that you implement should delegate to the CORBA object; any CORBA exceptions must be converted into corresponding non-CORBA exceptions (e.g. CorbaDeviceException to DeviceException). See PhantomAdapter for examples of how to implement these methods.

5.4. How the remote call works

Once the CORBA work has been done, the object can be used like this:

MyObject myObject = Finder.getInstance().find("My_Object_Name");
myObject.myMethod("foobar");

The way this is handled is as follows:

  • myObject.myMethod(“foobar”) calls the corresponding method in the adapter.
  • The adapter calls the CORBA stub.
  • The CORBA stub makes the remote call across the network.
  • On the server, the corresponding method in the implementation class is called by CORBA.
  • The implementation class calls the “real” object.

5.5. Reference

Phantom.idl:

#ifndef _PHANTOM_IDL_
#define _PHANTOM_IDL_

#include <detector.idl>

module gda {
module device {
module detector {
module phantom {
module corba {

/**
* An interface for a distributed motor class
*/
interface CorbaPhantom : device::detector::corba::CorbaDetector
{
   void setUpForCollection(in long numberOfFrames, in long framesPerSecond, in long width, in long height)
   raises (device::corba::CorbaDeviceException);
   any retrieveData(in long cineNumber, in long start, in long count) raises (device::corba::CorbaDeviceException);
   string command(in string commandString) raises (device::corba::CorbaDeviceException);
};

};};};};};
#endif

ImplFactory:

gda.factory.corba.util.ImplFactory

AdaptorFactory:

gda.factory.corba.util.AdaptorFactory

PhantomImpl:

gda.device.detector.phantom.corba.impl.PhantomImpl

PhantomAdaptor:

gda.device.detector.phantom.corba.impl.PhantomAdaptor