To help me output XHTML ... here are 3 classes. Most of the code below came from the wiki.
I updated a few generic class references. You'll want to put these in the (root)**.services package. -Luther import java.io.IOException; import org.apache.tapestry5.*; import org.apache.tapestry5.ioc.Configuration; import org.apache.tapestry5.ioc.MappedConfiguration; import org.apache.tapestry5.ioc.OrderedConfiguration; import org.apache.tapestry5.ioc.ServiceBinder; import org.apache.tapestry5.ioc.annotations.InjectService; import org.apache.tapestry5.services.AliasContribution; import org.apache.tapestry5.services.MarkupWriterFactory; import org.apache.tapestry5.services.Request; import org.apache.tapestry5.services.RequestFilter; import org.apache.tapestry5.services.RequestHandler; import org.apache.tapestry5.services.Response; import org.slf4j.Logger; /** * This module is automatically included as part of the Tapestry IoC Registry, it's a good place to * configure and extend Tapestry, or to place your own service definitions. */ public class TapestryModule { public static void bind(ServiceBinder binder) { // binder.bind(MyServiceInterface.class, MyServiceImpl.class); // Make bind() calls on the binder object to define most IoC services. // Use service builder methods (example below) when the implementation // is provided inline, or requires more initialization than simply // invoking the constructor. } public static void contributeAlias(Configuration<AliasContribution<MarkupWriterFactory>> configuration) { configuration.add(AliasContribution.create(MarkupWriterFactory.class, new XhtmlMarkupWriterFactory())); } public static void contributeApplicationDefaults( MappedConfiguration<String, String> configuration) { // Contributions to ApplicationDefaults will override any contributions to // FactoryDefaults (with the same key). Here we're restricting the supported // locales to just "en" (English). As you add localised message catalogs and other assets, // you can extend this list of locales (it's a comma seperated series of locale names; // the first locale name is the default when there's no reasonable match). configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en"); // The factory default is true but during the early stages of an application // overriding to false is a good idea. In addition, this is often overridden // on the command line as -Dtapestry.production-mode=false configuration.add(SymbolConstants.PRODUCTION_MODE, "false"); } /** * This is a service definition, the service will be named "TimingFilter". The interface, * RequestFilter, is used within the RequestHandler service pipeline, which is built from the * RequestHandler service configuration. Tapestry IoC is responsible for passing in an * appropriate Log instance. Requests for static resources are handled at a higher level, so * this filter will only be invoked for Tapestry related requests. * * <p> * Service builder methods are useful when the implementation is inline as an inner class * (as here) or require some other kind of special initialization. In most cases, * use the static bind() method instead. * * <p> * If this method was named "build", then the service id would be taken from the * service interface and would be "RequestFilter". Since Tapestry already defines * a service named "RequestFilter" we use an explicit service id that we can reference * inside the contribution method. */ public RequestFilter buildTimingFilter(final Logger log) { return new RequestFilter() { public boolean service(Request request, Response response, RequestHandler handler) throws IOException { long startTime = System.currentTimeMillis(); try { // The responsibility of a filter is to invoke the corresponding method // in the handler. When you chain multiple filters together, each filter // received a handler that is a bridge to the next filter. return handler.service(request, response); } finally { long elapsed = System.currentTimeMillis() - startTime; log.info(String.format("Request time: %d ms", elapsed)); } } }; } /** * This is a contribution to the RequestHandler service configuration. This is how we extend * Tapestry using the timing filter. A common use for this kind of filter is transaction * management or security. */ public void contributeRequestHandler(OrderedConfiguration<RequestFilter> configuration, @InjectService("TimingFilter") RequestFilter filter) { // Each contribution to an ordered configuration has a name, When necessary, you may // set constraints to precisely control the invocation order of the contributed filter // within the pipeline. configuration.add("Timing", filter); } } import org.apache.tapestry5.ContentType; import org.apache.tapestry5.MarkupWriter; import org.apache.tapestry5.dom.MarkupModel; import org.apache.tapestry5.internal.services.MarkupWriterImpl; import org.apache.tapestry5.services.MarkupWriterFactory; /** * @author luther.baker */ public class XhtmlMarkupWriterFactory implements MarkupWriterFactory { // private private final MarkupModel xmlModel = new ImprovedXhtmlMarkupModel(); /** * @see org.apache.tapestry5.services.MarkupWriterFactory#newMarkupWriter(org.apache.tapestry5.ContentType) */ @Override public MarkupWriter newMarkupWriter(ContentType contentType) { return new MarkupWriterImpl(xmlModel, contentType.getParameter("charset")); } /** * @see org.apache.tapestry5.services.MarkupWriterFactory#newMarkupWriter(java.lang.String) */ @Override public MarkupWriter newMarkupWriter(String pageName) { // TODO Auto-generated method stub return null; } } import java.util.HashSet; import java.util.Set; import org.apache.tapestry5.dom.DefaultMarkupModel; import org.apache.tapestry5.dom.EndTagStyle; /** * @author luther.baker */ public class ImprovedXhtmlMarkupModel extends DefaultMarkupModel { private static final Set<String> DONT_ABRV = newSet("script", "div", "span", "p"); @Override public EndTagStyle getEndTagStyle(String element) { boolean isDontAbr = DONT_ABRV.contains(element); return isDontAbr ? EndTagStyle.REQUIRE : EndTagStyle.ABBREVIATE; } @Override public boolean isXML() { return true; } private static final Set<String> newSet(String a, String b, String c, String d) { Set<String> set = new HashSet<String>(); set.add(a); set.add(b); set.add(c); set.add(d); return set; } } 2008/9/9 Luther Baker <[EMAIL PROTECTED]> > I do remember the generics being a bit tricky but not too bad. > > I will post what I have a bit later tonite. > > -Luther > > > > > > On Tue, Sep 9, 2008 at 12:24 PM, ProAdmin Dariusz Dwornikowski < > [EMAIL PROTECTED]> wrote: > >> And it wokred for you ? >> >> public static void contributeAlias(Configuration<AliasContribution> >> configuration) { >> >> configuration.add(AliasContribution.create(MarkupWriterFactory.class, >> new XhtmlMarkupWriterFactoryImpl())); >> } >> >> >> I get error after insering that in AppModule. Eclipse says: >> >> >> The method create(Class<X>, X) in the type AliasContribution is not >> applicable for the arguments >> (Class<MarkupWriterFactory>,XhtmlMarkupWriterFactoryImpl) >> >> >> >> W dniu 9 września 2008 19:18 użytkownik Luther Baker >> <[EMAIL PROTECTED]> napisał: >> > >> > I followed the wiki instructions and the other posts here and yes, I am >> > generating correct XHTML now. >> > >> > I haven't attempted to remove the superfluous tapestry css file nor have >> I >> > convinced the library to put the Content-Type meta tag first - but I'm >> > satisfied with valid XHTML. >> > >> > The only other style *thing* I've been been disappointed with is that >> things >> > like the provided beaneditform template (from the tutorial) include >> > Javascript files within the html body tags. Although it generally works >> in >> > most browsers, I don't think script tags are legal body tag children .. >> ie: >> > not XHTML compliant. I loved to be proved wrong but as far as I know, it >> is >> > generally considered poor practice to include Javascript in the body >> tags of >> > the html. >> > >> > That said, I'm not sure whether this component just needs to be tweaked >> or >> > if this is inherent in component html frameworks since the Javascript is >> > relevant to the component being referenced. The >> > [EMAIL PROTECTED] makes me think that it is also >> > possible to do the same for >> > Javascript files - but I've not written or tried to fix the provided >> > beaneditform. I found this: >> > [EMAIL PROTECTED]("${tapestry.scriptaculous}/dragdrop.js") >> > but I have to assume it is being used in the beaneditform - and in that >> > case, it is NOT pushing these script includes into HEAD ... but I >> suppose >> > it'd be best to look at the source in this case. >> > >> > All in all - these are minor style points - it really is a fantastic >> > framework. >> > >> > -Luther >> > >> > >> > >> > On Tue, Sep 9, 2008 at 11:18 AM, ProAdmin Dariusz Dwornikowski < >> > [EMAIL PROTECTED]> wrote: >> > >> > > Did you manage to achieve it in 5.0.14 ? Im very curious, how to do >> the >> > > Wiki >> > > method in 5.0.14. >> > > >> > > 2008/9/1 Luther Baker <[EMAIL PROTECTED]> >> > > >> > > > Is there a way to adjust the html that is generated - especially in >> the >> > > > header? >> > > > >> > > > Specifically, the generated head section does not appear to be xhtml >> > > > compliant. >> > > > >> > > > Here is what I'm including in my own custom "wrapping" component: >> > > > >> > > > <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" >> > > > "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> >> > > > <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd >> " >> > > > lang="en"> >> > > > <head> >> > > > <meta http-equiv="Content-Type" content="text/html; >> > > charset=UTF-8"/> >> > > > <title>${pageTitle}</title> >> > > > <link rel="stylesheet" href="css/styles.css" >> type="text/css"/> >> > > > </head> >> > > > >> > > > >> > > > *A few points: >> > > > * >> > > > a) The xhtml strict DOCTYPE should be pretty straightforward >> > > > b) I want the Content-Type first in the <head> tag >> > > > c) The meta tag *MUST* have a closing slash - otherwise the document >> is >> > > not >> > > > well formed. >> > > > d) The same goes for the two <link tags. XHTML dictates that all >> tags >> > > must >> > > > be well formed. >> > > > >> > > > >> > > > *Unfortunately, my application ends up generating >> > > > * >> > > > <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" >> > > > "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> >> > > > <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> >> > > > <head> >> > > > <link href="assets/tapestry/5.0.14/default.css" rel="stylesheet" >> > > > type="text/css"> >> > > > <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"> >> > > > <title>Home</title> >> > > > <link href="css/styles.css" rel="stylesheet" type="text/css"> >> > > > </head> >> > > > >> > > > >> > > > For the most part - this is fine ... but in the details, I believe >> my >> > > > problem is two fold: >> > > > >> > > > 1) I would really like the "Content-Type" to be the first tag in >> head. >> > > > 2) The link and meta tags are not properly closed. Unfortunately, >> this >> > > > code-gen is just not valid xhtml. >> > > > >> > > > I do have one last (not so terrible) issue with the EXTRA <link tag >> > > > (tapestry specific css) that is showing up in the head as well. I'm >> sure >> > > it >> > > > is nice for exceptions (which the final user should never see) but >> it has >> > > a >> > > > few more problems: >> > > > >> > > > 1) It tells everyone what version of a particular library I am >> using. I'd >> > > > rather not do that. >> > > > 2) The tag appears before my Content-Type tag - which as I >> mentioned, I'd >> > > > prefer FIRST in the hierarchy. >> > > > 3) Finally, the tapestry stylesheet is not well formed. Again, >> proper >> > > xhtml >> > > > demands that tags be balanced/closed. >> > > > >> > > > I know Code Gen is hard -- but I generally pay extra attention to >> ensure >> > > I >> > > > produce valid, well formed xhtml documents and the codegen going on >> > > behind >> > > > the scenes here is making that a bit hard. >> > > > >> > > > Thoughts? >> > > > >> > > > I'm not sure how to close the tags - maybe I can set a flag or pass >> > > > something else in as an xml attribute of the root tag of my >> templates? >> > > > Regarding the extra tapestry css file inserted ... maybe the >> Tapestry >> > > > library has a DEBUG and a RELEASE mode? Maybe there a flag to turn >> off >> > > the >> > > > DEBUG mode and put this library into RELEASE mode? I really don't >> want >> > > that >> > > > tapestry specfiic css page requested everytime I serve up a page. I >> > > > understand the filter takes care of it ... but it still shows up in >> my >> > > > request logs, on user pages, in proxies, etc ... >> > > > >> > > > Is it even wise to consider opening up the tapestry JARs and see if >> the >> > > > components implementeing this section of code can simply be tweaked >> to >> > > have >> > > > proper xhtml balance. >> > > > >> > > > On a positive note, the library is working well and I enjoy the >> general >> > > > programming model. I think convention is great - but it needs to be >> valid >> > > > in >> > > > this case. Thanks again in advance for any thoughts. >> > > > >> > > > -Luther >> > > > >> > > >> > > >> > > >> > > -- >> > > Pozdrawiam, >> > > Dariusz Dwornikowski >> > > ------------------------------------ >> > > ProAdmin >> > > ul. Królowej Jadwigi 44/2 >> > > 61-872 Poznań >> > > tel: 061 623-20-92 >> > > kom: 0601 59-64-74 >> > > fax: 061 623-20-93 >> > > www.proadmin.com.pl >> > > [EMAIL PROTECTED] >> > > >> >> >> >> -- >> Pozdrawiam, >> Dariusz Dwornikowski >> ------------------------------------ >> ProAdmin >> ul. Królowej Jadwigi 44/2 >> 61-872 Poznań >> tel: 061 623-20-92 >> kom: 0601 59-64-74 >> fax: 061 623-20-93 >> www.proadmin.com.pl >> [EMAIL PROTECTED] >> > >