Accessibility

Flex Article

 

Using Macromedia Flex in a Portal Environment


Table of Contents

Comments

Technical Implementation

Rendering the Portlet’s User Interface

When a user requests a portal page, the portal asks the portlet container to generate the user interface for each portlet on the page. The portal creates the page by aggregating the fragments that the portlets generate, and returns the page to the client for the user to see.

To generate the user interface of a specific portlet, the portlet container invokes the portlet’s render() method. In GenericPortlet, the render() method dispatches the method call to the doView(), doEdit(), or doHelp() method depending on the portlet's mode. These methods typically execute user interface-related logic before dispatching the request to a JavaServer Page (JSP), which defines the markup for the portlet fragment.

Flex integrates seamlessly in this workflow. The major difference when using Flex to render the portlet user interface is that, instead of writing traditional HTML markup in the JSP, you simply embed the Flex application. The easiest way to embed a Flex application in a JSP is to use the MXML tag of the JSP tag library provided with Flex (see helloworld.jsp below). Alternatively, you can also manually code the HTML Object tag to embed the Flex application in the page.

Note: With the Flex JSP tag library, you can inline MXML (the Flex markup language) into a JSP, as opposed to pointing to an external MXML file.

The following example demonstrates a Flex-based Hello World portlet.

Listing 1: HelloWorldPortlet.java

package samples.portlet;

import javax.portlet.*;
import java.io.IOException;

public class HelloWorldPortlet extends GenericPortlet {

    public void doView (RenderRequest request, RenderResponse response)
            throws PortletException, IOException {

        response.setContentType("text/html");
        PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("/jsp/helloworld.jsp");
        rd.include(request,response);

    }

}

Listing 2: helloworld.jsp

<%@ taglib uri="FlexTagLib" prefix="mm" %>
<mm:mxml source="/jsp/helloworld.mxml"/>

Listing 3: helloworld.mxml

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" width="200" height="100">

    <mx:Label text="Hello World!"/>

</mx:Application>

Of course, you don't need Flex to display “Hello World!” The point is that this is all you need to create a rich user interface. At this point, you could modify helloworld.mxml to create a complete Rich Internet Application (using DataGrids, Trees, Charting Components, Drag and Drop behaviors, and so forth) rendered as a portlet in your portal application.

Accessing Data: Front-Controller Model

In the traditional portlet workflow, the portlet acts as a mini front controller: All the requests for processing actions and for rendering the user interface are routed through the portlet class using portlet URLs. The portlet then delegates the request to Model (for example, a JavaBean, an EJB, or a web service) and View components (for example, a JSP or a servlet). Portlet URLs are opaque URLs that the portlet container generates. There are two types of portlet URLs: action URLs or render URLs.

  • If the client requests an action URL, the container invokes the processAction() method on the target portlet. After processAction() has executed, the container triggers the render() methods for all the portlets on the page.
  • If the client requests a render URL, the container invokes the render() method on all the portlets on the page.

Even though Flex provides more efficient approaches—both from a user experience and a bandwidth point of view—to communicate with your portal back end, Flex-based portlets support this front-controller workflow. You can pass action and render URLs as parameters to the Flex application. The Flex application can then use these URLs to send requests to the portal, just like a traditional HTML-based portlet fragment would do.

The following example (Listing 4) demonstrates a Flex-based portlet using action and render URLs.

Listing 4: URLDemoPortlet.java

package samples.portlet;

import javax.portlet.*;
import java.io.IOException;

public class URLDemoPortlet extends GenericPortlet {

    public void doView (RenderRequest request, RenderResponse response)
            throws PortletException, IOException {

        response.setContentType("text/html");
        PortletURL actionURL = response.createActionURL();
        actionURL.setPortletMode(PortletMode.VIEW);
        request.setAttribute("actionURL", actionURL.toString());

        PortletURL renderURL = response.createRenderURL();
        renderURL.setPortletMode(PortletMode.VIEW);
        request.setAttribute("renderURL", renderURL.toString());
        PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("/jsp/urldemo.jsp");
        rd.include(request,response);

    }

}

Listing 5: urldemo.jsp

<%@ taglib uri="FlexTagLib" prefix="mm" %>

<mm:mxml source="/jsp/urldemo.mxml">
    <mm:param name="actionURL" value="<%= request.getAttribute("actionURL") %>" />
    <mm:param name="renderURL" value="<%= request.getAttribute("renderURL") %>" />
</mm:mxml>

Note: You can use the same parameter passing technique to pass any other contextual information to the Flex application: portlet initialization parameters, preferences, and so forth.

