Recursive Tweets

February 3rd, 2009

I’m a twitter user, you can follow me here. I’m also the nerd side of ROSA LOVES, and I do most of the tweeting for it as well. We’ve recently started sending out a newsletter via email quite regularly, and have been trying to combine that in various ways with our tweeting.A few days ago I realized I could easily create link that, when clicked on, would lead the user to their twitter homepage with the status text already completed with whatever text I chose. Pretty cool and not sleazy, as it doesn’t actually tweet, it just makes it easier for a user to do it. This is accomplished by providing a GET variable “status” to the twitter home url, like so:http://twitter.com/home?status=hello. If you click on that link and are logged in to twitter, you’ll immediately see the results I described. If you’re not logged in, you will be guided to the login page and, upon successful login, taken to your profile with the status populated as described.Useful for what we’re doing I thought, but I was wanting to step it up a notch. One of the major factors of the web 2.0 culture is the ease with which information can be created, spread or otherwise affected by general users. Think of how huge digg was (is?), how second-nature social bookmarking is, and how commonplace things like the Share This widget have become. What I wanted to create was a link that, when clicked, would result in a ready-to-tweet message as above, with the addition of link that would replicate the behavior tacked onto the end.And so, I present to you this link. Click it. Go ahead. It’s a URL shortened via bit.ly that expands to a twitter message populating link. That link, in turn, contains another link by this same URL. The hope then is that a user will use it to tweet a message, and then his/her followers will see it, like it, and just click the link to propagate the tweet to their own profile. And so on, so forth.Here’s a quick and dirty howto:

  1. First create your message, making sure to observe the length constraints. Be sure to leave sufficient room for your link.
  2. Next, find an unused short name at a shortening service. For example, check bit.ly URLs for their existence simply by concatenating a short name with the base URL. Let’s pretend “hellothere” is an available short name, which would give us the shortened URL http://bit.ly/hellothere. This works with bit.ly because they let you choose a short name, as long as it’s not already used. 
  3. Once you’ve found a free shortend URL, append that to your message making sure to observe the length restrictions imposed by twitter (or whomever).
  4. URL-encode your complete message so it can be passed as a parameter directly in the twitter URL. Here’s a simple URL-encoder.
  5. Now that you’ve encoded your message, test it by concatenating it with the twitter status URL. For example, if your message is “Hello there”, it will now be “Hello there (tweet: http://bit.ly/hellothere)” (encoded as “Hello+there+(tweet%3A+http%3A%2F%2Fbit.ly%2Fhellothere)”), then the URL to test will be http://twitter.com/home?status=Hello+there+(tweet%3A+http%3A%2F%2Fbit.ly%2Fhellothere).
  6. After verifying that the link works as expected, shorten that URL with bit.ly using your selected short name (”hellothere”).

Now you can use that URL directly in your browser to generate the twitter message with the embedded, recursive “tweeting” link. When posted, followers will see “Hello there (tweet: http://bit.ly/hellothere)”, and the link will propagate that exact message to their twitter status window when clicked. All they need do is click “update.”

Ganymede, run-jetty-run, and Tapestry 5

January 19th, 2009

Eclipse Ganymede 3.4.1 is so far a great environment for Tapestry 5, when paired with the m2eclipse plugin and run-jetty-run launcher (gorgeous live class reloading). A couple of quick notes: 1) Jetty’s slf4j breaks Tapestry’s.This is easily correctable by adding the VM argument to the launch configuration:-Dorg.mortbay.jetty.webapp.parentLoaderPriority=true (wiki article). 2) If using run-jetty-run 1.0.1, know that it will not add the servlet api jar to the classpath.The funny thing is that it does include this jar as a dependency, so it ends up in your maven repository (servlet-api-2.5-6.1.9.jar for example). You can easily “Add external jar” to include it, and be on your way.

Notes on Curl: Testing a Webservice

September 16th, 2008

msg=`cat soap-msg.xml`curl -H “Content-Type: text/xml;charset=UTF-8″ -d “$msg” http://foo.com/webservice/

Resume Update

April 1st, 2008

Today I finally got around to updating my resume. This is something that I never enjoy doing. Aside from basic polishing I added my Ruby and RoR experience. At the moment I still can’t say I’m onboard the RoR bandwagon, I do however find Ruby an interesting and fun language.

Tapestry 5: A Minor AJAX Enhancement

March 19th, 2008

