Tapestry Training -- From The Source

Let me help you get your team up to speed in Tapestry ... fast. Visit howardlewisship.com for details on training, mentoring and support!

Tuesday, May 17, 2005

MyEclipse now has Tapestry support via Spindle

MyEclipse (which creates and bundles Eclipse plugins for an annual subscription fee) has just announced a new 4.0 milestone release, with support for JSF and Tapestry. The Tapestry support is pretty obviously Spindle, but perhaps they'll do more than that in the future.

Wednesday, May 11, 2005

Big stack trace

So, I'm testing exception reporting in Portlet Tapestry under eXo and it's working pretty well. The same information as Servlet Tapestry, but not as pretty (because of the lack of style sheet control).

I'm amused at how deep the stack traces are. You can see a lot of Tomcat, eXo and AspectJ-generated code long before it even gets to Tapestry:

  • ognl.ObjectPropertyAccessor.getProperty(ObjectPropertyAccessor.java:123)
  • ognl.OgnlRuntime.getProperty(OgnlRuntime.java:1616)
  • ognl.ASTProperty.getValueBody(ASTProperty.java:96)
  • ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:170)
  • ognl.SimpleNode.getValue(SimpleNode.java:210)
  • ognl.Ognl.getValue(Ognl.java:333)
  • ognl.Ognl.getValue(Ognl.java:310)
  • org.apache.tapestry.services.impl.ExpressionEvaluatorImpl.readCompiled(ExpressionEvaluatorImpl.java:84)
  • $ExpressionEvaluator_103cbf6e379.readCompiled($ExpressionEvaluator_103cbf6e379.java)
  • org.apache.tapestry.binding.ExpressionBinding.resolveExpression(ExpressionBinding.java:110)
  • org.apache.tapestry.binding.ExpressionBinding.getObject(ExpressionBinding.java:103)
  • org.apache.tapestry.binding.AbstractBinding.getObject(AbstractBinding.java:87)
  • $Insert_1.getValue($Insert_1.java)
  • org.apache.tapestry.components.Insert.renderComponent(Insert.java:42)
  • org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:612)
  • org.apache.tapestry.BaseComponent.renderComponent(BaseComponent.java:92)
  • org.apache.tapestry.AbstractComponent.render(AbstractComponent.java:612)
  • org.apache.tapestry.AbstractPage.renderPage(AbstractPage.java:273)
  • org.apache.tapestry.engine.RequestCycle.renderPage(RequestCycle.java:355)
  • org.apache.tapestry.portlet.PortletRendererImpl.renderPage(PortletRendererImpl.java:70)
  • $PortletRenderer_103cbf6e30f.renderPage($PortletRenderer_103cbf6e30f.java)
  • org.apache.tapestry.portlet.RenderService.service(RenderService.java:45)
  • org.apache.tapestry.services.impl.EngineServiceOuterProxy.service(EngineServiceOuterProxy.java:65)
  • org.apache.tapestry.engine.AbstractEngine.service(AbstractEngine.java:240)
  • org.apache.tapestry.services.impl.InvokeEngineTerminator.service(InvokeEngineTerminator.java:60)
  • org.apache.tapestry.portlet.RenderRequestServicerToWebRequestServicerBridge.service(RenderRequestServicerToWebRequestServicerBridge.java:49)
  • org.apache.tapestry.portlet.ApplicationPortlet.render(ApplicationPortlet.java:161)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.render_aroundBody8(PortletApplicationHandler.java:226)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.render_aroundBody9$advice(PortletApplicationHandler.java:458)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.render_aroundBody10(PortletApplicationHandler.java)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.render_aroundBody11$advice(PortletApplicationHandler.java:340)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.render_aroundBody12(PortletApplicationHandler.java)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.render_aroundBody13$advice(PortletApplicationHandler.java:172)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.render_aroundBody14(PortletApplicationHandler.java)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.render_aroundBody15$advice(PortletApplicationHandler.java:738)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.render_aroundBody16(PortletApplicationHandler.java)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.render_aroundBody17$advice(PortletApplicationHandler.java:628)
  • org.exoplatform.services.portletcontainer.impl.PortletApplicationHandler.process(PortletApplicationHandler.java:226)
  • org.exoplatform.services.portletcontainer.impl.servlet.ServletWrapper.service(ServletWrapper.java:70)
  • javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
  • org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
  • org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
  • org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:704)
  • org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:590)
  • org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:510)
  • org.exoplatform.services.portletcontainer.impl.PortletContainerDispatcher.dispatch(PortletContainerDispatcher.java:370)
  • org.exoplatform.services.portletcontainer.impl.PortletContainerDispatcher.process(PortletContainerDispatcher.java:310)
  • org.exoplatform.services.portletcontainer.impl.PortletContainerDispatcher.render(PortletContainerDispatcher.java:271)
  • org.exoplatform.services.portletcontainer.impl.PortletContainerServiceImpl.render(PortletContainerServiceImpl.java:144)
  • org.exoplatform.portal.faces.renderer.html.portlet.PortletRenderer.encodeChildren(PortletRenderer.java:100)
  • javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:693)
  • org.exoplatform.portal.faces.renderer.html.container.ContainerRowRenderer.renderViewMode(ContainerRowRenderer.java:40)
  • org.exoplatform.portal.faces.renderer.html.container.ContainerRenderer.encodeChildren(ContainerRenderer.java:34)
  • javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:693)
  • org.exoplatform.portal.faces.renderer.html.container.ContainerRowRenderer.renderViewMode(ContainerRowRenderer.java:40)
  • org.exoplatform.portal.faces.renderer.html.container.ContainerRenderer.encodeChildren(ContainerRenderer.java:34)
  • javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:693)
  • org.exoplatform.portal.faces.renderer.html.container.ContainerColumnRenderer.renderViewMode(ContainerColumnRenderer.java:40)
  • org.exoplatform.portal.faces.renderer.html.container.ContainerRenderer.encodeChildren(ContainerRenderer.java:34)
  • javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:693)
  • org.exoplatform.portal.faces.renderer.html.container.ContainerRowRenderer.renderViewMode(ContainerRowRenderer.java:40)
  • org.exoplatform.portal.faces.renderer.html.container.ContainerRenderer.encodeChildren(ContainerRenderer.java:34)
  • javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:693)
  • org.exoplatform.faces.core.renderer.html.HtmlBasicRenderer.renderChildren(HtmlBasicRenderer.java:63)
  • org.exoplatform.portal.faces.renderer.html.portal.PortalRenderer.encodeChildren(PortalRenderer.java:58)
  • javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:693)
  • org.exoplatform.portal.faces.application.ExoPortalViewHandler.renderView(ExoPortalViewHandler.java:63)
  • com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:87)
  • com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:200)
  • com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:117)
  • javax.faces.webapp.FacesServlet.service(FacesServlet.java:198)
  • org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
  • org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
  • org.exoplatform.portal.filter.PrivateRequestFilter.doFilter(PrivateRequestFilter.java:82)
  • org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)
  • org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
  • org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)
  • org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
  • org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
  • org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198)
  • org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152)
  • org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
  • org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
  • org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
  • org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
  • org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
  • org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
  • org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
  • org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
  • org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
  • org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
  • org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
  • org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
  • org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
  • org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
  • org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
  • org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
  • org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
  • org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
  • java.lang.Thread.run(Thread.java:536)

