Categories
bdg Plumtree • BEA AquaLogic Interaction • Oracle WebCenter Interaction

Datamize vs. Plumtree: another silly software patent bites the dust

I usually don’t take much interest in legal matters, but I found this tidbit quite interesting and even a bit entertaining.

Two weeks ago, in an appellate court ruling, Chief Judge Vaughn R. Walker wrote that a patent infringement suit filed by Datamize against Plumtree Software should be essentially thrown out the window (by what’s called a summary judgment) based on the fact that the words “aesthetically pleasing” make Datamize’s patent invalid.

Intrigued? I was.

It turns out that Datamize filed patent 6,014,137 back in early 1997, right around the same time that Plumtree founders Joe McVeigh, Glenn Kelman and Kirill Sheynkman were dreaming up version 1.0 of the Plumtree portal and getting Plumtree Software, Inc. off the ground. The patent tries to lay claim to the act of “developing and maintaining user interface screens for multimedia kiosk systems” that can be “customized quickly and easily” while following “good standards of aesthetics and user friendliness.”

The appellate court’s main objection to the patent was the use of the phrase “aesthetically pleasing” because the definition of aesthetics has too much to do with deciding what’s beautiful and what’s not, which is far too subjective to be enforceable. In other words, as we all know, beauty is in the eye of the beerholder, even when it comes to kiosks!

I’m just happy to see another worthless software patent get thrown out for two reasons. One is that I have a particular distaste for overly broad and blatantly obvious software patents (e.g. the classic Amazon one-click ordering example, 5,960,411) and two is that I have sharp disdain for companies that try to use their patents to squeeze money out of the market-leader in their industry simply because they’re losing and acting like sore losers.

If you want to win in this business (or any business), make your product or service better, market it better, sell it better and support it better than your competitors. At least that’s our philosophy at bdg.

Categories
bdg Plumtree • BEA AquaLogic Interaction • Oracle WebCenter Interaction

bdg co-sponsors Odyssey+ADC 2005

I’m very pleased to announce that bdg has been selected by Plumtree as a co-sponsor of this year’s Odyssey+ADC, which is Plumtree’s User Conference and Advanced Developer Course.

For more information on Odyssey+ADC and to see the other sponsors, visit the Plumtree Odyssey+ADC partner page.

If you’re at all interested in Plumtree, I highly recommend that you attend Odyssey to get an understanding of the business and strategy side or the ADC to get the technical perspective.

Hopefully I’ll see you there!

Categories
Featured Posts Plumtree • BEA AquaLogic Interaction • Oracle WebCenter Interaction Software Development

Passing information between Plumtree portlets

This matter has been a subject of a great deal of debate among many of our customers, so I thought I would share my thoughts on the topic. What better place to do it than here on bdg’s Plumtree blog? 😉

This post expounds on the many methods you can use to pass information from one portlet to another or, in the more simple case, just store information temporarily for use later by a single portlet. There are at least three approaches I’ve found that accomplish this: the Plumtree Settings approach, the PCC/Adaptive Portlet approach and the backend-system approach. As you’ll see, there are also hybrids of these approaches that may work best for you, depending on your environment. I’m going to describe each of these in detail, but first, allow me back up a bit and explain the problem.

You’re building what Plumtree now calls an IAM (Integrated Activity Management) application. If you don’t think you are, check out this example (requires Flash). If you thought you were building an SOA (Service Oriented Architecture) application, well, a rose by any other name is still a rose, right? Basically, IAM, SOA and Composite Applications all mean the same thing to me, more or less. The way I define them is: you’re building an application that allows your end-users to achieve a business goal, say, an employee enrolling in his or her company’s health benefit plan. In order to pull this off, you need to build integration with several different corporate systems including perhaps getting an employee record from the HR system, deducting pre-tax payments from the employee in the company’s payroll system, and then registering the employee with an external site’s web services-based API to enroll him or her with the third-party benefits provider.

In order to pull this off in Plumtree, you’re going to need to design and build several portlets and perhaps a couple community pages or even multiple communities. Exactly how many portlets and whether to use one page, more than one page or one or more communities is one of the many decisions you’ll need to make in designing your application. All your decisions, BTW, should depend on how you want to structure your navigation and your screens to make your application usable. These decisions should not be ruled by what Plumtree is or isn’t capabile of doing but instead by how you’re going to make it easy (and even fun) for your employee to enroll in health benefits.

So, all that business aside, you’ve designed your application and it uses more than one portlet on, say, different communities. In keeping with our example, let’s say the first portlet allows the employee to confirm or update all his or her personal information and the second portlet asks the employee to pick amounts to be deducted from his or her paycheck for premiums and flexible spending. Now you’ve created at least two technical problems for yourself: 1) how do you get from the Employee Information community to the Payroll Management community and 2) how you get information (or state) from the Personal Information portlet to the Flex Spending portlet?

