http://www.perlmonks.org?node_id=388607

What is Maypole?

Maypole is a Perl framework for MVC-oriented web applications, similar to Jakarta's Struts. Maypole is designed to minimize coding requirements for creating simple web interfaces to databases, while remaining flexible enough to support enterprise web applications.

Simon Cozens, http://maypole.simon-cozens.org

It is a fact universally accepted that a database with contents must be in search of a presentation.

Jane Austen, «Pride and Prejudice Reloaded»

When I first caught eye of Maypole, I was startled by the shining beauty and the effortless grace with which it seemed to produce shiny web applications. I envied those who had a firm grasp of it and strived to employ Maypole to collect and publish the data available to me. But in that time, Maypole was a very immature Primadonna with very specific needs that were only faintly hinted at on websites only known to a few select people already in the clique. Armed with my knowledge of Class::DBI and frugal knowledge of mod_perl, I found myself rejected by Maypole and its requirements often for no reason apparent to me and loudly complained about this in the chatterbox, to the bemusement and annoyance of the other regulars there, I assume. After all, Maypole had been touted as the web application framework, being hawked through articles like flowers on the 14th of February and had received real money from the Perl Foundation. I felt I had a right to it.

Maypole aims to bring the virtues of the traditional MVC separation to web applications, by putting your data model into the database via Class::DBI, representing the data view as templates rendered via Template Toolkit and modifying your data through actions controlled by Apache::MVC, the heartpiece of Maypole itself. As much as the documentation touted these virtues, and as much as I acknowledge that having these virtues is a goal to strive for, not being able to get into closer contact with Maypole was something of a turn-off for me.

A few months have passed since and I have expanded my understanding of the nature of Maypole, and my love/hate relationship has come to some fruitition in the form of a small application working and online. While there are idiosyncrasies to it, there are also ways to wield Maypole as an effective tool to create web applications - if you set your aim right and avoid some pitfalls. Many of the things I will list are actually documented somewhere on the Maypole wiki[1] but haven't found their way into Perl code distributed with Maypole itself yet.

Prerequisites (Theory)

The road to hell is paved with good intentions.

Proverb

To get a start on the good side of Maypole, you need to know, understand and not entirely dislike Class::DBI. The whole object structure that Maypole operates on corresponds to your Class::DBI object and table layout. If you do not know Class::DBI or get easily lost with the setup of has_many() relationships and their ilk, start by getting familiar with Class::DBI without having Maypole in the way. Fighting a battle on two fronts is unadvisable, so make sure this side is covered. If you already have an existing database not specifically tailored with Class::DBI in mind, forget it. People have tried to use Class::DBI for existing databases, but I found them to be far more unhappy with what Class::DBI offered them than I ever was, but I see Class::DBI as a cheap object persistence solution with a good querying and batch manipulation language, and in that regard it has seldom let me down.

Secondly, Maypole requires Apache1 and mod_perl. If your version of Perl and the mod_perl delivered with your version of Apache1 match, you are off well. There is Maypole::CGI, but you will still need Apache::Request. chromatic has adapted Maypole to Jellybean[2], so that might be a good alternative approach to avoid another variable in your setup. If you decide to keep Maypole in its own Apache1 playpen and you want to avoid ruining your existing Perl installation by cluttering it with lots of obscure modules you will never look again, you are setting yourself up for much trouble in return. You will then have to create a separate instance of Apache1 with mod_perl, matching your perl executable, and fiddle with the include paths until it all works properly. If you decide to actually deploy a Maypole-based application, you will have to use a dedicated Apache1/mod_perl server anyway, as the namespace clashes will force you to do so. Although I have not personally tried it, chromatics solution of using Jellybean with Maypole::Container::Jellybean has the appeal of not requiring Apache1 and just requiring a working Perl installation, something you should have.

The third overtly documented prerequisite component is Template Toolkit - liked by many, even bestowed with a documenting book. You will not need to really know Template Toolkit, but basic knowledge about how a(ny) templating toolkit works and the common unifying abstractions will be required knowledge. If you know any of Mason, Petal or Template Toolkit, you will be well off and I think that even with only knowledge of HTML::Template, you will have enough to find your way around in Template Toolkit. In theory, it is easy to replace the templating backend for Maypole, and there already are the required modules and templates for HTML::Mason, but none have surfaced for Petal and HTML::Template yet.

Prerequisites (Practice)

No battle plan ever survives contact with the enemy.

Feldmarschall von Moltke

