JServices

(old product name : JASon)

Version 1.0.0 / 30/04/03

JServices is a container for services activities. This is a practical way for integrating new functions in a cooperating space. JServices provides a lot of mechanism for helping services to know and to share a working flow. User can use it for stand-alone server, for scheduling task or "simply" for building its own Application Server. JServices supports log,cache, many verbosity level, load balacing between threads or processes.

JServices is a shareware, it is free to try for 30 days, else you must register the full version at : http://www.japisoft.com/buy.html

1. Service

a. Introduction
 - JServices
 - Service Sample
 - Service Description
 - Verbose

b. JAS format

c. Standard services
 - AbstractService
 - ThreadableService
 - TaskableService
 - SocketService
 - ProcessableService
 - SchedulableService
 - Toolkit

d. Cooperation

e. State

2. Domain

a. Introduction
b. Door
c. Load Balancing
d. Score
e. Working space
f. Alert

3. Administration

a. Commands
b. Swing interface


1. Service

a. Introduction

JServices

JServices is a Java Services framework. This is a waste services container for Java Background tasks. A service is a piece of code that implements the jason.core.Service interface. Theorically, this is a thing that can be started and stopped and that needs a configuration for working propertly. JServices doesn't care about the service role, it cares only to offer the best space for helping the service to achieve its job,
helping administrator to control it, helping to share ressources and optimize it for working a long time. The way for exchanging service data or interact with the service container is the service context. Each service is initialized with a service context.  

What does JServices mainly offer ?

  1. A Service context that takes into account an XML configuration
  2. A Cache with several strategies
  3. An unlimited Thread pooling mechanism
  4. A special queue for processing
  5. A way to delegate processing to another service
  6. A switch to select a cooperation mode with multiple criterias
  7. A rating for knowing the best service at the good time
  8. A multiple verbose level with a powerful log system
  9. A lot of service from the core to be inherited (administration, updating, scheduler...)

Service Sample

Before describing what can be a Service, I propose you here to study an old straightforward Service : the admin service located before in the bin/conf/services/admin.xml file.

<!DOCTYPE service SYSTEM "conf/service.dtd">

<!-- Admin Service This service is used for stopping/starting a service
remotly -->

<service name="admin" classpath="classes/classes.jar"
class="jason.service.admin.AdminService"
verbose="true" thread="true" process="false">

<verbose type="*" enabled="true"/>

<!-- Trace user request -->

<property name="trace" value="false"/>
<property name="admin" value="jason01"/>
<property name="password" value="z86"/>
<property name="port" value="10000"/>

</service>

In this example, the admin service is known by the class jason.service.admin.AdminService that implements the jason.core.Service interface.

We define a set of properties like the trace support, an admin account, a password or a port value that will be used by this service for initializing correctly. We specify that this service should be "processable" (supports load balancing between processes) with the process attribute. We include too a politics for verbosity for any trace on the console with '<verbose type="*" enabled="true"/>'. Here it means, that all verbose level message should be supported by the service container.

As JServices supports its own "classLoader", you can specify a class location thanks to the classpath attribute. Here we locate the classes in the classes/classes.jar file. This location is again relativly to the service description location (here bin/conf/services/admin.xml). This classpath can contain a CLASSPATH similar syntax using ';' or ':' for separating each jar/zip or directory.

The problem is now to include this service into JServices. JServices supports many way to integrate services. The first way is to declare this service in the jason.xml main configuration file.

Here we locate this description service in the services/admin.jml relativly to the jason.xml file location (in the bin/conf directory).

... jason.xml previous part

<!-- This is an example of independant service description -->
<service location="services/admin.jml">

<!-- We override the port property to a new value as example -->

<property name="port" value="10004"/>

</service>

...

We override a property too for demonstration which it's the administration port. This first step is good enough but it doesn't look pretty practical to include this admin service as a real plugIn. JServices support a plugIn format extended by '.jas'. Look at this description in the JAS format section.

Another method is the usage of the door mechanism. A door is a piece of code that user can integrate to JServices for detecting new service and including it into the JServices container. By default the default door scans a path and includes any service description in XML or in JAS. For a flawless usage, you could integrate services from another JServices server or from Internet (by HTTP). Note that the door system is the
best suggested way for service intergration because it is tied to the updating service.

Service Description

