Portal Federation with WebLogic Portal WRSP Part 2: Advanced Techniques

Originally published at developer.com

In part 1 of this series you created your first federated portal utilizing WSRP. When the first WSRP spec was released, simply being able to render a portlet from one portal inside another with little or no additional development seemed really exciting. Like all new, cool technologies, once everyone had their gee-whiz moment, they started thinking about what else they wanted. As usual, they wanted a whole lot more, some of which is being addressed by the recently released WSRP 2.0 spec and the next Java portlet spec, JSR-286. Also as usual, neither development groups nor the WebLogic Portal product team waited for the next specification to start delivering the next generation of functionality. The over-arching theme of post-WSRP 1.0 requirements is how to go beyond sharing individual portlets, and begin integrating whole sections of portals together. Starting with version 9.2, the WebLogic Portal (WLP) began including both references on how to leverage existing capabilities as well as new APIs to allow enterprises to fully federate their portal assets. In this installment we’ll examine two of the major features that you can use to meet the expanding requirements you are bound to face once you get that first portlet reused through WSRP.

Federating Pages and Books

As all readers of developer.com are extremely intelligent I am certain that you have already concluded that if you can place one WSRP portlet in your portal, you can also place a whole page full of them in your portal. While this may be adequate for some portals, there are two scenarios that come immediately to mind (though there are bound to be others) where it would be better to have these portlets already grouped in the producer before integrating them into the consumer portal. One scenario is the division of labor provided wholesale importing of pages and books. Some portals are huge, containing hundreds of pages and thousands of portlets. Adding one or more pages to a portal administrator’s duties may simply not be practical. The other scenario is where the owners of the producer portal want to maintain a greater degree of control in how their portlets are combined no matter where they are rendered. Federated pages and books fulfill these needs easily.

WLP has made basic page and book federation extremely simple. So simple that we can just walk through the steps and understand why we are doing what we are doing.

In this walk-through we will use a simple taxonomy, keeping in mind that the more well-planned your taxonomy of portal assets is the easier your portal application will be to maintain. Once you have determined where your first federate page should reside, select the Portal perspective in Workshop, highlight the folder where you want your new page to live, and either select File > New > Other or use the CTRL+N shortcut to start the Workshop Wizard. In the first dialog, expand WebLogic Portal and select Page.

Figure 1: New Page Wizard

The wizard will have your highlighted path pre-selected for you and prompt you for a name for your page. Enter a name and click Finish and you now have a remote-able page where you can add your portlets. While it may seem odd at first to have a page with no book above it in Workshop, it will function the same as pages in the library of your Portal Administration Tool (PAT).

Figure 2: Remote  Page Layout

One nice improvement in WLP 9.2 is that the wizards generate the Definition Label of portal assets based on what you named them, rather than the old scheme of portlet_1, portlet_2, etc. While the portlet wizard prompts you for a title, the page wizard does not. With federated portals, some thought should be given to the value to use in the Title field of your remote pages (also for portlets and books). Unlike a Definition Label, the Title does not need to be unique as required by the API. However, consumer portal administrators will have no way of knowing the difference between three pages (or portlets or books) with the same name because they will not have the graphical view of them you do in Workshop or on your desktop. Consumer administrators can, however, change the Title field of a remote portal asset in the consumer portal library. Ah, but didn’t we say that one reason for federating pages was to leave the control with the producer? Like many areas of enterprise design and development, the approach needs to fit the situation. Deciding such trivial matters as portal asset titles in a in the early planning stages of a federated portal architecture will save time during the QA stage.

Adding a remote book to your producer portal starts with almost the exact same steps, the only difference being that you select the Book wizard rather than the Page wizard. Once your remote book is created, you then add pages as you would in a non-remote-able book. While it is somewhat counter-intuitive, remote pages can not be used in remote books laid out in Workshop.  Attempting to do so results in the remote page looking wrong in Workshop (the path to the page prints out where you would expect to see a layout). While this invalid configuration will build and deploy, the book with the remote page is not included in the published portal. If you have a remote page that you wish to be in a remote book, you will need to let the administrator of the consumer portal know. As with standard books, pages created in the book will be available in the PAT individually and there the administrator can assemble the way you could not in Workshop.

Note that if a portlet is consumed individually and later included in a remote page (or multiple remote pages are consumed containing the same portlet), a separate instance of the portlet is created on the consumer. If you know in advance that you will consume a portlet both individually and as part of a book or page, it is easiest to maintain your consumer portal by first placing the individual portlet before adding the remote page to your library.

Once the producer has published the remote pages and books, the consumer then needs to add them to the library. This is done in the same fashion as adding a WSRP portlet (as described in The Basics), only you select the Pages or Books section accordingly.

Figure 3: Remote Assets in the Portal Administration Tool

