http://www.developer.com/

Back to article

Integrate Legacy Web Applications as Full Page IFrames in WebLogic Portal


June 12, 2008

One of the many web site headaches that portal technology was expected to cure is the need for IFrames to integrate content and functionality between web applications. Portals provide a quick, clean approach to combine multiple applications into a single user interface. Intranets rapidly adopted the portal approach to combine the multitude of employee content and self-service applications into a single starting place with great success. The employee portal had two huge advantages over the earlier collection of internal sites, vendor sites, and emails: The employee only needed one URL to find what they needed, and they used it.

External facing portals have also enjoyed a rapid adoption, and they tend to evolve along one of two common paths. The first path is where a company had a small web presence when they adopted the portal approach. These companies could easily build a new portal that combined all of their URLs to a single location and then expand functionality as their web business grew. The other path is where a business was an early adopter of the web as a place to do business with their customers and enjoyed a very rapid return on their technology investment. These companies worked to rapidly expand their success by providing more and more web access for their customers. Whether driven by time to market requirements, external competition, internal competition, or just plain short-sightedness, the new web applications would have unique URLs, different architectures, and developed on whatever language was preferred by a department or decision maker. As with the Intranets, it became apparent that a portal would expose more people to more functionality and increase the technology ROI.

As IT professionals, we all know how difficult is to explain to non-developers that just because all of these features are already web-enabled it is still takes some time to pull them all together. And, we all know that we will eventually have to provide twice the functionality in half the time we need to do it right. In the case of portal integration, one short cut that always comes up is the use of the IFrame, which we thought portals were supposed to save us from.

So, there you are, stuck with using an IFrame to bring in legacy web applications to your portal to meet a deadline (after which you can campaign to "upgrade" the applications to proper portlets). For content-only sites and simple web applications, WebLogic Portal (WLP) has built-in features that make this pretty simple. In version 9.2, WLP introduced the Browser Portlet; it was perfect for pulling in content from other sites. The WLP team introduced an improvement with the release of 10.0, the Clipper Portlet. In many cases, these two approaches will allow you to pull in your external URL in no time flat. They both have two drawbacks that may make them unsuitable to your particular application. One is that you have to define the size of the portlet at design time. There are plenty of web applications where the first screen of a given workflow is smaller than subsequent screens, which makes this awkward. The other drawback is that the URL is defined at design time. If you already have a track scheduled to upgrade the external application to portlets and are confident that what is in production now will be the same until you do, this isn't an obstacle. This is often the exception to the rule, however.

The advantage of a portal framework such as WLP is that it provides frameworks that allow you to simply write code and not worry about how everything will get assembled into an integrated presentation and navigation model. To enjoy the full advantages of such frameworks, you want to always use an out-of-the-box (OOTB) feature before going off to design your own. When it comes to rendering a legacy application inside the portal using an IFrame, you can still do it with OOTB features, though you need to think just a bit out of the box to see how it will work.

A basic portal consists of a header, navigation, content, and a footer. In portals, the content is generally portlets, and the content area is designed to hold portlets, making filling the content area with an IFrame a somewhat daunting experience. The easiest way to define an IFrame so that you don't need to worry about the size of the content is to set its width and height at 100%. However, if you create a portlet to hold a JSP containing a IFRame of 100% X 100%, you only get as much space as you defined at design time (either through portlet properties or CSS). Figure 1 shows the worst-case scenario of no design-time definition:



Click here for a larger image.

Figure 1: JSP Portlet with IFrame

Now, think outside the box. The key elements that make up your portal are the header, navigation, content, and footer. Of those four elements, three of them are rendered by a direct counterpart within the look and feel framework, specifically within the skeletons (this is a bit of a simplification, but accurate enough to lead you to your solution). The odd part out here is content, which is rendered by a group of skeleton files. For a page with a single portlet, the basic skeleton files would be the page.jsp, gridlayout.jsp, placholder.jsp, titlebar.jsp. and window.jsp. The resulting HTML for all of this looks like this:

<div class="bea-portal-book-primary-page">
   <table class="bea-portal-layout-grid" cellspacing="0">
      <tr>
         <td class="bea-portal-layout-placeholder-container">
            <div class="bea-portal-layout-placeholder" >
               <div class="bea-portal-window" width="100%">
                  <div class="bea-portal-window-content">
                     <IFRAME id="example1"
                             NAME="example1"
                             SRC="http://www.developer.com/"
                             frameborder="0"
                             width="100%"
                             height="100%"
                             align="middle"
                             marginheight="0"
                             marginwidth="10"
                             scrolling="auto">
                     </IFRAME>
                  </div>
               </div>
            </div>
         </td>
      </tr>
   </table>
