Wednesday, December 22, 2010

Do Not Use Commas For Multi-Source JNDI

Here's a bit of fun with WebLogic JDBC configurations.  I ran into this issue after reading that p13nDataSource and  cgDataSource-NonXA should not be configured as multi-source. There were  some issues changing them to use the basic JDBC connection string and  when rolling back to the bad configuration the server went "Boom".  Since one purpose behind this blog is to share lessons learned, I just had to post this.

If you write your descriptors manually (as opposed to generating them using the WLS console) and put a comma-separated list of JNDI addresses like this:
<jdbc-data-source-params>
<jndi-name>weblogic.jdbc.jts.commercePool,
contentDataSource,
contentVersioningDataSource,
portalFrameworkPool</jndi-name>
<algorithm-type>Load-Balancing</algorithm-type>
<data-source-list>portalDataSource-rac0,
portalDataSource-rac1</data-source-list>
<failover-request-if-busy>false</failover-request-if-busy>
</jdbc-data-source-params>

so long as the first address resolves, it will still work. Sort of.  If you call this connection to do an update, only one node of the RAC instance is updated. Other wonderful side-effects include the server refusing to start sometimes.

The proper way to list the JNDI sources is one per node, like this:
<jdbc-data-source-params>
<jndi-name>weblogic.jdbc.jts.commercePool</jndi-name>
<jndi-name>contentDataSource</jndi-name>
<jndi-name>contentVersioningDataSource</jndi-name>
<jndi-name>portalFrameworkPool</jndi-name>
<algorithm-type>Load-Balancing</algorithm-type>
<data-source-list>portalDataSource-rac0,
portalDataSource-rac1,
portalDataSource-rac2
</data-source-list>
<failover-request-if-busy>false</failover-request-if-busy>
</jdbc-data-source-params>

(Props to Sandeep Seshan for locating the root cause)

Monday, September 13, 2010

Banishing Browser Caching in WebLogic Portal 10.3.2

I had a problem the other day where a user that was logged out still had their name showing on the screen. I thought the session wasn't being invalidated, but it was actually a case of the browser caching the page. Digging around, I found a solution that, when added to a backing file for the desktop to run during pre-render did the trick:
import com.bea.netuix.servlets.controls.content.backing
.JspBacking;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class NoCacheBacking implements JspBacking

{
public void dispose(){}
public boolean handlePostbackData(HttpServletRequest request,
HttpServletResponse response)
{

return false;
}

public void init(HttpServletRequest request,
HttpServletResponse response){}
public boolean preRender(HttpServletRequest request,
HttpServletResponse response)
{
response.setHeader("Cache-Control" ,
"no-cache, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control","no-store");
response.setDateHeader ("Expires", 0);

return false;
}
}

Sunday, September 12, 2010

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.

Friday, September 10, 2010

com/compoze/collab/log/LogEntryPrototype Error

While attempting to deploy an application built by someone new to WLP recently, I was getting a bit frustrated with a recurring error about "java.lang.NoClassDefFoundError: com/businessobjects/log/Logger" in the dev environment and deployment errors about com/compoze/collab/log/LogEntryPrototype in the integration environment.

Long story short (actually did it this time!), the issue was that the developer edited weblogic.xml by hand using an older WLP application as a guide and included the following:

wlp-collab-portlets-web-lib
10.3.2
10.3.2
false

Which is only available in a GroupWare-enabled environment. Once I removed that, everything was fine again.

Friday, September 3, 2010

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 Run\Open 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!

Wednesday, September 1, 2010

"No Global.app was found" error when starting a WLP Application

You'd think this would be a bad file error, but it wasn't. Turned out the portalDataSource connection pool had gone bad, preventing the desktop from being found or loaded.  Again, you'd think that a restart of the server would fix that, but it didn't. I had to un-deploy and re-deploy the connection pool before things started working again.

This was on WebLogic Portal 10.3.2. I haven't seen it before, but that doesn't necessarily mean it is restricted to that version.

Friday, August 20, 2010

Another Note on the WLP Content Presenter Portlet

Using the Content Presenter Portlet to add content will be unreliable if server affinity is not configured for the cluster. The portlet will reset itself mid-task. This may not be the case if session replication is turned on, though, as I ran across this in the early stage of the project. Still, something useful to be aware of.

