PageBox for Java: Web application deployment using Java PageBox

for
 PageBox for Java 
 API 
 Demo 
 Background 
Presentation Download User guide Implementation Epimetheus euroLCC Prometheus

Prometheus

Objective

This document explains how to use the Prometheus Web archive and presents the Prometheus implementation.

Assumptions

In this document we assume that you have installed:

Principle

Prometheus 0.0.2 is an example that illustrates the use of the Token API and of Active Naming in PageBox.

Token API

Function

This part of Prometheus is a simple chat application.

The user enters a pseudo and a set of metadata to enter a chat session. Then she can see messages from others and send messages to the other participants to the session. The key difference with a traditional chat system is that participants are distributed across multiple server sides. A distributed Prometheus constellation should be able to handle an unlimited number of participants. Because the number of participants can be huge Prometheus allows sending messages to subsets of the participant population.

Protocol

A Prometheus instance stores the names and metadata of its registered participants in a user map.

When a participant sends a new message the Prometheus instance checks the message destination.

If the message targets one or many participants in other Prometheus instances Prometheus stores the message in a foreignMessages map. Otherwise the Prometheus instance adds the message to a received map.

When it is notified about the arrival of the token frame the Prometheus instance adds the following items to the frame using the send method:

Active Naming

This part of Prometheus is a simple illustration of Active Naming. It is independent of the Token API part.

On an entries form the user creates entries with a name, a must parameter that requestors must match, a niceif parameter to which requestors must be as close as possible and a URL.

A JSP provided as a target page for routing displays the entry name, the must and the niceif parameters and a parm parameter of the query string.

A routing page allows setting requested entry name, must and niceif parameters and uses Active Naming to redirect to a page that can be the JSP page.

This example is enough to test and illustrate Active Naming. However in a real application the entry name would probably be hard-coded and the must and niceif parameters would be fields or data meaningful for the application. Furthermore Active Naming is flexible: the URL can include a query string. The application can generate entry names on the fly and doesn’t have to setup the must or niceif parameter.

Setting

To test Prometheus you need:

  1. To setup a PageBox

  2. To subscribe the PageBox to the Repository

  3. To publish the Prometheus archive on a Repository

See the PageBox installation guide to setup the PageBox.

Subscription

To subscribe your PageBox to the Repository follow the following steps:

  1. Go on the subscribe form of the Repository

  2. Logon with the subscriber account defined in the PageBox’s rules.xml

  3. Enter the URL of the PageBox’s deploy Web service, the user ID and password of your PageBox and click on the subscribe button

Publication

To publish Prometheus on the Repository:

  1. Go on the publish page of the Repository and log on with a Publisher account

  2. Click on the Browse button and select the prometheus.war archive. Then enter the documentation URL if you want and check the "Run application server installer" checkbox.

Use

Token API

Start your browser.

Let’s assume that you configured your PageBox with this rule.xml file:

<rules>

<repositories>

<repository>

<subscriber>

<name>subscriber</name>

<password>subscriber</password>

</subscriber>

<name>https://localhost:8443/Repository/repoquery</name>

<allow>copy</allow>

<deployer-class>PageBoxLib.JWSDPDeployer</deployer-class>

<querier-class>PageBoxLib.JWSDPQuerier</querier-class>

<publishers>

<publisher>

<name>publisher</name>

<allow>install</allow>

</publisher>

</publishers>

</repository>

<default>

<allow>none</allow>

</default>

</repositories>

<target>PageBox\deployed</target>

<root-path>/pb1</root-path>

<dbcreate>C:\deployed\dbcreate.bat</dbcreate>

<dbdrop>C:\deployed\dbdrop.bat</dbdrop>

<driver>com.mysql.jdbc.Driver</driver>

<url>jdbc:mysql://localhost/</url>

<user>pageboxa</user>

<password>pagebox</password>

</rules>

Prometheus will be installed in PageBox\deployed on the file system and under /pb1 on the Application server. Assuming that the Application server runs locally and is configured to listen on port 8443 (SSL) you can display the login form of Prometheus with https://localhost:8443/pb1/prometheus/login. You should get this:

Enter:

Click on the Login button to log in. Once you are logged in you may click on the Message link to send messages and display messages of others.

The Login form contains two other buttons:

The Message form looks like that:

On the top right the user name is displayed.

The form contains two parts. The top part displays the received messages. The bottom part allows sending messages.

The user drop-down list displays logged-in users. If a user is logged on the same PageBox the user string is user_name@local. If a user is logged on another PageBox the user string is user_name@PageBox_url where PageBox_url is the URL of the DeployIF Web service of the PageBox where the user is logged in.

The PageBox drop-down list displays the DeployIF Web service’s URL of the PageBox where users are connected.

