Developing Servlets V.3.00

 


Objective & Audience

 

This document provides an overview of how Thunderbolt Servlets work and how you can create your own. Depending upon which language bindings you intend to use for your Servlet development you should be competent in either:

 

·        Java if writing Java Thunderbolt Servlets and/or

·        C++ if developing Thunderbolt Servlets in C++. In this case familiarity with the Standard Template Library (STL) is also pretty essential.

 

Requirements

 

  • An internet connection;
  • The ThunderboltTM Servlet library;
  • GNU’s gcc version 2.96 compiler + GNU version of make + other development tools such as linkers, debuggers etc if developing in C++;
  • Sun’s j2ee-1.4.1 if developing Thunderbolt Servlets in Java;
  • Optionally Tomcat4, ant 1.5.1 if you wish to create Tomcat Servlets to call Thunderbolt transactions;
  • Access to the target systems on which connectors are to be deployed;
  • Optionally the Runtime Monitor to facilitates the control of the complete infrastructure;
  • Optionally the Transaction Designer for the creation of Transaction Model and associated Logic.

 

 

Thunderbolt engine an overview

 

When the complete system is up and running it looks something like this:

 

 

If everything has started correctly the Engine will know about the transaction definitions you have specified, the node controllers running on each machine will have started the Servlets required to satisfy the transactions and these will have been bound to the various transaction specs by the Engine.

The engine will then be waiting on the configured port for event requests. Upon receiving a request it will service it by initiating the requested transaction and optionally returning the results to the client.  Requests can be made:

 

  • Synchronous  - in which case the request is blocking for the duration of the transaction and the result of this is returned to the client immediately upon completion;
  • Asynchronous – in which case an immediate acceptance reply is returned to the client.

 

Connectors and engine communicate through TCP/IP secure connections so you can develop and run a connector on one platform while running other connectors, Engine, Runtime Monitor and Transaction designer on another system in a truly distributed way.

 

Servlets Overview

 

The system views Thunderbolt Servlets as collections of configurable attributes, objects with fields and methods.

 

 

 

 

Each Object, field and method is addressable in TML though a standard addressing convention (SAC):

 

serverName:ConnectorInstance.ObjectName.FieldName

serverName:ConnectorInstance.ObjectName.MethodName

 

You will find this kind of addressing syntax throughout the files defining the transaction model logic, located in the TransSpec sub-directory. These codings will generally be created by the Transaction Designer but can also be created manually if the Transaction Designer is not available. Refer to the Transaction Modeling Language examples (TML)

 

Connectors area a specialization of Thunderbolt Servlets. They are Servlets that connect up a target/source system to the middleware infrastructure, thus enabling it to partake in complex multi-part transactions involving any number of disparate geographically distributed systems.

Thunderbolt connectors can be bi-directional thus capable of reading and writing data to/from the target system. Or single directional thus capable of just reading or writing data to the target/source system.

 

The steps for creating a connector are the following:

 

1)      Model the sub-system, to which you want to connect up to, into a series of objects, fields and methods;

2)      Define each object and its fields;

3)      Define the methods which will act on the objects and fields;

4)      Define the property values for the connector;

5)      Code each object as a C++ or Java object;

6)      Code the Servlet unit which will instantiate the Objects you have defined;

7)      Code the main processing entry point to instantiate your Servlet and a Thunderbolt ServletRunner.

 

 

There is exactly one Servlet unit per connector and one or more Objects with one or more Fields and one or more Methods per connector.

 

                                     

Transformers are also a specialization of  Thunderbolt Servlets. They are Servlets which can access the  transaction data during the evolution of a transaction and modify, transform, add or delete data from the set.

 

The steps for creating a transformer are:

 

1)      Define the transformations to be carried out;

2)      Define the property sheet values for the transformer;

3)      Define the data keys to be transformed and their target values;

4)      Define the methods which will carry out the transformations;

 

There is exactly one Servlet per transformer.

 

What does the Servlet library do?

 

The Servlet library gives you transparent connectivity to the Engine by taking care of  all transmission protocols between Engine and your Servlet. As well as making your Servlet multi-process/multi-threaded it handles issues of persistency, transactionality and recovery. The library also transparently handles service events sent to your Servlets, by the Transaction Designer and Runtime Monitor GUIs.

 

Servlets what must I do to create one?

 