The answer to the first question is easy – use the pt:openerLink markup tag to create an URL that takes you from the Employee Information community to the Payroll Management community.

The answer to the second question depends on what type of state you need to pass, what form it’s in and how big it is. I’ll keep those things in mind as I discuss the three approaches to passing state.

Plumtree Settings approach

This approach works well if you have small bits of state that can be represented as strings and if you don’t mind having the page refresh (which it’s going to do anyway as you move from one community to another). To pull this off, you’ll need to use a User Setting, a type of setting that is unique for every user but that can be read (and set) by any portlet. First, you’ll need to settle on a name for your User Setting and then configure your Plumtree Web Service to “listen” for that setting. To do this, you need to open your Web Service editor, go to the Preferences page and then under where it says “Add specific preferences that you would like sent to this Web Service,” enter the name of your User Setting. You’ll need to do this in all the Web Services that need access to this information.

In our benefit enrollment application, the most likely thing we’ll need to pass is the employee ID, which shouldn’t be hard to represent as a string. Here’s what the code might look like in the Personal Information portlet:


PorltetContextFactory.createPortletContext(request, response).getResponse().setSettingValue(SettingType.User, "EmployeeID", employeeID);

And here’s the code for your Flex Spending porltet:


String employeeID = PorltetContextFactory.createPortletContext(request, response).getRequest().getSettingValue(SettingType.User, "EmployeeID");

PCC/Adaptive approach

The Plumtree Settings approach works well in this case, but what if you wanted to do this without a page refresh? Then I might suggest looking at two different adaptive portlet patterns: the Master-Detail pattern and the Broadcast-Listener pattern. These patterns do exactly the same thing, but with one major difference. The Master-Detail pattern assumes that you have no more than two portlets and that your two portlets are on the same page and the Broadcast-Listener allows you to send information to portlets on different pages and to broadcast from one portlet to many listener portlets.

Here’s how the PCC/Adaptive approach fits into our example: when the employee finishes updating his or her personal information in the Personal Information portlet, he or she is expected to click a button or link to indicate completion. The button or link needs to be tied to a javascript method that passes the employee’s ID to a PTHTTPGETRequest for the content (or a segment of the content) of the Flex Spending portlet using a querystring argument. When setting up a PTHTTPGETRequest, you’ll notice that the second argument is essentially a function pointer that allows this object to execute a callback when the response completes. All that callback function needs to do is place the content of the Flex Spending portlet into a div tag and you’re done.

I think Plumtree does a great job with all their Adaptive Portlet examples – you can literally copy and paste them into your portlet code and they just work. However, if you get stuck and need more help, feel free to post here or on portal.plumtree.com.

Backend System approach

So we’ve talked about how to pass a small piece of state from one portlet to another, covering the with-page-refresh and without-page-refresh cases in addition to the single-community/page and multiple-community/page case. But what about the case where your state is not quite as simple as a employee ID?

The first question I have to ask is, why are you trying to pass a lot of state? Isn’t the employee ID sufficient to go into the backend system and get whatever data you need? If the answer is no, then what form is your state in? Do you have a piece of text or an object? If you have a small piece of text, you can use either of the first two approaches: set it as a User Setting or URL-encode it and pass it around using Master-Detail or Broadcast-Listener. If you have a small object, you can serialize it and then Base-64 or UUEncode it and then use one of the first two approaches. But you need to be very careful. There are limits to the amount of data you can put on a querystring and limits to amount of data you can put in a header. These limits are not enforced by the HTTP spec, but the spec warns you about artificial limits on URL length based on web server implementations. Mark Nottingham, Senior Principal Technologist at BEA Systems, cautions against using headers larger than 2048 bytes in this post. Remember, all Plumtree Settings are passed back and forth between the portal and portlets as HTTP headers.

So you’re stuck with a somewhat bulky object, let’s say in our example, the entire employee’s record in a DTO, and so you’ve ruled out the first two approaches. Now what?

If you’re a traditional web programmer who’s new to Plumtree, you might have been thinking this all along – what about the HTTP session? Isn’t storing and passing state from page to page what sessions are for?

Sessions are great place for things like an employee record DTO, but in Plumtree, each portlet has its own session on the remote server. This means that you can put whatever you want in the session, but you’re not going to be able to share it with other portlets. Using the session also has interesting ramifications if you’re using Plumtree caching, but that’s the subject of another post.

So, what about the HTTP application? If you have a single remote server and all your portlets are using it, you can store objects, like the employee record DTO in the application, using a key consisting of the employee ID as follows (inside a Java servlet):