Tapestry 5 has seen a lot of updates over the past couple of months. With the addition of the Autocomplete mixin and the Zone component, AJAX is becoming evermore supported and ingrained. When writing AJAX components, using the Autocomplete source as a reference to “how it should be done” is a great thing to do. It’s concise, simple, and shows that AJAX components are on their way to feeling very natural. AJAX event handlers for components behave much the same as they do for normal ones, with the addition of a few new options in the return type. Tapestry makes it easy to respond with JSON objects, in that you can return a JSONObject:


Object onUpdatelist() {
	JSONObject messages = new JSONObject(
		"{users:[{user: 'clewis', firstName: 'Chris'}]}");
	return messages;
}

Nice. However there is another type that would be a very natural return type, JSONArray (not supported as of r638979). I say this because it’s already available in the API, and developers quite often need to return collections of (JSON) objects. So, why not support JSONArray return values? As it turns out, adding this support is not at all difficult, so today I opened a ticket and provided a patch to do just that. Check it out at: https://issues.apache.org/jira/browse/TAPESTRY-2286. The patch updates tapestry’s configuration module, and requires the additional class. With this addition you can now return JSONArrays, without the bother of wrapping your list in a useless object:


Object onUpdatelist() {
	JSONArray messages = new JSONArray("[{user: 'clewis', firstName: 'Chris'}]");
	return messages;
}

Of course even without compiling this into tapestry, you can provide this class and wire it up through your own module.

My Public Key

February 25th, 2008

Dealing with gpg public and private keys has been a bit of a pain for me in the past. It’s not a complicated matter really, using them, it’s just that when the time comes for me to renew or create a key pair, I never remember any of the gpg commands! I just went through the process and decided to write a quick post about it.Assuming you’ve created your key pair, you can enumerate your key (and any others in your keyring).

chris-lewis-computer:~ chrislewis$ gpg --list-keys
/Users/chrislewis/.gnupg/pubring.gpg
------------------------------------
pub   1024D/875E0AD6 2008-02-25 [expires: 2008-08-23]
uid                  Chris Lewis (burningodzilla) 
[ removed ]

Now that you know about your keys, you have the names. Above you see my public key’s name: 875E0AD6. I can now dump it in a printable (ascii-armored) format:

chris-lewis-computer:~ chrislewis$ gpg --export -a 875E0AD6
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.4.7 (Darwin)

mQGiBEfDIhIRBAC25JPhhfz6y86Jj5l6nwb5WQ6+4PDanuuF6fGPzSRLGlcnNF5m
4UUawqF1Ofvlo4RGFkNRfRo/xdiqh95oS75rFD8hZAAyoj4CJ+NTtaTunrW+X9K2
olhV2Mf4L4b1PTJWUAcErCZg9SM/BleSCQQjmnJpPZ7JWjSlPOZhwXP0nwCg5Vwt
NHu+rD7mOGFDFNI81RHFhU8EAIveXe1MhSnB2pxF+r0IzHJIXC0a+buUpJB28Tef
T5hRHYT5KS2Gcy7aGWeHqHnVQzDnIP1/sJ+vWrcjAHXFSBbgnXRqh/wBb+B8+IX9
qi30I1LIYdf8XMBpyMAl7XFf1Ee2N18dZgS7lI4Jz88Hzyn+aIIbZ6E1wyfCTcN2
uqnZA/9VDJ86n92Paa2AeyRQNsMK6xApZbndD+FjEOXb/WLPylgVQo22/46cpnW2
mqcPkOX5yHvFYJRH5K759NYG+ZAeLx5P7lXx8RZEHOjTvUpBL+OcVlfouFV8ozs7
DOLsBimTN/g/THiz6OWP0n6yahVpXTgbCIfDJRomQuss1MD4bbQzQ2hyaXMgTGV3
aXMgKGJ1cm5pbmdvZHppbGxhKSA8Y2hyaXNAdGhlZ29kY29kZS5uZXQ+iGYEExEC
ACYFAkfDIhICGwMFCQDtTgAGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRAAZ67s
h14K1itvAKDHO/Knhk2dKw/xhGUuVyM8A1su4ACeKxpWpx/Suf2aUNo+FT4cxeMv
Dlu5Ag0ER8MiEhAIAPN7rqN+UZdvQDj1zmbYttWaQIHdHVdFzDWJZjC7KhxZuD/9
fmQGIItxECDnf4sObNxHckCIOP6WOENBq7iyUhZlImLOlPcxXUjPG1wz5q28iUAo
wFXy9ftGVPYJWT84LOS0Ut9lhfG8irmYCR9I1Q0Z2G0mZ9Ftv398u/FbET43bpVh
NJKcNN0kvsoEcQyTAvNmzfY8m79985W8AkuIAQMhoxYsMYv+ILI+vy49uJbWHpKN
SIf39w/nAOhJIxbRLPR2ss58aHtLb4vA5wfMOiWSOvmiPbe3rEQFjk9/ORKbqc1I
DGK4cx3EmOCDQ9WYpEbiv6/9ShdoY+gBSkD5h9MAAwUH/3qRxCGJ+NlVCFrkFNHu
0TV36B1UCLdPYiK4JLtaLBe+NNDf9YlPqYAZRuV9XH4LytwYqKtizS9AGDfidmhz
rl5InYWjMqZkyG6FQI0E8y/RiqIo/DvButM21TsL5ciXTm/NOUecp7oNOL5pLwyJ
3JVOZQ74yqEXbV9hE0jc72CNQ2AeL0FnIHOPoD3onMF5zisdTFg71mOaXa4b+Urn
Bt43dxU27psK+Cw+5OQxPIXBHl/aOrEght5qhu43oDB2BRu8N9M0a9hJ9ZWt7qD2
jjSj5e3039iOBP4xUNIuW30E1GcOG93q2B9QMenYbPKTZtDjOsmwZl3zGw8IENHX
Ep6ITwQYEQIADwUCR8MiEgIbDAUJAO1OAAAKCRAAZ67sh14K1mnCAKCU6oWEEtKS
GZDGU/JVmcYvT0K7zACgswx0Ng2uWc7dRPaVH52BM485GYA=
=/cLY
-----END PGP PUBLIC KEY BLOCK-----