Say you have a sub-system either on your local intranet or reachable via a WAN and you want to be able to involve this system in a more or less complex business process involving other systems. You will have to create a connector Servlet to access this data. You may also need to create a transformer servlet to modify this data before it can interact with the rest of your transaction elements.

 

Generally in order to create a Thunderbolt Servlet you will need to define the objects, fields and methods that will make up the Servlet. This true for both C++ or Java Servlets; bindings to the library are provided for both.

 

1)      Each object must be derived from the appropriate library base class ServletObj if using C++ or BaseServlet if using java;

2)      Each object must have a Get, Set and Run method defined in it;

3)      Any other methods you intend to provide for use in the transaction model;

4)      The Servlet in which you instantiate your object classes;

5)      The main which instantiates your Servlet and invokes the ServletRunner to actually run your servlet.

 

 

 

 

 

The Servlet Objects

 

After having broken down the structure of the information from the sub-system we intend to target/source into a series of objects, fields and methods we need to create a code an object for each of the identified object. Within each object we model the fields and methods we have previously identified.

 

Each object must as a bear minimum define a Get a Set and run method. The Get end Set methods enable i/o access to the whole data set for the Object while the run() method provides routing to each method. Optionally other methods can also be defined to do practically anything you want.

 

The Servlet code

 

In the Servlet code you:

 

1)      Define an init routine for the connector;

2)      Define a finish method;

3)      Define a service method;

4)      Define the transaction functions, start, commit and roll back;

5)      Define the structure of your Servlet with its objects, fields and methods;

6)      Define the connector attributes which determine certain behaviors

 

The following methods enable you to describe the objects, fields and methods which will make up your connector:

 

AddConfigParam(string label, int maxLength, string inputRegExp, bool echoFlag)  enables you to define configurable parameters which will be displayed in the transaction designers and runtime monitor property sheet.

 

ClearObjects() – clears all known object, fields and methods from the connector.

 

AddObject(string ObjectName) – Adds an object to the connector.

 

AddField(string ObjectName, string FeldName) – Adds a field to an object. If the object doesn’t exist it’s also added to the connector knowledge base.

 

AddMethod(string ObjectName, string MethodName, ServletObj *obj) - Adds a method to the object. If the object doesn’t exist it’s also added to the connector knowledge base. The ServletObject is the object containing the method implementation.

 

The following public variables enable you to define the name you wish to assign to your servlet and the type of Servlet that is to be created.

 

        servletName = "MigrationDB";

        servletType = connector;              // connector, transformer or node

        servletState = running;                   // running | halted the initial state of

// the connector when its instantiated

 

 

The Main

 

The main class simply instantiates a servlet and a ServletRunner finally running the servlet by calling the ServletRunners run() method.

 

The main method

            Within an exception catch

Instanciate a new Servlet object

Instanciate a ServletRunner object (Servlet)

Call ServletObject run method

            Catch any exceptions

End of main

 

 

 

 


Developing and testing

 

You will need a running engine in order to design transactions and test your connectors. If you do not have an engine installation but still wish to develop a connector for later use or perhaps in order to try out the system or for a pilot project or perhaps even while you are waiting for a license to arrive, you may be able to use the engine found on softbolts.com. This engine is usually available for public use for the purpose of testing.

 

 

Java sample connector

 

A Java class is required to represent each of the objects to be modelled. Each object class will represent the fields and methods available though it. These objects, fields and methods can be dynamically created as in the TBDB sample JDBC connector which loads up a definition of tables->object and fields->rows on successfully login to a database.

 

All the code that follows can be found as part of the engine tar ball sub-directory dev/src/java/com/softbolts/connectors/TBGenericDB  and is a good starting point for creating your own connector Servlet.

 

Our sample Java connector consists of just one object:

 

BillingDB

 

So what you need to write is:

 

1)      A class for each object you wish your connector to represent with its relevant fields and methods

2)      A Servlet class which extends BaseServlet and instantiates the objects above

3)      A main class that instantiates an instance of ServletRunner which will run the servlet you wrote above.

 

 

The BillingDB Object

 

package com.softbolts.connectors.TBGenericDB;

 

import com.softbolts.lib.*;

 

import java.io.*;

import java.util.*;

import java.lang.*;

 

 

public class BillingDB extends ServletObj implements Serializable

{

 String Key1 = "000001";                                // In more ralistic case this info

 String Name = "Anthony";                               // would be retieved from a database

 String Surname = "Dawson";

 String Address1 = "Via Delle Farfalle 15";