Wednesday, August 18, 2010

Good Post on WLS 10.3 Start Up

I ran across a thread on LinkedIn that pointed me to an excellent article on IT on Guard dealing with a slow WLS start up issue.

Monday, July 12, 2010

LinkedIn Thread About Consulting Rates

This thread is a must-read if you are a consultant or ever thought of being one. Free LinkedIn membership required.

Thursday, June 24, 2010

One More Think About Inline Editing with WLP 10.3.2 Content Templates

In Inline Editing with WLP 10.3.2 Content Templates, I concluded that if something else came up I would blog it. Well, it did, so I will.

The shared library part went nice and smooth. To note the (semi-)obvious, the wlp-template-config.xml changes noted in the post must be done in the consuming application, not the shared application, as the consuming application always over-rides.

The part I forgot about was that you must create a role for editing the content or else only Admins will be able to do the inline editing.  I created an enterprise role named "homePageContentAdmin" for my first test, then granted that role update privelages on the content item. Once I did that, it worked properly.

As another sort-of-obvious note, this requires granting view privelages for anonymous or authenticated roles for other users to view the content.

Wednesday, June 23, 2010

Catching the Un-Catchable

I know it is bad practice to catch java.lang.NoClassDefFoundError.  Today, however, I did need a way to deal with it because I have this annoying habit of wanting everything else to work even when some non-critical piece is broken.

This case was a matter of a third-party security jar that would throw up rather than out when it could not find its properties file. No matter how many catches I had wrapped around the call to the method in the jar, the java.lang.NoClassDefFoundError would bubble up as a big render issue in the JSP.  I am only using this jar to get the user display name, so it isn't like my application is not secure if I don't have their name to make them feel special.

After several annoying an pointless approaches, I came up with the following (ugly-but-effective) solution:
try//the Security class relies on this property file but pukes if not found, so we test for it here
{
FileInputStream in = new FileInputStream("security.properties");
in.close();
}
catch(Exception e)
{
System.out.println("security.properties is missing from classpath");
return personInfo;
}
...go use the third-party class that depends on the file having proven it is there

This allowed the application to continue running and not falling apart at the header just because one file was missing. It is one thing to have a bug that is minor, another when that bug becomes something that users pick up the phone about.

Friday, June 18, 2010

Inline Editing with WLP 10.3.2 Content Templates

Carrying on from WLP Content Presenter Portlet Simplified, the next goal is to get the in-line editing from the sample application running because most clients think that is a cool feature and don't understand why it isn't available by default. Right now I am almost done, and wanted to blog the progress to date, even if the most important part won't be done until Monday...

There is a really (really, really) brief instruction in the official documentation to do this here.  I'm sure if you have been building content templates for years that document will be enough, just as I'm sure that if that were the case you won't be reading this (unless to make tsk-tsk noises at my ignorance). The files to import can be taken straight from there, which is:



  1. Display Template (Outer Template) – <WLPORTAL_HOME>\samples\applications\portalApp\ contentPresenterSampleWeb\samplePresenterTemplates\ inlineEditExamplePresenterTemplate.jsp

  2. CM Display Template (Inner Template) That Displays the Content – <WLPORTAL_HOME>\samples\applications\portalApp\contentPresenterSampleWeb\sampleCMTemplates\inlineEditExampleCMTemplate.jsp

  3. JSP File that Performs Other Work – <WLPORTAL_HOME>\samples\applications\portalApp\contentPresenterSampleWeb\sampleCMTemplates\saveNode.jsp



Now, the first time I tried this, I wanted my own paths and renamed everything. It didn't work. I'm sure I can rename them now, but at this stage the important thing is to get it working, with re-branding to the custom project being secondary.

The next step is to add these to the wlp-template-config.xml. Where the manual tells you to make your own, I find it much easier to simply go to the merged view and copy in the one from the shared install. While this may make a little more work for future WLP upgrading, it is worth it to me to save the time. With the file now in my project, I get the copy from the sample application and added the nodes to my own application that reference the files imported earlier. The relevant parts of the resulting file are below:
Under <content-name-space><name>wlp-content-presenter-single</name>:

