For the last five years I’ve been working for ad agencies doing rapid flash site development. Most of the sites I’ve worked on have had to be translated for multiple regions (sometimes more than fifty!) and plugged into various different forms of content management system. They have often had rotating casts of developers working on them, and usually those developers don’t have the opportunity to pass knowledge to the next person.

After leading a lot of teams and working with developers from a lot of different technical backgrounds, I’ve started seeing the same pitfalls over and over again, and I’ve come up with a few things that I think make flash coding in a team run smoother.

It’s important to note that these strategies are for sites on a very tight deadline. There are recommendations in here that would be a bad idea if you had the resources you need. But if you don’t, then you have to make compromises. These are the compromises to make:

1)    There is a big difference between doing what’s right, and doing what’s best.
The problem I often come across with developers who have come from another technical background, particularly in software, is they get a lot of enjoyment from figuring out the perfect solution and implementing it. The trouble is, there usually simply isn’t time for a perfectly architected solution. If it works, move on to something that doesn’t work, and only tackle poor architecture if it starts causing serious problems in other areas.

2)    Think about what it IS.
Often in rapid site development it’s hard to plan for every circumstance. The spec changes multiple times in mid project and suddenly the developers have to mould their work into something new.

If you can’t anticipate everything, what can you do to make the code as flexible as possible? The most important thing is to keep dependencies between site elements to a minimum. This is standard OOP stuff, but in the flash world it’s still often poorly executed. A common problem is using the same instances of a class to create site elements that look the same, but that are actually semantically different. An example might be a subheader that happens to have the same visual treatment as a photo caption. But to build a class to handle that text and use it for both the photo caption and subheader creates a dependency between those two elements that shouldn’t be there.

3)    Use constructors as much as you can.
The great thing about a constructor function is that it allows you to force an instantiator to pass the class everything it needs. Take advantage of this, and avoid having to use setter functions during instantiation. 

I know I know, getters and setters are standard practice. But bear with me – the point here is that if you define a constructor that builds everything you can be sure you have all the data you need. If you use properties and setters for instantiation you don’t know that, and it can be a real headache for a developer taking over who doesn’t know in what order properties need to be set, and what data the class needs to run properly. Constructors tell other developers clearly what data is needed to use a class, and they help avoid the need to write both constructor and modifying code, which takes more time and is more prone to bugs.

4)     Make new instances, don’t modify old ones
There are plenty of exceptions to this rule. But what I see often, particularly with simple components such as tooltips or notifications, popup panels etc, is developers instantiating a single instance of the class and then just changing the content of that instance when a new tooltip / panel is shown. The problem with this is that it forces you to build modifiers into a class instead of being able to just use a constructor, so that’s double the code and double the potential for bugs. Secondly, by using the same instance for two elements you’re often creating a dependency between two site elements that doesn’t need to be there, and can reduce flexibility and cause interference with mixed up variables, conflicting tweens etc.

5)    When taking over another developer’s work, take the time to understand it.
Code is difficult to read, especially when you didn’t write it, and modifying someone else’s code just isn’t as much fun as writing your own. Because of this, developers are often too quick to dismiss someone else’s code and rewrite from scratch. This is sometimes necessary, but often it’s just because the developer isn’t willing to take the time to figure out what the first dev did. Make sure you have a reason to rewrite someone else’s code other than not understanding it. If you must rewrite, try to rewrite only the parts that are aren’t up to par, don’t try and get it perfect (see 1).

6)    COMMENT!
Commenting doesn’t only help the next person to work on your code, it also helps you think clearly as you build. There’s no need to comment the simple, obvious stuff, but as soon as something isn’t intuitive there should be a short explanation in there. It often doesn’t feel like there’s time to do this, but it’s absolutely crucial and helps prevent situations like number 4 happening.

7)    Name things properly
Take the time to name your variables properly, and for God’s sake don’t use acronyms and short forms unless it’s really obvious what they stand for. If you’re using almost anything outside of the flash IDE these days then you’ll probably have auto-complete for your variables and functions anyway. So use full, descriptive names that leave no ambiguity about what that variable or method is. This will help you think clearer and it’ll be a godsend to the developer who takes over your work.

8)    Be realistic about changes
If a change to spec comes in, be clear about how it will affect timelines, and make sure you give yourself breathing room in your estimates.
 A lot of developers, especially as they get good, tend to be optimistic with their time estimates. They decide something is easy without taking the time to fully think it through, or they just want to look in control and competent. Don’t let your ego get involved when you’re setting other people’s expectations, be careful and realistic.

9)    Prioritize
Sometimes there are things that can be worked on after client delivery. Often there are things that need to happen outside development before the site can launch. Typical post-delivery work might be plugging everything into the CMS, making sure components work with all possible content not just the test data, or fixing bugs that are harder to reproduce. Keep track of them and keep the rest of the team aware that the work needs to be done, but leave them until the end if you want the best chance of meeting your deadline.

