Well

Well, that's out of my system. No more geeky stuff for a little while, I promise.

ClearQuest SOA: Part V/The Consumer

This is part 5 in a series about ClearQuest and SOA. If you're not a CQ geek, you'll want to skip this. If you're interested in playing along, go over to that first article and get set up.

In past conversations, we created a producer. It's sitting out there waiting for somebody to come along and ask it to produce something. The something it can produce are ClearQuest query results. This time, we'll create two consumers. To show the range of possibilities, we'll create one using Perl and one using an Ant task, written in java.

We're using RPC calls, so the important thing to start with is: we're looking to run the method called query.run. We'll feed it the name of a query. It will respond to us with a structured set of hashes. Since the communication between our producer and any particular consumer is via XML, it doesn't matter what language we use to write the consumer. So, since we wrote the producer in Perl, let's write a quick test script in Perl.

In the tests directory, create a file called consumertest.pl and edit it. We want to see if we can connect to the URL, pass it a method and parameter, and absorb results. My script looks like this:

# Use the frontier client to help us create and talk to the XML
# from RPC calls
use Frontier::Client;
# we need to know what URL to talk to
my $url = "http://localhost/cgi-bin/cqws.pl";
# Create a new client (attachment to the producer)
my $client = Frontier::Client->new(
url => $url,
debug => 1,
); # the debug will show the xml that's moving around!
# decide which query to run (and name the method we're calling)
my $name = "Public Queries/All Defects";
my $method = "query.run";
print "Testing with " . $name . "\n";
# -- this line is slightly different than our last test
my $queryResult = $client->call($method,$name);

# everything else is the same as our last test
foreach ( @$queryResult )
{
my $record = $_;
foreach ( sort keys %$record)
{
print "\tcolumn: $_ \tvalue: " . $record->{$_} . "\n";
}
print "\n";
}
Now, you run this script by typing perl consumertest.pl, and it's going to go to your producer via http to get the information it needs. There will be a lot of verbose output because we have debug set to 1, so the first thing you should see is:

Testing with Public Queries/All Defects
---- request ----
<?xml version="1.0"?>
<methodCall>
<methodName>query.run</methodName>
<params>
<param><value><string>Public Queries/All Defects</string></value></param>
</params>
</methodCall>
This represents the request. It might pause a moment while waiting for the producer's response. When it comes, it'll look like:

---- response ----
<?xml version="1.0"?>
<methodResponse>
<params>
<param><value><array><data>
<value><struct>
<member><name>Contact</name><value><string></string></value></member>
<member><name>dbid</name><value><i4>33555483</i4></value></member>
<member><name>Headline</name><value><string>Test Ant Task</string></value></member>
<member><name>id</name><value><string>SAMPL00001051</string></value></member>
Only more so, I suppose. This is the XML that's being returned by the system. Don't worry about that XML, though. It's only showing because we have debug turned on. What we really care about is that the Frontier client will hear that XML and turn it into a reference to an array of hashes that we can iterate over and print out. The valuable output is the final bit that looks like this:
column: Contact value:
column: Headline value: Test Ant Task
column: State value: Submitted
column: dbid value: 33555483
column: id value: SAMPL00001051
Well, that's just grand there, bucko, you're saying to yourself. So, we can have a perl script call another perl script. Big deal. Ok. The exciting part (if you have a low excitement threshold) is that a) we could repeat this now with the producer on one machine and the consumer on another (the only necessary change would be the URL in the consumer) and 2) we can instead make the consumer in some other language, like Java. Our next step, in fact, is to create ourselves an ant task that will run some query.

We're going to need some special stuff now. I want you to make a directory called antstuff. In the antstuff directory, create subdirectories called classes, lib, and src. Go out onto the web and find these jars:

Drop those jars into the antstuff\lib directory. We need them to create ant tasks.

Great. Now, we'll want to create a build file with a target for building our task and one for using the task to run a query. We'll need to create an ant task with Java. Create a file called CQQuery.java in the antstuff\src directory. Edit it to look like this:

// these are classes we use for any ant task
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;
// these are classes we need to take care of the RPC communication
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
// we'll need util just because
import java.util.*;

