Categories
Activism & Politics Elections 2016 Featured Posts Lessig for President Software Development

Lessig 2016: The Internet’s President

On the heels of Larry Lessig’s historic announcement of his Referendum Candidacy came another newsworthy item: Jimmy Wales announced that he is chairing LECEC, the Lessig Equal Citizens Exploratory Committee, which consists of me and scores of other volunteers and staffers working at a breakneck pace to make Lessig’s nascent campaign a reality.

At first blush, the Wales announcement might seem like a footnote on an afterthought, but I read something very different into it. Something that reminds me of Paul Revere. But no British are coming this time. Instead, Wales penned these nine simple words and so began the largest, most peaceful, and most desperately-needed democratic revolution in human history:

When you light up the Internet, anything is possible.

–Jimmy Wales, Chairman emeritus, Wikimedia Foundation

That’s right, Internet: He may have understated it a bit, but Jimmy Wales just asked us to mobilize and elect Lessig in 2016.

Let’s face it: No one has been kinder to the Internet than Larry Lessig. In the twenty-plus years I’ve followed his work, he’s rallied against outrageous software patents, fought copyright takedowns, drafted the contracts that legally protect and enable “open source” software (which powers most of the Internet), started the Center for Internet and Society at Stanford, fended off aggressive corporate and government entities in his quest for net neutrality and, naturally, he’s spoken at TED. Four times.

Larry is and has been the Internet’s dedicated steward for the better part of his career. His body of work enabled the Internet to become what it is today: a loosely-coupled network wherein heterogeneous data, applications, and systems play in an ecosystem with minimalist governance atop a tiny handful of protocols and specifications.

No one’s been a bigger advocate for the open internet than Larry Lessig.

–Cenk Uygur, The Young Turks

If Vint Cerf, Donald Davies and Bob Kahn are the “fathers of the internet” and if Aaron Swartz was “the internet’s own boy,” then Lessig is the Internet’s uncle.

What better way for the Internet to say thanks to Uncle Larry than to use its enormous catalytic power to hack him into the White House?

And who better to do the hacking than the hackers of our own generation? We were born into a world with basically no connectivity to information, services or people. Today, we have access to pretty much every other connected person and all of the world’s public digital information (so long as we can keep our phone batteries alive).

As software developers in the mid-90s, we didn’t just witness the explosive, hockey-stick growth of the commercial internet; we actually built huge swaths of that reality ourselves. My peers and their peers built out the data centers and server racks, the gateways and firewalls, the routers and switches, the firmware and software platforms, the web servers and middleware, the web services and mobile applications — that drew billions of people into a web of inter-connectivity, knit together so tightly that a single thread can be spun half way around the world and back again in just seconds.

As my peers and I built PayPal and Yahoo! and Oracle and Amazon and Google — and the millions of companies that weren’t as fortunate — we didn’t realize this tremendous side benefit:

We created the most powerful agent of social change in the history of humankind.

In 2012, when Lessig and Swartz “lit up” the internet to defeat the SOPA and PIPA bills, scores of sites — including Wales’ Wikipedia — “went dark” in protest of these hair-brained bits of legislation.

That was the battle. This is the war.

Today we are at war with a much darker evil, far more insidious than the foiled attempts to reign in and regulate the internet. Our government has become the handmaiden of the “funders” — billionaires, PACs, multinational corporations, labor unions and other special interests — and we are fighting to restore a representative democracy back to the citizens to whom it was promised.

We are fighting “the root of all evil,” the darkest evil with the deepest pockets. And we’re already in way over our heads.

But now, Jimmy, we’re gonna light up the Internet.

Darkness cannot drive out darkness; only light can do that.

–Martin Luther King, Jr.

If there exists one light great enough to drive the corrupting influence of money out of DC, it’s not burning torches and gleaming pitchforks. Rather, it’s the glow of a hundred million mobile phones, tablets and laptops, mobilized under a single, peaceful mandate. With every Facebook like, every share, every re-tweet, every blog post, every comment, every volunteer effort and every donation, the light spreads and burns ever more strongly, driving out the darkness.

Wales said:

When you light up the Internet, anything is possible.

I say:

Lessig for President in 2016.

Wales said anything. And it’s our job — as denizens of the Internet — not to prove him wrong.

Categories
Business Featured Posts Software Development

On Open Letter to the Java Community

java_oracleIn the wake of the Sun acquisition by Oracle, the much-lambasted Oracle vs. Google lawsuit over Google’s alleged JavaME patent infringement, and the rumblings I’ve been hearing at Oracle Open World / JavaOne / Oracle Develop 2010, I have a message to the Java community:

Quit your bitching and moaning and start doing something productive!

Now that I’ve offended all the Java fanboys/girls out there, let me explain:

  1. Why I’m qualified to give you all one big collective kick in the ass, and
  2. Why this collective ass-kicking is coming from a place of love, not hate.

