Tapestry has the notion of Pages, Components and Services.
While all of them are POJOs, Tapestry assumes that the POJOs in /pages folder are Pages, those in /components are Components and /services are Services.
Pages and Components have their corresponding .tml files. A page can be rendered, but a component cannot be rendered. A component can be used by a page.
Services do not have .tml files. Instead, each Service has an explicit interface and implementation. Services provided functionality that other classes can use. For example, a service can implement a business computation, it can transform, filter, process data, do security checks, write logs, handle email communication, schedule events for data backup, etc. Essentially, anything that is not directly related to rendering a page or handling a page event (user clicking on a page) can be made a service.
Tapestry allows Pages, Components and Dependencies to all be injected into each other, using the following annotations:
@InjectPage
@InjectComponent
@InjectService
Additionally, it has the generic @Inject annotation which "automagically" picks up the correct thing to inject (except when it runs into ambiguity - but let us not worry about that now).
In this post, let us create a Service POJO and inject it.
In /src/main/java/org/confucius, create a folder 'services'
In /src/main/java/org/confucius/services, create a Interface GreetDAO.java, like this:
package org.confucius.services;
import java.util.List;
import org.confucius.Greet;
public interface GreetDAO {
public List<Greet> getInternationalGreetsList();
}
In /src/main/java/org/confucius/services, create a class GreetDAOImpl.java, like this:
package org.confucius.services;
import java.util.ArrayList;
import java.util.List;
import org.confucius.Greet;
public class GreetDAOImpl implements GreetDAO {
public List<Greet> getInternationalGreetsList() {
List<Greet> greetList = new ArrayList<Greet>();
Greet englishGreet = new Greet("English", "Hello World!");
greetList.add(englishGreet);
Greet frenchGreet = new Greet("French", "Bonjour tout le Monde!");
greetList.add(frenchGreet);
Greet italianGreet = new Greet("Italian", "Buongiorno a Tutti!");
greetList.add(italianGreet);
Greet spanishGreet = new Greet("Spanish", "Hola Mundo!");
greetList.add(spanishGreet);
Greet swahiliGreet = new Greet("Swahili", "Jambo!");
greetList.add(swahiliGreet);
return greetList;
}
}
Now we need to tell Tapestry to load GreetDAOImpl as an implementation of service GreetDAO.
For this we need to make a Module.
A Module is a place where services are defined, besides other things. Conveniently, a Module is just another POJO - one with a very specific name by convention: AppModule.java.
In /src/main/java/org/confucius/services, create a class AppModule.java, like this:
package org.confucius.services;
import org.apache.tapestry5.ioc.ServiceBinder;
public class AppModule {
public static void bind(ServiceBinder binder){
binder.bind(GreetDAO.class, GreetDAOImpl.class);
}
}
Note that there are other ways to define modules, but we will not worry about that right now. We will just use the default AppModule.java
Finally, we need to make one more change for this Module to get loaded.
By convention, we should name our Tapestry Filter in web.xml 'app'. So update your web.xml, like this:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<context-param>
<param-name>tapestry.app-package</param-name>
<param-value>org.confucius</param-value>
</context-param>
<filter>
<filter-name>app</filter-name>
<filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>app</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
We are all set to inject our new Service.
Update your InternationalGreets.java class to use this GreetDAO service, like this:
package org.confucius.pages;
import java.util.List;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.confucius.Greet;
import org.confucius.services.GreetDAO;
public class InternationalGreets {
@Property
private Greet greet;
@Inject
private GreetDAO greetDAO;
public List<Greet> getInternationalGreetsList(){
return greetDAO.getInternationalGreetsList();
}
}
If you now rebuild and redeploy HelloWorldTapestry, you will see the International Greets in a table, just like you did before.
However, this time Tapestry injected the GreetDAO service to make the greets available.