Tynamo is model-driven, full-stack web framework based on Apache Tapestry 5

Tynamo's mission is to provide implementations for different aspects of a full web application stack that offer reasonable out-of-the-box functionality and are easy to customize. We are intent on proving that web applications based on Java can simultaneously be high performing, easy to implement and fun to develop. We leverage existing technologies where possible and provide integrations with proven, clean and compact libraries rather than limit ourselves only to standard Java (JSRs). Tynamo is both comprehensive and modular so you are free to choose the parts you like from our full stack. And finally, we like Tapestry and our modules use Tapestry IoC extensively.

Latest news

Tomcat 8 and skinny war deployment revisited

While Dokku, containerization and the like steal all of the deployment hype these days, the good old skinny wars are still alive and kicking. I was recently giving CPR to maintaining an older Tapestry 5 app that was moved from one of those ultra-cool but expensive PaaS platforms to an el cheapo VPS server (because nowadays, they offer just ridiculously good price/performance ratio and for whatever reason, the app didn’t achieve world domination at its time).

The PaaS had its own proprietary deployment API but the app had everything and the kitchen sink as dependencies so I quickly got tired of deploying the whole WAR when less than 1% of it had really changed. Since I’ve done plenty of skinny war deployments in the past and this app was in maintenance mode anyway, I figured a skinny WAR was the way to go, only to find out that the deployment script I had copied from another old project just didn’t work anymore in Tomcat 8.

Seems like there’s been lots of internal configuration changes in Tomcat 8. The problem is that there’s so much old information available (when you start googling for answers, nobody ever seems to care about specifying the version of Tomcat their advice is for) and that Tomcat’s own User Guide is hopelessly succinct, lacking any examples for the common cases or references to what and why something has changed.

Instead of utilizing the classloader hierarchy (common/shared classloaders) or using VirtualWebappLoader (which is removed), in Tomcat 8 you can configure external mount points for webapp Context resources. This is clearly documented in the relevant class in Tomcat 8’s documentation, the only problem is you have to find the class first. In any case, this is how you’d do it:

<Context path="/" docBase="ROOT.war" debug="0">
	<Resources className="org.apache.catalina.webresources.StandardRoot">
		<JarResources className="org.apache.catalina.webresources.DirResourceSet"

The base can obviously point to anything. These virtual resources are a bit like symbolic links and clearly offer way more flexibility than the previous methods should you ever need it. Now for Tapestry5 apps, loading the app and its classes from these virtual directories did not work, probably because Tapestry does its own classpath scanning for annotation support etc. I had to package my own application classes into jar and deploy it to /WEB-INF/lib to make it work (for Maven, configure the war plugin with true ). That opens up interesting possibilities, since I really don’t need to even deploy the skinny war but only the application jar to update the app. The problem with that though is that I lose the built-in benefits of parallel and hot deploying WAR files (see more about versioned parallel deployment to Tomcat ) but I guess I’ll just live with it for now.

tapestry-security 0.6.4 release addresses a serious vulnerability