 String Address2 = "Rome";

 String Address3 = "Italy";

 String Status = "Young free and single";

 

        //-----------------------------------------------------------

        public int run(NameValueTyp params)

        {

         String method = null;

 

                if((method = (String) params.get("sysMethod")) == null) return -1;

                if (method.equals("Get")) return Get(params);

                if (method.equals("Set")) return Set(params);

                return 0;

        }

 

        //-----------------------------------------------------------

        public int Set(NameValueTyp params)

        {

                Key1 = (String) params.get("Key1");

                Name = (String) params.get("Name");

                Surname = (String) params.get("Surname");

                Address1 = (String) params.get("Address1");

                Address2 = (String) params.get("Address2");

                Address3 = (String) params.get("Address3");

                Status = (String) params.get("Status");

                return 0;

        }

 

        //-----------------------------------------------------------

        public int Get(NameValueTyp params)

        {

                params.put("Key1", Key1);

                params.put("Name", Name);

                params.put("Surname", Surname);

                params.put("Address1", Address1);

                params.put("Address2", Address2);

                params.put("Address3", Address3);

                params.put("Status", Status);

                return 0;

        }

}

The Servlet

 

This is your servlet implementation. This is where you describe the objects your Servlet is going to represent as well as the Servlets properties and characteristics such as type, initial run state and name by which it will be refferd.

 

package com.softbolts.connectors.TBGenericDB;

 

import com.softbolts.lib.*;

import java.io.*;

import java.net.*;

import java.util.*;

import java.lang.Throwable;

 

public class Servlet extends BaseServlet

{

        public Servlet(String args[])

        {

                System.out.println("TBGenericDB Connector Started...");

 

                BillingDB bd = new BillingDB();

 

                servletName = "TBGenericDB";

                servletType = SvrTyp.connector;

                if (servletState == RunStatusTyp.running)

                        System.out.println("TBGenericDB Connector status is running...");

                else if (servletState == RunStatusTyp.halted)

                        System.out.println("TBGenericDB Connector status is halted...");

                else

                        System.out.println("TBGenericDB Connector status is undefined...");

 

                servletState = RunStatusTyp.running;

 

                AddConfigParam("Login", 20, "^[A-Za-z0-9_]*$", true);

                AddConfigParam("Password", 20, "^[A-Za-z0-9_]*$", false);

 

                AddObject("BillingAccount");

                AddField("BillingAccount", "Key1");

                AddField("BillingAccount", "Name");

                AddField("BillingAccount", "Surname");

                AddField("BillingAccount", "Address1");

                AddField("BillingAccount", "Address2");

                AddField("BillingAccount", "Address3");

                AddField("BillingAccount", "Status");

 

                AddMethod("BillingAccount", "Get", bd);

                AddMethod("BillingAccount", "Set", bd);

                AddMethod("BillingAccount", "Create_Account", bd);

                AddMethod("BillingAccount", "Update_Account", bd);

                AddMethod("BillingAccount", "Delete_Account", bd);

 

                //-----------------------------------

                //AddObject("BillingBankDetails");

                //AddField("BillingBankDetails", "Key1");

                //AddField("BillingBankDetails", "Name");

                //AddField("BillingBankDetails", "Surname");

 

                //AddMethod("BillingBankDetails", "Get", b);

                //AddMethod("BillingBankDetails", "Set", b);

                //AddMethod("BillingBankDetails", "Create_BankDetails", b);

                //AddMethod("BillingBankDetails", "Update_BankDetails", b);

                //AddMethod("BillingBankDetails", "Delete_BankDetails", b);

        }

 

        //-----------------------------------------------------------

        public void service(NameValueTyp params) throws ThrowableString

        {

        }

        //-----------------------------------------------------------

        public void service(NameValueTyp params) throws ThrowableString

        {

        }

 

        //-----------------------------------------------------------

        public void init(NameValueTyp params) throws ThrowableString

        {

                //System.out.println("init()");

                //throw new ThrowableString("ERR: init() - TBGenericDB - need to write some code here!");

        }

 

        //-----------------------------------------------------------

        public void finish(NameValueTyp params) throws ThrowableString

        {

                System.out.println("TBGenericDB.finish()");

                System.out.println("TBGenericDB Connector Stopped...");

        }

 

        //-----------------------------------------------------------

        public void beginTransaction(NameValueTyp params) throws ThrowableString

