lets examine starting tutorial from tapestry
creating project
http://tapestry.apache.org/tapestry5/tutorial1/first.html
mvn archetype:create
-DarchetypeGroupId=org.apache.tapestry
-DarchetypeArtifactId=quickstart
-DgroupId=org.apache.tapestry
-DartifactId=tutorial1
-DpackageName=org.apache.tapestry5.tutorial
when I typed command my maven shell printed nice error message saying that something went wrong and it gives up. but the command below will work and will create all nice preconfigured project for us
mvn archetype:generate
-DarchetypeCatalog=http:/</tapestry.formos.com/maven-snapshot-repository
-DarchetypeGroupId=org.apache.tapestry
-DarchetypeArtifactId=quickstart
-DgroupId=my.package
-DartifactId=mywebapp
the other way round would be creating simple maven web project and then editing pom file to get all necessary libraries.
If you want pretty printing for framework exception messages add
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<optimize>true</optimize>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.9</version>
<configuration>
<!-- Log to the console. -->
<requestLog implementation="org.mortbay.jetty.NCSARequestLog">
<!-- This doesn't do anything for Jetty, but is a workaround for a Maven bug
that prevents the requestLog from being set. -->
<append>true</append>
</requestLog>
</configuration>
</plugin>
</plugins>
...
</build>
<strong><reporting>
<!-- Adds a report detailing the components, mixins and base classes defined by this module. -->
<plugins>
<plugin>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-component-report</artifactId>
<version>${tapestry-release-version}</version>
<configuration>
<rootPackage>info.kamiseq</rootPackage>
</configuration>
</plugin>
</plugins>
</reporting></strong>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
tapestry and hibernate
http://tapestry.apache.org/tapestry5/tutorial1/forms2.html
I couldn’t force my project to work with db through hibernate. I had huge problems with tapestry-hibernate lib. so I switched to spring and configured hibernate as a JPA’s vendor. Anyway you don’t need that either, to finish the tutorial just create simple dao object that will hold HashMap of Address object to hold created with site addresses.
tapestry and IOC
tapestry works with Inversion of Control framework of its own. So there is no need to use external framework like spring inject you custom objects in simple app. to configure IOC you need create (unless there is one) AppModule in your.package.services package and add
public static void bind(ServiceBinder binder){
binder.bind(AddressDAO.class, AddressRdmsDao.class);
}
then you can use @Inject with your interface like any other service (bean)
@Injectprivate AddressDAO dao;
extending the tutorial’s example
I added row parameter to the grid (in Index.tml) so I could add action links and customizing grid’s content but then I wished to had action link that will show item in the grid in t:beandisplay component. ok let’s go..
in Index.java
@Property
@Persist
private Address address;
@Inject
private BeanModelSource beanModelSource;
@Injectprivate ComponentResources resources;
//this will control grid's display model but it can be done with add/reorder/include paramateres in the tml
public BeanModel<Address> getAddressModel() {
BeanModel<Address> model = beanModelSource.createDisplayModel(Address.class, resources.getMessages());
model.add("action", null);
return model;
}
//to handle show action
Object onActionFromShow(Long id) {
this.address = this.dao.find(id);
return this;
}
in Index.tml
<t:grid source="addresses" row="address" model="addressModel"
reorder="honorific, firstName, lastName, email, phone, street1, street2, city, zip, country, action"
add="show">
<t:parameter name="actionCell">
<t:pagelink page="address/create" t:context="address.id">update</t:pagelink>
</t:parameter>
<t:parameter name="showCell">
<t:actionLink t:id="show" t:context="address.id">show</t:actionLink>
</t:parameter>
<p:empty>
<p>Brak danych, wprowadź addresata - <t:pagelink page="address/create">dodaj</t:pagelink>.</p>
</p:empty>
</t:grid>
<ul>
<li><t:pagelink page="address/create">Create new address</t:pagelink></li>
</ul>
ok so we have show action that will set address reference to wanted object. but if we put t:beandisplay component below t:grid then we will see the last object processed by grid (as the grid and beandisplay uses the same property address). So to see the address we clicked on then wee need to use different name for property or swap grid and display components places, is there any other way??????.
<t:if test="address">
<t:beandisplay object="address">
</t:beandisplay>
</t:if>
<t:grid source="addresses" row="address" model="addressModel"
reorder="honorific, firstName, lastName, email, phone, street1, street2, city, zip, country, action"
add="show">
<t:parameter name="actionCell">
<t:pagelink page="address/create" t:context="address.id">update</t:pagelink>
</t:parameter>
<t:parameter name="showCell">
<t:actionLink t:id="show" t:context="address.id">show</t:actionLink>
</t:parameter>
<p:empty>
<p>Brak danych, wprowadź addresata - <t:pagelink page="address/create">dodaj</t:pagelink>.</p>
</p:empty>
</t:grid>
<ul>
<li><t:pagelink page="address/create">Create new address</t:pagelink></li>
</ul>
and finally surround t:beandisplay with t:if to test existance of address object