While the Apache Shiro team (me included) are still mulling over how to best fix a serious security vulnerability with Shiro’s default rememberMe cookies and object deserialization SHIRO-550, I went ahead and implemented a fix for the vulnerability in tapestry-security, following a similar approach I had proposed for Shiro as well. In essence, an attacker can potentially gain access to the server using a deserialization vulnerability (see more at https://www.contrastsecurity.com/security-influencers/java-serialization-vulnerability-threatens-millions-of-applications ). It’s a bit more convoluted for Shiro in general, but once again, service contributions make this a simple matter to handle in Tapestry. In 0.6.4 of tapestry-security, only known principal types can be deserialized. Long, Integer and String (which likely cover 99% of the use cases) are sanctioned by default and users can easily contribute additional principal types to the org.apache.shiro.io.Serializer service, for example:

public static void addSafePrincipalTypes(Configuration<Class> configuration) {

You are advised to update immediately. Currently the fix is only available for Tapestry 5.4 but I’ll make other releases available as requested. You can also easily copy the relevant classes from the source tree and override services as needed in your application.

Release notes

  • Upgrade Shiro to 1.2.5 #26
  • Safely deserialize principals from rememberMe cookie #27
  • Update to Tapestry 5.4.1 #28

tapestry-conversations 0.2.0 released!

We aim to serve. A user asked for a T5.4 compatible version of conversations module and we delivered. Upgrading the module was pure joy and it is a testament to the outstanding backwards compatibility record T5 has had throughout its existence. Note that I had written the original version for Tapestry 5.0 while we were still called the Trails framework! Checkout the tapestry-conversations guide for more info.

Release notes

  • Update to tapestry 5.4 #1

tapestry-security 0.6.3 released!

While working on securing an Ember frontend with Tapestry backend, I noticed that tynamo-resteasy didn’t want to play well with security. I’m fairly surprised this issue surfaced only now because tapestry-security is fairly well battle tested. Anyhow, if you’ve ever had a problem with T5.4 and tapestry-security not being able obtain assigned roles or user identity from the request, it’s time to upgrade.

Release notes

  • Update to T5.4-rc-1 #25
  • Store ShiroHttpServletRequest to RequestGlobals before processing #24

tapestry-model 0.6.0 released!

Finally, we have an officially compatible release tapestry-model for T5.4 available. We had one long running issue with the changes in tapestry core and it wasn’t until T5.4-rc1 before it was all sorted out. The official release note is short but there’s been lots of great functional changes to the core.

Release notes

  • Fix the test suite to use changed form element names #4
  • 0.5.2 has a dependency on eclipselink #2

Here’s a few screenshots of the brand spanking new tapestry-model in action (just to put down any potential qualms abouts us doing nothing but smoking weed all day long here). Also notice the search options. gol admin home gol admin filteringoptions

Back in business

Sorry, fans of Tynamo.org (both of you, just wanted to say hi :), we’ve been gone for a few weeks. Tynamo.org was another casualty of Codehaus’ demise. We were running on top of Codehaus’ Confluence-based infrastructure and after they went bust, we had to figure out a different platform. Luckily we had already moved the code over to Github over a year ago, so now we “only” need to rebuild the documentation and transform it to Markdown powered by Jekyll. Currently, we have just a rudimentary site, we’ll be adding more content in the coming weeks. Thanks for patience!

tapestry-routing 0.1.1 released!

Bada bing bada boom! New year, new releases - and just like that tapestry-routing 0.1.1 is ready for consumption with the latest T5 beta. There were some minor API adjustments made, otherwise it’s the same, trustworthy routing module. See the tapestry-routing guide for more info!

Release notes

  • Update routing to T5.4 beta-26 #3
  • Update routing to T5.4 beta-22 #2

tynamo-federatedaccounts 0.5.0 for T5.4

Thanks to the enthusiastic, borderline pestering community :), yet another tynamo module, this time tynamo-federatedaccounts 0.5.0, gets an upgrade to T5.4! Use it before the code expires, see tynamo-federatedaccounts guide and tynamo-federatedaccounts source code.

Release notes

  • Upgrade to T5.4 #1
  • Rewrite the CollapsiblePanel component as a requirejs module #2

Tynamo goes Github!

GitHub is cool and we so desperately want to be cool too that we decided Tynamo needs to be there as well. In all seriousness, Dragan Sahpaski wrote up a whizbang script to import all of the Tynamo’s SVN history, branches etc. to a Git repo so it made the move a no-brainer. Thanks Dragan. We still love Codehaus though and they’ll continue providing a lot of the infrastructure support, like CI builds and Confluence space but we are going to moving issue management over to Github as well so we can be ready for your pull requests instead of writing the code ourselves :) Also because we are good Git citizens, each Tynamo module now has its own Git repo. Checkout the Tynamo’s organization page at Github and navigate from there to your preferred module and start forking away!

RememberMe with rolling tokens

Why is it that I cannot find a definition of a rolling authentication token anywhere? Let me provide my own then: a rolling token is a security (authentication) token that can only be used for a single successful authentication. After a successful authentication, the used token is always replaced by a new one, therefore the token is said to be rolling. There, now we can talk. I’ve always disliked typical rememberMe implementations for the weak security they provide and I still admire this eight year old blog post by Charles Miller. Let me quote from “Persistent Login Cookie Best Practice”:

Persistent login cookies are the cookies that are stored with your browser when you click the “remember me” button on the login form. I would like to be able to say that such cookies are obselete, and we have a better way of handling user logins, but they aren’t, and we don’t.

The following recipe for persistent cookies requires no crypto more powerful than a good random number generator.


  1. Cookies are vulnerable. Between common browser cookie-theft vulnerabilities and cross-site scripting attacks, we must accept that cookies are not safe
  2. Persistent login cookies are on their own sufficient authentication to access a website. They are the equivalent of both a valid username and password rolled into one
  3. Users reuse passwords. Hence, any login cookie from which you can recover the user’s password holds significantly more potential for harm than one from which you can not
  4. Binding persistent cookies to a particular IP address makes them not particularly persistent in many common cases
  5. A user may wish to have persistent cookies on multiple web browsers on different machines simultaneously

With all this in mind, I’ve always implemented rememberMe based on rolling tokens in the various web applications I’ve worked on. However, I’ve never attempted to provide it as a reusable module until one day a few months ago while I was working on federatedaccounts it hit me: rolling tokens can be thought of as just another “remote” authentication provider that can be federated with the main account. For some months now, we’ve happily been using tynamo-federatedaccounts-rollingtokens in production. I added some quick documentation for it at the end of the generic tynamo-federatedaccounts guide, have (secure) fun with it!