Monday, December 2, 2013

What I Learned From NaNoWriMo 2013

"We learn wisdom from failure much more than from success. We often discover what will do, by finding out what will not do; and probably he who never made a mistake never made a discovery."
-- Samuel Smiles

I finished my first National Novel Writing Month (NaNoWriMo) having accumulated 21,196 words of the 50,000 needed to win. It can be argued that a challenge bested on the first attempt is no challenge at all, so I am dusting myself off and taking a hard look at what happened with an eye to the next time. I'm the sort of daydreamer who has often fantasized about chucking away the career to write for a living -- short stories, essays, articles, novels -- hardcore writing that owns my most wakeful hours of the day and tops the priority on the daily to-do list. Surely if I could only do that, I could be the kind of Self-Actualized Human Being that Abraham Maslow would place at the top of his eponymous pyramid, from whose pinnacle I would gaze down at the rest of the world like some sort of radiant Sun-God...

But before checking in to that flight of fancy, I knew that there were more reasonable milestones, like finishing something, and paying my ego-dues in rejection letters until I finally published a piece. And the steps towards those milestones, according to every writer who cared to opine on the subject, were to WRITE. EVERY. DAY. Not to make excuses. Not to lie there waiting for inspiration. But to make myself prolific and practiced enough to call myself a writer without qualifying the word, or feeling like a fraud.

NaNoWriMo was the perfect opportunity to test myself. I claimed to want the Writer's Life, but could I live it for 30 days? Could I block off the time to produce 1,667 words every day, alongside my day job and parenting a toddler, no matter how tired, burned-out, distracted, or blocked I felt?

No, as it turns out. I couldn't.
But now I have a much better sense of why.

I Dropped Out Of Weight Watchers, Too

Writing 50,000 words in 30 days is no easy task. In a standard manuscript format document, that equates to writing about six pages every day. For me, the daily 1,667 words took around 3 hours of writing time; more, if I had to piecemeal it throughout the day and settle back into the groove where I left off. Falling behind was disastrous. It incurred a debt not easily paid off.

It reminded me a lot of another exercise in self-discipline I attempted a few years ago: Weight Watchers. Both NaNoWriMo and Weight Watchers are structured to help you establish a goal-oriented lifestyle. Both have a form of daily check-in, progress-charting to encourage you, and legions of cheerleaders to help you to your feet when you stumble. And in both programs I fought against the downward spiral of failure begetting failure because it's so much easier to let gravity win and stay off program than it is to get back on. But while Weight Watchers is open-ended -- you can spend two years to take off those last 20 pounds if you need to -- NaNoWriMo has a narrow time frame in which to win. Sure, the ultimate lesson is that any progress towards your goal is better than none or regression. But when you're playing the NaNoWriMo game to win, unless you have the discretionary time to binge-write, do not fall behind.

NaNoWriMo, like Weight Watchers, is about establishing and sustaining habits that support a goal. Some would call that "intentional living." In concept, it's a great thing, and there's no good reason not to do it. And yet, somehow it's hard. Because... excuses.

Excuses, Excuses

There are those who claim that there are no reasons you can't reach your goals, only excuses. As a motivational slogan it may have merit, but as a description of reality, of course, it's horseshit. The slogan's main merit is to force you to examine your values and make the hard calls on where writing fits into the demands on your time -- on what constitutes a reason and what is an excuse. 

Was winning NaNoWriMo more important to me than caring for my 2-year-old, fulfilling the obligations that allow me to draw a paycheck, or feeding and taking out the dog? It was not, and that meant that I would not be writing between 6:30am and 9:30pm (except during a few stolen moments), weekdays and most weekends (my kid doesn't nap). That left 9 hours a day of discretionary/sleep time to allocate. 

Was winning NaNoWriMo more important than catching up on Boardwalk Empire/Homeland/American Horror Story/TheWalking Dead? Yes, it was. And still, there were nights when I didn't choose what I valued, I chose what felt comfortable. (Lesson learned: stay strong.) 

Was winning NaNoWriMo more important than sleeping? Sometimes it was, sometimes it wasn't. It depended on how many consecutive days I decided it was. (Lesson learned: I'm not as young as I used to be.)