        {

        }

 

        //-----------------------------------------------------------

        public void commitTransaction(NameValueTyp params) throws ThrowableString

        {

        }

 

        //-----------------------------------------------------------

        public void rollBackTransaction(NameValueTyp params) throws ThrowableString

        {

        }

}

 

 

The TBGenericDB

 

The object containing the main function This is where the Servlet you have created is instantiated and run by an instance of ServletRunner.

 

package com.softbolts.connectors.TBGenericDB;

 

import com.softbolts.lib.*;

import java.io.*;

import java.net.*;

import java.util.*;

import java.text.*;

import java.lang.*;

 

//-----------------------------------------------------------

public class TBGenericDB

{

        static public void main(String args[])

        {

                Servlet svr = new Servlet(args);

 

                try {

                        ServletRunner sr = new ServletRunner(svr, args);

                        sr.run();

                } catch (ThrowableString s) {

                        System.err.println(s.getMessage());

                }

        }

}

 

 

 

C++ sample connector

 

All the following code is available in the engine tar ball in the sub-directory dev/src/C++/connectors/MigrationDB

 

Our sample connector consists of two objects:

 

1)      Account

2)      BankDetails

 

Finally you need to implement the Servlet

 

The Account Object

 

#ifndef ACCOUNT_INCLUDED

#define ACCOUNT_INCLUDED

 

#include "MWTypes.hh"

 

class Account : public ServletObj

{

 public:

 

        Account();

        ~Account() {};

 

        int  run(NameValueTyp &params);

 

        int  Get(NameValueTyp &params);

        int  Set(NameValueTyp &params);

        int  Create(NameValueTyp &params);

        int  Update(NameValueTyp &params);

        int  Delete(NameValueTyp &params);

 

 private:

        string Key1;

        string Name;

        string Surname;

        string Address1;

        string Address2;

        string Address3;

};

#endif // ACCOUNT_INCLUDED

 

 

The Account Object Implementation

 

#include "Account.hh"

 

 

//----------------------------------------------------

Account::Account()

{

        Key1 = "001";

        Name = "Anthony";

        Surname = "Dawson";

        Address1 = "Via Riccione 6";

        Address2 = "Fregene";

        Address3 = "Rome 00050";

}

 

//----------------------------------------------------

int Account::run(NameValueTyp &params)

{

        if (params["sysMethod"] == "Set")

                return Set(params);

        else if (params["sysMethod"] == "Get")

                return Get(params);

        else if (params["sysMethod"] == "Create_Account")

                return Create(params);

        else if (params["sysMethod"] == "Update_Account")

                return Update(params);

        else if (params["sysMethod"] == "Delete_Account")

                return Delete(params);

 

        params["sysResultString"] = "ERR: Account::run() - no method with name: " + params["sysMethod"];

        return EXIT_FAILURE;

}

 

//----------------------------------------------------

int Account::Get(NameValueTyp &params)

{

        cerr << "Get Account--------------------------------------------------------" << endl;

        params["Key1"] = Key1;

        params["Name"] = Name;

        params["Surname"] = Surname;

        params["Address1"] = Address1;

        params["Address2"] = Address2;

        params["Address3"] = Address3;

        return EXIT_SUCCESS;

}

//----------------------------------------------------

int Account::Set(NameValueTyp &params)

{

        cerr << "Set Account" << endl;

        Key1 = params["Key1"];

        Name = params["Name"];

        Surname = params["Surname"];

        Address1 = params["Address1"];

        Address2 = params["Address2"];

        Address3 = params["Address3"];

        return EXIT_SUCCESS;

}

 

//----------------------------------------------------

int Account::Create(NameValueTyp &params)

{

        cerr << "Create Account" << endl;

        return EXIT_SUCCESS;

}

 

//----------------------------------------------------

int Account::Update(NameValueTyp &params)

{

        cerr << "Create Account" << endl;

        return EXIT_SUCCESS;

}

 

//----------------------------------------------------

int Account::Delete(NameValueTyp &params)

{

        cerr << "Create Account" << endl;

        return EXIT_SUCCESS;

}

 

The Bank Details Object

 

#ifndef BANKDETAILS_INCLUDED

#define BANKDETAILS_INCLUDED

 

#include "MWTypes.hh"

 

class BankDetails : public ServletObj

{      

 public:

 

        BankDetails();

        ~BankDetails() {};

       

        int  run(NameValueTyp &params);

 