<content-resource>
<name>htmlContent</name>
<default-template-uri>/portlets/wlp-content-publisher/templates/wlp-default/cm/wlp-default-resourceDefault.jsp</default-template-uri>
<view>
<name>Show</name>
<description>This is the detailed node view for simple HTML content in the Avitek Financial Intranet sample.</description>
<uri>/sampleCMTemplates/simpleShowView.jsp</uri>
</view>
<view>
<name>ShowEdit</name>
<description>This is the detailed node view with inline
editing for simple HTML content in the Avitek Financial
Intranet sample.
</description>
<uri>/sampleCMTemplates/inlineEditExampleCMTemplate.jsp</uri>
</view>
</content-resource>

Under <template-name-space><name>wlp-content-presenter-single</name>:

<view>
<name>Sample Single Item View with Inline Edit</name>
<description>This is the sample Content Presenter Display Template view for a single item that provides inline HTML editing.</description>
<uri>/samplePresenterTemplates/inlineEditExamplePresenterTemplate.jsp</uri>
</view>

Now, for this to work, you have to create a content type of named "htmlContent". I created this type with no parent and a primary property named "content" of data type binary.

I'm still testing to find out if the content needs to include ".html" as a suffix to the name.  And, yes, you can by-pass much of this "have to" stuff if you re-write everything, but the goal here is to get it deployed and have business users editing content today :)

I thought I had it with that, as I could then set the content in an instance of the Content Presenter portlet as a piece of content of the type htmlContent and see the Edit HTML button, but nothing happened on clicking it. Dang! Running it in FireFox (the project was targeted at IE, otherwise I would have started in FireFox), I found the disconcerting message "wlp dojo is not defined".

Ok, I haven't used the Dojo tookit yet. I have been building stuff by hand for so long, I just haven't had the need to use a pre-built JS framework, even one that is as highly praised as Dojo. So I'm not sure if I went about it the best way to get this fixed, but it was the fastest. I searched through the sample directory until I found dojo.js (in Windows, it was located at [WEBLOGIC_HOME]\wlportal_10.3\samples\domains\portal\servers\portalServer\tmp\_WL_user\portalApp\4ycmg9\beaext\dojo-0.4.3-ajax ). I also found that in inlineEditExampleCMTemplate.jsp, the path it was looking for was ${pageContext.request.contextPath}/dojo-0.4.3-ajax/dojo.js. I tried importing it directly to my project from OPOE, but it must be compressed or the path is too long, so I did a copy/paste to a temp directory and imported it from there.

And, viola! It worked.

Now all that is left is to make the web project into a shared library so that I don't have to turn off validation is my "real" project. If there is anything out of the ordinary with that process I will blog about it here.  Otherwise, go forth and edit.

Monday, June 14, 2010

REST Logout for WLP with JSP 2.0 EL

I used to create the log out URL like this:
String    webAppName    = request.getRequestURI().substring(1);
String    webAppPath    = request.getRequestURL().substring(0, request.getRequestURL().indexOf(webAppName));
String    restLogout    = webAppPath+webAppName.substring(0, webAppName.indexOf('/'))+"/bea/wlp/api/logout?invalidate_session=true";

Then, today I needed to have it in a Bighorn skeleton, so I came up with the following:
<c:set var="webAppName" value="${fn:substring(pageContext.request.requestURI, 1, fn:length(pageContext.request.requestURI))}" scope="application" />
<c:set var="webAppPath" value="${fn:substring(pageContext.request.requestURL, 0, fn:indexOf(pageContext.request.requestURL, webAppName))}" scope="application" />
<c:set var="restLogout" value="${webAppPath}${fn:substring(webAppName, 0, fn:indexOf(webAppName, '/'))}/bea/wlp/api/logout?invalidate_session=true" scope="application" />

With the URL in hand, you can now make the logout call:
function portalLogOut(restURL)
{
var xmlhttp    = null;
if (window.XMLHttpRequest)// code for IE7, Firefox, Mozilla, etc.
{
xmlhttp=new XMLHttpRequest();
}
else if (window.ActiveXObject)// code for IE5, IE6
{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}

if(xmlhttp.overrideMimeType)xmlhttp.overrideMimeType('text/xml');
if (xmlhttp!=null)
{
xmlhttp.open("POST",restURL,true);
xmlhttp.send(null);
}
}

