Gorm-couchdb grails plugin release 0.3 1

Posted by Warner Onstine on November 16, 2009

We actually released this to the Grails plugin repository last week but haven’t had time to blog about this release. There’s a lot of good stuff in this release, some bug fixes and some new features.

Before we dive into the new features there is a short how-to on the wiki. To install the plugin you can just do a

grails install-plugin gorm-couchdb

or download from the Grails Web site.

New Features

Domain objects now assume that there is a design document with the same name as the @CouchEntity type:


@CouchEntity
Customer {
    ...
 }

This will then map to a design document named customer. So a call to Customer.queryView("byName") is the same as Customer.queryView("customer/byName").

Added count() and list() methods that call the count and list view of the domain design document. You can optionally specify the view as the first parameter, e.g. Customer.list("byName"). Also, both methods take the options parameter, so default scaffolding code like the following works:


def list = {
    params.max = Math.min(params.max ? params.max.toInteger() : 10, 100)
    [tripInstanceList: Trip.list(params), tripInstanceTotal: Trip.count()]
}

Added dynamic finders support for list, find, and count methods that take the view name from the method. Instead of calling Customers.list("byName") you can now call Customers.listByName(). The list and count methods only accept options as parameters, for example Customers.listByName(params). The dynamic finder methods assume that the keys are passed first and that the last parameter of type Map contains any options, e.g., Customers.findByName("John Smith", "John Doe", params) will query the customers/byName view for keys that equal “John Smith” or “John Doe”.

The methods findByView() and findByViewAndKeys() were renamed to queryByView() and queryByViewAndKeys() to avoid any potential conflicts.

Added a “typeFieldName” parameter to the @CouchEntity annotation that specifies the name of the type field stored in the JSON document (and CouchDB database).

Added automatic type conversion on list, find, and query results if the name is the same as a field of the domain model. A field like lastUpdated will get returned as a Date object instead of a string that you would have to convert.

Added support for @Transient annotation on transient fields. This is in addition to the already present GORM “transient” support. This also works on “read-only” fields, i.e., bean properties with a getter but no setter.

The plugin now uses jcouchdb’s svenson library for JSON generation and parsing. This gives us a slight performance boost, but more importantly, keeps us inline with future jcouchdb changes and enhancements.

Added a toJSON() method to domain objects that returns a JSON version of the domain object. Note that this could be very different from the one returned by Groovy’s JSON as id becomes _id and version becomes _rev along with other changes.

Bug Fixes

  • Now correctly read attachment’s metadata
  • Now remove the automatically injected id and version properties, and rewrite the toString() method to use the right fields
  • Now allow spaces in id values for bulk operations
  • Can now store unicode data in any field (including id fields)

What’s next?

Right now we think we have a fairly stable plugin that we have started using in actual projects and will be improving this as we run into any issues. For me, the first thing will probably be compound key support, where something like project_myProjectName as the id value of my document instead of a generated value. Above and beyond that, handling object relationships is pretty high up there – we’re just trying to figure out the best way to do it.

Our main repository is on Cory’s Github since he’s been doing most of the work at this point and I’ve shifted into more of a project management role.

For bugs, please submit any issues to the bug tracker on Github. New feature and release planning will be on PivotalTracker. We haven’t setup a separate mailing list, but both of us are on the Grails user and dev lists. If you would like to become more involved, contact either of us through the Github system.

Finally, if you are developing a different NoSql Grails plugin we want to talk to you. We want to see if we can coordinate our efforts and if there’s any common ground we can agree on so that we aren’t all reinventing the wheel.

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

6 signs your Web UI was created by a programmer 3

Posted by Warner Onstine on October 22, 2009

This post was inspired by “The 7 signs your UI was created by a programmer” post on Voyce.com.

  1. Your Web UI consists solely of CRUD (Create, Read, Update, Delete) screens – no matter how complex the user interaction is, it can always be boiled down to CRUD. Right?
  2. Everything is in Times New Roman – who needs a nice-looking font anyway?
  3. Everything is using the latest JavaScript library with UI functionality – what do you mean not everyone is running the latest FireFox beta?
  4. It uses tables for layout. Everywhere. Because CSS sucks to debug (on top of that, “Screw the Semantic Web!”).
  5. The form fields validate, they just don’t have any errors next to them when they fail – because the user should know what they did wrong.
  6. And forms themselves go on and on and on

