Learn more by doing 2

Posted by Jimmy'z on February 28, 2007

I’ve come to realize that you learn a million times more by doing than by just studying. This may seem like a no brainer, but I really believe that experience is one of the best teachers. This applies to just about everything in life.

A couple of examples that have really driven this home for me has been the current Omniture competition that I’m involved in, the Adwords campaigns that we ran in Paul Allen’s Internet marketing class, and my recent starting of a business.

This year is my first year actually competing in the Omniture Analytics competition. I’ve attended all of the past final presentations, but always thought I was too busy to compete. I’ve watched, taken notes, and studied the charts, findings, and recommendations that prior teams have given, thinking that I could learn to be an effective data analyzer by just studying what the top teams have done. I’m sure this has helped us in getting into the finals this year, but I’ve gotta say, actually diving into Omniture’s Site Catalyst application and trying to pull out some gems is harder than it looks.

Our team spent hours and hours during the preparation time before the preliminary rounds just trying to figure out which direction to go. We debated key terms, key performance indicators, success events, and such. It actually took a good amount of time to narrow what we wanted to look for. Once we put it together, it all seemed obvious, but it was hard to not get distracted by all of the cool data found inside Site Catalyst. We watched training videos, read knowledge-base articles, but still, applying what we had studied was a whole new ballgame.

Last semester, we ran an Adwords campaign for WorldVitalRecords.com during our Internet marketing class. I had read plenty about how Adwords works, but I had never actually done it. It almost seemed intimidating to actually spend money on ads, but actually doing it was one of the best experiences that I had that semester. I learned more from doing than from learning about Adwords through articles and case studies.

Starting a business has been another awesome learning experience for me. I have always been fascinated by start-up businesses, but until last year had no experience with an actual start-up. I was able to spend 8 good months at Provo Labs, learning about what it took to run LDSAudio.com, LDSLibrary.com, and WorldHistory.com. I learned a lot of valuable lessons from that, but because ProvoLabs was venture funded, I missed out on a lot of the bootstrapped start-up experience.

My time at 42Co was a totally different experience, as we worked to get proposals to clients for contract work, pulled several all-nighters, and later pursued venture funding for TagJungle. I’m no longer with 42Co, but the time I spent there was very valuable. I was associated with a great team, and I moved closer to my goal of becoming an entrepreneur.

Now, Brian Corrales and I are starting our own venture, and things have been great. I’ve stepped into a new realm of managing my own business. It feels great to take charge of my future. I think the uncertainty and risk that comes along with entrepreneurship brings a lot of excitement and feeling of accomplishment when things come through.

I guess the point of all this is that experience is a great teacher. I know I’ll especially come to realize this in the next couple of days as all we’ve studied about being parents will fly out the window and we’ll be learning by doing.

RadRails Error – No such file to load — rubygems (LoadError) 5

Posted by Jimmy'z on February 27, 2007

I’m using the Eclipse plug-in named RadRails to work on Rails projects. I’m running on Mac OS X, and I finally got past this error that would come up every time I tried to generate a Model, Controller, or anything for that matter:

No such file to load -- rubygems (LoadError)

Strange thing is, generating models, controllers, and such worked just fine from my bash shell, but not from within Eclipse. I thought it was something to do with my system PATH variable, but that was not the case.

The way to fix this error is to add ruby to your list of interpreters in:

Window => Preferences => Ruby => Installed Interpreters

Add an interpreter, name it Ruby, and give it the path to your ruby binary file. To find where that is located, just type which ruby from your shell prompt.

I hope this helps someone else. It took me a long time to find a solution for this.

Switching to a MacBook 5

Posted by Jimmy'z on February 23, 2007

Yesterday, I got a nice and shiny new white MacBook. I eagerly tracked my order from China to Provo, and couldn’t wait to come home and fire it up.

So far my experience has been very good. I used a Mac for about a year and a half while working at BYU’s SAS Creative Marketing and came to really love Mac OS X. So, I’m not coming from a non-Mac user experience. Still, I’d never started from scratch with a brand new Mac.

The only real complication that I’ve experienced so far is that I was getting really slow response from my D-Link 524 wireless router. I finally fixed the problem by either running the updates, and changing a configuration on the WEP password. I don’t know which one fixed it, but it’s working really well now.