Listing 6: urldemo.mxml

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" xmlns="*"
    height="300" width="800" backgroundColor="#FFFFFF">

    <mx:Script>
        var actionURL: String;
        var renderURL: String;
    </mx:Script>

    <mx:Label text="{actionURL}"/>
    <mx:Label text="{renderURL}"/>

    <mx:Button label="Request Action URL" click="getUrl(actionURL)"/>
    <mx:Button label="Request Render URL" click="getUrl(renderURL)"/>

</mx:Application>

This example's portlet URLs workflow is primarily based on HTML clients operating in a traditional request/response model. The limitation of this model is that it is page-centric and that the user interface (in this case, the portal page) must refresh in response to each client request. This is both disorienting from a user experience point of view and sub-optimal from a bandwidth usage point of view. When using a rich client technology, that limitation goes away: you can communicate with back-end services in a service-oriented architecture (SOA) using XML over HTTP or SOAP without the need for refreshing the user interface. I discuss this SOA approach in the next section.

However, the ability for a Flex application to work with action and render URLs can sometimes prove useful. For example, a Flex application might use a render URL to ask the portlet container to change its window state.

Accessing Data: SOA Model

Flex clients can communicate with back-end services in a service-oriented architecture. Flex provides three different data services to accommodate the specific data access requirements of your application:

  • WebService Service: With this service, a client application can invoke SOAP-based web services.
  • RemoteObject Service: With this service, a client application can invoke methods on Java objects deployed in the middle tier without exposing the objects as web services. The Flex RemoteObject service takes care of the plumbing. You can choose between SOAP and AMF (a binary protocol over HTTP) as the communication protocol between the client and the server.
  • HTTPService Service: With this service, a client application can communicate with the server using XML over HTTP.

The following example demonstrates a Flex-based Stock Quote portlet using a web service.

Listing 7: StockQuotePortlet.java

package samples.portlet;

import javax.portlet.*;
import java.io.IOException;

public class StockQuotePortlet extends GenericPortlet {

    public void doView (RenderRequest request, RenderResponse response)
            throws PortletException, IOException {

        response.setContentType("text/html");
        PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("/jsp/stockquote.jsp");
        rd.include(request,response);

    }

}

Listing 8: stockquote.jsp

<%@ taglib uri="FlexTagLib" prefix="mm" %>
<mm:mxml source="/jsp/stockquote.mxml"/>

Listing 9: stockquote.mxml

<?xml version="1.0" encoding="UTF-8"?>

<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml"
    width="300" height="200"
    backgroundColor="#FFFFFF">

    <mx:WebService id="ws" 
        wsdl="http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl">
        <mx:operation name="getQuote">
            <mx:request>
                <symbol>{symbol.text}</symbol>
            </mx:request>
        </mx:operation>
    </mx:WebService>
            
    <mx:TextInput id="symbol"/>
    <mx:Button label="Get Quote" click="ws.getQuote.send()"/>
     
    <mx:Label text="{ws.getQuote.result}"/>

</mx:Application>

Security

Flex applications leverage the Macromedia Flash player sandbox environment. In this model, the client application can only communicate with the server that served it. You access the data access services described above (WebService, RemoteObject, and HTTPService) through a proxy servlet on that server. The proxy servlet intercepts requests to WebServices, HTTPServices, and RemoteObjects, redirects the requests appropriately, and then returns the responses to the client. You can secure access to the proxy servlet URLs through traditional J2EE security APIs or using a third-party security infrastructure, such as Netegrity SiteMinder.

Accessing the Porlet Session

Flex provides a session API that Flex client applications can use to access (set and get) attributes in the portlet session object.

Listing 10: The following example demonstrates a Flex-based portlet getting and setting a session attribute value.

<?xml version="1.0" encoding="utf-8"?>
	
<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml"/>

    <mx:RemoteObject id="sessionObj" source="servlet" showBusyCursor="true"/>

    <mx:HBox>
        <mx:TextInput id="fromSession" text="{sessionObj.session.result}"/>
        <mx:Button label="Get userName Session Attribute" click="sessionObj.session('get', 'userName')"/>
    </mx:HBox>

    <mx:HBox>
        <mx:TextInput id="toSession"/>
        <mx:Button label="Set userName Session Attribute" 
                   click="sessionObj.session('set', 'userName', toSession.text)"/>
    </mx:HBox>

</mx:Application>

Deployment Options

You deploy the Flex presentation server as a web application inside your application server. You can package Flex as part of the portlet web application, or you can deploy Flex as a separate web application. I have tested the examples in this article in these two configurations.