10)    Find compromises outside of the development
If something looks like it will be tricky to build, talk with the creatives about implementations that will be easier to develop and achieve the same goal. Sometimes the tiniest little components can cause big delays, and if there’s a faster way to implement them then it’s worth having a ten minute conversation to determine that.

 Don’t assume the creative is inflexible.

Thanks for reading, and I hope this helps! If you have any comments I’d be happy to hear them.

I’ve invited some of my friends and former colleagues to post here, in order to offer different perspectives on a wider subject matter. All of them are extremely well versed and highly experienced in varying areas of software development, and I’m looking forward to reading their posts.

The first is Rich Lowenberg. Rich has been a big presence in the professional Flash and Flex world for some time. He’s done a lot of work leading teams to bring together many very slick flash and flex based sites. He’s done some very cool stuff with Papervision3d as well. He’s also very well versed in web standards development and some server side technologies. He’s also a musician and writer, loves to travel, and recently moved to Amsterdam.

Enjoy!

Grails is a RAD framework that runs on the JVM. The project, formerly called Groovy on Rails before the RoR folks complained, is essentially just what their initial name describes. It’s meant to bring Rails-like productivity to the JVM world, while maintaining integration with all the lovely java-based API’s available. To many, what exists in the Rails world will be sufficient, but in some areas, Rails just isn’t there. Domain specific APIs (medical, banking, insurance, etc…) as well as some of the more beefy packages that would appeal to enterprise (security, workflow, rules, etc…) tend to come in Java or Java and .Net. Hence, the ability to get at these while gaining the velocity of Rails is very attractive.

Before we go too much further, though, a few points about what Grails is. Grails uses Spring and Hibernate, and can leverage the usual set of JS libraries (scriptaculous, prototype, jquery, etc…).

Code is written in Groovy, a dynamically typed language modeled to some extent on Java, but making heavy use of reduced syntax for common operations, and closures. Closures are a new beast in the java world, but should be familiar to those who write a lot of JS. Enclosing code in braces creates an implicit object which wraps that functionality and can be passed around. While this can take a bit of time for us Java guys to grok, it can be very useful.

Many dev actions are performed from the command line, using the “grails” command. This will be familiar to anyone who’s used Rails. For example, grails create-domain-class Book will create a domain class named “Book”. Subsequently running grails generate-all Book will generate scaffolding (a controller and various views) that can act as either a basis for code to use that object, or an out-of-the-box admin interface for that object. If you want to learn more about the details of using Grails, their Quick Start Guide is a good place to start.

While Grails has a lot of pieces of the puzzle, it still leaves a lot to be desired. The Eclipse plugins for Grails and Groovy have been in a dismal state for some time. SpringSource recently released a package for these which is a big improvement, yet problems persist. The dynamic typing nature of Groovy means method insight is rarely available, and the eclipse plugins appear to have huge memory consumption and some leaks. While a gc cleans up most of the memory (but not all), the frequency of gc’ing required really impinges on the dev velocity.

There continue to be bugs with complex relationships. Abstract domain classes cannot have many-to-many relationships or the app will fail to start. A given domain class can only reference itself once. This can prove challenging if one wants to build graph structures, for example. This is especially troublesome, since Hibernate supports these. Hence, something that translates Grails mapping syntax into Hibernate has serious flaws.

Grails also adds classes to the default imports, and these will have bizarre conflicts should any of your domain classes be named the same. The framework, and the tooling in the eclipse plugin, give no warning of potential problems.

I had the misfortune of having a domain class named PropertyValue. It lead to some very weird behaviour. The app would start fine and run fine, but a change to any class (controller, service, etc…) and the app would fail to run. I figured out later that something done in reloading the class would trigger the default import to take precedence, resulting in methods I was calling on my domain object not being present. When the app was assembled into a war for promotion, the app would fail to start entirely, for the same reason.

While Grails has a great many advantages, it is cumbersome to get into, and the failure in handling complex mapping situations will trouble many who are trying to build more advanced apps. I’m anxious to check out Spring’s new ROO framework, which looks to circumvent the problems posed by the new abstraction layers between the user code and the underlying frameworks in Grails by generating modifiable “glue code”, rather than the grails approach of implicit glue code. Anyone have any experience with Roo?

As some of you may know, startups need to spend a lot of their ramp up time off the radar, in order to allow their product(s) to mature. That phase just ended for my employer who has officially revealed themselves.

Brightsquid is a company who’s goal is enable online collaboration for healthcare professionals. We have great product, and some phenomenal to be announced partnerships. We have a bright future (no pun intended).

When I was approached with the option to work at Brightsquid I jumped at it. The idea of helping those who cure the sick and save the dying is appealing to me. To be offered the opportunity to contribute to the staggering efforts put forward by healthcare practitioners is inspiring in no small way. Further, the more I learned about Brightsquid, the more I could see what game changer it is. I hate to use marketing-jargon, but this is a paradigm shift if ever there was one.

One of our founders, Rahul Sood, has a blog post more insightful than anything I could ever hope to muster, so I’ll simply link to his post, and encourage everyone to read it.

I went back over some of my old posts and realised the code readability was horrible. I’ve added in syntax highlighting, should make things a little cleaner.

Enjoy!

In my previous writeup on Tapestry and Restlet, I missed something, which fortunately our integration tests turned up.

Since Tapestry is ignoring calls to our REST api, we aren’t hooked into their plumbing.  The problem here is that Tapestry stores a lot of stuff in ThreadLocal and removes it based on a Tapestry Filter.

Thus, while the result of my previous post will work in simple scenarios, one ends up with things like long running Hibernate sessions, and since Tapestry’s transaction management is a bit wonky, long running transactions as well.

To fix this problem, we need to create a Restlet Filter that will handle triggering Tapestry’s cleanup, and hook it onto our Router.  The cleanup filter:

package firstSteps.filter;
 
import org.apache.log4j.Logger;
import org.apache.tapestry5.ioc.services.PerthreadManager;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.Status;
import org.restlet.routing.Filter;
 
public class CleanupFilter extends Filter {
    private PerthreadManager perthreadManager;
 
    public CleanupFilter(Context ctx, PerthreadManager perthreadManager) {
        super(ctx);
        this.perthreadManager = perthreadManager;
    }
 
    @Override
    protected void afterHandle(Request request, Response response) {
        perthreadManager.cleanup();
    }
}

To hook this onto the router would be something like the following at the end of your Restlet Application’s createRoot method.

    CleanupFilter cleanupFilter = new CleanupFilter( getContext(),
        getService(PerthreadManager.class) );
    cleanupFilter.setNext( router );
    return cleanupFilter;

As one of our last big initiatives on Tapestry before we migrate platforms we’re starting to build a REST api.

REST stands for Representational Entity State Transfer, which explains nothing to someone not already familiar with it.  Essentially, one uses URL’s to define resources (http://mysite.com/users/trails for example), and leverages existing HTTP features instead of overloading parameters.  Specifically, using things like the HTTP method instead of a custom “action” parameter to specify the desired action to be performed on the resource specified by the url.

A former employer of mine, Gavin Terrill once pointed me to this introduction to REST article which is highly informative, and immediately sold me on the concept.

I have been for some time been a big fan of standards-based HTML.  Using things like <strong> instead of <span style=”font-weight:bold”> always struck me as an improvement in elegance; to leverage the tooling provided by a medium means others have an easier time understanding what your app is talking about, be it screen readers, browsers, search engines, etc…

REST strikes me as an analogue to standards-compliant HTML, the intent being to leverage things already defined by HTTP rather than re-inventing the wheel.  It turns out that HTTP is fairly feature-rich, much more so than the POST-and-GET-with-cookies extent to which it used by most webapps today.

REST certainly has a couple points of ambiguity, for example batching, but there are options here with various tradeoffs.

Even though we plan to decommission Tapestry in our application, we’re going ahead with this REST implementation because a) business needs dictate that we need this API b) the implementation is fairly independent of Tapestry.

There are a great many REST packages out there, we landed on Restlet simply because it seemed to require minimal integration, has a great set of features, and had the recommendation of a colleague.

We’re using their 2.0 package which is in a fairly high state of flux at the moment, but offers improvements over their 1.X version that make this worthwhile.  The code herein is based on their 2.0-M6 milestone release.

You’ll need to setup the dependencies in your pom (I assume you’re using maven), for the following artifacts which can be retrieved from Restlet’s public maven repo at http://maven.restlet.org/:

<dependency>
	<groupId>org.restlet.jee</groupId>
	<artifactId>org.restlet</artifactId>
	<version>2.0-M6</version>
</dependency>
<dependency>
	<groupId>org.restlet.jee</groupId>
	<artifactId>org.restlet.ext.servlet</artifactId>
	<version>2.0-M6</version>
</dependency>

Note the jee in the group id. This can be swapped for jse if you’re operating in a jse environment.

Restlet at its simplest is built based on the idea of an “application” which manages “resources”.  While it can certainly do much more complex stuff, this is sufficient for now.  We are familiar with resources as a core concept to REST, but the idea of adding on object called “Application” into your application might feel a little counter intuitive.  Your restlet “Application” can more easily be thought of as a REST url mapper.  It is the central object for your REST API.

You’ll need to build a basic one and an initial resource.  For these, please look at the resource and application in this restlet tutorial.

You’ll need to tweak the web.xml for your webapp to add the following snippet:

<context-param>
    <param-name>org.restlet.application</param-name>
    <param-value>
      firstSteps.FirstStepsApplication
    </param-value>
</context-param>
 
 <servlet>
    <servlet-name>RestletServlet</servlet-name>
    <servlet-class>
       org.restlet.ext.servlet.ServerServlet
    </servlet-class>
 </servlet>
 
 <servlet-mapping>
    <servlet-name>RestletServlet</servlet-name>
    <url-pattern>/api/*</url-pattern>
 </servlet-mapping>

I’ve mapped my REST stuff to appear under [application context]/api ,  [application context] being whatever you’ve setup your Tapestry application to run under.

We need to tell Tapestry to ignore the rest api, so we need to add the following to our main AppModule:

public static void contributeIgnoredPathsFilter(
    Configuration<String> configuration){
    // Tell tapestry to ignore this subpath,
    // which will be handled by the rest application
    configuration.add("/api/.*");
}

This will prevent tapestry from trying to service requests to the REST api.

The final piece of the puzzle is to hook up Resources to url templates, and have those Resources interact with Tapestry-managed services.  Typically, the approach would be to create singleton resources, and retrieve them through Tapestry’s IOC via a strategy pattern, mapping url templates to singleton Tapestry-managed Resources or something similar.  The challenge here is that restlet’s resources are necessarily one-off and restlet handles the instantiation.  Specifically, from the ServerResource javadoc:

Concurrency note: contrary to the Uniform class and its main Restlet subclass where a single instance can handle several calls concurrently, one instance of ServerResource is created for each call handled and accessed by only one thread at a time.

This could, I’m sure, be overridden, but this requires more plumbing code than I care to write.

To get our Resources talking to our Tapestry services, the restlet Resource will ask the restlet Application for services, hence the restlet Application needs access Tapestry’s registry, accomplished using the following:

package firstSteps;  
 
import org.restlet.Application;
import org.restlet.Restlet;
import org.restlet.routing.Router;
import javax.servlet.ServletContext;
import org.apache.tapestry5.TapestryFilter;
import org.apache.tapestry5.ioc.Registry;
 
public class FirstStepsApplication extends Application {  
 
	private Registry registry;
	/**
	 * Creates a root Restlet that will receive all incoming calls.
	 */
	@Override
	public synchronized Restlet createRoot() {  
 
		if ( this.registry==null ) {
			//This only works on RESTLET versions 2.0m6 or above
			//http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&amp;dsMessageId=2426537
			ServletContext ctx = (ServletContext) getContext().getAttributes().get(
			"org.restlet.ext.servlet.ServletContext" );
			registry = (Registry)ctx.getAttribute(TapestryFilter.REGISTRY_CONTEXT_NAME);
			if ( registry==null )
				throw new RuntimeException(
				"Failed to obtain a reference to Tapestry`s registry");
		}
		// Create a router Restlet that routes each call to a
		// new instance of HelloWorldResource.
		Router router = new Router(getContext());  
 
		// Defines only one route
		router.attach("/hello", HelloWorldResource.class);  
 
		return router;
	}  
 
	public <T> T getService(Class<T> service) {
		return registry.getService(service);
	}
}

Inside the createRoot method, we retrieve the registry from the ServletContext, and store it in an instance member.  We also add a method for service retrieval to be used by resources.  One could also add an additional method to retrieve Tapestry services by id, if needed.

Finally, we augment our resources:

package firstSteps;  
 
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
import com.myApp.service.MyService;
 
/**
 * Resource which has only one representation.
 *
 */
public class HelloWorldResource extends ServerResource {
	private MyService myService;
 
	public HelloWorldResource(){
		myService = ((FirstStepsApplication)getApplication()).getService(
				MyService.class);
		if ( myService ==null )
			throw new RuntimeException("Failed to obtain a reference to the MyService");
	}
 
	@Get
	public String represent() {
		return myService.getRepresentation();
	}  
 
}

That should be enough to get you rolling on Restlet and Tapestry.

UPDATE: I realized I missed a couple of things in this post.  Firstly, and most critically I missed triggering the cleanup of Tapestry resources which get stored in ThreadLocal.  This is addressed in a subsequent post.  Further, I had based some of the above code off of out of date doumentation, and have since corrected one or two method names.  Finally, I have corrected the maven dependencies, one is not required to deploy these artifacts oneself.

Spring, JRuby and Rails

By Taylor
Filed Under Software | 4 Comments 

I’m the process of porting our application.  Our objective is to increase the velocity of our development.  Our current framework, Tapestry5, has proven cumbersome and problematic (I dicussed my thoughts on Tapestry5 earlier, feel free to read through for details).  In furtherance of velocity, one should always consider the RAD frameworks, mainly RoR and Grails.

Given some of the API’s we need to use we can’t entirely get away from the Java world, but we have a large, highly talented pool of Ruby on Rails developers to draw on.  We also have a robust service layer built using packages like Hibernate, Quartz, and Spring Security, as well as domain-specific packages that are more mature in the Java world.

This presents a challenge; the talent pool screams RoR and the service layer constraints scream JVM (Grails).   From a purely technical standpoint, Grails seems the obvious choice, however, the ability to leverage an existing, vetted RoR resource pool is too appealing to a small tech company to resist.  Further, while I love Grails, it is a bit immature still.

I’m POC’ing a way to have my cake and eat it too (and avoid a data migration).  The approach is to hook a RoR web tier onto a Spring managed service layer, using the wonders of JRuby.  I want to be clear, I don’t suggest this to anyone looking to build a new application.  Chris Nelson, who wrote a plugin used in this, says:

“If you’re a Java programmer new to (J)Ruby and are thinking: “Awesome, I’ll use Spring in all my Rails apps because Spring is awesome!” you need to hold up a second. Spring is awesome — when you are developing Java applications. But in Ruby, dependency injection turns out to be unnecessary a whole lot of the time. This is because the Ruby language allows you to change things in a more straightforward way. And even if there were cases where you needed DI in Ruby there are probably better choices. I see the Spring plugin being useful where you have existing J2EE code wired together with Spring and want to front end it in JRuby on Rails.”

I couldn’t have said it better myself. So, bearing that in mind, on to the technical details.

First, you need to pull down the latest version of Goldspike, a JRuby on Rails integration package.  This can be done with the following command in the root of your rails app:

jruby -S script/plugin install svn://rubyforge.org/var/svn/
jruby-extras/trunk/rails-integration/plugins/goldspike

I’m going to assume you already know how to setup your Spring context, if you don’t the Spring docs can help.  You’ll need to make sure you compile a jar with dependencies.  To accomplish this, add the following inside the build/plugins of your pom.xml:

<plugin>
	<artifactId>maven-assembly-plugin</artifactId>
	<configuration>
		<descriptorRefs>
			<descriptorRef>jar-with-dependencies</descriptorRef>
		</descriptorRefs>
	</configuration>
	<executions>
		<execution>
			<id>make-assembly</id>
			<phase>package</phase>
			<goals>
				<goal>single</goal>
			</goals>
		</execution>
	</executions>
</plugin>

You need to get the resulting jar into your Rails application’s lib folder.

You’ll need to install warbler:

jruby -S gem install warbler

Run warble and then copy the generated tmp/war/WEB-INF/web.xml into the Rails application’s config folder.

You’ll need to modify the web.xml to add the Spring context listener by adding the two following:

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath*:service-context.xml</param-value>
</context-param>
<!-- ... -->
<listener>
	<listener-class>org.springframework.web.context.
		ContextLoaderListener</listener-class>
</listener>

I have my spring context, called service-context.xml in my jar and am loading it from there.

Now all we need to do is call a spring service from a Rails controller, and it turns out thanks to Chris Nelson’s work this uses no ugly glue code in the controller like one might expect:

class SpringTestController > ApplicationController
	include Spring
	spring_bean :testService
 
	def show
		@value = testService.value
	end
 
end

In the above, I pull a spring bean id’ed as testService out of the Spring context and from that pull a value and store it in a rails variable.  I can then use that as a normal rails variable in .html.erb

At this point you should be good to go, but I ran into problems with getting JRuby on Rails to connect to mysql.  Turns out you need to specify the mysql gem in your config/warble.rb to ensure it’s included in the war.  I just added this line to it:

config.gems += ["activerecord-jdbcmysql-adapter"]

After that, run warbler using the warble command in your rails package, and the war should be created in the rails application’s root.  Move it over to your favorite web container and you should be set.

So you’ve just finished reading that introduction to Hibernate.  Now you know how to do basic CRUD and queries, these are the things you need to know or do to take your hibernate game to the next level.

Everyone in the java world knows about (or should know about) Hibernate.  It’s a very popular persistence package for Java, handling the nuts and bolts of data persistance.  It also has a package for .NET, but I’m going to be discussing the Java API’s.

Hibernate is incredibly easy to use in simple cases, but I often find developers failing to understand some of the complexities of Hibernate that any developer working with the tech must know:

  1. Read the FAQ’s.  Hibernate’s documentation page links to FAQ’s for each API.  Read these proactively, not just when you have a problem.

  2. Understand the various relationships, and the complexities with each.  Any developer using hibernate should understand the domain, annotations/xml, and generated table structure hibernate will produce with each relationship type.  I don’t mean you need to memorize all their naming conventions, but you must understand how relationships are mapped in the db.

  3. Understand what triggers a query.  This is the biggest trap I see developers fall into.  Consider the following code:

    class Folder {
         private Set files;
         private String name;
         //getters and setters
    }
     
    class File {
         //properties
    }
     
    //in a page
    List folders = session.createQuery("from Folder").list();
    for(Folder folder:folders){
         response.write(folder.getName() + " has "
              + folder.getFiles.size() + " files\n");
    }

    This is fairly straightforward.  We’re outputting folder names and the number of files in each.  But there is a problem.
    Hibernate uses something called lazy loading.  While the details are available elsewhere, the high level description is when you load an object, it’s associated objects aren’t loaded until you use them.  This makes sense, since if you never use something it never gets loaded.  The details of how this works are available in the hibernate docs.  The defaults depend on what parts of hibernate you’re using, and this is all customizable within your hibernate mappings.
    The code above will, unless specifically otherwise mapped, trigger a query per Folder, to load each folder’s file list.  This is triggered by the call to folder.getFiles().size().  Under load (high volume of data and/or usage) this will fall over.  So what’s the solution?  In this case, itemizing the fields you want in the query will solve the problem nicely.
    Simply making everything eager (the opposite to lazy, in other words fetch at initial retrieval time) is NOT a general solution; you end up with huge object graphs being loaded into to memory very often.  Eager is appropriate in many situations, but like everything else, there are costs.

  4. Understand which associations are eager.  Hibernate annotations defaults *-to-one relationships to eager.  This is typically not problematic but create scenarios where a massive amount of joins and object creation takes place.  If you have a many X to one Y relationship, every time you load an X you necessary load the associated Y.  You also load anything which has an eager association with Y.

  5. Always check your code with sql logging on.  After you’ve built something, run through it with sql logging on and make sure the queries being made make sense to you.  If you see extraneous, investigate.  If it isn’t your code, your boss wil be happy if you find stuff like this.

Hibernate’s simplicity in basic use cases belies complex underpinnings.  People who use Hibernate blithely will fall into performance traps.  It is essential that any developer working with Hibernate understand the above; just because Hibernate does the nuts and bolts of JDBC for you isn’t an excuse to be ignorant of what it’s doing.

A Year of Tapestry

By Taylor
Filed Under Software | Leave a Comment 

Well, the blog is up and running.  Lots to do on it, but first and foremost is to get some stuff off my chest.

I’ve been working for a software startup for a little over a year.  I was brought in to help rebuild their product, a professional collaboration tool built in Java on top of a framework called Tapestry 5.

I’d heard of Tapestry before, but hadn’t paid much attention since the Java web framework space is so dominated by Spring.  Tapestry has been around for a while, but their latest version is a fundamental re-imagining.  Tapestry also has the distinction of being Apache’s recommended java web framework, a spot formerly held by the venerable Struts framework.

Having never used Tapestry before, and being familiar with both Spring and Struts, I can safely assert that I’m fairly objective.  I like Spring, but by no means do I carry a torch for them.  Many of the comparisons that follow are to Spring, since Spring is the defacto standard.

A good initial read on Tapestry is this InfoQ article, but a hefty pinch of salt is in order.   My opinions of Tapestry are decidedly more mixed.  Read on for details.

The good:

  • Basic IOC is elegant
  • Integration with Prototype, Scriptaculous is clean
  • Blackbird console is useful
  • Useful ui components for simple cases
  • A supportive (if small) set of primary participants on the mailing list

The bad:

  • Limited documentation
  • Spotty support, limited thought to people actually trying to run sites in the framework
  • Reinventing the wheel, only square – in many cases Tapestry has rebuilt, in a weaker fashion, what already exists elsewhere
  • Misleading/inaccurate statements about REST support

The ugly:

  • Transaction support is lame, minimal
  • 3rd party packages/integrations are few, and those that do exist are prototype-grade at best
  • Web tier is clunky, cumbersome in more advanced situations
  • Who the hell made everything final?
  • Serves up any file in the deployment, by default

I’m not going to talk too much about Tapestry’s strong points, since they and others talk about them quite well already.

The documentation for Tapestry is limited compared to Spring.  Some of this is no doubt an effect of team size and usage.  However, there are times when Tapestry documentation spends time extolling virtues of a given approach, rather than substantive examples.  The examples that are provided often gloss over details.  Overall, I found tapestry difficult to approach for this reason.  It’s hard to know what one part of the documentation is talking about because it assumes you know other Tapestry bits and refers to them in an offhand manner.

The support in Tapestry is essentially non-existant.  Once a final feature version (aka “dot-release”) is cut, no support releases are issued.  Case in point, the “stable” release of Tapestry at time of writing uses a version of Prototype that does not support IE8.  The newer version is incorporated into their trunk, but this is still in dev state, and there’s no fix indicated for the stable release.  If you have a production app and were hoping to support IE8, you’re SOL until the next Tapestry feature release.

Additionally, features get released in a “half-baked” form.  For example, a feature in the most recent feature version (5.1) of Tapestry is the ability override bean definitions.  The problem is that this circumvents all interception.  If one has a bean defined and decorated with interceptors (e.g. transactional interceptor), and one overrides the bean impl, one loses all interception.  The only work around here is to provide the overriding bean as a non-delegating (i.e. impolite) “interceptor”.  This is a hack that is very brittle to things like interceptor ordering.  I logged a bug about this some time ago, no movement, no comment.

Tapestry, as a framework, necessarily must do what many other frameworks do.  This has led to some interesting and novel approaches.  However, some of Tapestry’s implementations are severely lacking.  Take, for example, their decorator/interception model.  It involves an excessive amount of code, and going through the guts finds some inefficiencies (e.g. AbstractInvocation.getParameterCount() forces an array copy).  Further, many things are built in an almost xenophobic fashion.  There is no easy way to get the java.lang.reflect.Method from Tapestry’s interception framework (stunning since their Invocation impls all wrap Method objects, and expecting a java.lang.reflect.Method doesn’t seem a stretch or implementation specific).

It would seem they would have been better off to implement AOP Alliance than to home brew here.

Tapestry has also stepped away from the traditional MVC approach; it uses page beans instead of controllers.  Many claim that this is more intuitive, since now you can store state in the page.  I realize that JSF and others are doing this too, but I just don’t get it.  Why have services as singletons, and pages aren’t?  This strikes me as counter-intuitive but maybe this is just a subjective thing.

Regardless, this leads to a problem. Firstly, from the Tapestry site:

This is necessary for several reasons, most importantly because Tapestry pages are pooled. Creating a Tapestry page is an involved process, because the page object is simply the root of a large tree of other objects including user provided components, many kinds of structural objects, template objects, and others. Creating a new page instance for each request is simply not scalable.

This seems to imply that Tapestry is unable to handle high concurrency.  500 people viewing the same page at a time means that 500 page beans, and associated object trees must exist.  If the creation is such an involved process, how to handle spikes on accessing pages?  Tapestry has limiting built in, such that eventually, if too many people access a page at a given time, it stops creating new page beans and starts chucking errors.  I’ve seen Tapestry get to this state but I haven’t seen it recover (granted, I haven’t thoroughly tested this aspect, but it’s concerning nonetheless). Further the idea of “fixing” singleton controllers by imposing a cap and then throwing errors when that cap is exceeded strikes me as a cure that’s worse than the disease, for high-traffic sites at least.

The default limit per page is 30.  This configurable both globally and by page, but excessive object creation per thread means that even if one configures a huge limit, at some point all that has to be garbage collected.  The singleton approach (and I realise singleton is a hot-button issue, I don’t really want to get into a singleton debate here anyways) has this much going for it; it’s incredibly scalable.

Tapestry has made claims that it offers RESTful URLs.  There are several problems here.  Tapestry’s urls tend to follow the following pattern:

http://domain:port/folders/page:event?t:ac=something

Some of the above are situational, but the bits that start to cause problems are the page:event and t:ac parts.  I’ve read the RFC for URI’s, as far as I can tell a colon is allowed in two spots, to denote the protocol (e.g http://) and to separate the domain and port.  The colon separating the page and event, as well as the “namespaced” param violate the spec as far as I can tell (please correct me if I’m wrong).  Browsers don’t seem to mind the colon, but flash sure does, at least in AS2.  To “trick” flash into pulling a url with a colon you have to double-encode it.

Further, looking at the resultant HTML source for a Tapestry form shows something odd.  A hidden field that looks like the following (line breaks added by me):

<input name="t:formdata" type="hidden" value="H4sIAAAAAAAAAJXOM
Q4BQRSA4WcT1aokbkB0sw0N1YaoRCQbB3gznjXs7pvMDNZlnEBcQqFzBwfQqhS2
UGi1X/In//kJ9UMXOh6N4txE8QbL0ZrUVnI5ppwHWIH6grPQZ5sKNFiRqBpy3h7
7QrGlTEsh0ZGIZYWo/ERTtmwn5Hems7iGj9btHUBtCqHiwlvOZpiTh+Z0g3uMMi
zSKPFWF+mwNB4a+DPyz2D87+DcsiLnkp3MtXOai+tl2Vu9TvcAoDQfKFr/PiAB
AAA="></input>

And this is for a fairly simple form.  A complex form can lead to pages of gunk.  What is that?  Turns out it’s state and field binding information.  Eep!!  Aside from the obvious cludge of sending data from the server to the client, simply to have the client send it back to the server, isn’t there a security risk here?  Yes, but don’t worry, it’s hard to hack, we’re told:

Although you could use this technique (severe hacking of t:formdata) to control what ComponentAction was instantiated at what point in the form submission, the security effects of this are minimal; Tapestry includes only a finite set of ComponentAction classes and each has a very specific job; the worst that you could do would be to redirect certain property updates to certain other fields, and doing even that would require deep understanding of Tapestry and of the specific application.

Above was posted by Howard Lewis Ship, creator/lead of Tapestry.  The barrier to exploiting this is a) knowledge of Tapestry (open source software) and the target application.  Hence your real barrier is knowledge of the target application, but since many hacks are carried out by or involve insiders, this is not reassuring.  As Ivan Dubrov points out further down the list,

security by obscurity” [is] not [a] very good approach to secure code.

Ivan is spot on. This is concerning and Tapestry provides no means to suppress or replace this behaviour with something more secure.

In addition, requiring state information in any post is hardly RESTful.  To create a thick client that leverages web endpoints, the client must first load up a page, suss out all instances of t:formdata (there can be more than one in may forms), and then include that in its request.

The transaction support is one of my biggest pet peeves about Tapestry.  Any of us who have worked on complex apps that involve lots of data modification know the necessity of concise, well defined transactions.  The common definition of a transaction is a unit of work, but this can be a bit vague.  I like to think of them as the following: “it all passes or it all fails”.  Consider a transaction that both updates a record and performs audit trail logging into the db.  If the audit trail logging fails, we probably don’t want the change going through anyway.

In Tapestry, one has two choices; manual transaction management or use of their @CommitAfter annotation.  A service can have one or more methods annotated with @CommitAfter.  An interceptor then commits the current txn and starts a new one whenever a method with that annotation is exited.

In a situation where one annotated method calls another, when the second method is completed, all work is committed, and a new transaction is started.  Any subsequent work is in a new transaction, and if anything fails that first transaction is already committed in the db, there’s no way to call it back.  This leads to either brittle transactions or situations where service have two methods per logical method, one transactional and one not.  This makes reuse of service logic difficult and leads to code bloat.

The available 3rd party packages range from successful to mediocre.  Tapestry has successful integrations with Spring IOC and Hibernate (barring the transaction stuff described above).  However, outside of this, integrations are limited and when available, poorly implemented and supported.  The ChenilleKit package, for example, provides many enhanced widgets and integrations with packages like Opensymphony’s Quartz.  However on closer examination, these do not hold up.  Many controls fall apart in loops or AJAX contexts, and the Quartz integration works only with an in-memory job store, and provides no out-of-the-box integration with the Tapestry IOC.  In other words, if you want your jobs to talk to your services, you’re SOL.

While this isn’t something the Tapestry team can fix, it causes many problems for someone trying to build on top of Tapestry.  In these days of Ruby on Rails and Grails, the only reason to pick Java is the plethora of API’s available.  The slim pickins here hurt Tapestry’s ability to stay agile.

As mentioned previously, Tapestry take the page bean approach.  This can lead to pretty cumbersome pages as Tapestry’s expression language for their .tml’s  (.jsp analogues) is weak on anything more than data retrieval.  The recent 5.1 release took steps to improve this, but tracing data flow in a page often involves lots of back and forth between the .tml, and various methods within the page bean.  Additionally, all the getters and setters lead to very long page beans in terms of lines of code.

The default behaviour of Tapestry is to serve up any files with a couple of minor exceptions, from the deployment.  It will even serve up files out of jar’s and in 5.1 hands out directory listings.  This is done to ensure that plugins can be packaged in jars and still access assets like css, js, etc… they are packaged with.  It will also hand out any file in the deployment, including anything in the WEB-INF folder (so much for the servlet spec).  I would hazard that most sites out there running Tapestry 5 and using Hibernate are merrily serving up hibernate.cfg.xml(this usually includes a db name and password), none the wiser.  Our application isn’t but it was for a while.

Tapestry has mitigated this by allowing you to blacklist files by pattern, and defaults to .jar and .class files.  Still, this is stunningly insecure, and a serious trap for anyone who chooses to develop on Tapestry.  Further, this is discussed only in the mailing lists, so if one followed tutorials, without arbitrarily trawling the mailing lists, one’s fly is decidedly down, so to speak.

A lot of the above could be worked around, but Tapestry, and ChenilleKit by extension, make many classes final, and use runtime-generated bytecode.  This makes overriding or extended impossible in many instances.  This is done because previously users had complained when the framework changed and their extensions didn’t work, so they’re telling you what should and should not be extended.  However, it’s cold comfort when you’re facing a deadline, and have to re-implement a component in order to insert a two-line fix that would have been trivially easy with an extension.

End of rant.

I realise I just dumped hugely on Tapestry, and perhaps unfairly, I didn’t spend much time highlighting the good points. Overall though; Tapestry seems to have tripped over itself.  The elegant fundamentals of the IOC are overshadowed by the cumbersome aspects of its transactions and integrations, a highly dangerous security vulnerability, the clunky feel of the web tier, and the overall lacking support.

If you must go with Tapestry, consider using something like this tutorial, where the service layer and transactions are managed via Spring.  In such a case, however, what is one then using Tapestry for?

Tapestry hasn’t found it’s niche.  Ruby on Rails and Grails have it trumped for velocity, and Spring dominates in support, maturity and API availability.  While it does decently on several fronts, key problems keep it from being the best at anything.  Hence, regardless of what your priorities are, I wouldn’t recommend it as a platform.

Next Page →