27 December 2015

Was there

Someone pointed out that our building is visible in this still from (the regrettable satire) Being There (1979). Chance is walking south toward the Capitol. What would become NPR HQ is the white four-story building (only three stories are clearly visible) in the left (east) side of the frame, behind the Texaco sign. The gas station is gone, to be replaced by a grassy area in front of the D.C. Housing Authority building. On the right (west) side of the street, it would appear that the Sibley Plaza apartments aren't in place yet: the foreshortening makes judging location a little tricky.

21 November 2015

Save the tapes

Is your suite of CMSs hooked up to a searchable, durable digital archive? Probably not. Meredith Broussard walks us through a couple of examples.

05 October 2015

I hear that threads are good for eyebrows

Dave meets the Bobs.
For example, a network socket class implemented by Bob Eins—because socket.h was Not Invented Here, and thus not good enough—was namespaced as base::universe::posix::network::socket::Constants::IPV4. It was unclear what existed outside of the base::universe namespace.

19 September 2015


I meant to turn Melody Kramer's post about tutorials for GitHub and Python and other good thingsinto a Serendipity Days project (and maybe that will still happen), but for now I'll just drop the link here.

18 July 2015

The end of tote bags?

Melody Kramer argues that the current business model for public media stations (radio and TV), i.e., "member" = "financial contributor," needs some shaking up. She offers six novel ways to engage with the community, ways for people to engage with and provide valuable support to a station that don't involve monetary pledges. Interesting, thought-sparking stuff.

Incremental improvements

Robinson Meyer tells the story of the small team that put the wheels back on Healthcare.gov, injecting agile methods and tools into the cracks of the federal government's technology infrastructure.

01 July 2015

Fun with Struts 2