And that’s it. FYI, that is my real public key.

Involvement

February 19th, 2008

In an attempt to keep a somewhat vibrant blog about my professional (and nerdy personal) life, I’m writing to share my involvement in a small open-source project: tapestry5-components. This is a component library for the much-anticipated Java web framework, Tapestry 5. Today I officially joined the project and merged my code into the svn repo. This code was from a much smaller component library I started called gc-tapestry-components. I will work on this project in free areas of time (as they arise), and even though my contributions may be small at first, I will strive to keep them significant.

First Mac Package

August 1st, 2007

I’ve uploaded a Mac package (pkg in a dmg) of the Fondu font utilities. Among other things, these utilities can convert mac .suit font files (archives) into true type (ttf), suitable for systems like Linux or Windows. Grab it from the Downloads page.

An Exodous

July 15th, 2007

So here’s the deal - thus far in my career I’ve experienced the most satisfaction when developing applications in Java. Specifically, desktop applicaitons in Swing as well as some stand-alone server applications (not web apps/servlets). Of all the gripes and pains of Java, it is a proven, time-tested platform that has gained (and retains) a huge amount of support from 3rd party vendors and enterprise customers alike. Additionally, the developer ecosystem around Java has been on the forefront of software architecture and promoted the wide adoption of language constructs/paradigms such as AOP (No, the Java ecosystem did not invent or discover the concept of design patterns or aspects, but it is one of the most prominent responsible for the mass adoption of such practices over the last decade or so). I personally have learned and continue to learn from this ecosystem. While it has certainly not dictated my growth as a software developer, it has influenced it.

When I started looking in to web programming, a friend of mine turned me on to PHP. At this time I had probably been developing software for 2 years, so I was open to absolutely anything. Being that I didn’t have any push or guidance towards servlets or JSPs (my schooling focused on Swing and applets), I gave it a go. I very much enjoyed learning PHP. It was easy to set up, easy to learn, and fun to code. When I started getting into databases (MySQL of course), I saw the greater potential of PHP and, as many a fledgling developer, thought I was ready for anything with my new tools. I wrote several sites in PHP; raw, frameworkless PHP, and was happy with them. It wasn’t long before I noticed all the issues with this kind of development, none greater than the rigidity of the applicaitons (due to cut-past code, tight coupling, etc). For a year or two I used various tools and frameworks to improve the situation, but I have never been satisfied (my experiences and gripes with such tools, including mojavi, eclipse db, and cakephp, is beyond the scope of this post). On top of this I have developed a general distaste for PHP, and specifically its continued identity crisis as a language.

This laid the foundation for my investigation of J2EE (specifically servlets and JSPs). I had already used some J2EE components (including JDBC), but had yet to tinker with a container or to create even a Hello World servlet. After reading and working through “Core Servlets and Java Server Pages,” I wasn’t convinced this path was any better than my current one, so I didn’t make a transition. In fact it seemed about the same, with the additional overhead of compilation and the general pains of a servlet containers (deployment, reloading, etc). As such I continued down the same frustrating path of PHP, using cakephp as the framework as it at least sped development.

