6.4 Client Side Application

The class AppShell supports the implementation of the enclosing page for a client side application. Such an enclosing page typically contains a header area, some kind of menu, and a main area where the currently active component is embedded. The AppShell is designed to support an application page which contains all three elements.

It contains support for

In guidesigner 3.2.2.2 or newer, you can create an AppShell as child of the component as any other page. Then you have to choose which kind of AppShell you want to use by selecting the property Menu Type in the properties view of the page.

Both base classes are derived from the ContextAppShell. This class implements logic to show context strings of all started tasks and components in a list. The creation of the menu is done by adding MenuItems so that the actual SWT code is shielded from the developer.

In older versions of guidesigner, you had to create a DialogPage extended from an AppShell in the guidesigner to implement the enclosing page of a client side application. This was done by simply creating a DialogPage and add entries like the following to the guidesigner.properties:

application.shell=MenuShell/MenuShellPage #identifies the Component/Page serving as AppShell
AppShell=MenuAppShell #states from which kind of AppShell the Page is to extend (MenuAppShell, TreeMenuAppShell)

In your AppShell page you design the widgets for the header area, a composite for the tree menu, and a composite to hold the embedded components. The header area is typically completely implemented in this page. For the menu you can use a XMA Tree(XMA Tree)or a SWTMenu.

If you make use of a XMA Tree(XMA Tree)you derive your page class from TreeMenuAppShell which provides the binding of the abstract menu tree to the XMA TreeWM. If you want to use an SWTMenu you derive your page class from MenuAppShell .

For the client area you create a composite to hold the embedded components. You can also create a further composite holding the context information.

This page has to implement the following abstract methods to make the application page work.

AppShell - Implement Abstract Methods

This method has to return the composite, where components (i.e. Pages) are to be embedded. e.g.:

getClientComposite(){
    return clientCompW;
}

This method has to return the java.util.ResourceBundle containing the labels for all menu items. e.g.:

getMenuResource() {
    Locale locale = getComponent().getContext().getLocale();
    ResourceBundle labels = ResourceBundle.getBundle("at.spardat.demoshell.client.menu",locale);
    return labels;
}

This method has to create the root task of the application. The root task will be called immediately after the window of the AppShell is opened and takes over the job of creating the main menu (by adding MenuItem s). e.g.:

createRootTask(){
   return new MyRootTask(this);
}
You must pass the root task a reference to the AppShell. This is best done in form of a constructor parameter.

An root task example can be seen in: Root Task

ContextAppShell - Implement Abstract Methods

This method has to return the SWT-Composite where the base class can attach a list containing the context strings of all tasks and components on the call stack. This list will fill the composite completely and will be accessible via the protected member variable contextW. e.g.:

