>.
-====
-
-
-[[tapestry-pre4-style-di]]
-===== Dependency Injecting Spring Beans into Tapestry pages
-First we need to make the `ApplicationContext` available to the Tapestry page or
-Component without having to have the `ServletContext`; this is because at the stage in
-the page's/component's lifecycle when we need to access the `ApplicationContext`, the
-`ServletContext` won't be easily available to the page, so we can't use
-`WebApplicationContextUtils.getApplicationContext(servletContext)` directly. One way is
-by defining a custom version of the Tapestry `IEngine` which exposes this for us:
-
-[source,java,indent=0]
-[subs="verbatim,quotes"]
-----
- package com.whatever.web.xportal;
-
- // import ...
-
- public class MyEngine extends org.apache.tapestry.engine.BaseEngine {
-
- public static final String APPLICATION_CONTEXT_KEY = "appContext";
-
- /**
- * @see org.apache.tapestry.engine.AbstractEngine#setupForRequest(org.apache.tapestry.request.RequestContext)
- */
- protected void setupForRequest(RequestContext context) {
-
- super.setupForRequest(context);
-
- // insert ApplicationContext in global, if not there
- Map global = (Map) getGlobal();
- ApplicationContext ac = (ApplicationContext) global.get(APPLICATION_CONTEXT_KEY);
- if (ac == null) {
- ac = WebApplicationContextUtils.getWebApplicationContext(
- context.getServlet().getServletContext());
- global.put(APPLICATION_CONTEXT_KEY, ac);
- }
- }
- }
-----
-
-This engine class places the Spring Application Context as an attribute called
-"appContext" in this Tapestry app's 'Global' object. Make sure to register the fact that
-this special IEngine instance should be used for this Tapestry application, with an
-entry in the Tapestry application definition file. For example:
-
-[source,xml,indent=0]
-[subs="verbatim,quotes"]
-----
- file: xportal.application:
-
-
-
-
-----
-
-
-[[tapestry-componentdefs]]
-===== Component definition files
-Now in our page or component definition file (*.page or *.jwc), we simply add
-property-specification elements to grab the beans we need out of the
-`ApplicationContext`, and create page or component properties for them. For example:
-
-[source,xml,indent=0]
-[subs="verbatim,quotes"]
-----
-
- global.appContext.getBean("userService")
-
-
- global.appContext.getBean("authenticationService")
-
-----
-
-The OGNL expression inside the property-specification specifies the initial value for
-the property, as a bean obtained from the context. The entire page definition might look
-like this:
-
-[source,xml,indent=0]
-[subs="verbatim,quotes"]
-----
-
- ****
-
-
-
-
-
-
-
-
- global.appContext.getBean("userService")
-
-
- global.appContext.getBean("authenticationService")
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-----
-
-
-[[tapestry-getters]]
-===== Adding abstract accessors
-Now in the Java class definition for the page or component itself, all we need to do is
-add an abstract getter method for the properties we have defined (in order to be able to
-access the properties).
-
-[source,java,indent=0]
-[subs="verbatim,quotes"]
-----
- // our UserService implementation; will come from page definition
- public abstract UserService getUserService();
- // our AuthenticationService implementation; will come from page definition
- public abstract AuthenticationService getAuthenticationService();
-----
-
-For the sake of completeness, the entire Java class, for a login page in this example,
-might look like this:
-
-[source,java,indent=0]
-----
- package com.whatever.web.xportal.pages;
-
- /**
- * Allows the user to login, by providing username and password.
- * After successfully logging in, a cookie is placed on the client browser
- * that provides the default username for future logins (the cookie
- * persists for a week).
- */
- public abstract class Login extends BasePage implements ErrorProperty, PageRenderListener {
-
- /** the key under which the authenticated user object is stored in the visit as */
- public static final String USER_KEY = "user";
-
- /** The name of the cookie that identifies a user **/
- private static final String COOKIE_NAME = Login.class.getName() + ".username";
- private final static int ONE_WEEK = 7 * 24 * 60 * 60;
-
- public abstract String getUsername();
- public abstract void setUsername(String username);
-
- public abstract String getPassword();
- public abstract void setPassword(String password);
-
- public abstract ICallback getCallback();
- public abstract void setCallback(ICallback value);
-
- public abstract UserService getUserService();
- public abstract AuthenticationService getAuthenticationService();
-
- protected IValidationDelegate getValidationDelegate() {
- return (IValidationDelegate) getBeans().getBean("delegate");
- }
-
- protected void setErrorField(String componentId, String message) {
- IFormComponent field = (IFormComponent) getComponent(componentId);
- IValidationDelegate delegate = getValidationDelegate();
- delegate.setFormComponent(field);
- delegate.record(new ValidatorException(message));
- }
-
- /**
- * Attempts to login.
- *
- * If the user name is not known, or the password is invalid, then an error
- * message is displayed.
- */
- public void attemptLogin(IRequestCycle cycle) {
-
- String password = getPassword();
-
- // Do a little extra work to clear out the password.
- setPassword(null);
- IValidationDelegate delegate = getValidationDelegate();
-
- delegate.setFormComponent((IFormComponent) getComponent("inputPassword"));
- delegate.recordFieldInputValue(null);
-
- // An error, from a validation field, may already have occurred.
- if (delegate.getHasErrors()) {
- return;
- }
-
- try {
- User user = getAuthenticationService().login(getUsername(), getPassword());
- loginUser(user, cycle);
- }
- catch (FailedLoginException ex) {
- this.setError("Login failed: " + ex.getMessage());
- return;
- }
- }
-
- /**
- * Sets up the {@link User} as the logged in user, creates
- * a cookie for their username (for subsequent logins),
- * and redirects to the appropriate page, or
- * a specified page).
- */
- public void loginUser(User user, IRequestCycle cycle) {
-
- String username = user.getUsername();
-
- // Get the visit object; this will likely force the
- // creation of the visit object and an HttpSession
- Map visit = (Map) getVisit();
- visit.put(USER_KEY, user);
-
- // After logging in, go to the MyLibrary page, unless otherwise specified
- ICallback callback = getCallback();
-
- if (callback == null) {
- cycle.activate("Home");
- }
- else {
- callback.performCallback(cycle);
- }
-
- IEngine engine = getEngine();
- Cookie cookie = new Cookie(COOKIE_NAME, username);
- cookie.setPath(engine.getServletPath());
- cookie.setMaxAge(ONE_WEEK);
-
- // Record the user's username in a cookie
- cycle.getRequestContext().addCookie(cookie);
- engine.forgetPage(getPageName());
- }
-
- public void pageBeginRender(PageEvent event) {
- if (getUsername() == null) {
- setUsername(getRequestCycle().getRequestContext().getCookieValue(COOKIE_NAME));
- }
- }
- }
-----
-
-
-[[tapestry-4-style-di]]
-===== Dependency Injecting Spring Beans into Tapestry pages - Tapestry 4.x style
-Effecting the dependency injection of Spring-managed beans into Tapestry pages in
-Tapestry version 4.x is __so__ much simpler. All that is needed is a single
-http://howardlewisship.com/tapestry-javaforge/tapestry-spring/[add-on library], and some
-(small) amount of (essentially boilerplate) configuration. Simply package and deploy
-this library with the (any of the) other libraries required by your web application
-(typically in `WEB-INF/lib`).
-
-You will then need to create and expose the Spring container using the
-<>. You can then inject
-Spring-managed beans into Tapestry very easily; if we are using Java 5, consider the
-`Login` page from above: we simply need to annotate the appropriate getter methods in
-order to dependency inject the Spring-managed `userService` and `authenticationService`
-objects (lots of the class definition has been elided for clarity).
-
-[source,java,indent=0]
-[subs="verbatim,quotes"]
-----
- package com.whatever.web.xportal.pages;
-
- public abstract class Login extends BasePage implements ErrorProperty, PageRenderListener {
-
- @InjectObject("spring:userService")
- public abstract UserService getUserService();
-
- @InjectObject("spring:authenticationService")
- public abstract AuthenticationService getAuthenticationService();
-
- }
-----
-
-We are almost done. All that remains is the HiveMind configuration that exposes the
-Spring container stored in the `ServletContext` as a HiveMind service; for example:
-
-[source,xml,indent=0]
-[subs="verbatim,quotes"]
-----
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-----
-
-If you are using Java 5 (and thus have access to annotations), then that really is it.
-
-If you are not using Java 5, then one obviously doesn't annotate one's Tapestry page
-classes with annotations; instead, one simply uses good old fashioned XML to declare the
-dependency injection; for example, inside the `.page` or `.jwc` file for the `Login`
-page (or component):
-
-[source,xml,indent=0]
-[subs="verbatim,quotes"]
-----
-
-
-----
-
-In this example, we've managed to allow service beans defined in a Spring container to
-be provided to the Tapestry page in a declarative fashion. The page class does not know
-where the service implementations are coming from, and in fact it is easy to slip in
-another implementation, for example, during testing. This inversion of control is one of
-the prime goals and benefits of the Spring Framework, and we have managed to extend it
-throughout the stack in this Tapestry application.
+for the web user interface and the Spring container for the lower layers.
+For more information, check out Tapestry's dedicated
+https://tapestry.apache.org/integrating-with-spring-framework.html[integration module for
+Spring].
@@ -35356,7 +34607,7 @@ throughout the stack in this Tapestry application.
Find below links to further resources about the various web frameworks described in this
chapter.
-* The http://java.sun.com/javaee/javaserverfaces/[JSF] homepage
+* The http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html[JSF] homepage
* The http://struts.apache.org/[Struts] homepage
* The http://tapestry.apache.org/[Tapestry] homepage