ForbesPrint.com and Open Source

A year ago, my wife, daughter and I visited my wife’s aunt and uncle in Waterford, Michigan area. She signed me up to do a small web site for them to promote the printing business. The printing business has been in the family since 1946.

I decided to use open source tools as much as possible to deliver the site. Long term, I don’t expect to have access to tools I use at work and I actually know I shouldn’t use tools from work to work on external projects. And so, I stayed with open source tools as much as possible.

I set up the website relatively quickly with ruby on rails, but did not launch it for awhile. While I like the ruby on rails approach to rapid development I haven’t used ruby enough to learn the syntax and be productive in it. In the meantime between developing the site and actually launching it, I worked on a project for a client that utilized symfony. This gave me enough opportunity and time to learn php and the symfony framework. So the in-development site was migrated from a ruby on rails to symfony project.

One thing I liked when I set up the rails project was the usage of capistrano to manage the deployment of the application to my slicehost instance. I decided to see how it could work with symfony as well. In the end, I was able to get a good amount of information from the following site. Besides paths and server changes to the configuration presented on the page, I utilize git as version control.

I have found great value in git over subversion. I like the fact that git does not require server software to run. Getting it up and running with just a dedicated user and ssh was a snap. Even better, git doesn’t manage every file with 3 extra files per instance like subversion seems to do. To copy a subversion branch from one server to another takes forever due to all the .svn files. Git can easily be moved around and ability to remove git from a file structure works just as easily.

In the end, I built the very small site, ForbesPrint.com with the following tools:

  • php for scripting language
  • symfony for php framework
  • nginx for web server
  • fastcgi for php runtime environment
  • git for source control
  • gimp for image editing
  • slicehost for server hosting utilizing Ubuntu virtual machine
  • SpringSource Tool Set for IDE with Aptana Studio plugin for php project support

Now that the basics are in place, I hope to expand the site to better accommodate their needs and growth the business.

Blogging on the iPad

My new 3g iPad arrived today and I have spent the evening having a look through the app store for apps that are built for the device. One of the apps I found was WordPress for the iPad. This is my first post on the iPad and the initial impression is that it is easy to do, but it is prone to moving the cursor around a little too easily.

So far the other apps I have tried are Netflix and USAToday. As my previous post mentioned, I imagine the most use of this device will be reading in certain room. I’ll have to wait until later to see how that goes.

On a technology front, my latest project involves the use of SDL Tridion for CMS. I don’t have too much to state about the product as yet. I’ll wait until the developers get going with the implementation before I mention anything about it.

MAMP & PECL/UUID Module Working On Snow Leopard

I had a previous article that discussed in detail on how to get imagick php plugin working on MAMP. As always, as you get more exposed to technologies and frameworks you find new ways to do things. One thing to keep in mind with MAMP is that 1.8.4 is still 32-bit build. Once it goes 64-bit, I am sure the whole thing will get easier.

In this instance, I was working through adding UUID generation support to my PHP code. While the uniqid provides a function to generate IDs, it is not a GUID specification. There is PECL UUID module that provides “a wrapper around libuuid from the ext2utils project”. After looking around for how to add it to MAMP, I came across the following article that talked about how to enable the uploadprogress module. utilizing the same process I attempted to build the uuid module. Unfortunately, the uuid module failed to compile. This eventually lead to a defect report for the uuid module about Mac OS X and older version of files. Attached was a patch file; patched the files and remade. Installed, reloaded and all was good.

The following are the steps I used for the installation of uuid module.

Download and extract the uuid module
Grabbed the 1.2 version of the uuid module.


macbook:Downloads mleo$ wget http://pecl.php.net/get/uuid-1.0.2.tgz
...
mabook:Downloads mleo$ tar -xzf uuid-1.0.2.tgz 
macbook:Downloads mleo$ cd uuid-1.0.2

Get & Apply Patch
Copy patch code from here. Save the contents into mac.patch file. Apply patch. It did require entry of the path to two test files during the patch process.


macbook:uuid-1.0.2 mleo$ patch < mac.patch 
patching file config.m4
patching file php_uuid.h
can't find file to patch at input line 103
Perhaps you should have used the -p or --strip option?
The text leading up to this was:
--------------------------
|diff -urp uuid-1.0.2/tests/uuid_mac.phpt uuid-
|1.0.2.mine/tests/uuid_mac.phpt
|--- tests/uuid_mac.phpt  2008-04-01 08:59:22.000000000 -0700
|+++ tests/uuid_mac.phpt  2008-08-14 10:21:57.000000000 -0700
--------------------------
File to patch: tests/uuid_mac.phpt
patching file tests/uuid_mac.phpt
can't find file to patch at input line 116
Perhaps you should have used the -p or --strip option?
The text leading up to this was:
--------------------------
|diff -urp uuid-1.0.2/tests/uuid_time.phpt uuid-
|1.0.2.mine/tests/uuid_time.phpt
|--- tests/uuid_time.phpt  2008-04-01 08:59:22.000000000 -0700
|+++ tests/uuid_time.phpt  2008-08-14 10:22:50.000000000 -0700 
--------------------------
File to patch: tests/uuid_time.phpt
patching file tests/uuid_time.phpt
patching file uuid.c