And then, of course, there's that most universal of excuses: the holidays. I used to wonder why NaNoWriMo was in November. Thanksgiving is in November. There's travel (or houseguests), cooking, cleaning, interacting with family in real-time without the benefit of a computer screen and asynchronous communication. Now I think it's genius that NaNoWriMo chose November. Thanksgiving plans are usually made well in advance; the holiday is toward the end of the month, and there is ample time to plan your strategy around the holiday -- because if you're going to live the Writing Life, this kind of stuff can't knock you off your game. In Weight Watchers, they would devote an entire meeting session just before each holiday to help people plan how to manage the caloric temptations, and familial pressures to eat, that we all knew to expect. Was winning NaNoWriMo more important than cooking the family meal, or spending time with my mother who lives alone in another city, but had come for a week to spend time with her son and granddaughter? Hellz no. And I knew that before November even started. Lesson learned: plan for the holiday.

The clearest lesson out of this process of weighing values was that there was a set of things I was willing to give up, and a set of things I was not. That defines one's level of commitment to any new undertaking, and sets some practical boundaries and expectations. I learned a lesson in undergraduate that hadn't been true before, but has been true ever since: there are things that can't be accomplished even by staying up all night. When we were young, we were encouraged to know our limits so we could exceed them. In my 40s, I'm starting to feel the need to know my limits so I don't sprain something.

But I Did Some Stuff Right, Too

In October, I prepared for NaNoWriMo by creating an outline, and it was the smartest thing I did. I had never written a novella-length piece of fiction before, and I didn't know how to approach one. But I had written many a short story, and I figured out pretty early on that I wanted four point-of-view characters in my novel. Not only were they the smallest subset of characters who could properly represent the story's events, but they had some elegant symmetries and contrasts that seemed too clever for me to pass up. I started by having four headings, one for each character, and jotting down a rough chronology of events or scenes I envisioned unfolding under each point of view. I kept this outline electronically so I could review and tweak it on the bus, in the restroom, between meetings -- whenever I could. My goal before November was to have four reasonable character arcs, as though I were writing four short stories.

At various points, two or more characters' scenes would intersect, so I restructured my outline from a character chronology to a global chronology. For the outline, I used my favorite Web-based productivity tool, Workflowy, which let me create a line to describe each scene, and I tag each scene with the characters who appeared in it, as well as a "#todo" that I would later remove after the scene had become paragraphs in my manuscript. I could then use the tags and Workflowy filters to collapse the global chronology to a character-specific one, or even to just the scenes I had left to write. Before I even began writing the novel, I ended up with two things: a sequence of scenes that told a complete story, and some confidence that each character had his or her own internal journey over the course of the tale. I've trained myself to be ruled by checklists, so having an ordered (and re-orderable) set of bullet-pointed scenes made the whole idea of writing a novel much more approachable.

As I was writing, of course, I allowed myself the freedom to veer off the outline, and if I chanced upon something interesting, I retrofitted it back in to the plan. I also used the outline to jot down notes about the emotional core of a scene, and what experiences of my own I could tap into to make the scene ring true. Or I'd make a note about character voice -- channel a little Han Solo when writing this guy, or Hannibal Lecter when writing that woman.

