Showing posts with label tapestry. Show all posts
Showing posts with label tapestry. Show all posts

Monday, June 04, 2007

Tapestry Components in Scala

Recently, I became interested in Scala: Multiple inheritance, good support for functional programming, a nice syntax, to mention the greatest highlights.

As a first exercise, I tried to write some Tapestry-4 components in Scala to gain some real-world experience, and to see whether Tapestry's pretty extensive use of bytecode-generation would somehow break Scala's Java-compatibility. I was pretty pleased with the results:

The following is a trait to add authorisation support to arbitrary (form-)components. It controls whether to render the component into which it is mixed in and binds its disabled parameter.

package ch.marcus.components;

import org.apache.tapestry._

trait AccessControlled extends AbstractComponent {
object binding extends IBinding {
def getObject = Boolean.box(getIdPath.contains("readOnly")) // TODO: delegate to ac-service
def getObject(c: Class) = getObject
def getDescription = "AccessControl disabled-binding"
def setObject(o: Object) = {}
def isInvariant = false;
def getLocation = null;
}

override def finishLoad = {
setBinding("disabled", binding )
}

/**Derived components delegate to the desired renderComponent method here: */
def renderAccessControlled ( w: IMarkupWriter, c: IRequestCycle )

override def renderComponent( w: IMarkupWriter, c: IRequestCycle ) {
if ( ! getIdPath.contains("invisible") ) // TODO: delegate to ac-service
renderAccessControlled(w,c);
}
}


Here is how to derive an access-controlled version of the standard TextField component by inheriting from TextField and the trait we just defined:


package ch.marcus.components;

import org.apache.tapestry._
import org.apache.tapestry.form._

abstract class AuthorisedTextField extends TextField with AccessControlled {
//duplicate from scala.Object to make Tap's class-enhancer happy
@remote override def $tag(): Int = 0

override def renderAccessControlled( w:IMarkupWriter, c: IRequestCycle )
= super[TextField].renderComponent(w,c);

}

The only gotcha is the override of $tag which seems to be necessary due to a glitch in Tapestries class-enhancer. Oh, and for components with a specification(.jwc)-file this must be copied for the derived component. This is slightly annoying, but unnecessary for component that consequently use annotations (specless components).

This is how a Tapestry page looks like in Scala:

package ch.marcus.pages
import org.apache.tapestry.annotations._
import scala.reflect._

abstract class Home extends ScalaPage {
val text = "Hello, this is Scala."

@Persist
def getMbr : String
def setMbr( m:String )

def onSubmit = {
setMbr (getMbr + "x")
}
}

Note, how clean the code looks without all the syntactic noise you'd have to add in Java and how nice the Tapestry annotations (Persist) work with Scala.

Friday, September 15, 2006

Honeycomb now comes with a Maven2 archetype for Tapestry/Hibernate based web-apps.

Version 0.3.3 of Honeycomb is released.
Honeycomb provides an easy integration for Tapestry and Hibernate. Its distinguishing key feature is session-per-conversation support.
The main changes in this release are:

  • re-structuring into 4 libraries replaced the templates for the Core/Webapp projects with maven archetypes. Maven users get started without manual downloads.
  • Fixed rollback on RedirectException.
  • Fixed possible concurrency issue in cross-request service-model
  • Fixed: Removed dangerous loophole allowing a conversation to survive a rollback triggered by an exception.
  • Cleaned up HiveMind descriptors and moved them into the lib-modules.
  • added a Watch component to the tap-lib (calls a listener when a property has changed in a submit)

Monday, February 27, 2006

KickStart is now Honeycomb, release 0.3 out

Kickstart has moved from SourceForge to JavaForge, and it's changed its name to Honeycomb (alluding to the central role that HiveMind plays in it). Honeycomb integrates Tapestry with Hibernate for painless full-stack web-dev-support.
New features comprise

  • A hibernate DataSqueezer

  • Pluggable Audit-Trail via hibernate interceptor

  • Support for session per request pattern via simple config switch.

Sunday, January 15, 2006

With Kickstart 0.2 Tapestry supports the hibernate session-per-conversation pattern out of the box

I've uploaded a new release of KickStart. Improvements are:

  • Full support for the hibernate-session-per-conversation pattern. See hibernate.org for more.

  • fixed wrong unsaved-value-mapping

Saturday, January 07, 2006

KickStart integrates Tapestry with Hibernate for painless full-stack web-dev-support

While Web-Development with Java is supported by a variety of great frameworks it is still not easy (even tedious) to, firstly, choose the right ones for a given problem and, secondly, make them work together. (needless to refer to all the envious appraisals of RoR and, yes, even Visual-Studio by Java-developers).

I've set up a Sourceforge project, called KickStart, (first download available right now!). It's goal is to get newbies started with the most cutting edge JEE-stuff immediately, and even more important, to provide a platform to discuss the non-trivial task of glueing together the most powerful of the existing Java-frameworks into something that "just works". I believe that all the interesting problems (and solution-patterns) of framework integration patterns recurring in mailing lists and wikis deserve being collected and made available in the form of preconfigured templates for whole applications.

Kickstart strives to provide a selection of integration-patterns with well defined domains of application. Each pattern comes with a complete template application getting you kickstarted with your application in minutes.

For the time being, Kickstart is based on Tapestry, Hivemind and Hibernate. Also, Kickstart is in an early state. While it works, there's only one application pattern and template supported right now. But nevertheless, please try it and tell me whether it works for you.