Configure and Build the Module
I’ll leave the prompts out of this one to make it easier to copy and paste the set of commands, but each line in the below code block is different command.


/Applications/MAMP/bin/php5/bin/phpize
MACOSX_DEPLOYMENT_TARGET=10.6
CFLAGS="-arch i386 -arch x86_64 -g -Os -pipe -no-cpp-precomp"
CCFLAGS="-arch i386 -arch x86_64 -g -Os -pipe"
CXXFLAGS="-arch i386 -arch x86_64 -g -Os -pipe"
LDFLAGS="-arch i386 -arch x86_64 -bind_at_load"
export CFLAGS CXXFLAGS LDFLAGS CCFLAGS MACOSX_DEPLOYMENT_TARGET
./configure --with-php-config=/Applications/MAMP/bin/php5/bin/php-config
make
make install

Add module to php.ini
Edit the /Applications/MAMP/conf/php5/php.ini file and add “extension=uuid.so”.

Test Installation
Can check info to see if uuid module loads and run the uuid_create() function to see if it returns.


macbook:uuid-1.0.2 mleo$ /Applications/MAMP/bin/php5/bin/php -r 'print phpinfo();'
...
uuid
UUID extension

Version => 1.0.2 (stable)
Released => 2008-04-01
CVS Revision => $Id: uuid.c,v 1.9 2008/04/01 15:58:52 hholzgra Exp $
Authors => Hartmut Holzgraefe 'hartmut@php.net' (lead)
...

macbook:uuid-1.0.2 mleo$ /Applications/MAMP/bin/php5/bin/php -r 'print uuid_create() . "\n";'
85C43B35-1416-435F-AEFF-3E4693ACEE65
macbook:uuid-1.0.2 mleo$ 

Most Popular Room for iPad

My prediction for the iPad is that some survey will come out 6 months after the release that finds people use their iPad more often in the bathroom than any other room in the house. The logic on this is simple. People already have laptops, desktops and fully functional computers available in the living room, office and/or bedroom. The bathroom is really one of last bastions of truly tech free peace and quiet.

Using YAML as Response Format for Services in Spring

Recently, we were developing an iPhone application where the iPhone developer was insistent on utilizing YAML as the response format for service calls. This seemed odd given the prevalence of JSON as a response format and an already built library for parsing and handling JSON within Objective C that works with the iPhone SDK. The other advantage to JSON is there is another project that has built a JSON view resolver for converting model/domain objects into JSON. The advantage with YAML is that it inherently supports circular references and can resolve them during serialization and deserialization. While domain objects can have circular references in design, I try to keep them minimal and out of the model objects to ensure most serialization techniques work easily.

I couldn’t quickly find any YAML Spring View support so went about working through my own. Using the source of the JSON Spring View project as baseline I was quickly able to build out a baseline view handler. I say baseline because I haven’t fully unit tested the code as yet.

YamlView Class
This makes use of the jyaml library.


public class YamlView extends AbstractView {
    private static final String DEFAULT_YAML_CONTENT_TYPE = "application/yaml";

    public YamlView() {
        super();
        setContentType(DEFAULT_YAML_CONTENT_TYPE);
    }

    /**
     * Creates a YAML String from the model values.
     */
    @SuppressWarnings("unchecked")
    protected final String defaultCreateYaml(Map model) {
        return Yaml.dump(model);
    }

    /**
     * Creates a Yaml String from the model values.
     */
    @SuppressWarnings("unchecked")
    protected String createYaml(Map model, HttpServletRequest request, HttpServletResponse response) {
        return defaultCreateYaml(model);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        response.setContentType(getContentType());
        writeYaml(model, request, response);
    }

    @SuppressWarnings("unchecked")
    protected void writeYaml(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        
        String yaml = createYaml(model, request, response);
        response.getWriter().write(yaml);
        
    }
}

Configuration: applicationContext.xml
In one of the Spring configuration files where the web presentation layer is set.


...
  <bean name="xmlViewResolver" 
        class="org.springframework.web.servlet.view.XmlViewResolver" 
        p:order="3" 
        p:location="classpath:xmlViews.xml" />        
...

The order is in place because this configuration file has multiple ViewResolvers. The xmlViews.xml then has the configuration:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView"/>

    <bean name="yamlView" class="com.example.web.view.YamlView"/>
    
</beans>

And finally, the usage within a controller:


public class ExampleController extends AbstractCommandController {
...
  @Override
  protected ModelAndView handle(HttpServletRequest request,
      HttpServletResponse response, Object command, BindException bindException)
      throws Exception {
    
...
    String viewType = "jsonView";
    if (request.getRequestURI().endsWith(".yaml")) {
      viewType = "yamlView";
    }
    
    return new ModelAndView(viewType, model);
  }  
...
}

It really is amazing the little amount of custom code required these days to get great results.