Friday, June 11, 2010

IE OnResize Scripting

I ran into some ugliness recently setting an iFrame height dynamically where the script would run away on IE.  I found the answer at http://stackoverflow.com/questions/1500312/javascript-onresize-event, posted by Pim Jager.  The resulting combination of the resize and his event handling is as follows:
function getDocHeight()
{
var D = document;
return Math.max(
Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
Math.max(D.body.clientHeight, D.documentElement.clientHeight));
}

function setIframeHeight(frameId, offset)
{
document.getElementById(frameId).height = (getDocHeight()-offset)+'px';
}

var resizeIframeTimeOut = null;

var func = function() {setIframeHeight('boInfoViewIframe', 150);};

window.onresize = function(){
if(resizeIframeTimeOut != null) clearTimeout(resizeIframeTimeOut);
setTimeout(func, 100);
};

setIframeHeight('boInfoViewIframe', 150);

One note about resizing elements is that IE will resize again if your new size causes the document size to grow. That was a two hour lesson for me :)

Wednesday, June 9, 2010

Early Morning Security Ramblings

Posting it here for those that don't belong to LinkedIn or subscribe to Answers there:
Q:  Which Tastes Better for Security, Java or .NET?

Both this two languages are safe by security point of view with their own levels, but which one tastes better w.r.t your working experience?

A:  As others have noted, the security of the individual applications written in these languages depends on the development approach used. The next level from their is the application servers, which really depends on the app server vendor for Java and again back to the developer and the server admin. And, of course, the servers sit inside an operating system, which adds another layer of vulnerability. This is point where the earlier poster who noted that Microsoft is more often the target comes in to play. Microsoft is more often targeted, which increases the likelihood of someone trying to break in. However, the biggest threat is admins and/or policies that prevent keeping up to date on patches. Then there is the architecture as a whole, where there are points in the network, structure of the firewalls and accessibility of data. There are still plenty of admin servers that have the default log in credentials set.

Then again, the vast majority of real digital break ins come from the hacker knowing passwords in advance, which is an issue that is platform independent :)

Tuesday, June 8, 2010

JDBC BEA-001129

If you don't have a LinkedIn membership, this discussion should be enough reason to sign up (for the record, I did not provide the responses to this question):

Q:
I have a problem in production environment with WebLogic 9.2 mp3.We are using Multi datasource with Oracle 9i RAC two nodes. Database team have maintaince so they took out one node out of RAC. when one of the WebLogic instance associated with connection pool to that RAC node shown the following Warning message and could not start the instance.The multi datasource is configured with algorithm-type as "Load-Balancing"

<Jun 3, 2010 3:12:23 AM EDT> <Notice> <WebLogicServer> <BEA-000365> <Server state changed to STARTING>
<Jun 3, 2010 3:14:10 AM EDT> <Warning> <JDBC> <BEA-001129> <Received exception while creating connection for pool "DS2": Io exception: The Network Adapter could not establish the connection>

What are the recommandations to avoid this kind of problems when one of the RAC nodes down and the WebLogic server should have High Availability and scalable?

Any configuration parameters need to set for this??

A:

The way 9.2 mp3 works with RAC is that the multidatasource represents a pool of datasources so if one datasource is not available it will mark that down and use the other datasources configured in the multidatasource. WLS controls the failover, not RAC and this version does not use FAN or FCF.

I assume you have test on reserve set in the connection of all the data sources as that is required to use multdatasource. This parameter is at datasource->connection pool-> advanced

"could not start the instance" means that WLS did not come up??

If you are bringing up a WLS instance without the DB up you may want to set initial connections to 0


Wednesday, June 2, 2010

WebLogic Portal (WLP) Lost Samples in 10.3.2

Ran across a fun new quirk this morning. To make sure that source control has everything necessary for a build I maintain two workspaces and check the build in one after a check in from the other. There were two errors today. One was just weird, which is that the path of WEB-INF/src somehow became required. Annoying, but no big deal to check it in (and probably could have removed it from org.eclipse.wst.common.component and .classpath without causing an issue).