Oddly enough, the sequence of pages in a remote book is not maintained when consumed, so communication must be maintained between the producer developers and consumer portal administrators so that they can be arranged as desired in the consumer once the remote book has been added to the consumer desktop.

Passing Data Between Remote Portlets

Inter-Portlet Communication (IPC) is when an action in one portlet causes a reaction in another portlet. There is an example in the WLP documentation of how to have a receiver react to an Event fired by a sender. In this article we will take IPC one step forward and pass a run-time value from the sender to the receiver.

The important thing to remember when passing data from one remote portlet to another is that the request object is not shared between portlets. While mildly annoying, this makes perfect sense as the collection of remote portlets on a given consumer page may not necessarily be from the same producer. There are multiple solutions to get around this, and in the following example we will use a non-standard approach to illustrate that there are times when requirements remind us that best practices are guidelines rather than rigid rules. I promise to cover the best practices approach in the next installment.

For this example, we are going to assume that our requirement is to maintain the value in session once it has been set. This is mighty convenient for or fictitious development project as we can accomplish this with the least amount of work. First, we will create a Serializable object to hold our value, and use a session singleton pattern just to keep the example simple:

package common.example;

import javax.servlet.http.HttpSession;

public class SharedData  implements java.io.Serializable

{

private String          ipcValue1;

private static final long     serialVersionUID  = 1518508811L;

private static final String   SESSION_DATA_ID   = “sharedSessionData”;

public static SharedData getInstance(HttpSession outerSession)

{

if(outerSession.getAttribute(SESSION_DATA_ID)==null)

{

outerSession.setAttribute(SESSION_DATA_ID, new SharedData());

}

return (SharedData)outerSession.getAttribute(SESSION_DATA_ID);

}

private SharedData (){}

public String getIpcValue1(){return ipcValue1;}

public void setIpcValue1(String ipcValue1) {this.ipcValue1 = ipcValue1;}

}

Now we will create a page flow controller that uses our SharedData object to store a value submitted by a form. While a formbean is potentially redundant for our needs, we’ll cheat and use one anyways as the JSP wizards in Workshop make building a form using the form bean only a moment’s work. As the “Advanced” in the tile of this article assumes you already know how to build basic portlets, we’ll just look at the relevant parts of the code (you can always download the example application to see the full code):

public Forward begin(IpcDemo3FormBean form)

{

HttpServletRequest      outerRequest      = null;

SharedData              sharedData        = null;

outerRequest      = ScopedServletUtils.getOuterRequest(getRequest());

sharedData        = SharedData.getInstance(outerRequest.getSession());

if(form!=null && form.getIpcValue()!=null)

{

sharedData.setIpcValue1(form.getIpcValue());

}

return new Forward(“default”);;

}

The outerRequest reference may be unfamiliar ff you haven’t had to deal with request objects in WLP before. WLP breaks up the request object before providing it to portlets, scoping the request variables down to the portlet level. By using org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils you can gain access to the full request, which is what you need for another portlet to be guaranteed access to your object.

Finally, let’s create the portlet that will get this data and display it (or whatever else you want to do with the data):

public Forward begin(common.formbeans.IpcDemo3FormBean form)

{

HttpServletRequest            outerRequest      = null;

SharedData              sharedData  = null;

outerRequest      = ScopedServletUtils.getOuterRequest(getRequest());

sharedData        = SharedData.getInstance(outerRequest.getSession());

if(sharedData.getIpcValue1()!=null)

{

form.setIpcValue(sharedData.getIpcValue1());

}

return new Forward(“success”);

}

That seemed too easy. Actually, it is too easy. The most frequent cause of bugs in this type of IPC is where the receiver expects there to always be a value. Even if you have a fairly well-orchestrated work flow to get to the portlet with a value it can use, our users are frequently adept at finding ways around such good intentions and then getting mad at us for not anticipating it. In this particular example, we will handle the missing value in the JSP like this:

<netui:label defaultValue=”No IPC Value Set” value=”${actionForm.ipcValue}” />

Of course, this works only because all we are doing with the value is displaying it. Your mileage may vary, and so long as you remember that the value may be null, you will still not crash.

So, we place our page flows into portlets, build, deploy, go to the consumer PAT, add the new portlets (or a remote page containing both already) from the remote producer to the library, place it on our desktop and present users first with:

Then show them what they want:

In conclusion, once you have federated your first portlet, you will probably be asked to federate more portlets, then pages of portlets, and possibly books of portlets. Once you start consuming pages and books, you have essentially created a portal within a portal, and someone will want it to act that way, such as sharing data between remote portlets.  Now you can.

Shortly after you demonstrate your ability to all of the above, they will probably want you to have even more inter-portlet communication with more data, get some of that data you are putting into session out of the session once it has been passed, pass some of the data through hyperlinks instead of forms, and then navigate from one remote page to another by choosing an action in a portlet. That’s ok, though. We’ll cover that in part three.

