- Microsoft takes email design back 5 years – Campaign Monitor Blog
I spent a lot of time at my last job working on consumer email, Notes was always the worst. I think the HTML formatting in Outlook 2007 is going to be worse than Notes and that’s really saying something.
(categories: outlook 2007 email marketing css html )
All posts by ajohnson
ROME and wfw namespace elements
I created a ROME parser and generator for wfw:comment and wfw:commentRss elements today. You can read all about it here and download the source code here.
Not sure what the wfw:comment or wfw:commentRss elements are for? Imagine you’re reading my blog in desktop aggregator and you want to post a comment to my blog. The aggregator has no way of knowing where your comments should be HTTP posted too, so you have to open up another tab in Firefox and go to my blog to enter a comment. wfw:comment is an element that provides the HTTP post endpoint in the feed so that aggregators and widget developers can comment inline, just like this. wfw:commentRss is an element that provides you (or your favorite aggregator) with a link to the comments for the post you’re currently viewing.
ROME and custom Generator elements
The majority of the articles I’ve seen on using ROME to create Atom and RSS feeds don’t show you how to customize the optional ‘generator’ element that both Atom and RSS support. It’s really easy. I’m assuming that you’ve already created and populated a SyndFeed instance:
SyndFeed feed = ..
WireFeedOutput feedOutput = new WireFeedOutput();
WireFeed wireFeed = feed.createWireFeed();
if (wireFeed.getFeedType().startsWith("atom")) {
Feed atomFeed = (Feed)wireFeed;
Generator gen = new Generator();
gen.setUrl("http://yoursite.com/");
gen.setValue("Your Site");
gen.setVersion("1.0");
atomFeed.setGenerator(gen);
feedOutput.output(atomFeed, ...);
} else {
Channel rssFeed = (Channel)wireFeed;
rssFeed.setGenerator("Your Site 1.0 (http://yoursite.com/)");
feedOutput.output(rssFeed, ...);
}
Make a decision about which feed you’re going to produce, cast to the appropriate implementation of WireFeed (Channel for RSS and Feed for Atom), and then use the appropriate setters on each of those respective classes.
Links: 1-9-2007
- Dare Obasanjo aka Carnage4Life – Updated: XML Has Too Many Architecture Astronauts
JSON is a better fit for Web services that power Web mashups and AJAX widgets due to the fact that it is essentially serialized Javascript objects which makes it fit better client side scripting which is primarily done in Javascript.
(categories: json javascript client xml data browser ) - Using prototype.js v1.5.0
Developer notes for Prototype 1.5 released.
(categories: prototype documentation javascript ) - Ajaxian » Browser Cache Usage: Only 40-60%?
Quote: “… 40-60% of Yahoo!?s users have an empty cache experience and ~20% of all page views are done with an empty cache. “
(categories: caching cache browser http performance )
Firefox mimeTypes.rdf corruption
Came across another interesting bug today involving Firefox and mime types. Firefox uses a file called mimeTypes.rdf (stored in your profile folder) to keep track of a) what application should be opening the file you’re downloading and b) what kind of file it should tell a server it’s sending when you upload a file. And it works … for the most part. See, if you download a PDF file from a server that (incorrectly) states that the content-type of the file is ‘application/unknown’, choose to open it using Adobe Acrobat and then check the box that says ‘Do this automatically from now on’, Firefox will store that bit of knowledge away in mimeTypes.rdf. Now go and use a web application that you upload files to and which analyzes the content-type of the files you’re uploading and upload a PDF file. If you’re using LiveHTTPHeaders, you’ll notice that you’re not sending ‘application/pdf’ but instead ‘application/x-download’.
It looks like this bug was filed in bugzilla a couple times and even acknowledged in their documentation, but has yet to be fixed. You can ‘fix’ the problem by deleting your mimeTypes.rdf file and restarting Firefox.
Five Things
My friend and ex-roommate David tagged me with the five things meme, so here are five things about me you probably don’t know:
- My parents tell me that the doctor dropped me on the floor when I was born.
- I lettered in soccer and baseball in high school.
- I got my first computer (a Color Classic) in college. I remember playing Maelstrom while listening to Tribe Called Quest with my roommate for hours.
- I worked at Fuddruckers during my college summers, gaining a ‘Guest Service Representative’ certification. I’m not sure if my certification expired, but if you buy me lunch, I’ll be happy to refill your drink.
- I’ve seen Major League Baseball games at the following parks:
- Dodger Stadium
- Angel Stadium
- Jack Murphy Stadium
- PETCO Park
- Candlestick Park
- Bank One Ballpark
- Coors Field
- Shea Stadium
- McAfee Coliseum
- Kingdome
- Fenway Park
- Skydome*
- Camden Yards
- Yankee Stadium
I’ll tag Joe, John, Ryan, Erik and Mike.
* The visit to the Skydome probably shouldn’t count, I didn’t actually see a game there because I was in Toronto in November. I think there was a Canadian Aboriginal festival happening that day.
Links: 1-3-2007
OGNL: getter and setter types must match
Yesterday I ran into a interesting bug with the WebWork application I spend my waking hours working on, at least initially I thought it was a WebWork bug. I had a WebWork action with a getter / setter combination that looked like this:
public void setUser(String username) {
...
}
public User getUser() {
...
}
The thinking here was that if I invoked the action using a request like this:
/myaction.jspa?user=aaron
then the action would look up the user based on the given username and populate a User object, which would then be returned by the getUser() method (populating the user instance using a custom IOC interceptor would have also worked but would have been overkill in this particular case). The problem was that the setUser(String username) method was never getting called. After checking and double checking the method names and the parameter being passed, I googled around and found this email thread which discusses the very issue, saying that the problem was in fact not with WebWork, nor with it’s underlying expression engine OGNL, but rather the ‘Java reflection API semantics’. In the thread, Laurie Harper, a Struts committer, says that the:
… restriction (where getter and setter have to be of the same type) comes from the Java relection API semantics, not OGNL. A property can only have one type, so it makes sense that the getter and setter for a JavaBean property must agree on that type.
I didn’t doubt what he said, but I needed to see it with my own eyes, so I dove into the deep sea that is OGNL, reflection and JavaBeans. First I read the JavaBeans specification, which seems to back up his story: page 55 of the PDF says this:
By default, we use design patterns to locate properties by looking for methods of the form:
public <PropertyType> get<PropertyName>();
public void set<PropertyName>(<PropertyType> a);
If we discover a matching pair of “get<PropertyName>†and “set<PropertyName>†methods
that take and return the same type, then we regard these methods as defining a read-write property whose name will be “<propertyName>â€.
So the JavaBeans specification requires the getter and setter to be of the same type, but how does OGNL figure out that the I’m trying to trick it with two different types?
I found the answer by digging pretty deep: the OgnlRuntime class looks up a PropertyDescriptor for the given class (in my case the WebWork action) and then calls the getWriteMethod() on the PropertyDescriptor instance. The documentation for that method mentions that it may return null if the property can’t be written but the documentation doesn’t mention why that might happen. If you grab the source for the PropertyDescriptor class, you’ll see that the getWriteMethod() method invokes a private method findPropertyType(), which is where I finally found the culprit. It compares the return type of the getter and the parameter type of the setter and throws an IntrospectionException if the types don’t match (line 602), which the getWriteMethod() catches and then returns null, which leaves the OgnlRuntime with no method to call.
So it sounds to me like this is really a JavaBean specification requirement, not a Java reflection API semantic, but then I guess it’s all just semantics anyway right?
Links: 1-1-2007
- the next great blogging tool > Second Verse
Quote: “… the next great blogging tool will integrate seamlessly with instant messaging.”
(categories: blogging IM )
Links: 12-25-2006
- IT Conversations: Ryan Freitas
Great rant on what collaboration is and isn’t and on what some of the cool tools are.
(categories: collaboration podcast email wikis IM sharing ) - Blog by Kveton > The PDX Mojo: Open Source Finding its Stride
Like Portland? Work at Jive! http://www.jivesoftware.com/company/jobs.jsp
(categories: portland jobs oregon ) - Scripting News for 12/20/2006 > Scripting News Annex
Douglas Crockford: “The good thing about reinventing the wheel is that you can get a round one.”
(categories: json javascript quotes ) - Daring Fireball: About the Footnotes
In case you’re wondering where I got the hankering for footnotes in my posts on the Clearspace blog. Wait, you haven’t seen my posts over there? Check it out: http://jivesoftware.com/blog/
(categories: footnotes design html usability blogging )