OpenWGA 7.5 - OpenWGA Concepts and Features

Design and development » TMLScript

Registering problems

OpenWGA has a facility called "problem registry" where OpenWGA itself or designs running on it are able to register "problems" that the administrator of a system should know about. Those problems show up in admin client, on menu "Runtime" > "Registered problems":

problem-registry.png

Here an administrator can review what might be problematic on the current WGA runtime and try to fix the problem. After that he can either dismiss the problem or the problem will disappear automatically once it is fixed, depending on how it was registered.

Registering a Problem in TMLScript

Any OpenWGA design may also register problems to be displayed here using the according methods on the TMLScript Design object. The most important one being addProblem():

WGA.design().addProblem("occasionKey", "problemKey")

As you can see a problem is registered by using two keys:

  • The occasionKey is a string which should represent on what occasion the problem occured, i.e. what you actually were trying to do when it happened. Often many potential problems share the same occasion key as they can occur at the same occasion. It is up to you to define that occasion.
  • The problemKey is a string which represents the individual problem.

As you might guess both keys are not the actual messages that are shown on the problem view but just keys identifying the problem. They should be alphanumeric without whitespaces. Each unique combination of occasionKey and problemKey can only be used to register one problem.

Defining problem messages

The actual messages instead are to be defined like WebTML labels. Create a properties file "problems.properties" inside those label folders of your design whose language you want to provide the messages in. We strictly recommend to at least do this for the english language inside file container folder "files/labels_de" of your design.

There you can provide problem messages under the following label keys (which are based on the problem keys):

  • <occasionkey>.title - The title of the problem, which is just dependent on the occasion. Describes what you were trying to do and that it didn't work.
  • <occasionkey>.<problemkey>.message - The message of the problem. Describes shortly what precisely went wrong
  • <occasionkey>.<problemkey>.description -  The description of the problem. Might be a longer text describing in detail what happened and maybe the impact of the malfunction on the system.<occasionkey>.
  • <occasionkey>.<problemkey>.solution - Optional. Might provide instructions on how to solve the problem.

Problem parameters and message variables

An optional third parameter can be given to addProblem() which is a lookup table providing additional parameters to the problem. It has two purposes:

1. There are some predefined keys which can be used on the lookup table to provide specific information about the problem:
    • severity: "HIGH" | "LOW" | "INFO"
      • Denotes the severity of the problem: "info" is a mere information where no actual problem exists. "low" is a problem which has no critical impact on the app. "high" is a problem with critical impact, meaning that something quite important for the app or system does not work. If no severity is given then "low" is assumed.
    • error: <throwable>
      • Any JavaScript error or Java throwable that is connected to this problem, maybe even caused it.

2. All other keys are used as message variables for the messages, meaning that they are inserted into the messages when they are put out at predefined positions. This is quite equal to WebTML label params, but has one difference: Problem message params are named, not indexed. Therefor the insert positions in those messages are denoted by "{keyname}" instead of just a number.

There is one message variable which are always available without being defined:

  • "dbkey" - The database key of your app

An example

Imagine your app performs a Lucene fulltext query for a pretty important functionality of it. When there is no fulltext index enabled for your app it cannot do what it is built to do, so the administrator should know that something is not working the way it currently is configured.

So you could write this little script on the page which executes the query to test the lucene index and register a problem if it does not exist.

if (!WGA.app().isLuceneIndexed()) {

  WGA.design().addProblem("performQuery", "noLuceneIndex", {query: "Timeline", severity: "HIGH"});

}

We defined an occasion key "performQuery" because we were about to perform a query which will not work. We defined a problem key "noLuceneIndex" because the query fails because of a missing lucene index. Also we set the severity to "high" because we think the application will not be able to do what it should do because of this problem.

Now we can create a file "files/labels_en/problems.properties" in our design where we provide the messages for those keys:

performQuery.title=A problem occured executing a query of application "{dbkey}"

performQuery.noLuceneIndex.message=The application "{dbkey}" has no lucene fulltext index

performQuery.noLuceneIndex.description=Query "{query}" needs the Lucene index to work. Without it this function will be unavailable.

performQuery.noLuceneIndex.solution=In OpenWGA admin client open the configuration of this app and enable the Lucene fulltext index on tab "Fulltext configuration".

In these messages we use both, the predefined variable "dbkey" as well as the variable "query" which we provide on registration.

This creates a problem which needs to be manually dismissed by the administrator once it is fixed. For certain situations however you can also register problems which disappear automatically once its cause is corrected.

Registering self-clearing problems

With a slightly different approach you could register a problem which clears itself on the next occurrence of the problem occasion when the problem got fixed. For that to work you must first tell the script runtime that the problem occasion started:

var occasion = WGA.design().startProblemOccasion("occasionKey");

This will do the following:

  • It will remove all existing problems with the given occasion key that are already registered
  • It returns an "occasion" object which is to be used instead of the occasion key on all addProblem() calls for this occasion

if (problem1happened) {

  WGA.design().addProblem(occasion, "problemKey1");

}

if (problem2happened) {

  WGA.design().addProblem(occasion, "problemKey2");

}

That way each run of the occasion clears the problems of the previous run automatically. Only the problems that are still present are registered again.

Self-clearing problems should only be used for occasions that do not run "too frequent". The problem clearing process can be quite exhaustive and take a long time, so it might not be a good idea to use it on occasions that run on frequently called WebTML requests which need to have good performance. A better place for these kind of problems would be the connect script of a design, a scheduled Job or some WebTML action that is not called too frequently.

Because of this performance restriction we might want to perform the lucene test on the databases connect script and work with the self-clearing approach there. With a slight change of the key meanings we could also test for an existing index here:

var occasion = WGA.design().startProblemOccasion("testPrerequisites");

if (!WGA.app().isLuceneIndexed()) {

  WGA.design().addProblem(occasion, "noLuceneIndex", {severity: "HIGH"});

}