Now we know how to insert a new service, we look a bit more at the Service Definition. This service uses the conf/service.dtd DTD for validating the content.

Service tag
Attribute Role
name Name of the service
class Java class of the service. This class must directly or indirectly implement the jason.core.Service interface
classpath Service classpath similar to the CLASSPATH syntax
verbose Enable/Disable verbosity
test Enable/Disable test for the first request
thread Enable/Disable the thread pooling usage
process Enable/Disable the load balancing between process.
persistence Delete or not the service file after inserting into the JServices container
start-period Activate the service every specified minutes. Only for service that extends the jason.core.SchedulableService class
start-minute Activate the service at the right time for the specified minutes. Only for service that extends the jason.core.SchedulableService class
start-hour Activate the service at the right time for the specified hour. Only for service that extends the jason.core.SchedulableService class
start-day Activate the service at the right date for the specified day. Only for service that extends the jason.core.SchedulableService class
start-month Activate the service at the right date for the specified month. Only for service that extends the jason.core.SchedulableService class
autoRestart
Restart the service automatically on a service runtime exception. By default 'false'
autoRestartCounter
Integer for specifying how many times for trying to restart. By default '-1' meaning infinite times
Verbose tag
Attribute Role
type An integer that indicates a verbose level
enabled Enable/Disable the verbose for the tied level

The service properties are described in the property.dtd. This description follows a part of the XML-RPC specification. So user can define complex properties structure with array and hashtable.

Property tag
Attribute Role
name Name of the property
value Value of the property

When a property doesn't contain a value attribute, it can contain the following tags :

... Service description

<!-- Structure with Array -->

<property name="test3">
<struct>
<member name="test3.1">
<value><string>Value for test3.1</string></value>
</member>
<member >
<name>test3.2</name>
<value>
<array>
<data>
<value><boolean>false</boolean></value>
<value><double>21.1</double></value>
</data>
</array>
</value>
</member>
</struct>
</property>

Bellow, we define a property in a service description file which is an "hashtable" containing for the key test3.1 a string and for the key test3.2 an array. In a Service java code, we will get it thanks to the getProperty method.

Verbose

Here we describe how to manage verbose. In the Service description, we show that a verbose tag exists. So the question is how to manage it for selecting only a verbose at a time ?. If you look at the jason.core.AbstractService which is a common class for Service, you will see the sendCustomMessage( int type, String message ) definition. Here, we specify a verbose type with the first argument and a verbose message witht the last one.

You can use several verbose definitions in your service like that :

... Previous service definition
<verbose type="1" enabled="true"/>
<verbose type="2" enabled="false"/>
<verbose type="3" enabled="true"/>

Here we enable the verbose type "1" and "3" but not the "2". It means that any verbose with sendCustomMessage( 2, 'message' ) will not be processed by the container.

You can use a generic type '*' for describing all verbose type.

Verbosity is also for usual message : Information, Warning, Error and InnerError. All this is available respectivly with the methods : sendInformationMessage,sendWarningMessage,sendErrorMessage,sendInnerError. These methods are available from the jason.coreAbstractService or if you wish only to implement the jason.core.Service service from the jason.core.ServiceContext

b. JAS format

A good way for integrating service in the container is the usage of the JAS format. This format is simply a jar file that contains XML file describing service and a set of libraries and classes for the service working.

For instance, consider the administration service that needs an admin.jml file for description and a classes.jar file for classes.

>jar cvf admin.jas admin.jml classes

The new admin.jas file can now be integrated in JServices through a door location. A default door is in the bin/conf/door directory. We simply copy the admin.jas in this directory and we restart JServices for taking into consideration this service.

When JServices finds a .jas format, it creates a directory labelled from the file name and uncompresses the file. Then, it searches for all .jml file and run as possible each service.

The usage of JAS is in relation with the default Door. Look at this section for more information on the Door.

Note for the 0.8 version : For practical reason, the previous .xml service format is renamed as .jml for the JServices Markup Language. The content is not altered with the 0.7 version.

c. Standard Services

AbstractService

At this step, we have seen a short decription of service from the XML point of view. Now, we describe the service reality in a more Java sens.

For building a service, user can extend the jason.core.AbstractService class that implements the jason.core.Service interface. He can read a property with the getProperty, getIntProperty, getBooleanProperty methods. The getProperty returns an Object that must be casted. So for the last choice, be careful not to alter the property description without changing the service code. 