        int  Get(NameValueTyp &params);

        int  Set(NameValueTyp &params);

        int  Create(NameValueTyp &params);

        int  Update(NameValueTyp &params);

        int  Delete(NameValueTyp &params);

};     

#endif // BANKDETAILS_INCLUDED

 

The Bank Details Object implementation

 

#include "BankDetails.hh"

 

 

//----------------------------------------------------

BankDetails::BankDetails()

{

}

 

//----------------------------------------------------

int BankDetails::run(NameValueTyp &params)

{

        // Get and Set methods are compulsory for each object

        // The engine will call these to retrieve the objects

 

        if (params["sysMethod"] == "Set")

                return Set(params);

        else if (params["sysMethod"] == "Get")

                return Get(params);

        else if (params["sysMethod"] == "CreateBankDetails")

                return Create(params);

        else if (params["sysMethod"] == "UpdateBankDetails")

                return Update(params);

        else if (params["sysMethod"] == "DeleteBankDetails")

                return Delete(params);

 

        params["sysResultString"] = "ERR: BankDetails::run() - no method with name: " + params["sysMethod"];

        return EXIT_FAILURE;

}

 

//----------------------------------------------------

int BankDetails::Get(NameValueTyp &params)

{

        // Here you implement the Get method which

        // may consist of a search on a db

        // or perhaps an implementation using

        // third party AIPs

        // any mesage printed out to stderr will

        // appear in the log file

        // values for each field declared must be

        // retuned in the params map

       

        cerr << "Get BankDetails" << endl;

        params["Key1"] = "001";

        params["Name"] = "Anthony";

        params["Surname"] = "Dawson";

        return EXIT_SUCCESS;

}

 

 //----------------------------------------------------

int BankDetails::Set(NameValueTyp &params)

{

        cerr << "Set BankDetails" << endl;

        return EXIT_SUCCESS;

}

 

//----------------------------------------------------

int BankDetails::Create(NameValueTyp &params)

{

        cerr << "Create BankDetails" << endl;

        return EXIT_SUCCESS;

}

 

//----------------------------------------------------

int BankDetails::Update(NameValueTyp &params)

{

        cerr << "Create BankDetails" << endl;

        return EXIT_SUCCESS;

}

 

//----------------------------------------------------

int BankDetails::Delete(NameValueTyp &params)

{

        cerr << "Create BankDetails" << endl;

        return EXIT_SUCCESS;

}

 

The Servlet implementation

 

This ties the objects and the connector library together by implementing the initialization, and finish routines. Note that the specification of the object in the constructor could just as well be declared in the initialization routine.

 

#include "Servlet.hh"

 

#include "Account.hh"

#include "BankDetails.hh"

 

 

 

//----------------------------------------------------

Servlet::Servlet(char **argv)

{

                                                //----------------------------------------------------------

                                                // Instanciate the object you want the connector to represent

 BankDetails *b = new BankDetails();

 Account *a = new Account();

                                                                        //-----------------------------------

                                                                        // Set the connector's specifications

        //-----------------------------------

        // Alternative is to get a definition

        // in XML and read that in with a

        // utility

        //-----------------------------------

 

        servletState = running;

                                                                                                                                // -----------------------------------

        servletName = "MigrationDB";                                                                 // The Name Identifying this connector

        servletType = connector;                                                                           // The Name Identifying this connector

                                                                                                                                // AddConfigParam(string paramName, int size,

                                                                                                                                //                string allow, bool display);

        AddConfigParam("Connection String", 20, "^[A-Za-z0-9_]*$", true);               // Configurable parameters

        AddConfigParam("Login", 20, "^[A-Za-z0-9_]*$", true);

        AddConfigParam("Password", 20, "^[A-Za-z0-9_]*$", false);                             // false = Don't display string in style sheet

 

                                                                                                                                //------------------------------------

                                                                                                                                // For object Account

        AddObject("Account");                                                                             // The object name

        AddField("Account", "Key1");                                                                // The fields in this object

        AddField("Account", "Name");

        AddField("Account", "Surname");

        AddField("Account", "Address1");

        AddField("Account", "Address2");

        AddField("Account", "Address3");

                                                                                                                                // The methods availale for this object

        AddMethod("Account", "Get", a);                                                          // Get and Set Are mandatory for every object

        AddMethod("Account", "Set", a);

        AddMethod("Account", "Create_Account", a);

        AddMethod("Account", "Update_Account", a);

        AddMethod("Account", "Delete_Account", a);

                                                                                                                                //------------------------------------

        AddObject("BankDetails");                                                                                       // For object BankDetails

        AddField("BankDetails", "Key1");

        AddField("BankDetails", "Name");

        AddField("BankDetails", "Surname");

 

        AddMethod("BankDetails", "Get", b);

        AddMethod("BankDetails", "Set", b);

        AddMethod("BankDetails", "Create_BankDetails", b);

        AddMethod("BankDetails", "Update_BankDetails", b);

        AddMethod("BankDetails", "Delete_BankDetails", b);

}

 