// every ant task starts off like this:
public class CQQuery extends Task {
String sURL; // the url we'll go to
String sMethod; // the name of the method we'll call
String sParameter; // the value that will be passed in
// the method call. For us it'll be the name of a query
// but maybe we'll want some other parameter for some other
// method.

// these setters all relate to things
// you'll pass in from the build.xml
// Notice how the name relates to the parameter in the
// build.xml file
public void setURL(String u) {
  sURL = u;
}

public void setMethod(String m) {
  sMethod = m;
}

public void setParameter(String p) {
&nbps; sParameter = p;
}

// this is where we do the deed
public void execute() {
// verify there is a producer provided
// (otherwise fail the "build")
if ( sURL==null ) {
throw new BuildException("ERROR: need URL");
}
// need to know what method to call
if ( sMethod==null ) {
throw new BuildException("ERROR: need name of method");
}
// let's provide a little feedback to the user
log("Calling " + sURL + " to execute " + sMethod);
log("The parameter is: " + sParameter);

Object[] paramSet = new Object[] {sParameter};

// try to connect and ask to run our method
try {
XmlRpcClientConfigImpl rpcConfig = new XmlRpcClientConfigImpl();
rpcConfig.setServerURL(new java.net.URL(sURL));

XmlRpcClient rpcClient = new XmlRpcClient();
rpcClient.setConfig(rpcConfig);
// assume the result is always an ARRAY of HASHes
Object[] resultSet = (Object[]) rpcClient.execute(sMethod,paramSet);
for ( int i = 0; i < resultSet.length; i++) {
// add some error checking later
HashMap hResultSet = (HashMap) resultSet[i];
Set myKeys = hResultSet.keySet();
for ( Iterator it = myKeys.iterator(); it.hasNext();) {
Object k = it.next();
Object rs = hResultSet.get(k);
log(" " + k.toString() + ":" + rs.toString());
}
}
} catch (Exception ex) {
System.err.println("Error @ XmlRPcClient: " + ex.getMessage());
}
}
}
When we compile that, we'll have a little jar with an ant task in it that we can call in an ant target. Save this in a build.xml file and you'll be able to compile the jar and also run a query against CQ across the magical internet.

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="CQTasks" basedir="." default="jar">
<!-- properties for the compile -->
<property name="src.dir" value="${basedir}/src"/>
<property name="classes.dir" value="${basedir}/classes"/>
<property name="lib.dir" value="${basedir}/lib"/>

<target name="clean" description="Delete all generated files">
  <delete dir="${classes.dir}" failonerror="false"/>
  <delete file="${ant.project.name}.jar"/>
</target>

<target name="compile" description="Compiles the Task">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}">
<classpath>
<pathelement location="${lib.dir}/xmlrpc-client-3.0rc1.jar"/>
<pathelement location="${lib.dir}/xmlrpc-common-3.0rc1.jar"/>

</classpath>
</javac>
</target>
<target name="jar" description="JARs the Task" depends="compile">
<jar destfile="${ant.project.name}.jar">
<fileset dir="${classes.dir}"/>
<fileset dir="${lib.dir}"/>
</jar>
</target>


<target name="test_query" description="Use the task to do things" depends="jar">
<taskdef name="cqquery" classname="CQQuery">
<classpath>
<pathelement location="${ant.project.name}.jar"/>
<pathelement location="${lib.dir}/xmlrpc-client-3.0rc1.jar"/>
<pathelement location="${lib.dir}/xmlrpc-common-3.0rc1.jar"/>
<pathelement location="${lib.dir}/ws-commons-util-1.0.1.jar"/>
<pathelement location="${lib.dir}/ws-commons-java5-1.0.1.jar"/>
</classpath>
</taskdef>
<cqquery url="http://localhost/cgi-bin/cqws.pl" method="query.run" parameter="Public Queries/All Defects"/>

</target>

</project>
There ya go! From the command line, run ant jar to make sure the code we wrote compiles. Or run ant test_query to get the thing to run against your producer. My output from this run is:


Buildfile: build.xml

compile:

jar:

test_query:
  [cqquery] Calling http://localhost/cgi-bin/cqws.pl to execute query.run
  [cqquery] The parameter is: Public Queries/All Defects
  [cqquery]  State:Submitted
  [cqquery]  Contact:
  [cqquery]  Headline:Test Ant Task
  [cqquery]  dbid:33555483
  [cqquery]  id:SAMPL00001051
So, we are done. We installed ClearQuest and a web server, then we made a set of perl scripts to run a named ClearQuest query. We also wrote a little perl script that accepts the requests via XML (using RPC). Finally, we wrote some clients in perl and in Java to make the requests and get the responses. This last client can run from anywhere we can run Java! No install of CQ necessary on the client side.

I'll leave it to you to do all the other things that ought to be done to make this useful, like error trapping, changing into real, useful perl modules, fixing up that classpath loading, passing user credentials and making even more generic.


All the parts in this series:

How the Other Half Lives

If only it really were half & half

This doesn't have a subheading of "tale," so it is absolutely true, at least as far as my memory serves me.

Sometimes the world reminds us that living in our little community is different from living in other little communities.

On Sunday morning, the Brunette volunteered to help the run in Rock Creek Park that generated aid for women in Congo. I dropped her off and wandered over to the nearest Starbucks to surf the web do some work. The nearest Starbuck was just south of Chevy Chase Circle, one of the nicest areas of the District. Lots of hoity toities there.

After I exhausted my battery, I walked around a bit. There's a large fountain in the Chevy Chase Circle, built in the '30s. Far as I could tell, there was no legal way to walk over to the fountain, since it was in the center of the circle. But since there were benches arrayed around it, I thought it worth the legal risk to wander across and read for a bit.