synchronized(this) {
this.getServletContext().setAttribute("com.bdgportals.iam.example.EmployeeRecordDTO" + employeeID, employeeRecordDTO);
}

Different portlets can now access this attribute, but you need to make sure that all your code that writes to this attribute is threadsafe.

Of course, this assumes that you’re using the same application server for all your portlets, which is not necessarily true, even for a single application (because you may be load-balancing your porltets across different application servers).

* * *

If there are other ways you’ve found to pass state between portlets, I’d love to hear about them via comments on this post.

Categories
bdg Plumtree • BEA AquaLogic Interaction • Oracle WebCenter Interaction Software Development

Washington DC Plumtree Training

bdg plans to offer a 5-day Plumtree Training Course in the Washington DC Metro Area starting on August 22nd. We’re combining our two most popular courses into one jam-packed week. The first three days will cover Plumtree Administration followed by two days of Portlet Development with the EDK. The course will be given in Herndon, VA about 10 minutes from Dulles Airport.

If you’re interested, you may download the complete syllabi from our Web site.

There are no pre-requisites for the Plumtree Administration course other than a basic understanding of Web applications. The Portlet Development course requires strong programming skills in either Java or .NET including Web programming concepts such as posting forms, retrieving parameters from the querystring and working with basic Javascript for form validation.

The price for this course is $500/day. You may attend the 3-day segment, the 2-day segment or the entire week.

There is a limit of 10 participants. You must sign up by Friday, August 12th and bdg must receive payment by Friday, August 19th. We now accept VISA/MC payments in addition to corporate checks and money orders.

To sign up, please send an e-mail to [email protected]. If you have any questions, please send us an e-mail or call us at 703 234 7910.

Categories
Plumtree • BEA AquaLogic Interaction • Oracle WebCenter Interaction Software Development

Plumtree RSS feeds of interest

If you like RSS and you like Plumtree, you might find the following links interesting:

This blog: http://feeds.feedburner.com/bdg/plumtree

Links related to Plumtree from del.icio.us: http://del.icio.us/rss/tag/plumtree

Plumtree’s Developer Feeds:

http://portal-img.plumtree.com/ptimages/rss/dev_additions_feed.xml
http://portal-img.plumtree.com/ptimages/rss/dev_articles_feed.xml
http://portal-img.plumtree.com/ptimages/rss/dev_samples_feed.xml
http://portal-img.plumtree.com/ptimages/rss/dev_docs_feed.xml
http://portal-img.plumtree.com/ptimages/rss/dev_releases_feed.xml
http://portal-img.plumtree.com/ptimages/rss/dev_events_feed.xml

And here’s one called “Code Sermon” that I’ve been listening to as a podcast. Even though it’s not related to Plumtree, it’s a good resource for software development best practices:

http://www.codesermon.org/portals/15/podcast.xml

Categories
bdg Plumtree • BEA AquaLogic Interaction • Oracle WebCenter Interaction

It’s official: bdg becomes a Plumtree partner

I am very pleased to announce that bdg has joined Plumtree’s Synergy Alliance program. Please check out our partner landing page on www.plumtree.com.

We’ve been “drinking the Plumtree Kool-Aid” since 1998, but now it’s finally official.

Categories
Featured Posts Plumtree • BEA AquaLogic Interaction • Oracle WebCenter Interaction Software Development

Query filters explained, at last

I can’t even begin to count the number of times I’ve been asked how to write a query filter in Plumtree. Yesterday, I had to write one for myself and lo and behold, I was confused. I’ve come to the conclusion that they’re just hard to write. Despite this, they’re incredibly useful when trying to lookup objects in the Plumtree API.

(Note: this post does not apply to writing portlets or other integrations. It’s only useful when writing Pluggable Navigation, PEIs, or other customizations to the UI.)

To use a query filter, you’ll first need access to a Plumtree user’s session. Let’s assume that you have one in the variable plumtreeSession and that it’s already connected as a user who has at least read-level access to some objects. This query will work for any object, but just for the sake of example, let’s use Groups. Also, I wrote this in Java, but it works almost exactly the same way in C#.

First you need to get an IPTObjectManager as shown here:

IPTObjectManager groups = plumtreeSession.GetUserGroups();

Next, we’ll build up the query filter, which is always an Object[][].

Object[][] filter = new Object[3][1];
filter[0][0] = new Integer(PT_PROPIDS.PT_PROPID_NAME);
filter[1][0] = new Integer(PT_FILTEROPS.PT_FILTEROP_EQ_NOCASE);
filter[2][0] = "Everyone";

Let’s go through that line by line. First of all, why did I choose 3,1 for my array dimensions? All query filters are 2D arrays. The first dimension always has three items:

    1. The name of the property on which you’re filtering
    2. The operator (equals, less than, greater than, etc.)
    3. The value of the property you’re evaluating