Do stacks this deep affect performance? Who knows? It's just interesting to see. Back in the day, when I was a PL/1 coder for Stratus, there was operating system code and application code. The operating system code was very stable, and the Stratus file system was like a simple hierarchical database (not dissimilar to what you can do today with an embedded database like Berkeley DB).

There was no "application stack". No frameworks, no libraries, no toolkits, no open source -- except what we created ourselves (even back then, I tended to write libraries and test suites). The application was our single layer on top of the operation system. When things went wrong, you would rule out the operating system, and start picking apart your code.

It's so much more complex now. "Your code" is a single eye dropper-full in an olympic sized swimming pool, mixed in with open source and proprietary code up the wazoo. When things go wrong, it can be a major effort just to identify the culprit, never mind provide a fix or work around.

Just chalk it up as a sign of the times; the demands of having 24/7 coverage, supporting all kinds of clients, high reliability, remote monitoring and administration ... all of these things add up to more and more code around your application and, barring some blazing insight within the industry, it's not going to change any time soon. But it does make me cringe a bit a deployment time, makes me nervous -- will it work in production? And I've been there, reworking code under deadline to get transactions and remote JMS queues working together inside a WebLogic cluster.

There's a quote I half remember from one of the Apollo astronauts, sitting on the pad, during the countdown ... trying not to remember that their lives depended on hundreds of thousands of different parts, all provided by the lowest bidder. Deploying a major application sometimes feels like that ... even when some of the parts are quite expensive, and others are routinely free.

Sunday, May 08, 2005

OSCON 2005

I was just perusing the schedule for OSCON 2005, which is the first week in August this year, in Portland, Oregon.

They don't have a master side-by-side session schedule, which makes it tedious to pick a path through the many tracks. Here's what I've found, so far, for me:

