Embedding Pages into a Workplace

In the First Steps, you learned already how to build pages that are generated by the Layout Painter. This part explains how to integrate Application Designer pages into workplace/portal environments. There are different scenarios that are described here:

  • Usage of the Application Designer workplace framework that lets you design and implement individual workplaces for your application.

  • Integrating Application Designer pages into various portal scenarios by opening them with a URL.

  • Writing a workplace framework on your own - i.e. use Application Designer in order to build your workplace, but not on base of the Application Designer workplace framework.

The information provided in this part is organized under the following headings:


Integration into Other Workplace/Portal Scenarios

In many cases, you want to run Application Designer pages inside your own environments that are outside of Application Designer.

The requirements of other workplace/portal environments are:

  • Pages must be accessible by URLs.

  • There must be a possibility to pass information to pages. For example, user management is provided by a portal management. The result (the name of the user who is currently logged in) should be passed to applications for further processing.

To call Application Designer pages with a URL: normally each single Application Designer page can be called individually with a corresponding URL. "Normally" means that this is true from the Application Designer perspective - maybe it is not completely true from your application’s perspective: one page requires a certain page to be run first, etc.

To call an Application Designer page, simply use the following URL:

http://<host>:<port>/cis/StartCISPage?PAGEURL=<pageURL>

Replace the <pageURL> with the URL of the wanted Application Designer page and it will be opened.

For information on additional parameters that you can pass via the StartCISPage servlet, see Appendix E - StartCISPage Servlet .

Passing Parameters to your Application Designer Page

You can append any number of parameters to the URL mentioned in the previous section. Each parameter consists of the sequence "&<paramName>=<paramValue>". If you want to pass the customerId to a "customer detail" page, the URL would look like:

http://<host>:<port>/cis/StartCISPage?PAGEURL=/appxyz/customerdetail.html&customerId=4711

Each parameter is bound to a corresponding property of the page adapter. For example, the "customer detail" page is hooked on the adapter CustomerDetailAdapter. Therefore, it must provide a corresponding customerId property to which the parameter is passed at runtime:

public class CustomerDetailAdapter extends Adapter	
{	
    ...
    public void setCustomerId(String value)	
    {
        ...
    }	
    ...
}

Extended Functions in the Application Designer Workplace

The previous section covered the "normal usage mode" of the Application Designer workplace. But there are extended functions allowing you to more interactively operate with the Application Designer workplace.

These functions include:

  • Drag-and-drop interface: you can drag and drop icons within the hierarchy of the workplace. You can drop information that was dragged from any content page into the workplace.

  • Right mouse button interface on workplace nodes.

These functions allow the users to arrange their workplace settings (e.g. functions that are part of their workplace) in a simple way on their own.

This section covers the following topics:

Interface IMFWorkplaceEventListener

The base of the extended functions is the interface com.softwareag.cis.workplace.IMFWorkplaceEventListener. The interface contains methods that are called on certain events. The most important methods are:

  • reactOnContextMenuRequest
    This method is called when a user presses the right mouse button on a tree node of the workplace. Your implementation can build up a context menu - just as normal context menus are built up inside the tree management.

  • reactOnDrop
    This method is called when the user performes a drag-and-drop operation inside the workplace. Your implementation may copy the dragged nodes below the dropped node or may open a pop-up menu in which the user is asked about what to do with the dragged items.

  • reactOnDropGeneric
    This method is called when the user performes a drag-and-drop operation from any DROPICON control that is part of content pages.

The implementation of the interface is completely "yours". Use the workplace interface you got to know in the previous section to manipulate the workplace, e.g. to access the currently shown tree and to manipulate it.

An instance of the workplace event handler is passed by calling the method registerMFWorkplaceEventListener inside the MFWorkplaceInfo class:

MFWorkplaceInfo workplaceInfo = new MFWorkplaceInfo("/HTMLBasedGUI/empty.html",
                                             "../softwareag/styles/CIS_DEFAULT.css");        
workplaceInfo.setSynchTabNavigation(true);
workplaceInfo.registerMFWorkplaceEventListener(new XYZ(...));        

See the Java API documentation for detailed information.

Example

Among other features, the Application Designer demo workplace framework provides the following:

  • Right mouse button click on a workplace menu item (copy, cut, paste, etc.).

  • Drag-and-drop within the workplace menu (to move menu items).

Have a look at the event listener source coding. You can find it in your installation at:

<installdir>/cis/cisdemos/src/com/softwareag/cis/demoworkplace/CISDemoWorkplaceEventListener

Building Own Workplaces as a Frameset Definition

A set of functions is available which simplify the usage of Application Designer HTML pages inside a given HTML frameset definition. The functions are not only usable in the scope of workplace/portal management, but can also be used apart from this.

This section covers the following topics:

Basics

The basic functions cover the following aspects:

  • You can define an HTML page containing any kind of frameset you want. In this page, you design the frames, their sizes, their scroll behavior, their behavior when resizing the screen, etc. For each frame which which you want to interact, you define an identifier name.

  • You open Application Designer pages inside the frames. There are two possibilities:

    1. Open these pages with a URL as described in the previous section.

    2. Open these pages with adapter methods (server-side processing).