I jumped around in the chronology. I wrote the first few scenes of each character, then the last climactic scenes. Then I started working backwards and forwards toward the middle. I stuck with one character until I got bored or blocked, and then I moved to a different one. I dispensed with scene transitions if I was eager to write the action. Or if I couldn't think of a good way to move a scene forward, I'd pour in physical description or prattling dialogue until something sparked (or until I got my night's word count).

And as the NaNoWriMo coaches encourage, I dialed down my internal editor as much as I could. The only metric that mattered for November was word count. If I used the same turn of phrase in two consecutive paragraphs, I let it slide. If the descriptions were workmanlike and lacking flair, I didn't worry about it. If I wasn't sure of a detail, and wanted to do some research first, I went with my gut and deferred the research. From my experience with short stories I knew that revision was where the magic (and much of the fun) happened. I committed to making my job in November the creation of a substantial draft that I could revise.

Even if I didn't win, I'm pretty happy with the result. I wrote 19 of the 26 scenes I had planned in my outline, and I have 75 pages of writing. This is a project I believe I could finish. And isn't that the bedrock difference between real writers and dabblers? Real writers finish things. And I now have the confidence I can do it.

Monday, May 20, 2013

The Answer Is 42, and I Am the Answer


It was my birthday yesterday. In his Hitchhiker Trilogy, Douglas Adams revealed that the answer to Life, the Universe, and Everything is 42. The trickier proposition, of course, is figuring out the question that goes with the answer. In my younger days (as a 41 year old), I thought that -- at least by family history -- I'm well past my halfway mark, so maybe "42" answers the question, "what will I be when I grow up?" The glumly tempting implication was, "this is the end of my becoming." But that was when I was young and foolish.

Now, I AM the answer. 42. And I now know that this is the year when my insights will "stick." This is the year that, even if I've had the same realization a thousand times before, the ideas will motivate me to act. Example: yesterday, I went to a panel discussion of science fiction authors who had just published their first books, attended by mostly aspiring writers. Some of these authors had been working for more than a decade on their first work. All of them had “day jobs,” all of them had bills to pay. And they were all in agreement about how they got it done. They made the time. They were serious and passionate enough about this accomplishment that they used their problem solving skills to carve out the time to write, regularly. If it were easy, everybody would have done it. I’d heard that before, even agreed with it. But now, at the age of 42, when I am the answer, I finally get it.

I am the answer. It’s on me.

Sunday, July 1, 2012

Chicago NATO Summit Journal: A Survivor's Tale

CHICAGO, IL - MAY 18: Police try to prevent pr...

May 18, 2012, CHICAGO, IL. The Tribune, the Sun-Times, and WGN had warned us about the coming NATO Summit. They warned us of the protesters who were stockpiling human excrement to unleash on the police, the danger of having our wireless connections hijacked, the hair-trigger Chicago police, and the mayhem that would surely engulf and raze the Windy City to smoking rubble. They warned us to stay out of downtown, they warned us not to wear suits lest we be mistaken for targets/Visiting Dignitaries.

Many of us did not heed the warnings.

This, originally published as it unfolded on Facebook, is one survivor's story of the Chicago NATO Summit Apocalypse.

NATO Summit Journal, 8:19am.
It's Day 1, and the sense of wrongness in the air is tangible. It's like walking through invisible, greasy smoke. I can see downtown Chicago in the distance from the train platform. It is surrounded by a blood red haze. But the highway... Traffic is going the wrong way. Gods help us, it's going the wrong way.

NATO Summit Journal, 8:26am.
The lights are out in the subway. The only illumination comes from my phone. The train car is rocking, but I have no sense of moving forward. The air is becoming thin. I need my Ventolin. I wish I could see the sun.

NATO Summit Journal, 9:02am.

They've locked us in. Those bastards locked us in.
I found a sewer line to escape. Made it to the surface. Update later, when I can clean up.

NATO Summit Journal, 9:20am.
I escaped the subway station in a sewer pipe. The rats seemed afraid of something, not me. There was a dead man on the street near my office; his head was twisted completely around. Everybody is ignoring him. Why is the sky so red?











NATO Summit Journal, 9:32am.

Food is becoming scarce.















NATO Summit Journal, 9:36am.

I'm locked out if my computer. Someone is scanning my files. I try to ignore the ominous buzz coming from my Blackberry.

NATO Summit Journal, 10:03am.
A colleague logged onto the internet over unsecured Wi-Fi and his laptop exploded. There isn't enough of him to bury.

NATO Summit Journal, 11:14am.
A man with a "peace" sign on his t-shirt is sitting in the middle of the street, covered in filth, beside an empty barrel. He is weeping. Protestors have been stockpiling urine and feces for months in preparation for today. The only saving grace is that they didn't think through how to transport it.

NATO Summit Journal, 12:47pm.
I made it to the elevator, and turned to see a man across the lobby running towards me, clutching a piece of paper to his chest. "He has Facebook stock!" someone shouted. "The One Percent! Get him!" They swarmed like angry hornets. I let the elevator doors close. The look on his face haunts me. It was just a restaurant menu in his hand. Just a menu.

NATO Summit Journal, 1:23pm.
The protestors are filming the cops. The cops are filming the protestors. Passers-by are filming them both, and each other. Every eye is watching through a recording lens, waiting for someone to slip up. Waiting to capture the flashpoint. To document the beginning of the end.

NATO Summit Journal, 2:28pm.
They've hijacked my signal. All my Anytime Minutes are gone. The Sun Times warned me to use land lines only. But it makes no difference now. They're not just shutting down the cell towers. Oh my gods... they're tearing them down. THEY'RE TEARING DOWN THE TOWERS.

NATO Summit Journal, 3:13pm
.
Protesters pulled a policeman from his bike. We heard the helicopters just before we saw the blinding flash. When our vision returned this sign was all that remained. It says "Give Peace a Chance."













NATO Summit Journal, 3:21pm.

They've deployed the gun boats. Why are they aiming at the Michigan Avenue Bridge? Wait... NO!







NATO Summit Journal, 3:45pm.

The riot police have secured Pioneer Court. The bridge is down to the south. It looks like they're setting up some sort of bunker where the Marilyn Monroe statue used to be. Men in white lab coats enter and exit.













NATO Summit Journal, 3:52pm.
We were all warned not to wear a suit downtown during the summit, but one of our sales execs had a live pitch meeting in the West Loop. He pulled a hoodie over his jacket and covered himself with a shabby overcoat. He shambled past the milling protesters to the street corner where he could hail a cab. But as he stood there, some of the protesters were eyeing his shiny leather shoes. From the 15th floor window, I could see the agitation spread through the crowd, angry ripples centered on his business attire. The cab came too late. I remember he would always make a fresh pot of coffee whenever he took the last cup. Not many execs do that.

NATO Summit Journal, 4:06pm.
Email just came in, addressed to all employees:

Good Afternoon -


I have just been notified by the building that protesters have gathered on Wacker and Michigan. Arrests have been made. Your safety is our #1 concern so I advise everyone in the office to avoid the building's Wacker exits. You should exit via South Water Street or Stetson.


Please be careful when exiting the office.

NATO Summit Journal, 4:48pm.
The fighting is inside the building. The announcement went out just before power was cut to the elevators. I don't know if the underground Pedway system will be salvation, or a death trap. Either way, I have to move NOW.

NATO Summit Journal, 5:11pm. 
The Pedway is choked with the bodies of the dead and dying. I'll have to find another way.

NATO Summit Journal, 5:24pm.
My gods, I saw one. A NATO Dignitary. Under the eerie red sky, he was striding through the crowd, chest, shoulders and head above the tallest protester. His arms stretched impossibly far, and his too-long fingers coiled around someone's neck. His jaw unhinged like a python, and... I'm no hero. I ran.
The media was right. They wear suits. Tell everyone -- you will know them by their suits.

NATO Summit Journal, 5:39pm.
This isn't me. I give my seat to old ladies on the train, I don't grab them by the arm and pull them off to make room to board. What has this Summit done to me? What have I become?

NATO Summit Journal, 6:55pm, final entry.
I've escaped. Back in my neighborhood, far from downtown, the sun is shining and the sky is a soft, powdery blue. Birds chirp, a dog barks, and the scent of lilacs fills the air. My daughter plays in the garden. Here, one could believe that all the hype and worry over the Summit was overblown. One could almost believe that life will go on.

THE END.


Enhanced by Zemanta

Friday, March 25, 2011

AWS: Here's how you subscribe an SQS queue to an SNS topic!

Amazon Web Services logoImage via Wikipedia
There's precious few code examples for subscribing an Amazon Web Services' SQS queue to an SNS topic, especially using the SDK for Java. I've finally figured it out, and this is my way of giving back to the authors of all the hints I could find around the Web. The tricky part is the queue policy; if you create it incorrectly, you won't see any error messages -- it just won't work.

The methodology is this:
  1. Create an SNS topic.
  2. Set a policy on the topic to allow subscriptions.
  3. Create an SQS queue.
  4. Set a policy on the queue to allow message posting.
  5. Subscribe the queue to the topic.
  6. Wait for AWS settings to propagate and "take."
  7. Send an SNS notification message.
  8. Listen for the message on the queue.
And here's the code:


public class SnsWithSqsDemo {
private static final Log LOG = LogFactory.getLog(SnsWithSqsDemo.class);
private static final String TOPIC_NAME = "TestTopic";
private static final String QUEUE_NAME = "TestQueue";

/**
* This program demonstrates how to hook up an AWS SQS queue to an AWS SNS
* topic to receive messages.
*
* 1. Create an SNS topic.
* 2. Set a policy on the topic to allow subscriptions.
* 3. Create an SQS queue.
* 4. Set a policy on the queue to allow message posting.
* 5. Subscribe the queue to the topic.
* 6. Wait for AWS settings to propagate and "take."
* 7. Send an SNS notification message.
* 8. Listen for the message on the queue.
*
* @param args not used
*/
public static void main(String[] args) {
AWSCredentials awsCredentials = null;
AmazonSNS sns = null;
AmazonSQS sqs = null;
String topicArn = null;
String queueUrl = null;
String queueArn = null;
String subscriptionArn = null;
LOG.debug("Beginning.");
try {
awsCredentials =
new PropertiesCredentials(
SnsWithSqsDemo.class.getResourceAsStream("AwsCredentials.properties"));
sns = new AmazonSNSClient(awsCredentials);
// 1. Create a topic
System.out.println("Step 1. Create an SNS topic.");
CreateTopicResult ctResult =
sns.createTopic(new CreateTopicRequest(TOPIC_NAME));
topicArn = ctResult.getTopicArn();
System.out.println(String.format("Created topic %s with ARN %s",
TOPIC_NAME, topicArn));
// 2. Set policy on topic to allow open subscriptions
System.out.println("Step 2. Set a policy on the topic to allow subscriptions.");
Policy snsPolicy =
new Policy().withStatements(
new Statement(Effect.Allow)
.withPrincipals(Principal.AllUsers)
.withActions(SNSActions.Subscribe));
System.out.println("Set SNS policy: " + snsPolicy.toJson());
sns.setTopicAttributes(new SetTopicAttributesRequest(
topicArn, "Policy", snsPolicy.toJson()));
// 3. Create a queue
System.out.println("Step 3. Create an SQS queue.");
sqs = new AmazonSQSClient(awsCredentials);
CreateQueueResult cqResult =
sqs.createQueue(new CreateQueueRequest(QUEUE_NAME));
queueUrl = cqResult.getQueueUrl();
System.out.println(String.format("Created queue %s with URL %s",
QUEUE_NAME, queueUrl));
GetQueueAttributesResult queueArnResult =
sqs.getQueueAttributes(new GetQueueAttributesRequest(queueUrl)
.withAttributeNames("QueueArn"));
queueArn = queueArnResult.getAttributes().get("QueueArn");
System.out.println("Queue ARN = " + queueArn);
// 4. Set the queue policy to allow SNS to publish messages
System.out.println("Step 4. Set a policy on the queue to allow message posting.");
Policy sqsPolicy =
new Policy().withStatements(
new Statement(Effect.Allow)
.withPrincipals(Principal.AllUsers)
.withResources(new Resource(queueArn)) // Note: queue, not topic
.withActions(SQSActions.SendMessage)
.withConditions(
ConditionFactory.newSourceArnCondition(topicArn)));
Map queueAttributes = new HashMap();
queueAttributes.put("Policy", sqsPolicy.toJson());
sqs.setQueueAttributes(new SetQueueAttributesRequest(queueUrl, queueAttributes));
System.out.println("Set SQS policy to " + queueUrl + ": " + sqsPolicy.toJson());
// 5. Subscribe the queue to the topic
System.out.println("Step 5. Subscribe the queue to the topic.");
SubscribeResult sResult =
sns.subscribe(new SubscribeRequest(topicArn, "sqs", queueArn));
subscriptionArn = sResult.getSubscriptionArn();
System.out.println("Subscription ARN: " + subscriptionArn);
// 6. Wait a bit for AWS to get all synched-up
System.out.println("Step 6. Wait for AWS settings to propagate and \"take.\"");
Thread.sleep(60000L);
// 6.1. Verify queue attributes
GetQueueAttributesResult gqaResult =
sqs.getQueueAttributes(new GetQueueAttributesRequest(queueUrl)
.withAttributeNames("Policy", "QueueArn", "ApproximateNumberOfMessages"));
if (gqaResult.getAttributes().size() == 0) {
System.out.println("Queue " + QUEUE_NAME + " has no attributes");
} else {
System.out.println("Attributes for " + QUEUE_NAME);
for (String key : gqaResult.getAttributes().keySet()) {
System.out.println(String.format("\t%s = %s",
key, gqaResult.getAttributes().get(key)));
}
}
// 6.2. Verify topic attributes
GetTopicAttributesResult gtaResult =
sns.getTopicAttributes(new GetTopicAttributesRequest(topicArn));
if (gtaResult.getAttributes().size() == 0) {
System.out.println("Topic " + TOPIC_NAME + " has no attributes");
} else {
System.out.println("Attributes for " + TOPIC_NAME);
for (String key : gtaResult.getAttributes().keySet()) {
System.out.println(String.format("\t%s = %s",
key, gtaResult.getAttributes().get(key)));
}
}
// 6.3. Verify subscription
ListSubscriptionsByTopicResult lsbtResult =
sns.listSubscriptionsByTopic(new ListSubscriptionsByTopicRequest(topicArn));
if (lsbtResult.getSubscriptions().size() == 0) {
System.out.println("Topic " + TOPIC_NAME + " has no subscriptions.");
} else {
System.out.println("Subscriptions for " + TOPIC_NAME);
for (Subscription subscription : lsbtResult.getSubscriptions()) {
System.out.println("\t" + subscription.getProtocol() + ": "
+ subscription.getEndpoint());
}
}
// 7. Send a notification
System.out.println("Step 7. Send an SNS notification message.");
PublishResult pResult =
sns.publish(new PublishRequest(topicArn,
"Mr Watson -- Come here -- I want to see you."));
System.out.println("Sent message ID = " + pResult.getMessageId());
// 8. Wait for message receipt in queue
System.out.println("Step 8. Listen for the message on the queue.");
for (int i = 0; i < 10; i++) { Thread.sleep(2000L); ReceiveMessageResult rmResult = sqs.receiveMessage(new ReceiveMessageRequest(queueUrl)); if (rmResult.getMessages().size() > 0) {
// A message has been received
for (Message message : rmResult.getMessages()) {
System.out.println(message.getBody());
sqs.deleteMessage(new DeleteMessageRequest(queueUrl,
message.getReceiptHandle()));
}
break;
} else {
// ??? Why aren't we receiving messages?
System.out.println("No messages available, attempt " + (i+1));
}
}
} catch (Exception e) {
e.printStackTrace(System.err);
} finally {
System.out.println("Shutting down...");
// Unsubscribe the queue from the topic
if (sns != null && subscriptionArn != null) {
sns.unsubscribe(new UnsubscribeRequest(subscriptionArn));
System.out.println("Unsubscribed queue from topic.");
}
// Destroy queue
if (sqs != null && queueUrl != null) {
sqs.deleteQueue(new DeleteQueueRequest(queueUrl));
System.out.println("Deleted the queue.");
sqs.shutdown();
}
// Destroy topic
if (sns != null && topicArn != null) {
sns.deleteTopic(new DeleteTopicRequest(topicArn));
System.out.println("Deleted the topic.");
sns.shutdown();
}
}
LOG.debug("Done.");
}

}

Enhanced by Zemanta

Thursday, March 24, 2011

AWS: How do you subscribe an SQS queue to an SNS topic?

Image representing Amazon Web Services as depi...Image via CrunchBase
If there are any AWS (Amazon Web Services) gurus out there, I'm stumped on trying to use a Simple Queue Service queue to receive notifications sent out on a Simple Notification Service topic. Any pointers?

In the code below, I'm using the AWS SDK for Java (available here). The program does the following:


  1. Create an SNS topic.
  2. Set a policy on the topic to allow subscriptions.
  3. Create an SQS queue.
  4. Set a policy on the queue to allow message posting.
  5. Subscribe the queue to the topic.
  6. Send an SNS notification message.
  7. Listen for the message on the queue.
Steps 1-6 seem to work just fine, but on step 7, it listens in vain for messages. All ten iterations go by without picking up any messages on the queue. As an added note, if I subscribe an email address to the topic, messages are delivered. Only the queue appears to be bypassed when SNS sends its notifications.


public class SnsWithSqsDemo {
private static final String TOPIC_NAME = "TestTopic";
private static final String QUEUE_NAME = "TestQueue";

/**
* This program demonstrates how to hook up an AWS SQS queue to an AWS SNS
* topic to receive messages.
*
* 1. Create an SNS topic.
* 2. Set a policy on the topic to allow subscriptions.
* 3. Create an SQS queue.
* 4. Set a policy on the queue to allow message posting.
* 5. Subscribe the queue to the topic.
* 6. Send an SNS notification message.
* 7. Listen for the message on the queue.
*
* @param args not used
*/
public static void main(String[] args) {
AWSCredentials awsCredentials = null;
AmazonSNS sns = null;
AmazonSQS sqs = null;
String topicArn = null;
String queueUrl = null;
String queueArn = null;
String subscriptionArn = null;
try {
awsCredentials =
new PropertiesCredentials(
SnsWithSqsDemo.class.getResourceAsStream("AwsCredentials.properties"));
sns = new AmazonSNSClient(awsCredentials);
// 1. Create a topic
CreateTopicResult ctResult =
sns.createTopic(new CreateTopicRequest(TOPIC_NAME));
topicArn = ctResult.getTopicArn();
System.out.println(String.format("Created topic %s with ARN %s",
TOPIC_NAME, topicArn));
// 2. Set policy on topic to allow open subscriptions
Policy snsPolicy =
new Policy().withStatements(
new Statement(Effect.Allow)
.withPrincipals(Principal.AllUsers)
.withActions(SNSActions.Subscribe));
// ??? Is there no Java SDK constant for "Policy"?
sns.setTopicAttributes(new SetTopicAttributesRequest(
topicArn, "Policy", snsPolicy.toJson()));
// 3. Create a queue
sqs = new AmazonSQSClient(awsCredentials);
CreateQueueResult cqResult =
sqs.createQueue(new CreateQueueRequest(QUEUE_NAME));
queueUrl = cqResult.getQueueUrl();
System.out.println(String.format("Created queue %s with URL %s",
QUEUE_NAME, queueUrl));
// 4. Set the queue policy to allow SNS to publish messages
Policy sqsPolicy =
new Policy().withStatements(
new Statement(Effect.Allow)
.withPrincipals(Principal.AllUsers)
.withActions(SQSActions.SendMessage)
.withConditions(ConditionFactory.newSourceArnCondition(topicArn)));
Map queueAttributes = new HashMap();
queueAttributes.put("Policy", sqsPolicy.toJson());
sqs.setQueueAttributes(new SetQueueAttributesRequest(queueUrl, queueAttributes));
// ??? Why isn't the queue ARN in the queue attributes?
AmazonIdentityManagement idMgr = new AmazonIdentityManagementClient(awsCredentials);
String accountId = idMgr.getUser().getUser().getUserId();
queueArn = String.format("arn:aws:sqs:us-east-1:%s:%s", accountId, QUEUE_NAME);
// 5. Subscribe the queue to the topic
SubscribeResult sResult =
sns.subscribe(new SubscribeRequest(topicArn, "sqs", queueArn));
subscriptionArn = sResult.getSubscriptionArn();
System.out.println("Subscription ARN: " + subscriptionArn);
// 5.5. Wait a bit for AWS to get all synched-up
Thread.sleep(60000L);
// 6. Send a notification
PublishResult pResult =
sns.publish(new PublishRequest(topicArn,
"Mr Watson -- Come here -- I want to see you."));
System.out.println("Sent message ID = " + pResult.getMessageId());
// 7. Wait for message receipt in queue
for (int i = 0; i < 10; i++) { Thread.sleep(2000L); ReceiveMessageResult rmResult = sqs.receiveMessage(new ReceiveMessageRequest(queueUrl)); if (rmResult.getMessages().size() > 0) {
// A message has been received
for (Message message : rmResult.getMessages()) {
System.out.println(message.getBody());
sqs.deleteMessage(new DeleteMessageRequest(queueUrl,
message.getReceiptHandle()));
}
break;
} else {
System.out.println("No messages available, attempt " + (i+1));
}
}
} catch (Exception e) {
e.printStackTrace(System.err);
} finally {
// Unsubscribe the queue from the topic
if (sns != null && subscriptionArn != null) {
sns.unsubscribe(new UnsubscribeRequest(subscriptionArn));
System.out.println("Unsubscribed queue from topic.");
}
// Destroy queue
if (sqs != null && queueUrl != null) {
sqs.deleteQueue(new DeleteQueueRequest(queueUrl));
System.out.println("Deleted the queue.");
sqs.shutdown();
}
// Destroy topic
if (sns != null && topicArn != null) {
sns.deleteTopic(new DeleteTopicRequest(topicArn));
System.out.println("Deleted the topic.");
sns.shutdown();
}
}
}

}


Enhanced by Zemanta

Saturday, February 19, 2011

2011: My Android Year

Android robot logo.Image via Wikipedia
Gadget journalism on the Web seems to be held to the same standard as entertainment journalism, meaning rumors, guesswork and hype make up most of my Google News alerts and Twitter feeds. But (like entertainment journalism, to those who follow it), the hype is strangely addictive. And the hype isn't just about a new device hitting the shelves, but upcoming announcements about devices that won't see a shelf for months, or even announcements about upcoming announcements. It starts with leaked device code-names or Photoshopped concept images, then there are unconfirmed spec sheets and rumored release dates, followed by official teasers and then trade show releases (with the hands-on videos and device comparison sheets). Finally, YouTube starts getting the gadget version of amateur porn: the unboxing videos. It's an information strip-tease, showing just enough to catch the attention and drive the imagination wild with what isn't revealed.

I'm not an early adopter of technology, and when something starts to get exciting, I research it for months before I make the jump. I've been carrying around a Windows Mobile phone (the HTC Touch Pro 2), top-class technology that integrated well with work when I bought it, but it seems that Microsoft as a mobile platform is moribund, while Android is the new market share powerhouse. In early 2010, I started following rumors of a beast of an Android phone called the HTC "Scorpion" and for the next year, I submerged myself in Android hype. By January's Consumer Electronics Show, I was sold on two or three Android devices scheduled to release in the first half of the year.

I'd followed a rumored Motorola Android tablet code-named "Stingray," which was introduced at CES as the "Xoom." The Xoom is the hardware reference for Google's new release of Android, version 3.0 dubbed "Honeycomb," and it boasts a dual-core processor, rear- and front-facing cameras for video chats and HDMI output among its features. When the iPad came out, I couldn't understand where it fit in the gadget ecosystem: was it a bulky smartphone (sans calls), an underpowered laptop or a high-eyestrain eBook reader? Then, as I moved many of my computer activities into the cloud, live-blogged from geek conventions and trips, and grew weary of taking my laptop out of my carry-on at airport security, I began to realize that the tablet was the ideal travel laptop. The more I researched the applications and accessories (like a Bluetooth keyboard) that would be available, the more the tablet's niche solidified:

  • Live-blogging
  • Travel laptop that stays in the carry-on, through security
  • Garmin navigator replacement
  • Stream media (Netflix, Hulu, etc.) to any TV
  • SSH into my work computers and Amazon EC2 instances
  • Portable movies
  • Document editing (with Google Docs)

As of this writing, the Xoom is supposed to release on February 24, 2011. But that information comes from the gadget rags: Motorola and Verizon are silent on the topic.

As for the Android phone, up until CES 2011, I was looking forward to the HTC Thunderbolt, billed as "Not your dream phone. The one after that." It's sleek like the Nexus One, thin but with a huge 4.3" screen. It's the first "4G" phone on Verizon's LTE network. But Motorola came to CES with a surprise: the heretofore un-hyped (and unheard of) DROID Bionic, with a dual-core processor (the Thunderbolt's is single-core), more on-board storage and an HDMI-out port. The Bionic's case is not as pretty as the Thunderbolt's, but it seems to be more of a powerhouse. Even if Android 2.2 doesn't utilize dual core processors (and that's a big IF -- I haven't seen it categorically demonstrated that this is the case), Android 2.4 will, and software always evolves to push the hardware. The Bionic will have staying power. My wife surprised me by turning down an iPhone to replace her dying BlackBerry Storm, so I'm going to get her the Thunderbolt and stick with my Windows Mobile phone until the Bionic comes out. I'll be able to do some real comparisons then.