I’m not quite set up to the point that I can put away my Windows machine yet, but I’m getting there. The applications that I’ve installed so far include:

  • Adium – a messenger client that handles my MSN and Google Talk accounts
  • Skype – I can’t live without skype. It’s my favorite chat/voip client
  • Fugu – an visual SFTP application for file transfers
  • Firefox – I’m hooked on Firefox, although I’ll give Safari another look
  • Growl – a notifier that helps with alerting me of Adium messages
  • DarwinPorts – helps me get and compile Open Source applications and their dependencies with which I’ve installed RubyGems, MySQL5, and other web related applications
  • Eclipse – an IDE for writing applications in either Java, PHP, Ruby, etc. I’ll use this until I can get TextMate.

Still to come:

  • Parallels – A virtual machine application that will allow me to run Windows, Linux, etc. while running Mac OS X
  • TextMate – An awesome code editor for the Mac
  • Macromedia Studio – I have a Mac/Windows version of MX 2004 which I’ll be installing here
  • MS Office for Mac – I’m still deciding whether to do this, just run my Windows version from Parallels, or get an Open Office version.
  • Other cool applications from FreeMacWare.com

I still like Mac OS X. I’m new to Tiger, so I don’t have any favorite Dashboard widgets yet. I’m still discovering cool new features that didn’t exit in Panther.

Anyone have a killer app that they can’t go without on the Mac?

Benefits of Service Oriented Architecture

Posted by Jimmy'z on February 20, 2007

I’m a believer in Service Oriented Archicecture (SOA). Some of the main benefits that I see from SOA is that it defines clear ownership of data, provides reusability of enterprise resources, maximizes system interoperability.

Clear Ownership of Data

Service oriented architecture provides a clear ownership of data. A typical web service will store, retrieve and manipulate data in a database that is hidden from the view of the client that is making calls to that service. This is good because we know that the web service is the owner of the data in that database. 10 different applications might be requesting data from the web service or posting transactions to the web service, but they don’t touch the database directly.

Because only the web service is touching the database directly, business logic and data controls can be put in place in one spot. If a bug is introduced into the system and the data in the database gets corrupted, it’s the web service’s fault. It has clear ownership and responsibility for the data that it maintains.

Reusability of Enterprise Resources

Service oriented architecture also allows for reusability of enterprise resources. Divisions within an enterprise often need access to the information that another division mantains. Setting up services for a single division can open up that data and processing to other divisions that would otherwise be unavailable or not shared as easily. By allowing multiple business functions share the same resources, costs are brought down, and the organization can run more efficiently.

Of course, access controls will need to be in place so that only the right people are gaining access to or manipulating sensitive information.

System Interoperability

Web services are breaking down the walls of incompatibility. It doesn’t matter which language you are programming in, which platform you are running on, web services provide a way for systems to talk to each other. Platforms and programming languages all have their strengths and weaknesses. Web services allow developers to play to the different strengths of a particular programming language to solve a problem that is most appropriate for that language. This can lead to more efficient developer cycles.

This doesn’t mean that you particularly want to have a conglomerate of languages and operating systems that make up your information system. That could quickly become very difficult to maintain. However, it does provide flexibilty in the construction of an information system.

So much to learn

I recently bought Enterprise SOA by Dirk Krafzig, Karl Banke, and Dirk Slama, and am trying to make my way through the concepts in that book. SOA is more than just being able to slap a SOAP inteface on some software that you’ve written. It requires a new way of thinking when designing and implementing information systems. I think SOA will have a large impact on IT in the future. I’m excited to continue learning.

SOAP Server with PHP5 – part3: the glue code 9

Posted by Jimmy'z on February 20, 2007

Part 2 of this series of blog posts focused on creating your wsdl. Now we will move on to the “glue code” and putting it all together. In part 2, I created a wsdl that defined the application programming interface (API) for an inventory web service. We defined one simple function called getItemCount which takes a upc in the form of a string as a parameter and returns the count in the form of an integer.

Let’s go ahead and code up the function:

<?php //inventory_functions.php
function getItemCount($upc){
//in reality, this data would be coming from a database
$items = array('12345'=>5,'19283'=>100,'23489'=>234);
return $items[$upc];
}
?>

