Sunday, September 16, 2007

"FALL"-ing

Yesterday we were playing " Buzz Lightyear and evil Zurg" ( a game Alex invented for the sake of the peace at home) and I've noticed how quickly the Fall came this year! I know it is not officially Fall, but all the leaves and the cold weather tell me other.
We had so much fallen leaves on our front lawn, that in the spur of the moment we decided we are going to take some home, to let them dry and make postcards or pictures with them. Two years ago we collected so many leaves, left them to dry but then we moved and never had the time to actually do something with them. So we started to select the best leaves, red, green, yellow, brown, even black. So colorful and beautiful! Well, I have to admit at some point the only one excited about the leaves was me :-), but that's just because I have just shown my son how to climb trees( my favorite thing when I was a kid), so he had an excuse :-). My daughter? Well she prefers to "try" ( eat, nibble, whatever you like to call it) everything new and interesting, but maybe she was just hungry.
Anyway, we took the leaves home, put them in one of these BIG Yellow pages catalogs and left them dry.
Now while we ALL are waiting for them to dry, let me tell you something about these catalogs and all the junk mail we are getting! ( Now you've got me going!)
WHO ON EARTH ever uses them and most importantly WHY these people continue to put trees to waste just to send so many of them to us, so they could rotten on the porch sun and rain for two weeks, before somebody eventually remembers to bring them in, put them in a box in the basement, or just start the fire in the fireplace during the winter with them?!
I remember getting one of these "Save the trees" brochures, with SO MUCH PAPER in them, and they are sending them randomly to so many people!
For goodness sake, people, stop for a second and THINK what are people doing with all this paper you are sending them! They THROW AWAY, they BURN, they SHRED, but the bottom line is IT IS ALL TO WASTE, and the thought is YOU are saying you are TRYING to save the goddamn trees! You don't need Al Gore to tell you this ( do you?), it's not rocket science- STOP SENDING USELESS INFORMATION ON PAPER!
Deep breath, the leaves are already dry!
We took them and we made these pictures,I am posting here, I hope you enjoy them as much as we had fun making them.
And while you are enjoying them, think of all the beautiful trees out there, that are going to be wasted just so you can get your bank statement in writing for example, go on your bank's website and subscribe for the "online banking", "paperless statements" or whatever they call it, and DO SOMETHING that would help your grandchildren to enjoy the dry leaves picture making 20 years from now, the way your kids do!

Friday, September 14, 2007

Grapestry view and controller resolvers

This is a posting that I had started quite a while ago (right when I was starting w/ Grapestry), and I never posted it. Anyway, I thought that the content might be useful to someone trying to use hivemind with Tapestry 4. It would be very interesting when I will get a chance to try the same using the new and shiny Tapestry 5.

--------------------

The first couple of steps from the Grapestry wish list is to make the templates and pages be located in the same spot where the standard Grails gsp-s and controllers are (e.g. in grails-app/views and grails-app/controllers respectively).

First to set up the stage to what I'll talk about. For starters, I knew that HiveMind is what makes Tapestry tick. Secondly, I knew that Tapestry is very flexible and customizable, and I expected to fairly easy be able to make it look in all the right places.

So, first stop was the Tapestry User Guide configuration section. At the bottom of the page it says that there is a "configuration point" for org.apache.tapestry. specification-resolver-delegate and org.apache.tapestry. template-source-delegate - the explanations seem to point out that this is exactly what I need. So, I start thinking : how hard could it be to implement a couple of interfaces to just point to the directories I want and have it do it's magic. Well, it turns out, not as easy as it sounds.


  1. So, for the template resolver, I only need to implement this one interface, that should be easy

    public ComponentTemplate findTemplate(IRequestCycle cycle, IComponent component, Locale locale) { }






  2. Alright, I got right on it. Now, I only need to figure out how to produce a ComponentTemplate. I start digging through the Tapestry core source code, So, the constructor for ComponentTemplate looks like this:


    public ComponentTemplate(char[] templateData, TemplateToken[] tokens) {}


    OK, I can figure out how to produce a char array from a file, but these TemplateToken-s... At this point, I started realizing that this is not something that I should try to figure out from the top of my head, but rather go out and find an example that already implements the ITemplateSourceDelegate interface, surely somebody has done this before.



  3. So, I start digging around for an example. This is where it started getting scary. The first couple of links that come up talk about how nobody has really posted a good example of how this is done. Overall, the problem is that there is a boatload of "helper" objects (e.g. DefaultParserDelegate, TemplateParser, ComponentSpecificationResolverImpl, etc. the list goes for quite a bit) that you need to create before you can actually create an instance of this ComponentTemplate. On one hand, it all makes sense: Tapestry is a very modular framework, and you could potentially replace each one of it's pieces with some other component that implements the contract. On the downside, if you don't know much about the guts of Tapestry (e.g. for someone like me), digging into the guts is not that much fun.



  4. So, I say, I'll give the code that was posted on the mailing list, that should certainly work, especially since the responders say that they do work. Great, I copy-paste-compile.. and when I run my test Tapestry app (with a similar structure to a grails app - e.g. with WEB-INF/grails-app/views, etc)... a NullPointerException.. Luckily, Tapestry is open source, I dig into the source and I realize that I get the NPE when it's trying to log something.. So, do I need to inject a log into every object that I create ???



  5. This is when I realized that I just need to use the facilities that Tapestry uses to inject it's dependencies - namely, Hivemind. The thing is, I know nothing about it.. After reading up about it, it turns out that it uses these configuration points that you can use as well. So, my task moved from "copy and paste an example from the mailing list" to "figure out how this HiveMind thing works and then make it work for my ITemplateSourceDelegate implementation. I have read 2 books on Tapestry, but neither of them says anything about HiveMind (I admit, one was older, on Tapestry 3.0, the other one more focused on Tapestry itself, not its infrastructure). So, here is what I ended up using for my hivemind config file:
    <module id="id" version="0.0.1" package="package">
    <implementation service-id="tapestry.page.SpecificationResolverDelegate">
    <invoke-factory>
    <construct class="com.troymaxventures.grapestry.framework.ViewsSpecificationResolverDelegate">
    <set property="pagePath" value="grails-app/controllers"/>
    <set property="componentPath" value="grails-app/views"/>
    </construct>
    </invoke-factory>
    </implementation>

    <implementation service-id="tapestry.parse.TemplateSourceDelegate">
    <invoke-factory>
    <construct class="com.troymaxventures.grapestry.framework.ViewsTemplateSourceDelegate">
    <set property="grailsAppPath" value="WEB-INF"/>
    <set-service property="parser" service-id="tapestry.parse.TemplateParser" />
    <set-object property="contextRoot" value="infrastructure:contextRoot" />
    <set-service property="componentSpecificationResolver" service-id="tapestry.page.ComponentSpecificationResolver" />
    <set-object property="componentPropertySource" value="infrastructure:componentPropertySource" />
    <set-object property="rootOverride" value="app-property:grapestry-webapp-root-override" />
    </construct>
    </invoke-factory>
    </implementation>
    </module>


This hivemind configuration almost works for what I needed it to do in Grapestry. Unfortunately, it didn't get too far as the Grails test / development configurations work slightly differently than in production.

The general conclusion on the technology / Hivemind : it definitely seems like a cool dependency injection solution, especially in the way that it can dynamically aggregate modules and create a configuration on the fly (e.g. compared to Spring, where you have to explicitly say what goes into the config and how the different configs will interact). However, as with anything else, the high level of decomposition, where each class does only one job, and the many dependencies between the classes, make it sometimes difficult to figure out : e.g. if for a simple change like this, you have to track down 10 dependencies, that might have dependencies on their own, it sometimes makes you wish that the software you're trying to use wasn't as clean.

Friday, September 7, 2007

Grapestry progress and wishlist

I've been making some progress in making the Grapestry Grails plugin more integrated into Grails. Overall, it hasn't been quite a walk in the park, mostly due to the way Tapestry works. Here are a couple of things that would really be nice-to-have before Grapestry can really be usable as a Grails plugin:


  1. Tapestry templates (pages and components) should show up directly under the grails-app/views directory. Overall, the idea is that that's where Grails GSPs typically show up, and it would be most natural for Grapestry to do the same

  2. Tapestry page and component classes should live directly under grails-app/controllers. Overall, in Grails, the controllers are what process the requests. Since the page and component classes have the corresponding duty in Tapestry, so it would make sense to keep them there

  3. Since Grails emphasizes convention over configuration, creating pages should default to no page specification files. Everything that a page spec does should be accomplished using annotations (totally acceptable in regular Tapestry)

  4. Add groovy scripts and templates that would set up a default page template and page classes, e.g. something like 'grails create-grapestry-page' and 'grails create-grapestry-component'

  5. Add scaffolding similar to the one that exists in Grails controllers. It seems totally possible that there could be default methods like 'list', 'edit', etc on a grapestry page that would do the equivalent job of the Grails controllers with dynamic or static scaffolding

  6. Have some NetBeans support (hopefully coming in NetBeans 6.0) for Grails and Tapestry to make editing the Tapestry components in Groovy at least on par with doing them in Java



I did make some progress in accomplishing the first couple of bullets above. I kinda thought I had that down; however, it turns out that the "Development" grails configuration doesn't quite obey the same rules (it uses some resouce loaders that load resources directly from the ${app_dir}/grails-app/view and controllers directory), so I'm working on some workarounds for that.

Just yesterday, I got the Grails plugin account, but I still need to take a look at a standard grails plugin structure before I put anything out there.

Popular Posts

Related Posts with Thumbnails