The quirky part was the second error, which was that it was unable to resolve the reference to "wlp-sample-widgets-web-lib" library. I went to the WebLogic shared libraries in preferences, and sure enough it wasn't there. Long story short, the sample widgets are not configured in a workspace unless it is added to a project in that workspace. The fix was to remove and then add the facet back in and then OEPE installed it into the workspace.

Thursday, May 20, 2010

WLP Content Presenter Portlet Simplified

I find the steps at Adding the Content Presenter Portlet to be a bit hard to follow as the content loops back and forth between the sample application and your application, and has frequent references to other documentation where the link goes to the start of the document rather than the specific section necessary for the task at hand. Having always liked reading and writing Quick Start guides, I am posting this one for the WebLogic Portal Content Presenter Portlet. I will later add how to incorporate the inline editing demonstrated in the sample application once I figure it out for myself.

So, first off, I will skip ahead to explain why I start the Quick Start where I do, which is that the templates we will want to add later spit compile errors in OPOE. For that reason, I am creating a separate Portal Web Application that will later be deployed as a shared library. If you don't need the templates from the sample  app,  you can just use your main application. If you don't know how to get that far on your own, see the WLP Quick Start and come back here. One other caveat is that you will need a DataSync project associated with the EAR project.

Once you have whatever portal web application that will be Content Presenter enabled chosen, you need to add the necessary facets. Unlike WebLogic Workshop for WLP, you aren't prompted to add facets when creating the project, so you need to go to the Project Properties after creating the Portal Web Application and add them.

The facet we care about is Content Presenter Framework. It does, however, have some dependencies. Fortunately, OPOE  lets you know what they are:

[caption id="attachment_435" align="aligncenter" width="450" caption="Adding Facets to WLP"][/caption]

So, rather than list them all out here, just select Content Presenter Framework under WebLogic Portal (Optional) and follow the errors for what to add. One note is that you will want Struts 1.2 instead of 1.3. Otherwise, the default version will do the trick.

To save time, I also selected the Sample Framework Components facet. You will eventually need to build your own log-in portlet, but this should do to get the Content Presenter working.

If you don't already have one, create a .portal file for your portal web application and add the Sample Login Portlet. You could add the Content Presenter portlet at this time, but unless you are only going to have one in the application you don't want to as it will be tied to the library instance. By adding it to new desktop  in the Portal Administration Tool (PAT), you will create a separate instance each time.

[caption id="attachment_445" align="aligncenter" width="450" caption="Create .portal File and Add Login"][/caption]

If you don't already have some content in your repository to display, once you deploy the portal application go create some as the Content Presenter doesn't seem to have the facility to create new content (or I haven't figured it out yet, but if you are reading this then you haven't either :) ).