It is important to test all of your functions outside the scope of your web service to iron out all of the bugs, otherwise, you’ll be dealing with some nasty debugging as soon as you connect this with the SOAP glue code. I like to keep the functions or classes that are connected to the web service separated from the glue code, unlike the php soap extension tutorial does. That way I can test it more easily.

The glue code

The glue code is responsible for handling incoming soap requests and returning valid soap xml. It takes the wsdl service definition and it connects it with your function or class. Here’s what it looks like:

<?php //server.php
require 'inventory_functions.php';
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
$server = new SoapServer("inventory.wsdl");
$server->addFunction("getItemCount");
$server->handle();
?>

The inventory_functions.php contains my getItemCount function. It is important that the function has been included (or required) before the $server->addFunction("functionName"); is called. Also, make sure that you have no white space before or after your opening and closing php tags.

Once you know that your wsdl is correct, and you won’t be changing it, remove the ini_set function from the glue code.

Important: Make sure your wsdl’s service block is pointing to the http accessible url of the glue code (see part 2 for details).

Testing the service

Now is the moment of truth, to see if your service works like you had anticipated. Simply create a script like this one:

<?php //client-test.php
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
$client = new SoapClient("http://[path to the service]/inventory.wsdl");
$return = $client->getItemCount('12345');
print_r($return);
?>

Substitute the [path to the service] with your url path, and execute the script. Hopefully, you should be seing the results that you expected.

Tutorial Files

For all the files that have been discussed in this tutorial, download the tutorial.zip

Sorry, this post has received a barrage of spam. I had to shut down comments. Try one of the other posts in this series.

SOAP Server with PHP5 – part 2: fun with wsdl 1

Posted by Jimmy'z on February 20, 2007

Part 1 of this series of blog posts should help you get started with setting up a simple soap server with one function, a stockquote request. It points you to the soap extension tutorial on the Zend Developer Zone.

In this part, I’m going to explain some of the different parts of the wsdl so that the wsdl isn’t so intimidating. So let’s begin by examining the wsdl found on the tutorial here.

I’m going to start from the bottom of the wsdl and work my way to the top.

The ’service’ block

<service name='StockQuoteService'>
<port name='StockQuotePort' binding='StockQuoteBinding'>
<soap:address location='http://[insert real path here]/server1.php'/>
</port>
</service>

This ’service’ block of the wsdl gives some basic definitions for your soap server. You’ll want to pick a service name and stay consistent throughout the wsdl. This example uses ‘StockQuote’ for all its naming but you could use something like ‘Weather’ or ‘Inventory.’ Just stay consistent. So, if you were to make an ‘Inventory’ service, your service block of the wsdl would look something like this:

<service name='InventoryService'>
<port name='InventoryPort' binding='InventoryBinding'>
<soap:address location='http://[insert real path here]/server1.php'/>
</port>
</service>

The port name and binding connect this block with the other parts of the wsdl, so just keep to your naming convention and you’ll be fine.

The address location points to the location of what I call the “glue code” or the php script that glues your function to the soap extensions server libraries. The glue code is what handles all of your xml messages and passes the right parameters to your functions.

The ‘binding’ block

<binding name='StockQuoteBinding' type='tns:StockQuotePortType'>
<soap:binding style='rpc'
transport='http://schemas.xmlsoap.org/soap/http'/>
<operation name='getQuote'>
<soap:operation soapAction='urn:xmethods-delayed-quotes#getQuote'/>
<input>
<soap:body use='encoded' namespace='urn:xmethods-delayed-quotes'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:xmethods-delayed-quotes'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>
</binding>

The ‘binding’ block has a lot of stuff in it, but most of it is just defining how the soap client and server will communicate. There is very little code here that you’ll need to change to fit your service. There are 4 parts that you’ll need to modify in order to map the service to the function that you wish to put in the service. Those parts have been bolded and italicized above. Change the binding name and type, the operation functionName and the #functionName at the end of the soap:operation.

So, if we were to modify this for our inventory example we might change the getQuote to getItemCount and our binding block would be as follows:

