Categories
Business Software Development

Twitter down again?

twitter-down-againWith the amount of downtime that twitter experiences, it makes me wonder whether or not Ruby on Rails is a viable alternative to PHP, Java, etc.

Is it the platform (RoR) or is it just bad code from Twitter? Or something else entirely?

Categories
Software Development

Why I. . . .

whyiA couple weeks ago I teamed up with college buddy, recent Kellogg grad and former PayPal/eBay product manager Chris Gregory to design and write a fun little Facebook application called WhyI.

He did the design and product management, my wife Allison did the logo design and I wrote the code. After a few weeks of hacking in Ruby on Rails (using RFacebook) and many hours of Skyping between Chris and Chris, I’m very pleased to announce that we’re done and the application is live on Facebook!

You can use the app to share five-word WhyI “taglines” about your passions on your profile. You can also ask other people to create taglines by asking them “Why do you?” questions.

If you have any questions or feedback on the application, please comment here or send a note to [email protected].

Categories
Software Development

Firebug in IE — No Joke!

I realize it’s close to April Fools’ Day, but this is not a joke: you can actually use Firebug in IE. Well, sort of. Joe Hewitt, the author of every developer’s favorite Firefox extension, has created a Javascript file that you can drop into your web pages and, voila, you get the debug console. And it works in IE. I realize this isn’t quite as good as the full blown Firebug, but it’s sure a lot better than the alternative:

<script>// <![CDATA[ alert('this sucks'); // ]]></script>
Categories
Featured Posts Software Development

Say hello world to comet

A couple of weekends ago I inflicted upon myself a quest to discover what all the buzz was about regarding Comet. What I discovered is that there is quite a bit of code out there to help you get started but the documentation around that code, and about Comet in general, is severely lacking. All I really wanted to find was a Comet-based Hello World, which as any developer knows, is the cornerstone of any programming language or methodology.

Since I couldn’t find one on Google, I ascertained that no Hello World exists for Comet and therefore I took it upon myself to write one.

For those of you who are new to Comet, the first thing you should do is read Alex Russell’s seminal blog post on the topic. At its core, Comet is really just a message bus for browser clients. In one browser, you can subscribe to a message and in another you can publish a message. When a message gets published, every browser that’s subscribed (almost) instantaneously receives it.

What? I thought clients (browsers) had to initiate communication per the HTTP spec. How does this work?

Under the covers, Comet implementations use a little-known feature of some web server implementations called continuations (or hanging gets). I won’t go into details here, but at a high level, a continuation initiates from the browser (as all HTTP requests must do) and then, when it’s received by the server, the thread handling it basically goes to sleep until it gets a message or times out. When it times out, it wakes up and sends a response back to the browser asking for a new request. When the thread on the server receives a message, it wakes up and sends the message payload sent back to the browser (which also implies that it’s time to send a new request). Via this mechanism, HTTP is more or less “inverted” so that the server is essentially messaging the client instead of vice-versa.

A few questions immediately pop into mind, so let’s just deal with them right now:

Why is this better than Ajax alone?

It boils down to latency and users’ tolerance for it. In the worst case, traditional web applications force entire page refreshes. Ajax applications are a little better, because they can refresh smaller parts of a page in response to users’ actions, but the upshot is that the users are still waiting for responses, right? A Comet-driven application has essentially removed the user from the picture. Instead of the user asking for fresh data, the server just sends it along as soon as it changes, given the application more of a “realtime” feel and removing virtually all perceived latency.

So are we back to client server again?

Sort of. Comet gives you the benefit of server-to-client messaging without the deployment issues associated with fat clients.

Can’t applets do this?

Of course they can. But who wants to download an applet when some lightweight Javascript will do the trick?

Why the name Comet?

Well, clearly it’s a pun on Ajax. But it’s not the only name for this sort of technology. There’s something out there called pushlets which claims to do the same thing as Comet, but which didn’t seem to catch on, I guess.

Back to the whole point of this post: my hello world. I pieced this example together using dojo.io.cometd and a recent version of Tomcat that into which I dropped the relevant parts of Jetty to provide support for continuations.