Eventually, the drizzle was too much for me to risk a book to. But it was fine for walking, so I wandered around the neighborhood gaping at the big ole houses and finely manicured lawns. I stopped by their Safeway before driving back to the park. The cashier had some candy bars for sale supporting one of those be-ribboned causes. I believe it was breast cancer. At any rate, the cashier asked the gentleman in front of me if he'd like to buy a bar.

"No," he said emphatically. "I don't believe in charity. This is a dog-eat-dog world. People need to learn to look out for themselves."

I'm sure that cancer victims would be thrilled to hear they just need to pull up their own dang bootstraps. The cashier nodded slowly and finished his transaction. She asked him if he needed any help carrying his bags to his car. I waited poised to jump in with a comment, but he said, "No."

"Better not have," I said to the cashier. "That would have been charity."

Bikers Welcome

I rode my bike up to the Whole Foods in Silver Spring the other day. It was my lunch break and I thought it'd be a quick jaunt. When I got there, I discovered that the bike parking was serving not only as a place to rest the signs of local businesses, but as an anchor to lock them to, as well.

Which meant, of course, that only one of the spots was useful. Way to be bike-friendly Silver Spring!

Luce Women

Well, Cat's Eye horrified me with its depiction of the evil machinations of teenage girls and how they torture each other. We dropped by a revival of Clare Boothe Luce's The Women last night. Clare Boothe Luce eventually became an ultra-conservative Republican politician and diplomat who was held up as a strong opponent of FDR's plans. Perhaps this explains the misogynistic feel to her play. It is populated by grown up versions of Atwood's evil girls. This performance at the Greenbelt Arts Center was full of conniving women and sadly empty relationships.

It was also quite funny.

I suppose it might be insulting to say that Claire Williams was born to play Sylvia? She wakes up the rest of the cast and forcibly drags them through the action. She was an unsinkable Molly Brown, but with claws. I think she did a great job of pushing Sylvia to the edge of caricature. If she had reined it in even the slightest bit, we would have come away more disillusioned and angry; instead, we can laugh off the hurt in this play like we might laugh off the cartoonish violence of Wile E. Coyote.

Mostly, anyway.

Lori Libes also helped balance the hatred with her portrayal of Peggy. Peggy's reserve was the opposite of Sylvia's mania. Her expressive face reflected the turbulence of this little world created by the splashing around of the more externalized characters. Poor Peggy was buffeted and bruised by these backstabbing women, though she was not their main target. Everybody gets hurt by hurtful society, I guess.

Speaking of hatred, I have to say I hated the stage. At first, the complicated turn-table fascinated that gadget-fixated part of my brain. But eventually, it became a distraction. It was frustrating to see this Rube Goldberg contraption absorbing so much time in set up and scene modification. One would have thought that the only point of such a device would be to ease scene transition, but it seemed to require six helpers at several points in the play to move things on and off the great wheel. I'm particularly thinking of the scene changes required to set up the shopping scene in the first act.

But that's a minor quibble. Consider this thing a period piece and you'll enjoy the catty humor a lot, I think. And perhaps it'll also give you pause in thinking about "women's inhumanity toward woman."

You Have Answers? We Have Questions!

OK. I'm putting these here in case somebody comes along and can help. Or in case I figure out the answer and can put it here. Or in case I run out of the building screaming and flailing my arms: you'll know why.