I could only come up with 6, but I’m sure there are many more. Add your favorites in the comments below!

I’m also hoping to turn this into a somewhat regular series on Web Developers and tips and tricks for designing usable, non-ugly interfaces. If you have any tips, let me know in the comments and I’ll be sure to credit you.

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Here comes gorm-couchdb plugin for grails 4

Posted by Warner Onstine on October 21, 2009

Well, crazy or not I actually (somehow) convinced someone to help me out. And boy did he help! I got some of the basics going and then Cory took off with them. He’s put a lot into this plugin and for that I wanted to publicly thank him.

Now, onto the nitty-gritty. This is an alpha release, so it’s still missing some features (mainly object inheritance and any kind of relational mapping right now). Basically what you can do is to create an object and save it in a CouchDB database. We have some configuration options and some other cool things that you can try out like loading/reloading of views in your database.

Here are some of the basics of what you can do with the gorm-couchdb plugin

  • Save a class as a CouchDB document
  • Specify the type of document you want to save (special field in the database)
  • Save attachments with a document
  • Specify a custom id an version field to use for your class/document
  • Load and reload .js views directly into your database when they change

There is a short how-to on the wiki. To install it you can just do a

grails install-plugin gorm-couchdb

or download from the Grails Web site.

We’ve switched the main repo over to Cory’s since he’s been doing most of the work at this point and I’ve shifted into more of a project management role. I’ll get to down to some more development of features I really want (like composite keys) in the near future.

For bugs, please use the one on Github, we will be doing all of our release planning over on PivotalTracker. We haven’t setup a separate mailing list but both of us are on the grails user and dev lists. If you would like to become more involved contact either of us through the Github system.

Finally, if you are developing a different NoSql grails plugin we want to talk to you. Primarily we want to see if we can coordinate our efforts and if there’s any common ground we can agree on so that we aren’t all reinventing the wheel.

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Crazy? Working on CouchDB Grails OR plugin 4

Posted by Warner Onstine on September 16, 2009

Not sure if I’m crazy or not but after getting an initial setup with jcouchdb I am getting tired of manually mapping my class fields with the Couch fields so I’m starting to work on a gorm-couchdb plugin.

Pouring over Grails code (and the gorm-jpa plugin code). Chime in if you’re interested in helping as this is secondary to what I want to get done. I’ll throw some code up to github soon (maybe tomorrow with an early, early version).

Posted via web from BlackBox Post

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Git, Mercurial, or Bazaar? 9

Posted by Warner Onstine on July 07, 2008

The other big change I’m considering is actually moving away from Subversion. I’ve really enjoyed using it, but a recent discussion on the Groovy Dev list about Distributed Version Control Systems (DVCS) has got me looking at alternatives and why it would be good. I asked my friend Kate if she had any blog posts on why switching to a dvcs is a good idea and she whipped one up for me.

After reading through it I think I’m sold, but now I’m trying to figure out which one to try out first. Git honestly looks like the clear winner here in a number of respects:

  • Serious mindshare amongst the OSS projects
  • Has a great community committed to pushing the project forward (as Kate suggests )
  • Has some really good functionality (even if it is a bit obtuse to get to understand)
  • Looks like the beginnings of some plugins

But it also has some (current) drawbacks:

  • Tools are really only available on Linux – Mac looks like its coming but could be a pain in the ass to build, forget Windows right now
    • No IDEA plugin yet (bummer) – but it does look like IDEA 8 will support it
    • No NetBeans plugin
  • It’s a bit obtuse to learn – the commands are not necessarily the easiest to understand but they do have a Subversion -> Git guide online

So, I think I will try Git first, maybe. What about the other two – Bazaar and Mercurial? Bazaar honestly looks like 3rd place contender right now, but it does have some interesting tools available to it. Let’s look at Mercurial next.

  • There are some pre-built packages for OS X and Windows – nice
  • Again, looks like the beginnings of some plugins

Some current drawbacks

  • Doesn’t seem to have the same mindshare as Git does (this is my perception not necessarily true)

Now onto Bazaar.

Of course after I started this I found this much more in-depth review of the different systems over at InfoQ.

