Thursday, March 25, 2010

Embedded Javascript

At the time this entry was posted I was using Tapestry 5.1.0.5

The java script PopUp function wasn't working like it did under T3 so I started Googling for an answer. What I found was references to a "delegate" class. You are supposed to create a "block" () for the javascript text and then "delegate" it (with ).

I couldn't seem to figure this one out. You know I think the lack of Documentation effort in Tapestry was less of an issue when it used the interface model. But I'm keeping an open mind. Some things do seem easier (better?).

It seemed to me that the problem had to do with whitespace characters getting removed from the javascript. Line endings matter because...well it's not xml with close tags...it's javascript.

So I added the following property to my html tag: xml:space="preserve". No go. I messed with this for a good hour trying to determine why Tapestry was deleting the line ending right after the <!-- tag on the line above the first line of code. The browsers didn't like this:

<!-- function PopUp(page, size) {

In the end it became apparent that no matter how many line endings I put between the comment and the function lines, Tapestry was going to delete them and put them on one line. Even with that xml:space="preserve" thing T5 was still deleting those particular whitespace characters.

In the end I did get it working. All that was required was giving something for Tapestry to place after the <!-- characters. I added the characters // right after the <!--. This gave Tapestry something to screw with and since // marks the beginning of a comment limited to the remainder of the current line in javascript, it didn't have any affect on the script.

Here is what ended up working (Note the extra // slashes at the beginning):

<script type="text/javascript">
<!-- //
function PopUp(page, size) {
Npop = window_handle = window.open(page,'popupWindowName', size, 'status=no,toolbar=no,scrollbars=no');
}
//-->
</script>

As it turns out the xml:space="preserve" is not required. The script text doesn't get messed with by Tapestry except for that issue with the first line. I'm still going to leave the spaces in there for now so that I can more easily see what is being generated by T5.

Monday, March 22, 2010

Exception Page Not Showing Detail

After doing the basic setup for the project as described earlier, I noticed that the default exception page lacked the detail normally included in tapestry. I could still get it from the Netbeans log window, but that's pretty cumbersome because it just isn't laid out as nice.

It turns out that Tapestry 5 defaults to "production-mode" in order to hide all the excess information from users. Only a summary message is shown.

The easiest way to ensure that production-mode is off when testing in Netbeans and when deployed to your server is to specify a flag in the VM settings of your server. Note that putting this into the VM settings of the project doesn't work reliably.

In Netbeans, under Services, Servers right click on Apache Tomcat 6.0.xx and select the Platform tab and in the VM Options box enter: -Dtapestry.production-mode=false

Restart the sevice and you should be golden.

To make the setting at the application level or so the production mode is off while deployed on a server (while beta testing for example), edit the web.xml and add the following lines:

<context-param>
<param-name>tapestry.production-mode</param-name>
<param-value>false</param-value>
</context-param>

Just make sure to go back later and edit the web.xml and remove or change this to true (the default is true) if you want to deploy on a live server without the exception detail.

You can also define tapestry.exception-report-page (in web.xml) and program your own exception page in which you might be able to do something like Cold Fusion does, and specify that error detail only gets displayed to certain client IP addresses, which is handy if you want to diagnose a problem in something that's already running on a live server. Primarily this custom exception page function is intended to be used for displaying a user friendly error page, but you can do pretty much anything you want.

Thursday, March 18, 2010

Undeclared namespace prefix "p"

First time I used the if component as documented here like in this example:

<t:if test="loggedIn">
Welcome back, ${user.firstName}
<p:else>
<t:pagelink name="login">Login</t:pagelink> /
<t:pagelink name="register">Register</t:pagelink>
</p:else>
</t:if>


I got the followng exception:

Failure parsing template classpath... Undeclared namespace prefix "p" at....

on the tag I was using.

The problem? I didn't add xmlns:p="tapestry:parameter" to the html tag in the template file (look at the example).

Shell, CommonBorder or Border Components in T5

There is no Shell or Body component in Tapestry 5, but the newer method actually makes a lot more sense. Doing common borders was kind of screwy in Tapestry 3.

In t5 the "Layout" component "pattern" is used. See the basic idea here at http://tapestry.apache.org/tapestry5/guide/layout.html.

Various methods can be used to add images and style sheets including just coding simple "link" and "img" XHtml tags for static assets. Relative tags are not recommended for maximum component flexibility.

You will need to put BOTH the "tml" file and "java" file for components in the folder for the "appname.components" package. Otherwise you'll get nothing.

So far this "improved" approach looks good.

Tapestry 5 and Netbeans 6.8

There are a few pages on the internet about setting up Tapestry 5 on Netbeans 6.8.

I did manage to get it work with the Netbeans Maven plugin (as opposed to installing the maven package). I don't know much about Maven, but the whole repository thing sounds a bit too slick for me. At the scale of development I'm doing, there's no question it is overkill.

In order to set the new application I just did created a regular java web app. This is based on the "Tapestry 5, Netbeans 6.5" page at old.nabble.com. Using the regular Tapestry 5.0.5 download I created a library with the following jars in it:

antlr-runtime-3.1.1.jar
commons-codec-1.3.jar
javassist-3.9.0.GA.jar
log4j-1.2.14.jar
slf4j-api-1.5.2.jar
slf4j-log4j12-1.5.2.jar
stax2-api-3.0.1.jar
stax-api-1.0.1.jar
tapestry5-annotations-5.1.0.5.jar
tapestry-core-5.1.0.5.jar
tapestry-ioc-5.1.0.5.jar
woodstox-core-asi-4.0.3.jar


The application is called "test" in the following examples.

Setup your web.xml to look something like this (set the applicaton name):

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Test Application</display-name>
<context-param>
<param-name>tapestry.app-package</param-name>
<param-value>test</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>app</filter-name>
<filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>app</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>


You might as well delete the index.jsp file.

In Web Pages folder, create an empty file called Start.tml:


<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
<head>
<title>Start Page</title>
</head>
<body>
<h1>Start Page (Start.tml/Start.java)</h1>
<p> The current time is: ${currentTime}. </p>
<p>
[<t:pagelink t:page="Start">Refresh</t:pagelink>]
</p>
</body>
</html>


In the Source Packages folder create project called "test.pages". If you are going to do anything serious here, you might as well create a "test.components" package because you will need that to build any sort of application. Other locations can be used for other classes.

In "test.pages" create java class "Start.java":

package test.pages;
import java.util.Date;

public class Start {
public Date getCurrentTime() {
return new Date();
}
}


By the way these examples above would look better with indenting. I'm afraid I don't see a way to do this with blogspot. To bad you couldn't just wrap stuff in a pre tag.

Make sure you add the library with those jars listed above in it, then build and then run. If you didn't remove the index.jsp you will get a "Hello World". If not you'll get a demo screen showing the current time (so you know it is real :-)).

Why Bother migrating to Tapestry 5?

I have one web application that's integrated with our internal customer service system and it came time to and upgrade to current supported releases of java, jasper, and tapestry. It didn't take long to discover that moving to Tapestry 5.1 from Tapestry 3.0 required a "whole rewrite" of the application.

Apparently T3 to T4 also required extensive code changes, although the scope is much smaller. So I decided that I wasn't going to go down this road (of rewriting the app every 3 years) and started looking into the myriad of java web frameworks available out there.

To make a long story short, I ended up back at Tapestry. I even considered going way back to Cold Fusion, but that didn't sound like it'd be much fun.

Howard was promising that this would be the last time a rewrite would be required. Backward compatibility was going to be there from version 5 on out. (Of course his use of "t:comp" in his #2 screencast is already obsolete!).

Thinking the whole development process through, it seemed that the way this particular application was put together, very little of the code was actually Tapestry specific. It shouldn't be all that difficult to take this small website, move the html files to templates and flesh out the classes behind them with a lot of the same code. Deciding to take a chance, I've begun the process of migrating.