getContextComp(){
    return contextCompW;
{
If no context information should be shown than this method simply can return null .

TreeMenuAppShell - Implement Abstract Methods

This method has to return the SWT-Composite where the base class can attach a tree containing the menu items. This tree will fill the composite completely. The tree will be accessible via the protected member variable menuW. e.g.:

getMenuComp(){
    return menuCompW;
{

This method is already implemented in the MenuAppShell . In the MenuAppShell's implementation a menu of the style SWT.BAR at the Shell's top is created (the "classic" Windows menu). This method can be overwritten if some other kind of menu should be used as root menu for the MenuItems (like a pop-up menu). The SWT menu will be accessible via the protected member variable menuW. An example of a implementation with a pop-up menu as root:

protected Menu getMenu(){
     Menu menu = new Menu(aComposite,SWT.POP_UP);
     aComposite.setMenu(menu);
     return menu;
}

The life cycle of an AppShell is the same as for all pages, see (Page Life Cycle). There are only two additions:

  1. The method createRootTask() is called after createWidgets() immediately before enter().

  2. After the window of the AppShell is opened the root task is started. Thus you are given the possibility to start a search dialog on top of the main window or to do similar things.

The logical menu of an AppShell is implemented using XMA MenuItem objects. Every menu entry is represented by one MenuItem. It represents the logical entry of a menu with an attached Task as well as the underlying SWT implementation (a MenuItem in the case of a MenuAppShell and a TreeItem in the case of a TreeMenuAppShell).

An XMA MenuItem contains

  • a name which must be unique within the application.

  • an optional Task which is called every time the MenuItem is selected.

  • an optional list of MenuItems constituting the sub-menu of this MenuItem. MenuItems are added by addItem(MenuItem item)

  • an optional Image which is shown at the SWT MenuItem or at the SWT TreeItem.

  • an optional SWT style. The style should be set by using an SWT constant and specified according to the type of menu (SWT Menu or an XMA Tree(XMA Tree)) and is prolonged either to an SWT MenuItem or to an SWT TreeItem. If an SWT Menu is used then the style has to be set or the resulting menu can be have errors.

Whenever a MenuItem with an Task is selected, all tasks on the call stack which are outside the given MenuItem are closed by calling closeRequested() on them. The call stack rewinds until the task which corresponds to the given MenuItem is on top.

At least some basic menu is usually built in the root task .A code example for using MenuItems can be seen in: Root Task

When constructing an SWT menu by using the MenuAppShell and XMA MenuItems the style information has to be set in the constructor and is prolonged to the underlying SWT MenuItem. The following styles are valid for SWT MenuItems:

Note: Every XMA MenuItem which has children must be of the style SWT.CASCADE !

Otherwise a RuntimeException would be thrown. And of course it makes no sense to attach a Task to a MenuItem of the style SWT.CASCADE or SWT.SEPARATOR as this Task could never be chosen. If no style is set then the MenuItem behaves like an item with an SWT.PUSH style, but this behaviour is nether documented nor guaranteed by SWT. A programmer constructing an SWT Menu by using XMA MenuItems has not to regard that a SWT MenuItem always needs a SWT Menu as parent. The needed SWT Menus are generated by the XMA framework, so child items can be directly added to MenuItems of the style SWT.CASCADE.

Usually the style information for the XMA MenuItem can be omitted. SWT does not document any special styles for TreeItems.

The purpose of the task concept is to realize the workflow of a given business process at one place instead of scattering the flow decisions and page sequences across all involved components. This makes reuse of components in different business processes easier, as the components need no knowledge about potential successors in different workflows.

Tasks are simple Java objects which implement a workflow in a method ( run() ). They create components, set their input properties, invoke them, read their output properties, and decide which component to invoke next. The components themselves do not invoke other components. They are invoked from tasks and return the information needed for flow decisions in their output properties.

Tasks cooperate with the AppShell(Application Shell)and MenuItems(Menu (AppShell)). Tasks can embed components in the AppShell(Application Shell). This can be done blocking or nonblocking. Blocking means the task waits until the component is finished and continues then. Nonblocking means the task continues immediately. Of course, the components can be invoked as dialogs, too.

A Task may be associated with a MenuItem. Every MenuItem may contain a Task, which is called whenever the MenuItem is selected.


The active Tasks of a client side application form a stack. The currently running Task is on top of this stack. Its page or component is embedded in the application shell. The components of the other tasks are not visible.

To implement a Task you create a class derived from Task . You have to implement the abstract method run(). This method is called when the Task is called. It can be invoked more than once on the same instance. After this method is completed, control returns to the caller.

The protected member field app contains the application shell this task is running in. The protected member field menu contains the parent MenuItem of the Task.

A Task may include its own menu. These own MenuItems are attached to the MenuItem it belongs to in his run() method.

For every entry of the menu of the Task: Create the subtask which should be called whenever its MenuItem is selected. Set its input properties. Create the MenuItem and pass it its menuId and the subtask. Add this new MenuItem to the parent MenuItem of the Task.

    MySubTask subtask = new MySubTask(getComponent());
    subtask.setIdClient(idClient);
    menu.addItem(new MenuItem("MySubTask", subtask));    

These MenueItems are automatically removed when the Task is closed by calling closeRequested(). If you call setCleanSubmenu(false) on the Task before, the MenueItems are not removed automatically.

With callBlocking() you can embed a component in a modal mode. It disables the menu of the application page and blocks it until the embedded component is finished. Then the menu is enabled again.

    EmbeddableComponent comp = (EmbeddableComponent) getComponent().getSession().getComponent("MySubTask");
    comp.setIdClient(idClient);
    callBlocking(comp);    
With callNonBlocking() you can embed a component. It does not disable anything and returns immediately after the component is embedded.
    EmbeddableComponent comp = (EmbeddableComponent) getComponent().getSession().getComponent("MySubTask");
    comp.setIdClient(idClient);
    callNonBlocking(comp);
To start a component as dialog you can use its invoke() method. Do not forget to dispose the component after using it.
    EmbeddableComponent comp = (EmbeddableComponent) getComponent().getSession().getComponent("MySubTask");
    comp.setIdClient(idClient);
    comp.invoke(app.getShell);
    comp.dispose();

A Task can call another Task as subtask. This enables modularisation and eases reuse.

To call a subtask you instantiate it and start it with the method call(). This puts the subtask on top of the task stack and calls its run() method.

    MySubTask subtask = new MySubTask(getComponent());
    subtask.setIdClient(idClient);
    call(subtask);

For passing information to tasks you can implement properties on them. Simply add some get- and set-methods to your task implementation.

If you want to call a task, you have to use the method call() of the Task on top of the call stack. You get this Task by calling getTopTask() on the application shell. If you call from a page embedded directly or indirectly in the main application page you get the application shell by calling getDialog(). If you call from a page invoked as dialog, you have to maintain a variable pointing to the application shell yourself.

    MySubTask subtask = new MySubTask(getComponent());
    subtask.setIdClient(idClient);
    ((IAppShell)getDialog()).getTopTask().call(subtask);

After a task object is created, it is not fully initialized. It depends on which constructor was used, which protected member variables are defined, and which are undefined.

When the task is started, it is attached to its parent task and therefore to the task stack of the AppShell. Now all of its member variables get fully initialized, it enters its active state and its run() -method is called at last.

The task stays active and attached to its parent task and the task stack until its method closeRequested() is called. In this method it removes the component or page it embeds in the AppShell and detaches from its parent task and the task stack. It becomes inactive and most of its member variables become null.

closeRequested() is called automatically from the runtime when another menu item is selected. If the task only uses callBlocking() you should call closeRequested() at the end of your run() -method to close the task.

An AppShell s Root Task is a Task returned by the AppShell's method createRootTask(). Usually the implementation of this method contains only of: return new MyRootTask(this).

In the Root Task's run() -method is the code that builds the menu - by using XMA MenuItems - and attaches Tasks to items. An example:

    public void run() {

        menu.addItem(new MenuItem("search",new Task(getComponent()) {
            public void run() {
                IComponentClient comp = getComponent().getSession().getComponentExtern("http://localhost:8080/xma_samplespar/Kundensuche");
                callBlocking((IXMAControl)comp);
            }
        }));

        MenuItem sparen = new MenuItem("sparen",SWT.CASCADE);
        menu.addItem(sparen);

        sparen.addItem(new MenuItem("sparen_search",new Task(getComponent(),SWT.PUSH,someImage) {
            public void run() {
                IComponentClient comp = getComponent().getSession().getComponent("SparenSearch");
                callNonBlocking((IXMAControl)comp);
            }
        }));

        sparen.addItem(new MenuItem("sparen_umsatz",new Task(getComponent(),SWT.PUSH) {
            public void run() {
                IComponentClient comp = getComponent().getSession().getComponent("SparenUmsatz");
                callBlocking((IXMAControl)comp);
            }
        }));
    }

There is no special toolbar support in XMA. You cannot define a toolbar in guidesigner. But you can use the SWT classes ToolBar and ToolItem in your code. In guidesigner you can use a composite as placeholder at the position in the page where you want to place your toolbar.

In your code, overwrite createWidgets() to add the toolbar to the widgets of your page. You have to call super first, to create all the widgets defined in guidesigner. A ResourceBundle will be needed to externalize your texts into a property file for internationalization. The composite you created in guidesigner as placeholder will be used as parent of the composite. If you give no layout information, the toolbar will be placed top left into this composite.

Example:

    ToolBar toolBar;
    ToolItem itemOpen;
    ...

    protected void createWidgets() {
        super.createWidgets();

        Locale locale = getComponent().getContext().getLocale();
        ResourceBundle messages = ResourceBundle.getBundle("at.spardat.zz.example.client.Messages",locale);

        toolBar = new ToolBar(toolbarCompW, SWT.FLAT | SWT.RIGHT | SWT.WRAP );

        // create item
        itemOpen = new ToolItem(toolBar, SWT.PUSH);
        itemOpen.setImage(getComponent().getImage("at/spardat/zz/example/client/Open.gif"));
        itemOpen.setText(messages.getString("open"));
        itemOpen.setToolTipText(messages.getString("openTooltip"));

        // define event method
        itemOpen.addSelectionListener(new XMASelectionAdapter(this){
            public void widgetSelectedImpl(SelectionEvent event) {
                // place your code here
            }
        });

        // create next item
        ...
     } 

It is important to use an XMASelectionAdapter as listener, because it disables the creation of SWT events by XMA during your event handling code (see SWT Event-Handler). Additionally it adds exception handling code.

In XMA the use of SWT menus (Windows menus) is supported by the usage of a MenuAppShell. In this case the programmer has only to build the logical menu and has not to deal with the SWT implementation. See Application Shell for details.

There might be cases where the use of a MenuAppShell is not suitable and the menu is to be build directly by SWT means (this would be typical for context menus). In this case the approach is similar to building a ToolBar at your application (see Toolbar).

In your code, overwrite createWidgets() to add the menu to your page. You have to call super first, to create all the widgets defined in guidesigner. A ResourceBundle will be needed to externalize your texts into a property file for internationalization. For building an SWT menu you have to deal with the classes Menu and MenuItem. Usually you will create a Menu with several MenuItems as children on which listeners are registered. If you want to cascade further, you have to add an MenuItem of the style SWT.CASCADE. On this a Menu with further MenuItems can be added (for possible MenuItem styles see Building an SWT Menu or the SWT documentation).

Example:

    Menu rootMenu;
    MenuItem itemOpen;

    ...

    protected void createWidgets() {
        super.createWidgets();

        Locale locale = getComponent().getContext().getLocale();
        ResourceBundle messages = ResourceBundle.getBundle("at.spardat.zz.example.client.Messages",locale);

        //create a classic windows menu (at the shell's menubar)
        rootMenu = new Menu(getShell(),SWT.BAR);
        getShell().setMenuBar(rootMenu);

        //create a context menu
        rootMenu = new Menu(aControl,SWT.POP_UP);
        aControl.setMenu(rootMenu);

        // create a menu item
        itemOpen = new MenuItem(rootMenu, SWT.PUSH);
        itemOpen.setImage(getComponent().getImage("at/spardat/zz/example/client/Open.gif"));
        itemOpen.setText(messages.getString("open"));

        // define event method
        itemOpen.addSelectionListener(new XMASelectionAdapter(this){
            public void widgetSelectedImpl(SelectionEvent event) {
                // place your code here
            }
        });

        // create next item
        ...
     } 

It is important to use an XMASelectionAdapter as listener, because it disables the creation of SWT events by XMA during your event handling code (see SWT Event-Handler). Additionally it adds exception handling code.

In XMA it is possible to use Components from different server side applications in one client side application.

The use of a Component of a different application is quite easy. For creating the component, you use XMA_SessionClient.getComponentExtern() which takes the absolute URL of the desired component as parameter. This component can be used just like any component of the own server side application. It can be called as dialog (Calling a Component ) or embedded (Calling Components and Embedding the Component).

The main difference in using such a component of an other server side application is, that its interface class is not in your classloader. You can not use the getters and setters of its properties. You have to use the string representation of its properties instead. You use ComponentClient.getProperty() and ComponentClient.setProperty() instead. See Old Style Component Properties and String Representations of Properties for more information.

When creating the first component of an other server side application, a new session is created for this application. Depending on the used login plugin, this may cause the need of a new login for the user. If you are using the alpha plugin, on CS2000 workstations the single sign on features of the client side Alfa installation are used and the user is logged in automatically to the second server side application. When disposing the last component of the other server side application, its session is terminated.

On client side, each XMA-Session is running in its own classloader. The components of each server side application together with all other jar-files it downloads including the xmaruntime.jar are loaded by the classloader of its session. Therefore different applications can use different versions of XMA runtime and other libraries without problems.


Since XMA Bootruntime 1.7.0 on client side three classloaders are used.

In the system classloader are the classes of the Java runtime, of the XMA bootruntime and of the libraries it needs.

In the SWT classloader are the classes of SWT and of xmacom.jar which contains an extension to SWT COM implementation and the interfaces IComponent, IDialog and IXMAControl which are dependent on SWT.

In the session classloader are the classes of the XMA application, of XMA runtimeclient.jar and all other resources which are downloaded with the application. The only exception to this rule are the SWT classes which are always loaded in the SWT classloader even if they are downloaded with the application. (SWT-Description)

In most cases there is exactly one session classloader per JVM instance. Only if components of different server side applications are integrated in one client side application, there is one session classloader per server side application.


In XMA Bootruntime versions before 1.7.0, there was no special SWT classloader. The SWT classes have bean loaded into the system classloader together with the XMA bootruntime. The session classloader already worked exactly like now.