I think after reading a ton more on this (and the InfoQ article) that I’m going to give Mercurial a short first and see how it goes. Kate makes two more points at the end of this blog post on Mercurial vs. Git (which itself was a response to another blog post) – If you need Windows support or documentation are important items then Mercurial may be a better choice. For me, while I don’t need Windows support, it will be nice to understand what I’m trying to do first.

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Is Maven going away? 12

Posted by Warner Onstine on July 06, 2008

First, let me say, I like Maven – a lot. I’ve liked the idea, if not the execution, since 1.0 (yes, I know there is some serious bad blood for the implementation of 1.0, and yes I still liked it). But I’ve recently run into some irritating problems with Maven that would again, I think, require a major reworking of what it does.

Here is the main issue Maven is designed to handle one language only for its compilation – primarily Java. This is rapidly starting to fall apart now that the JVM has some serious contenders besides Java, namely Groovy, JRuby, Jython, and Scala. There are some hackish things for getting Maven to deal with these, however it still only has one “true” source directory for compilation. A case in point is a mixed Java/Groovy project – trying to get IntelliJ to respect the fact that I want not one, but two main source directories is a pain in the ass as I have to either tell it not to sync everytime I launch or I have to refix the source directories each time I update the project.

This is what triggered this post – what happens when I want to do some Flex programming with some Java, ActionScript and MXML, all of these are true source files (and in Maven specfic directories). I’m sure some Mavenite is going to say that these should be separate projects, but in alot of cases they aren’t and it doesn’t make sense to actually separate them into sub-projects. And I’m equally as sure that some Ant-ite is going to come along and tell me to use Ant – I won’t. Ant is stuck in the past and I won’t use it unless I absolutely have to. I like the “imposed” structure that Maven offers. I can walk up to any project and know where to find stuff instead of blindly hunting around for hours trying to piece it together like some giant source-code jigsaw puzzle, blech.

So, I’m at cross-roads, what should I do? There is Ivy (for dependency management -which they got from Maven natch), but that requires Ant, blech. There’s also Gant, ok, this is better, but still Ant. GMaven, but I’m right back where I started.

Enter, Gradle, a new Groovy-based build system that offers alot of the benefits of Maven without locking you in and the flexibility of Ant. I’m not 100% sold on it yet, but I’m going to give it a shot for a relatively complex project that will have a fair amount of Java, Groovy and other fun resource files. It looks interesting in that all the build files are actually Groovy scripts that are a DSL (like Gant files). Here’s a short example with some dependencies (taken directly from their examples in the download).

import org.gradle.api.tasks.util.FileSet

usePlugin('groovy')

group = 'org.gradle'
version = '1.0'

sourceCompatibility = 1.5
targetCompatibility = 1.5

dependencies {
   clientModule(['groovy'], ":groovy-all:1.6-beta-1") {
       dependency(":commons-cli:1.0")
   }
   compile project(':groovycDetector')
   testCompile ":junit:4.4"
}

compile {
   exclude('**/Exclude.java')
   groovyExclude('**/ExcludeGroovy.groovy')
   groovyJavaExclude('**/ExcludeGroovyJava.java')
}

manifest.mainAttributes(myprop: 'myvalue')
metaInf << new FileSet(new File(srcRoot, 'metaInfFiles'))

test.options.systemProperties['org.gradle.integtest.buildDir'] = buildDir.absolutePath

I will try and keep everyone up to date as I continue to investigate this new build system. They also state that they are going to be supporting polyglot programming in the near future which I’m looking forward to.

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Flex vs. OpenLaszlo

Posted by Warner Onstine on May 14, 2008

Last night I presented part 2 of a 2-part series looking at Flex and OpenLaszlo at the Tucson JUG. Here are my final thoughts on the two (given a brief introduction to each):

  • Both are good platforms for RIA
  • I really like the fact that you can compile Flex apps in either XML or in ActionScript
  • I like OpenLaszlo’s xpath notation for connecting to XML datasources
  • I feel that Flex has really gained the mind-share of the Open-Source community. I found many more tools available to me in Flex-land than in OpenLaszlo
    • See BlazeDS, GraniteDS for some excellent Open-Source data and messaging providers for Flex
    • Maven and Ant(included with the Flex SDK) tools for Flex
    • Unfortunately the Eclipse plugin for OpenLaszlo appears to be gone, gone, gone.
    • Both have Unit testing frameworks available – ASUnit, FlexUnit, and LzUnit
  • I like the fact that OpenLaszlo supports additional run-times through the new “legals” initiative (DHTML and others are in the pipeline through a partnership with Sun)
  • I couldn’t find an easy way to setup a project for OpenLaszlo through Ant or Maven. I’m sure they exist but nothing turned up in a cursory search
    • I take it back, I finally found this on the OpenLaszlo wiki for ant tasks included with the source. But not packaged up all nice and clean like the ones for Flex. Blech.
  • I also like how easy it is to create and modify components for Laszlo. I don’t know how easy it is to do this in Flex.
  • The docs for OpenLaszlo are somewhat scattered and some are sorely out of date. Several examples on their own site didn’t work at all with 4.0.12