ClearQuest Web 7.0
So, we've upgraded our little ClearQuest installation from 2003.06.15 to 7.0. It was exciting and fun and all that. So far, the only real differences I've noticed are:
  • The program icons have changed (but not the client interfaces otherwise)
  • The web server now asks for the database on the login page (like it used to a long time ago, but then didn't any more last year)
  • It demands you upgrade your Access .mdbs to a newer version of Access
We operate in a reverse proxy mode, with our web server being real Apache (not IBM's stripped down thing) funneling requests back to the Rational Web Platform running on a different port. We do this so we can have other apps running on the same web server as our ClearQuest. Ever since the upgrade, the ClearQuest Web has been "forgetting" its list of SchemaRepositories every few hours. All you have to do is go in and restart the CQ Registry Service and they reappear (we're on Windows), but a few hours will pass and the login page will once again have an empty list for SchemaRepositories (and databases, for that matter).

My workaround has been to create a scheduled task to restart the CQ Registry service every four hours. Ah, I love Windows.

CruiseControl, Subversion and Java 1.5
We're switching our application over to WebLogic 9.2, which will require us to move to Java 1.5. However, I still need to build in both 1.4 and 1.5. I haven't quite been able to get CruiseControl to build 1.5, yet, because its modificationset task dies with:
[cc]Sep-21 12:51:25 SVN - Error executing svn log command svn log --no n-interactive --xml -v -r {2006-09-21T16:35:04Z}:{2006-09-21T16:51:25Z} http://s ubversion.server/my_repository/branches/my_branch
java.io.IOException: The handle is invalid
at java.io.FileInputStream.close0(Native Method)
at java.io.FileInputStream.close(FileInputStream.java:245)
at net.sourceforge.cruisecontrol.sourcecontrols.SVN.execHistoryCommand(S VN.java:255)

StatCounter

I love my weekly statcounter reports (though they came a few days late this week). The keyword activity tells me what people are searching for (all twelve of them) when they find me through a search engine. They're looking for:

  • how is qualxserve Yeah, this one's recent because of my fun with Dell. The second guy was great: he called to keep me updated as his schedule changed through the morning, he actually showed up, and he fixed my laptop. But the company itself has to faulted: they are over-scheduling their tech reps, they do not handle non-stationary customers very well (don't get into the wrong territory!), and they do not have an escalation process
  • clearquest get count reference list This one pops up a lot, but I'm sure I've never addressed getting a count from a reference list. Is that really all you're looking for? You want to know how to count how many items are in a reference list? Or is it something else? Do you want it in Perl or VB?
  • dog puns Lots of these all of a sudden. I think I titled one of my posts "No Dog Puns" or something. Which ought to be self-explanatory: we don't have any dog puns on this site, so there's no need to "terrier" here any longer.
  • molten sulfer Oh, yeah, this blog is a hot-bed of molten sulfer information, let me tell you. I think I mentioned molten sulfer once, because I can watch trains carrying it go by in my window at work. But it was actually DC Cube who pointed us to what it might be.
  • don't ha ha ha paddy clarke I get a lot of searches that look like book report trolls to me. Not a lot this week, though. I don't get the "don't" on the front of this search. I wonder if the title overseas had "don't" in it.

A Walk in the Woods (Bill Bryson)

"I think we were somewhere in Ohio when I decided to kill you," the Brunette told me.

"What?"

"Was it Findlay? Upper Sandusky?" She looked at the ceiling fan as if it might remember.

"You decided to kill me in Upper Sandusky, Ohio?" I asked.

"No," she said after pondering for a moment. "It was definitely before we got to Upper Sandusky."

I had been waxing poetic about Bill Bryson's book, A Walk in the Woods, when she sprung (sprang?) this planning for my demise thing on me. I liked Bryson's easy style and his humorous descriptions of various hikes along the Appalachian Trail. I related several of the funny anecdotes to my partner. It's possible I described the town in Pennsylvania that is perpetually on fire. I might have mentioned Bryson's fear of bears. It is conceivable that I suggested that it might be fun -- maybe -- if we tried the hike ourselves. A little walk to help cement the ties of our marriage.

"The AT is over two thousand miles long," she pointed out. I've tried to explain to her that this unusual attachment to putting "value" on "facts" like these is going to hold her back in life. She generally responds with some unrelated comment about "maps", "inability to read", and "two months forever wiped away, never to be recovered."

"I think it was when we rolled into McKeesport (near Pittsburgh) that I decided to never talk to you again," she continued. "But then I thought that might make it hard to keep close enough to kill you." I was beginning to think she might not be whole-heartedly behind the couple-conquering-the-wilderness concept.

"He never actually saw a bear," I pointed out. "At least, he wasn't sure if he ever did."

"Bears are not the issue," she said.

"Not that many people actually died on the trail."

"Did Bryson's wife go along?" she asked, significantly.

"Well, no. He went with his overweight friend. He was the funniest part." I told the story of his friend throwing away half their food because it was too heavy. She gave me a look I hadn't seen since we tried to bike across the country."There was Wisconsin, you know."

The ride up the Potomac from Washington to Pittsburgh was pretty much as we had expected, but it rained for most of the journey across Ohio. There were grumpy people in Indiana and Illinois, and Minnesota was hillier than expected. But Wisconsin is a touring cyclist's paradise. We were able to spend hundreds of miles on trails, the people were friendly, and the Brunette got to compete in a pottery tournament. In fact, when we got to Minneapolis, instead of going forward, we decided to bike back into Wisconsin and along the shores of Lake Superior.

She nodded. "Not a single mile of the Appalachian Trail is going to be like Wisconsin. Remember that even on a bicylce, we didn't get 2000 miles. You think you can walk it?"

"1500 miles is nothing to sneeze at," I said defensively. "Besides, think of the wonderful views."

"And where will those views be?"

That one had me stumped. I was pretty sure that 'on the AT' was too obvious to be the answer for which she searched. This is one of those things you learn by living with someone else: usually when people ask you a question, they're not interested in the obvious answer. They could have figured that out on their own. It's not like school, where you could pretty much guess the answer the teacher wanted just by how she phrased the question.

"And do polite people hit their neighbors with spitwads, Billy Blake?" the teacher might ask.