It’s finally time to say “hello world” to my hello world.

First off, download one of the more recent dojo builds that contains support for dojo.io.cometd. Drop dojo.js on your Java-based web/application server. (I used Tomcat, but you can use JBoss, Jetty, Weblogic, Websphere or any other web server with support for servlets.) Add this page in the root of your application:

<script src="js/dojo.js" type="text/javascript"></script>
<script type="text/javascript">//<![CDATA[
  dojo.require("dojo.io.cometd");
  cometd.init({}, "cometd");
  cometd.subscribe("/hello/world", false, "publishHandler");
  publishHandler = function(msg) { alert(msg.data.test); }
// ]]></script>
<input type="button" value="Click Me!" />

Without a cometd-enabled web server behind it, the above page does absolutely nothing.

So, to make this work, I needed to find a Java-based web/application server with support for continuations. I’m sure there are many ways to skin this cat, but I picked Jetty. You can get Jetty source and binaries if you’d like to follow along. Since all of our customers who embrace open source are lightyears more comfortable with Tomcat than they are with any other open source web/application server (ahem . . . Jetty), I decided to embed Jetty in Tomcat rather than run everything on Jetty alone. It’s all just Java, right?

Here I ran into a few snags. The maven build file for Jetty didn’t work for me, so I dropped everything in org.mortbay.cometd and org.mortbay.cometd.filter into my Eclipse project and just integrated it with the ant build.xml I was already using to build my web application. Here’s the relevant portion of my build.xml:

<javac srcdir="${srcdir}" destdir="${classdir}" debug="true" debuglevel="lines,vars,source">
<classpath>
<pathelement location="${jetty.home}/lib/jetty-util-6.0.1.jar"/>
<pathelement location="${jetty.home}/lib/servlet-api-2.5-6.0.1.jar"/>
</classpath>
</javac>

Once Jetty was essentially hacked into Tomcat, the rest was smooth sailing. I just wrote a JSP that dropped a “goodbye world” message onto the same old queue that I used in the last example, but I did so using server-side code. Here’s the JSP:

<%@page import="org.mortbay.cometd.*"%>
<%@page import="java.util.*"%>
<%
Bayeux b = (Bayeux)getServletContext().getAttribute(CometdServlet.ORG_MORTBAY_BAYEUX);
Channel c = b.getChannel("/hello/world");
Map message = new HashMap();
message.put("test", "goodbye world");
c.publish(message, b.newClient());
%>

This page does not produce any output of its own; rather, it just drops the “goodbye world” message on the queue. When you hit this page in a browser, any other browser listening to the /hello/world queue will get the message. The above JSP, along with the dojo page you created in the first step, should be enough to wire together two different flavors of Comet messaging: browser to server to browser and just plain old server to browser.

I’m curious 1) if this was helpful and 2) if you’d like to share what you’re doing with Comet with me (and please don’t say cleaning your kitchen).

Categories
bdg dev2dev Featured Posts Software Development

Everyone likes a friendly URL

As part of our BEA World strategy for this year, we’re revamping our corporate web site, http://www.bdg-online.com. You should expect an unveiling in the upcoming weeks.

While there will be some revised and some additional content, this is primarily an infrastructure upgrade, including moving to more powerful virtual hosts and upgrading the backend from ASP to ASP.NET (yes, I know, it’s about time).

One of things that really bugs me about ASP and ASP.NET is the failure to include built-in support for friendly URLs. By friendly I mean something that doesn’t end in .asp, .htm, .aspx or some other extension and naturally also doesn’t have a querystring (?foo=bar&boo=moo . . . etc.). For example, http://www.bdg-online.com/customers is a lot more friendly than http://www.bdg-online.com/customers.asp and definitely more friendly than something like http://www.bdg-online.com/content.aspx?p=/customers.

Java provides a nice facility for this in the form of servlet mappings. Since a lot of people are using MVC these days, you are probably going to set up servlet mappings anyway. Here’s an example from a sample web.xml file:

<servlet>
 <servlet-name>customers</servlet-name>
 <servlet-class>com.bdg-online.www.Customers</servlet-class>
</servlet>