Overall I think I will be focusing my future efforts on Flex/ActionScript 3.0 and unfortunately leaving Laszlo behind. I have been a fan of it for quite a while but I don’t think it has kept up at all with Flex and is starting to lose mind-share amongst the Open-Source community.

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Optimizing Tapestry 4 for development

Posted by Warner Onstine on May 02, 2008

Periodically I will do small consulting gigs and recently had a client who wanted to know if there was a way that they could improve their development experience with Tapestry 4. Their specific problem lied in the fact that when they initially pulled up any Tapestry page it was incredibly slow to render that first time. They were not using the property org.apache.tapestry.disable-caching so that definitely wasn’t the issue.

The solutions that I came up with after doing some research and looking at their code were these:

  • Use Jetty for development
  • Convert as much of their pages (and components) to be “spec-less” as possible

Two primary reasons to use Jetty are that it allows you to more easily reload HTML changes and in general is a much more lightweight container than Tomcat, therefore getting an overall faster startup time and increasing development time. One of their own developers was already using Jetty and was seeing speed increases.

The primary reason to convert your HTML pages to be ”spec-less” (in other words no *.page file to bother with) is that reduces the overhead that Tapestry 4 puts into place to parse the XML file and figure out how all the components are wired together. Instead it puts this in either the HTML template, which it is already parsing, or in the Java class as an Annotation.

This also has the side benefit of prepping your code for converting up to Tapestry 5 as it uses no *.page files whatsoever.

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Groovy DSL roundup

Posted by Warner Onstine on April 24, 2008

This is my first attempt at categorizing some of the DSLs I’ve run across into some kind of logical grouping. First I’ll list out some Groovy DSL examples (sound off in the comments for those I’m not aware of, the more the better). I’ll go through the DSLs first and then look at the possible categories after the break. And the first two are mine that I created

I know there are more out there but this is a good starting point for sure.

Now, on to the actual categories of DSL “types”

I have been paying attention to Martin Fowler’s new DSL book in which he specifies several types of Internal DSLs. I’m not 100% on board with all of these yet, but here they are (of course these may change as this is a work in progress, so if he changes them it isn’t my fault :P ):

  • Expression Builder: A layer that provides a fluent interface over a regular API
  • Function Sequence: A combination of function calls as a sequence of statements.
  • Nested Function: Compose functions by nesting function calls as arguments of of other calls.
  • Method Chaining: Make modifier methods return the host object so that multiple modifiers can be invoked in a single expression.
  • Object Scoping: Put DSL code in a subclass of a class that provdes the DSL vocabulary.
  • Closure:
    • Nested Closure: Express statement sub-elements of a function call by putting them into a closure in an argument.
  • Literal Collection Expression: Form language expressions using literal collection syntax
  • Dynamic Reception: Handle messages without defining them in the code
  • Annotation: Data about program elements, such as classes and methods, which can be processed during compilation or execution.
  • Macro: Define DSL expressions as macro definitions
  • Parse Tree Manipulation: Capture the parse tree of a code fragment to manipulate it with DSL processing code.

Ok, so these are the basic categories as Martin has defined them. How do these map up to the tools and techniques we have in Groovy?

  • Method/Property Missing – a special method that is called when a method can not be found allowing a developer to intercept the call
    • Maps to Dynamic Reception fairly well
  • Categories – allows new methods to be added to any class at runtime
    • Could fit into Object Scoping or maybe a new one, Duck Typing? – not sure
  • ExpandoMetaClass – a dynamically expandable bean
    • Again Dynamic Reception
  • Closures/Nested Closures
    • Closures/Nested Closures
  • Relaxed rules on the use of parentheses
    • Hmm, not sure where this would fit
  • Built-in list and map syntax
    • I believe this is Literal Collection Expression
  • Ability to dynamically add methods to an interface and have concrete classes also have the methods
    • Again, this sounds like Dynamic Reception
  • Operator overloading
    • Hmm, again I’m not sure where this fits
  • Annotations
    • Annotation