Facebooktwitterredditlinkedinmail
© Scott S. Nelson

Portal Federation with WebLogic Portal WRSP Part 1: The Basics

Originally published at developer.com

WSRP stands for Web Services for Remote Portlets, a handy specification from the folks at OASIS that provides a standard for portal applications to share portlets between portals. Put another way, WSRP is the ability to produce an interface to useful functionality which can be consumed throughout your enterprise with little or no changes to existing code. Sound familiar?

Almost all of the latest versions of commercial and open source portal products support WSRP, though your mileage may vary based on the vendor.  The basic mechanism is the same as any old web service. The producer provides a WSDL that instructs the consumer on how to generate a SOAP request. The difference between web services and WSRP is that with a web service the developers of the consumer application next need to figure out how they will use the SOAP response where the WSRP consumer receives a response at the presentation level and all the consumer needs to do is decide where they will display it.  The portal frameworks abstract the heavy lifting and all that is required of developers is to configure the producer and consumer to achieve basic WSRP integration. In theory, this simplicity provides all an enterprise needs to reuse portlets across the enterprise “instamagiclly”. In practice, business requirements rarely let us get off the hook so easy.  In fact, once an enterprise begins to use WSRP, the requirements tend to get more and more complicated, which is why the WebLogic Portal (WLP) has evolved to provide more and more WSRP functionality with increasing ease of development.

When WSRP Makes Sense

WSRP is a technology that provides three benefits. One is reuse; another is performance, (though oftentimes using WSRP will provide only one these two benefits); and the third is the ability to release portlets asynchronously.

WSRP is not the only approach to achieving portlet reuse. Portlets can also be bundled into a WAR file and used as a shared library, or simply copied from one application to another.  Where reuse is the goal, WSRP is the solution of choice when the portlet is used in more than one portal.

Sometimes portlets are resource intensive. If a portal page contains a collection of portlets where system or network resources impact the usability of the portal, WSRP can provide a strategy where the processing is divided across servers to improve performance.

Portals provide the ability to aggregate access to applications. In many enterprises, these applications are owned and maintained by disparate groups where the coordination of release schedules can be difficult (if not impossible). Here, WSRP provides the advantage of allowing a portlet or group of portlets to be released independently of the main portal application.

The Best Way to Consume a Remote Portlet

In the WebLogic Portal, portlets are WSRP enabled by default since version 9.2, as shown below:

In fact, the notation in the .portlet file is only required if you are not offering your portlet as remote, as show by these two snippets:

<netuix:portlet definitionLabel=”simpleProducerA_1″ title=”Simple Producer A”>

<netuix:portlet definitionLabel=”nonRemoteExample_1″ offerRemote=”false” title=”Locals Only”>

In a WSRP implementation, the remote portal is the producer and the portal displaying the remote portlet is the consumer. The consumer gains access to the producer by registering the producer as a remote producer by accessing the producers WSDL. The WSDL is generated automatically by WLP and available as an address from the producers web application in the format of [server_address]/[web_application]/producer?wsdl. The example portal applications referenced in this article are named wsrpConsumer and wsrpProducer, with the portal web applications being named wsrpConsumerWEB and wsrpProducerWEB, which would make the producer’s WSDL address http://localhost:7001/wsrpProducerWEB/producer?wsdl. This WSDL simply defines key details about interacting with the producer, such as security:

<wssp:SecurityToken TokenType=”http://docs.oasis-open.org/wss/2004/01/oasis-2004-01-saml-token-profile-1.0#SAMLAssertionID”>

And where to find various services, such as registration:

<s0:port binding=”s3:WSRP_v1_Registration_Binding_SOAP” name=”WSRPRegistrationService”>

<s4:address location=”https://localhost:7002/wsrpProducerWEB/producer/wsrp-1.0/registration” />

</s0:port>

While the most basic of WSRP producers require 60+ lines of XML to define the WSDL, even the most complicated WLP applications will generate a WSDL for you. The only hand editing you may need to do is with simpler files such as wsrp-producer-config.xml and wsrp-producer-registry.xml.

Remote portlets are consumed in the producer with a proxy portlet, and WLP provides two ways to create a proxy portlet. One method is through the WebLogic Workshop IDE at design time. Defining a proxy portlet at design time requires providing an address to the producer in a .portlet file, which cannot be changed at runtime. Due to this drawback, this approach is not recommended in this article. If you want to see how it works in detail, you can follow the tutorial included in the WLP documentation.

The other method to define a proxy portlet is through the WLP Portal Administration Tool (PAT). To define proxy portlets in the PAT, you must first create a streaming portal. Streaming portals are database-driven rather than file-based (where users access the portal through a .portal file defined in Workshop). There are many considerations outside of WSRP in choosing between a file-based versus a streaming portal and are beyond the scope of this article.

