Integrating IBM Lotus Forms with WebSphere Portal to create a form-centric application

Let us show you how to integrate IBM Lotus Forms with IBM WebSphere Portal. As part of this integration, we show you how to create a portal application that responds to both a user request for a form and a user submission of a completed form.

Si Ri Lin (linsiri@cn.ibm.com), Software Engineer, IBM

Lin Si Ri is a Software Engineer at the IBM Shanghai Globalization Lab (SGL) located in Shanghai, China. He works on Globalization Interoperability Testing projects. He is interested in Java, J2EE, Globalization, and Open Source. You can reach him at linsiri@cn.ibm.com.



Steve Shewchuk, Information Development Manager, IBM

Steve Shewchuk is a manager with the IBM Victoria Software Lab located in Victoria, Canada. He joined IBM as part of the PureEdge acquisition and has been working with forms for more than 10 years.



19 November 2008 (First published 06 March 2007)

IBM Lotus Forms allows you to create and deliver XML forms applications. As one of its components, it provides a common, open application programming Interface (API). Using this API, you can integrate electronic forms data with server-side applications as well as access and manipulate forms as structured data types. IBM Lotus Forms also provides a component called Webform Server that delivers a true zero-footprint solution, allowing external users to view and fill electronic forms quickly and easily through a standard Web browser. Additional plugins are required only for client-side signing and printing.

In this article, we explain how to integrate IBM WebSphere Portal V6 with the API and Webform Server to create a form-centric application.

We assume that you have some knowledge of form design and Java programming, as well as portlet development on IBM WebSphere Portal.

To follow the steps outlined in this article, you require the following software:

  • IBM WebSphere Portal V6 or later
  • IBM Lotus Forms Server V3.5 or later
  • IBM Rational IDE (such as IBM Rational Software Architect or IBM Rational Application Developer)

Business scenario

To demonstrate our integration, we use a common business scenario: the process of completing and submitting a purchase order. In this scenario, you begin with an XFDL purchase order that is hosted in WebSphere Portal, so that the user can rely on the WebSphere Portal interface to access the form.

When the user logs into WebSphere Portal to create a new purchase order, we use Webform Server to translate an XFDL form into HTML and JavaScript. The form, as HTML, is then displayed in the user’s Web browser. After the user completes and submits the form, WebSphere Portal retrieves the data model from the submission and passes it to one or more processing applications (such as a workflow that routes the form).

Developing these processing applications is beyond the scope of this article. Consequently, you set up your application simply to display the form data on the screen for the user.

To create this sample scenario, follow these steps:

  1. Install Webform Server.
  2. Install and set up the API on WebSphere Portal.
  3. Design the XFDL form.
  4. Create a portlet to display the form.
  5. Create a two-pane portal page.
  6. Configure the portal application.

Installing Webform Server

When installing Webform Server, you should consider two central components:

  • The Translator. This is the component that translates forms between XFDL and HTML. It is the heart of Webform Server, and it does most of the work.
  • The Servlet/Portlet Application. This is an application that you write (either a servlet or a portlet) that serves forms. This application uses the Translator to translate those forms.

A typical installation of Webform Server is a distributed installation. This means that your form application (your servlet or portlet) is normally hosted on your application server, while the Translator is normally installed on a second server. This is necessary because both Webform Server and WebSphere Portal are resource-intensive applications. Installing them on the same server is possible, but doing so results in poor performance under any significant load.

If you want to set up a simple test environment and if you do not expect a heavy load, you can install all the components on a single server. This certainly works – it just isn’t recommended for a high-load or production environment.

For this solution, we install Webform Server in a distributed manner. To install Webform Server, follow the instructions in Installing Webform Server. Install all the Webform Server components on a dedicated server (that is, not on WebSphere Portal). This gets the Translator up and running.

After you have completed the installation, open the following link in your Web browser to be sure that Webform Server is running correctly:

http://<<Webform server name>>:8085/translator/Translate? Action=toolbelt

If Webform Server is running correctly, you see the welcome page. The Translator is now running on your dedicated server. The rest of this article focuses on creating the portlet application that you need to call the Translator. Once you have developed that portlet, you install it on your WebSphere Portal and configure it to call the Translator on the dedicated server.