The installation process should be as easy as perl -MCPAN -e "install Maypole", but, alas, it is not. The prerequisite listing of Maypole 1.7 gets you almost there though. The missing modules are:

  1. A DBD driver fitting your database
  2. The appropriate Class::DBI subclass for whatever DBD driver you selected above (for example Class::DBI::mysql or Class::DBI::SQLite)
  3. Template::Plugin::Class

Best install these three modules in that order and then install Maypole. Template::Plugin::Class is the only module explicitly missing in the prerequisites of Maypoles Makefile.PL and the Maypole wiki will guide you towards the other missing modules. On that occassion the authors and users of Module::Build earn bad karma for their future life as Module::Build does not support the PREFIX= parameter of ExtUtils::MakeMaker and thus any local installation of Template::Plugin::Class will require manual intervention instead of simply working through CPAN.pm. The rest of the modules depends on your choice of database and cannot be automated and detected much more sensibly.

A first date

It might seem easy enough, but [it] is just like a stroll in the park.
Jurassic Park, that is.

Larry Wall, <1994Jun15.074039.2654@netlabs.com>

After some rounds of forced installs (in my case because mod_perl was not in @INC of plain perl), you will believe you have everything together and plan for the first ride. You modify your webserver configuration, you set a location, dress up and navigate to the URL, to find yourself alone on a blank page, or at best with a 500 HTTP Error for company. You decide to wait around, but as you grow weary after 30 seconds and look into the error log, you find that your date has not shown up and left you without a message. Error reporting, if present at all, is abysmal with Maypole. Syntax errors in your code modules abort the loading of these modules at that place so you will end up with one half of a module loaded into your webserver when an error stopped parsing of that module. There is no facility of tracing progress, so you will have to put calls to warn all over the place to glimpse a hint of Maypole where possibly the cause for the error could lie. This also holds true for errors in your templates - they vanish secretly and silently as well. Maypole itself generates some "redefinition" and "undefined" warnings itself, but all of these warnings you will only see if you write a command line script to exercise your code. The only good advice I can offer here is to make your modules emit a message to the log as they have been parsed and to manually load all your class modules from within your main module in an eval loop to catch and log all occurring errors yourself.

Inner workings and structure of Maypole

All of the "Model" part of Maypole is based around the idea that you want to perform an action on a row in a table through a request. To that effect, Maypole maps all requests of the form table/action/row_id to your Class::DBI subclass wrapping table, retrieves the data corresponding to row_id into it, and then calls the method indicated by action of that object. The whole association of table and implementing class happens without any additional declaration just by matching name to class name. Only those methods declared as :Exported can be called in such a manner, so there is no way of reaching internal methods from the outside through Maypole, creating unsuspected security holes. The idea of wrapping the table/class, the action and the row identifier in the URL is nothing new, for example the (Python-based) Zope-based Plone[3] framework. Before Maypole will execute such a request, it allows you to perform authentication and authorization to make sure that only those actions get performed that the user is allowed to perform.

The downside of this approach is that actions acting on a larger set of objects than one have no easy match, and the syntax deviates far enough from the common CGI parameter syntax that it does not scale well for more than one object to be acted upon on a request. The situation that you want an action to be performed on more than one object in one request does not only happen when you want the same action performed on a list of objects of the same class, like ordering several different kinds of flowers for your bouquet, it also happens when you want to display two objects together that can be formed into a new product, like a diamond and a ring, which together form a present. The present has no representation in the database though, as it consists simply of the two components and should not need its own database table.

... and they lived happily ever after

Any sufficiently advanced technology is indistinguishable from magic.

Sir A. C. Clarke

Hokey religion, and ancient weapons are no match for a good blaster at your side.

George Lucas, «Star Wars»

After you have managed to get the supplied example, beerdb, working, you will fever to embark on some ventures of your own devising instead of remaining on the known shores that Simon Cozens outlined for you. Many times have I complained about how Maypole stacks more magic upon the piles of magic that Class::DBI heaps upon the database. My advice is to stay away from all additional magic like Class::DBI::Loader::Relationship, which purports to give you a concise, natural (english) language way of declaring the relationships in your database. All it will give you though, are headaches after headaches as it misinterprets your instructions in the most innovative yet useless ways. Even Simon recommends to stay away from it, and he is the author of it.