My first experience with Java was in 1994/95, when Stanford started switching its Computer Science curricula from C/C++ to Java. After struggling with memory management, segmentation faults, horrific concurrency problems and the other ways I kept shooting myself in the foot, Java was a breath of fresh air. My first corporate experience with Java was working as a summer intern for JavaSoft (a former subsidiary of Sun) in 1997 porting Patrick Chan’s Java 1.0 sample applications (remember Hangman?) from JDK 1.0 to JDK 1.1.

I went on to join Plumtree. Originally, they were a Microsoft darling. I helped lead the charge to switch them from COM/DCOM, ASP 1.0 and SQL Server to Java and Oracle.

In 2002, I started a Plumtree-focused consulting firm, helping 50+ customers install, maintain and grow their Plumtree deployments. In all but a precious few of those accounts, I wrote all of the code in Java/JSP.

Since about 2008, we’ve been using Ruby on Rails for most of our software. When Rails hit the scene, I had a similar “breath of fresh air” moment similar to when I first encountered Java.

But this letter is not about Ruby or about Rails; it’s about Java. A language I’ve used since it’s very first iteration in 1994/95 and up to the present day. A language wherein I’ve written at least half a million lines of code, most of which still run in production today inside Plumtree/AquaLogic User Interaction/WebCenter Interaction, at major customer sites in the corporate world and in the federal government.

So, fast-forward to today, this is what I’m hearing about Java, in a nutshell:

  1. Oracle’s going to kill/close-source/fuck up Java
  2. Life’s not fair!
  3. Blah blah blah

Twitter _ Jock Murphy_ @oracle I love Java, I do .All of this bitching and moaning starts right at the top with Java grandfather and CEW (Chief Executive Whiner) James Gosling, who is showing incredibly poor leadership, lousy judgment and massive immaturity with his totally irrelevant, outdated and hateful anti-Oracle bitch-fest.

Twitter _ Marcello de Sales_ Solaris 11 to be contI’ve heard people whining about everything around them that’s not running on Java: mobile applications, web sites, conference tools, Twitter, Facebook, etc.

Twitter _ Paweł Szymczykowski_ @dendro Awesome thaI even saw someone complain on Twitter that the Black Eyed Peas, who Oracle paid an undoubtedly handsome sum of money to entertain your sorry asses last night, gave a shoutout to Oracle and not “The Java Community.” Seriously? Give it a rest, folks!

There are lots of choices of development stacks and people are free to choose the one that works best for them.

Embrace that freedom; don’t fight it.

And the word Oracle doesn’t mean “database” anymore. It is an umbrella term that could refer to thousands of different products.

Let’s take a look at some of the advantages of Oracle owning Java.

With respect to OpenWorld, the Java Community got:

  1. Your own conference with around 400 sessions
  2. Your own tent
  3. Your own street closure (Mason Street)
  4. Invited to OTN Night, one of the best parties at OpenWorld

More importantly, with Oracle Corporation, the Java community gets:

  1. Cemented into the infrastructure of nearly all of Oracle’s products, meaning that nearly all of their customers — most of the Fortune 1000 — are now Java shops (if they weren’t already)
  2. Stability, stewardship, thousands of really bright engineers and nearly unlimited resources
  3. One of Corporate America’s most powerful legal teams backing you up
  4. A secure and promising future, including a just-announced roadmap for JDK 7 and 8

And, with all that being said, guess what?

Java is still open source.

Do you know what that means?

Let me answer that question with another question: what brilliant phoenix rose from the ashes of the debacle that was the AOL acquisition of Netscape in 1998?

It was Firefox, a free, open source-based browser that literally revolutionized the massively screwed up browser market and gave the dominant browser (IE 5, and later, IE 6) a true run for its money. From wikipedia:

“When AOL (Netscape’s parent) drastically scaled back its involvement with Mozilla Organization, the Mozilla Foundation was launched on July 15, 2003 to ensure Mozilla could survive without Netscape. AOL assisted in the initial creation of the Mozilla Foundation, transferring hardware and intellectual property to the organization and employing a three-person team for the first three months of its existence to help with the transition and donated $2 million to the foundation over two years.”

IBM’s symbiotic relationship with Eclipse is another great example.

So, dear Java community, to ensure your own survival, please, in the name of Duke, stop complaining and start thinking strategically about how you can “pull a Firefox” here. You’re all brilliant engineers, so start putting all the effort you’re wasting in complaining toward something productive.

I love you all and I love all your passion and energy, but I hate your bitching — use that energy to go save the world, Java style!

Categories
bdg Software Development

Shameless Self-Promotion

panel_picker_voteAt last year’s SXSW I said to myself: “Self, you need to be speaking at this conference next year.”