This section will focus on the second possibility since the first is just a certain usage of what is described in the previous section. This offers you an explicit control about what happens inside the frames: e.g. a page within frame "A" should be replaced by another page. Before proceeding, the user should be asked whether to store unsaved data (or not).

It is possible to communicate with frames on the client side. This means, you can build up interaction (e.g. you want to update another frame’s content) without any flickering in the target frame.

Defining the Frameset

In the following screen, a page is shown which is divided into three frames:

graphics/image174.png

The corresponding frameset definition of the page is:

<html>

<head>
<title>New Page 2</title>
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
</head>

  <frameset cols="200,*">
    <frameset rows="*,*">
      <frame name="lefttop" src="/cis/servlet/StartCISPage?PAGEURL=/cisdemos/frameleft.html">
      <frame name="leftbottom" src="blank.html">
    </frameset>
    <frame name="right" src="blank.html">
  </frameset>

</html>

The frameset contains three frames with the IDs lefttop, leftbottom and right. The lefttop frame opens the Application Designer page /cisdemos/frameleft.html. This page contains buttons for some functions and acts like a "menu page".

Simple Way of Opening Pages in Frames

When choosing the Customer Orders button, the corresponding Application Designer page is opened in the leftbottom frame:

graphics/image175.png

The page shows a list of customer orders. It is a normal Application Designer page. How can it be opened by choosing the Customer Orders button?

The /cisdemos/frameleft.html page (acting as a "menu page") is hooked on to a Java adapter class which looks as follows:

import com.softwareag.cis.server.Adapter;

// This class is a generated one.

public class FrameLeftAdapter
    extends Adapter
{
    /** */
    public void onArticleMaster()
    {
        // TODO Auto-generated method stub
    }

    /** */
    public void onCustomerMaster()
    {
        // TODO Auto-generated method stub
    }

    /** */
    public void onCustomerOrders()
    {
        this.openCISPageInTarget("OpenCustomerOrders.html", "leftbottom");
    }
}

By choosing the Customer Orders button, the method onCustomerOrders is called. This method performs a method openCISPageInTarget inherited from class Adapter. The first parameter of the method is the page that is to be opened; the second parameter defines the ID of the frame in which the page is to be opened.

The page OpenCustomerOrders.html, which is opened when choosing the Customer Orders button, is running inside the same subsession as the page from which it was called. If you need to access the page adapter before opening the page inside the "leftbottom" frame, use the findAdapter method inside your adapter.

A More Complex Way of Opening Pages in Frames

When selecting an order in the leftbottom area of the previous example, a customer order page is displayed in the right frame:

graphics/image176.png

The data from the order you selected is transferred into the corresponding fields of the customer order page. Have a closer look at the details.

This is the source of the adapter for listing customer orders:

import java.util.Iterator;

import com.softwareag.cis.server.Adapter;
import com.softwareag.cis.server.IInteractionSessionMgr;
import com.softwareag.cis.server.InteractionSessionMgrFactory;
import com.softwareag.cis.server.util.SelectableLine;
import com.softwareag.cis.server.util.TEXTGRIDCollection;
import com.softwareag.cis.util.CDate;

public class OpenCustomerOrdersAdapter
    extends Adapter
{
    // ------------------------------------------------------------------------
    // inner classes
    // ------------------------------------------------------------------------

    public class Order
        extends SelectableLine
    {
        public Order(String number, String date, String customer)
        {
            m_customer = customer;
            m_date = new CDate(date);
            m_number = number;
        }

        // property >orders[*].customer<
        String m_customer;
        public String getCustomer() { return m_customer; }
        public void setCustomer(String value) { m_customer = value; }

        // property >orders[*].date<
        CDate m_date;
        public CDate getDate() { return m_date; }
        public void setDate(CDate value) { m_date = value; }

        // property >orders[*].number<
        String m_number;
        public String getNumber() { return m_number; }
        public void setNumber(String value) { m_number = value; }
    }

    // ------------------------------------------------------------------------
    // property access
    // ------------------------------------------------------------------------

    // property >orders<
    TEXTGRIDCollection m_orders = new TEXTGRIDCollection();
    public TEXTGRIDCollection getOrders() { return m_orders; }

    // ------------------------------------------------------------------------
    // public adapter methods
    // ------------------------------------------------------------------------

    public void onOrderSelect()
    {
        // find the selected item
        Order selectedOrder = null;
        Iterator iter = m_orders.iterator();
        while (iter.hasNext())
        {
            selectedOrder = (Order)iter.next();
            if (selectedOrder.getSelected() == true)
                break;
            else
                selectedOrder = null;
        }
        if (selectedOrder == null)
            return;
        // session management: "refresh" subsession
        String sessionId = this.m_interactionProcess.getSessionId();
        IInteractionSessionMgr iism = InteractionSessionMgrFactory.getInteractionSessionMgr();
        iism.removeSubsession(sessionId,"subsession_right");
        iism.createNewSubsession(sessionId,"subsession_right");
        // prefetch and manipulate adapter inside the refreshed subsession
        CustomerOrderDetailAdapter coda = (CustomerOrderDetailAdapter)iism.findAdapterInSubsession
            (sessionId, // sessionID
             "subsession_right", // subsessionId
             CustomerOrderDetailAdapter.class.getName(), // class
             "", // pageId, typically ""
             findPageApplication()); // application project
        coda.setNumber(selectedOrder.getNumber());
        coda.setName(selectedOrder.getCustomer());
        // navigate to page
        openCISPageInTarget("CustomerOrderDetail.html","subsession_right","right");
    }

    // ------------------------------------------------------------------------
    // standard adapter methods
    // ------------------------------------------------------------------------

    // property >messageType< implemented in Adapter
    // property >messageShortText< implemented in Adapter
    // property >messageLongText< implemented in Adapter

    /** initialisation - called when creating this instance*/
    public void init()
    {
        m_orders.add(new Order("4711","20020706","Software AG"));
        m_orders.add(new Order("4734","20020702","Banana Import Export Ltd."));
        m_orders.add(new Order("4798","20020604","Johnsons's Bread"));
    }
}