A place where the magic comes in handy is when you declare which methods your classes should make visible to the outside. You simply declare a subroutine in your class as :Exported, and it will be reachable via the request to table/action/row_id. This declaration mechanism also makes it very easy to add introspection to any application. A list of all valid external requests can be easily created, allowing you to add a detailed permission scheme to any application. I wrote such a scheme in one day, and at the price of 7 additional tables and a bit of self-contained code Maypole allows easy restriction of any action to specific usergroups.

Maypole does not enforce or supply any user management or permission in its bare form - it is just a web display for database rows. This leaves you with the freedom to keep your application as simple as possible. There is no common way to add plugins with their own database schema easily and without much thought yet, but including that would increase the overall complexity to something comparable to Plone and thus raise the barrier of entry quite a bit.

References

  1. http://maypole.perl.org/ http://wiki.simon-cozens.org/?Maypole
  2. http://www.wgz.org/chromatic/jellybean/
  3. http://www.plone.org

Update: Changed link to the Maypole Wiki

  • Comment on Maypole and I - Tales from the Frontier of a Relationship

Replies are listed 'Best First'.
Re: Maypole and I - Tales from the Frontier of a Relationship
by sri (Vicar) on Sep 05, 2004 at 23:02 UTC
    ++Corion

    Since yesterday I am the new maintainer of Maypole.

    Just wanted to say that after some time of inactivity it's now again very actively maintained and I am happily accepting patches! ;)
    So most of the pitfalls will be covered soon.

    And yes, there is a common way for plugins, but it's cleanly separated into another module named Rubberband.

    You can subscribe to maypole@lists.netthink.co.uk and maypole-dev@lists.netthink.co.uk to get involved.

      woo hoo. good news indeed. a maintainer is just what is needed.

      i'm pretty sure Maypole will work with apache2 as a mod_fastcgi script. i know it works fine that way on apache1. the fastcgi FAQ and examples have the code, it's only a few lines added into CGI::Maypole to make a FCGI::Maypole.

      it's also easy enough to get around the Apache::* dependencies, i believe A::Request is just used for Cookies.

      imho, the Apache::* dependencies should be removed as they are mod_perl related and not merely for apache. i hacked my FCGI Maypole enough to support Cookies and Sessions using the same interface that the Maypole modules use (Maypole::UserSessionCookie or somesuch) but just using the functions provided by CGI::Simple. just a little work would let Maypole support request headers without relying on A::Request.

      i have patches for most of these things, but since nobody was maintaining i didn't send them in. the original project i chose Maypole for is about ready for it's second incarnation and i've been wondering if i should continue with Maypole or try another path.

      i'm on the mailing lists, i'll pay attention now that there's somebody at the helm and i hope Maypole picks up some momentum.

        It would be nice if someone started a patches section on th e Maypole wiki to keep that kind of stuff on. It would be an easy way for you to show your patches and hopefully get them worked into development. Just my 2 cents! :)


        ___________
        Eric Hodges
Re: Maypole and I - Tales from the Frontier of a Relationship
by eric256 (Parson) on Sep 05, 2004 at 16:06 UTC

    Hey, Thanks for the great review. Having beaten Maypole with a stick myself I appreciate seeing this info out there for new commers. I hated most that non of its documentation even seems to address the problems it has. Of course once you find the problem it is normaly easy to find the answers in the documentation, unfortunatly 90% of my time was spent trying to figure out what the problem was.

    On the plus side once I got it working it seems pretty nifty, as it matures and gets some better examples, documentation, and some of the patches integrated with it, it should be an amazing framework. With some effort (read lots and lots of effort) Maypole can even be convinced to run on Apached2 mod_perl 1.99

    Thanks for the great review, perhaps you could make some of your Maypole accomplishments available for others to try out.

    PS one of my biggest problems turned out to be an error in the TT macro file provided with it. So if you have problems with relative links look there.


    ___________
    Eric Hodges
      Could you immortalize your "lots and lots of effort" with hints, pointers and/or code? I also see that CountZero mentioned problems.

      Update:   Now that I'm peeking over Maypole maillist archives I see people saying they've gotten it working under Apache2. Might you look at a couple of the msgs like msg332 and thence to msg248 to see how they compare with your experiences?

        Those are indeed the two posts I eventualy found. I admit I didn't search the mail lists as early as I should have. That was definitly an error on my part. After working my way threw those two patches wich are a good starting block, and then manageing to get Apache::Request to install, which involved some hand installing of modules (instead of CPAN) and some reinstalling of core modules. Two modules (which i can't currently remember) had a recursive dependency (they required each other) that both needed reinstalled before libpreq2 would install. These may not be issues everyone will have but the bewildered me for quite some time. Note that I had never touched Apache (1 or 2) and any form of mod_perl, so these might all be issues that more experienced users fix without even blinking. :) Best of luck and from now on I know to search mailing lists first!


        ___________
        Eric Hodges