To send a message put the message text in the text area. To send a broadcast message, just click on the Send button. To send a message to all users on a PageBox, select the PageBox on the PageBox drop-down list and click on the send button. To send a message to a user, select the user on the user drop-down list and click on the send button. You can also send a message to all users that match a criterion that you enter on the filter area. This filter can be loc/user_location or sub/user_area_of_interest where user_location is the location entered by the user on the Login form and user_area_of_interest is an area of interest entered by the user on the Login form. You can also send a message to all users of a PageBox that match a criterion. In this case select the PageBox on the PageBox drop-down list and enter a filter string.

Active Naming

Assuming the same setting as with the Token API you can declare a service instance on this page:

In this case two services instances are already declared. The name is the logical name of the entry. On a Prometheus instance an entry is served by only one service instance but many Prometheus instance can declare the same entry point. For a given entry point routing and load balancing take place between the service instances declared with this entry point. The must is the first parameter used for routing. This instance can only be selected if the request has a must parameter with the same value. The niceif is the second parameter used for routing. This instance has more chances to be selected if the request has a niceif parameter close to this instance.

Let’s take the case of entry1. Let’s assume that another Prometheus instance declared entry1 with niceif=mmmmm and a third instance declared entry1 with niceif=zzzzz. If the request has a niceif that equals aaaba, the first instance is the closest. Therefore it has more chances to be chosen. The second instance has fewer chances to be chosen and the third one even fewer chances because it has the farthest niceif.

The last URL is the service instance URL. We declared here the URL of redirect.jsp on this Prometheus instance with a query string parm=entry1 in case of entry1 because redirect.jsp displays parm.

We can do the same kind of declaration on other Prometheus instances installed from the same repository.

Then we can display the routing page on any Prometheus instance installed from the same repository:

On this form we are displayed a drop-down list where all entry points declared on the constellation for the Prometheus Web archive are displayed. We select one of these entry points and we enter the must and the niceif parameters of the request.

When we click on the send button we are redirected on the target URL, redirected.jsp in our case, which displays:

Implementation

Design choices

Prometheus is made of the following components:

Name

Function

Install.java

Installation class. Updates the prometheus web.xml.

login.jsp

Displays a form where the user enters or display her pseudo, location and areas of interest (login view)

prometheus/LoginCtrl.java

Handles login requests (controller servlet)

prometheus/LoginBean.java

Stores the user pseudo, location and areas of interest (model)

prometheus.jsp

Displays a form where the user displays messages and can submit new messages (message view)

prometheus/PrometheusCtrl.java

Handles message sending (controller servlet)

prometheus/PrometheusBean.java

Returns PageBox instances in the constellation, users and messages from PrometheusCallback

prometheus/PrometheusCallback.java

Implements the Token API, receives and send messages.

prometheus/Message.java

Contains the actual message.

prometheus/UserInfo.java

Describes a user.

prometheus/UserManager.java

Used to remove users whose session was invalidated

entries.jsp

Displays a form where the user declares service instances

prometheus/EntriesCtrl.java

Handles service instance declarations

prometheus/EntriesBean.java

Store service instance data and uses Active Naming

routing.jsp

Displays a routing page where the user enters an entry name and the must and niceif parameters

prometheus/RoutingCtrl.java

Handles routing requests and returns a redirect page when applicable. Uses EntriesBean as model.

prometheus/Entry.java

Describes a service instance

prometheus/NiceIf.java

Wrapper for a niceif string that implements the ActiveComparable interface

redirected.jsp

Example of target page

Install

Install.java is a stripped-down version of the generic installation demonstrated in euroLCC that onlyreplaces the first <!--Install_wordir--> place holder in web.xml by the installation directory of the archive.

LoginCtrl

LoginCtrl implements three methods:

LoginBean

LoginBean contains four member variables:

LoginBean implements the HttpSessionBindingListener interface. Because LoginCtrl binds LoginBean instances to sessions (with the HttpSession.setAttribute method) the LoginBean’s valueUnbound method is called when the session is invalidated either thank to user action (unlog button) or because the session has expired. valueUnbound calls the removeUser method of PrometheusCallback.

PrometheusCtrl

PrometheusCtrl implements three methods:

PrometheusBean

PrometheusBean implements three methods of interest:

PrometheusCallback

PrometheusCallback implements the TokenCallbackIF and HttpSessionListener interfaces.

PrometheusCallback also implements methods called by LoginCtrl:

PrometheusCallback also implements methods called by LoginCtrl:

PrometheusCallback has five member objects of interest:

A user in users and foreignUsers is represented by a UserInfo object. The UserInfo class is defined like this:

class UserInfo implements Serializable {

String location = null;

String[] aoi = null;

}

Where

Message is defined like this:

class Message implements Serializable {

String user = null;

String timestamp = null;

String from = null;

String msg = null;

}

Where

setSender

The setSender of TokenCallbackIF is called when Prometheus calls the registerCallback method of the PageBox API to insert into the ring. setSender stores the sender object in the sender member variable.

