I love you Steve. This is a much more solid approach to what I have been doing (templates stored in a filesystem, then the path saved in the db, didn't know you could get a hivemind resource from a string.)
Sorry, I am about to thread jack this, but how do you handle page cache clearing? Is there a programatic way of telling tapestry to discard a page when you update the template? If it is in the docs please reply rtfm, with a link to the page :) On 12/11/06, Tapestry User List <[EMAIL PROTECTED]> wrote:
Thank you Steve. That is exactly what I were looking for. D. 2006/12/2, Steve Shucker <[EMAIL PROTECTED]>: > > I've got this working for pages and components, but it's probably a bit > different than what you want. I have a template table in my database > and I'm looking up content by a numeric PK rather than a name because I > have a requirement to let users version some templates. I'm also > leaving out my db access because it's somewhat domain-specific. This > assumes that all pages/components are specless and lets you specify a > backing class to associate with each template. You should be able hack > the page/jwc lookups using this as a model, though. > > Credit goes to the tapestry wiki for how to write a delegate and > DynamicBlock for the trick with URL handlers to turn a string into a > hivemind resource. > > -Steve > > @Entity > @Table(name = "tapestry_components") > @SequenceGenerator(name = "SEQ", sequenceName = "tapestry_components_SEQ") > public class TapestryComponent { > private Integer id; > private String name; > private String template; > private Date creationDate = new Date(); > private String backingClass; > > @Column(name="backingClass") > public String getBackingClass() { > return backingClass; > } > > public void setBackingClass(String backingClass) { > this.backingClass = backingClass; > } > > public TapestryComponent() {} > > public TapestryComponent(String name) { > setName(name); > } > > @Id > @Column(name = "id") > @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ") > public Integer getId() { > return id; > } > > @Column(name = "name") > public String getName() { > return name; > } > > public void setId(Integer id) { > this.id = id; > } > > public void setName(String name) { > this.name = name; > } > > @Lob > @Column(name="template") > public String getTemplate() { > return template; > } > > public void setTemplate(String template) { > this.template = template; > } > > @Column(name="creation_date") > public Date getCreationDate() { > return creationDate; > } > > public void setCreationDate(Date creationDate) { > this.creationDate = creationDate; > } > } > > public class DatabasePageResolver implements > ISpecificationResolverDelegate { > > public DatabasePageResolver() {} > > public IComponentSpecification > findComponentSpecification(IRequestCycle cycle, > INamespace namespace, String name) { > return findSpecification(cycle, namespace, name, false); > } > > public IComponentSpecification findPageSpecification(IRequestCycle > cycle, INamespace namespace, String name) { > return findSpecification(cycle, namespace, name, true); > } > > private IComponentSpecification findSpecification(IRequestCycle > cycle, INamespace namespace, String name, boolean isPage) { > try { > Integer.valueOf(name); > } catch (NumberFormatException e) { > return null; // not a valid format > } > DatabasePageResource resource = new DatabasePageResource(name, > cycle.getEngine().getLocale()); > if (!resource.exists()) { > return null; > } > Resource specResource = resource.getRelativeResource(name + > (isPage ? ".page" : ".jwc")); > IComponentSpecification specification = new > ComponentSpecification(); > specification.setPageSpecification(isPage); > specification.setSpecificationLocation(specResource); > specification.setLocation(new LocationImpl(resource)); > if (resource.getBackingClass() != null) { > specification.setComponentClassName(resource.getBackingClass > ()); > } > return specification; > } > > } > > public class DatabasePageResource implements Resource { > > private Locale locale; > private String componentName; > private TapestryComponent component; > > public DatabasePageResource(String componentName, Locale locale) { > this.componentName = componentName; > this.locale = locale; > load(); > } > > public String getBackingClass() { > return component.getBackingClass(); > } > > private void load() { > try { > Integer componentId = Integer.valueOf(componentName); > component = // code omitted - use your own infrastructure to > read TapestryComponent object from the database here > } catch (NumberFormatException e) { > throw new IllegalArgumentException(componentName + " is > non-numeric and therefore not a valid component ID"); > } > } > public Locale getLocale() { > return locale; > } > > public Resource getLocalization(Locale arg0) { > return this; > } > > public String getName() { > return componentName; > } > > public String getPath() { > return componentName; > } > > public Resource getRelativeResource(String resourceName) { > return new DatabasePageResource(componentName, locale); > } > > public boolean exists() { > return component != null; > } > > public URL getResourceURL() { > try { > return new URL(null, "database:///" + componentName, new > DatabaseURLStreamHandler(component.getTemplate())); > } catch (MalformedURLException e) { > // no-op - fall through to next page locator > return null; > } > } > > public String toString() { > return "DatabasePageResource (ID=" + getName() + ")"; > } > > static class DatabaseURLConnection extends URLConnection { > private String template; > > public DatabaseURLConnection(URL url, String template) { > super(url); > this.template = template; > } > > public boolean exists() { > return template != null; > } > > public void connect() {} > > public boolean getAllowuserInteraction() { > return false; > } > > public Object getContent() { > return template; > } > > public InputStream getInputStream() { > if (template == null) { > return null; > } > return new ByteArrayInputStream(template.getBytes()); > } > > public String getString() { > return template; > } > } > > static class DatabaseURLStreamHandler extends URLStreamHandler { > private String template; > > DatabaseURLStreamHandler(String template) { > this.template = template; > } > > public URLConnection openConnection(URL url) { > return new DatabaseURLConnection(url, template); > } > } > } > > hivemodule entry: > <implementation service-id="tapestry.page.SpecificationResolverDelegate" > > <create-instance > class="com.vms.infrastructure.tapestry.DatabasePageResolver" /> > </implementation> > > Tapestry User List wrote: > > IComponentSpecification spec = new ComponentSpecification(); > > spec.setComponentClassName(CommonPage.class.getName()); > > > > Resource componentResource = ??? how to instanciate a resource and > > fill it > > with a String retrieved from a database ??? > > > > spec.setSpecificationLocation(componentResource); > > > > AssetSpecification template = new AssetSpecification(); > > ??? how to fill the asset with a String retrieved from a database ??? > > > > template.setLocation(new > > DescribedLocation(spec.getSpecificationLocation(), > > "")); > > spec.addAsset("$template", template); > > > > Any idea ? > > > > D. > > > > > > 2006/12/1, Tapestry User List <[EMAIL PROTECTED]>: > >> > >> Hi, > >> > >> I would like retrieve a tapestry specification definition (.page) and > >> the > >> template (.html) from a database. > >> > >> For doing that, I create a class that implements > >> ISpecificationResolverDelegate . > >> > >> The method findPageSpecification must return a > >> IComponentSpecification. So > >> I instanciate a ComponentSpecification object. > >> > >> The problem is: how can I fill my componentSpecification object with > the > >> .page content (xml) and .html content retrieved from a database ? > >> > >> Thank you very much, > >> > >> D. > > > > --------------------------------------------------------------------- > 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]