With method onOrderSelect, the selected line is determined first.

In the next steps, frame communication is prepared and finally done. The difference to the previous "simple" scenario is that the page which is opened runs in a different subsession inside the session management of Application Designer.

Remember that each browser instance internally requests one session, and that each session is divided into various subsessions. Adapters are running inside subsessions. The subsession is responsible for keeping and releasing resources. It corresponds to one interaction process which has a defined life cycle - e.g. the data input of a customer order. For more information, see the section Session Management. Each subsession has an identifier - in this example, the name of the subsession is subsession_right. You can also create a unique ID with the class com.softwareag.cis.util.UniqueIdMgmt.

Our example program first removes the subsession subsession_right. Everything which is currently managed inside the subsession will be released. Since there is no subsession when being called the first time, no error will occur.

After releasing this subsession, a new subsession is immediately created. With the interaction session manager, you can access a method which passes back an adapter instance inside a given subsession. Like the method findAdapter of class Adapter, this method returns an adapter object which is managed inside the same subsession in which the adapter is running. With the interaction session manager, you can also access adapters inside different subsessions.

The returned adapter instance gets the selected data. Finally, the frame communication takes place: pay attention that the ID of the subsession has to be passed inside the openCISPageInTarget method.

When to Use the Complex Way

The complex way should be your "standard thinking" in this scenario. When dealing with Application Designer pages inside different frames, you have to take care about how you manage your sessions at the server side.

The content which runs inside the frames (e.g. the Customer Order screen) is not aware of these session management dependencies. But the designer of the workplace has to take care of the interaction possibilities inside the workplace.

Opening Normal HTML Pages inside Frames

In addition to the methods openCISPageInTarget, there is an equivalent method openPageInTarget which you inherit from the Adapter class. This page opens a normal HTML page inside one frame.

Frame Communication

When working with frames, it is possible to open a client-side communication channel between frames: by the client, you call an adapter method of an Application Designer page which is opened in a different frame. This is done by the method invokeMethodInTarget(methodName,targetName) which you inherit from the com.softwareag.cis.server.Adapter class.

Frame communication

This sounds strange at first: in the adapter processing of frame LEFT, you call an adapter method of frame RIGHT and the call is executed by the client - what is the reason for this? The advantage of calling the method by the client is that the call is initiated by the page which runs inside the target frame. This means that the target frame sends the request for method execution and updates its content as a reaction of the request’s response. In other words: you can update pages in other frames without redrawing the page, i.e. without flickering.

This is a very powerful way of allowing communication between frames - but there are some restrictions which you have to keep in mind:

  • The frame which initiates the interaction as well as the target frame must be in the same frameset page - in other words: they must share the same "document parent".

  • The page shown in the target frame must be received by the same server and port as the page which initiates the communication. Otherwise, you will receive a JavaScript security exception - it is (by default) not allowed to establish a client communication between pages coming from different hosts.

The frame communication framework acts upon error situations in a quite tolerant way:

  • If you invoke a method inside a frame target and the frame does not exist, nothing will be done on the client side.

  • If you invoke a method inside a frame target and there is no valid Application Designer page inside the frame, nothing will be done.

  • If you invoke a method inside a frame target and the corresponding "target adapter" does not provide the requested method, the content of the frame target’s page will be synchronized with its adapter. This is similar to defining a BUTTON control and specifying a method which does not exist inside the adapter.

Tip:
Only use frame communication if you want to update the content of another frame page. Do not use this method for "normal" interaction between adapters, without any changes on the page.

Multiple Frame Operations

You can call the methods openCISPageInTarget, openPageInTarget and invokeMethodInTarget multiple times inside one request, for example, if there are multiple frames you want to manipulate at the same time.

When Building your Own Workplaces

As you learned in this section, Application Designer provides powerful mechanisms to build flexible workplace/portal scenarios. Be aware that workplace management means more than bringing up some pages into different frames. Workplace management also means, for example, that you take care of opening and closing the session state (in Application Designer: subsession state) and that you have to provide global data (like the currently logged in user) shared by all adapters, etc.