call

The call method of TokenCallbackIF is called when the PageBox receives a frame. This frame may contain:

When it is called with type = "prometheus" call adds the message to the received map.

When it is called with type = "user" calls adds the user map of the foreign Prometheus instance to the foreignUsers map.

Then call adds a message of "prometheus" type to the frame (with the sender.send method) for every entry found in the messages map.

Eventually call adds a message of "users" type to the frame (with the sender.send method) for its users map.

addUser

addUser adds a user to the users map except if this user name is "all", which is the broadcast user or the user name starts with "!", which is used for filters.

removeUser

removeUser removes a user from the users map except if this user name is "all", which is the broadcast user or the user name starts with "!", which is used for filters.

send

There are three flavors of the send method

addLocalMessage

addLocalMessage adds the message to the received map with a "local" key.

sendTo

The sendTo method sends a message to all users on a specified PageBox. If the PageBox is "local" sendTo calls the addLocalMessage method to send the message to the "all" local user. Otherwise sendTo adds the message to the message map with the designated PageBox as target and "all" as user name.

sendFiltered

The sendFiltered method sends a message to users that match a filter string on a specified PageBox. If the PageBox is "local" sendFiltered calls the addLocalMessage method to send the message to a "!" filter string local user. Otherwise sendFiltered adds the message to the message map with the designated PageBox as target and "!" filter string as user name.

getUserMessages

getUserMessages is called by PrometheusBean.getMessage to return messages of interest for a user, which are:

  1. Messages targeting this specific user

  2. Broadcast messages

  3. Messages whose filtering criteria match the user location and areas of interest


getUserMessages returns null if there is no message for this user or a TreeMap that it builds in the following way:

  1. getUserMessages enumerates the entries in the received map

  2. If the target user is this user getUserMessages adds the entry content to the returned TreeMap

  3. If the target user is "all" getUserMessages adds the entry content to the returned TreeMap

  4. If the target user is a filter (starts with "!") and if this user matches filtering criteria (matchingFilter(filter, user) returns true) getUserMessages adds the entry content to the returned TreeMap

matchingFilter

matchingFilter is called by getUserMessages to check if a message target is a filter and matches the user location and areas of interest.

matchingFilter parses the filter string and checks


Therefore matchingFilter returns true only if when the user fulfills all criteria in the filter.

UserManager

UserManager is normally redundant with the HttpSessionBindingListener implementation of LoginBean. Its attributeRemoved method is called like the valueUnbound method of LoginBean when the session is invalidated.

UserManager implements the HttpSessionAttributeListener interface to be called when an attribute is added to or removed from the session. The container calls the HttpSessionAttributeListener methods when the UserManager class is declared as a listener in web.xml:

<listener>

<listener-class>prometheus.UserManager</listener-class>

</listener>

The attributeRemoved method calls the removeUser method of PrometheusCallback.

EntriesCtrl

EntriesCtrl implements three methods:

EntriesBean

EntriesBean has the following members of interest:

The Entry class is defined like this:

class Entry {

String must;

NiceIf niceif;

	String url;

}

It contains essentially the same data as the ActiveEntry class of PageBoxLib. This map of entries is filled by addEntries and used by the getEntries method to display the service instances declared locally.

init

init creates the PageBox instance and calls its ActiveNamingLogon method.

addEntry

addEntry adds a new entry to the entries map and calls the addEntry method of the PageBoxAPI instance.

end

end is called by the destroy method of EntriesCtrl when the Prometheus application is unloaded.

end calls the clearEntries and the ActiveNamingLogoff methods of the PageBoxAPI instance.

getEntries

getEntries is called by entries.jsp to display the service instances declared locally.

getEntries enumerates the entries to return a set of HTML rows that displays the service instances.

getNames

getNames is called by routing.jsp to display a drop down list of the entry points declared in the constellation. getNames calls the getEntries method of the PageBoxAPI instance and returns the response formatted in HTML select options.

redirect

redirect is called by RoutingCtrl.doPost with a handle to the servlet output writer.

redirect calls the getCandidate method of the PageBoxAPI instance that returns the service URL.

Then redirects writes on the servlet output writer:

<html>

<body onload="javascript:document.parmSend.submit();">

<form name="parmSend" method="post" action="service URL">

<input type="hidden" name="name" value="entry logical name" />

<input type="hidden" name="must" value="must parameter" />

<input type="hidden" name="niceif" value="niceif parameter" />"

</form>

</body></html>

When this page is loaded in the browser it automatically redirects to the service page with a POST request that contains the entry logical name, the must and the niceif parameters. When the service page is redirect.jsp it displays these data.

RoutingCtrl

RoutingCtrl implements three methods:

Contact:support@pagebox.net
©2002-2004 Alexis Grandemange. Last modified .