Ruby: Ruby on Rails: Enjoying the Ride of Programming David Heinemeier Hansson Mon 8/1/ 1:30-5
Emerging Topics: Learning Ajax David Heinemeier Hansson Thu 8/2 8:30-12
Linux: Application Development With Firefox and Mozilla Shane Caraveo Wed 8/3 10:45-11:30
Java: SiteMesh: A Simple Approach to Web Site Layout Joe Walnes Wed 8/3 4:30-5:15
Java: Tapestry In Action Howard M. Lewis Ship Wed 8/3 5:20-6:05
Java: RAD That Ain't Bad -- Domain Driven Development with Trails Chris Nelson Thu 8/4 11:35-12:20
Ruby: Metaprogramming Ruby Glenn Vanderburg Thu 8/4 2:35-3:20
Ruby: Dependency Injection: Vitally Important or Completely Irrelevant? Jim Weirich Thu 8/4 4:30-5:15

Friday, May 06, 2005

I would'nt install Google WebAccelerator if I were you ...

I was a little "bleeding edge" today and installed Google Web Accelerator. Woops. It kind of screws things up for a lot of sites I hit and is a little tricky to uninstall (we'll see if I'm rid of it after a reboot). Others have seen security issues.

Update: After uninstalling it, rebooting, re-installing FireFox ... it is still running on my computer. Whenever I view source, I see:

<script language='javascript' src='http://127.0.0.1:1029/js.cgi?pca&r=5436'>>/script>

On my pages; worse, that URL is live, and returns:

bash-2.05b$ curl http://127.0.0.1:1029/js.cgi?pca\&r=5436

var blockedReferrer = 'blockedReferrer';
NS_ActualWrite=document.write;
// Popup Blocker -->
RanPostamble=0;
NS_ActualOpen=window.open;
function NS_NullWindow(){this.window;}
function nullDoc() {
   this.open = NS_NullWindow;
   this.write = NS_NullWindow;
   this.close = NS_NullWindow;
}
function NS_NewOpen(url,nam,atr){
        if((nam!='' && nam==window.name) || nam=='_top'){
           return(NS_ActualOpen(url,nam,atr));}
        obj=new NS_NullWindow();
        obj.focus = NS_NullWindow;
        obj.blur = NS_NullWindow;
        obj.opener = this.window;
        obj.document = new nullDoc();
        return(obj);
}
function NS_NullWindow2(){this.window;}
function NS_NewOpen2(url,nam,atr){
        if((nam!='' && nam==window.name) || nam=='_top'){
           return(NS_ActualOpen(url,nam,atr));}
    return(new NS_NullWindow2());
}
function op_stop() { NS_ActualOpen2=window.open; window.open=NS_NewOpen2; }
function op_start() { window.open=NS_ActualOpen2; }
function noopen_load() {
    op_stop(); if(zl_orig_onload) zl_orig_onload(); op_start();
}
function noopen_unload() { op_stop(); if(zl_orig_onunload) zl_orig_onunload(); op_start(); }
function postamble() {

  if(!RanPostamble) {
    RanPostamble=1;
        zl_orig_onload = window.onload;
        zl_orig_onunload = window.onunload;
        window.open=NS_ActualOpen;
  }
}
window.open=NS_NewOpen;
document.ignore = new Object()
bash-2.05b$

So don't install it; can't get rid of it, and I'm pissed!

Update #2: I'd some more checking; this thing claims to be a popup blocker, but I think it might be part of some Spyware. Or it might be some kind of kludgey thing supplied by Firefox to block popups?

Update #3: It is a popup ad blocker, it's part of ZoneAlarm Pro, which I've been testing out. Seems like it will hijack almost any HTTP traffic ... and interesting problem that could break some Ajax code potentially!

Just fired up Eclipse 3.1M6

I just fired up eclipse 3.1M6 for the first time, on my existing workspace. This will be interesting to see what works and what doesn't. I'm hoping to start experimenting with JDK 1.5 features at some point soon, even though I don't plan on using them in the Tapestry or HiveMind cores for some time to come.

JavaOne: Tapestry In Action

My session, Tapestry In Action, at this year's JavaOne has been scheduled. Mark your calendars!

It's a 60 minute session, from 1:30 PM to 2:30 PM on Wednesday June 29th. It'll be in Esplan 307-310, which seats 1200 (!).

Sixty minutes is not much time to cover any aspect of Tapestry; this will be an accelrated version of the my Tapestry NoFluffJustStuff session, with no live coding, and more code on the slides. It uses similar examples to NFJS, it's been recoding against Tapestry 4.0.