Here a sample of service :

/**
* Here a straightforward class for a minimal service usage
*
* @author "Alexandre Brillant"
* @version 1.0
* @since 1.0
* @see AbstractService
*/
public class HelloService extends AbstractService {
/**
* In this constructor, I specify not to use this service in a Thread
* So it will be run once only.
*/
public HelloService() {
super();
}

/**
* This method will be called by the container */
public void run() {
// Show a simple message
String message = getProperty( "message" );
sendInformationMessage( message );
}
}

In this service, we don't expect to be run more that once, that why we specify to inherit from the jason.coreAbstractService. We send an information to the console with the sendInformationMessage method. This message will be available too in the bin/log directory (a little delay may be needed for refreshing).

Note that it is not necessary to override the init,start or stop method for doing a particularing step code. Use rather if you inherit from the AbstractService :

ThreadableService

This last code looks prettily ridiculous, so how to change the behavior and run it in a thread that could send a message every 30s. We will see later that the scheduler is a better candidate for that, but for the moment we concentrate on the AbstractService.

The first thing is to change the parent class AbstractService by the class ThreadableService. We specify to run this service as a Thread in the constructor by super(true), so the run method will now be called by a thread. The second thing is to specify the loop delay for our thread with the setThreadLoopDelay method from the ThreadableService. Not that by default the thread as a loop behavior that launches your run method, so you needn't to manage a loop yourself. You can stop this thread by the stop() method or by the setThreadLoopMode method.

Here a sample of service :

/**
 * Here a straightforward thread class for a minimal usage
 * @version 1.0
 * @see ThreadableService
 */
public class HelloThreadableService extends ThreadableService {

    /**
     * In this constructor, I specify to use this service in a Thread
     * So it will be run once only. */

    public HelloThreadableService() {
    super( true );
    // Manage the thread loop
    setThreadLoopMode( true );
    // 30 * 1000 ms = 30 s
    setThreadLoopDelay( 30 * 1000 );
    }

    /**
     * This method will be called by the container */
    public void run() {
    // Show a simple message
    String message = getStringProperty( "message" );
    sendInformationMessage( message );
    }
}

TaskableService

A TaskableService is a good starting parent class when your service needs to do a short work regularly. For instance, your service could be an HTTP server, so it needs to do always the same task which is "get a document and return it to a client with a Socket". TaskableService is also a subclass of the ThreadableService, it adds the method notifyTask that takes a Task object as parameter.

A Task is a little interface. It has two methods, one for initializing the task (init) and one for starting the task (runTask). This is very similar to a thread, however it mustn't be confused, because a task is run only once.

The Taskable service is for parallelling running. So it can cost a lot of thread depending on your multiple instance of Task. JServices integrates a system for dispatching finely the Tasks to threads. Morever, it is able to delay a Task in a common Task queue. This task is dispatched to a special service  : the TaskService.

Note that is the setThreadable( false ) method is called, the task will be runned in the current JServices thread which is very bad for global performance but you have only one service (??). 

For helping you to build a Task, an AbstractTask class is available.

Here a sample of task :

/** Here a part of the admin service, this is a task for
processing a user request. These request is tied with a
socket. That's why we extends from SocketTask that itself extends
from the AbstractTask */
class AdminProcessing extends SocketTask {
public AdminProcessing( Socket host ) {
super( host );
}
public void run() {
// Our running code ...

}

We can send our task thanks to the notifyTask method from the TaskableService.

SocketService

SocketService is a subclass of the TaskableService. It concentrates on the Socket management. By default it uses a port property from the JServices service description, listening for an host request.

User must override the method getTaskForSocket. It returns an object that supports the Task interface. Hence when a user sends a request it is directly managed by calling this method. When user returns a Task, this is dispatched to a thread pooling manager that can itself sends this task in a processing queue if no thread are available (with the jason.core.service.TaskService)

Several abstract class are available for Task :

Here a sample of SocketService from the AdminService implementation

...

/**
* Admin
* Service that offers administration capacity for JASon.
* It can for known user stops and starts special service.
*
* Next release could include information about working
*
* @author Alexandre Brillant
* @version 1.2 */
public class AdminService extends SocketService {

public static String TYPE = "admin";

public AdminService() {
super();
initActions();
try {
setType( new ServiceType( ServiceType.JASON_SERVICE, new String[] { TYPE } ) );
} catch( ServiceException exc ) {
fireCriticalErrorDetected( exc );
}
}

...

protected Task getTaskForSocket( Socket host ) throws ServiceException {
return new AdminProcessing( host );
}

In this sample, the AdminService processes any request from the port property value thanks to the AdminProcessing object. Here the code for this object.