//----------------------------------------------------

void Servlet::commitTransaction(NameValueTyp &params) throw(exception)

{

        cerr << "commitTransaction called" << endl;

}

 

//----------------------------------------------------

void Servlet::beginTransaction(NameValueTyp &params) throw(exception)

{

        cerr << "beginTransaction called" << endl;

}

 

//----------------------------------------------------

void Servlet::rollBackTransaction(NameValueTyp &params) throw(exception)

{

        cerr << "rollBackTransaction called" << endl;

}

 

//----------------------------------------------------

void Servlet::finish(NameValueTyp &params) throw(exception)

{

        cerr << "finish called" << endl;

}

 

//----------------------------------------------------

void Servlet::service(NameValueTyp &params) throw(exception)

{

}

 

//----------------------------------------------------

void Servlet::init(NameValueTyp &params) throw(exception)

{

                        // check to see if all the parameters we need to be initializes

                        // are actually initialized before we have a go at initializing

 

        if (configParams["Login"].set == true)

        {

        }

}

 

 

Compiling your source

 

#-----------------------------------------------------------

# Defines do the following:

# ------------------------

# DEBUG_LEVELn turns on various levels of debugging

 

DEFINES = -DDEBUG_LEVEL3 -DDEBUG_LEVEL2 -LINUX

 

TARGET_EXE = ../../../bin/MigrationDB

 

 

#------------------------------------------------------------

#              Your source here

SOURCES = Servlet.cc Account.cc BankDetails.cc

 

 

#-----------------------------------------------------------

all: $(TARGET_EXE)

 

 

#-----------------------------------------------------------

INCLUDE_DIR = -I. -I../../lib

 

PROJ_LIBS = -L../../../lib -lthunderbolt

 

#-----------------------------------------------------------

# the following are special GNU-make variables

#-----------------------------------------------------------

LOADLIBES = $(PROJ_LIBS)

LINK.o = $(CXX) $(LDFLAGS) $(TARGET_ARCH)

 

#-----------------------------------------------------------

#.SUFFIXES: .pc

#

#.pc.$(CXX_EXT):

#       $(PROC) $(PROCFLAGS) iname=$* $(PROCPPFLAGS)

 

#-----------------------------------------------------------

# Force auto-dependency checking using GNU make and g++

# (lifted from the GNU make info pages)

# Make sure the lines below are tabbed out and not spaced out

# or this will not work on some system

%.d: %.$(CXX_EXT)

        $(SHELL) -ec 'g++ -MM $(INCLUDE_DIR) $< \

        | sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \

        [ -s $@ ] || rm -f $@'

 

include $(SOURCES:.$(CXX_EXT)=.d)

#-----------------------------------------------------------

 

OBJECTS = $(SOURCES:.$(CXX_EXT)=.o)

 

$(TARGET_EXE): $(OBJECTS) ../../../lib/libthunderbolt.a

        g++ -o $(TARGET_EXE) $(OBJECTS) $(PROJ_LIBS) -lgcc -lpthread

 

clean:

        rm *.d *.o $(TARGET_EXE)

 

 

 

Appendix A – environment variables

 

export M_WARE_PATH=/home/thunderbolt/dev

export M_WARE_LOGS=$M_WARE_PATH/log

export M_WARE_TRANSSPECDIR=$M_WARE_PATH/TransSpec

export M_WARE_PERSISTDIR=$M_WARE_PATH/Persist

export M_WARE_CONFIGDIR=$M_WARE_PATH/ConConfig

export M_WARE_TMP=$M_WARE_PATH/tmp

export M_WARE_TID=$M_WARE_PATH/tid

 

export M_WARE_ENGINEHOSTNAME=ganymede

export M_WARE_ENGINESOCKET=4000

export M_WARE_PERSISTENCE=false