Re: Maypole and I - Tales from the Frontier of a Relationship
by johnnywang (Priest) on Sep 05, 2004 at 18:00 UTC
    Thanks, great information. I've been using Struts for quite sometime for several projects, always wanted to look into Maypole. Can someone with experience with both provide some comparison?

    You explicitly said Apache1/mod_perl, is there any issue with Apache2/mod_perl2?

    Thanks.

    Updated: For example, Struts has a very strong presentation layer in the form of many jsp tag libs. Template Toolkit doesn't seem to have that. This is of course more a TT issue than Maypole. How about server side validation in Maypole? The weakness of Struts is that it doesn't really do much about the model layer, it seems Maypole does more with Class:DBI.

      Yes, there is an issue with Apache2/mod_perl2, mainly that it doesn't work. Maypole works with Apache2 as CGI (Maypole::CGI), and eric256 mentioned much pain to get it to play nice with Apache2/mod_perl2. The main problem is that Maypole relies on Apache::Request, which is, I hear, not supported anymore under mod_perl2.

        Just to clear this, Apache::Request has been ported to Apache2/mod_perl2.
        And the development version of Maypole already includes native Apache2/mod_perl2 support (Apache2::MVC)! ;)

      Maypole uses CGI::Untaint for all its validation, and it is pretty strong on that side. I switched Taint protection on fairly late in the process, and did not need to change any line of code in either Maypole or my additional code, as Maypole educates the user in a fairly controlled manner to always properly untaint the data.

      Personally, I'm no big fan of TT, as it allows to do far too much in the custom language instead of pushing complex things back to the Model layer. I prefer the Petal approach of things, where simple things, such as method calls are possible, and everything harder must be implemented in Perl code in the relevant class.

      I searched far and wide, read all I could find on the subject, even tried some of the recipes which were offered to let Maypole play nicely with Apache2/mod_perl, but I did not succeed. It is no use installing Apache2 and then restrict yourself to only use Maypole in CGI-mode. As it is a rather heavy application (stacking Maypole, Template Toolkit and Class::DBI and compiling all this for every CGI-request) it would benefit very much from mod_perl, but now it defeats itself.

      There is a compatibility layer in mod_perl for the easy transfer from Apache1 to Apache2 but somehow I could not get it to work on Maypole. And as the error-messaging system is less than perfect, it I could not find a solution and gave up on it.

      Pity, it seemed an interesting project.

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Maypole and I - Tales from the Frontier of a Relationship
by sintadil (Pilgrim) on Sep 05, 2004 at 15:52 UTC

    ++ for an informative and insightful meditation. I've been curious about Maypole for a while, and this answered a good number of my questions about it. Thanks!

Re: Maypole and I - Tales from the Frontier of a Relationship
by itub (Priest) on Sep 06, 2004 at 15:15 UTC
    Great post. I've also had a love/hate relationship with Maypole. The installation was tricky, and its dependence on so many modules with version numbers close to 0.01 by various authors didn't inspire much confidence, but it worked. I also had to add warns all over the place to figure out where things were crashing.

    The introductory documentation and articles are all good, but I found that when I started to try to actually adapt and extend Maypole for my needs, there were gaps that could only be filled by reading the code. And then when I tried to deviate a bit from the table/action/id model or add better support for many-to-many relationships things got ugly and I almost had to override entire classes (Class::DBI::AsForm was problematic). But it worked out in the end. My only concern is that it tends to be slow in my poor old hardware.

    Using Maypole was definitely a great learning experience. I still use it for the application I developed at that time. When later I had to write a simpler application I found that it was much easier to write it from scratch thanks to the experience I gained. That doesn't mean that I won't use it again, it depends on what I want to do.

Re: Maypole and I - Tales from the Frontier of a Relationship
by diotalevi (Canon) on Sep 08, 2004 at 12:40 UTC

    Could you describe the problem with the module loading and other error and warning hiding? Did you see the code for this? Is it because of $SIG{__WARN__} and $SIG{__DIE__} or because of unchecked eval-block expressions?

      I haven't delved into the depths of Apache::Registry and Maypole to determine where the errors get eaten and not reraised. I believe that the reason are unchecked eval-block expressions, but I can't offer any hard facts for that assumption.