Installing and setting up the API on WebSphere Portal

You need to install the API on WebSphere Portal so that your application can use functions from the API to process the form. Experience has shown, though, that this setup is the single biggest problem that users encounter when creating a WebSphere Portal application. It’s not that the process for setting up the API is particularly difficult – it’s not. The problem is simply that there are many steps to follow and that those steps are somewhat error prone.

Keep this in mind as you follow the steps we outline in this section. Make sure you follow the steps carefully, and double-check each step as you go.

The steps for setting up the API are outlined in Installing Lotus Forms - API, but we repeat them here because this is a problem area. In our installation, we work with a Linux platform. If you need to install on another platform, refer to the product documentation.

To set up the API to work with WebSphere Portal, perform the following steps:

  1. Log in as root and run the installer LFServer_35_API_Linux.bin to install the API on your computer.
  2. Copy the redistributable files to the /usr/lib directory:
    cp –r –p <API Installation Folder>/redist/Linux/* /usr/lib

    NOTE: Replace <<API Installation Folder>> with the root installation directory for the API. By default, this is: /opt/IBM/Lotus Forms/Server/3.5/API directory.
  3. Modify the files so that other users can access them:
    chmod -R a+r+x /usr/lib/PureEdge
    chmod a+r /usr/lib/libpe_cc.so /usr/lib/libpe_java.so /usr/lib/libuwi_java.so
  4. In the /etc directory, create or update the PureEdgeAPI.ini file. The file should contain the following setting:
    [API]
    7.6.* = /usr/lib/PureEdge/76
  5. Ensure that other users can access the PureEdgeAPI.ini file:
    chmod a+r /etc/PureEdgeAPI.ini
  6. Locate the directory /etc/PureEdge/API 7.6/prefs. If the directory does not exist, create it, noting that there is a space in the directory API 7.6.
  7. In the /etc/PureEdge/API 7.6/prefs directory, create a configuration file called prefs.config. The API relies on this configuration file to set a number of properties. In this case, you are concerned only with the javaPath property, which sets the path of the libjvm.so file that is used in the Java Virtual Machine (JVM). Use the following sample content in the configuration file:
    javaPath = /opt/IBM/WebSphere/AppServer/java/jre/bin/classic/libjvm.so

    NOTE: If there are two or more JVMs installed in your server, the javaPath must point to the same JVM that WebSphere Portal uses to make the API work with WebSphere Portal. By default, WebSphere Portal uses the JVM in the /opt/IBM/WebSphere/AppServer/java directory. If you are not sure which JVM WebSphere Portal is using, go to the WebSphere Application Server Administration Console to find the information: open Environment - WebSphere Variables, specify the scope to the node that contains WebSphere Portal, and then check the JAVA_HOME variable to see the Java base directory.
  8. Ensure that users other than root can access the configuration file.
    chmod –R a+r /etc/PureEdge
  9. Set the WebSphere variables:
    • In the WebSphere Application Server Administration Console, go to Environment - WebSphere Variables.
    • Click Browse Nodes, and select the node that contains WebSphere_Portal.
    • Click New to create an environment variable, and call it LFS_API_DIR (see figure 1). Set its value to /usr/lib.
    • Repeat the previous step to create another environment variable called LFS_API_LIB_DIR. Set its value to ${LFS_API_DIR}/PureEdge/76/java/classes.
Figure 1. Adding a new WebSphere variable – LFS_API_DIR
Adding a new WebSphere variable – LFS_API_DIR
  1. Set the Java process definitions:
    • In the WebSphere Application Server console, open Servers - Application servers - WebSphere_Portal - Java and Process Management - Process Definition - Environment Entries (see figure 2). Note that the exact location varies depending on the version of WebSphere Application Server that you have.
    • Add ${LFS_API_DIR}:${LFS_API_DIR}/PureEdge/76/system: to the beginning of the existing LD_LIBRARY_PATH property.
Figure 2. Modifying environment entries
Modifying environment entries

NOTE: Remember to use the correct separator; Windows uses a semicolon (;), but UNIX platforms use a colon (:).

  1. Set the shared libraries:
    • In the WebSphere Application Server console, go to Environment - Shared Libraries.
    • Click Browse Nodes, and select the node that contains WebSphere_Portal.
    • Clear the Server field, and click Apply.
    • Click New to create a shared library and call it LFS_API_LIB (see figure 3). Under Classpath, list the following files (one per line):
      ${LFS_API_LIB_DIR}/pe_api.jar
      ${LFS_API_LIB_DIR}/pe_api_native.jar
      ${LFS_API_LIB_DIR}/commons-codec.jar
      ${LFS_API_LIB_DIR}/xmlsec-1.4.1.jar
Figure 3. Adding a new shared library – LFS_API_LIB
Figure 3. Adding a new shared library – LFS_API_LIB
  1. Set the server class loader:
    • In the WebSphere Application Server Administration Console, open Servers - Application servers - WebSphere_Portal - Java and Process Management - Class loader.
    • Select the existing classloader, and then click Libraries.
    • Click Add to add a new Library Reference.
    • Under Library Name, select LFS_API_LIB, and click OK.
  1. Save all changes to the master configuration and then restart WebSphere Portal.

Designing the XFDL form

For this application, we need to create a purchase order form that we can host in WebSphere Portal. You can create forms using IBM Lotus Forms Designer. For your convenience, we have provided the completed form, shown in figure 4, with this article.

Figure 4. The purchase order form
The purchase order form

The purchase order form uses an XForms submission to submit the data model of the form. This means that we are submitting only the form’s data, not the presentation itself (the XFDL elements).

This is a design choice that we have made. We could submit the entire form if we wanted, but then we would have to extract the data during processing. By submitting just the model, we can skip this step. In some cases, though, it is preferable to submit the entire form. For instance, if you want a complete record of the transaction for regulatory purposes, submitting and storing the entire XFDL form is a good idea.

To set the form to submit only the XForms model, you need to make some simple settings in the form itself. The sample form that we provided already has these settings, but reviewing them briefly is worthwhile.

Open the form in IBM Lotus Forms Designer and inspect the submission in the XForms view (see figure 5). It has the following properties:

  • An action property of "http://"
  • A method property of "post"
  • A replace property of "all"
Figure 5. Setting properties for the XForms submission
Setting properties for the XForms submission

Setting the action property in the XForms submission is mandatory. Because you use Webform Server to display the form in WebSphere Portal, you can set this property to any value. Webform Server actually ignores this setting and instead overwrites this URL with the correct portlet URL when translating the form. This approach ensures that the form is always returned to the correct portlet without requiring you to know the URL ahead of time.

NOTE: If you use Webform Server in a servlet, the return URL is not automatically overwritten. In addition, if you need the form to work in both IBM Lotus Forms Viewer and Webform Server, be sure to set the URL correctly for the Viewer. This ensures that it works properly in Lotus Forms Viewer but is still overwritten when used in Webform Server.

When running Webform Server in a portal environment, you may also want to prevent users from performing some actions such as saving or opening forms. You can do this by disabling the buttons in the Webform Server toolbar.

These buttons are controlled by settings in the form itself, which allows you to control the buttons on a form-by-form basis, rather than being restricted to always having the buttons either on or off. Again, the form we provide is already set up to turn the appropriate toolbar buttons off, but these settings are worth a quick review.

In Lotus Forms Designer (with the sample form loaded), go to the Outline view and select globalpage - Form Global. In the Properties view, open General - ufv_settings - menu. Note that the open, refresh, and save properties are all set to off.

This ensures that the open, refresh, and save buttons are turned off in Webform Server and are not available to the user.

NOTE: This setting controls only the toolbar buttons in Webform Server and Lotus Forms Viewer. If you provide separate controls in your form, such as a save button or a print button, those controls still work normally.


Creating a portlet to display the form

In our scenario, when the user requests a form from WebSphere Portal, Webform Server translates the form into HTML before sending it to the user. Figure 6 shows the steps involved.

Figure 6. Requesting a form from Webform Server
Requesting a form from Webform Server

Follow these steps:

  1. The user requests a form from the portlet.
  2. The portlet receives the request and locates the correct file in a Form Repository.
  3. The portlet retrieves the form.
  4. The portlet passes the form to the Webform Server.
  5. The Webform Server converts the form to a combination of HTML and JavaScript and sends the converted form back to the portlet.
  6. The portlet passes the converted form back to the user.

From these steps, we can see that any portlet we write must communicate with Webform Server. Fortunately, Webform Server also provides a specialized portlet and servlet class that performs this communication for you. This means that instead of extending the generic portlet and servlet classes to write your application, you extend a Webform-specific portlet or servlet class. These classes automatically handle all the communication with the Translator component of Webform Server – you don’t have to write any code to make that happen. Each of these classes also provides a small API to facilitate the development of form-related applications. For example, you can set your portlet to always translate forms into HTML or automatically to detect whether or not your users have the Viewer installed and to send XFDL if they do.

Because the supplied classes remove you from the details of translating the form, you are free to write code that always assumes you are working with XFDL. You never have to process HTML yourself. All HTML that is sent back from the user is intercepted and translated back into XFDL before your code processes it.

For our sample scenario, we want to create a portlet that serves forms to the user. To do this, we must extend the IBMWorkplaceFormsServerPortlet class, which is an abstract class representing a Webform-specific, custom implementation of a JSR 168 Portlet. After you extend this class, you just need to follow some simple rules to develop your own portlet.

The following steps show you how to create a portlet called FormViewPortlet that displays the form and manipulates the form's submission.

  1. Create a JSR168 Portlet Project in IBM Rational IDE.
  2. Copy all the JAR files from the <Webform Server Install Dir>/redist/ directory to the WebContent/WEB-INF/lib/ directory in the portal project. This automatically adds the JARs to the build path.
  3. Locate WebformPortletSampleSrc.zip. It is in the <webform install>\samples\portlet folder. Extract resourceBundle-<version>.jar, and rename it to ws_resourceBundle.jar. Move ws_resourceBundle.jar to the WebContent/WEB-INF/lib/ directory in the portal project.
  4. In the Rational IDE, create a new Java class called forms.portlets.FormViewPortlet, which extends the IBMWorkplaceFormsServerPortlet abstract class (see figure 7).
  5. Select the Inherited abstract methods option to create abstract method stubs for the new class.
Figure 7. Creating the FormViewPortlet
Creating the FormViewPortlet
  1. Copy the following imports to the source code of FormViewPortlet:
    import com.PureEdge.DTK;
    import com.PureEdge.IFSSingleton;
    import com.PureEdge.error.UWIException;
    import com.PureEdge.xfdl.FormNodeP;
    import com.PureEdge.xfdl.XFDL;
  2. If you are using Rational IDE, you must add the pe_api.jar and the uwi_api.jar to the build path. These two files are installed with API in the <API Install Dir>/ lib/java directory. The IDE uses them to compile the code, and the portlet needs these files when working with forms; however, you must not include these two JARs in the WEB-INF/lib/ directory because you have already installed the API to work with WebSphere Portal.
    • Right-click the portal project, then select Properties from the pop-up menu.
    • Select the Java Build Path page.
    • On the Libraries page, click the Add External JARs button to add the pe_api.jar and uwi_api.jar to the build path (see figure 8).
Figure 8. Adding the API JARs to the build path
Adding the API JARs to the build path
  1. Override the init method to initialize the API as shown in listing 1.
    Listing 1. Overriding the init method
    public void init(PortletConfig config) throws PortletException {
    	// always invoke the ancestor's method
    	super.init(config);
    	try {
            // Initialize the API
            DTK.initializeWithLocale("WFS Portal Sample", "1.0.0", "7.5.0", null);
    	} catch (UWIException e) {
          throw new PortletException(e);
    	}
    }
  1. Override the doView method to render the portlet view; see listing 2. In this method, you use super.useHTML(request, true) to force the portlet to translate the XFDL form into HTML. After that, you call the super method and end this method. The IBMWorkplaceFormsServerPortlet object continues operations from that point and decides whether to call the doViewEx method based on its state.
    Listing 2. Overriding the doView method
    public void doView(RenderRequest request, RenderResponse response)
    			throws PortletException, IOException {
    		log.debug("Start to execute the doView method...");
    		// force the portlet to display the XFDL form in HTML mode
    		super.useHTML(request, true);
    		// invoke the ancestor's method
    		super.doView(request, response);
    	}
    NOTE: The IBMWorkplaceFormsServerPortlet maintains a state of either empty or full. The empty state means that no form is loaded and that doViewEx should be called to load a form. The full state means that a form is loaded and that doViewEx does not need to be called.
  1. Implement the doViewEx method; see listing 3. In this method, the portlet uses the API to read the form from the File System and to prepopulate the form with store information by using the FormNodeP.updateXFormsInstance method. Then the method writes the form to the response object and sets the content type of the response object to application/vnd.xfdl.
    Listing 3. Implementing the doViewEx method
    public void doViewEx(RenderRequest request, RenderResponse response)
    			throws PortletException, IOException {
    		log.debug("Start to execute the doViewEx method...");
    		// inform the ancestor portlet of the XFDL form's filename 
    		setFilename(request, "PurchaseOrder.xfdl");
    		PortletContext context = this.getPortletContext();
    		// obtain the form file
    		String formFilePath = context.getRealPath("/") + 
    "/WEB-INF/form/PurchaseOrder.xfdl";
    		FileInputStream fis = new FileInputStream(formFilePath);
    		FormNodeP theForm = null;
    		try {
    			// set the content type appropriately
    			response.setContentType("application/vnd.xfdl");
    // obtain the XFDL object, which is an interface through which you can access
    // the form’s root node.
          XFDL theXFDL = IFSSingleton.getXFDL();
          // read a form into memory from a specified file
          theForm = theXFDL.readForm(fis, XFDL.UFL_SERVER_SPEED_FLAGS);
          fis.close();
    
          // obtain the store information 
          String storeFilePath = context.getRealPath("/") + 
          "/stores/ID001001.xml";
    // replaces the XForms instance in the form’s data model to prepopulate 
    // the form with store information
    theForm.updateXFormsInstance(null,
    	"instance('poInstance')/schemaNS1:store", null,	
    	storeFilePath, null, XFDL.UFL_XFORMS_UPDATE_REPLACE);
          // write the form to the portlet response output stream
          theForm.writeForm(response.getPortletOutputStream(), null, 0);
         } catch (Exception e) {
          log.error("Failed to display the form!", e);
        } finally{
          if(theForm != null){
            try {
            // destroys the indicated FormNodeP to remove it from memory
            theForm.destroy();
            } catch (UWIException e1) {
              log.error("Failed to destory the form object!", e1);
              }
            }
          }
    	}

    After you write the form to the response object, you can end the doViewEx method. The IBMWorkplaceFormsServerPortlet continues operations from that point. Because you have set the portlet to always display the form as HTML, the IBMWorkplaceFormsServerPortlet object automatically calls Webform Server to perform the translation, and it returns the HTML form to the user.
  1. Now that you have completed the code to display the form in the portlet, implement the processActionEx method to process the XForms submission.

    An XForms submission with a replace="all" setting works differently than an XForms submission with a replace="instance". When using a replace="instance" submission, the data submitted is automatically passed to a processing URL by Webform Server, and the return data is automatically embedded into the form and returned to the user. This has the effect of replacing a data instance in the form while the user is still working with it. You have to handle replace="all" manually, though; Webform Server does not automatically process this request in the same way.

    When Webform Server receives an XForms submission with a replace="all" attribute, it sets the xformsreplaceall HTTP header to true and returns the data to the application. In this method, you use the isReplaceAll function to determine if the portlet received an XForms submission; see listing 4. If there is an XForms submission, the portlet reads the submission data from the request input stream and then stores the data in a FormViewSessionBean object that is saved within the session.
    Listing 4. Using the isReplaceAll function
    public void processActionEx(ActionRequest request, ActionResponse response)
          throws PortletException, IOException {
        log.debug("Start to execute the processActionEx method...");
        if (isReplaceAll() == true) {
          // the portlet received an XForms submission here
          FormViewSessionBean bean = this.getFormViewSessionBean(request);
          bean.reset();
          bean.setReplaceAll(true);
          bean.setReplaceAllContentType(request.getContentType());
    
          // read the submission data from the request inputstream
          InputStreamReader reader = new 
    InputStreamReader(request.getPortletInputStream(), "UTF-8");
          StringBuffer replaceAllData = new StringBuffer();
          char[] chars = new char[32000];
          int charsRead;
         while ((charsRead = reader.read(chars, 0, chars.length)) != -1) {
            replaceAllData.append(chars, 0, charsRead);
          }
    			
            // store the data in a FormViewSessionBean object
            bean.setReplaceAllData(replaceAllData.toString());
          } else {
            log.debug("Portlet received other kinds of action in the processActionEx.");
    		}
    	}
  1. Update the doViewEx method to display the submission data on the screen for the user; see listing 5. The method gets the submission data from the FormViewSessionBean object in the session and writes the data to the portlet response object.
    Listing 5. Updating the doViewEx method
    public void doViewEx(RenderRequest request, RenderResponse response)
          throws PortletException, IOException {
          log.debug("Start to execute the doViewEx method...");
          FormViewSessionBean bean = this.getFormViewSessionBean(request);
        if (bean.isReplaceAll()) {
        // the method has been called after a submission that resulted in a replaceAll
        String replaceAllData = bean.getReplaceAllData();
         // write the XML data as text in the screen
        replaceAllData = replaceAllData.replaceAll("<", "&lt;");
        replaceAllData = replaceAllData.replaceAll(">", "&gt;");
        response.setContentType("text/html; charset=UTF-8");
        String userMessage = "Document submitted successfully. <BR><BR> ";
        PrintWriter writer = response.getWriter();
        writer.write(userMessage);
        writer.write(replaceAllData);
        writer.flush();
        bean.reset();
      } else {
        // here is the code to display the form for the user
        	…
        }
    }

    As you can see, the doViewEx method must handle two different scenarios. In the first scenario, the doViewEx method must display a form to the user. In the second scenario, the doViewEx method must display some other result, such as an HTML response to a form submission.

    Also, for our sample, we return the submission data to the user. In a real application, you would likely send the submission data to some other application (such as a workflow) and get a response from that application, such as a success or failure message. You could then forward this response to the user or move the user on to the next stage in your application (such as a second form).

Creating a two-pane portal

Now we expand our scenario to include a two-pane portal, in which each pane is a separate portlet. The first pane is our FormViewPortlet; the second pane, called SupplierListPortlet, displays a list of suppliers. When the user selects one supplier in the SupplierListPortlet, the FormViewPortlet prepopulates the form with information for the selected supplier, and then displays the form.

To create this portal, follow these steps:

  1. Create a new JSR 168 portlet in Rational IDE, and call it SupplierListPortlet (see figure 9). Because the SupplierListPortlet portlet does not handle XFDL forms directly, it does not need to extend the IBMWorkplaceFormsServerPortlet class. Instead, it extends the GenericPortlet class. As such, it requires a doView method and a processAction method.
Figure 9. Creating the SupplierListPortlet
Creating the SupplierListPortlet
  1. In the doView method, set the SupplierListPortlet portlet to create a list of all XML files available in the <context root>/suppliers folder; see listing 6.
    Listing 6. Setting the SupplierListPortlet portlet to create a list of XML files
    public void doView(RenderRequest request, RenderResponse response)
          throws PortletException, IOException {
        log.debug("Start to execute the doView method...");
        // get the suppliers
        File supplierDirectory = new 
        File(this.getPortletContext().getRealPath("/") + "/" + 
    "suppliers");
        File[] supplier_files = supplierDirectory.listFiles(new SupplierXMLFileFilter());
        // display the suppliers in the screen
        response.setContentType("text/html; charset=UTF-8");
        StringBuffer html = new StringBuffer();
        html.append("Please select a supplier for the purchase order:");
        html.append("\n<UL>");
        int length = supplier_files.length;
        for (int i =0; i<length; i++) {
          File element = supplier_files[i];
          PortletURL url = response.createActionURL();
          url.setParameter("file", element.getName());
          html.append("\n<LI><a href=\"").append(url.toString()).append("\">");
    			
          html.append(element.getName()).append("</a></LI>");
    	}
        html.append("\n</UL>");
        PrintWriter writer = response.getWriter();
        writer.write(html.toString());
        writer.flush();
    	}
  1. In the processAction method, set the SupplierListPortlet portlet to use a bean called SupplierListSessionBean; see listing 7. This bean records which supplier is selected by the user and is stored in the session.
    Listing 7. Setting the SupplierListPortlet portlet to use a bean
    public void processAction(ActionRequest request, ActionResponse response)
    			throws PortletException, IOException {
    		log.debug("Start to execute the processAction method...");
    		String filename = null;
    		if ((filename = request.getParameter("file")) == null) {
    			log.debug("No file has been selected!");
    		} else {
    			// store the selected supplier in the session
    			SupplierListSessionBean bean = 
    			getSupplierListSessionBean(request);
    			bean.setFilename(filename);
    		}
    	}
  1. Now update the doView method in FormViewPortlet; see listing 8. The portlet must first get the selected supplier from the session. As mentioned earlier, IBMWorkplaceFormsServerPortlet maintains a state to record whether or not the portlet has displayed a form. In this case, you want to set the portlet to be empty when a new form is selected. You can do this by calling the super.resetPortlet method. This causes the portlet to call the doViewEx method. Accordingly, you must also remove the information from the session to avoid reloading the form each time the page is refreshed.
    Listing 8. Updating the doView method in FormViewPortlet
    public void doView(RenderRequest request, RenderResponse response)
          throws PortletException, IOException {
        log.debug("Start to execute the doView method...");
    		
    String requestFilename = null;
        // obtain filename from the session. The value was put into the session by the 
        //SupplierListPortlet.  
        SupplierListSessionBean listSessionBean = 
    this.getSupplierListSessionBean(request);
        if(listSessionBean != null && (requestFilename = 
        listSessionBean.getFilename()) != null){
          log.debug("A supplier has been selected: "+requestFilename);
          // obtain the session bean
          FormViewSessionBean bean = this.getFormViewSessionBean(request);
          // update the FormViewSessionBean bean's values based on those found 
    // in the request's session
          bean.setFilename(requestFilename);
        // remove the filename in the request's session once we got it to avoid reloading
    // the form every time
          listSessionBean.setFilename(null);
          // reset the ancestor portlet so that we guarantee the doViewEx() method is 
    //invoked to read in the new XFDL form
          super.resetPortlet(request);
        }else{
          log.debug("No supplier was selected");
        }
    
        // force the portlet to display the XFDL form in HTML mode
        super.useHTML(request, true);
        // invoke the ancestor's method
        super.doView(request, response);
    	}
  1. Next, you update the doViewEx method in FormViewPortlet; see listing 9. Before writing the form into the response output stream, the portlet gets the file name from the session and uses the FormNodeP.updateXFormsInstance method to prepopulate the form with the supplier information.
    Listing 9. Updating the doViewEx method in FormViewPortlet
    // read the directory and filename from the session bean
      String supplierFile = bean.getFilename();
      if(supplierFile != null){
        String supplierFilePath = context.getRealPath("/")+"/suppliers/"+supplierFile;
        // prepopulate the form with the supplier information
        theForm.updateXFormsInstance(null, "instance('poInstance')/schemaNS1:supplier", 
    null, supplierFilePath, null, XFDL.UFL_XFORMS_UPDATE_REPLACE);
    	}

Configuring the portal application

In the portlet.xml, you must configure the init-param settings for the IBMWorkplaceFormsServerPortlet. This is crucial for distributed installations, in which the various components of Webform Server may be distributed across multiple servers. The portlet.xml provides the map that is used to determine where each component is installed.

The key settings are:

  • translatorLocation: Mandatory. The location of the Webform Translator servlet (called translator).
  • logServerName: Optional. The host name for the Log Server.
  • logServerPort: Optional. The port number for the Log Server.
  • logLevel: Optional. Sets which events are logged.
  • portletWidth: Optional. The width of the portlet in the browser.
  • portletHeight: Optional. The height of the portlet in the browser.

As discussed earlier, you are creating a solution in which all the Webform Server components are installed on a dedicated server. For the purpose of this article, call this server ogrdform. The portlets are hosted on WebSphere Portal and rely on the portlet.xml file to locate the Webform Server components. As such, our portlet.xml file looks like the code in listing 10.

Listing 10. The portlet.xml file
<portlet>
		<description>Form View Portlet</description>
		<portlet-name>Form View Portlet</portlet-name>
		<display-name>Form View Portlet</display-name>
		<portlet-class>forms.portlets.FormViewPortlet</portlet-class>
		<init-param>
			<name>translatorLocation</name>
			<value>http://ogrdform:8085/translator</value>
		</init-param>		
		<init-param>
			<name>logServerName</name>
			<value>ogrdform</value>
		</init-param>
		<init-param>
			<name>logServerPort</name>
			<value>4560</value>
		</init-param>				
		<init-param>
			<name>logLevel</name>
			<value>1</value>
		</init-param>
		<init-param>
			<name>portletWidth</name>
			<value>800</value>
		</init-param>			
		<init-param>
			<name>portletHeight</name>
			<value>400</value>
		</init-param>
		<expiration-cache>0</expiration-cache>
		<supports>
			<mime-type>text/html</mime-type>
			<portlet-mode>VIEW</portlet-mode>
		</supports>
		<supported-locale></supported-locale>       
		<resource-bundle></resource-bundle>
	</portlet>

When using portlets with Webform Server, you also have to use a special servlet, called the WebformPortletForwarder. You must also add the following content to the portlet’s web.xml file to ensure that the application uses the WebformPortletForwarder servlet properly; see listing 11.

Listing 11. Content added to the portlet's web.xml file
<servlet>
	<servlet-name>PWSForwarder</servlet-name>
	<servlet-class>
	com.ibm.form.webform.framework.portlet.WebformPortletForwarder</servlet-class>
		<init-param>
			<!-- This parameter points to the location of the Translator 
servlet in Webform Server -->
			<!-- You can change the server name and port here according 
to your configuration of Webform Server-->
			<param-name>translatorLocation</param-name>
			<param-value>http://ogrdform:8085/translator</param-value>
		</init-param>	
</servlet>
<servlet-mapping>
	<servlet-name>PWSForwarder</servlet-name>
	<url-pattern>/PWSForwarder/*</url-pattern>
</servlet-mapping>

Finally, you must make sure the supporting files are in the right locations:

  • The PurchaseOrder.xfdl XFDL form goes in the WEB-INF/form directory.
  • The XML file for the stores goes in the WebContent/stores directory.
  • The XML files for the suppliers in the WebContent/suppliers directory.

You are now ready to create your portlets and deploy them to WebSphere Portal. We assume that you deploy the portlet without detailed steps; however, note that when you deploy the portlets, you must place the SupplierListPortlet above the FormViewPortlet in the portal page (see figure 10).

Figure 10. Deploying the portlets to a page
Deploying the portlets to a page

Testing the portal application

Testing the application allows you to ensure that the portal and WebSphere Portal are set up correctly.

  1. Open a Web browser and log into WebSphere Portal, then open the page that is hosting the portals you built. You can see the supplier list at the top of the page and the form immediately below that. If you look at the form, you can also see that it has been prepopulated with the correct store information.
  2. Select a supplier in the Supplier List Portlet. You can see in figure 11 that the form is updated with the supplier's information.
  3. Use the Add Row or Delete buttons to add or remove items for purchase in the form, then enter values for each item.
Figure 11. Filling out the form
Filling out the form
  1. After completing the form, click the Submit button to submit the data back to the server. The application responds by returning the data you submitted along with the message "Document submitted successfully."

Conclusion

IBM Lotus Forms enables the creation and delivery of XML forms applications. Furthermore, by using Webform Server, you remove the need to distribute Lotus Forms Viewer to each user – users can rely solely on their Web browser to interact with Lotus Forms. When using Webform Server, you create these applications by extending the portlet (or servlet) class that is provided with the product. You can then include whatever processing code you want, including ties to other applications (such as workflows or databases). Although this article provided a simple example that did not tie into any other systems, it’s easy to see how you would add that sort of processing, thereby creating an end-to-end solution for your enterprise.


Download

DescriptionNameSize
Code sampleWFSPortalProject.war395 KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into IBM collaboration and social software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Lotus, WebSphere
ArticleID=202740
ArticleTitle=Integrating IBM Lotus Forms with WebSphere Portal to create a form-centric application
publish-date=11192008