2.A. Parameter Server

2.A.1. Writing a Parameter Server

Report Viewer supports push technology by means of interacting with a parameter server. A programmer can write a parameter server using the class quadbase.reportdesigner.ReportViewer.ParamServer to supply updated data continuously for Report Viewer to plot the report.

On the client side, the HTML syntax is:

<applet code = "quadbase.reportdesigner.ReportViewer.Viewer.class" width=640 height=480>
<PARAM name="filename" value="example.rpt">
<PARAM name="ParameterServer" value="machine:portno">
</applet>
            

Once the browser has loaded Report Viewer class and the report data from the web server, Report Viewer attempts to connect to the specific machine and port number identified in the parameter. For security reasons untrusted applets are not allowed to open a connection to other machines. The parameter server can interact with Report Viewer in order to update and manipulate the records held by Report Viewer.

On the server side, a server program should be written to listen to the port number. This server can be written using the class quadbase.reportdesigner.ReportViewer.ParamServer.

Upon opening a connection, the server will supply data to Report Viewer.

The constructor for the server is:

public ParamServer(DataInputStream in, DataOutputStream out)
            

Where in and out are the socket input and output used to communicate with the server.

ParamServer has three basic methods to manipulate the records in Report Viewer:

int addRecord(Object record[]);
int deleteRecord(int recordNo);
int updateRecord(Object record[], int recordNo);
            

After a sequence of record updates a final call

void repaint();
            

will send a request to Report Viewer to repaint the report using the new data.

The following Java program provides an example of using the parameter server class to generate new reports. Report API for ParamServer is provided in the online API documentation. In this example, one field in the twelfth record is simply updated with an integer chosen at random. In a real application, a programmer would have to write the code which enables the parameter server to interact with the data source.

import java.io.*;
import java.net.*;
import java.util.*;
import quadbase.reportdesigner.ReportViewer.ParamServer;

// Sample Program to update the data in EspressReport Viewer
// using Parameter Server
public class pserver extends Thread {
protected int port = 1997; // port no for report viewer to connect

protected ServerSocket listen_socket;

public static void fail(Exception e, String msg) {
System.err.println(msg + ":" + e);
System.exit(1);
}

public pserver() {
try {
listen_socket = new ServerSocket(port);
}
catch (IOException e) {
fail(e, "Exception creating server socket");
}
this.start();
}
public void run() {
try {
while(true) {
// create a thread for each connection to handle the
// request
Socket client_socket = listen_socket.accept();
Connection c = new Connection(client_socket);
}
}
catch (IOException e) {
fail(e, "Exception while listening for connections");
}
}
public static void main(String[] args) {
new pserver();
}
}

class Connection extends Thread {
protected Socket client;
protected DataInputStream in;
protected DataOutputStream out;

public Connection(Socket client_socket) {
client = client_socket;
try { // get the input and output stream
in = new DataInputStream(client.getInputStream());
out = new
DataOutputStream(client.getOutputStream());
}
catch (IOException e) {
try {
client.close();
}
catch (IOException e2) {}
return;
}
this.start();
}

public void run() {
ParamServer paramserver;
Random random = new Random(System.currentTimeMillis());
try {
paramserver = new ParamServer(in, out);
System.out.println("Total no of record = " + paramserver.getRecordNo());

// get record 12 from the report viewer
Object rec[] = paramserver.getRecord(12);
for (int i=0; i < 100; i++) {
// update the third field of record 12
rec[3] = new Integer(random.nextInt() % 30);
paramserver.updateRecord(rec, 12);
// tell the report viewer to repaint //after every tenth record is updated
if (i % 10 == 0)
paramserver.repaint();
}
}
catch (IOException e) {}
finally {
try {
client.close();
}
catch (IOException e2) {}
}
}
}
            

Report Viewer would have read an HTML file of the form:

<html>
<title>Sample Report</title>
<applet code = "quadbase.reportdesigner.ReportViewer.Viewer.class" width=600 height=450>
<PARAM name="filename" value="PServer.cht">
<PARAM name="ParameterServer" value=":1997">
</applet>
</html>
            

Here the Java class that Report Viewer reads is the name of a report file Pserver.rpt and the next line specifies the machine and port to which Report Viewer should open a connection. EspressManager will then provide information to Report Viewer at regular intervals such as updated records so that Report Viewer can refresh the report it displays.

2.A.1.1. Variables

UPDATE_RECORD

public final static int UPDATE_RECORD

INSERT_RECORD

public final static int INSERT_RECORD

DELETE_RECORD

public final static int DELETE_RECORD

GET_RECORD

public final static int GET_RECORD

GET_RECORDNO

public final static int GET_RECORDNO

GET_RECORD_DATATYPE

public final static int GET_RECORD_DATATYPE

REPAINT

public final static int REPAINT

OK

public final static int OK

ERROR

public final static int ERROR

2.A.1.2. Constructor

public ParamServer(DataInputStream in, DataOutputStream out) throws IOException

Constructor for Parameter Server

2.A.1.3. Methods

updateRecord

public int updateRecord(String rec[], int recordNo) throws IOException

Update a record

Parameters:

rec - the record passed in as a string array, see class quadbase.reportdesigner.ReportAPI.DbData for the format of the string array.

recordNo - the record number to be updated

Returns:

OK if success, returns ERROR if no such record number or record type mismatch.

updateRecord

public int updateRecord(Object rec[], int recordNo) throws IOException

Update a record

Parameters:

rec - the record passed in as an object array

recordNo - the record number to be updated

Returns:

OK if success, return ERROR if no such record number or record type mismatch.

addRecord

public int addRecord(String rec[]) throws IOException

Add a record

Parameters:

rec - the record passed in as string array

Returns:

OK if success, returns ERROR if record type mismatch.

addRecord

public int addRecord(Object rec[]) throws IOException

Add a record

Parameters:

rec - the record passed in as an object array

Returns:

OK if success, returns ERROR if record type mismatch.

deleteRecord

public int deleteRecord(int recordNo) throws IOException

Delete a record

Parameters:

recordNo - the record number to be deleted

Returns:

OK if success, returns ERROR if record type mismatch.

repaint

public void repaint() throws IOException

Inform the report viewer to repaint the report

checkRecord

public Boolean checkRecord(Object rec[])

Auxiliary function to check whether the record type given matches the record type used in report viewer

Parameters:

rec - the input record to be checked

Returns:

true if record match, otherwise return false

getRecordNo

public int getRecordNo() throws IOException

Get the number of records used

Returns:

the number of record

getDataType

public int[] getDataType() throws IOException

Get the data type of the record used

Returns:

array of data types as defined in jdbc/Types.class, the size of the array is equal to the number of field in record

getRecordSize

public int getRecordSize()

Get the number of fields in record

Returns:

number of fields in record

getRecord

public Object[] getRecord(int recordNo) throws IOException

Get the record

Parameters:

recordNo - the record number to be retrieved

Returns:

an object array for the record

convertRecord

public Object[] convertRecord(String rec[])

Convert a record in string array format to Object array format

Returns:

object array for the record, null if data type mismatch