    class AdminProcessing extends SocketTask {

public AdminProcessing( Socket host ) {
super( host );
}

public void run() {
try {
...
} catch( IOException ex ) {
sendErrorMessage( ex.getMessage() );
}
}
}

ProcessableService

A subclass of the SocketService is the ProcessableService for load-balancing an host request between processes. The ProcessableServicecreates a copy of the request and dispatches it to another JServices server. For helping the SocketService to build this copy, you may have to override the method getHostRequestFromInputStream.

You can find several examples of ProcessableService with the following services :

Please look at the Load Balancing section for more information.

SchedulableService

A schedulable service is another service type, it can be started at a particular date or period. This last value if defined in the conf/service.dtd DTD with the values

These values can be associated, like "start-minute=0 and start-hour=0" for starting the service once by day at midnight. As the Schedulable service class extends the AbstractService, the only thing to do is to defined the run method with the needed task.

Here a sample of schedulable service :

package jason.core.service;

import jason.core.*;
import java.util.Date;

/**
*
* This is a service for testing only,
* it does no operation
*/
public class NopSchedulableService extends SchedulableService {
public NopSchedulableService() {
setName( "nop-schedule" );
}

/**
* default behavior */
protected void notifyInitReady() {
sendInformationMessage( "init at " + new Date() );
}

protected void notifyStartReady() {
sendInformationMessage( "start at " + new Date() );
}

protected void notifyStopReady() {
sendInformationMessage( "stop at " + new Date() );
}

}

This code simply showes a "start at " message each time the service is started. For instance, if I specify a start-period of 10, this message will appear every 10 minutes.

Toolkit

JServices provides more Services class for helping you.

Class Role
jason.core.service.InnerService This is used only for inner service. This class notifies the container that this service can be overrided by another service
jason.core.service.DebugService This service will print all properties when running. This is useful to debug your property description
jason.core.service.NopSchedulableService A minimal schedulable service that shows a date when it is started and stopped
jason.core.service.NopService A minimal serivce that shows a date when it is started and stopped

d. Cooperation

One way to cooperate with other service is the ServiceType class, this is defined in each service by the setType method ( from the AbstractService only, else the Service interface support the getType).

For instance :

setType( new ServiceType( ServiceType.CUSTOM, "hello" ) );

In this case, we define (note this is better to set it in the constructor of your service), a serviceType that comes into the CUSTOM category with a hello type target. It means that your service proposes to manage any requests tied to the "hello" category. Note that a service can support several types at once.

On the contrary, you can find now every services matching this type by the getServiceForType method from the ServiceContext class (accessible in the Service interface).

Here a part of the ServiceContext code to show you how to send a request to a particular service Type

    public void sendInformationMessage( String service, String content ) {
getMessageHandler().sendInformationMessage( service, content );
try {
fireRequestForType( jason.core.service.LogService.TYPE, new ServiceRequest( service + "(Inf) : " + content ) );
} catch( ServiceException exc ) {}
}

This method will invoke a LogService type by the fireRequestForType. A Service request is wrapped with the ServiceRequest class.

So, another way to delegate a request is the usage of the fireRequestForType method in the ServiceContext. For finding a service, the ServiceContext will search all service matching the good type, then it will try to manage to request using the manageRequest method of each Service. The first one that will have a good response will be the used one. A good response is a response that is not null and that doesn't throws a ServiceException.

Another important way to delegate a request is the usage of multiple criteria. The JServices evaluates each services with a rate mechanism. So you can select a service for a rate using another argument in the fireRequestForType. This argument can be one of the following values :

e. State

A service can store its inner state. This is possible thanks to the jason.core.ServiceState class. This class uses reflection for getting current class values (the stored values). These values comes fom every "get" method that support a Serializable returned object. This values doesn't include those of the ancestor classes of the service. For understanding how its works, here a service state storing and restoring cycle :

Restoring cycle :

1. The service is made persistent (invoking setPersistent(true))
2. The service is initialized (invoking init)
3. The ServiceState object is retreived thanks to the service name on disk
4. The state of the service is restored (invoking all "set" methods)
5. The service is started (invoking start)

Storing cycle :

1. The service is started
2. The service is stopped (invoking stop)
3. The ServiceContainer is notified of the service stopped state
4. The ServiceContainer retreives the current ServiceState object (invoking getServiceState)
5. The ServiceState is serialized on disk thanks to the service name.

Here a sample of service that stored/restored its state with the CurrentDate property :

...

public class HelloServiceExt extends AbstractService {