<binding name='InventoryBinding' type='tns:InventoryPortType'>
<soap:binding style='rpc'
transport='http://schemas.xmlsoap.org/soap/http'/>
<operation name='getItemCount'>
<soap:operation soapAction='urn:xmethods-delayed-quotes#getItemCount'/>
<input>
<soap:body use='encoded' namespace='urn:xmethods-delayed-quotes'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</input>
<output>
<soap:body use='encoded' namespace='urn:xmethods-delayed-quotes'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'/>
</output>
</operation>
</binding>

If you were to add another function to your service, you would just copy the ‘operation’ section of this block, and paste it right below, and change the function name. Pretty simple.

The ‘portType’ block

<portType name='StockQuotePortType'>
<operation name='getQuote'>
<input message='tns:getQuoteRequest'/>
<output message='tns:getQuoteResponse'/>
</operation>
</portType>

The ‘portType’ block connects your binding block to the message blocks which define your method parameter and return types. The name should match the type from the binding block. You’ll also need to change the operation name and the input and output message attributes. The message attribute can be named however you wish as long as it matches the name of its corresponding message block, which we’ll talk about next.

For the inventory example, we’d change our portType block to the following:

<portType name='InventoryPortType'>
<operation name='getItemCount'>
<input message='tns:getItemCountRequest'/>
<output message='tns:getItemCountResponse'/>
</operation>
</portType>

Again, if you wish to add another method to your service, you would just have two operation blocks within the portType block.

The ‘message’ block(s)

<message name='getQuoteRequest'>
<part name='symbol' type='xsd:string'/>
</message>
<message name='getQuoteResponse'>
<part name='Result' type='xsd:float'/>
</message>

Here we have 2 message blocks that correspond to the message attributes found in the portType block of the stockquote.wsdl. This is where the meat of your wsdl resides.

The part element in the document specifies parameters for the requests messages, and the return structure for the variable returned by your function. For parameters, make sure you mape the name with the parameter name, and specify the type. Here is a list of primitive data types accepted: http://www.w3.org/TR/xmlschema-2/#built-in-primitive-datatypes.

For our inventory example, we might modify this section like so:

<message name='getItemCountRequest'>
<part name='upc' type='xsd:string'/>
</message>
<message name='getItemCountResponse'>
<part name='Result' type='xsd:integer'/>
</message>

The ‘definitions’ header

The definitions header is what defines the namespaces of your wsdl document. You can mostly leave this as it is from the example, but you should change a few parts. Here is how I’ve modified my inventory service header:

<definitions name='Inventory'
targetNamespace='urn:JimmyzInventory'
xmlns:tns='urn:JimmyzInventory'
xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/'
xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'
xmlns='http://schemas.xmlsoap.org/wsdl/'>

And that’s pretty much it. Creating your own wsdl isn’t really as bad as it appears.

My final inventory wsdl is located here.

See part 3 for implementing the web service.

SOAP Server with PHP5 – part 1 4

Posted by Jimmy'z on February 19, 2007

Setting up a SOAP web service with php used to seem pretty intimidating to me, until I finally decided that I would hunker down and build my own WSDL. Now that I’ve successfully gone through the process of building a SOAP web service with php5, I would say that it really isn’t all that bad. I was actually quite surprised at how easy it was in the end.

To get started, I recommend the PHP Soap Extension article found on the Zend Developer Zone website. Before going through the tutorial you’ll need to make sure that you are running on php 5 with the soap extension installed. If you’re not sure if you are on version 5 or if the SOAP extension is indeed installed, create a script with the following code:

<?php phpinfo(); ?>

That should give you all of your server configuration information that you need. Search that page for “SOAP” and if you find it there with some configuration variables, you’ll know that you’re good to go.

I recommend setting up the SOAP server that is given in the tutorial which requires 3 files: stockquote.wsdl, server1.php, and client3.php. Place those files in a directory that is accessible via http and modify the stockquote.wsdl file, replacing http://[insert real path here]/server1.php with the path to your server1.php file.

Test the service by running the client3.php script. As you modify the service to return more complex data types, you’ll want to change the print function with a print_r to get a dump of the whole data schema that has been returned.

Once you have that working, you can begin to modify the function or WSDL to do what you need it to do.

Important: Before you make changes to the WSDL, add the following line above the client code and at the top of the server1.php script:

ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache

Also, in the wsdl there is a part that has urn:xmethods-delayed-quotes. This has nothing to do with stockquotes, and you should just leave it alone.

See part 2 for an explanation of the wsdl.