"No, Mrs. Throgmorton," is the answer you know she's looking for, no matter what you think of the politeness due to certain cretin neighbors who had been kicking you in the shin all day long.

It's just not the same in the real world.

"You're stalling," she said, interrupting my train of thought. "What was the most important thing we learned on our trip?"

"Padded bicycle shorts are supposed to be worn without underwear."

"OK," she said. "The second most important thing?"

"Oh, that's easy. Avoid roads that have Hilltop, Valley, and Crest in their names."

"And Mountain View," she added.

"So, why did we move to Ridge Road?" I asked.

"I think you see my point," she said.

"You have to admit, though, you never did kill me," I said.

"I think the third most important thing we learned on that very, very long trip was patience."

Maybe a hike in an isolated patch of wilderness, with no witnesses to speak of and a few too many handy cliffs, is not the best plan after all.

Talk Like a Pirate Day

I'm not much of one for bandwagons, but even the Metro is doing it. ARR Arr.

Computer Woes

A Dell Update

Well, the guy called to let me know he'd be late, but he was only 5 minutes late, and he was good enough to have called me twice. You have to give him credit for that.

And now my computer is working again, so tomorrow I can go back to whinging about something else.

A Time Line

A Dell Report

OK, just to keep everyone on track with my computer woes and to vent my anger a bit, here's a time line.

Tuesday

  • Early Afternoon -- Laptop starts blue screening. Not excited.
  • Mid Afternoon -- Call Dell support (our company has a next-day service contract -- Whicker Support or something). Speak with Neil. Neil is friendly, like all Canadians should be. Neil walks me through some checks to verify it is hardware related.
  • Late Afternoon -- I cut my thumb while removing parts of the laptop under Neil's direction. Neil lets me know that blood on the motherboard will not void my warranty because I did it under his direction.
  • COB -- I leave a diagnostic program running after having moved to an older saved software configuration. I let it run for hours and go home
Wednesday
  • 8:30am -- Neil calls back (on time!) to see how the diagnostics went. Unfortunately, the diagnostics didn't find anything, so we agree it must be a hardware issue. Grand. Neil puts in a ticket to send a part to Maryland and I wait for Dell's service contractor to contact me for an appointment.
  • 12pm -- A representative from QualXserve (or something) calls to tell me that someone will call by noon on Thursday to schedule the appointment. Great, I say, I'll work from Greenbelt tomorrow!
Thursday
  • 1pm -- Nobody has called. I call QualXserve and ask when I might expect someone to schedule arrival today. The call center person apologized. The system shows that the part arrived at 8:30. The call center person will page the tech service rep and I should hear in an hour.
  • 3pm -- Nobody has called. I call QualXserve again. They are very sorry, but will try to get somebody higher up to call me. I mention that the day is getting awfully short. Oh, it'll be within the hour, she says.
  • 4:30pm -- Nobody has called. I call QualXserve again. They are very sorry. They want to try paging again. I wonder how somebody who hasn't scheduled an appointment might possibly be able to schedule, appear and fix my computer before the business day ends in thirty minutes. Perhaps QualXserve has an escalation procedure? Oh, the escalation procedure is to page someone. Perhaps, there is an escalation procedure within the call center? Oh, nobody else seems to be here. So my only escalation option is to go back to Dell?
  • 4:45 -- I fire off an angry email to my new best friend Neil, who eventually responds with an apology.
  • 5:30 -- The tech rep calls! Can he come by tonight? I'm sorry, I'm not sitting around here waiting for a tech rep who may or may not show up; I have to pick up my wife and go get dinner and lord knows what else. He suggests that we might (I am not making this up!) "settle this like adults." I don't know if he means with swords at thirty paces or with an extra cash incentive; either way, I don't like it. I explain that I will not be available tonight. Pehaps he can fix my computer tomorrow. Ah, but tomorrow I'll be in Silver Spring. The tech rep cannot go to Silver Spring. But it's exactly 9.1 miles from where I'm standing now, I exclaim. Not his problem. Perhaps he can give the part to someone who can come to Silver Spring? He'll have to call his boss. Perhaps I would like to have this fixed on Saturday? He can come to my house on Saturday. No, I would like my computer fixed tomorrow. Very sorry, he cannot help me.