<servlet-mapping>
 <servlet-name>customers</servlet-name>
 <url-pattern>/customers/*</url-pattern>
</servlet-mapping>

But what about ASP or ASP.NET? No one cares about ASP any more, so I didn’t bother to research that. But for .NET, I came up with a simple and elegant solution to the friendly URL problem. All you need to do is add the following code (or something like it) to your Global.asax.cs file:

protected void Application_BeginRequest(Object sender, EventArgs e)
{
 if (!Request.RawUrl.EndsWith("htm") &&
     !Request.RawUrl.EndsWith("css") &&
     !Request.RawUrl.EndsWith("ico") &&
     !Request.RawUrl.EndsWith("jpg") &&
     !Request.RawUrl.EndsWith("js") &&
     !Request.RawUrl.EndsWith("gif"))
 {
   if ("".Equals(Request.RawUrl) || "/".Equals(Request.RawUrl))
   {
     Context.Server.Transfer("default.aspx");
   }
   else
   {
     Context.Server.Transfer(Request.RawUrl + ".aspx");
   }
 }
}

You’ll note that I forward requests to the corresponding aspx page, as long as the request isn’t for static content (images, css, etc.).

Of course you also need to do two things:

  1. Configure an .aspx page for every friendly URL you want resolved
  2. Add a wildcard mapping in IIS for * (files without extensions) to the asp.net ISAPI filter

The process for #2 is a little involved. It’s also different for IIS 5 (XP) and IIS 6 (2003). I don’t feel like posting screen shots right now, but if anyone wants to give this a trial run and can’t figure out how to do #2, just e-mail me and I’ll walk you through it.

I just came up with this a couple of hours ago and I haven’t put it through much testing, so YMMV.

Categories
Software Development

Fedora Core 5 Support for Intel Pro Wireless (Centrino)

I bought a new Gateway MP6954 Laptop yesterday and decided to give Linux another go. This time I told myself: I’m not even going to attempt to run any Windows applications using Crossover Office or anything else. I’m just going to go with what works best: httpd, Tomcat, Java, PHP, Perl, Ruby, Oracle, MySQL, etc.

I installed Fedora Core 5 again (kernel build 2.6.15-1.2054_FC5smp) from the same CDs I used last time and it installed and came up cleanly, but with no wireless support. There is very little documentation about running Linux on my particular laptop model, but the wireless hardware (Intel Centrino/Pro Wireless ipw3945) is fairly commonplace and, according to the many sources I referenced, it’s “well supported” by Linux. Intel even offers a driver for it, but it’s a source-only distribution.

According to the install guide for the driver, I first needed to download and compile the IEEE 80211 subsystem. I later found out that in most cases, doing so is a bad idea. Compiling the subsystem (version 1.1.14) and then the driver (version 1.1.0) led to runtime incompatibilities — “Invalid Module Format” was the exact error. However, against the 80211 module included with the 2.6.15 kernel source, the driver wouldn’t even compile. So I was in a bind.

I needed to find an IEEE 80211 subsystem that was compatible with the 1.1.0 version of the driver. The answer was actually more simple than I thought. All I needed to do was upgrade to the latest FC5 kernel 2.6.17, install the latest kernel sources (yum install kernel-devel) and then build the driver from there. These are the instructions I followed.

And just like that, I had wireless support for my new laptop under FC5. Now only if I could get the sound card working . . . .

Categories
Software Development

Cracking open ISO files

I’ve been doing a lot of installing and re-imaging lately 🙁 and I’ve had to work with ISO files quite a bit. I haven’t found any Windows freeware that writes ISO files to CDs that actually work. However, I did discover that WinRAR has built-in support for extracting ISO files onto your hard drive.

It won’t, however, help you burn an ISO to a CDR, but hopefully with this info you might not have to!

(By the way, Mac OSX has native support for burning ISOs to CDs built into the operating system.)

Categories
Software Development

Adventures in desktop linux

I’ve had such a good experience using Fedora on several of bdg’s enterprise systems (SugarCRM, Subversion, Bugzilla, Vetrics, Connotea, etc.) that I thought I would give desktop linux a shot.

What a mistake.

Actually, it was a good learning experience. But still, a mistake.

First I download Fedora Core 5 (Bordeaux) using BitTorrent. My first problem was mastering the ISO files to CD. Windows has no native support for this (surprise) and for the life of me I couldn’t find a free product without filesize restrictions or other issues. Finally I remembered that I had a purchased a license for Sateira DropToCD some time ago, so I attempted to use that miserable excuse for a program. I tried to burn the five CDs at 24x (~10 minutes each) and my computer would not recognize them. The CD-Rs, once burned, were useless, yet Windows did not show any data on them nor a volume label.

I did a little Googling and then remembered that I needed to burn at 4x in order to get Fedora Core 4 (and Solaris x86 — another mistake) to work. So I tried that (at ~30 minutes per CD) and again, total failure. Finally I used a real operating system, OS X, running on my wife’s Mac laptop, to create the ISOs. (Of course OS X has built in support for ISO burning that works like a charm.)

After all this nonsense, I was finally ready to install FC5. So I backed up all my company files, music, photos and other stuff to my Western Digital 250 Gb external firewire drive and off I went.

I must say, there are some nice things about FC5. Unfortunately, it’s a short list:

  1. The installer, Anaconda, is awesome.
  2. The graphic design is beautiful.
  3. Wireless networking just works.
  4. Firewire just works.

So I was off to a running start. But here is where my problems began. At the top of my shit list is CodeWeavers‘ CrossOver Office. What a complete piece of garbage. From all their press releases, I was led to believe that they actually supported some useful Windows programs such as Office and, more recently, iTunes on various flavors of Linux. Don’t believe what you read. It’s all lies. Damn lies.

I started with Office 2003. That just failed utterly and completely. I wasn’t about to go back to Office XP, so I gave up on running M$ Office. FC5 comes with OpenOffice, which claims to support Word, Excel, etc. so I figured I would just use that.

Next I moved to iTunes. First off, installing it is a series of hacks and kludges. Upon following these ridiculous instructions, iTunes actually launched! But:

  1. All my playlists were gone, even though I repeatedly pointed iTunes to my backed up iTunes Music folder.
  2. The best feature in iTunes, search, didn’t work — the search box was grayed out.
  3. A basic feature — scrolling — was inconsistent and buggy.
  4. It crashed about 10 times before I completely gave up on it.

So now I had limited options. I decided that I would give up on purchasing DRM music through the iTunes store (and save about $500/yr in the process) and switch to Banshee, which claimed to be everything that iTunes was minus the music store.

Okay, so music is just music. But what about e-mail? I’m totally addicted to Outlook — the proof is my 1.5+ Gb .pst saved mail file. Without CrossOver Office running Outlook, I had to fall back on Evolution or Thunderbird. Access to saved mail, however, was a showstopper. To use my gi-normous .pst file in a non-M$ program, I needed to convert it to MBOX format. That proved impossible. Or at least not possible within my own personal constraints of time, patience and most importantly, sanity.

First I tried Thunderbird, because I remembered using its Outlook .pst conversion program. After struggling for a long time with compilation issues, linking issues/missing dependencies (including the wrong version of libstdc++) and segfaults, I finally got the ol’ T-bird working on FC5. But to my disbelief, the option to import a .pst was missing. After some Googling, I found out that Mozilla’s hairbrained implementation actually relies on MAPI, so you need to have Outlook installed and configured on the machine with Thunderbird in order to convert from .pst to MBOX.

I tried various other programs, including a useless dungheap called MailNavigator. I also tried hand-compiling a C program called libpst that was supposed to work and didn’t. I was beginning to think that my .pst file had been corrupted, but that was impossible because it was running fine in Outlook.

After all this nonsense, I used my wife’s laptop to download a DOS book disk with fdisk, deleted all my partition info, and now here I am back on Windows XP.

Lessons learned:

  1. Linux is not ready for the desktop, even if you’re a hardcore developer.
  2. Don’t believe anything CodeWeavers say about CrossOver Office. It just doesn’t work. Period.
  3. Windows, for all its faults, is actually not that bad. I can’t believe I just said that, but it’s true. 😉
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.