</div>

Your goal here is to fill the portal page with an IFrame, and all of the extra markup from the gridlayout, placeholder, and window (you dropped the titlebar in your portlet properties) is what makes it hard to do what you want. The solution is to create a theme that only uses the page. The theme requires all of the skeleton files listed above, that make up a page for compilation purposes, even though you won't be using them. All but page.jsp should be empty files. page.jsp will look like this:

<%@ page import="java.net.URLDecoder,
   com.bea.netuix.servlets.controls.page.PagePresentationContext,
   com.bea.netuix.servlets.controls.page.BookPresentationContext,
   org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils"
%>
<%@ page session="false"%>
<%@ taglib
    uri="http://www.bea.com/servers/portal/tags/netuix/render"
    prefix="render" %>
<%! static final String URL_KEY = "urlKey";%>
<render:beginRender>
<%
   PagePresentationContext pageCtx =
      PagePresentationContext.getPagePresentationContext(request);
   String urlKey    = pageCtx.getPresentationId();
   String iFrameUrl = ScopedServletUtils.getOuterRequest(request).
      getSession().getServletContext().getInitParameter(urlKey);
%>
<div style="margin-top:-5px">
   <IFRAME id="<%=urlKey %>"
           NAME="<%=urlKey %>"
           SRC="<%=iFrameUrl %>"
           frameborder="0"
           width="100%"
           height="100%"
           align="middle"
           marginheight="0"
           marginwidth="10"
           scrolling="auto">
   </IFRAME>
</render:beginRender>
<render:endRender>
</div>
</render:endRender>

Your two variables (urlKey and iFrameUrl) are what give you extensibility. urlKey is defined in your page properties at design time. Then, you set the iFrameUrl in web.xml as follows:

   <context-param>
      <param-name>IFRAME_URL1</param-name>
      <param-value>http://www.developer.com/</param-value>
   </context-param>

Running our example in a portal, the resulting HTML is much simpler:

<div class="bea-portal-book-primary-content">
   <span class="bea-portal-theme-iframe2">
      <div style="margin-top:-5px">
         <IFRAME id="IFRAME_URL1"
                 NAME="IFRAME_URL1"
                 SRC=http://www.developer.com/
                 frameborder="0"
                 width="100%"
                 height="100%"
                 align="middle"
                 marginheight="0"
                 marginwidth="10"
                 scrolling="auto">
         </IFRAME>
      </div>
   </span>
</div>

And, your screen fills up the way you want it to, as shown in Figure 2:



Click here for a larger image.

Figure 2: IFrame Page Theme

A variation on this approach is to use a portlet and a backing file instead of the Presentation ID of the page. The portlet approach requires a urlKey preference with the URL as the value and the backing file setting the value into the request. The urlKey then is pulled from the request instead of from the servletContext. The backing file code can be written something like this:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.bea.netuix.servlets.controls.content.backing.
   AbstractJspBacking;
import com.bea.netuix.servlets.controls.portlet.backing.
   PortletBackingContext;

public class IframePathBacking extends AbstractJspBacking
{
   private static final long serialVersionUID = 1L;
   private static final String URL_KEY = "urlKey";

   public boolean preRender(HttpServletRequest request,
                            HttpServletResponse response)
   {
      PortletBackingContext pbc =
         PortletBackingContext.getPortletBackingContext(request);
      String urlKey = pbc.getInstanceLabel();
      request.setAttribute(URL_KEY, urlKey);
      return true;
   }
}

The portlet approach is better if you need to define some or all of your IFrame pages at run-time without restarting the application.

One last note. The 100% height setting does not work on Windows Vista (or at least on Vista Ultimate, which was discovered while writing this article), which should give you the excuse you need to upgrade to portlets as soon as possible. Meanwhile, you can work around this with fixed height (if all your apps can use the same size), a height preference in your portlet (if you went the portlet/backing file route) or a JavaScript function to dynamically set the IFrame height.

About the Author

Scott Nelson is a Senior Principal Consultant specializing in portals and other web complex web applications. He has built them both the "right" way and the "right now" way for companies ranging from one-person shops to Fortune 500© multi-nationals.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date