Welcome back to the Digital Hub Enterprise Software series! Today we are going to use web services to pull weather data out of our database "hub" and chart the data using Perl and AppleScript.
Though we will type some code and create some working software in this article, my primary goal is not to teach you Perl, AppleScript, or even web services. There are already great resources on those subjects (see the links at the end of the article for a few of them). Instead, I would like to use these technologies to spark your imagination and get you thinking about what is possible, particularly in business applications, when you combine diverse technologies and are no longer limited to completing tasks on one computer at a time.
We can do some really fun stuff when we combine server-based data repositories (the hub) with client-based display technologies (spokes). Web services technology provides a standard means of communication between your components, as well as between your software and third-party services.
This is the final article in a series of six articles on enterprise software design. To get the full value of the series, I recommend that you start at the beginning. I realize that there will be some of you who are just here for the subject of web services, so I will try to keep the dependencies on code that we previously covered to a minimum. You are at least required to build the database described in part two and the WeatherHub application that we built using WebObjects in part four.
|
Related Reading
AppleScript: The Missing Manual |
Web services are a standardized way to move data between computers on a network using common Internet protocols. Many different computer languages have methods available for both vending and consuming web services, which makes them pretty easy to use in a cross-platform environment. If you want a more technical definition, there are a bunch of them out there on the net, but I find it is best not to get too bogged down in the details. Consider a common office scenario: you call your vendor and ask them to send their latest prices to you, which they send back to you in a fax. Now, imagine that instead of people, two computers make that transaction. A web service would be a great way to make a transaction like that happen.
Yes, but what are they good for? That is the real question, isn't it? Here are some initial ideas. By the end of the article, you should have a much better idea of specific applications.
Collaborative tools requiring centralized data storage.
Data input from a remote device (such as a thermometer in a polar ice cap).
Remotely querying the status of a server process.
Client-side report generation tools.
Cross-platform or cross-language data transfer.
The tutorial will focus on number four. Since Mac OS X has some great graphic tools and powerful scripting abilities, it is a great platform for building graphical reports. Also, tutorials are more rewarding when there are nice graphics as a reward for your efforts!
How do we build a web service? We already did!
You say that you do not remember building a web service? Check out the last page of part four, near the end. We added one line of code to our WebObjects project:
WOWebServiceRegistrar.registerWebService(XML.class, true);
Our XML.java class had a public method for adding weather data to the database, and a public method for building an XML string that contains the entire set of weather data. By registering that class with the above line of code, its public methods become accessible through as web service. Simple!
Of course, you can also vend a web service with just about any computer language that you like. Since our WeatherHub already has this functionality, though, most of our efforts in this article will deal with consuming the data provided by the web service.
In the third article, we discussed a design for wrapping all of the weather data from our database into a single XML file. While you can certainly use web services to transfer simple data types like integers, we can also use a web service to transfer our complete XML. After all, it is just a long string, isn't it?
Imagine that you want to compute the average temperature of all of the temperature readings that are stored in our weather database. The result will be a single number. It would certainly be the most efficient use of network bandwidth to add a Java function to our XML.java class that computes the average temperature on the server and then makes this result available through a web service. In fact, you could even do it at the database level before the data even gets passed to your WebObjects application. If you have huge data sets, it is better to process the data closer to the source so that the bulk of the data does not need to be processed by each component.
However, we are going to send the complete XML data set in our tutorial for a few reasons. The first reason to send all of the data is that we already have a function to generate the XML on the server. In real-world applications, you probably will not want to change the server software very often so that it can stay running 24 hours per day, seven days a week. Providing access to the raw data means not having to change the server application for each new situation that comes up. The second reason is that, as the designer of the server software, you may not know what the client applications are going to do with the data. Perhaps you want to give your customers access to the web service so that they can write their own spoke applications. By making all of the data available in an XML file, you provide maximum flexibility for web service clients.
Of course, when it comes to your own applications, you will have to make the decision based on your circumstances as to whether you will pre-process data on your server or vend it raw over your web service.
Let's build a system for charting our weather data on a graphical timeline. We are going to leverage a Cocoa application I developed, called Bee Docs' Timeline. Please download the latest version from MacUpdate or VersionTracker. The demo version will be fine for our tutorial. Here is a screenshot of the application:
Bee Docs' Timeline can chart a timeline from a tab-delimited data file, so we will be using Perl to generate this data file based on information retrieved via a web service from our WeatherHub application. Then, our Perl script will call some AppleScript to load the data file into the timeline software and format it to look nice.
Before we build our script, there are a few preparatory chores that we need to attend to:
Perl is pre-installed with Mac OS X, but our script with take advantage of the following Perl modules which will need to be installed on your computer:
You should be able to download and install them using the cpan command in Terminal.
For example: sudo cpan -i SOAP::Lite.
WOPort=55555. This will insure that the WeatherHub is accessible on a consistent port, which is important, since our Perl code will need to connect to a consistent URL.Apple-R in Xcode. It needs to be running for the Perl script to interact with it. In the real world, you would probably deploy the WeatherHub on a server in a data center, but everything can run on a single computer for our tutorial purposes.
|
Type the following code in a text file named weatherTimeline.pl and give the file permission to execute with the command chmod +x weatherTimeline.pl in Terminal. To run the script, use Terminal to navigate to the directory containing the script and type ./weatherTimeline.pl.
Here is the code:
#!/usr/bin/perl -w
use SOAP::Lite;
use XML::Simple;
use Mac::AppleScript qw(RunAppleScript);
my $service = SOAP::Lite ->
service('http://localhost:55555/cgi-bin/WebObjects/
WeatherHub.woa/ws/XML?wsdl');
my $weatherXml = $service->buildCompleteXml();
$weatherXml =~ s/"/"/g;
$weatherXml =~ s/>/>/g;
$weatherXml =~ s/</</g;
my $config = XMLin($weatherXml, keyattr => ['id']);
my $outfile = "/tmp/weatherOut.txt";
open(OUT, ">$outfile");
print OUT "Label\tStart Time\tEnd Time\n";
foreach my $itemId (keys %{$config->{data}->{item}}) {
my $thisItem = $config->{data}->{item}->{$itemId};
my $typeId = $thisItem->{typeId};
print OUT $config->{measureTypes}->{type}->{$typeId}->{name}
. ": ";
print OUT $thisItem->{data} . "\t";
print OUT $thisItem->{time} . "\t\n";
}
close(OUT);
The above code does the following:
Connects to the WeatherHub application and downloads an up-to-date version of the weather data via a web service.
The weather data, which was returned as an XML string, is parsed into a data structure.
A tab-delimited text file is created, based on the information stored in the data structure.
Now that the tab-delimited file has been created, we can open it with the Bee Docs' Timeline application and do some formatting. We are going to control the Timeline application with AppleScript, but since we are already using Perl, we will call the AppleScript events directly from within the Perl script. Add the following code to the end of your Perl script:
my $script = qq(tell application "Timeline"
activate
open POSIX file "$outfile"
tell first document
set font name to "HelveticaNeue-Bold"
set font size to "12.0"
set background color to {28583, 35517, 42334}
set the returned_events to every event
repeat with i from 1 to the count of the returned_events
set thisLabel to label of event i
if thisLabel starts with "Temp" then
set event color of event i to {65535, 65535, 65535}
set label of event i to thisLabel & "° F"
else
set event color of event i to {1758, 8435, 15546}
end if
end repeat
end tell
end tell);
my $result = RunAppleScript( $script ) ||
die "Couldn't run script: $script";
Hint: When creating this code, it was helpful to test the AppleScript code using the normal Script Editor application. Once the AppleScript code was working, I just pasted it into the Perl script.
If you would prefer to download the code, here is a version with comments added. If WeatherHub is running and you have the modules installed, running the script should download all of the weather measurements from your database, create a timeline with the data, and format the timeline to look similar to the following. Of course, your timeline will be based on your actual data, so it may not exactly like mine.
Take note that we were able to create a cool timeline chart of our data without making any changes to the database, WebObjects code, or data entry tools. In fact, our various spoke components now contain code in Objective-C, Java, Perl, and AppleScript, and everything works together happily through the magic of XML and web services.
The above map charts out people in the United States who have recently downloaded the Timeline beta from my web site. The map chart was drawn using iMap, which is a pretty cool app (as you can see).
Let us say that you wanted to create a map like this every morning for your sales team. You could start by creating a web service on your web server that returns summarized data from your web logs. Your spoke application could pull the data from the web service, resolve the IP addresses to physical locations, and put the data into a format that iMap can import. How do you get a physical location from an IP address? Another web service, of course. Check out this commercial web service that will do exactly that.
Keep in mind that the web service on the server does not need to be running on any particular platform for this to work. If you are trying to convince your company to buy you a new PowerBook but they are already committed to another server platform, whip up a little demo like this that works with their current server data. I cannot guarantee you will have a new laptop waiting for you at your next review, but you never know.
Here is another example of where this technology can go. I built a web-based document management system using similar technology. Our servers manage and store thousands of scanned documents. The user interface (build with Macromedia Flash) and administration tools (in Java, Perl, and Cocoa) communicate with the servers by passing XML back and forth with web services over secure HTML connections.
Want more ideas? How about some of the following?
Allow unit-testing scripts to automatically log bugs to a centralized bug-tracking tool.
Create a program on your process servers that can vend the latest processing statistics. Create client applications that use the data and cool Macintosh technology to prepare executive reports.
Track the position of your web site in Google. (Click here for more information on Google web services.)
Allow your retail locations to send sales data back to the corporate headquarters.
Web services really are a great technology which fit very nicely into the Hub and Spoke architecture that we have been exploring throughout this entire series. I would love to hear how your are applying these concepts to your area of expertise, so I encourage you to use the comment feature to share what you are up to. Maybe your application will spark ideas for someone else.
I hope that you have enjoyed this series and have learned something you can use. I have enjoyed putting them together and have been encouraged by your emails and comments. Here a summary of what we covered:
Part one, Applying "Digital Hub" Concepts to Enterprise Software Design
Overview of the hub-and-spoke design philosophy and why it works well for enterprise environments.
Part two, Designing the Database
How to design a database hub that is very flexible and expandable.
Part three, Designing the XML
XML is a great technology for transferring information in a platform independent way. How can we represent our data in XML while retaining the flexibility of our database?
Part four, XML Data Transfer with WebObjects
Using WebObjects technology to complete the hub and make it easy to import and export data from our database hub.
Part five, Creating a Data Entry Tool With Cocoa
Our first spoke is a Cocoa application that reads and writes the XML used by the hub.
Part six, Web Services and Informative Data Display
We use our second spoke to demonstrate the power of web services, particularly as they relate to retrieving hub data for applying information display technologies on a client machine.
Adam Behringer works as the CEO of Bee Documents, which strives to help legal and medical firms efficiently manage their documents.
Return to MacDevCenter.com.
Copyright © 2009 O'Reilly Media, Inc.