Of course during this time Ruby on Rails had emereged and had begun to take the web world by storm (at least in the tinkering sector) (It was RoR that led me to cakephp, as I was not interested in learning a new language or any of it’s surrounding technologies). I have investigated RoR, and while there are some clearly useful innovations, I’m simply not sold on ActiveRecord or it’s interpretation of MVC (specifically its whole controller/action paradigm).

There are other praises and complaints I have about RoR and related spin-offs, but that’s not what this post is about. What it is about is my repeated attempts to find a sane transition from PHP to Java/J2EE, when much of the world is taking an inverted path (not specifically to PHP, but to lightweight technologies like it or RoR). I believe I have found this path via Apache Tapestry.

Oddly enough, I discovered Tapestry through a PHP framework heavily influenced by it (Prado). I’ll go ahead and state that to date, no framework has made database interaction as quick or easy as RoR, including Tapestry. In fact, Tapestry provides no persistent layer at all, which is admittedly a drawback (note that the upcoming version 5 includes a tapestry-hibernate jar, but I’m not sure what all it does). If you want praises on Tapestry, try google, but what I will say is that getting started with it (version 4.1.2) is pretty simple. Get set up with Eclipse 3.3, Tomcat 5.5, and the Tomcat/Eclipse plugin, throw in the example chapters from EWDT, and you’re on your way. I bought the full book and it was well worth it.

I’ll close with a few statements that will hopefully add some cohesion to this post. Tapestry provides a way for me to impelement web applications on a J2EE stack, without having to invest so much time in digesting the staggeringly large J2EE spec. It also provides a fasinating paradigm to develop applications in, namely it’s component-based approach. An added bonus is the fact that I can share code between web and thick client apps where it makes sense to do so.

Will I invest time in digesting more of the J2EE stack? Most likely, but with Tapestry I can start develping effectively without first spending so much time mucking around in the massive spec that is J2EE.

Odd ‘document’ behavior With Prototype.js 1.5 in Safari 2.0.4

May 19th, 2007

I ran in to an annoying bit of behavior while working on a generic hovering element effect in Safari, using Prototype.js 1.5. Firstly, I’m not well-studied in the general quirks of the onload and unload events, how they work and should work etc, but this issue seems to stand outside that.
The code I’m working on uses the wonderful document.getElementsByClassName to locate the exact element to operate on. Everything was working smoothly, save for the usual and expected cross-browser kinks to be sorted out. Basically I have an element structure like this:

<div class='news-summary'>
    <div class='title'>Today's News</div>
    <div class='date'>5/18/2004</div>
    <div class='summary'>This is a great post...</div>
    <div class='admin-toolkit-canvas'>
	    <a>Edit</a>
    </div>
</div>

This represents a simple news preview or summary, possibly one in a list that you might find on a news post index or a side element or portlet. Now if you are logged in as an admin, hovering over the summary should cause a translucent canvas to appear over it, containing easy to access admin functions (like edit). The css class news-summary is a top-level container for summary content, and contained in this is an element of class admin-toolkit-canvas. This element is invisible, and is positioned absolutely within the parent news-summary element. When any child element of the summary element is hovered over, the canvas is rendered. I use document.getElementsByClassName to locate the actual canvas element in various contexts, mainly for showing/hiding it. I had no serious issues until navigating away from the page in the same window, and then using the ‘back’ button in Safari to return to it.
It seemed that the hover events over the summary containers were no longer being handled properly, or more likely that the code I had written to locate the child canvas was breaking.
After some precursory investigation I had assumed this was a side affect of Safari’s handling of the onload event, but further experimenting proved otherwise.
Prototype does some things that some call bad practice, like augmenting core objects and classes provided by the browser environment. One such victim is the global document object, which it equips with the getElementsByClassName method. It works fine… until you return to a page using this method via the back button. So what’s the problem? The augmentations to core objects (not classes), specifically on document made by prototype are apparently reverted. That’s right. No more getElementsByClassName. Why? I’m not sure. This seems to be how WebKit is designed - to blindly (re)initialize the core objects on any page visit.

Is this a bug or a feature? I’m not yet sure. I haven’t done any other tests outside this, nor have I tried the WebKit nightlies. IE and FF seem to work as expected. More to come on this, no doubt. Share some input if you have any!