[long] Why building Spindle is hard Pt.1

Geoff Longman <[email protected]> Sat, 11 Feb 2006 13:09:35 -0500
Newsgroups gmane.comp.ide.eclipse.spindle.devel
Message-ID <[email protected]>
Let's ease into the discussion of why Tapestry 4 is so hard to build
tools for. That's my opinion and I could be wrong. I am fallible and
may not have seen the obvious approach. All I can do is lay out the
problem.

Note that I'm not bashing Tapestry in any way. I'm merely pointing out
the truth. These email discussions are not advocating that Tapestry
change in any way. I do have opinions on how Tapestry could change to
make tool support easier but that is another conversation altogether.

Consider a java class. It has a name and exists in a package.
com.foo.MyClass is how we reference the class MyClass. It's
*invariant* that we reference MyClass that way. There is no other way
to reference MyClass. There is only one true namespace in a running
java application and that namespace is The Classpath.

We can never refer to com.foo.MyClass as net.sf.MyClass and expect to
get the same class.

This rigid static structure of a Java application is what makes
building compilers and tools for Java applications relatively easy.
Compilers and tools operate on the assumption that types in the
Classpath are always referenced in the same way, package+name. We can
refer to a package and any of it's sub packages as a 'namespace' but
it is a pseudo namespace allowed in the larger classpath namespace
because of the invariant nature of the Classpath in general. There
might be the argument that the classloader hierarchy (and custom
classloaders) make the Classpath malleable but in the end, when a
piece of code "links" to a type at runtime, the classpath is in fact
invariant. The type is there or not and it is still referred to the
same way (the invariant package+name convention).

It's interesting to note that the layout of Java source files, every
package fragment (a fragment is the 'com' in com.foo), being a folder
and each sub fragment ('foo' of 'com') being a sub folder of it parent
fragment's folder, is a *convention* and is not mandated by any Java
specification. In theory the source files could be laid out in any
bizarre folder layout. But, since each source file explicitly
*declares* it's place in the namespace it would still be possible to
compile each type in the namespace in the proper place. The convention
is good though and nobody would accept any bizarre alternative layout
for Java source files.

So, namespace placement for Java types is static, it never changes. A
type's placement is bound early into the classpath, at the time the
programmer types out the 'package' declaration in the source file. At
runtime the placement in the classpath is invariant.

In J2EE style web applications there is no 'compilation' step (ignore
JSP compilation as JSP compilation doesn't affect what I'm going to
say). (Warning, I'm oversimplifying a lot here). In a regular servlet
application there is a rigid namespace, the namespace defined by the
web.xml file.  Frameworks like Struts have a rigid namespace (defined
by web.xml + the struts-config.xml file).

Servlets and Struts do not have the statically compiled enforcement of
their respective namespaces but in effect they are like the Java
Classpath - there is one runtime namespace and unless you edit a
config file, the namespace is invariant. There is no way to refer to
servlets or Struts bits without an explicit declaration in the config
file. Although, people are doing funky things with annotations these
days so who knows if that (will/already has) changed.

Building tools for Servlet's and Struts is therefore relatively easy.
Find the config file and parse it to discover all the interesting bits
that exist in the namespace. If it isn't in the config file it doesn't
exist at runtime. Even with annotated additions (if they exist) it's
still pretty easy as everything exists in one namespace only.

In Tapestry is no explicit concept of a single overall namespace.
Rather, Tapestry builds a hierarchy of namespaces. There are 2 main
kinds of namespaces and one special namespace (the Framework
namespace) that exists outside of the hierarchy. All these namespaces
are represented by a Namespace object, which may or may not be backed
by and xml file (a .application or .library file to be precise).

At this point I'll make a statement:

"Tapestry Pages and Components are allowed to exist in more than one
namepace in its namepace hierarchy"

Quite different than the Classpath or Servlets or Struts described so
far. And, as will be shown in later emails, this is the FIRST FACTOR
that makes it hard to build tools for Tapestry. I'll show how this is
possible and how this fact (take it as a fact for now) is aggravated
by other Tapestry features.

It is a SIDE EFFECT of the way Tapestry works, and it has always been
there. While there may be arguments that this makes Tapestry more
flexible, there are UNINTENDED CONSEQUENCES that not only make tool
building hard. In other words, this side effect can impact
applications that use the Tapestry framework.

Let me state right here, I am not trying to spread FUD about Tapestry.
The impacts on end users are rare and in fact I've never come across a
message in the Tapestry list where a user has described a problem they
had that I could attribute to the side effect. Perhaps that's because
it's hard to diagnose that the side effect is the cause of a problem.
More likely it's it requires what would be considered mistakes
according to the doctrine for building Tapestry applications.Mistakes
that are not detected at runtime beyond the fact that encountering the
side effect will in almost all cases result in an Exception page.

Some of the new features of Tapestry 4 make it even less likely that
an end user would encounter the side effect. But, since all the
mechanisms from Tapestry 3 used to define pages/component are still
available in Tapestry 4, it can still happen and tools must still
account for the problem.

This email is getting too long so I'll illustrate an example of how
the side effect can impact end users of Tapestry.

download

http://spindle.sf.net/broken.war

(it's a tapestry 3 app but if you replaces the libs with T4 libs it
would run and break in exaclty the same way).

try running it in the your servlet container of choice

http://localhost:port/app

The home page presents two links, the first one works. and the second
one does not (an Exception page displays).

Can you figure out why it breaks?

Why this is the case will open the next email.

Geoff


-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid3432&bid#0486&dat1642