This document explains how to use the Prometheus Web archive and presents the Prometheus implementation.
In this document we assume that you have installed:
Prometheus 0.0.2 is an example that illustrates the use of the Token API and of Active Naming in PageBox.
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.
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:
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.
To test Prometheus you need:
See the PageBox installation guide to setup the PageBox.
To subscribe your PageBox to the Repository follow the following steps:
To publish Prometheus on the Repository:
Start your browser.
Let’s assume that you configured your PageBox with this rule.xml file:
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:
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.
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:
Prometheus is made of the following components:
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 implements three methods:
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 implements three methods:
PrometheusBean implements three methods of interest:
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:
Message is defined like this:
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.
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 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 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.
There are three flavors of the send method
addLocalMessage adds the message to the received map with a "local" key.
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.
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 is called by PrometheusBean.getMessage to return messages of interest for a user, which are:
getUserMessages returns null if there is no message for this user or a TreeMap that it builds in the following way:
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 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:
The attributeRemoved method calls the removeUser method of PrometheusCallback.
EntriesCtrl implements three methods:
EntriesBean has the following members of interest:
The Entry class is defined like this:
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 creates the PageBox instance and calls its ActiveNamingLogon method.
addEntry adds a new entry to the entries map and calls the addEntry method of the PageBoxAPI instance.
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 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 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 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:
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 implements three methods: