Groovy/Grails Talk
Home     Login     Register
These are all the Blogs posted in July, 2009.
Friday, 31
Book - Grails 1.1 Web Application Development - Part 9
Chapter 8 - More GORM and Criteria

Part 1 of this series can be seen here.
Part 2 of this series can be seen here.
Part 3 of this series can be seen here.
Part 4 of this series can be seen here.
Part 5 of this series can be seen here.
Part 6 of this series can be seen here.
Part 7 of this series can be seen here.
Part 8 of this series can be seen here.

Chapter 8 builds upon our application by adding file versioning capability to our file sharing system. This provides the excuse to revisit GORM and criteria queries as promised in an earlier chapter.

As we start the chapter, file sharing is modeled through two domains, File and FileData in a 1:1 relationship. Here we add FileVersion. FileVersion takes on all the responsibilities that File had, while File creates a hasMany property for the versions. In order to achieve the capability of retrieving the versions in the desired order, the author added a SortedSet property using the same name as the container specified in the hasMany map for the versions. In order to allow this ordering, FileVersion had to implement the Comparable interface and a compareTo method. Jon used the public access modifier on the compareTo method, which is unnecessary in Grails. It was nice having implementation of an ordered relationship between the two domains.

After the requisite changes and additions were made, File is 1:m to FileVersion, and FileVersion is 1:1 to FileData. With this change, it became necessary to change how data was retrieved on the home page. This lead to the discussion of criteria queries. The first thing the author did was to show three dynamic queries from chapter 5 and the equivalent versions written using criteria. This clearly demonstrated how criteria queries are built. He then explains that nodes within the criteria can be used to specify logical operators and to query across associations. For the latter, a property added to File meant to hold a reference to the current FileVersion was used in demonstration. He also discussed the use of FetchMode as we still want to retrieve the User eagerly from the current version. After providing two tables, one a criteria reference, the other a listing of logical criteria operators, we are shown the use of criteria properties, in this case, limiting the results of our File query to ten. He closes the discussion of criteria queries by providing links to the Hibernate Criteria Javadoc, and informing us of and providing links to documentation on Projections and Scrollable Results.

At this point, we are directed to modify the save method in the FileController. Here we run into a problem. The code listing on page 160 meant to display the errors does not work. In the listing, a view of post is referenced. No post view has been created thus far, nor is it contained in the downloaded source. The downloaded source references create as expected. Worse, though, is that by changing the model here from file to currentVersion breaks causes no messages to be displayed on an upload error. The problem is that the save is done on the File object and the Error object is bound to that, not to currentVersion. There are multiple solutions to this. One possible solution is to add a line just before the render to set the current version error object to the file error object. This is shown below.
if (file.save()) {
flash.userMessage = "File [${currentVersion.name}] has been uploaded."
redirect(controller: 'home')
}
else {
currentVersion.errors = file.errors
render(view: 'create', model: [file: currentVersion])
}

However, this smells to me. Rather, the preferred change in my opinion is to the create.gsp. Here the code currently reads:
< g:hasErrors bean="${file}" >
< div class="validationerror" >
< g:renderErrors bean="${file}" as="list" / >
< /div >
< /g:hasErrors >

Change this to:
< g:hasErrors >
< div class="validationerror" >
< g:renderErrors as="list" / >
< /div >
< /g:hasErrors >

After writing the rather complex save logic in the controller, Jon tells us that he understands it is complex and difficult to test. He states that we will be moving much of this logic to a service in the chapter.

The chapter is closes with the required changes to our home page and message properties, and by updating the download method in the FileController.

I have to admit to being a bit frustrated by the errors encountered, though most books do seem to have some problems. None encountered so far have been insurmountable to me, but a noob may be really dazed and confused. Then again, problem solving is a great way to learn. If you feel that way, I suggest you download the free version of Jason Rudolph's mini-book Getting Started with Grails available at InfoQ, which was based on very early version of Grails and Groovy.
Posted by Bill Turner at 08:53 PM
in Book Review | GORM, Persistence, DBs | Grails Controllers | GSP, Tags & Templates
Wednesday, 29
Book - Grails 1.1 Web Application Development - Part 8
Chapter 7 - File Sharing

Part 1 of this series can be seen here.
Part 2 of this series can be seen here.
Part 3 of this series can be seen here.
Part 4 of this series can be seen here.
Part 5 of this series can be seen here.
Part 6 of this series can be seen here.
Part 7 of this series can be seen here.

This chapter is quite short, as are the next two. A welcome respite after the more intense topics of earlier chapters. More than anything else, this chapter is really about adding functionality to the application we are building, adding the ability to upload and download files. With Grails providing access to Spring's MultipartFile interface, this is all very simple, just as so much else is easy when using Groovy and Grails.

To accomplish these tasks, we create a File domain, controller, and create.gsp. We are told that the maxSize constraint provides a hint to GORM when generating the database schema. We are later reminded that relationships between domain objects use lazy instantiation by default. Thus, we create another domain called FileData that enjoys a one-to-one relationship with the File domain and is used exclusively for holding the contents of the file. This, we are assured, increases efficiency because when we load a list of files we will not be loading all the binary data associated with each file until requested. I am not sure if at this point this is the first time we are exposed to the belongsTo property. I have done enough Grails development that this is just trivia to me. Assuming it is the first time because a point was made of it, we learn that this is used to signify cascading operations between objects, i.e. when File is saved or deleted, the same operation is applied to FileData, which has implemented the belongsTo method.

There were a couple more problems in this chapter, as well. I'll deal with the more minor first. In the section wherein we are putting in the logic for downloading files, we are given directions for updating the FileController. As is, it will not work quite properly in Firefox (on Windows, anyway) when downloading files with embedded spaces in their names. The fix is quite simple. Here is the line as specified on page 149:
response.setHeader("Content-Disposition", "attachment; filename=${file.downloadName}")

Changing this to:
response.setHeader("Content-Disposition", /attachment; filename="${file.downloadName}"/)

will assure that the proper file name is used. Here I used Groovy's slashy strings and surrounded the filename in double quotes. This fix was tested not only in Firefox, but also IE, Google Chrome, Opera and Safari, all on Windows XP.

The second problem is more troubling, not so much that the mistake was made, but what it is I discovered along the way. When we are directed to update the home page, we are told to add code after the message div. There is no div in anything we've coded to this point that uses an id of message, nor a class of the same name. Now, looking at the code, it was fairly obvious to me what changes needed to be made to the section of code we were not directed to update based upon the code we were told to add. Essentially, this amounted to adding a div with a class of panel, plus a few other minor changes. However, to be sure I wasn't doing anything wrong, I felt it best to go back to the publisher site and check the errata. Here is what troubles me the most. The errata still has not been changed to include my submission from some weeks back. The only existing erratum is a fairly trivial syntax issue, not a code issue (or explanation thereof)as I had previously submitted. Is this an indication that the publisher wants to deny that there are any issues with the book? Or, are they just extremely slow with updating the errata? In either case, it is bad. Anyway, I downloaded the source code for the book. The source code from the previous chapters confirmed my theory that I had not failed to code properly, which agreed with a review of the previous chapters. It is just plain wrong. I will be submitting this to the publisher. We'll see what good that does.
Posted by Bill Turner at 04:02 PM
in Book Review
Thursday, 23
Book - Grails 1.1 Web Application Development - Part 7
Chapter 6 - Testing

Part 1 of this series can be seen here.
Part 2 of this series can be seen here.
Part 3 of this series can be seen here.
Part 4 of this series can be seen here.
Part 5 of this series can be seen here.
Part 6 of this series can be seen here.

There are many plugins available to the Grails developer. Among them are: Easyb Testing, though new to it, a personal favorite of mine (the plugin does not appear to be ready, yet, there is little info on the plugin page. You can still use it. See the official easyb site.), Build Test Data, Selenium, Test Code Coverage, Canoo WebTest, CodeNarc and many others. While it would have been nice to have a more comprehensive chapter on testing, giving those listed above their proper due would get lengthy, perhaps worthy of a book of their own. The author instead focuses on unit testing, including many of the built-in mocking features, integration testing and functional testing using Functional Testing.

The chapter starts off with a bit of history behind automated unit testing, its relationship to Extreme Programming (XP) and Test Driven Development (TDD). He explains how the original unit testing framework is JUnit and that Groovy comes with this, extending and enhancing it, and that the JUnit framework on which Groovy and Grails builds uses the conventions prior to JUnit 4 (meaning before annotations were available). I won't go into detail here. However, I do want to point out that he remarks on one of the best practices of using descriptive test names. Here is a place where I feel easyb, a Behavior Driven Development (BDD) framework, is far superior.

I have another quibble, as well, in this section. He speaks of how many developers write test cases that do not execute against their application code, implying, I believe, that not only do you have to write tests that exercise the production code, but also that the tests must actually be meaningful. I will return to this later. My problem with this section, though, is that he gives an example of a bad test and does not demonstrate what a good test should look like. Someone likely to write a bad test, in my opinion, may not really understand what is wrong with the test as written and not intuit the proper way to write it.

And, this brings up yet another quibble. Here, again, Jon seems to have chosen to roll his own rather than using the automated features included with Grails. Maybe the way test cases were generated changed during the writing of the book explaining the differences between the code he has here in this and other examples. That could explain it, but I think that this should have been revisited and updated with the 1.1 Grails release. I'd like to hear Jon comment on this. The changes are not dramatic, though. The name of the generated unit test for class User, for example, would read UserTests rather than UserUnitTests. Similarly, he extends GroovyTestCase, at least in the example on page 116 and others, rather than GrailsUnitTestCase. In other examples, he does extend GrailsUnitTestCase. In the example testing the MessageController, the framework generates a class that extends ControllerUnitTestCase and he uses GrailsUnitTestCase. The auto-genned classes, too, come with stubs for the setUp and tearDown methods, something not included in his examples.

Jon does list the JUnit assert methods and the additional assert methods provided by the GroovyTestCase, from which GrailsUnitTestCase inherits. These additional assert methods are: assertArrayEquals, AssertContains, assertLength, assertScript, and assertToString. Also included are the convenience methods shouldFail and shouldFailWithCause. These shouldFail methods are then explained further with an example. These are a bit tricky. They take a closure and the closure is expected to throw an exception. If one is not thrown, the test fails. By using the WithCause variation, you can specify the exact type of exception you do expect. Any other exception or no exception at all will cause the test to fail.

On page 121, the author tells us of the convention of where tests are expected to live, and explains that the tests are automatically generated when you use one of the create commands. He then goes on to write his own variation, as stated before, and inexplicably in my opinion. The example here is missing the import for GrailsUnitTestCase. I am not sure that the test was tested!

We are then instructed on how to run the test case and the reporting explained. Nothing here should surprise the professional developer, especially one that has used one of the xUnit frameworks before.

Next, Jon goes on to tell us of the problems we'll quickly encounter with testing a Grails app. Unit tests do not run within the Grails container. This means that dynamic methods and properties are not available to the unit test. This leads to a couple solutions, neither of which is ideal, mocking and running the tests as integration tests. Luckily, as Jon explains, mocking support is built-in through the GrailsUnitTestCase class. He provides a table showing the various methods supporting mocking and a brief description regarding their use: mockController, mockDomain, mockForConstraintsTests, mockFor, mockLogging, mockTagLib and registerMetaClass. Of these, he demonstrates the use of mockController, mockDomain, mockForConstraintsTests, and mockFor. He goes in depth on the latter to explain how the delegate property is used on the closure.

When discussing mockForConstraintsTests the author seemingly violates his earlier assertion that you should write meaningful tests that I mentioned above. I find this rather ironic. Here he tests a constraint (page 127), but to validate only writes:

assertTrue(message.hasErrors())


Well, this means that no matter what error is thrown, the test will pass. Wholly inadequate, in my opinion. It would be better, in my opinion, to take greater advantage of the error property. For example, the test in question could be written as:

assertTrue message.errors.allErrors[0].toString().contains("Field error in object 'app.Message' on field 'title': rejected value []")
assertEquals 1, message.errors.errorCount
assertEquals "title", message.errors.fieldError.field
assertEquals "", message.errors.fieldError.rejectedValue


The first line above could be used instead of the latter three, though takes a bit more work to figure out. You may need to run a test outputting the actual error string. Certainly, your test could get more sophisticated than this and there are other alternatives. All three tests in this example are similarly challenged and the solutions for testing reliably will vary.

After explaining mocking, we are told of the limitations of unit testing, and Jon goes on to discuss integration testing. This is all fairly familiar territory so will not be discussed in depth. He does introduce us to grails.util.Environment in this section, something he promises to delve into deeper in a later chapter. I don't really agree with the reason he is using it, however. He is manipulating the creation of data in our BootStrap.groovy for testing reasons. It is my opinion that the test case should neither depend on the existence or non-existence of such data. Test cases should manage all the variables that impact proper execution.

Finally, we get to functional testing and the Functional Testing plug-in. This is all so simple to install, create and implement, that it almost seems trivial. Just what we developers need! He does stress the trade-off necessary between the level of code coverage and the time it takes functional tests to run. The functional tests are run within the Grails container.

While totally gratuitous on my part, a short discussion of the differences between Webtest and Functional Testing plugins is probably relevant. Webtest had been the original "go to" plugin for functional testing. The Functional Testing plugin seems to be the new favorite. Since many will undoubtedly work on legacy applications that use the former, understanding the differences could be necessary. There is a page on the Grails site that does discuss this, but is rather incomplete. Oh, well.
Posted by Bill Turner at 04:21 PM
in Book Review | Plug-ins | Testing
Wednesday, 15
Book - Grails 1.1 Web Application Development - Part 6
Chapter 5 - Authentication with JSecurity Plug-in

Part 1 of this series can be seen here.
Part 2 of this series can be seen here.
Part 3 of this series can be seen here.
Part 4 of this series can be seen here.
Part 5 of this series can be seen here.

Many applications require security. Luckily, through Grails plug-in architecture and a number of available plug-ins devoted to the task, adding security a Grails application is relatively easy. In this chapter, Jon takes us through implementation of many normally encountered requirements using the JSecurity plug-in. I have only used the Spring Security (Acegi) plug-in prior to this, so I really looked forward to the experience (I have read about JSecurity and CAS previously). My impression after this chapter is that implementing JSecurity via the plug-in is a fairly simple process and is one I'll strongly consider on future projects. The only caveat to this is the same complaint I've had of features the book covered earlier, namely the decision to "roll your own" rather than using the supplied commands to create artifacts and teaching and modifying those. In the end, I am not sure what it is I don't know and will be forced into digging into the features of the plug-in before I use it. Certainly, this being a tutorial, a few additional pages covering the plug-in in greater detail does not seem unwarranted.

The chapter starts off introducing us to the fact that there is a plug-in mechanism and tells us of several of the many areas for which plug-ins have been written. Jon explains that plug-ins can generate a number of artifacts, from classes to static resources, and can take part in build and runtime events. Further, he states that the core features of Grails are implemented as plug-ins, thus making the plug-in architecture fundamental to Grails, and provides the sample of GORM as a core plug-in, the plug-in used to abstract Hibernate.

It seems that the reason JSecurity was used in the project is the ease with which it could be integrated with the existing domain model. This proved to be true, in my opinion.

Jon explained that plug-ins are installed in a default directory, your user account. He then states that this gives rise to a number problems and provides two:
  • Other users may not be able to execute the plug-in.
  • If the name of the project is changed, you must remember to dig around in your user directory to change the installation location of the plug-in.
I am not sure that these are truly serious concerns. Perhaps they are on larger projects than those on which I've worked. He then tells us how to override the default plug-in location, putting it into another location. Prior to Grails 1.1, the default location was within the project tree. With the change, a number of people had problems and one of the common solutions suggested on the mailing list was to do what Jon demonstrates here, except to use the path as had been used in earlier releases. I personally now just use the default. However, I followed Jon's instructions. What I found, and it could be a user error, is that my editor, Intellij IDEA, did not recognize the path specified in the BuildConfig.groovy file causing a cannot resolve symbol JSecurity error when I created the TeamworkRealm.groovy file. This error is specific to the browser. There were no problems building the project outside of IDEA. I did try many possible solutions, and think I covered them all, but no "solution" worked. So, I just ended up installing the plug-in into the default directory. But, I digress.

He went on to explain more about the structure of plug-ins, which is certainly nice to know information. He then tells us of the scripts the JSecurity plug-in makes available to the developer. However, we are then told that one will not be used because the default domain model generated is more complicated than the simple model used by the application. We do eventually use the CreateAuthController script to generate the login action and page.

We are then provided a quick overview of JSecurity, covering the role, permissions, subject, principal and realm concepts. Permissions are not used in the application. Realms are delved in more deeply than the other subjects, and then we go on to creating our own realm. There are a couple scripts supplied by JSecurity for creating realms, CreateDbRealm and CreateLdapRealm, that are not used. What these create should be self evident from their names.

Next, we go on to implementing the authenticate method in the realm. This gives rise to a discussion of dynamic finders. This is covered relatively sufficiently. Explaining how the term dynamic is derived from dynamically constructed method names rather than the fact that the methods are added to the domains dynamically, he covers all the operators that can be used when constructing a name. He rightly implies that the junction operators And and Or are limited to two conditions. This could easily be missed by the noob and gives rise to one of my complaints about Grails. For example, you may write a finder such as Book.findAllByAuthorLastNameAndPublicationDate(name, date). This is perfectly legitimate. When you try running your code with finder Book.findAllByAuthorLastNameAndPublicationDateAndBinding(name, date, binding), you'll find that it fails and will have a large stack trace on the console. You cannot have three conditions. This violates the principle that you should always write your code so that someone else has a clear mental model of what to expect. Unless you've read the one line in the Grails document that points this out or you've properly inferred from other writings, and it has stuck with you, you will run into this error. Perhaps this is a problem with the underlying Hibernate implementation. Either way, it is wrong. Never make people guess. I digress again.

From here we are introduced to the use of criteria for more complex queries. This is barely touched upon, but we are promised that we will get a deeper introduction in a later chapter.

Then come the concepts of filters. These are similar to filters in Java Servlets. They are quick and easy to implement. And, soon, we have our first filters written.

Because the authentication is in place, we are not able to log into our application. There are no users! So, Jon takes us through adding users via our bootstrap class and we are introduced to the encryption function provided by the plug-in. This gives us the required background for encrypting the password when the user is created or updated. Jon did teach a trick here of which I was unaware. He updated the password field after calling hasErrors and save. This takes advantage of the Open Session in View pattern for hibernate. This means that changes to your object will not be persisted until all server-side operations have finished.

Finally, we add some other features to our application: an improved permission denied page, a sign out link, and displaying the author of our messages. In the latter, we are introduced to services briefly and told we will learn more about services in an upcoming chapter. We are told that Grails supports the concept of a service layer, though little more. We are also required to relate messages to users. This was done simply, but Jon does not use belongsTo or hasMany properties to do so. We are also introduced to Hibernate's lazy loading feature, the n + 1 problem to which this gives rise, Hibernate fetch strategies, and using the eager strategy to resolve the n + 1 problem.

One error was found in the code listings in the chapter on page 100. It is fairly minor. The author wrote Sha1Hash(user.password).toHex() and it should read Sha1Hash(userInstance.password).toHex(). I've submitted an error report to the publisher. Hopefully it will show up on the errata soon. Similarly, there was an instance where he used the word principle rather than principal on page 89 in the text that was not listed in the errata. I have not submitted this and likely will not.
Posted by Bill Turner at 04:33 PM
in Book Review | GORM, Persistence, DBs | Grails Services | Miscellaneous Topics | Plug-ins
Tuesday, 7
Book - Grails 1.1 Web Application Development - Part 5
Chapter 4 - Introduction To Groovy

Part 1 of this series can be seen here.
Part 2 of this series can be seen here.
Part 3 of this series can be seen here.
Part 4 of this series can be seen here.

Chapter 4 is the obligatory Groovy introduction. An in-depth introduction is not called for and has no place in an introductory Grails book. When it becomes necessary to have a deeper understanding, I recommend reading Groovy In Action by Koenig, et al, or Programming Groovy by Subramaniam.

The chapter starts off with a brief introduction of Groovy and where it fits in the pantheon of languages. For those new to Grails, any fear of needing to learn a new language is quickly dispelled by showing how closely Groovy resembles java and how well it integrates with java. Of course, this only applies if you are currently a java programmer. Jon makes it clear that almost anything written in java can be run as Groovy, unfortunately, at no point does he tell us where this isn't the case. A simple pointer to the Differences from Java and to the Things you can do but better leave undone pages on the Groovy site would have been helpful.

He covers all the basic features: everything an object, semicolons being optional, strings, GStrings, slashy strings, numbers, lists, maps and ranges. Truth and equality are likewise covered. Closures are explained. Closures are very important for the budding Groovy programmer. An understanding of closures is absolutely necessary for Grails development. Jon goes on to explain Plain Old Groovy Objects and how metaprogramming is used to add dynamic behavior, including how to use invokeMethod. This is a very interesting feature and goes to the heart of dynamic programming for those unfamiliar. While this knowledge is not critical to the Grails newbie, it is nice to know, and we are told that we will do more with it in a later chapter while developing a plug-in. Dynamic interception of calls is heavily used by Groovy Builders, which is the last section covered in the chapter.

Armed with the knowledge in this chapter, we should be able to build a fairly sophisticated application.
Posted by Bill Turner at 12:00 AM
in Book Review | Miscellaneous Topics
Monday, 6
July 2009 Groovy - Grails Job Market
The Tiobe Groovy numbers show a sharp decline from the last month. It was biggest drop in percentage and in rank, and the lowest rating since I started keeping track.

Not having numbers from Dice or Indeed for June, it is not possible to make a monthly comparison. Here, though, the numbers look encouraging. They are generally bigger than the last numbers collected. This might mean that the job market is picking up in general but that Groovy/Grails are not seeing the growth in demand that is happening with other languages.

The TIOBE Programming Community Index for Groovy
Month / Year Rating Change Rank
07/2009 0.114% -0.038% 47
06/2009 0.152% +0.020% 36
05/2009 0.132% -0.033% 41
04/2009 0.165% +0.031% 36
03/2009 0.134% +0.005% 42
02/2009 0.129% -0.006% 40
01/2009 0.135% -- 38
Dice Keyword Search for Groovy and Grails
Month / Year Groovy/Grails Change Grails Change Groovy Change
07/2009 27 -- 35 -- 68 --
02/2009 23 11 29 12 56 25
01/2009 12 -- 17 -- 31 --
Indeed Keyword Search for Groovy and Grails
Month / Year Groovy/Grails Change Grails Change Groovy Change
07/2009 168 -- 274 -- 407 --
02/2009 89 18 110 -11 305 -80
01/2009 71 -- 121 -- 385 --


Results from the search engines should be considered carefully as the results are just the numbers returned from key word searches.

Posted by Bill Turner at 12:00 AM
in News, Jobs, Marketplace
Thursday, 2
Book - Grails 1.1 Web Application Development - Part 4
Chapter 3 - Posting Messages

Part 1 of this series can be seen here.
Part 2 of this series can be seen here.
Part 3 of this series can be seen here.

The beginnings of the business goals of the project are implemented with this chapter. We create a new domain, Message, two views, one for adding messages, the other for viewing, along with corresponding controllers. Along the way, we learn about binding, validation and other user messages, the flash scope, redirection, the domain list method, several gsp (Groovy Server Pages) tags, layouts including the main.gsp and how SiteMesh renders layouts, and securing the site from XSS (cross site scripting) attacks.

There were a few small mistatements or errors. First, when explaining how dateCreated and lastUpdated properties can be added to domains and will be updated for free, he states that they must have the corresponding constraints set to nullable:true. The corresponding example shows this, as well. Setting these properties to null is unnecessary. To be fair, this could've been true in an earlier release of Grails.

The second issue is really minor. At one point Jon suggests you use the BootStrap.groovy to create some initial messages then says you can view the home page and see these messages. What he fails to mention is that the application needs to be restarted to pick up the changes to the BootStrap.groovy (unless that was just some strange issue on my side, but I think not).

The final error was when HTML encoding was discussed. We are instructed to make the highlighted changes, though the code sample has no highlighting. I trust experienced developers can overcome this.

In earlier chapters we were introduced to some command line arguments for creating domains and controllers. In this chapter, however, we are never introduced to generate-views. I thought this curious. Yes, generate-views would create several unneeded views, but I feel this being an introductory text, it would be better to demonstrate the command and direct the reader to delete the unnecessary views. The positive side of having the reader hand code the views is that it makes it far more obvious how various code fragments relate to the other parts of the application, as well as the introduced GSP tags.

At the end of this chapter, the reader should now have an understanding of the basic building blocks of Grails. This chapter covered a lot of territory. Even so, it seemed simpler than the previous chapter, likely because domain development is so fundamental to most applications. Readers should have at this point a good idea of how rapid development can be with Grails.
Posted by Bill Turner at 12:00 AM
in Book Review | Grails Controllers | GSP, Tags & Templates | Miscellaneous Topics
sun mon tue wed thu fri sat
    1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  

Latest Posts
Archives
Categories
Bookmarks
Authors
Search
Syndicate This Site
Add to Technorati Favorites