    public HelloServiceExt() {
    super();
     setName( "Hello2" );
// Important method for state storage usage
     setPersistent( true );
// At the end of the run method the stop method will be invokated 
    setAutoStop( true );
    }

    /** Current date */
    private Date cCurrentDate;


    /** Method for persistence demonstration */
    public void setCurrentDate( Date currentDate ) {
    this.cCurrentDate = currentDate;
    }

    /** Method for persistence demonstration */
    public Date getCurrentDate() {
    if ( cCurrentDate == null )
         setCurrentDate( new Date() );
    return cCurrentDate;
    }

    /**
     * This method will be called by the container */
    public void run() {
    // Show a simple message
    String message = "New message " + getStringProperty( "message"
) + " first at " + getCurrentDate();
    sendInformationMessage( message );
    getServiceContext().cleanWorkingDirectory( true );

    try {
        // Write it in a temporary file
        BufferedWriter mWriter = new BufferedWriter( getServiceContext().getWorkingDirectoryFileWriter( "message.txt" ) );
        mWriter.write( message );
        mWriter.close();
    } catch( Exception exc ) {
        System.err.println( "Can't write to message.txt" );
    }
...

 In this last example, the current date is stored and restored automatically even if we stop the JServices server.

JServices stores the service state in the working directory in a "_state" file. Note that the cleanWorkingDirectory method from the ServiceContext will ignore such file.

2. Domain

a. Introduction

A domain contains all user services. It is defined in the bin/conf/jason.xml file. This file supports the jason.dtd DTD. A domain has a set of service definition. Each service description is stored in a single XML file or bundled in a large XML file. In the last case, a file has several service definition. The location of each service is done relativly to the jason.xml file. For instance if I write that the location of my service is myService.xml, it means it is stored in the same level than the jason.xml file.

Here a Domain definition example :

<?xml version="1.0"?>

<!DOCTYPE jason SYSTEM "conf/jason.dtd">


<jason version="x" domain="default">

<!-- Domain definition -->

<domain name="default" verbose="true">

<!-- This is an example of a configuration services file -->

<services location="services.xml"/>

<!-- This is an example of independant service description -->

<service location="services/admin.xml">
<!-- We override the port property to a new value as example -->

<property name="port" value="10004"/>
</service>

<!-- Here a message handler, look at the jason.core.MessageHandler interface for your own handler -->

<messageHandler class="jason.core.ConsoleMessageHandler"/>
</domain>

</jason>

In this domain definition, we load several services from the services.xml file and the file. The first one contains the definition of the HTTP service and the Servlet engine service. The last one is desribed in the first part of this document.

Note that user can override service properties, this is done above with the services/admin.xml file, we update the port property to a value of 10004.

User can update the log system by defining a class that implements the jason.core.MessageHandler interface. This interface has four methods :

/** This method give the current domain, user can ignore it */

public void setDomain( Domain d );

/** Show an error message from a service */

public void sendErrorMessage( String service, String content );

/** Show a warning message from a service */

public void sendWarningMessage( String service, String content );

/** Show an Information message from a service */

public void sendInformationMessage( String service, String content );

User can update it with the messageHandler class. By default we use the jason.core.ConsoleMessageHandler class that prints any log to the console.

b. Door

Integrating new service seems a bit difficult because we can corrupt easily the server configuration. JServices support another mecanism for including services called "Door". A door is first of all a tag in the Domain definition file that contains a location attribute. This location by default contains a directory. When starting a Domain, JServices will list all service file from this location and include in the current Domain.

For instance : <door location="door" name="defaultDoor"/> means loading when starting all services from the door directory in the relativly to the configuration file.

User can change the behavior of the door by specifying a class in the door definition that implements the Door interface. This interface will return simply all valid services.

User can for instance load services from an HTTP server, or any suitable protocol....

A domain can contains a non limited number of Door.

c. Load Balancing

JServices supports serveral levels of Load Balancing. The first one is a Thread Balancing and the second one is a Process Balancing. Due to an original concept, JServices builds a super-server when the user runs several processes.

Each service can accept or not the Load Balancing though the attributes 'thread and process in the Service tag.

How it works ? JServices supports the Load Balancing for all service that extends the jason.core.ProcessableService. When you run several process of JServices, each service try to see if another service uses the current port, if it is true, they try to contact the other service to collaborate. When the attribute 'process' is not equals to the 'false' value, the cooperation is established.

Here the standard JServices trace when you run it once :

Starting JASon x ... 

[domain/default] Starting the domain

[domain/default] Starting http_1.0

[domain/default] Starting crusader

[crusader] Mapping /servlet/servletTest --> jason.servlets.ServletTest

[http_1.0] Listening on port :10001

[domain/default] Starting admin

[crusader] Listening on port :8080

[admin] Listening on port :10004

Here the standard JServices trace when you run it twice :

Starting JASon x ... 

[domain/default] Starting the domain

[domain/default] Starting http_1.0

[domain/default] Starting crusader

[crusader] Mapping /servlet/servletTest -->
jason.servlets.ServletTest

[http_1.0] Listening on port :10001

**[http_1.0] Can't use the port : 10001 / Adresse déjà utilisée

[http_1.0] LoadBalancing mode for service on port 10002

[http_1.0] Listening on port :10002

[domain/default] Starting admin

[crusader] Listening on port :8080

** [crusader] Can't use the port : 8080 / Adresse déjà utilisée

[crusader] LoadBalancing mode for service on port 8081

[crusader] Listening on port :8081

[admin] Listening on port :10004

** [admin] Can't use the port : 10004 / Adresse déjà utilisée [admin]
Can't run the service

In this second running, each service tries to run on the default port. As this default port is already used by the first JServices instance, they try to find another port by getting a new incremented number. When they find a free port, they contact the original JServices services for cooperation. Cooperation is a way to balance each user request into several process. The original services (from the first instance) maintains a cursor that point to a service in the current process or in another process.

To communicate, service uses a simple protocol that starts with the ASCII code 1, so it is impossible for you to use a protocol with this fact. Note that for the moment, a service waits for the code 1 and a port number for establishing the load Balancing.

For instance the crusader module will balance user request to the port 8080 or the port 8081. In the same way, the http service will balance a user request to the port 10001 or the port 10002.

If you stop a service or if a service crashes, JServices will remove this service from the collaborative list and will continue to work with remain services.

Note that in this version, JServices doesn't support to load balancing into serveral computer. This function will be established very soon through an extension of the domain definition

From the API point of view, you have to inherit from the to support load balancing. When a request must be load balanced, it is necessary to download the full request in memory. The problem is that sometime the connexion is never closed depending on the protocol (like HTTP) so you have to show to the service how to be sure to have the full request.

Here the default code from JServices to download fully the user request. This code is available on the jason.core.HTTPService.

    protected byte[] getHostRequestFromInputStream( InputStream in ) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int last1 = 0;
int last2 = 0;
int last3 = 0;

while ( true ) {
int n = in.read();
if ( n == -1 )
break;
// Condition out for HTTP only
if ( ( n == 10 ) && ( last1 == 13 ) && ( last2 == 10 ) && ( last3 == 13 ) )
break;
out.write( n );
last3 = last2;
last2 = last1;
last1 = n;
}
return out.toByteArray();
}

As you can see, this is a simple way to download fully an HTTP request, the request is stored in a byte array only if this is the end of the input stream (value = -1 ) or if two consecutive caracters 10 and 13 (\n et \r) are found.

d. Score

The JServices container defines a rate for all service which is available when starting JServices. By default the score is componed of two part :

By default a Service has a score of '0.0' meansing for the first a 0 rate for user request processing and for the last a 0 rate for service request. Here a sample of JServices scoring.

Starting JASon x ...
[domain/default] Starting the domain default with 8 services
[domain/default] Starting scheduler v1.0 / s0.0
[domain/default] Starting log v1.0 / s0.1
[domain/default] Starting task v1.0 / s0.0
[domain/default] Starting http_1.0 v1.0 / s0.0
[domain/default] Starting crusader v1.0 / s1.0
[crusader] Mapping /servlet/servletTest --> jason.servlets.ServletTest
[http_1.0] Listening on port :10001
[domain/default] Starting admin v1.0 / s0.0
[crusader] Listening on port :8080
[admin] Listening on port :10004
[test2] init at Mon Jun 17 11:52:12 CEST 2002
[scheduler] Add schedulable service test2
[domain/default] Starting hello v1.0 / s-2.0
[hello] Hello World

After each Service version, we find a score by the 's' letter. For instance the 'crusader' has a 1.0 score meaning a '1' rate for user request and a '0' rate for service request.

All this score are stored in the file bin/state/score.xml updated when you stop the JServices server.
<?xml version="1.0" encoding="ISO-8859-1"?>
<score>
<service host="0" id="admin/v1.0" request="0"/>
<service host="1" id="crusader/v1.0" request="0"/>
<service host="0" id="log/v1.0" request="1"/>
<service host="0" id="task/v1.0" request="0"/>
<service host="-2" id="hello/v1.0" request="0"/>
<service host="-2" id="test2/v1.0" request="0"/>
<service host="0" id="http_1.0/v1.0" request="0"/>
<service host="0" id="scheduler/v1.0" request="0"/>
</score>


e. Working Space

Each service has a working disk space, this space is stored in the working directory. Each service has a sub-directory depending on the service name :

Here a sample of directories :

drwxr-xr-x    2 abrillan cvs          4096 oct  6 20:31 hello/
drwxr-xr-x    2 abrillan cvs          4096 oct  6 16:32 log/
drwxr-xr-x    2 abrillan cvs          4096 oct  6 16:32 scheduler/
drwxr-xr-x    2 abrillan cvs          4096 oct  6 16:32 task/
drwxr-xr-x    2 abrillan cvs          4096 oct  6 16:32 Updatable/

Each service directory is available by the ServiceContext.

Here a sample of Service writing on the working directory :

/**
* This method will be called by the container */
public void run() {
// Show a simple message
String message = "New message" + getStringProperty( "message" );
sendInformationMessage( message );
getServiceContext().cleanWorkingDirectory( true );

try {
// Write it in a temporary file
BufferedWriter mWriter = new BufferedWriter( getServiceContext().getWorkingDirectoryFileWriter("message.txt" ) );
mWriter.write( message );
mWriter.close();
} catch( Exception exc ) {
System.err.println("Can't write to message.txt" );
}
}


In this example, we clean the tied service directory with getServiceContext().cleanWorkingDirectory( true ); including sub-directories. We write a file
thanks to the getServiceContext().getWorkingDirectoryFileWriter("message.txt" ) instruction returning a FileWriter.


f. Alert

A domain can contain a set of alert properties. This properties is used by the AlertService for sending mail to one or several user for three service message types :
You choose one or several of this message types using the 'alert' tag from the bin/conf/jason.xml.