With content ready, create a portal and desktop (again, if you haven't already) and add the content presenter portlet onto a page in the desktop (again, we do this here to have a specific instance):

[caption id="attachment_449" align="aligncenter" width="450" caption="Add Content Presenter Portlet to Desktop"][/caption]

You will also need to enable Disc on your desktop if you want the sample login portlet to work.

And...

[caption id="attachment_453" align="aligncenter" width="450" caption="Ta Daaaa!"][/caption]

At this point you can return to the standard documentation at Section 14.2.1, "Configuring the Content Presenter Portlet" for the rest of the steps as it seems to be back on track (for my taste) at that point.

Wednesday, May 19, 2010

WebLogic Portal (WLP) Content Presenter Portlet in 10.3.2

I hope to update this post with a vastly simplified approach to using the content presentation feature. Meanwhile, I do want to point out one thing that had me spinning my time for awhile. The URI for the templates TLDs in the sample files  cause a compile error. At first I thought it was because the URI changed from http://www.bea.com/servers/content/ui/jsp/templates to http://www.bea.com/tags/wlpapps/contentui/templates, so I changed it. Then I got run-time errors because some of the methods aren't in the new library. So I rolled back to the original values and just turned off validation for JSPs. That worked. So I am taking the approach of putting the templates into a shared library and taking the deployment hit rather than the development hit of having validations turned off for the main branch of the project. Later, I should create a build file that merges the projects at build time and drops the share library reference.

Tuesday, May 18, 2010

WebLogic Shared Library Reference

One of those items I always have to go look up the specifics for is creating the MANIFEST.MF file for WebLogic shared libraries.
Reference URL can be found here.

Thursday, May 13, 2010

Thursday, April 15, 2010

WebLogic Server Session Affinity and Serialization

I've had on my to-do list for awhile now to post about a recent investigation into a WLS  stuck thread issue I fixed. And I still will, as the way I got there is probably more useful to some than the end result. But, someone sent me a question that led straight to the solution today, so I thought I would post the email thread here to benefit my reader:
Q: Can we configure a cluster of WLS that is behind a F5 to use jdbc based persistence without the server affinity defined by load balancer?

A: By persistence, I would assume you mean user session. The limitation is on the applications deployed rather than WLS itself. All objects in session must be serializeable in order for WLS to properly manage persistence, regardless of whether it is database or file or in-memory persistence.

If your client has an issue where session data is lost unless server affinity is maintained it is because persistence has been manually turned off for the application. This is almost always done be developers or vendors when their application does not support serialization.

I've run across this situation twice this year. The first time was a sloppy, dishonest vendor (they clearly stated both that their product supported serialization and that they had never tested it...so I did, and it did not) that did not make their session objects serializable. The second time they had issues with a third party application that serialized PDF reports that were generated for a request and they had to turn off persistence to keep the disks from filling up every quarter.

Tuesday, March 30, 2010

Today's LinkedIn Answers-Inspired Rant

In response to the following question on LinkedIn today:
R&D time - how do folks manage it? - similar to Google's 20% research time - free form, scheduled, pros-con's - approved projects...looking for suggestions.

<RANT>
The old rule of thumb was that a senior IT professional should be engaged in deliverables only 65% - 85% of the time (depending on budget and the intelligence of management). The "unproductive" time was when R&D occurred, along with training.

These days, most R&D I see happening is when it is built into a project plan (either through creative padding or selling the ROI in advance and within a short time frame).

What little R&D I do see happening between projects these days is structured by people too far removed the deliverable level. As such, the time lines are too aggressive and the focus towards mindless repetition of simple examples rather than understanding the technology by stretching it to see what it is capable and where else it will apply.

</RANT>

Monday, March 29, 2010

An Alternative to RUP

I wrote this a long time ago on a Blackberry in a fit of frustration on a project...it still cracks me up

In an effort to reduce the strain on some clients who seem to have difficulty adopting the RUP process, I present to you an alternative methodology based on a model of what they’ve accomplished in the past and continue to strive for in the present.

First, schedule the project. Any project worth doing should have a deadline, and this needs to be set immediately after coming up with a catchy-yet-vague project name. Really import projects require the deadline to be set before the project is named.

Once a completion date is set, work backwards to build a full schedule. If the date is 6 months away, we know it takes as long to do QA as it did to code, so code freeze will be in 3 months. Everyone realizes that requirements need to be gathered, approvals gained, and designs considered, so let’s plan to do that at the same time. Just to make sure there is enough time to get it all done, give it 4 months. The math is clear: start the project last month.

Next, program something. Anything. We’ll find a use for it somewhere. Yes, we’ll give you requirements just as soon as we decide what the project is. And while you program, please create a design document to show that you used design. To make sure it is an accurate description, write it after you’re done coding. Also, please make all documents as boring as possible so others don’t waste valuable company time reading them.

Laugh maniacally to prove you are fully stressed. If you are stressed, then we have an accurate deadline. If you’re relaxed we obviously gave you too much time. If you’re just burnt out, you’re probably faking it. We have a perfect schedule, everything is on time, and if it’s not on time we can always change the requirements to be on time. We also reserve the right to change the requirements if we happen to feel like it. We’ll let you know critical changes during QA so you can add it in while you fix bugs.

Announce publicly the full functionality and the release date of the project. This should be done prior to QA. Also, to build public awareness and industry anticipation, announce that this service is availablet, program something. Anything. We’ll find a use for it somewhere. Yes, we’ll give you requirements just as soon as we decide what the project is. And while you program, please create a design document to show that you used design. To make sure it is an accurate description, write it after you’re done coding. Also, please make all documents as boring as possible so others don’t waste valuable company time reading them.

Laugh maniacally to prove you are fully stressed. If you are stressed, then we have an accurate deadline. If you’re relaxed we obviously gave you too much time. If you’re just burnt out, you’re probably faking it. We have a perfect schedule, everything is on time, and if it’s not on time we can always change the requirements to be on time. We also reserve the right to change the requirements if we happen to feel like it. We’ll let you know critical changes during QA so you can add it in while you fix bugs.

Announce publicly the full functionality and the release date of the project. This should be done prior to QA. Also, to build public awareness and industry anticipation, announce that this service is available now.

Test the application. Hey, we planned for QA early on, and we’re doing it! Be sure to only test the user experience, because this is all the public and our non-IT departments understand. If all of the data is wrong, that’s a production issue. The guys in production have nothing to do anyway, right?

Throw it away and try again. Nothing worked the way it was supposed to, no one uses the software, and we’ve identified a scapegoat (read “lead developer”). Bring in a consulting firm to fix it all. And remember, we have this process in place and we’ve used it before. It’s documented. So make sure the consultants follow this method.

Like any methodology, it needs a catchy acronym to be considered a real process, so lets look at what we do and see what it spells (we would never consider coming up with the acronym and then trying to make the process fit J):
Schedule
Program
Laugh insanely
Announce it’s finished
Test it
Throw it away.

So, there you go. As a viable alternative to the RUP process, I offer you…

SPLATT!

Thursday, March 25, 2010

Extra Required Step When Creating 10.3.2 WLP EAR

Wasted a good week until someone pointed out that OPOE does generates application.xml for exploded deployments (such as within the IDE) , but leaves it out when creating an EAR. So, when you create your WLP EAR project, you must check the "Generate application.xml deployment descriptor" box or the Portal Admin Tools will not get configured properly for the application.

[caption id="attachment_393" align="aligncenter" width="288" caption="You MUST Check This"]WLP EAR Wizard[/caption]

Tuesday, March 23, 2010

Example of Creating a User in Oracle DB for WebLogic

One of those things I ran across recently that I always forget between projects so I thought I would share here:

1 Set the Oracle Home

export ORACLE_HOME=/usr/lib/oracle/xe/app/oracle/product/10.2.0/server/


2 SQL Plus - Idle Instance $ORACLE_HOME/bin/sqlplus /nolog

3 Connect as SYS User

connect sys/welcome1@xe as sysdba;


4 Create the WEBLOGIC_PORTAL

User CREATE USER WEBLOGIC_PORTAL IDENTIFIED BY WEBLOGIC1;


5 Grant Roles and Permissions

GRANT CONNECT, RESOURCE,DBA TO WEBLOGIC_PORTAL;


6 The WLS install seems to expect a table named SYSTABLES, so you will need to create it:

CREATE TABLE SYSTABLES (TEMP NUMBER);

Friday, March 12, 2010

Creating a Local WLS 10.3.2 Domain

While setting up a new project this morning I was reminded of a somewhat counter-intuitive sequence when setting up a local environment (even with the simple Pointbase install). When you get to this screen:



Clicking Next will give you this warning:



Just click OK. The database isn't running at this time.

And, for those who haven't upgraded in a while and don't read the manual, you will want to click Run Scripts when you see this screen:



After the wizard completes, look for the create_db.cmd in the domain root and run it before starting the server. The first start, the server will have problems starting. Let it run until nothing is spit into the console anymore, then kill it and start it again. This time it should come up.

Thursday, March 11, 2010

Blue Screen Haiku

Ed note: This was posted on my old site in 2004. Every time you think we are making progress in computing, read this :)