Friday
  • 2pm -- The QualXserve guy calls. Wants to know if he can come and fix my computer in Greenbelt. I'm not sure if it's the same guy or not, so I do not say: "What part of the conversation did you not understand yesterday?" No, I explain that I am in Silver Spring today. Can he come to Silver Spring? No, he cannot come to Silver Spring. Perhaps there is somebody who is allowed to venture into Silver Spring? He doesn't know. When might I be in Greenbelt again? I tell him that I will never be in Greenbelt again as far as he is concerned. I made a lot of changes in my schedule to spend my day in Greenbelt and nobody showed up. I have customers to support, too. I need to be able to plan my days. He is sorry that he cannot help me.
  • 4:20pm -- A woman from QualXserve calls. She has me on her schedule as needing help in Greenbelt. I explain to her that I needed help in Greenbelt yesterday. Today, I need help in Silver Spring, perhaps she could have someone in Silver Spring fix my computer? Well, the guy who is scheduled to fix my computer isn't allowed to go to Silver Spring. I refrain from asking if there are border guards at the city limits. She will try to reschedule me with a tech rep from Rockville. Hopefully, Rockville and Silver Spring are both still honoring the ceasefire agreement.
  • 4:45 -- The woman from QualXserve wants to know what address in Silver Spring. Darn! I forgot that West Silver Spring and North Silver Spring are still staring at each other with angry eyes over the DMZ.
  • 4:55 -- The woman from Quallex calls to give me a new dispatch number. I should hear by noon on Monday when somebody might be able to heal my computer. She wants me to have a nice afternoon.
So, right now, I continue to be sans nice computer. I am working on the ratty backup laptop.

The Death of the Internet Economy?

Ok, maybe that's overreacting a bit? I'm pretty sure, though, that something like 85% of our product's traffic comes between 10 and 2 every day. I have to assume that some of these people are actually at a work location.

So if everybody's workplace decided to block 75% of web traffic, are there a lot of business that would start failing?

My workplace just put a block on flickr, which is a popular free place to store pictures. Most of the pictures on this blog, in fact, are served up by flickr. Now, I can't see my own pictures during the day, including diagrams of interesting (to me) technical efforts. All that data, lost to the people trapped behind the firewall.

No Dog Puns

SwimmingDog_Climb
Yesterday was a nice day. The community came out to torture its dogs.

Each year at the end of the summer season, after the community pool closes its outdoor pool to the human population, it opens the outdoor pool for a day for the pooches. The dogs seem evenly split between loving and hating this event. Retrievers and labs definitely enjoy lunging into the water after tossed balls, batons and babies, but the hounds and huskies are a bit freaked out by the whole thing.

All the dogs, however, love running around in circles.

The zombies' chihuahua was a great swimmer, but mostly in that "help me, my momma's trying to drown me again" style. No matter which way they pointed him, the chihuahua figured out the shortest distance to land and swam in that direction. When he reached land, he just stood there shivering. His little body flopped about until I was sure it would just blow to pieces.

Of course, he always shivers like that.

I enjoyed the day until a Doberman decided I was as good as a fire hydrant. I was sitting in an Adirondack chair, but he still must be given style points for hitting me in the chest. I'll give him credit, but it won't stop me from breaking all four of his legs, the little jerk.

Kidnapped (Robert Louis Stevenson)

I generally get stage fright at Fuddruckers. Fuddruckers is an American hamburger chain. It sells rather large hamburgers. I think the key draw is that you can put salad on your burger any way you like. There's a point in the ordering process where you stand at a register and the person taking your order asks for a name to associate with your food so that you can be called when it's ready. I always want to offer up something that's exotic, or at least interesting. Like Iago or Des Cartes or Consuela or something.

Usually, I freeze and pop out something inane like 'Bob'.

So, I was feeling pretty good about myself when I joined my Great Uncle Leadbelly at the table he had chosen toward the back. After all, if you can get to the point where 'Bob' is your creative bar, you're sitting pretty. I could only hope that my great uncle was not going to ruin my mood, but I wouldn't have put money down.

Leadbelly is the cornerstone of my imaginary extended family. He's my great uncle on my sister's side. He is a curmudgeon; there's no way around the fact. But I do my duty and take him on short excursions. Ostensibly, these trips are to give him a break from the happy confines of the Republican Retirement Ranch where he has a small apartment. In fact, the Ranch calls every so often to remind me of my family obligations and to plead for some respite for their staff.

"Read any good books lately?" I asked brightly. Great Uncle's already furrowed brow creased more deeply still.

"You know I have," he grumbled. "I don't know why you make all of us read. Why couldn't you imagine up a nice drinking binge for me or maybe a quick party with a flapper?"

"Well," I said, "There are all those women in your senior housing center. I understand you're outnumbered..."

"Fine," he interrupted. "Let's just stick to reading. Oop, there's my name."

I sat fuming silently while Great Uncle Leadbelly retrieved his sandwich and dressed it up carefully with lettuce and onion. His look of false innocence when he returned only offended me more.

"What seems to be the matter, young Great Nephew?" he asked with exaggerated politeness.

"You told them your name was Ebenezer Balfour," I asked and answered.

"I've been reading Kidnapped. It was the first name that came to mind."

"Ebenezer Balfour paid to have his nephew kidnapped!" I cried.

"Didn't hurt him any."

"Didn't hurt him?" I sputtered. "He nearly drowned in a shipwreck! He had to skulk across Scotland undercover!"

"Don't go depleting your stock of exclamation points," Leadbelly instructed.

