Is the way I'm building my custom select model the "approved" Tap 5 way? My concern is if OptionModelImpl and SelectModelImpl are still considered internal Tapestry classes and should be avoided? This stuff works fine for me and it's fairly elegant (IMHO), I just want to know if there is a better way.
<div class="w-row"> <div class="w-tlabel"><t:label for="article" />:</div> <t:select t:id="article" style="width:60%;" t:value="articleId" t:model="articlesModel" /></div> @Cached public SelectModel getArticlesModel() { final List<SelfHelpArticleBean> articles = getArticles(); return new SelectModel() { private final SelectModel model; { OptionModel[] options = new OptionModel[articles.size()+1]; options[0] = new OptionModelImpl("-- Please Select", 0); int index = 1; for(SelfHelpArticleBean article : articles) { String label = article.getId() + ": " + article.getAnchorBody(); int value = article.getId(); options[index++] = new OptionModelImpl(label, value); } model = new SelectModelImpl(options); } public List<OptionGroupModel> getOptionGroups() { return model.getOptionGroups(); } public List<OptionModel> getOptions() { return model.getOptions(); } public void visit(SelectModelVisitor aVisitor) { model.visit(aVisitor); } }; } On Tue, May 8, 2007 at 12:50 AM, Bill Holloway <[EMAIL PROTECTED]> wrote: > I'm just hoping for a stable, best-practice, and relatively simple way > to set things up like Selects. Whatever you think is the best > approach and put in the documentation. > > Things like selects should be a snap, IMHO. > > Bill > > > > On 5/7/07, Howard Lewis Ship <[EMAIL PROTECTED]> wrote: > > My approach has to been to keep everything internal if possible. Thus an > > interface is public, the implementation is internal. > > > > If something is truly necessary, such as OptionModelImpl, there are two > > approaches: > > > > 1) Make the implementation class public (possibly breaking existing code > > that extends from the internal class) .... oh, and probably make it final > as > > well. > > > > 2) Define a public factory service for the implementation. > > > > Right now, you can actually use the TypeCoercer as a kind of factory; if > you > > pass in a comma-separated string and ask for an SelectModel you'll get it. > > Here, though, you're looking for something a little better adapted to your > > entity classes. However, a bare-bones implementation of OptionModel (that > > always returns false for isDisabled(), and null for getAttributes() ) is > > only a couple of lines of code. > > > > I think T4 fell into a trap of too much convenience stuff exposed as public > > APIs. I would rather err on the side of over-zealousness for T5. You can > > take internals public, but not the other way around, and once something is > > public, it also is (or should be) final. > > > > On 5/7/07, Bill Holloway <[EMAIL PROTECTED]> wrote: > > > > > > I've written similar code -- while remembering that OptionModelImpl is > > > an "internal" class that Howard, in the documentation, has admonished > > > us not to use. > > > > > > Community, what's the better solution? > > > > > > Bill > > > > > > On 5/7/07, Joel Wiegman <[EMAIL PROTECTED]> wrote: > > > > Eureka! > > > > > > > > Finally got it all working. What caused the drop down to not be > > > > defaulting is the fact that I declared my "Brand" list in two separate > > > > lists... One for the ValueEncoder and one for the SelectModel. Big no > > > > no! An "equals" is called on the value from the SelectModel and the > > > > value from the ValueEncoder, so if they are initialized as separate > > > > objects in separate lists the framework won't notice that they are > equal > > > > (because they would point to a different memory location). I found > that > > > > the framework also seems to like things better if the List of Brands is > > > > "@Persist"ed between pages. Here's the final source code that I used > to > > > > get it all working (Enjoy!): > > > > > > > > Brand.java (simple POJO): > > > > > > > > public class Brand { > > > > > > > > private String id; > > > > private String description; > > > > > > > > public Brand() {} > > > > > > > > public Brand(String id, String description) { > > > > this.id = id; > > > > this.description = description; > > > > } > > > > > > > > public String getId() { > > > > return id; > > > > } > > > > > > > > public String getDescription() { > > > > return description; > > > > } > > > > > > > > } > > > > > > > > > > > > Test.java > > > > > > > > public class Test { > > > > > > > > @Persist > > > > private Brand brand; > > > > > > > > @Persist > > > > private List<Brand> brands; > > > > > > > > public Brand getBrand() { > > > > return brand; > > > > } > > > > > > > > public void setBrand(Brand brand) { > > > > this.brand = brand; > > > > } > > > > > > > > private List<Brand> getBrands() > > > > { > > > > if(brands == null) { > > > > brands = new ArrayList<Brand>(); > > > > brands.add(new Brand("1", "Brand 1")); > > > > brands.add(new Brand("2", "Brand 2")); > > > > brands.add(new Brand("3", "Brand 3")); > > > > brands.add(new Brand("4", "Brand 4")); > > > > } > > > > > > > > return brands; > > > > } > > > > > > > > public BrandSelectModel getBrandSelectModel() { > > > > return new BrandSelectModel(getBrands()); > > > > } > > > > > > > > public BrandValueEncoder getBrandValueEncoder() { > > > > return new BrandValueEncoder(getBrands()); > > > > } > > > > > > > > public class BrandValueEncoder implements ValueEncoder<Brand> { > > > > > > > > private List<Brand> brands; > > > > > > > > public BrandValueEncoder(List<Brand> brands) { > > > > this.brands = brands; > > > > } > > > > > > > > public String toClient(Brand brand) { > > > > return brand.getDescription(); > > > > } > > > > > > > > public Brand toValue(String string) { > > > > for(Brand brand : brands) { > > > > > > > > if(brand.getDescription().equals(string)) { > > > > return brand; > > > > } > > > > } > > > > return null; > > > > } > > > > > > > > } > > > > > > > > public class BrandSelectModel implements SelectModel { > > > > > > > > private List<Brand> brands; > > > > > > > > public BrandSelectModel(List<Brand> brands) { > > > > this.brands = brands; > > > > } > > > > > > > > public List<OptionGroupModel> getOptionGroups() { > > > > return null; > > > > } > > > > > > > > public List<OptionModel> getOptions() { > > > > List<OptionModel> optionModelList = new > > > > ArrayList<OptionModel>(); > > > > for(Brand brand: brands) { > > > > optionModelList.add( > > > > new OptionModelImpl( > > > > brand.getDescription(), > > > > false, > > > > brand, > > > > new String[0] > > > > ) > > > > ); > > > > } > > > > return optionModelList; > > > > } > > > > > > > > } > > > > > > > > } > > > > > > > > > > > > Test.html > > > > > > > > <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> > > > > <t:form> > > > > > > > > <select t:type="select" t:id="brand" > > > > value="brand" model="brandSelectModel" > > > > encoder="brandValueEncoder" > > > > onchange="this.form.submit();" /> > > > > > > > > <br/> > > > > > > > > <t:if test="brand"> > > > > ${brand.description} > > > > </t:if> > > > > > > > > </t:form> > > > > </html> > > > > > > > > > > > > -----Original Message----- > > > > From: Howard Lewis Ship [mailto:[EMAIL PROTECTED] > > > > Sent: Monday, May 07, 2007 12:17 PM > > > > To: Tapestry users > > > > Subject: Re: T5: SelectModel - a real world example > > > > > > > > Odd that you lost your value; the field is itself persistent > (@Persist). > > > > Unless you are testing on a multi-machine cluster, you shouldn't see > any > > > > problems along these lines! > > > > > > > > On 5/7/07, Joel Wiegman <[EMAIL PROTECTED]> wrote: > > > > > > > > > > Impressive! I was injecting that value via Spring to bootstrap it. > > > > > Makes sense I should have removed that... > > > > > > > > > > No errors now... However, the field doesn't appear to be binding on > a > > > > > > > > > form submission. The encoder and the model appear to be receiving > and > > > > > > > > > returning the correct values, the brand getter and setter appear to > be > > > > > > > > > getting called, and the dropdown renders correctly except that it > > > > > always appears to be reset to the default value... > > > > > > > > > > I apologize for being so high-maintenance. If there is a working > > > > > example of a T5 binding select box anywhere on the web, please point > > > > > me there and I will leave you alone! > > > > > > > > > > Main.html > > > > > > > > > > <t:form> > > > > > <select t:type="select" class="mint_font_black_background" > > > > > t:id="brand" > > > > > value="brand" model="brandSelectModel" > encoder="brandValueEncoder" > > > > > onchange="this.form.submit();" /> > > > > > </t:form> > > > > > > > > > > > > > > > Main.java > > > > > > > > > > public class Main { > > > > > > > > > > @Inject > > > > > @SpringBean("enterprise") > > > > > private Enterprise enterprise; > > > > > > > > > > @Persist > > > > > private Brand brand; > > > > > > > > > > public Brand getBrand() { > > > > > return brand; > > > > > } > > > > > > > > > > public void setBrand(Brand brand) { > > > > > this.brand = brand; > > > > > } > > > > > > > > > > public BrandSelectModel getBrandSelectModel() { > > > > > return new BrandSelectModel(enterprise.getBrands()); > > > > > } > > > > > > > > > > public BrandValueEncoder getBrandValueEncoder() { > > > > > return new BrandValueEncoder(enterprise.getBrands()); > > > > > } > > > > > > > > > > public class BrandValueEncoder implements ValueEncoder<Brand> > > > > > { > > > > > > > > > > private List<Brand> brands; > > > > > > > > > > public BrandValueEncoder(List<Brand> brands) { > > > > > this.brands = brands; > > > > > } > > > > > > > > > > public String toClient(Brand brand) { > > > > > return brand.getDescription(); > > > > > } > > > > > > > > > > public Brand toValue(String string) { > > > > > for(Brand brand : brands) { > > > > > > > > > > if(brand.getDescription().equals(string)) { > > > > > return brand; > > > > > } > > > > > } > > > > > return null; > > > > > } > > > > > > > > > > } > > > > > > > > > > public class BrandSelectModel implements SelectModel { > > > > > > > > > > private List<Brand> brands; > > > > > > > > > > public BrandSelectModel(List<Brand> brands) { > > > > > this.brands = brands; > > > > > } > > > > > > > > > > public List<OptionGroupModel> getOptionGroups() { > > > > > return null; > > > > > } > > > > > > > > > > public List<OptionModel> getOptions() { > > > > > List<OptionModel> optionModelList = > > > > > new ArrayList<OptionModel>(); > > > > > for(Brand brand: brands) { > > > > > optionModelList.add( > > > > > new OptionModelImpl( > > > > > brand.getDescription(), > > > > > false, > > > > > brand, > > > > > new String[0] > > > > > ) > > > > > ); > > > > > } > > > > > return optionModelList; > > > > > } > > > > > > > > > > } > > > > > > > > > > } > > > > > > > > > > > > > > > > > > > > -----Original Message----- > > > > > From: Howard Lewis Ship [mailto:[EMAIL PROTECTED] > > > > > Sent: Saturday, May 05, 2007 9:45 PM > > > > > To: Tapestry users > > > > > Subject: Re: T5: SelectModel - a real world example > > > > > > > > > > What annotations are on the brand field of your Main class? > Something > > > > > > > > > has changes that field to be read-only, which is usually a sign that > a > > > > > > > > > value was injected. > > > > > > > > > > On 5/4/07, Joel Wiegman <[EMAIL PROTECTED]> wrote: > > > > > > > > > > > > Still getting unintuitive errors... I've added the ValueEncoder and > > > > > > now when I submit the form I get the following stack trace (and yes > > > > > > the "Main" component has a setBrand(Brand) method, which from the > > > > > > root > > > > > > > > > > > cause exception seems to be the cause of the problem?): > > > > > > > > > > > > [ERROR] RequestExceptionHandler Processing of request failed with > > > > > > uncaught exception: > > > > > > org.apache.tapestry.ioc.internal.util.TapestryException: Failure > > > > > > writing parameter value of component com.foo.pages.Main:brand: > Field > > > > > > > > > > com.foo.pages.Main.brand is read-only. [at > > > > > > context:WEB-INF/Main.html, line 89, column 278] > > > > > > java.lang.RuntimeException: > > > > > > org.apache.tapestry.ioc.internal.util.TapestryException: Failure > > > > > > writing parameter value of component com.foo. > > > > > > pages.Main:brand: Field com.foo.pages.Main.brand is read-only. [at > > > > > > context:WEB-INF/Main.html, line 89, column 278] > > > > > > at > > > > > > org.apache.tapestry.corelib.components.Form.onAction(Form.java:356) > > > > > > at > > > > > > > > > > org.apache.tapestry.corelib.components.Form.handleComponentEvent(Form. > > > > > > ja > > > > > > va) > > > > > > at > > > > > > > org.apache.tapestry.internal.structure.ComponentPageElementImpl.hand > > > > > > le > > > > > > Ev > > > > > > ent(ComponentPageElementImpl.java:903) > > > > > > at > > > > > > > org.apache.tapestry.internal.structure.ComponentPageElementImpl.trig > > > > > > ge > > > > > > rE > > > > > > vent(ComponentPageElementImpl.java:1002) > > > > > > at > > > > > > > org.apache.tapestry.internal.services.ActionLinkHandlerImpl.handle(A > > > > > > ct > > > > > > io > > > > > > nLinkHandlerImpl.java:100) > > > > > > at > > > > > > > org.apache.tapestry.internal.services.ActionLinkHandlerImpl.handle(A > > > > > > ct > > > > > > io > > > > > > nLinkHandlerImpl.java:53) > > > > > > at > > > > > > > $ActionLinkHandler_11258c2d07d.handle($ActionLinkHandler_11258c2d07d > > > > > > .j > > > > > > av > > > > > > a) > > > > > > at > > > > > > > org.apache.tapestry.internal.services.ComponentActionDispatcher.disp > > > > > > at > > > > > > ch > > > > > > (ComponentActionDispatcher.java:115) > > > > > > ... 40 more > > > > > > Caused by: org.apache.tapestry.ioc.internal.util.TapestryException: > > > > > > Failure writing parameter value of component > > > > com.foo.pages.Main:brand: > > > > > > Field com.foo.pages.Main.brand is read-only. [at > > > > > > context:WEB-INF/Main.html, line 89, column 278] > > > > > > at > > > > > > > > > > org.apache.tapestry.internal.structure.InternalComponentResourcesImpl. > > > > > > wr > > > > > > iteParameter(InternalComponentResourcesImpl.java:223) > > > > > > at > > > > > > > org.apache.tapestry.corelib.components.Select._$update_parameter_val > > > > > > ue > > > > > > _0 > > > > > > (Select.java) > > > > > > at > > > > > > > org.apache.tapestry.corelib.components.Select.processSubmission(Sele > > > > > > ct > > > > > > .j > > > > > > ava:238) > > > > > > at > > > > > > > org.apache.tapestry.corelib.base.AbstractField.processSubmission(Abs > > > > > > tr > > > > > > ac > > > > > > tField.java:210) > > > > > > at > > > > > > > > > > > > > > > > org.apache.tapestry.corelib.base.AbstractField.access$100(AbstractField. > > > > > > java:47) > > > > > > at > > > > > > > org.apache.tapestry.corelib.base.AbstractField$ProcessSubmissionActi > > > > > > on > > > > > > .e > > > > > > xecute(AbstractField.java:116) > > > > > > at > > > > > > > org.apache.tapestry.corelib.base.AbstractField$ProcessSubmissionActi > > > > > > on > > > > > > .e > > > > > > xecute(AbstractField.java:110) > > > > > > at > > > > > > org.apache.tapestry.corelib.components.Form.onAction(Form.java:347) > > > > > > ... 40 more > > > > > > Caused by: org.apache.tapestry.ioc.internal.util.TapestryException: > > > > > > Field com.foo.pages.Main.brand is read-only. [at > > > > context:WEB-INF/Main. > > > > > > html, line 89, column 278] > > > > > > at > > > > > > > org.apache.tapestry.internal.bindings.PropBinding.set(PropBinding.ja > > > > > > va > > > > > > :7 > > > > > > 1) > > > > > > at > > > > > > > > > > org.apache.tapestry.internal.structure.InternalComponentResourcesImpl. > > > > > > wr > > > > > > iteParameter(InternalComponentResourcesImpl.java:219) > > > > > > ... 47 more > > > > > > Caused by: java.lang.RuntimeException: Field > > > > > > com.foo.pages.Main.brand is read-only. > > > > > > at com.foo.pages.Main._$write_brand(Main.java) > > > > > > at com.foo.pages.Main.setBrand(Main.java:92) > > > > > > at > > > > > > $PropertyConduit_11258c2d0a9.set($PropertyConduit_11258c2d0a9.java) > > > > > > at > > > > > > > org.apache.tapestry.internal.bindings.PropBinding.set(PropBinding.ja > > > > > > va > > > > > > :6 > > > > > > 7) > > > > > > ... 48 more > > > > > > > > > > > > > > > > > > > > > > > > -----Original Message----- > > > > > > From: Howard Lewis Ship [mailto:[EMAIL PROTECTED] > > > > > > Sent: Friday, May 04, 2007 2:32 PM > > > > > > To: Tapestry users > > > > > > Subject: Re: T5: SelectModel - a real world example > > > > > > > > > > > > In your OptionModel, the label is the Brand description, and the > > > > > > value > > > > > > > > > > > is the Brand itself. > > > > > > > > > > > > You then supply a ValueEncoder that converts between Brands and > > > > > > brand ids (as strings, for the client side). If Brand is an entity > > > > > > object, then it may be necessary to have the ValueEncoder talk to > > > > > > the database > > > > > > > > > > > or session store. > > > > > > > > > > > > On 5/4/07, Joel Wiegman <[EMAIL PROTECTED]> wrote: > > > > > > > > > > > > > > Thanks for the reply Howard. > > > > > > > > > > > > > > >> The Select component doesn't know how to create a client-side > > > > > > > representation of a Brand (it doesn't magically know to use the > > > > id). > > > > > > > > > > > > > > So, then... I guess my question would be... what is the > > > > > > > BrandSelectModel for? In that object, I'm essentially mapping a > > > > > > > Brand's "description" to the Brand object. > > > > > > > > > > > > > > Just curious what your thoughts are on that... > > > > > > > > > > > > > > > > > > > > > -----Original Message----- > > > > > > > From: Howard Lewis Ship [mailto:[EMAIL PROTECTED] > > > > > > > Sent: Friday, May 04, 2007 1:42 PM > > > > > > > To: Tapestry users > > > > > > > Subject: Re: T5: SelectModel - a real world example > > > > > > > > > > > > > > In the simplest case, T5 thinks that the options in the drop down > > > > > > > list > > > > > > > > > > > > > are all strings. > > > > > > > > > > > > > > In your case, they are Brands. The Select component doesn't know > > > > > > > how to create a client-side representation of a Brand (it doesn't > > > > > > > magically know to use the id). > > > > > > > > > > > > > > You must provide a ValueEncoder that can convert between Brands > > > > > > > and client-side string values. This is the encoder parameter of > > > > > > > the Select component. > > > > > > > > > > > > > > > > > > > > > On 5/4/07, Joel Wiegman <[EMAIL PROTECTED]> wrote: > > > > > > > > > > > > > > > > Not to be harsh, but I don't think I've ever written a select > > > > > > > > box with > > > > > > > > > > > > > > > constant values (Enum). Seems like even Male/Female drop downs > > > > > > > > need > > > > > > > > > > > > > > to be data-driven now-a-days. :-> > > > > > > > > > > > > > > > > I've started to stub out a very simple "real world example" of > a > > > > > > > > > > > > select component in T5, but it doesn't appear to be as simple > as > > > > > > > > > > > > I > > > > > > > > > > > > > thought it would be. > > > > > > > > > > > > > > > > A shiny nickel to anyone that can spot the flaw, because I sure > > > > > > > can't... > > > > > > > > I'm new to Tapestry in general so I could be missing something > > > > > > > > really mundane here, but seems like it should work in my mind. > > > > > > > > > > > > > > > > Here are the players: > > > > > > > > > > > > > > > > << THE ERROR >> > > > > > > > > > > > > > > > > [ERROR] DefaultRequestExceptionHandler Processing of request > > > > > > > > failed with uncaught exception: com.foo.data.Brand cannot be > > > > > > > > cast to java.lang.String > > > > > > > > java.lang.ClassCastException: com.foo.data.Brand cannot be cast > > > > > > > > to > > > > > > > > > > > > > java.lang.String > > > > > > > > at > > > > > > > > > > > > > > > > org.apache.tapestry.corelib.components.Select$1.toClient(Select.ja > > > > > > > va > > > > > > > :6 > > > > > > > 2) > > > > > > > > at > > > > > > > > > > > > org.apache.tapestry.corelib.components.Select.writeOptions(Select. > > > > > > > > ja > > > > > > > > va > > > > > > > > :1 > > > > > > > > 94) > > > > > > > > at > > > > > > > > > > > > > > > org.apache.tapestry.corelib.components.Select.options(Select.java:16 > > > > > > 9) > > > > > > > > at > > > > > > > > > org.apache.tapestry.corelib.components.Select.beforeRenderTempla > > > > > > > > te > > > > > > > > (S > > > > > > > > el > > > > > > > > ec > > > > > > > > t.java) > > > > > > > > > > > > > > > > > > > > > > > > << Main.html (abridged) >> > > > > > > > > > > > > > > > > <t:form> > > > > > > > > <select t:type="select" t:id="brand" value="brand" > > > > > > > > model="brandSelectModel"/> > > > > > > > > </t:form> > > > > > > > > > > > > > > > > > > > > > > > > << Main.java (abridged) >> > > > > > > > > > > > > > > > > package com.foo.pages; > > > > > > > > > > > > > > > > import com.foo.data.Brand; > > > > > > > > > > > > > > > > public class Main { > > > > > > > > > > > > > > > > private Brand brand; > > > > > > > > > > > > > > > > public Brand getBrand() { > > > > > > > > return brand; > > > > > > > > } > > > > > > > > > > > > > > > > public void setBrand(Brand brand) { > > > > > > > > this.brand = brand; > > > > > > > > } > > > > > > > > > > > > > > > > public BrandSelectModel getBrandSelectModel() { > > > > > > > > return new BrandSelectModel(getBrands()); > > > > > > > > } > > > > > > > > > > > > > > > > public List<Brand> getBrands() { > > > > > > > > List<Brand> brands = new ArrayList<Brand>(); > > > > > > > > brands.add(new Brand("1", "Brand 1")); > > > > > > > > brands.add(new Brand("2", "Brand 2")); > > > > > > > > brands.add(new Brand("3", "Brand 3")); > > > > > > > > return brands; > > > > > > > > } > > > > > > > > > > > > > > > > } > > > > > > > > > > > > > > > > > > > > > > > > << Brand.java (abridged) >> > > > > > > > > > > > > > > > > package com.foo.data; > > > > > > > > > > > > > > > > public class Brand { > > > > > > > > > > > > > > > > private String id; > > > > > > > > private String description; > > > > > > > > > > > > > > > > public Brand() {} > > > > > > > > > > > > > > > > public Brand(String id, String description) { > > > > > > > > this.id = id; > > > > > > > > this.description = description; > > > > > > > > } > > > > > > > > > > > > > > > > public String getId() { > > > > > > > > return id; > > > > > > > > } > > > > > > > > > > > > > > > > public String getDescription() { > > > > > > > > return description; > > > > > > > > } > > > > > > > > > > > > > > > > } > > > > > > > > > > > > > > > > > > > > > > > > << BrandSelectModel.java >> > > > > > > > > > > > > > > > > package com.foo.uisupport; > > > > > > > > > > > > > > > > import com.foo.data.Brand; > > > > > > > > > > > > > > > > public class BrandSelectModel implements SelectModel { > > > > > > > > > > > > > > > > private List<Brand> brands; > > > > > > > > > > > > > > > > public BrandSelectModel(List<Brand> brands) { > > > > > > > > this.brands = brands; > > > > > > > > } > > > > > > > > > > > > > > > > public List<OptionGroupModel> getOptionGroups() { > > > > > > > > return null; > > > > > > > > } > > > > > > > > > > > > > > > > public List<OptionModel> getOptions() { > > > > > > > > List<OptionModel> optionModelList = new > > > > > > > > ArrayList<OptionModel>(); > > > > > > > > for(Brand brand: brands) { > > > > > > > > optionModelList.add(new > > > > > > > > OptionModelImpl(brand.getDescription(), false, brand, new > > > > > > String[0])); > > > > > > > > } > > > > > > > > return optionModelList; > > > > > > > > } > > > > > > > > > > > > > > > > } > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ---------------------------------------------------------------- > > > > > > > > -- > > > > > > > > -- > > > > > > > > - To unsubscribe, e-mail: [EMAIL PROTECTED] > > > > > > > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > > Howard M. Lewis Ship > > > > > > > TWD Consulting, Inc. > > > > > > > Independent J2EE / Open-Source Java Consultant Creator and PMC > > > > > > > Chair, Apache Tapestry Creator, Apache HiveMind > > > > > > > > > > > > > > Professional Tapestry training, mentoring, support and project > > > > work. > > > > > > > http://howardlewisship.com > > > > > > > > > > > > > > > ------------------------------------------------------------------ > > > > > > > -- > > > > > > > - To unsubscribe, e-mail: [EMAIL PROTECTED] > > > > > > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > > Howard M. Lewis Ship > > > > > > TWD Consulting, Inc. > > > > > > Independent J2EE / Open-Source Java Consultant Creator and PMC > > > > > > Chair, Apache Tapestry Creator, Apache HiveMind > > > > > > > > > > > > Professional Tapestry training, mentoring, support and project > work. > > > > > > http://howardlewisship.com > > > > > > > > > > > > > -------------------------------------------------------------------- > > > > > > - To unsubscribe, e-mail: [EMAIL PROTECTED] > > > > > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > > > > > > > > > > > > > > > > > > > > > > > -- > > > > > Howard M. Lewis Ship > > > > > TWD Consulting, Inc. > > > > > Independent J2EE / Open-Source Java Consultant Creator and PMC Chair, > > > > > Apache Tapestry Creator, Apache HiveMind > > > > > > > > > > Professional Tapestry training, mentoring, support and project work. > > > > > http://howardlewisship.com > > > > > > > > > > --------------------------------------------------------------------- > > > > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > > > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > > > > > > > > > > > > > > > > > > -- > > > > Howard M. Lewis Ship > > > > TWD Consulting, Inc. > > > > Independent J2EE / Open-Source Java Consultant Creator and PMC Chair, > > > > Apache Tapestry Creator, Apache HiveMind > > > > > > > > Professional Tapestry training, mentoring, support and project work. > > > > http://howardlewisship.com > > > > > > > > --------------------------------------------------------------------- > > > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > > > > > > > > > > > > > -- > > > "The future is here. It's just not evenly distributed yet." > > > > > > -- Traditional > > > > > > --------------------------------------------------------------------- > > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > > > > > > > > > -- > > Howard M. Lewis Ship > > TWD Consulting, Inc. > > Independent J2EE / Open-Source Java Consultant > > Creator and PMC Chair, Apache Tapestry > > Creator, Apache HiveMind > > > > Professional Tapestry training, mentoring, support > > and project work. http://howardlewisship.com > > > > > -- > > > "The future is here. It's just not evenly distributed yet." > > -- Traditional > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]