In Japan, they have replaced the impersonal and unhelpful Microsoft error messages with Haiku poetry messages:

Your file was so big.
It might be very useful.
But now it is gone.
-------------------------
The Web site you seek
Cannot be located, but
Countless more exist.
--------------------------
Chaos reigns within.
Reflect, repent, and reboot.
Order shall return.
-----------------------------
Program aborting:
Close all that you have worked on.
You ask far too much.
------------------------------
Windows NT crashed.
I am the Blue Screen of Death.
No one hears your screams.
--------------------------------
Yesterday it worked.
Today it is not working.
Windows is like that.
---------------------------------
First snow, then silence.
This thousand-dollar screen dies
So beautifully.
---------------------------------
With searching comes loss
And the presence of absence:
"My Novel" not found.
--------------------------------
The Tao that is seen
Is not the true Tao-until
You bring fresh toner.
Stay the patient course.
Of little worth is your ire.
The network is down.
---------------------------------
A crash reduces
Your expensive computer
To a simple stone.
---------------------------------
Three things are certain:
Death, taxes and lost data.
Guess which has occurred.
---------------------------------
You step in the stream,
But the water has moved on.
This page is not here.
---------------------------------
Out of memory.
We wish to hold the whole sky,
But we never will.
--------------------------------
Having been erased,
The document you're seeking
Must now be retyped.
---------------------------------
Serious error.
All shortcuts have disappeared.
Screen. Mind. Both are blank.