Since it’s an Object[][], we can’t use primatives, so we must box our constants in Integer objects because the constants themselves are primatives.

When using the Query method that supports a query filter, you also need to specify an ordering attribute. You can only order ascending, but you can order by up to three properties which will be applied in the order they are put in the array, as shown below:

int[] orderBy = {PT_PROPIDS.PT_PROPID_NAME, PT_PROPIDS.PT_PROPID_OBJECTID};

In the code above, I’m asking to order first by name, then by object ID. (Since no two names can be the same in Plumtree, this dual ordering doesn’t really make much sense, but oh well.)

Now, finally, it’s time to run the query:

IPTQueryResult group = groups.Query(PT_PROPIDS.PT_PROPID_OBJECTID + PT_PROPIDS.PT_PROPID_NAME, -1, orderBy, 0, -1, filter);

Let’s break down those parameters one by one. The first, PT_PROPIDS.PT_PROPID_OBJECTID + PT_PROPIDS.PT_PROPID_NAME is a bitmask of properties you want to include in your results.

The second, -1, means query all folders in the admin directory. (If you want to restrict your query to a single folder (and all folders below it), use the folder id here. If you want to query down two distinct folder trees, you’ll need to run two queries.

The third, orderBy is your ordering attribute(s), explained above.

The fourth, 0 is your starting row.

The fifth, -1 is the number of rows to return (-1 means all rows). This parameter, along with the starting row, can be very useful for pagination.

The sixth and final parameter is your beloved query filter.

We did it! Now that wasn’t so bad, eh? Iterating through the results set is trivial, so I won’t cover it here, but if you have you have a question, feel free to make a comment here or post on the developer forums.

Categories
Plumtree • BEA AquaLogic Interaction • Oracle WebCenter Interaction

Resources for running Plumtree on Oracle

Many of our customers run Plumtree on Oracle, for better or worse.

Despite it’s complexities and eccentricities, it’s been a good platform albeit not without it’s driver issues, configuration issues and other weirdnesses.

While doing some research on running Oracle over TCPS (TCP + SSL), I discovered two excellent Oracle resources in the blogosphere:

1. http://vanbortel.blogspot.com
2. http://tkyte.blogspot.com

Enjoy!

Categories
bdg Plumtree • BEA AquaLogic Interaction • Oracle WebCenter Interaction

bdg launches the PHP EDK 5.1

I am very pleased to announce that on Friday, 8 July 2005, bdg released the PHP EDK 5.1 to the Plumtree Code Share. Largely due to a Herculean effort on the part of Rich Weinhold, our resident PHP and Plumtree Guru, we were able to take the com.plumtree.remote.portlet.* package from zero to released in just three weeks.

We are offering this code up for redistribution and use under the BSD License, which is the standard for the Plumtree Code Share.

In order to access the code (for now), you’ll need to create a login on portal.plumtree.com. We are currently considering other distribution methods, such as SourceForge, and we’ll make an announcement should we choose to go down that path.

We look forward to seeing some PHP portlets start to emerge for the Plumtree platform. If you’re interested in developing a PHP portlet for Plumtree, let us know — we’d love to hear from you.

Categories
Plumtree • BEA AquaLogic Interaction • Oracle WebCenter Interaction Software Development

Server-to-server SSL with Plumtree

Two different customers of ours have recently experienced problems with server-to-server SSL and Plumtree, so I thought I would shed some light on the issue in the hope that it might help someone else who’s having the same problem.

The reality is that server-to-server SSL is no different with Plumtree than it is in any other environment, but it’s just poorly understood in general. Also, Plumtree makes server-to-server requests in places where you might not think to look. For example, you might think that only end users hit the Image Server, but in fact both the Portal Server and the Collaboration Server make server-to-server connections to the Image Server to pull down javascript files. (It’s possible that Content Server, Studio Server and the new Analytics Server make similar requests; I just haven’t run into problems with these products — yet.)

So, here’s the gist: in order for a server to communicate with another server over SSL, the requesting server needs to have the host server’s certificate installed in it’s keystore. Doing this is pretty straighforward and well documented. First, you need to export the certificate from the host server and copy it over to the requesting server. You can read about how to do this in IIS or how to do this in a JVM-based application server such as Weblogic or Tomcat.

After exporting the cert, you’ll end up with a .cer file that you’ll need to install on the requesting server. Say that server is a Tomcat instance on which you’ve installed Plumtree’s Collaboration Server. In this case, this set of instructions should help you get that part working.

One gotcha is that the name of the server in the certificate must match the name being placed in requests made to that server. For example, if the requesting server is making a call to https://images.mycompany.com, you need to have images.mycompany.com as the name of the server in its certificate.