First up we have our builders (AntBuilder, XMLBuilder, Criteria Builder, etc.) these essentially mimic some other existing structure (an Ant build file, XML file, or SQL syntax). What patterns do these use? Just off the top of my head I think I see:

  • Expression Builder
  • Nested Closures
  • Dynamic Reception
  • Literal Collection Expression

JSON-lib’s Groovy interface has the following:

  • Literal Collection Expression
  • Dynamic Reception
  • Operator Overloading (as)

My Groovy Higher Order Messaging DSL has:

  • Dynamic Reception
  • Nested Closures

My Groovy Math DSL has:

  • Dynamic Reception
  • Nested Closures (or possibly what would be considered Function Sequence in some cases, even though they aren’t functions but it might fit)
  • Operator Overloading

GroovyLab has:

  • Expression Builder
  • Probably has more just don’t have time to dig into the code – I’m just looking at the quick examples)
  • Operator Overloading

Guillaume’s Unit Manipulation DSL has:

  • Expression Builder
  • Dynamic Reception
  • Closure/Nested Closure
  • Operator Overloading

Ken Barclay’s GParsec has:

  • Dynamic Reception
  • Parse Tree Manipulation? (not sure if this qualifies for this or not)

GroovyRestlet DSL has:

  • Literal Collection Expression
  • Closure/Nested Closure
  • Function Sequence

GSpec has:

  • Closure/Nested Closure
  • Function Sequence
  • Dynamic Reception

Grails’ Domain Class Validation DSL has:

  • Literal Colleciton Expression
  • Closure
  • Macros?

Tiago Antão’s Malaria Drug DSL has:

  • Object Scoping
  • Dynamic Reception

Human readable date modification has:

  • Object Scoping
  • Operator Overloading

Now, one of the big things that I think Fowler is missing here (and one that you can see several DSLs take advantage of) is Operator Overloading/Overriding. This, I think, is a key technique in DSLs and one that can make a DSL go from good to great. It’s all about letting the user think in the context they are in – be it math matrices, sql queries, file and string manipulation (overriding the << or >> operators). It’s all about the user’s context and making it easy for them to “think” in their domain and not have to worry about the language implementation (I use it quite heavily in my Math DSL to implement matrix operators for example).

I know I didn’t hit on all the DSLs I mentioned, but will try and come up with a wiki or something that people can contribute back to. In the mean time sound off in the comments if you have a DSL that I didn’t mention, or you feel my categorization is wrong (and why). I’m also curious if there are examples of some of the ones I didn’t touch on such as Annotations. This is an initial stab at this and as I said earlier I’m not 100% on board with how Fowler has organized things but I think it’s a good start.

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Portal/Portlet work continues

Posted by Warner Onstine on March 29, 2008

So I thought I’d update everyone on my progress so far with the Portal/Portlet component I’ve been working on, as well as some of the issues I’ve run into.

Normally I would have posted this to my Tapestry 101 blog but I’m going to try and consolidate my blogs together and I’m extremely tired of JRoller’s broken Textile formatting, such a pain in the ass (I have fallen in love with Markdown and code markup, it rocks!). I’ll be crossposting this, but soon I will stop updating the JRoller blog.

I now have a basic implementation of the Portal component complete and it consists of the following classes:

  • Portal.java – Stores a TreeSet of columns
  • Portal.html – Adds in the portlet controls div and some custom CSS stuff (which I’ll talk about shortly)
  • PortalColumn – Stores a TreeSet of Portlets plus some configuration for viewing (width and background color)
  • Portlet – Stores the Portlet title, content and it’s location
  • portal/scripts/
    • Portal.script – includes all the JavaScript files and does some dynamic stuff (coming up shortly)
    • prototype/scriptaculous scripts
    • portal_hooks.js – the hooks for the portal actions (close, move, etc.)
    • portal.js – the actual JavaScript for the portal functionality that can be called by the portal_hooks.js file
  • portal/css – portal.css
  • portal/images – all the images for the portal controls and rendering (rounded corners)