Wednesday, March 10, 2010

ClassNotFoundException for PageFlowContextListener

I was a bit surprised to run across this issue for the first time in a 10.3.0 installation.  According to a post on OTN, it is caused by the actual Beehive library not added correctly in config.xml. However, when I ran across it, it was a different library (the sample projects) that were missing, but the same error occurred.

Go figure.

Tuesday, March 9, 2010

How to Check Your Google Listings

To find out what on your site is indexed on Google, go there and run the following search:

site:mydomain.com

Where "mydomain" is your domain name (change the . com if you have a different domain extension).

Click here for an example.

Sunday, March 7, 2010

Dynamic Log Location for log4j

I was really surprised that log4j doesn't have any facility to set the log file location with a relative path. Hard to build a portable application if you need to set the full value of a local path. And don't talk to me about config files, because that requires reading documentation, which is only read less than it is written.

So, if you use the standard log4j servlet approach to start your logging, you can weave in the following to set your path relative to your app:



org.w3c.dom.NodeList nodes = doc.getElementsByTagName("param");;
org.w3c.dom.Node node = null;//nodes.item(0);
org.w3c.dom.NamedNodeMap nodeMap = null;
for(int i=0; i < nodes.getLength(); i++)
{
    node = nodes.item(i);
    nodeMap = node.getAttributes();
    if(nodeMap.getNamedItem("name")
        .getNodeValue().equals("File"))
    {
        node = nodeMap.getNamedItem("value");
        outputFile = new File(getServletContext().getRealPath(node.getNodeValue()));
        outPutPath = outputFile.getAbsolutePath();
        outPutPath = outPutPath.replace('', '/');
        node.setNodeValue(outPutPath);
    }
}




Then you can set the log location to outPutPath.

Enjoy :)

Thursday, March 4, 2010

PCAnywhere and Your Firewall

I'm always forgetting what ports to set for PCAnywhere use. This time I thought I'd share the link I found on PCAnywhere ports at http://www.nthelp.com/NT6/pcanywhere_ip_port_usage.htm.

Though these days I'm using TeamViewer, which has no problem with firewalls though does get filtered by some networks admins.

Wednesday, March 3, 2010

Facelet Face Off on WLP

If you chose the Facelet aspect for your WLP project in 10.3.2, your portlets will use the "native" (i.e., WLP-only) portlet bridge rather than the "JSR-329" (i.e., crystal ball) bridge.  In case you need to reuse your portlets in another portal framework.

I haven't had time to try it out, but in theory one could write the .portlet file by hand and still get the best of both worlds.

Tuesday, February 23, 2010

WLP 10.3.2 ClassCastException in FacesContext

If you see:
java.lang.ClassCastException: com.bea.portlet.container.ActionRequestImpl

Try adding the following:
import javax.portlet.ActionRequest;

...
ActionRequest actionRequest = (ActionRequest) ctx.getExternalContext().getRequest();
HttpServletRequest httpRequest = (HttpServletRequest) actionRequest.getAttribute("javax.servlet.request");

Friday, February 12, 2010

Oracle Enterprise Pack for Eclipse 11gR1 Released

From the description on the product page, this is a new version of WebLogic Workshop, but without the WebLogic Portal tools. WLP has a new release due out soon, and Oracle is focusing on their other IDE, so this makes sense, even if it doesn't make old-time WebLogic developers feel all warm and fuzzy (or remembered).