Help me fulfill my self-fulfilling prophecy and please take a minute to vote for one (or both) of my proposed talks! Unlike the SXSWi Web Awards last year, you don’t have to vote every day — once is plenty.

The first is a solo presentation on the future of RSS.

The second is a panel discussion on whether it’s better to have one horizontal social network like Facebook or loads of smaller, niche social networks.

Thanks for your support.

Categories
Software Development

Chris Bucchere Speaking at the NovaRUG on June 18th, 2008

Calling all local Rubyists! I’m speaking about modular page design in Ruby on Rails at tomorrow night’s NovaRUG. The title of my talk is “To Portal or Not to Portal: How to Build DRY, Truly Modular Mashups in Rails.”

The meat of my talk is going to come from these two recent blog posts:

Modular Page Assembly in Rails (Part 1)
Modular Page Assembly in Rails (Part 2)

I’ll be followed by Arild Shirazi of FGM giving a presentation entitled “CSS for Developers.”

Get all the details here.

P.S.: Free pizza!

Categories
Software Development

Modular Page Assembly in Rails (Part 2)

In Part 1, I explained how you can develop clean, DRY and encapsulated MVC code that allows for completely modular page assembly in Ruby on Rails.

In this follow up post, I explain how you can use a combination of layouts and content_for to apply title bars and consistent styles to your page components (or modules or portlets, or whatever you want to call them).

The code here is easy to follow and it pretty much speaks for itself. It consists of two layouts (which I called aggregate and snippet), a sample controller and two sample views. Let’s start with the controller for one page in your site that, say, aggregates a couple of modular page components together to show a nice view of company information.

Controller code (app/controllers/company_controller.rb):

def index
  render :action => 'index', :layout => 'aggregate'  
end

This controller simply delegates the rendering of the page to the index.html.erb view and tells Rails to use a layout called aggregate.

Now let’s inspect the view.

View code (app/views/company/index.html.erb):

<% content_for :left do %>
 <%= embed_action :controller => 'company', :action => 'company_list' %>
 <%= embed_action :controller => 'feed', :action => 'feed' %>
<% end %>

<% content_for :center do %>
 <%= embed_action :controller => 'company', :action => 'detail' %>
<% end %>

<% content_for :right do %>
 <%= embed_action :controller => 'home', :action => 'sponsors' %>
<% end %>

This view defines three content regions, with the end goal being to create a page with three columns of “portlets.” The left column contains two portlets: a list of all companies (company_list) and a news feed (feed). The center column contains a company detail portlet and the right column contains a portlet with information about sponsors. (Note that the portlets come from three different functional areas of the site, so they’re decomp’d appropriately into three different controllers.)

Now, let’s take a look at some layout magic.

Here’s the aggregate layout (app/views/layouts/aggregate.html.erb):

<table class="main" cellspacing="0" cellpadding="0">
  <tbody>
    <tr>
      <td id="column-left" class="column" valign="top">
        <div id="region-left" class="region"><%= yield :left %></div>
      </td>
      <td id="column-center" class="column" valign="top">
        <div id="region-center" class="region"><%= yield :center %></div>    
      </td>
      <td id="column-right" class="column" valign="top">
        <div id="region-right" class="region"><%= yield :right %></div>
      </td>
    </tr>
  </tbody>
</table>

I chose a table (yes, I still use tables) with three divs in it, one for each region of modules, but you could use pure divs with floating layouts or any other approach.

The three content regions, left, center and right, match up with the three content sections defined in the index view above using content_for. In case this isn’t obvious, when the layout encounters a page-level definition of a content region in the view, it renders it. If there is no definition for a particular region, the containing column will just collapse on itself, which is the behavior we want.