"He was nearly gunned down by an angry mob! He lost his money in a poker game!"

"Probably did him some good. He got to see a bit of the world. He learned how to handle a sword. At the end of the day, he was likely both wiser and stronger. Now, I'll grant you that he had to hang around with that prissy Alan Breck..."

"Alan Breck! See, now, he was interesting," I interrupted. "He was great at fighting and at playing the pipes. He had a little gambling problem, but he was always decked out in nice clothes. He was well-rounded; a real Renaissance man."

"Let me tell you something, great nephew o' mine. Renaissance men are over-rated. Look at all the men of the Renaissance. Where are they today?"

"Um."

"Dead."

"Uh."

"Victorians? Dead. Edwardians? Mostly dead."

"Are there any Edwardians still alive?" I asked.

"Doesn't matter. The only hale and hearty souls alive today were born in the last eighty years or so."

"Eighty years?"

"Well, fifty at any rate."

"Elizabethans?"

"I suppose," he said. "Of course, that's a very Anglocized view of the world. Let's just say modern man is where it's at."

"Where it's at," I echoed. We were quiet a moment or two. "I can't believe you told them you were Ebenezer Balfour."

"Not like I could pay anyone to kidnap you," he said. "It'd take more than a ten pound note and a pat on the back to get someone to put up with you."

"I'm not going to sit here and argue that I'm lovably kidnapable," I said.

"Tried to get your friends to dump you in Tijuana, but it didn't work out."

I tried not to, but I couldn't stop myself from asking, "Why couldn't you get my friends to dump me in Tijuana?"

"You didn't have any friends."

"Are you sure you weren't in Vaudeville?"

"Then, I had the bright idea to lose you in Disney World."

"You never took me to Disney World," I said.

"Your parents wouldn't let me. The best I could do was drop you in Dutch Wonderland, but you found your way home."

"I was sixteen," I pointed out.

"Well, I can't be held responsible for how you turned out," he said. "I tried to make a man out of you."

"Wait a minute! You left me in a library when I was eight!"

"It seemed like a good idea at the time."

"All those books. It was like heaven."

"Yes, well," he grumbled. He fell silent as he munched on his sandwich.

"You know, I've visited the house in Brae Mar where he wrote that book."

"You have?" Great Uncle was plainly not fascinated.

"Well, I've stood on the street outside the house," I admitted.

"Now you're just bragging."

"Well, I did want to slip that in before my story ended, but I couldn't figure out how to do it smoothly."

"Oh, that was smooth. When does your story end?"

"When they call my name. Oh, there it is."

"'Simba'?" Great Uncle Leadbelly echoed.

"Sorry, gotta go get my veggie burger," I said and scampered off.

Hudson and DeSoto (1:20/1:30)

Sometimes my ride to work is like a search for the Northwest Passage. Certainly, the easier path from Greenbelt to Silver Spring is equally as mythical. I just looked up De Soto on Wikipedia. Although he was an explorer, he was probably not searching for the Northwest Passage. I like this bit about how he died, though:

He is presumed to have died on the banks of the Mississippi River near present-day Lake Village, Arkansas by taunting an angry bull that lost its girl friend.
Dude, don't taunt the lovesick cows.

Oddly, today's Word of the Day from Dictionary.com is "veronica", which (who?), in addition to being one of the Archies, is a flower and a bullfighting move.

But, I digress.

To avoid the hill at Park Valley this morning, I left Sligo Creek at the hospital and rode down Maple to Ritchie. The hill at Ritchie is much, much worse. It's marked on my map as a suggested route, but I once again note that it seems whoever makes these suggestions is much more worried about traffic than about hills. Give me traffic any day over a bad hill.

While I'm whinging, I think they've set the bicycle/pedestrian light at Metzerott and Route 1 to not operate during rush hour. It worked for me two weeks ago, when I rode through near dark. But it hasn't worked for me any other time this summer when I rode through at rush hour.

Happy Labor Day

LaborDay_2006_Parade010

Well, I can't seem to work up the energy for an exciting description of the weekend, so here's a quick re-cap. With pictures.