Now, I wait. Neither Verizon, nor HTC nor Motorola have made an official statement about release dates, but the current rumor-mill has the Motorola Xoom releasing on February 24 2011, the HTC Thunderbolt releasing on February 28 2011, and the Motorola DROID Bionic releasing in June 2011. After that, I'll have to wean myself off of Android hype news, and enjoy what I have instead of lusting after the next cool thing.
Enhanced by Zemanta

Monday, January 24, 2011

Amrut Fusion: the acclaimed single malt whisky from... India??

Whisky writer Jim Murray named Amrut Fusion Single Malt the world's third finest whisky, giving it 97 out of 100 points. What's interesting is that Amrut Fusion isn't a product of Scotland, or Ireland or even Kentucky. This whisky comes from Bangalore India, a city known for outsourced information technology rather than fine spirits. As a friend put it, "Beating the English at Cricket or Soccer, well that's just fun... but beating the Scots and Irish at booze... that I have to taste!"

As did I. And this evening, my wife came home from work with a surprise for me. The local Binny's Beverage Depot carries the entire line of Amrut products. "Amrut" in Hindu mythology is the nectar of the gods. I've been looking forward to pouring a glass and sharing the experience with you. Let's begin!

This whisky is a lovely light amber color, and its aroma hits you right as you pour it: the first whiff reminds me of cedar and cherry. It's a very fresh profile, but if you stick your nose in the glass like a wine taster, you can smell an undercurrent of smoke and maybe a hint of peat.

My first sip bites at the tip of my tongue like a super-hot chutney. This is not a whisky I would typically drink neat. It's rough on the tongue, but full of flavors of fruit and vanilla-oak, with cloves and orange rind simmering at the back of the throat after it goes down. I'm not well-versed in whisky, but I've tasted a fair bit of wine, and Amrut Fusion has the same level of complexity I'd find in some of my favorite wines. It changes in your mouth, from the sharp, sweet attack at the tip of the tongue, to a spicy, smoky robustness at the end.

The Indian men of my parents' generation love their Canadian Club, and get excited when they get their hands on a bottle of Chivas Regal. Now, they can drink something light years ahead of their old standards. And best of all, it's from their homeland. Amrut, you've made a drink worthy of the name.
Enhanced by Zemanta