This is a slight digression, but note how I used CSS classes to identify the columns and regions in a general way (using classes) and a specific way (using ids). This allows me to style the whole module-carrying region with CSS using table.main as my selector, all the columns using table.main td.column as my selector or all the regions using table.main td.column div.region as my selector. I can also pick and choose different specifc areas (e.g. table.main td.column#column-right) and define their style attributes using CSS. As you’ll see in a minute, I can write CSS selectors to say if module A is in the left column, apply style X but if module A is in the center or right column, apply style Y. Pretty cool.

Now, let’s explore the module layout. (Note that I’ve been calling page snippets portlets, modules or components, pretty much interchangeably. I think this illustrates that it doesn’t make a difference what we call ’em — e.g. portlets vs. gadgets — the concept is fundamentally clear and fundamentally the same.)

Module layout (app/views/layouts/snippet.html.erb):

<div id="<%= yield :id %>"><%= yield :id %>" class="snippet-container">
  <div class="snippet-title"><%= yield :title %></div>
  <div class="snippet-body"><%= yield :body %></div>
</div>

This layout expects three more content regions to be defined in the view: id, title and body. Here are the matching content regions from one sample view (for sponsors) — for brevity’s sake, I didn’t include all the views.

Sample module view (app/views/home/sponsors.html.erb):

<% content_for :id do %>sponsors<% end %>

<% content_for :title do %>Our Sponsors<% end %> 

<% content_for :body do %>
Please visit the sites of our wonderful sponsors!
<% end %>

Now, because of some nicely-placed classes and ids, I can once again use CSS selectors to give a common look-and-feel to all portlet containers (div.snippet-container), portlet titles (div.snippet-title) and to portlet bodies (div.snippet-body). Of course, if I want to diverge from the main look-and-feel, I can call out specific portlets: div.snippet-body#sponsors.

If I really want to get fancy, I can use CSS selectors to select, say, the sponsor portlet, but only when it’s running in the right column: table.main td.column-right div.snippet-container#sponsors.

So, in summary, using layouts, content_for and some crafty CSS, I can create a page of modules that can be styled generically or specifically. Combine this approach with what I described in Part 1, and you can “portal-ize” your Rails applications without using a portal!

Was this useful to you? If so, please leave a comment.

Categories
bdg Software Development

Modular Page Assembly in Rails (Part 1)

Recently I was faced with an interesting problem: I wanted to create a modular, portal-like page layout natively in Ruby on Rails without using another layer in the architecture like SiteMesh or ALUI. Java has some pretty mature frameworks for this, like Tapestry, but I found the Ruby on Rails world to be severely lacking in this arena.

I started with Rails 2.0 and the best I could come up with at first brush was to create a html.erb page comprised of several partials. Each partial would basically resemble a “portlet.” This works fine, but with one showstopping pitfall — you can’t call controller logic when you call render :partial. That means in order for each page component (or portlet, if you like) to maintain its modularity, you would have to either 1) put all the logic in the partial view (which violates MVC) or 2) repeat all the logic for each component in the controller for every page (which violates DRY).

If that’s not sinking in, let me illustrate with an example. Let’s say you have two modular compontents. One displays the word “foo” and the other “bar”, which are each contained in page-level variables @foo and @bar, respectively. You want to layout a page containing both the “foo” and the “bar” portlets, so you make two partials.

“foo” partial (app/views/test/_foo.html.erb):

<%[email protected]%>

“bar” partial (app/views/test/_bar.html.erb):

<%[email protected]%>

Now, you make an aggregate page to pull the two partials together.

aggregate page (app/views/test/aggregate.html.erb):

<%=render :partial => 'foo' %>
<%=render :partial => 'bar' %>

You want the resulting output to say “foo bar” but of course it will just throw an error unless you either embed the logic in the view (anti-MVC) or supply some controller logic (anti-DRY):

embedded logic in the view (app/views/test/_foo.html.erb):

<%@foo = 'foo'%>
<%[email protected]%>

embedded logic in the view (app/views/test/_bar.html.erb):

<%@bar = 'bar'%>
<%[email protected]%>

— OR —

controller logic (app/controllers/test_controller.rb):

def aggregate
 @foo = 'foo'
 @bar = 'bar'
end

Neither solution is optimal. Obviously, in this simple example, it doesn’t look too bad. But if you have hundreds of lines of controller logic, you certainly don’t want to dump that in the partial. At the same time, you don’t want to repeat it in every controller that calls the partial — this is supposed to be modular, right?

What a calamity.

I did some research on this and even read a ten-page whitepaper that left me with no viable solution, but my research did confirm that lots of other people were experiencing the same problem.

So, back to the drawing board. What I needed was a way to completely modularize each partial along with its controller logic, so that it could be reused in the context of any aggregate page without violating MVC or DRY. Enter the embed_action plugin.

This plugin simply allows you to call invoke a modular bit of code in a controller and render its view, but not in a vacuum like render :partial. With it, I could easily put controller logic where it belongs and be guaranteed that no matter where I invoked the “portlet,” it would always render correctly.

Here’s the “foo bar” example, implemented with embed_action.

“foo” controller (app/controllers/foo_controller.rb):

def _foo
 @foo = 'foo' #this logic belongs here
end

“bar” controller (app/controllers/bar_controller.rb):

def _bar
 @bar = 'bar' #this logic belongs here
end

aggregate view (app/views/test/aggregate.html.erb):

<%= embed_action :controller => 'foo', :action => '_foo' %>
<%= embed_action :controller => 'bar', :action => '_bar' %>

That’s it! Note that there is no logic in the aggregate controller — that’s not where it belongs. Instead, the foo and bar logic has been modularized/encapsulated in the foo and bar controllers, respectively, where the logic does belong. Now you can reuse the foo and bar partials anywhere, because they’re 100% modular.

Thanks to embed_action, I was finally able to create a completely modular page (and site) design, with very little effort on my part.

In a follow-up post (Part 2), I’ll explain how you can create really nice-looking portlets using everything above plus layouts and content_for.

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).