We start with a shot of Kweisi Mfume harrassing some child on the parade route, Monday. The kid seems to have been attacked by the sticker monster. I really enjoy living in a town that will draw so many candidates to its Labor Day parade. I think it says something about the political activeness of Greenbelt. (It could be that we're the only parade that day?) The candidates for all the offices this year, as far as I could tell, from Senate down to Registrar of Wills, walked the parade route shaking hands. Even Michael Steele was there. You have to give him credit for that: Greenbelt isn't exactly friendly territory for Republicans.

I've lost my list of candidates whose hands we shook. Ben Cardin, certainly. Zeese, Lichtman, and Rassmussen, too. Here's a list of Maryland candidates over all. O'Malley was there, of course, but not Ehrlich.

By the way, Mfume did not shake our hands. I haven't decided whether he was scared off by our shirts and "Diversity is Divinity" sign.

I do wish that they'd add political speeches or a debate to the events. So many politicians wandering around, but you don't learn much from just shaking hands. Seems like Labor Day ought to be even more politically involved than it is.

LaborDay_2006_Art3rdPlace

In other Labor Day news, I won third prize for my painting "Measure for Measure," shown here. We bought a lot of books at the book sale. We ate sweet potato fries, watched most of Hamlet, Revenge, took in a bit of the 24 hour improv session, and played a lot of skee ball. I understand that our friends in GreenBeLT Pride and Friends of Still Creek won awards, too. Congratulations!

I didn't take so many pictures as I thought I had. So many of my parade pictures turned out fuzzy or overly shaded.

ClearQuest SOA: Part IV/RPC and XML

This is part 4 in a series about ClearQuest and SOA. If you're not a CQ geek, you'll want to skip this. If you're interested in playing along, go over to that first article and get set up.

At the end of this series, we will have created an Ant task that runs a ClearQuest query without installing ClearQuest on the client machine. Through this exercise, we will have explored very simple SOAification of ClearQuest.

Last time, we created a producer. It's sitting out there waiting for somebody to come along and ask it to produce something, using RPC. This time, we're going to take a brief diversion and look at RPC and the structure of the XML it produces.

CQWS - part 4

At this point, you should have these directories, or similar:

C:/Perl/site/lib/CQWS Contains two modules for talking to CQ
C:/Perl/site/lib/CQWS/tests Contains a script to test the modules
C:/Perl/site/lib/CQWS/cgi-bin Contains one script for talking to web
Let's take a moment to talk about Remote Procedure Calls. Think of RPC as a technology for implementing a Service Oriented Architecture. SOA can be implemented in any number of ways (e.g., SOAP, WSDL, etc.), but RPC is a quick and easy way to get up and running. With RPC, we don't really pass objects around, we just ask for the producer to execute some method using parameters that we pass along. We don't have to know what the language on the other side is; it could be written in Fortran for all we care.

We happen to know that our producer is ready to perform a method called query.run and that it is expecting the name of a ClearQuest query as its parameter. The request is going to be rendered in XML as:

<?xml version="1.0"?>
<methodCall>
<methodName>query.run</methodName>
<params>
<param>
<value>
<string>Public Queries/All Defects</string>
</value>
</param>
</params>
</methodCall>
In fact, save that bit to a file called test.xml in your cgi-bin directory. Make sure to change the name of the query from Public Queries/All Defects to something appropriate for your CQ database. Now, you can run the cgi script from the command line and pass it this xml.

The system should respond with the xml that it would have sent to the web. This is the general format of a response where the response is a structured set of hashes. See the RPC spec for an explanation of all the forms this could take.

Here's what my run looks like:

C:\Perl\site\lib\CQWS\cgi-bin>Perl cqws.pl test.xml

<?xml version="1.0"?>
<methodResponse>

<params>
<param>
<value>
<array>
<data>
<value>

<struct>
<member><name>Contact</name><value><string></string></value></member>
<member><name>dbid</name><value><i4>33554458</i4></value></member>
<member><name>Headline</name><value><string>part number column not wide enough</string></value></member>
<member><name>id</name><value><string>SAMPL00000026</string></value></member>
<member><name>State</name><value><string>Opened</string></value></member>
</struct>

</value>
<value>

<struct>
<member><name>dbid</name><value><i4>33554457</i4></value></member>
<member><name>Headline</name><value><string>heading of application looks too crowded</string> </value> </member>
<member><name>id</name><value><string>SAMPL00000025</string></value></member>
<member><name>State</name><value><string>Resolved</string></value></member>
</struct>

</value>

</data>
</array>
</value>
</param>
</params>
</methodResponse>
As you might remember from way back in that second episode, the method returns an array of hashes, where each hash object is a line of the resultset representing a record in ClearQuest. So, this XML notes that it is an array and each "value" node is the hash for each line in the query's result. You might think of the value as a structured data element, where the keys are the column names. In our example, the first node has a Headline of part number column not wide enough (in hash terms, think $record->{'Headline'} = "part number column not wide enough".)

In fact, in terms of an array of hashes, think $recordSet[0]->{'Headline'} = "part number column not wide enough".

So, in our example, we used XML to pass a string as input to a method and the response was in the form of XML that represents a structured data reference. In fact, we could create the producer's methods in such a way that they're looking to accept arrays or hashes or any sort of structured set of hashes and arrays. In the future, for example, we might want to have the query.run method accept a structured data set representing login values (say, a hash with username, password, database, and connection (or dbset) as keys) along with a string representing the name of the query to run.

Isn't that exciting? Well, that brief look at RPC was less brief than I expected, so I guess we'll have to go to a part 5 for actually making a producer. Part 5 will be the last installment.


All the parts in this series: