The Community OpenORB - TradingObjectService

Jerome Daniel

J.Scott Evans


Table of Contents

Introduction
1. Overview
2. Compilation
3. Installation
4. Configuration
5. Deployment
How to run the Trading Object Server ?
The Easy Trader System
The STDL compiler
A quick tutorial
The Trading Service Plugin
6. Frequently Asked Questions
A. Appendix

Introduction

This document provides important information about the OpenORB Trading Object Service. More precisely, this document explains how to build, install, configure and use this service.

Chapter 1. Overview

A Trading Service facilitates the offering and the discovery of instances of services of particular types. A trader is a CORBA object that supports the trading object service in a distributed environment. It can be viewed as an object through which other objects can advertise their capabilities and match their needs against advertised capabilities.

Advertising a capability or offering a service is called export. Matching against needs or discovering services is called import. Export and import facilitate dynamic discovery of, and late binding to, services.

To export an offer, a service describes a Service Type that contains a set of properties ( typed values ). A client application matches its needs by applying a constraint on the properties ( through a constraint language defined by OMG ). Dynamic properties are allowed ( it means that such a property is evaluated by an external property evaluator that gives the ability to measure some specific features like for example memory ).

The OpenORB Trading Service provides a fully compliant implementation of this service. It provides:

  • traders federation
  • embedded or standalone service type repository
  • proxy offers
  • dynamic properties
  • persistent or transient modes
  • a graphical console to browse service offers, to query and so on...

Chapter 2. Compilation

The OpenORB Trading Object Service requires : OpenORB, and the Persistent State Service

Thus, before building and installing OpenORB, be sure that the previous requirements are correctly installed and configuring on your host.

The Trading Service is built thanks to an Ant script. In addition, the Trading Service provides two scripts files : build.bat for Windows and build.sh for Unix. To build the Trading service, run the script: build or sh build.sh

To run the ant script, the Ant tool must be previously installed. Ant is provided with the OpenORB distribution. When you add the OpenORB openorb_tools-{version}.jar file into your classpath, it is not necessary to add something else into your classpath in order to use Ant ( except if you are using JDK 1.1.x )

This script builds the Trading Service, the examples and the documentation. In addition, you can also build the trading service plugin : build plugin

Chapter 3. Installation

Now, extend your classpath to add the openorb_trader-{version}.jar ( this file is created into the dist directory ).

The trading service used a set of properties to manage its behavior. These properties are define in a module named trader which is described in the trader.xml file. This file is by default embedded in the Trading Service Jar file.

At least a property must be customized in the trader module. The next chapter explains how to do that.

After this step, the OpenORB trading service is now installed. Please check the next section to discover how to configure it.

Chapter 4. Configuration

The module trader.xml available in src/config for the source code distribution and config for the Pre-Built version, must be edited to customized at least one property.

Each Trading Server must have a name. To specify it, the module contains a property named name. Customize its value to supply the trader name to use. All the others properties have a default value that can be used, so, if you don't want to study during your first read the next properties, you can directly go to the next sub title How to complete the configuration ?

If you start two trading servers on the same host, they will have both the same trader name !. To avoid this problem, you can specify the trader name for the second trading service from the command line ( see next section about how to run the trading object server.

When a service offer is exported, the trading server will apply additional checks if you set the property name ir to true . This property specifies if the Interface Repository must be used to apply additional checks.

If set to true, the Interface Repository must be previously started before running the trading object service. All interface descriptions should have been previously loaded into the interface repository.

If you want to use the service type repository as a stand alone server, you have to supply the following properties :

  • embedded_repository : this property is set to true if the service type repository is embedded
  • repository_url : if the service type repository is not embedded, this property specifies the CORBA URL that denotes the stand alone service type repository

By default, the trader is started under a transient mode. However, it's possible to modify this default behaviour through the persistence property. If you want to always start the trader under a persistent mode, set its value to true.

The trading service behaviour is influenced by a set of properties:

  • supports.modifiable_properties : if set to true, this property means that modifiable properties are supported.
  • supports.dynamic_properties : if set to true, this property means that dynamic properties are allowed.
  • supports.proxy_offers : if set to true, this property means that proxy offers are allowed.

In addition to the previous properties a set of attributes are defined through properties.

  • imports.def_search_card : default upper bound of offers to be searched for a query operation
  • imports.max_search_card : maximum upper bound of offers to be searched for a query operation
  • imports.def_match_card : default upper bound of matched offers to be ordered in applying a preference criteria
  • imports.max_search_card : maximum upper bound of matched offers to be ordered in applying a preference criteria
  • imports.def_return_card : default upper bound of ordered offers to be returned to an importer
  • imports.max_return_card : maximum upper bound of ordered offers to be returned to an importer
  • imports.def_hop_count : default upper bound of depth of links to be traversed
  • imports.max_hop_count : maximum upper bound of depth of links to be traversed
  • imports.max_list : the upper bound on the size of any list returned by the trader, namely the returned offers parameter in query, and the next_n operations in OfferIterator and OfferIdIteraor
  • imports.def_follow_policy : default link follow behaviour for a particular trader
  • imports.max_follow_policy : limiting link follow policy for all links of the trader
  • imports.link_follow_policy : most permissive follow policy allowed when creating new links

To complete the configuration, we are going to replace the embedded configuration by the new one. The way to do that depends on the distribution that you are currently using : source code or pre built distribution. The following paragraphs describes how to proceed for each distribution kind.

In the case of the source code distribution, a Ant target is provided to replace the embedded configuration file. From the command line: build config

The new configuration file must be available in the src/config directory. Moreover, the Jar file where the configuration will be output must be available in the dist directory.

In the case of the pre built distribution, the config directory contains a script named setConfig ( setConfig.bat for Windows and setConfig.sh for Unix ). We have just to start this script to replace the embedded configuration file.

The new configuration file must be available in the config directory. Moreover, the Jar file where the configuration will be output must be available in the lib directory.

Chapter 5. Deployment

How to run the Trading Object Server ?

The Trading Object Server is composed of 2 parts: the trader, and the service type repository

To start the trader, execute the Java class org.openorb.trader.Server. You can apply several options when you start the trader:

  • -ir : Use this flag if you want to use Interface Repository for type checking.
  • -ior : This flag implies the generation of the Lookup interface IOR into a file named lookup.ior. If the service type repository is embedded, another file is generated strep.ior for it.
  • -naming : This flag specifies to the trader, to bind the Lookup interface to the naming service with the following name : COS\TradingService\Lookup. If the service type repository is embedded, it is bound with the following name : COS\TradingService\ServiceTypeRepository
  • -tradername : This flag allows the trader name specification from the command line : -tradername foo
  • -url : This flag specifies the service type repository URL : -url corbaname://1.2@foo:3080/bar
  • -persistence : this flag starts the trader under a persistent mode.
  • -namingpath : This flag supplies a name for the naming service to bind the lookup interface : -namingpath COS\MyPath implies the Lookup interface to be bound with the COS\MyPath\Lookup

The service type repository can be used as embedded into the trader or in a stand alone mode. ( In this case, you have to start the trader and specifying the CORBA URL for the stand alone service type repsitory ).

To start the service type repository, execute the following Java class org.openorb.trader.repository.Server. Several options are available :

  • -ir : Use this flag if you want to use Interface Repository for type checking.
  • -ior : This flag implies the generation of the service type repository IOR into a file named strep.ior
  • -naming : This flag binds the service type repository with the following name : COS\TradingService\ServiceTypeRepository
  • -persistence : this flag starts the service type repository under a persistent mode.

The Easy Trader System

The Easy Trader System is an exclusive mechanism provided by the OpenORB Trading Object Service. The OMG Trading Service is a very interesting service that provides powerful features. However, it is often very difficult to use it, because it requires a lot of code to develop a simple application.

This is the reason why the OpenORB Trading Object Service provides a Service Type compiler that generates some Java classes ( fully portables ) to facilitate the Trading Service usage.

To describe a Service Type, you have to use the following grammar :

            service <ServiceTypeName> [ : <BaseServiceTypeName>
            [ , <BaseServiceTypeName> ]* ]
            {
            interface <InterfaceTypeName>;
            [ [ mandatory ] [ readonly ] property <IDLType>
            <PropertyName> ; ]*
            };
            

Each service type description must be defined in a file that uses the ".st" extension. This file could include IDL descriptions ( via #include ), and could use comments ( /* .. */ ).

This description must be compiled with the OpenORB Service Type compiler ( see next chapter to get more information about this compiler ).

When a ServiceType description is compiled, a file is generate <ServiceTypeName>Helper.java. This class provides the following operations :

  • create_service : this operation creates the service type description into the trader server. If the description is already registered, no exception is raised.
  • remove_service : removes a service type description from the trader server.
  • resolve_service : returns a list of offers compliant with the provided constraints.

Plus, if you use the -export flag with the service type compiler, another class is generated with the following name : <ServiceTypeName>.java

This class contains several operations :

  • two accessors for each property described into the service type. An accessor to set a value for the property and an accessor to set the evaluator for this property ( to use a dynamic property ).
  • export : export an offer to the trader server. To export an offer, the user has to previously use the accessors to set the values for all properties.
  • modify : modify an offer.
  • remove : remove an offer.

The STDL compiler

The OpenORB Trading Object Service provides a service type compiler to generate Java classes that provide an easy way to use the trader.

The compiler class is: java org.openorb.trader.compiler.StdlCompiler

In addition to the standard IDL compiler flags, the STDL compiler provides :

  • -release : displays the release number of the OpenORB Trading Object Service
  • -export : generates a java class to export offers.

A quick tutorial

How to access to the Trading Object Service ?

How to export a service type description ?

How to export an offer ?

How to find a service type ?

The dynamic properties

This tutorial explains how to use the OpenORB Trading Service and in a more generic way how to use a trader. The source code used by this tutorial is available into the "examples" directory of the OpenORB Trading Service distribution.

The source code for the steps 1 to 4 is available inside the "example/bank" directory.

To access the trader server, the TradingService key word must be resolved. A Lookup interface reference is returned :

                org.omg.CosTrading.Lookup lookup = null;
                try
                {
                    org.omg.CORBA.Object obj =
                    orb.resolve_initial_references("TradingService");
                    lookup = org.omg.CosTrading.LookupHelper.narrow( obj );
                }
                catch ( org.omg.CORBA.ORBPackage.InvalidName ex )
                {
                    System.out.println("Unknown service :" + ex.toString() );
                    System.exit(1);
                }
                

The Lookup interface provides all attributes and operations to use and manage the Trading Service.

There are two solutions to describe a service type :

  • to develop all the description that use Trading Object Service API
  • to describe the service offer and to use the OpenORB TOS ServiceType compiler.

Here, we are going to explain the two methods, but we will begin by the second solution, which is really easier !

We would like to describe a service type that corresponds to a bank. This service type provides a bank name and a property that indicates if this bank object supports the transactions. Thus, we create a file named "Bank.st" where we describe the following service :

                #include "bank.idl"
                service BankService
                {
                    interface Bank;
                    mandatory property string bank_name;
                    mandatory property boolean transactional;
                };
                

Now, we have to compile this description : java org.openorb.trader.compiler.StdlCompiler bank.st -export

Two files are generated :

  • BankServiceHelper.java
  • BankServive.java

In the Bank server, to create the BankService description creation into the trader, we have to write:

                BankServiceHelper.create_service( lookup );
                

And that's all !

The second solution to create a service type description is a little bit more complicated. First, we have to describe each properties, then the interface type, then the inheritance ( if any ) as shown in the following source code we have :

First, we create the list of properties ( here 2 : bank name + transactional ) :

                org.omg.CosTradingRepos.ServiceTypeRepositoryPackage.PropStruct []
                properties = new org.omg.CosTradingRepos.
                ServiceTypeRepositoryPackage.PropStruct[2];
                

Then, we describe the two properties ( name / mode / type ) :

                // Property bank_name
                properties[0] = new org.omg.CosTradingRepos.ServiceTypeRepositoryPackage.PropStruct();
                properties[0].name = "bank_name";
                properties[0].value_type = orb.get_primitive_tc( org.omg.CORBA.TCKind.tk_string );
                properties[0].mode =org.omg.CosTradingRepos.ServiceTypeRepositoryPackage.PropertyMode.PROP_MANDATORY_READONLY;

                // Property transactionnal
                properties[1] = new org.omg.CosTradingRepos.ServiceTypeRepositoryPackage.PropStruct();
                properties[1].name = "transactional";
                properties[1].value_type = orb.get_primitive_tc( org.omg.CORBA.TCKind.tk_boolean );
                properties[1].mode = org.omg.CosTradingRepos.ServiceTypeRepositoryPackage.PropertyMode.PROP_MANDATORY;
                

Now, we describe the inheritance ( here no inheritance ) :

                String [] inherited = new String[0];
                

Then, to finish we create the new description ( first, we have to get access to the repository ) :

                try
                {
                    org.omg.CosTradingRepos.ServiceTypeRepository repository =
                    org.omg.CosTradingRepos.ServiceTypeRepositoryHelper.narrow( lookup.type_repos() );
                    org.omg.CosTradingRepos.ServiceTypeRepositoryPackage.IncarnationNumber incarnation = null;
                    incarnation = repository.add_type( "BankService", "::Bank", properties, inherited );
                }
                catch ( java.lang.Exception ex )
                {
                    System.out.println("Unable to create the service type description !");
                    System.exit(1);
                }
                

Now, this is finished ! We suggest you always use the Service Type compiler, because it generates portable source code that could be reused by another trading service !

To export an offer, two approaches are also available !

The first one is as usual the most simple, it uses the generated files from the service type description. If you use the -export flag with the compiler, it also generates a class which has the same name than the service type. The following piece of code explains how to use this class :

                BankService bank_service = new BankService( orb, lookup );
                

The previous line uses the constructor to create a new instance of the BankService. This class contains an accessor to set the value for each property :

                bank_service.bank_name( "Barclays" );
                bank_service.transactional( false );
                

When the values are set, the last thing to do is to export the offer :

                if ( bank_service.export( bank._this( orb ) ) == null )
                {
                    System.out.println("Unable to export offer...");
                }
                

The second approach ( the standard approach ) is more complicated as shown above :

                org.omg.CosTrading.Property [] properties = new org.omg.CosTrading.Property[2];

                properties[0] = new org.omg.CosTrading.Property();
                properties[0].name = "bank_name";
                properties[0].value = orb.create_any();
                properties[0].value.insert_string( "barclays" );

                properties[1] = new org.omg.CosTrading.Property();
                properties[1].name = "transactional";
                properties[1].value = orb.create_any();
                properties[1].value.insert_boolean( false );

                try
                {
                    return register.export( bank._this( orb ), "BankService", properties );
                }
                catch ( java.lang.Exception ex )
                { }
                

To find a service, again, two solutions :

                org.omg.CosTrading.Offer [] offers =
                    BankServiceHelper.resolve_service( orb, lookup, "transactional == FALSE", "" );
                

In the previous line, we ask for a BankService offer, by providing the ORB instance, the Lookup reference, the constraint and the preference.

                // -- Check for errors --
                if ( offers == null )
                {
                    System.out.println("An error occured during query...");
                    System.exit(0);
                }
                // -- Check if there are some compliant offers --
                if ( offers.length == 0 )
                {
                    System.out.println("No compliant Bank found...");
                    System.exit(0);
                }
                // -- Access to a compliant offer --
                Bank bank = BankHelper.narrow( offers[ 0 ].reference );
                

The second possibility ( standard way ) :

                org.omg.CosTrading.OfferSeqHolder offers =
                    new org.omg.CosTrading.OfferSeqHolder();
                org.omg.CosTrading.OfferIteratorHolder iterator =
                    new org.omg.CosTrading.OfferIteratorHolder();
                org.omg.CosTrading.PolicyNameSeqHolder limits =
                    new org.omg.CosTrading.PolicyNameSeqHolder();

                try
                {
                    org.omg.CosTrading.Policy [] policies =
                    new org.omg.CosTrading.Policy[3];

                    policies[0] = new org.omg.CosTrading.Policy();
                    policies[0].name = "exact_type_match";
                    policies[0].value = orb.create_any();
                    policies[0].value.insert_boolean( true );
                    policies[1] = new org.omg.CosTrading.Policy();
                    policies[1].name = "use_dynamic_properties";
                    policies[1].value = orb.create_any();
                    policies[1].value.insert_boolean( true );
                    policies[2] = new org.omg.CosTrading.Policy();
                    policies[2].name = "use_proxy_offers";
                    policies[2].value = orb.create_any();
                    policies[2].value.insert_boolean( true );

                    org.omg.CosTrading.LookupPackage.SpecifiedProps
                    desired_properties = new org.omg.CosTrading.LookupPackage.SpecifiedProps();
                    desired_properties.all_dummy((short)0);

                    lookup.query( "BankService", "transactional == FALSE", "",
                        policies, desired_properties, 10, offers, iterator, limits );

                    return offers.value;
                }
                catch ( java.lang.Exception ex )
                {
                    System.out.println("An error occured during query...");
                    System.exit(0);
                }
                // -- Check if there are some compliant offers --
                if ( offers.value.length == 0 )
                {
                    System.out.println("No compliant Bank found...");
                    System.exit(0);
                }
                // -- Access to a compliant offer --
                Bank bank = BankHelper.narrow( offers.value[ 0 ].reference );
                

A property can be dynamic. It means that you don't have to provide a value for the property, but you have to register an external evaluator that is invoked when you want to get the dynamic property value.

The source code of this example is available in example/task. In this section we only explain the most simple way which uses the OpenORB TOS extension ( the service type compiler and its generated files ).

The example Task shows this kind of properties. In this example, we are looking for a task executor which provides in its offer the quantity of memory available to run the task. The memory quantity is evaluted via a dynamic property :

                service TaskService
                {
                    interface Task;
                    mandatory property string host_name;
                    mandatory property long long memory;
                };
                

As you see in the previous description, the memory property is not marked as dynamic. Indeed, any property can be dynamic ! The compiler generates two kind of accessors for each property :

  • a simple accessor to export a value
  • a complex accessor to export an evaluator reference for a dynamic property.

Example :

                public class TaskService
                {
                    // ...
                    public void memory( long value )
                    {
                        // ...
                    }
                    public void memory( org.omg.CosTradingDynamic.DynamicPropEval eval )
                    {
                        // ...
                    }
                }
                

An evaluator is simple to develop :

                public class MemoryEval
                    extends org.omg.CosTradingDynamic.DynamicPropEvalPOA
                {
                    private org.omg.CORBA.ORB orb;
                    public MemoryEval( org.omg.CORBA.ORB orb )
                    {
                        this.orb = orb;
                    }
                    public org.omg.CORBA.Any evalDP(
                                java.lang.String name,
                                org.omg.CORBA.TypeCode returned_type,
                                org.omg.CORBA.Any extra_info )
                        throws org.omg.CosTradingDynamic.DPEvalFailure
                    {
                        if ( ! name.equals("memory") )
                            throw new org.omg.CosTradingDynamic.DPEvalFailure( name,
                                            returned_type, extra_info );
                        long free = java.lang.Runtime.getRuntime().freeMemory();
                        org.omg.CORBA.Any any = orb.create_any();
                        any.insert_longlong( free );
                        return any;
                    }
                }
                

Now to export the offer :

                TaskService task_service = new TaskService( orb, lookup );
                String name = java.net.InetAddress.getLocalHost().getHostName();
                task_service.host_name( name );
                task_service.memory( eval._this( orb ) );
                // -- And to finish, export the offer --
                if ( task_service.export( task._this( orb ) ) == null )
                {
                    System.out.println("Unable to export offer...");
                }
                

The Trading Service Plugin

The plugin requires the ManagementBoard distribution. For more information concerning that module, refer to the documentation which is delivered with the ManagementBoard packaging.

You can download the ManagementBoard module on the http://openorb.sf.net web site. You need to put the openorb_board-{version}.jar file in your CLASSPATH environment variable.

Once you have dowloaded that module, you can build the Trader Plugin application with the ant tool. Enter the following command to build the Plugin : ( under the TradingService directory ) build plugin

You will then find a traderplugin-{version}.jar file in the dist directory. Add it to your CLASSPATH environment variable.

You also have to update your OpenORB.xml file to specify that you want to start the Board with the Trader Plugin. When editing your OpenORB.xml file, add the following information in the board module.

            <property name="traderPluginClass"
            value="org.openorb.trader.plugin.Plugin">
            <property name="traderPluginPath"
            value="<PATH>/traderplugin.jar">
            <property name="traderPluginHelp" value="">
            

Add the trader plugin to the plugins list in the board module.

For more information about such a configuration, refer to the ManagementBoard documentation.

Now, before beginning this overview, be sure that the Trading Object Service is running.

When starting the Management Board, a new tab is available for the Trader Plugin. Select this tab and click on the connect button.

The following dialog window appears. If the Trading Service is previously configured on your host, you can resolve it through the initial references, so click on the connect button.

Now, the Trader Plugin is connected to the trading server. The plugin interface is divided into two parts :

  • on the left side, a tree provides all topics that can be managed by the plugin,
  • on the right side, a panel displays the content of the selected topic of the left side.

For example, click ( on the left side ) on the service types topic. All service types descriptions managed by the trading service are displayed as children of this topic. If you click on one of these children, you will get its description on the right panel, as shown on the next screenshot :

Thanks to the Trader plugin, you can manage all parts of your trading server :

  • it's possible to browse the service type descriptions
  • it's also possible to browse the offers and the proxy offers
  • you can view and modify the trader configuration
  • you can also browse the trader links
  • at last, you can query some offers from the trader plugin !

To see the offers, click on the offers topic ( on the left side ). All available offers are displayed as children of the offer topic. If you select one of the available offers, its properties values are displayed on the right side.

To view or modify the Trading Server configuration, select on the left side the config topic. The right panel displays all configuration parameters and their values.

To modify a parameter, select it in the right panel then click on the edit button.

At last, to query some offers, click on the query topic on the left side. All existing queries are displayed as children of the query topic. To create a new query, click on the add button. Fill all the required fields and validate.

Then, to execute a query, select the query name ( on the left side ), then click on the execute button. All compliant offers are displayed on the right panel.

Chapter 6. Frequently Asked Questions

Set

6.1. ?
6.1.

?

!

Appendix A. Appendix