Ok, so that’s the basics here are some of the specifics.

Portal.script

<input-symbol key="columns" required="yes" />
<initialization>
 function init() {
 portal = new Xilinus.Portal("#portal div", {onOverWidget: onOverWidget, onOutWidget: onOutWidget, onChange: onChange, onUpdate: onUpdate, removeEffect: Effect.SwitchOff});
   <foreach key="column" expression="columns">
    <foreach key="portlet" expression="column.portlets">
    portal.add(new Xilinus.Widget().setTitle('${portlet.title}').setContent('${portlet.content}'), ${column.index});
    </foreach>
   </foreach>
   // Add controls buttons
   portal.addWidgetControls("control_buttons");
 }
 Event.observe(window, "load", init);
</initialization>

What I’m doing here is creating a new Portal (from Xilinus) and then I’m looping through each column and then each portlet inside of the column to add it’s content.

I dive into the hackish parts after the break.

Portal.html

This part contains some of the CSS hackish-ness I was hoping to avoid.

<span jwcid="@Script" script="Portal.script" columns="ognl:columns"/>
<div id="portal">
<div jwcid="@For" value="ognl:column" source="ognl:columns">

    <div jwcid="@Any" id="ognl:'widget_col_' + column.index" />
</div>
</div>

This first part just adds in the Portal.script and then declares the html div element we want to use (this element is used throughout the CSS and JavaScript files. The next piece loops over the TreeSet of columns and outputs one specially-named div for each column.

This just creates the HTML for the portlet controls (don’t know how customizable I’m going to make this yet).

Now comes the hack.

<style type="text/css">
<span jwcid="@For" value="ognl:column" source="ognl:columns" renderTag="false">
#widget_col_<span jwcid="@Insert" value="ognl:column.index"/> {
  float:left;
  width: <span jwcid="@Insert" value="ognl:column.width"/>;
  background:<span jwcid="@Insert" value="ognl:column.backgroundColor"/>;
}
</span>
#edit_button {
  background: url(<span jwcid="@Insert" value="ognl:editButton.buildURL()"/>);
}
#delete_button {
  background: url(<span jwcid="@Insert" value="ognl:removeButton.buildURL()"/>);
}
</style>

Here you see I had to do some inline styles so that I could add in some new attributes for the columns, as well as images for the control buttons. I posted a query to the mailing list about 2 weeks ago, asking if there was anything like RCSS (Ruby CSS) where you could actually use Ruby to generate CSS stylesheets – which is exactly what I need here.

After talking with Howard there did not appear to be any good way of going about doing this. One solution discussed was to let the user drop in a replacement stylesheet, but to me this seems silly, they don’t need to recreate the whole style sheet.

Another solution was to create a Tapestry page that acted like a CSS file. This still holds some promise, but is technically going to be a bear to implement due to the fact that we have to change the mime-type. The kicker in all of this though is that this isn’t going to be easier in Tapestry 5, at least not right away.

The other issue that I have with implementing this is what a pain it is to work with JavaScript in this environment and now I completely understand why it wasn’t really worked with before. Customizing the JavaScript that I need to output is a truly a pain, using XML to do my looping for me feels…wrong. If there are two areas I would like to contribute to these are it – making JavaScript and CSS more first-class citizens. Outputting HTML isn’t everything you do in a Web application.

What’s left?

Not quite done with this yet. I still have the following items to clear up:

  • Need to make the Portal, Portlet, and PortalColumn classes persistable
  • Once that’s done I need to modify the JavaScript hooks so that some kind of Ajax call happens whenever a user moves a portlet, adds or removes a portlet so that their selected portlets are saved in the database
  • Need a new Page so that a user can see all possible portlets to add to their custom page
    • For this page was kind of thinking of doing a slick sliding door effect, dunno yet
  • Add in some further customizations
  • Replace default button images with ones that are easier to read/understand and fit with our internal scheme a bit better (these are customizable)

I’m trying to get this code Open-Sourced, so it may take a little bit to get this code available but it shouldn’t be too much of a problem (and we have some other cool little items we’re going to release as well – just need to clean them up).

Share and Enjoy:
  • Print
  • Digg
  • Reddit
  • del.icio.us
  • Twitter
  • Facebook
  • Google Bookmarks
  • DZone

Easy AdSense by Unreal