To quickly illustrate the steps of creating a streaming portal and consuming a WSRP portlet we will use the naming conventions from our example applications as well as the existing assets in the example. For simplicity we will have both portal applications deployed to the same domain. With this in mind, here is the process to create a streaming portal and consuming a simple remote portlet:

With portal server running, navigate to http://localhost:7001/wsrpConsumerAdmin for your consumer portal’s administration console (or, with the Portal perspective open in Workshop, select RunOpen Portal Administration Console) and log in with the admin credentials. From the Portal Management page, create a streaming portal and a desktop based on the .portal file you created in Workshop. In the screen shot below, we’ve created a portal named “wsrp” with desktop named “default”.

Next, add your producer portal to your library by expanding Library and Remote Producers, then click on the Add Producer button. In the wizard, enter

http://localhost:7001/wsrpProducerWEB/producer?wsdl and click Search. Click on the Remote Producer in the search results, then follow the self-explanatory prompts to complete registration.

With your remote producer registered, click on the producers’ name, then Selected Portlets to access the Add Portlets button. The Add Portlets button will start a straight-forward wizard to add your remote portlets.

Finally, add the Hello Producer to your Consumer Desktop using the intuitive PAT, which will display as follows once completed:

In WLP 9.2, the process of placing your remote portlets must be repeated manually for each environment (typically, with varying names and number of environments, Test, Staging, and Production). Beginning in WLP 10.0, WSRP portlets can be included in propagation as other portal configurations are in earlier versions of WSRP (see Propagating Weblogic 8.x Portals for an introduction to portal propagation).

If you followed the naming examples in this article you can browse to http://localhost:7001/wsrpConsumerWEB/appmanager/wsrp/default to see the results.

Congratulations, you have achieved portal federation with WSRP!

Facebooktwitterredditlinkedinmail
© Scott S. Nelson

WSRP over HTTPS in WLP

Ever run across a problem that sounds real familiar, but you don’t remember all the details of the solution? Recently someone was telling me an issue they were having with WSRP where the WSDL when accessed over the HTTPS port still showed the HTTP end point.  That is when I experience De Ja Vue (I’v seen this before).

When using HTTPS with WSRP in WLP you must edit the wsrp-producer-config.xml in the producer application:

<!– This element describes the capabilities of this producer. Set the secure attribute to “true” if you require this producer offer any port over SSL. –>
<service-config>
<registration required=”true” secure=”true“/>
<service-description secure=”true“/>
<!– Set accepts-mime to true to more efficiently process uploaded files when the consumer is a WebLogic Portal. –>
<markup secure=”false” rewrite-urls=”true” transport=”string” accepts-mime=”false”/>
<portlet-management required=”true” secure=”true“/>
</service-config>

The bold is where the default value has been changed to true. My conclusion from this is that with WLP your WSRP portlets are either available over HTTP or HTTPS, but not both. I haven’t tested this theroy, however, as I have not yet worked on a WSRP project that was not over HTTPS.

Facebooktwitterredditlinkedinmail
© Scott S. Nelson

WLP Sessions and Porlets in Shared Libraries

Awhile back, I ran into an issue where session data was being lost between requests in a WebLogic Portal project. As it only occurred in a clustered environment, it was obvious that the value was not being persisted, even though persistence was set properly with

<wls:session-descriptor>
<wls:persistent-store-type>replicated_if_clustered</wls:persistent-store-type>
</wls:session-descriptor>

After much frustration, someone on the team ran across an additional setting for the session-descriptor node: sharing-enabled. In the case where a portlet is from a shared library, the persistence does not work unless sharing-enabled is set to true.

<wls:session-descriptor>
<wls:persistent-store-type>replicated_if_clustered</wls:persistent-store-type>
<wls:sharing-enabled>true</wls:sharing-enabled>
</wls:session-descriptor>

In hindsight, this behavior makes some sense, in that most portlets that are distributed as shared libraries by vendors do not require session values. However, in the case where a shared library is created by an application team to reuse portlets across portals where WSRP is not practical, the need to share sessions may arise, and now you know how to fix it.

For other deployment descriptor options, see http://download.oracle.com/docs/cd/E12840_01/wls/docs103/webapp/weblogic_xml.html

Facebooktwitterredditlinkedinmail
© Scott S. Nelson

Useful Google API Article Series

Developer.com has a series on Google integration with PHP at http://www.developer.com/services/article.php/3680076.

I suppose this would be a good time to grouse that they never gave my two series (WSRP and POI) a page of their own 🙂

Between the York District Boy Scouts  Spring Wateree Campout and a cold, I have not been posting much lately, so this a is re-tread from Frequently Unasked Questions.

Facebooktwitterredditlinkedinmail
© Scott S. Nelson