Learn how to use the IBM Lotus Expeditor Toolkit to do the following:
- Create and customize an embedded browser view in a client application.
- Use the EmbeddedBrowser API to further control the embedded browser view.
- Enable single sign-on to log into a Web application with existing account credentials.
- Enable a Web application to interact with a client application through exposed application programming interfaces (APIs) from the Document Object Model (DOM) specification of the World Wide Web Consortium (W3C).
The Lotus Expeditor embedded browser allows application developers to programmatically control and interact with the Web applications using the W3C DOM API in the client application.
You should be familiar with the following technologies:
- Eclipse plug-in development
- Rich client application development using Lotus Expeditor Toolkit
- W3C DOM API
Minimum software requirements to complete this sample are as follows:
- Java (TM) 1.4.2 or 5.0
- One of the following software development platforms:
- IBM WebSphere Application Server Toolkit 6.1.1
- IBM Rational Application Developer 7.0
- IBM Rational Software Architect 7.0
- IBM Lotus Expeditor Toolkit, Version 6.1 or 6.1.1
- IBM Lotus Expeditor Client, Version 6.1 or 6.1.1
For the purposes of this article, IBM WebSphere Application Server Toolkit 6.1.1 and the Lotus Expeditor 6.1 Toolkit were installed on a Microsoft Windows platform.
Importing the embedded browser sample project from the samples gallery
The first step is to create a client service project and implement an embedded browser view. Start with the embedded browser sample, located in the Samples Gallery. To import this sample, follow these steps:
- Open the Rational Software Development Platform.
- Select Help - Samples Gallery. The Samples Gallery window is displayed.
- Select Technology samples. Expand the plus sign (+) next to Lotus Expeditor samples, and select Embedded Browser sample. The embedded browser sample description is displayed as shown in figure 1.
Figure 1. The Embedded Browser sample
- Click Setup instructions to import the sample into your workspace, launch the test runtime, and run the sample.
NOTE: After importing com.ibm.rcp.samples.ui.browser.launch into your workspace, it is a good idea to read the
embedded browser Sample.pdf file, located in the /doc directory. This document explains the details of this sample.
After importing the embedded browser sample, a sample project is created with the following:
- A sample perspective is defined, which displays an embedded browser view. See BrowserPerspective.java.
- A launcher item is defined. You can create new embedded browser views using NewTabAction.java.
If you are not familiar with perspectives or launcher items, see the Lotus Expeditor Information Center.
Customizing the embedded browser view
This section discusses how to customize embedded browser views. The NewTabAction.java API defines an IworkbenchWindowActionDelegate interface, which is triggered when the user chooses Embedded Browser - Add Browser from the menu. Listing 1 depicts the code for launching an Embedded Browser view.
Listing 1. Launching an embedded browser view
public void run(IAction action) {
final String secondaryId = BROWSER_VIEW_ID
+ Integer.toString(++counter);
Map configMap = new HashMap();
configMap.put("ID", secondaryId); //$NON-NLS-1$
setupConfig(configMap);
EmbeddedBrowser browser = BrowserFactory.launch(null, configMap, null);
if (browser != null) {
addListeners(browser);
}
}
|
The BrowserFactory.launch() method accepts a Map object for each embedded browser view that you want to create. The Map object contains settings for public configurations. These configurations are described in the Lotus Expeditor Information Center in the following sections:
In this sample, you can modify the setupConfig() method to customize each newly created embedded browser view. For example, you can customize an embedded browser view with the following items:
- No toolbar, no status bar
- Disable to show context menu
- Set the initial URL to http://www.ibm.com/products/us/
Listing 2 shows the customized code in the setConfig() method.
Listing 2. Customized code in the setConfig() method
import com.ibm.rcp.ui.browser.BrowserPreference;
private void setupConfig(Map configMap) {
configMap.put(BrowserPreference.SHOW_TOOL_BAR,"false");
//Disable toolbar
configMap.put(BrowserPreference.SHOW_URL_ENTRY, "false");
//Disable URL input entry
configMap.put(BrowserPreference.INITIAL_URL, "http://www.ibm.com/products/us/");
//Set the initial URL
configMap.put(BrowserPreference.ENABLE_CONTEXT_MENU, "false");
//Disable Show context menu
}
|
To verify the results, follow these steps:
- Run the project from the existing run configuration.
- Select Embedded Browser Sample from the Open list to show the first sample.
- Select Embedded Browser - Add Browser. This step launches a new embedded browser view as shown in figure 2.
Notice that the view does not include a toolbar or status bar. Also, right-clicking the Web page does not display a context menu.
Figure 2. Embedded browser view
Hints:
- You can use Eclipse preferences to define default preferences for the embedded browser. In this way, all browser instances are affected. For details, see information about implementing an embedded Web browser in the information center.
Setting to the Map object at construction affects only one instance. The configurations in the Map object override the default settings, including the settings defined by Eclipse preferences.
- Each configuration item accepts a string value only.
- The default embedded browser view does not support running Applet. Set BrowserPreference.
ENABLE_APPLET to true to enable it.
NOTE: This preference is applicable only to Microsoft Internet Explorer for the Windows platform.
Using the EmbeddedBrowser interface
The com.ibm.rcp.ui.browser.EmbeddedBrowser interface allows you to enhance the view by adding listeners to handle events and by implementing navigation. In this article, we focus on how to get this interface for each embedded browser instance.
For general use information, see the Lotus Expeditor Information Center.
Using the BrowserFactory.launch() method
The BrowserFactory.launch() method returns the EmbeddedBrowser interface directly after the browser view is created.
Using the BrowserFactory.getBrowser() method
The BrowserFactory.getBrowser() method returns the EmbeddedBrowser interface using the given ID string. The ID string is an index to return the correct instance. It is recommended that you call one of these methods before calling the getBrowser() method:
- BrowserFactory.setBrowser()
- BrowserFactory.setBrowserMap()
Best practices include the following:
- Use the secondary view ID as the same ID string, and use the method to generate a unique secondary view ID string as shown in listing 3.
Listing 3. Secondary view IDpublic final static String Sample_BROWSER_VIEW_ID = "com.ibm.rcp.samples.ui.browser.launch.SampleBrowserView"; private String genID() { return Sample_BROWSER_VIEW_ID + Long.toString(System.currentTimeMillis()); }
- Set the ID string to the BrowserPreference.ID configuration item in the Map object.
- The EmbeddedBrowser interface is initialized after the embedded browser view is shown; otherwise, it returns NULL. NULL is returned when a browser view is in the IperspectiveFactory.createInitialLayout() method and attempts to query the EmbeddedBrowser interface.
This sample project does not demonstrate how to get the first embedded browser view shown in the perspective. The updated code demonstrates how to get the EmbeddedBrowser interface after the perspective is shown; however, there is a limitation.
In the IPerspectiveFactory.createInitialLayout() method, the EmbeddedBrowser interface cannot be queried if you call as shown in listing 4.
Listing 4. Query EmbeddedBrowser interface in BrowserPerspective.java
public void createInitialLayout(IPageLayout layout)
{
HashMap configMap=new HashMap();
String secondaryId="defaultBrowserView"; //$NON-NLS-1$
configMap.put("ID", secondaryId); //$NON-NLS-1$
configMap.put(BrowserPreference.INITIAL_URL, "http://www.ibm.com"); //$NON-NLS-1$
BrowserFactory.setBrowserConfigMap(secondaryId, configMap);
layout.setEditorAreaVisible(false);
layout.addView(BrowserPreference.BROWSER_VIEW_ID+":"+secondaryId,IPageLayout.BOTTOM,
0f,IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$
EmbeddedBrowser defaultBrowser=BrowserFactory.getBrowser(secondaryId);
}
|
This limitation occurs because the embedded browser view is added into layout only within the createInitialLayout() method. The instance is not created; thus, getBrowser() returns NULL in the function call. This limitation means that you can use only the returned EmbeddedBrowser interface. In the updated code shown in listing 5, a listener is registered to watch when the view is created and uses getBrowser() to get the instance. Then, its APIs can be called.
Listing 5. Update BrowserPerspective.java to query EmbeddedBrowser interface
/*
* Licensed Materials - Property of IBM
*
* 5724-R09
*
* (C) Copyright IBM Corp. 2006. All rights reserved.
*
*/
package com.ibm.rcp.samples.ui.browser.launch.prsp;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPerspectiveFactory;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import com.ibm.rcp.ui.browser.BrowserFactory;
import com.ibm.rcp.ui.browser.BrowserPreference;
import com.ibm.rcp.ui.browser.EmbeddedBrowser;
import java.util.HashMap;
public class BrowserPerspective implements IPerspectiveFactory {
public String secondaryId=
"com.ibm.rcp.samples.ui.browser.launch.defaultBrowserView"; //$NON-NLS-1$
private EmbeddedBrowser defaultBrowser=null;
public void createInitialLayout(IPageLayout layout)
{
HashMap configMap=new HashMap();
configMap.put(BrowserPreference.ID, secondaryId); //$NON-NLS-1$
configMap.put(BrowserPreference.INITIAL_URL, "http://www.ibm.com"); //$NON-NLS-1$
BrowserFactory.setBrowserConfigMap(secondaryId, configMap);
layout.addView(BrowserPreference.BROWSER_VIEW_ID+":
"+secondaryId,IPageLayout.BOTTOM, 0f,IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$
PlatformUI.getWorkbench().getActiveWorkbenchWindow().
addPageListener(new IPageListener(){
public void pageActivated(IWorkbenchPage arg0) {
if(defaultBrowser!=null){
return;
}
defaultBrowser=BrowserFactory.getBrowser(secondaryId);
if(defaultBrowser==null){
System.out.println("Fail to query EmbeddedBrowser interface");
}
}
public void pageClosed(IWorkbenchPage arg0) {
if(defaultBrowser!=null){
defaultBrowser=null;
}
}
public void pageOpened(IWorkbenchPage arg0) {
}});
}
}
|
In this updated code example, IpageListener is registered to the current active workbench window. In the page- activated method, the EmbeddedBrowser interface is queried, and the reference is cleaned when the page is closed as shown in listing 6.
Listing 6. Clean the reference to EmbeddedBrowser interface
public void pageClosed(IWorkbenchPage arg0) {
if(defaultBrowser!=null){
defaultBrowser=null;
}
}
|
NOTE: The Java garbage collection (GC) does not release EmbeddedBrowser if an object refers to it.
Enabling single sign-on to a Web application with existing account credentials
The IBM Lotus Expeditor Accounts component provides the ability to store, retrieve, and manipulate account- related data. In this section, the Accounts API is used to sign on a Web application without prompting for a user name and password.
For more information about the Accounts component, see the following sections in the Lotus Expeditor Information Center:
Use case: The following items are applicable to the client application:
- An embedded browser view is directed to visit a Web application.
- The Web application requires authentication.
- The authentication information (user name/password) is already maintained by the Accounts component.
Prerequisite: The Web server must return a cookie for single sign-on.
This sample project assumes that you want to single-sign-on to a portal home page using the default embedded browser view in the perspective. To do so, follow these steps:
- Lay out the embedded browser view with an empty URL.
- Query the EmbeddedBrowser interface in the IpageListener.
- Use the Accounts API to query the existing cookie credentials. If cookie credentials do not exist, you can also call the Login() method with the Accounts API to log in, and then query the cookie credentials again.
- Call the EmbeddedBrowser.setCookie() method to set the cookie credentials.
- Call EmbeddedBrowser.setURL() to set the target URL.
Listing 7 shows the updated code in BrowserPerspective.java, which performs a single sign-on to the portal home page. Add a dependency to the Account component.
Listing 7. Update MANIFEST.MF
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Embedded Browser sample
Bundle-SymbolicName: com.ibm.rcp.samples.ui.browser.launch;singleton:=true
Bundle-Version: 6.1.1
Bundle-Vendor: IBM
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
com.ibm.rcp.ui,
com.ibm.rcp.ui.browser,
com.ibm.rcp.accounts,
org.apache.commons.httpclient
Eclipse-LazyStart: true
|
Update the BrowserPerspective.java file as shown in listing 8.
Listing 8. Updating the BrowserPerspective.java file
/*
* Licensed Materials - Property of IBM
*
* 5724-R09
*
* (C) Copyright IBM Corp. 2006. All rights reserved.
*
*/
package com.ibm.rcp.samples.ui.browser.launch.prsp;
import org.apache.commons.httpclient.Cookie;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPerspectiveFactory;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import com.ibm.rcp.accounts.Account;
import com.ibm.rcp.accounts.AccountsManager;
import com.ibm.rcp.accounts.AccountsManagerFactory;
import com.ibm.rcp.security.auth.SingleSignonToken;
import com.ibm.rcp.security.auth.service.ILoginContextService;
import com.ibm.rcp.ui.browser.BrowserFactory;
import com.ibm.rcp.ui.browser.BrowserPreference;
import com.ibm.rcp.ui.browser.EmbeddedBrowser;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.security.auth.RefreshFailedException;
import javax.security.auth.Subject;
public class BrowserPerspective implements IPerspectiveFactory {
public String secondaryId=
"com.ibm.rcp.samples.ui.browser.launch.defaultBrowserView"; //$NON-NLS-1$
private EmbeddedBrowser defaultBrowser=null;
public void createInitialLayout(IPageLayout layout)
{
HashMap configMap=new HashMap();
configMap.put(BrowserPreference.ID, secondaryId); //$NON-NLS-1$
configMap.put(BrowserPreference.INITIAL_URL, "about:blank"); //$NON-NLS-1$
BrowserFactory.setBrowserConfigMap(secondaryId, configMap);
layout.addView(BrowserPreference.BROWSER_VIEW_ID+":"+
secondaryId,IPageLayout.BOTTOM, 0f,IPageLayout.ID_EDITOR_AREA); //$NON-NLS-1$
PlatformUI.getWorkbench().getActiveWorkbenchWindow().
addPageListener(new IPageListener(){
public void pageActivated(IWorkbenchPage arg0) {
if(defaultBrowser!=null){
return;
}
defaultBrowser=BrowserFactory.getBrowser(secondaryId);
if(defaultBrowser==null){
System.out.println("Fail to query EmbeddedBrowser interface");
//$NON-NLS-1$
return;
}
if(ssoBrowser("http://9.181.66.227:10038/wps")==false){
System.out.println("Fail to single-sign-on to the portal server");
//$NON-NLS-1$
}
defaultBrowser.setUrl("http://9.181.66.227:10038/wps/myportal");
//$NON-NLS-1$
}
public void pageClosed(IWorkbenchPage arg0) {
if(defaultBrowser!=null){
defaultBrowser=null;
}
}
public void pageOpened(IWorkbenchPage arg0) {
}});
}
private boolean ssoBrowser(String url){
if(defaultBrowser==null){
return false;
}
AccountsManager manager = AccountsManagerFactory.getAccountsManager( );
if(manager ==null){
return false;
}
List accList=manager.getAccountsByServer(url);
if(accList==null||accList.size()==0){
return false;
}
for(int count=0;count<accList.size();count++)
{
try{
Account acc=(Account)accList.get(count);
String cookieType=null;
String cookieValue=null;
if(acc==null){
return false;
}
ILoginContextService context = acc.getLoginContext();
if(context==null){
return false;
}
Subject subject = context.getSubject( );
Set credentials = subject.getPrivateCredentials(SingleSignonToken.class);
if(credentials==null){
return false;
}
Iterator iterator = credentials.iterator();
Cookie[] cookie = null;
while (iterator.hasNext()) {
SingleSignonToken credential = (SingleSignonToken)iterator.next();
if (!credential.isCurrent()) {
try {
credential.refresh();
} catch (RefreshFailedException rfe) {
continue;
}
}
cookie = credential.getSsoTokens();
if (cookie != null && cookie.length >0){
int iCookieIndex=0;
for(iCookieIndex=0;iCookieIndex<cookie.length;iCookieIndex++){
cookieType = cookie[iCookieIndex].getName();
cookieValue = cookie[iCookieIndex].getValue();
if(cookieType!=null){
defaultBrowser.setCookie(url, cookieType+"="+cookieValue);
//set cookie
}
}
}
}
}catch(Exception e){
e.printStackTrace();
return false;
}
}
return true;
}
}
|
In the updated sample project, these factors are important:
- http://9.181.66.227:10038/wps/portal/ specifies the IBM WebSphere Portal server for testing.
- In the plug-in manifest, two new bundles are required:
- com.ibm.rcp.accounts
- org.apache.commons.httpclient.
- Notice that there are two setURL calls in the updated code. The first call is set to a blank page; the second call sets the target URL after calling the setCookie API. The cookies must be set prior to loading the target URL.
- The ssoBrowser() method queries the Account APIs to get all the returned credentials from the server. In this sample, it does not perform a real login. It is assumed that it is already logged in before the application opens. If the account does not have credentials returned, this typically means that the target server does not return cookies or that it has not logged in yet.
- You can call EmbeddedBrowser.setCookie multiple times with the same URL because it accepts a cookie string with type=value pairs. If you set the string twice to the same URL with the same type and different values, the later one takes effect.
To run the updated code, follow these steps:
- Run the Lotus Expeditor Client. Provide a password if required.
- Choose File - Preferences, and then select the Home Portal Account preference page. Enter the testing portal server information as shown:
- In the Server field, enter http://9.181.66.227:10038/wps/.
- In the User field, enter the user name for the server.
- In the Password field, enter the password for that server.
- The Advanced Properties group, Home Portal URL field, and Authentication URL field are filled automatically.
- In the Authentication Type field, select the J2EE-FORM option from the box.
Figure 3. The Home Portal Account Preferences page
- Click OK for confirmation. A login action to the portal server is performed automatically.
- Select the Embedded Browser Sample option from the Open list. This option loads the portal home page without a login page as shown in figure 4.
Figure 4. Embedded Browser View with single sign-on enabled
Having the Web application interact with W3C DOM API
A major feature of the embedded browser is that it allows an application to interact with a Web application
through an exposed W3C DOM HTMLDocument interface.
After the embedded browser view completely loads the Web application, it exposes the org.w3c.dom.
html.HTMLDocument interface through the DocumentComplete listener. Other components and applications can interact with Web applications using this HTMLDocument interface. The use case in this section makes the following assumptions:
- A browser view loads the IBM product home page: http://www.ibm.com/products/us/.
- If a user performs a search in the Web application, the Java application captures this event and appends IBM in the search text.
To implement this functionality, update the code with the following changes:
- Implement EmbeddedBrowserDocumentCompleteListener, getting the HTMLDocument interface after that page is loaded.
- Parse the DOM tree of HTMLDocument, and get the target element of the search input box and search button.
- Add a DOM event listener to the search button in Java code.
- When the search button click event is triggered, query the text value of the search input box. Append IBM in the search string and go search.
The updated code fragments in NewTabAction.java are as follows:
- Update class import, as shown in listing 9.
Listing 9. Update class importimport org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.events.Event; import org.w3c.dom.events.EventListener; import org.w3c.dom.events.EventTarget; import org.w3c.dom.html.HTMLDocument; import org.w3c.dom.html.HTMLInputElement;
- Update default EmbeddedBrowserDocumentCompleteListener implementation, as shown in listing 10.
Listing 10. Update EmbeddedBrowserDocumentCompleteListenerbrowser.addDocumentCompleteListener(new EmbeddedBrowserDocumentCompleteListener(){ public void changed(EmbeddedBrowserDocumentCompleteEvent event) { htmlDoc=event.getHTMLDocument(); if(htmlDoc==null){ return; } try{ NodeList inputList=htmlDoc.getElementsByTagName("input"); for(int i=0;i<inputList.getLength();i++){//query the list Node curNode=inputList.item(i); if(curNode instanceof HTMLInputElement){ HTMLInputElement curInputElement=(HTMLInputElement)curNode; if("image".equalsIgnoreCase(curInputElement.getType()) && "Search".equalsIgnoreCase(curInputElement.getName()) && "Search".equalsIgnoreCase(curInputElement.getValue())){ // Search Button if(curInputElement instanceof EventTarget){ EventTarget searchTarget=(EventTarget) curInputElement; searchTarget.addEventListener("click", new EventListener(){ public void handleEvent(Event event) { if(searchTextBox!=null){ String searchText=searchTextBox getValue(); System.out.println("You are searching:" +searchText+" in IBM.com"); searchTextBox.setValue("IBM "+ searchText); //event.stopPropagation(); //event.preventDefault(); } }}, true); } } if("text".equalsIgnoreCase(curInputElement.getType()) && "q".equalsIgnoreCase(curInputElement.getName()) && "q".equalsIgnoreCase(curInputElement.getId())){ searchTextBox=curInputElement; } } } }catch(Exception e){ e.printStackTrace(); } } });
Notes:
- In this sample, the IBM product home page has HTML text to define these two input elements; see the code in listing 11. W3C DOM API is used to get the target element.
Listing 11. HTML text<input value="" type="text" size="15" name="q" maxlength="100" id="q" class="input" /></td> <td width="7"> <input type="hidden" name="v" value="14" /><input type="hidden" name="lang" value="en" /><input type="hidden" name="cc" value="us" /><input type="hidden" name="en" value="utf" /></td> <td><input value="Search" type="image" src="//www.ibm.com/i/v14/t/us/en/search.gif" name="Search" alt="Search" />
- There are two places to use class cascade. It is recommended to catch a possible cascade exception.
- The W3C DOM Level 2 HTML specification and the W3C DOM Level 2 Events specification are supported. Mouse and keystroke events are also supported, such as click, dblclick, keydown, keyup, keypress, mousedown, mousemove, mouseup, mouseout, and mouseover. You can find a complete list of these events in the specification.
You have learned how to implement and customize an embedded browser view in Lotus Expeditor Toolkit and how to perform a single sign-on to improve usability. Moreover, the DOM manipulation gives you the capability to have Web applications inside the embedded browser view interact with other components in Lotus Expeditor.
Learn
-
Read the developerWorks Lotus article, "Using the Personal Wizards plug-in in IBM Lotus Expeditor."
-
Read the developerWorks Lotus article, "Migrating J2EE projects to IBM Lotus Expeditor V6.1."
-
Read the developerWorks Lotus article, "End-to-end integration with pervasive messaging and IBM Lotus Expeditor micro broker."
-
Read the developerWorks Lotus article, "Building an offline application in IBM Lotus Expeditor."
-
Read the developerWorks Lotus article, "Developing and deploying rich client applications on desktops and mobile devices using IBM Lotus Expeditor V6.1."
-
Read the developerWorks Lotus article, "Migrating Eclipse RCP applications to IBM Lotus Expeditor."
-
Read the developerWorks Lotus article, "Creating collaborative components for IBM Lotus Expeditor Property Broker."
-
Read the developerWorks Lotus article, "Developing an OSGi service as a Web service in IBM Lotus Expeditor."
-
Read the developerWorks Lotus article, "Building and deploying a simple Web Services Resource in IBM Lotus Expeditor."
-
Read the IBM Redbooks publication,
Building Composite Applications in Lotus Expeditor V6.1
.
-
Read the developerWorks Lotus Expeditor page.
-
Consult the Lotus Expeditor Information Center.
-
Refer to the IBM Lotus Expeditor documentation.
-
Learn more about the W3C DOM Specification.
-
Learn more about the Document Object Model (DOM) Level 2 HTML Specification.
Get products and technologies
-
Download a trial version of the IBM Lotus Expeditor V6.1 Toolkit.
Discuss
- Participate in the discussion forum.
-
Participate in the developerWorks Lotus team blog.
Comments (Undergoing maintenance)