My team is building its first application in the Apache Struts 2 framework (it's actually a migration from a Struts 1 application). So we already have a substantial suite of actions already coded, organized into modules. The Struts 2 package concept handles our modules well.

We have standard logic that we want to execute for the invocation of any action (authentication, logging, timing, etc.), so I've recoded our Struts 1 filters as interceptors.

Then there is exception handling. It took me several readings of the documentation and various forum postings and some trial and error to get this working the way we need it, including being able to catch exceptions thrown by interceptors. I ended up deciding to pass the exception info directly to a view JSP, rather than an action class, but we might revisit that decision and do some refactoring.

The docs explain how to configure a handler to be applied globally to the entire application, and how to configure an action-specific handler. But in our case, we have one module that consists of actions that respond to Ajax requests, and hence render JSON, while the other modules render complete web pages with JSPs. The problem statement: how can you configure a Struts 2 global exception handler with the <global-exception-mapping> tag that will apply to a specific package, but will share the same interceptor stack with the rest of the application? For actions in our JSON module, we want error info returned as JSON payload, not HTML.

Well, it turns out that you can do it, but you have to be a little creative with the package inheritance hierarchy. What follows is a simplified (and slightly redacted) version of our actual application, so I can't vouch that this code is complete and accurate, but it should give you the general idea.

The key is to make a package just for the interceptors. Then every other package extends that package. The core package defines exception handlers and global results that all packages use, except the json package, which defines its own.

Here's the struts.xml (again, in our production solution, every package is defined in a separate file that is brought in with <include>, but it's easier to see what's going on with everything in one place):

          "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    <constant name="struts.convention.default.parent.package" value="interceptors"/>
    <package name="interceptors" namespace="/" extends="struts-default">
            <interceptor name="appTracer" class="org.CLIENT.cmsui.interceptor.TracerInterceptor" />
            <interceptor name="appAuthentication" class="org.CLIENT.cmsui.interceptor.AuthenticationInterceptor" />
            <interceptor-stack name="appStack">
                <interceptor-ref name="exception">
                     <param name="logEnabled">true</param>
                     <param name="logLevel">ERROR</param>
                <interceptor-ref name="appTracer">
                    <param name="message">===begin interceptor stack===</param>
                <interceptor-ref name="appAuthentication" />
                <interceptor-ref name="defaultStack" >
                     <param name="exception.logEnabled">true</param>
                     <param name="exception.logLevel">ERROR</param>
        <default-interceptor-ref name="appStack" />
    <package name="core" namespace="/" extends="interceptors">
            <result name="generalExceptionResult">/jsp/GeneralException.jsp</result>
            <!-- results returned by authentication interceptor -->
            <result name="passwordWrongResult">/jsp/user/UserLogin.jsp?passwordWrong=true</result>
            <exception-mapping exception="java.lang.Exception" result="generalExceptionResult"/>
    <package name="alpha" namespace="/alpha" extends="core" >
        <action name="EditAlpha" class="org.CLIENT.cmsui.alpha.action.EditAlphaAction" >
            <result name="Success">/jsp/alpha/EditAlpha.jsp</result>
    <!-- and similarly for packages bravo, charlie -->
    <package name="json" namespace="/json" extends="interceptors" >
             <result name="generalExceptionResult">/jsp/GeneralException.jsp</result>
             <result name="jsonExceptionResult">/jsp/JsonException.jsp</result>
            <!-- results returned by authentication interceptor -->
            <result name="passwordWrongResult">/jsp/user/UserLogin.jsp?passwordWrong=true</result>
            <exception-mapping exception="java.lang.Exception" result="jsonExceptionResult"/>
        <action name="GetLookupInfo"
            class="org.CLIENT.cmsui.json.action.GetLookupInfoAction" >                
            <result name="Success">/jsp/json/GetLookupInfo.jsp</result>

A couple of things to point out:

  • Notice that we use <global-results> to account for results returned by interceptors, as well as the exception handling mechanism.
  • I consider it a blot that you have to define <global-results> in two places, in both the core and json packages, but that's apparently what you have to do.
  • I recommend creating a tracer interceptor as part of your tool kit. All that it does log a message (here, set as a configurable parameter). Writing the code is a good tutorial for creating your first interceptor from scratch, and once you've got it, you can use it to debug your interceptor stacks. I've only shown one stack in this example, but when your requirements call for alternative stacks, it's good to know that you're executing the one you want.

22 April 2015

Catching the bus

Temporarily unavailable for yesterday's link roundup: Maciej Stachowski uncovers a frightening edge case: Firefox poops out when handed markup with <font> tags nested 158-deep.

21 April 2015

Links roundup 3

  • Brian Hayes works through Fawn Nguyen's multiplication problem for her sixth graders, and uses shoe-lacing diagrams to analyze the solution.
  • Guy Fedorkow gives a virtual tour of the Computer History Museum's IBM 1401 mainframe, and delves into the intricacies of data processing with master and detail card decks.
  • Congratulations to the inaugural winners of the Powerful Women Programmers award, 30 talented women from the D.C. area (including three of my past and present colleagues!) recognized by DCFemTech. 
  • Colleague Davar Ardalan gives her take on digital storytelling.

15 March 2015

One of the WAVES

Gillian Jacobs directs The Queen of Code, a short film about Grace Hopper, pathfinder despite herself for women in computing. Two minor errors in the graphics (Fortran was not a computing business; the CO in COBOL stands for "Common"), but otherwise a good piece of work.

11 March 2015

Fred Mallard lives

When I was a little kid of about 6 or 8, one day I wrote a letter to my mother (I think this was at a time when we didn't see each other every day). It's in one of her keepsake boxes for me. I wrote something like this: Dear Mom, How are you? I am fine. Today I had a 60/40 day. (I was a precocious squirt, and I was just getting glimmerings of the ideas [a] of relative proportions and [b] that daily life was not an unmixed joy.) 60 bad because I lost the room's kickball in the woods, (No fence around the playground.) And 40 good because I found it again.

Today was a 60/40 day. Except that, instead of the room's kickball, it was 83K rows from a key table in the central CMS database. A backup copy of the database, a magic Perl script, and the help of Jason, Stephen, Justin, Paul, and Jared, and the rows have been retrieved from the woods.

09 March 2015

Trusting the team

My colleagues Patrick Cooper and Scott Stroud talk to Ethan Marcotte and Karen McGrane about our approach to responsive web design and how we use agile techniques to get projects done.
This project has also given us the chance to really think about our products in general, and not just thinking about the website, or the mobile site, but also thinking about our overall digital products. The product is companionship. How do we become a better companion to people?
Greetings from Evanston, Ill.

15 February 2015

Cmptr chss

I've given this post my performance optimization tag. Sometimes you want to optimize for programmer productivity, sometimes for execution speed, sometimes for space. Olivier Poudade, a fan of "sizecoding," has done that, building a chess-playing program that fits in 487 bytes, as Leo Kelion reports. In other words, Poudade's BootChess, after assembly, takes up less memory than the markup for post you just read.

What's new?

Melody Joy Kramer and some of her folks re-imagine how a home for digital news works. My favorite idea from the brainstorming session: News Based on News People Far Away from Me Have Read.

03 February 2015

Leave no rider behind

Two very different solutions to the user experience problem of vending a card for riding the subway, from New York's MTA and the Bay Area's BART. I love the hand-drawn flow charts by Aaron Reiss.
When Antenna Design came in, commuters were having a hard time adjusting to a pay-first interface, a system much like BART’s current ticket machines. “I saw immediately that wasn’t going to work,” said [Masamichi] Udagawa, “the interface was a big problem.”

New Yorkers simply didn’t trust the machines.

26 January 2015

Big update

We launched a big tranche of updates to our podcast technology, on both the front and back ends. Mathilde Piard has the details on the user-facing side of the story.

On the server side, we re-integrated podcast channels and episodes into the overall data model. Now, podcasts are first-class objects in the CMS, peers of blog posts, news stories, topic landing pages, bios, and other kinds of content. Podcasts now can be associated with multimedia assets like video—oh, and audio—just like everything else in our digital universe.

20 January 2015

Embrace change, and design for it

Laura Sydell profiles Barbara Beskind: retired Army occupational therapist, holder of six patents, 90-year-old designer for IDEO.
"Everybody who ages is going to be their own problem-solver," she says.