The tapestry-core module provides the interfaces and annotations that form the Tapestry API.
tapestry-core is built upon the Tapestry IoC Container.
Tapestry 5 represents a significant advance over Tapestry 4. The goal is to make Tapestry 5 significantly easier to use than Tapestry 4 (or any other Java web framework). We're keeping the essence of Tapestry 4, but starting with a brand new code base designed to provide a stable, powerful, extensible platform for many years to come.
Here's a few of the planned and implemented features:
A key feature of Tapestry 5 is adaptive API.
In traditional Java frameworks, including Tapestry 4, user code is expected to conform to the framework. You create classes that extend from framework-provided base classes, or implement framework-provided interfaces.
This works well until you upgrade to the next release of the framework: with the new features of the upgrade, you will more often than not experience breaks in backwards compatibility. Interfaces or base classes will have changed and your existing code will need to be changed to match.
In Tapestry 5, the framework adapts to your code. You have control over the names of the methods, the parameters they take, and the value that is returned. This is driven by annotations, which tell Tapestry under what circumstances your methods are to be invoked.
For example, you may have a login form and have a method that gets invoked when the form is submitted:
public class Login
{
@Persist
private String _userId;
private String _password;
@Component
private Form _form;
@Inject
private LoginAuthenticator _authenticator;
private Object onSubmit()
{
if (_authenticator.isValidLogin(_userId, _password))
return Start.class;
// Stay on this page:
_form.recordError("Invalid user name or password.");
return null;
}
public String getUserId() { return _userId; }
public String getPassword() { return _password; }
public void setUserId(String userId) { _userId = userId; }
public void setPassword(String password) { _password = password; }
}This short snippet demonstrates a bit about how Tapestry operates. Pages and services within the application are injected with the @Inject annotation. The method name, onSubmit(), informs Tapestry about when the method is to be invoked (when a form component contained by the page emits a "submit" event). The method's return value directs Tapestry on what to do next: jump to another page within the application (here identified as the class for the page, but other options exist), or stay on the same page to display the error message.
This also represents a distinct change from Tapestry 4. In earlier versions of Tapestry, the Form component's listener parameter would be bound to the method to invoke, by name. Further, the listener method had to be public. This new approach not only support multiple listeners, but provides an improved separation of view concerns (inside the page's HTML template) and logic concerns, inside the Java class.
In many cases, additional information about the event is available, and can be passed into the method by adding parameters to the method. Again, Tapestry will adapt to your parameters, in whatever order you supply them.
Finally, Tapestry 5 explicitly separates actions (requests that change things) and rendering (requests that render pages) into two separate requests. Performing an action, such as clicking a link or submitting a form, results in a client side redirect to the new page. This is often called "redirect after post". This helps ensure that URLs in the browser are book-markable ... but also requires that a bit more information be stored in the session between requests (using the @Persist annotation).