 <jason version="1.0" domain="default">

 <!-- Domain definition -->

 <domain name="default" verbose="true">
    <alert host="smtp.yourHost" user="admin1@myCompany.be" warning="false" error="true" exception="true"/>
    <alert host="smtp.yourHost" user="admin2@myCompany.be" warning="true" error="true" exception="true"/>

...

In this sample, we send alerts to adm1@myCompany.be for each error or excepion message from one service. The same thing for
admin2@myCompany.be with also the warning messages.

3. Administration


Clients are remoted administration commands. We have both command line and GUI interface facilities.

a. Commands


Here a description of a commands found in the /bin directory :

Command
Role
Result sample
startService [Service name]
Start a service.

stopService [Service name]
Stop a service

listService [*]
List available services
scheduler
log
admin
time
listeService
List available services with its name, state, version and information.
Here the state number meaning :
-1 : No state
0 :  Initialized
1 : Stopped
2 : Started
scheduler       2       v1.1    null
log     2       v1.1    null
admin   2       v1.1    null
time    2       v1.0    null
listpService
List properties of the service
port=20000
setService [Service name] [Property] [value]
Update a service property

putService [JAS file path]
Add a new service. The service must be in the .JAS format


b. Swing interface

The swing interface uses all previous commands but the setService. For starting the interface, use the client.sh or client.bat commands. Once you have run the interface, you may have to change the connection parameters using the Server/Login menu. Press the Connection button, a tree will be generated with all current JServices services. You can click on a node and start/stop the tied service


(c) 2002-2003 JAPISOFT