Chapter: System Usage
prev | next | index |
![]() |
The Jet Virtual Medium
by Radu Sion |
We are presenting here methods of using the system. The system as described above is fully functional providing all the advertised facilities and implementations. The first step in using the system would be to download the latest version (http://jvm.sunsite.pub.ro/). Please look at the Online Links and Source Docs Chapter for more details. Unpacking the package may be done by using system specific utilities. Under Windows you may use the winzip program to unpack the provided tgz format package, under Unix you may use the tar and the gzip utility to do this.
Using the system may mean two basic things:
developing applications on top of JVM and running a (distributed)
medium structure.
We are going to talk mainly of the distributed
case here. The multi-server distributed medium topology consists of
many servers, using the jvm.server.DistributedCommunicationHandler
(running in distributed communication mode)
server side plugin or any other compatible one, started at different network
coordinates (host, port). For example you might have on the same computer
many different servers running on different ports. This of course wouldn't
make much sense. The recommended approach is to have only a single server
started on a certain computer. This eases also maintenance tasks and makes
things allot faster. The server generates debugging and logging info
to stdout and stderr, according to the debug level defined inside
the main resource file via the DEBUG_LEVEL resource. The recommended approach
is to filter this output to get relevant informations. For example you
might filter it using the debugging level field that appears in the output.
There is such a filtering tool underway for Unix platforms using awk and
shell scripting.
After unpacking and reading the top level README of the package you are ready for a first test of the facilities provided by JVM. In order to do this we provided a test client application that allows you to test your server based medium. Of course you have to have a java 1.1x (and up) enabled platform.
First you have to start up the medium.
Identify the composing elements (files) of the provided main package. The main elements are contained inside the export/ directory which should contain every binary needed for running the system at server side and also contains all the class files needed for writing a client. The server.jar file contains the server-side part of the system, the client.jar contain the client related classes and also a simple test client app that we are going to use in out example here. If you plan to use, for example, applets that connect to the server then you have to make the client.jar file accessible to the web, together with the class files that compose your applet. (of course;)
In order to start up a server, the CLASSPATH environment variable should contain the server.jar file location, at server side. If you will surely decide to run a distributed multi-server topology, you will start more servers at different net coordinates. (computer, port) Everywhere you have to include the server.jar file in your CLASSPATH variable.
Go to the next section for details on
starting up the servers.
We are going to talk here about starting a distributed medium structure composed of three separate servers running on the same computer, on different ports. The same steps apply to any number of computers/servers running at different coordinates (ports, ip address, etc.) The medium will then be used (in this example) to allow the inter-communication of three different testclient apps (provided also inside the client.jar file) that connect to the three servers (each one to another server) and begin performing usual client tasks like grouping, sending objects, broadcasting, connection testing etc.
We will use the provided jvm.server.DistributedCommunicationHandler plugin, although you may write your own compatible communication handler, implementing maybe also a distributed communication scheme.
In order to start up a server (the same applies to each of the three servers we're planning to start) you have to edit it's main configuration and password file. Simply backup the provided server.res file and then modify it to suit your server. The file is self explaining but we'll explain here the main fast-start steps needed. Please also look at the more detailed docs in the System Resources Section.
Modify DEBUG_LEVEL.
The default usually dumps to much info.
Set it to 2 or 3 in order to get only the main errors and warnings.
Modify SERVER.
This is very important. You should set
here the fully qualified hostname of your computer. (including domainname)
You may also use localhost if you're just playing on a single computer.
If your computer has more ip addresses (and hostnames) and listens to all
of them you have to decide here which one you want to use. This information
is used in identifying uniquely the JVM server from other servers.
Modify PORT.
Another important resource, which you
should set to the portnumber where you want JVM to listen for incomming
client connection requests. Port on which to run the server. This is a
internet TCP port used by the server. The user running the system should
have permissions to use that port. In the case of a Unix server that means
that either the server is run as root or the portnumber is a unused portnumber
above 1024.
Modify PASSWORD_FILE.
Set this to be a filename that points
to a existing file that contains similar entries to the provided passwords
file entries, being the needed passwords for the system servers and clients.
Please look at the authentication section for details
on the passwords file.
Modify PST_COMMUNICATION_HANDLER.
This resource defines the communication
policy of the whole system, defined by the active use communication handler.
This is the fully qualified class name of the required used communication
handler. For more details see the Communication Handlers section. Because
we're starting in this example a distributed multi-server medium we are
using the provided distributed communication handler running in distributed
mode, and this should be set to "jvm.server.DistributedCommunicationHandler".
Modify SYSTEM_WATCHDOG.
Because we are planning to run a distributed
structure we have to use here the required "jvm.server.DistributedMaintenanceWatchdog"
setting, that enables this particular watchdog, needed in cooperation with
the PST_COMMUNICATION_HANDLER resource.
Modify MW_RESOURCES.
This resource setting is needed only
if we use the DistributedMaintenanceWatchdog which uses this resource to
find it's own resource file. This should be set to be the name of a resource
file like the provided watchdog.res file. (PENDING: Write some docs on
the watchdog)
Modify watchdog.res:SERVERS. (This
resource is inside the watchdog.res file)
Make this to be the filename of a file
containing a list of the serverid's of all the started servers, composing
the medium. A sample would be the provided servers.def file.
After modifying all the above resources you are ready to start up the three servers. Let's assume that your computer fully qualified name is "HOST". (This of course can't be true as it doesn't contain any domain name;) Let's assume you have access to the three ports 7009, 7010, 7011 on the computer where you plan to run the three servers. (Remember that we're running three servers on the same computer on different ports, for simplicity) This means that we are using three different server resource files, one for each started server, because they differ at least in the port setting. We can share some other files (like the passwords file or the servers.def file) between the three servers because they run on the same computer, and are started from the same directory etc. (just for this test) Normally each server should have it's own separate configuration files.
In the following we are going to show the summary modification needed inside the resource file of one of the servers. We named this resource file server1.res. The other two remaining resource files (for the other two servers) should differ from this first one only by the PORT resource setting, each server having it's own port where it listens for incomming connection requests.
Your modified main server resource file (server1.res) settings should be (don't modify any other settings !!!):
DEBUG_LEVEL 3 SERVER "HOST" # All servers are on the same computer PORT 7009 # Each server has here another portnumber ! PASSWORD_FILE "passwords" PST_COMMUNICATION_HANDLER "jvm.server.DistributedCommunicationHandler" SYSTEM_WATCHDOG "jvm.server.DistributedMaintenanceWatchdog" MW_RESOURCES "watchdog.res"
Remember also to modify the PORT number to be the corresponding number for the particular server you're starting. That is, inside server1.res PORT should be as above, 7009, inside server2.res PORT should be 7010, inside server3.res PORT should be 7011.
We defined the passwords file to be the file named passwords in the server startup directory (where also the server.res file should be). This is how the passwords file should look like (notice the last line!):
# passwords file # the test users ... test1 "test1" test2 "test2" test3 "test3" # The three servers ... jvm://HOST:7011 "jvm://HOST:7011" jvm://HOST:7010 "jvm://HOST:7010" jvm://HOST:7009 "jvm://HOST:7009" # Just in case ... don't change this jvm://localhost:7011 "jvm://localhost:7011" jvm://localhost:7010 "jvm://localhost:7010" jvm://localhost:7009 "jvm://localhost:7009" 12345.0 "67890.0"
We also defined the system watchdog resource file to be the file named watchdog.res in the server startup directory. This is how this file should look like:
# servers connections (initial topology) definition file SERVERS "servers.def" # this defines how long the watchdog sleeps before trying again # to do it's job ... 30 sec might be a good deal. SLEEP 30000
Inside the above described watchdog.res file we defined the SERVERS resource to be the file named servers.def in the server startup directory. This is how this file should look like:
# file used by the distributed maintenance watchdog. # active servers file definition # this file defines the initial topology of the medium jvm://HOST:7009 jvm://HOST:7010 jvm://HOST:7011
If everything went ok, now it's time to start up the three servers. A server might be started by issuing the following command from withing the main server startup directory, where also the configuration files should be (the export directory might be a good choice):
java jvm.server.ServerMain [server resource filename]
where [server resource filename] is one of server1.res, server2.res, server3.res. Of course you have to issue the above command three times for starting the three servers. On unix you might start the three servers by using a small script like this:
#!/bin/sh # Server startup script. # It basically starts up some JVM servers on the local computer. # ver. 000 java jvm.server.ServerMain server1.res > server1.log 2>&1 & sleep 1 java jvm.server.ServerMain server2.res > server2.log 2>&1 & sleep 1 java jvm.server.ServerMain server3.res > server3.log 2>&1 &
Upon startup, the server will throw allot of debugging and log informations to stdout and stderr. In the above example we redirected all the output to some log files named server1.log, server2.log, server3.log. Please look at the next section on how to use the log output.
Next thing we do is test if the servers started well and run. We do this by connecting directly, using telnet, to each of the servers and issuing any simple text mode command, like described in the Pre-login text mode client-server negotiation protocol section. On unix you might connect to the first server (for example) like this:
telnet HOST 7009
Then you might issue the JVM command HELP, by typing HELP and pressing enter. Then issue for example the commands VER, ECHO teststring, HANDLER, NOP etc. When issuing the HANDLER command, the name of the used "jvm.server.DistributedCommunicationHandler" should appear as server reply. Issue the the QUIT command in order to disconnect from this server and repeat then the same also with the other two servers. (telnet HOST 7010, telnet HOST 7011)
If the above doesn't work you might want to check out the server log files in order to see why the servers didn't start. (PENDING: Write failure faq)
Ok, now we know that the servers are started and running, the medium is constructed of three servers, running on different ports, on the same computer. The next step is starting the testclient, a small app written in order to test the facilities offered by JVM. The application basically connects to a medium server and starts using all the provided facilities. We want to start three apps for connecting to the three different servers and then "talking" to each other via the medium, sending objects, grouping, testing connection speeds etc.
Starting up the test app is easy (remember to include client.jar in the CLASSPATH). The syntax is:
java testclient [serverid] [username] [password] [login-loop-count] [messages-loop-count]
The serverid parameter defines the server to which to connect. The username/password defines the username/password pair to use in login. The login-loop-count parameter defines how many times the client logs in & out (it might be only 1), messages-loop-count defines how many times to repeat sending the same sequence of messages.
Because we're conducting this example on the same computer where also the servers are started we are starting the test clients also from within the export/ directory and directing their log output to different files. On unix this may be done by using the script bellow:
#!/bin/sh # Client test suite startup script. # It basically starts up some JVM clients. # ver. 000 java testclient jvm://HOST:7009 test1 test1 2 10 > client1.log 2>&1 & sleep 3 java testclient jvm://HOST:7010 test2 test2 2 10 > client2.log 2>&1 & sleep 3 java testclient jvm://HOST:7011 test3 test3 2 10 > client3.log 2>&1 &
The above script starts up the three test clients and directs their output to different files, named client1.log, client2.log, client3.log. The clients perform two login/logout passes and 10 message loops at each pass. The output of the script consists of description of each made step. It should be basically consistent across different architectures and platforms although it may differ slightly because of timing issues and overall time.
When testing 100% Java cross-platform compatibility for example, you should check the client log files and verify for consistent output across different java platform implementations. The test client output looks like this:
Simple JVM Test Client ver.1.0 testclient: Creating new Client instance ... testclient: Done. testclient: Connecting to jvm://smart:7009 ... testclient: Connected. testclient: Computing bytes/sec using 2 passes ... testclient: Estimated 17492 bytes/sec rate. testclient: Listing local logged in clients ... testclient: No clients logged in yet. testclient: Login loop no. 0 **************************** testclient: Login as user test1:(test1) testclient: Logged in. testclient: Setting ourselves as incomming message handler. testclient: My unique allocated EntityID is jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://127.0.0.1:0:(server) testclient: The server based synced time is 898384121434 testclient: Groups i am part of now: [null:[everyone]] testclient: Entering group null:[test-group] testclient: Waiting 10 sec for group add ... testclient: Received a java.lang.String from jvm://smart:7009:(server) testclient: Groups i am part of now: [null:[test-group], null:[everyone]] testclient: Exiting group null:[test-group] testclient: Waiting 10 sec for group exit ... testclient: Received a java.lang.String from jvm://smart:7009:(server) testclient: Groups i am part of now: [null:[everyone]] testclient: Entering group null:[test-group] for future use ... testclient: Message loop no. 0 ############################# testclient: Local server broadcast ... testclient: Overall medium broadcast ... testclient: Group broadcast ... testclient: Single destination ... testclient: Multiple destinations ... testclient: Received a java.lang.String from jvm://smart:7009:(server) testclient: Received a java.util.Hashtable from jvm://smart:7009:(test1) testclient: Received a java.util.Vector from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7009:(test1) testclient: Received a java.lang.Long from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7010:(test2) testclient: Received a java.lang.String from jvm://smart:7011:(test3) testclient: Message loop no. 1 ############################# testclient: Local server broadcast ... testclient: Overall medium broadcast ... testclient: Group broadcast ... testclient: Single destination ... testclient: Multiple destinations ... testclient: Received a java.util.Hashtable from jvm://smart:7009:(test1) testclient: Received a java.util.Vector from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7009:(test1) testclient: Received a java.lang.Long from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7009:(test1) testclient: Received a java.lang.String from jvm://smart:7010:(test2) testclient: Received a java.lang.String from jvm://smart:7011:(test3) ... testclient: Sleeping before logout ... testclient: Logging out ... testclient: Login loop no. 1 **************************** testclient: Login as user test1:(test1) ...
The above output illustrates exactly what happens inside the app. You might look inside the app source code to see how the app interacts with the medium via the Client interface.
We see how we send & receive messages
from other entities and also from ourselves, how we enter&exit groups,
how we determine the connection speed of our connection, how we are uniquely
identified inside the medium etc. You may take a look inside the
provided testclient.java source file in order to
We're going to illustrate here a recommended way on how to use server-side stderr/stdout output. Server output is going to stdout & stderr. The level of output is determined currently by the DEBUG_LEVEL resource file setting. Most of the logs are there for debugging purposes, as the system is modular and many new added modules may still be in beta testing. The stderr output starts with a integer number (1-5) which represents the level of importance of that particular log line. (1-most important) We recommend enabling through the DEBUG_LEVEL resource, the level 3 (WARNING and bellow) log output. (That is you have to set DEBUG_LEVEL to 3 inside the main server resource file)
There is a log output parsing tool underway.
Please stay tuned online. Basically the ideea is that you might parse the
output and select relevant lines by using this first field of debug level
information.
This is a task that requires of course some programming skills. You should start by reading first of all the whole general docs. The main entry-point from that moment on should be the jvm.client.Client interface. This is the only class doc that should be necessary for you to be able to use the whole system. Of course looking at jvm.message.EntityID and jvm.message.Message is also required. A implementation of the client interface is the jvm.client.JVMClient, the provided main JVM client class. After writing your application that uses the client interface facilities (be careful not to use any implementation specific methods that don't appear inside the client interface if you want to be able to use also other client implementations) you may want to start testing it inside the system. In most cases testing the application won't require any complex distributed topology schemes so just using the jvm.server.DistributedCommunicationHandler running in single-server mode should suffice for you to be able to test your app. After using this single server medium to test things you may go over to your normal running distributed medium, if there is any need for this.
Please stay tuned online for the JVM
Made Easy Guide for writing apps on top of JVM.
Writing plugins is a task that requires some level of insight into the system, depending of the type of the plugin. In most cases the interface docs of the plugin to be written is enough to make things easy. In some other cases of course looking also at some examples or even at the provided plugins helps even more.
The most difficult task would be writing a new custom communication handler. This requires you to practically think over every aspect of the system, including watchdogs, authentication, overall communication, EntityID usage, Message treatment etc. This task implies thus reading all provided docs and even some source file examples. Remember that the communication handler is practically the core of the system and determines fully all system parameters.
In the case of writing a user watchdog you should become familiar with some internals of the system, depending on what, you need to implement using the watchdog. Remember that a watchdog has access to all the server areas and runs inside the server, thus it should be written very carefully.
The provided password authentication should not be used for security critical applications. You should write your own AuthHandlers instead that may implement complex AUTH schemes. Remember that you have to write a client-side and a server-side handler. The client side handler should be able to negotiate with the server side handler via two i/o streams and to come up with a positive (zero inclusive) AUTH level return. This means that you have to write your own small AUTH protocol or you have to implement certain existing AUTH protocols SSH-alike etc. For some updates on this topic please keep in touch with the online distribution site.
Message filters are easy to write
classes that allow a client to filter messages at the server side. Take
a look at the jvm.message.MessageFilter interface docs for details on how
you should implement in your filter.
The system now is in beta stage. This means that there are still some bugs out there waiting for some special untreated case to pop up. The system is equipped with a fairly good internal checking facility. If a bug pops up, it will, in most cases, show up as a traced internal error information that you should post to the recommended address. Fixes are available as soon as possible, after you post any bug.
Being beta is not the only reason bugs may appear. Most of the existing Java implementations are still buggy and the extent the system makes use of Java facilities may soon bring up some bugs of your particular Java implementation itself. Those bugs are recognizable by showing up as errors or as reported virtual machine internal flaws. Please post those bugs to your Java implementation vendor but also to the author by specifying details on your platform and circumstances.
Thank you for your support.
![]() |
Visit Smart Software. |