diff --git a/apps/mailreader/src/main/java/mailreader2/AppData.java b/apps/mailreader/src/main/java/mailreader2/AppData.java index fde44477a..26ed3e63b 100644 --- a/apps/mailreader/src/main/java/mailreader2/AppData.java +++ b/apps/mailreader/src/main/java/mailreader2/AppData.java @@ -37,6 +37,7 @@ public class AppData { /** *

Adapt internal Integer value to external boolean value.

+ * * @return False if host_auto==0, True otherwise */ public boolean isHost_auto_checkbox() { @@ -57,6 +58,7 @@ public class AppData { /** *

Return true if a logic or state test passed, * such as whether a record already exists.

+ * * @return True if a business logic test passed. */ public boolean isNominal() { diff --git a/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java b/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java index c32fb71e0..c7a269cdc 100644 --- a/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java +++ b/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java @@ -29,7 +29,7 @@ import java.io.*; /** *

ServletContextListener that initializes and finalizes the - * persistent storage of User and Subscription information for the Struts + * persistent storage of User and Support information for the Struts * Demonstration Application, using an in-memory database backed by an XML * file.

*

@@ -50,7 +50,7 @@ import java.io.*; *

  • Class to store protocol list (an array here).
  • *

    * - *

    + *

    * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring. *

    */ diff --git a/apps/mailreader/src/main/java/mailreader2/AuthenticationInterceptor.java b/apps/mailreader/src/main/java/mailreader2/AuthenticationInterceptor.java index 10cc36823..627c456bc 100644 --- a/apps/mailreader/src/main/java/mailreader2/AuthenticationInterceptor.java +++ b/apps/mailreader/src/main/java/mailreader2/AuthenticationInterceptor.java @@ -1,16 +1,19 @@ package mailreader2; -import com.opensymphony.xwork2.interceptor.Interceptor; -import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.Action; -import java.util.Map; +import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.interceptor.Interceptor; import org.apache.struts.apps.mailreader.dao.User; -public class AuthenticationInterceptor implements Interceptor { +import java.util.Map; - public void destroy () {} +public class AuthenticationInterceptor implements Interceptor { - public void init() {} + public void destroy() { + } + + public void init() { + } public String intercept(ActionInvocation actionInvocation) throws Exception { @@ -18,12 +21,11 @@ public class AuthenticationInterceptor implements Interceptor { User user = (User) session.get(Constants.USER_KEY); - boolean isAuthenticated = (null!=user) && (null!=user.getDatabase()); + boolean isAuthenticated = (null != user) && (null != user.getDatabase()); if (!isAuthenticated) { - return Action.LOGIN; - } - else { + return Action.LOGIN; + } else { return actionInvocation.invoke(); } diff --git a/apps/mailreader/src/main/java/mailreader2/Constants.java b/apps/mailreader/src/main/java/mailreader2/Constants.java index 5685e9617..44b64a46a 100644 --- a/apps/mailreader/src/main/java/mailreader2/Constants.java +++ b/apps/mailreader/src/main/java/mailreader2/Constants.java @@ -75,7 +75,7 @@ public final class Constants { public static final String PACKAGE = "org.apache.struts.apps.mailreader"; /** - *

    The session scope attribute under which the Subscription object + *

    The session scope attribute under which the Support object * currently selected by our logged-in User is stored.

    */ public static final String SUBSCRIPTION_KEY = "subscription"; @@ -91,11 +91,10 @@ public final class Constants { */ public static final String HOST = "host"; - // ---- Error Messages ---- /** - *

    + *

    * A static message in case message resource is not loaded. *

    */ @@ -103,31 +102,31 @@ public final class Constants { "ERROR: Message resources not loaded -- check servlet container logs for error messages."; /** - *

    + *

    * A static message in case database resource is not loaded. - *

    + *

    */ public static final String ERROR_DATABASE_NOT_LOADED = "ERROR: User database not loaded -- check servlet container logs for error messages."; /** - *

    + *

    * A standard key from the message resources file, to test if it is available. - *

    + *

    */ public static final String ERROR_DATABASE_MISSING = "error.database.missing"; /** - *

    + *

    * A "magic" username to trigger an ExpiredPasswordException for testing. - *

    + *

    */ public static final String EXPIRED_PASSWORD_EXCEPTION = "ExpiredPasswordException"; /** - *

    + *

    * Name of field to associate with authentification errors. - *

    + *

    */ public static final String PASSWORD_MISMATCH_FIELD = "password"; diff --git a/apps/mailreader/src/main/java/mailreader2/Logoff.java b/apps/mailreader/src/main/java/mailreader2/Logoff.java index 4cbafa55a..4d8839307 100644 --- a/apps/mailreader/src/main/java/mailreader2/Logoff.java +++ b/apps/mailreader/src/main/java/mailreader2/Logoff.java @@ -24,9 +24,7 @@ package mailreader2; public class Logoff extends MailreaderSupport { public String execute() { - setUser(null); - return SUCCESS; } } diff --git a/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java b/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java index 7b5837dd8..4382c83c1 100644 --- a/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java +++ b/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java @@ -19,8 +19,6 @@ package mailreader2; import com.opensymphony.util.BeanUtils; -import org.apache.struts2.interceptor.ApplicationAware; -import org.apache.struts2.interceptor.SessionAware; import com.opensymphony.xwork2.ActionSupport; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -30,6 +28,8 @@ import org.apache.struts.apps.mailreader.dao.User; import org.apache.struts.apps.mailreader.dao.UserDatabase; import org.apache.struts.apps.mailreader.dao.impl.memory.MemorySubscription; import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUser; +import org.apache.struts2.interceptor.ApplicationAware; +import org.apache.struts2.interceptor.SessionAware; import java.util.Map; @@ -54,13 +54,13 @@ public class MailreaderSupport extends ActionSupport /** * Return CANCEL so apropriate result can be selected. + * * @return "cancel" so apropriate result can be selected. */ public String cancel() { return Constants.CANCEL; } - // ---- ApplicationAware ---- /** @@ -140,7 +140,7 @@ public class MailreaderSupport extends ActionSupport * @param value The task to set. */ public void setTask(String value) { - task = value; + task = value; } // ---- Token property (utilized by UI) ---- @@ -166,18 +166,17 @@ public class MailreaderSupport extends ActionSupport * @param value The token to set. */ public void setToken(String value) { - token = value; + token = value; } - // ---- Host property ---- /** - *

    Field to store Subscription host.

    + *

    Field to store Support host.

    *

    *

    The host is an immutable property of the Subscrtion DAP object, so * we need to store it locally until we are ready to create the - * Subscription.

    + * Support.

    */ private String host; @@ -191,7 +190,7 @@ public class MailreaderSupport extends ActionSupport } /** - *

    Store new Subscription host.

    + *

    Store new Support host.

    * * @param value */ @@ -401,7 +400,7 @@ public class MailreaderSupport extends ActionSupport try { user = database.findUser(username); - } + } catch (ExpiredPasswordException e) { user = getUser(); // Just so that it is not null @@ -437,19 +436,19 @@ public class MailreaderSupport extends ActionSupport } } - // ---- Subscription property ---- + // ---- Support property ---- /** - *

    Obtain the cached Subscription object, if any.

    + *

    Obtain the cached Support object, if any.

    * - * @return Cached Subscription object or null + * @return Cached Support object or null */ public Subscription getSubscription() { return (Subscription) getSession().get(Constants.SUBSCRIPTION_KEY); } /** - *

    Store new User Subscription.

    + *

    Store new User Support.

    * * @param subscription */ @@ -458,13 +457,13 @@ public class MailreaderSupport extends ActionSupport } /** - *

    Obtain User Subscription object for the given host, or return null + *

    Obtain User Support object for the given host, or return null * if not found.

    - * + *

    *

    It would be possible for this code to throw a NullPointerException, * but the ExceptionHandler in the xwork.xml will catch that for us.

    * - * @return The matching Subscription or null + * @return The matching Support or null */ public Subscription findSubscription(String host) { Subscription subscription; @@ -473,19 +472,19 @@ public class MailreaderSupport extends ActionSupport } /** - *

    Obtain uSER Subscription for the local Host property.

    + *

    Obtain uSER Support for the local Host property.

    *

    *

    Usually, the host property will be set from the client request, * because it was embedded in a link to the Subcription action. * - * @return Subscription or null if not found + * @return Support or null if not found */ public Subscription findSubscription() { return findSubscription(getHost()); } /** - *

    Provide a "temporary" User Subscription object that can be used to + *

    Provide a "temporary" User Support object that can be used to * capture input values.

    */ public void createInputSubscription() { @@ -495,11 +494,11 @@ public class MailreaderSupport extends ActionSupport } /** - *

    Provide new User Subscription object for the given host, or null if + *

    Provide new User Support object for the given host, or null if * the host is not unique.

    * * @param host - * @return New User Subscription object or null + * @return New User Support object or null */ public Subscription createSubscription(String host) { @@ -509,7 +508,7 @@ public class MailreaderSupport extends ActionSupport if (null != sub) { // FIXME - localization - "error.host.unique") - addFieldError(Constants.HOST,"That hostname is already defined"); + addFieldError(Constants.HOST, "That hostname is already defined"); return null; } @@ -517,10 +516,10 @@ public class MailreaderSupport extends ActionSupport } /** - *

    Create a new Subscription from the current Subscription object, - * making the new Subscription the current Subscription.

    + *

    Create a new Support from the current Support object, + * making the new Support the current Support.

    *

    - *

    Usually, the "current" Subscription is a temporary object being used + *

    Usually, the "current" Support is a temporary object being used * to capture input values.

    * * @param host @@ -536,17 +535,17 @@ public class MailreaderSupport extends ActionSupport } /** - *

    Delete the current Subscription object from the database.

    + *

    Delete the current Support object from the database.

    */ - public void removeSubscription() { + public void removeSubscription() { getUser().removeSubscription(getSubscription()); getSession().remove(Constants.SUBSCRIPTION_KEY); } /** - *

    Provide MailServer Host for current User Subscription.

    + *

    Provide MailServer Host for current User Support.

    * - * @return MailServer Host for current User Subscription + * @return MailServer Host for current User Support */ public String getSubscriptionHost() { Subscription sub = getSubscription(); diff --git a/apps/mailreader/src/main/java/mailreader2/Registration.java b/apps/mailreader/src/main/java/mailreader2/Registration.java deleted file mode 100644 index e6764eef2..000000000 --- a/apps/mailreader/src/main/java/mailreader2/Registration.java +++ /dev/null @@ -1,91 +0,0 @@ -package mailreader2; - -import org.apache.struts.apps.mailreader.dao.User; - - -/** - *

    Insert or update a User object to the persistent store.

    - */ -public class Registration extends MailreaderSupport { - - /** - *

    Double check that there is not a valid User logon.

    - * - * @return True if there is not a valid User logon - */ - private boolean isCreating() { - User user = getUser(); - return (null == user) || (null == user.getDatabase()); - } - - /** - *

    Retrieve User object to edit or null if User does not exist.

    - * - * @return The "Success" result for this mapping - * @throws Exception on any error - */ - public String input() throws Exception { - - if (isCreating()) { - createInputUser(); - setTask(Constants.CREATE); - } else { - setTask(Constants.EDIT); - setUsername(getUser().getUsername()); - setPassword(getUser().getPassword()); - setPassword2(getUser().getPassword()); - } - - return INPUT; - } - - /** - *

    Insert or update a User object to the persistent store.

    - *

    - *

    If a User is not logged in, then a new User is created and - * automatically logged in. Otherwise, the existing User is updated.

    - * - * @return The "Success" result for this mapping - * @throws Exception on any error - */ - public String execute() - throws Exception { - - boolean creating = Constants.CREATE.equals(getTask()); - creating = creating && isCreating(); // trust but verify - - if (creating) { - - User user = findUser(getUsername(), getPassword()); - boolean haveUser = (user != null); - - if (haveUser) { - addActionError(getText("error.username.unique")); - return INPUT; - } - - copyUser(getUsername(), getPassword()); - - } else { - - // FIXME: Any way to call the RegisrationSave validators from here? - String newPassword = getPassword(); - if (newPassword != null) { - String confirmPassword = getPassword2(); - boolean matches = ((null != confirmPassword) - && (confirmPassword.equals(newPassword))); - if (matches) { - getUser().setPassword(newPassword); - } else { - addActionError(getText("error.password.match")); - return INPUT; - } - } - } - - saveUser(); - - return SUCCESS; - } - -} diff --git a/apps/mailreader/src/main/java/mailreader2/RegistrationSave.java b/apps/mailreader/src/main/java/mailreader2/RegistrationSave.java deleted file mode 100644 index 9692a915d..000000000 --- a/apps/mailreader/src/main/java/mailreader2/RegistrationSave.java +++ /dev/null @@ -1,8 +0,0 @@ -package mailreader2; - -/** - *

    Stub class to allow extra validation on initial Save.

    - */ -public final class RegistrationSave extends Registration { - -} diff --git a/apps/mailreader/src/main/java/mailreader2/Subscription.java b/apps/mailreader/src/main/java/mailreader2/Subscription.java deleted file mode 100644 index e67da1bf1..000000000 --- a/apps/mailreader/src/main/java/mailreader2/Subscription.java +++ /dev/null @@ -1,125 +0,0 @@ -package mailreader2; - -import com.opensymphony.xwork2.Preparable; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - *

    Provide an Edit method for retrieving an existing subscription, and a - * Save method for updating or inserting a subscription.

    - */ -public class Subscription extends MailreaderSupport - implements Preparable { - - /** - *

    Field to store list of MailServer types

    - */ - private Map types = null; - - /** - *

    Provide the list of MailServer types.

    - * - * @return List of MailServer types - */ - public Map getTypes() { - return types; - } - - /** - *

    Setup the MailerServer types and set the local Host property from - * the User Subscription (if any).

    - */ - public void prepare() { - - Map m = new LinkedHashMap(); - m.put("imap", "IMAP Protocol"); - m.put("pop3", "POP3 Protocol"); - types = m; - - setHost(getSubscriptionHost()); - - } - - /** - *

    Setup a temporary User Subscription object to capture input - * values.

    - * - * @return INPUT - */ - public String input() { - createInputSubscription(); - setTask(Constants.CREATE); - return INPUT; - } - - /** - *

    Load User Subscription for the local Host property.

    - *

    - *

    Usually, the Host is being set from the request by a link to an Edit - * or Delete task.

    - * - * @return INPUT or Error, if Subscription is not found - */ - public String find() { - - org.apache.struts.apps.mailreader.dao.Subscription - sub = findSubscription(); - - if (sub == null) { - return ERROR; - } - - setSubscription(sub); - - return INPUT; - - } - - /** - *

    Prepare to present a confirmation page before removing - * Subscription.

    - * - * @return INPUT or Error, if Subscription is not found - */ - public String delete() { - - setTask(Constants.DELETE); - return find(); - } - - /** - *

    Prepare to edit User Subscription.

    - * - * @return INPUT or Error, if Subscription is not found - */ - public String edit() { - - setTask(Constants.EDIT); - return find(); - } - - /** - *

    Examine the Task property and DELETE, CREATE, or save the User - * Subscription, as appropriate.

    - * - * @return SUCCESS - * @throws Exception on a database error - */ - public String save() throws Exception { - - if (Constants.DELETE.equals(getTask())) { - removeSubscription(); - } - - if (Constants.CREATE.equals(getTask())) { - copySubscription(getHost()); - } - - if (hasErrors()) return INPUT; - - saveUser(); - return SUCCESS; - } - -} diff --git a/apps/mailreader/src/main/java/mailreader2/SubscriptionSave.java b/apps/mailreader/src/main/java/mailreader2/SubscriptionSave.java deleted file mode 100644 index 413cdf5ba..000000000 --- a/apps/mailreader/src/main/java/mailreader2/SubscriptionSave.java +++ /dev/null @@ -1,20 +0,0 @@ -package mailreader2; - -/** - *

    Workaround class. Submitting to an alias doesn't seem to work.

    - */ -public final class SubscriptionSave extends Subscription { - - public void prepare() { - super.prepare(); - // checkbox workaround - getSubscription().setAutoConnect(false); - } - - public String execute() throws Exception { - return save(); - } - - - -} diff --git a/apps/mailreader/src/main/java/mailreader2/Welcome-action.xml b/apps/mailreader/src/main/java/mailreader2/Welcome-action.xml new file mode 100644 index 000000000..8577d073c --- /dev/null +++ b/apps/mailreader/src/main/java/mailreader2/Welcome-action.xml @@ -0,0 +1,15 @@ + + + + + + + + /pages/Welcome.jsp + + + + + diff --git a/apps/mailreader/src/main/java/mailreader2/Welcome.java b/apps/mailreader/src/main/java/mailreader2/Welcome.java index 08ec12581..c7348bd21 100644 --- a/apps/mailreader/src/main/java/mailreader2/Welcome.java +++ b/apps/mailreader/src/main/java/mailreader2/Welcome.java @@ -14,14 +14,13 @@ public class Welcome extends MailreaderSupport { } // Confirm database loaded - if (null==getDatabase()) { - addActionError(Constants.ERROR_DATABASE_NOT_LOADED); + if (null == getDatabase()) { + addActionError(Constants.ERROR_DATABASE_NOT_LOADED); } if (hasErrors()) { return ERROR; - } - else { + } else { return SUCCESS; } } diff --git a/apps/mailreader/src/main/resources/mailreader2/RegistrationSave-validation.xml b/apps/mailreader/src/main/java/mailreader2/registration/Create-validation.xml similarity index 97% rename from apps/mailreader/src/main/resources/mailreader2/RegistrationSave-validation.xml rename to apps/mailreader/src/main/java/mailreader2/registration/Create-validation.xml index 689640742..ccf277b4a 100644 --- a/apps/mailreader/src/main/resources/mailreader2/RegistrationSave-validation.xml +++ b/apps/mailreader/src/main/java/mailreader2/registration/Create-validation.xml @@ -1,28 +1,28 @@ - - - - - - - - - - true - 4 - 10 - - - - - - - - - - - - password eq password2 - - - - + + + + + + + + + + true + 4 + 10 + + + + + + + + + + + + password eq password2 + + + + diff --git a/apps/mailreader/src/main/java/mailreader2/registration/Create.java b/apps/mailreader/src/main/java/mailreader2/registration/Create.java new file mode 100644 index 000000000..7e7bca129 --- /dev/null +++ b/apps/mailreader/src/main/java/mailreader2/registration/Create.java @@ -0,0 +1,33 @@ +package mailreader2.registration; + +import mailreader2.Constants; +import org.apache.struts.apps.mailreader.dao.User; + +/** + *

    Insert new user, providing extra validation.

    + *

    + *

    (On an update, the password change is optional.)

    + */ +public final class Create extends Update { + + public String execute() + throws Exception { + + // trust but verify + boolean creating = Constants.CREATE.equals(getTask()); + creating = creating && isCreating(); + if (!creating) return ERROR; + + User user = findUser(getUsername(), getPassword()); + boolean haveUser = (user != null); + + if (haveUser) { + addActionError(getText("error.username.unique")); + return INPUT; + } + + copyUser(getUsername(), getPassword()); + + return SUCCESS; + } +} diff --git a/apps/mailreader/src/main/java/mailreader2/registration/Input.java b/apps/mailreader/src/main/java/mailreader2/registration/Input.java new file mode 100644 index 000000000..a034366cf --- /dev/null +++ b/apps/mailreader/src/main/java/mailreader2/registration/Input.java @@ -0,0 +1,31 @@ +package mailreader2.registration; + +import mailreader2.Constants; + +/** + *

    Retrieve User object to edit or null if User does not exist.

    + */ +public class Input extends Support { + + /** + *

    Retrieve User object to edit or null if User does not exist.

    + * + * @return The "Success" result for this mapping + * @throws Exception on any error + */ + public String execute() throws Exception { + + if (isCreating()) { + createInputUser(); + setTask(Constants.CREATE); + } else { + setTask(Constants.EDIT); + setUsername(getUser().getUsername()); + setPassword(getUser().getPassword()); + setPassword2(getUser().getPassword()); + } + + return SUCCESS; + } + +} diff --git a/apps/mailreader/src/main/resources/mailreader2/Logon-validation.xml b/apps/mailreader/src/main/java/mailreader2/registration/Retrieve-validation.xml similarity index 100% rename from apps/mailreader/src/main/resources/mailreader2/Logon-validation.xml rename to apps/mailreader/src/main/java/mailreader2/registration/Retrieve-validation.xml diff --git a/apps/mailreader/src/main/java/mailreader2/Logon.java b/apps/mailreader/src/main/java/mailreader2/registration/Retrieve.java similarity index 80% rename from apps/mailreader/src/main/java/mailreader2/Logon.java rename to apps/mailreader/src/main/java/mailreader2/registration/Retrieve.java index 0c8fa735e..0fed8130c 100644 --- a/apps/mailreader/src/main/java/mailreader2/Logon.java +++ b/apps/mailreader/src/main/java/mailreader2/registration/Retrieve.java @@ -1,45 +1,46 @@ -/* - * $Id: LogonAction.java 360442 2005-12-31 20:10:04Z husted $ - * - * Copyright 2000-2004 Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package mailreader2; - -import org.apache.struts.apps.mailreader.dao.User; -import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException; - -/** - *

    Validate a user logon.

    - */ -public final class Logon extends MailreaderSupport { - - public String execute() throws ExpiredPasswordException { - - User user = findUser(getUsername(), getPassword()); - - if (user != null) { - setUser(user); - } - - if (hasErrors()) { - return INPUT; - } - - return SUCCESS; - - } - -} +/* + * $Id: LogonAction.java 360442 2005-12-31 20:10:04Z husted $ + * + * Copyright 2000-2004 Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mailreader2.registration; + +import mailreader2.MailreaderSupport; +import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException; +import org.apache.struts.apps.mailreader.dao.User; + +/** + *

    Validate a user logon.

    + */ +public final class Retrieve extends MailreaderSupport { + + public String execute() throws ExpiredPasswordException { + + User user = findUser(getUsername(), getPassword()); + + if (user != null) { + setUser(user); + } + + if (hasErrors()) { + return INPUT; + } + + return SUCCESS; + + } + +} diff --git a/apps/mailreader/src/main/java/mailreader2/registration/Support.java b/apps/mailreader/src/main/java/mailreader2/registration/Support.java new file mode 100644 index 000000000..0316314e1 --- /dev/null +++ b/apps/mailreader/src/main/java/mailreader2/registration/Support.java @@ -0,0 +1,20 @@ +package mailreader2.registration; + +import mailreader2.MailreaderSupport; +import org.apache.struts.apps.mailreader.dao.User; + +/** + *

    Base class to store shared methods.

    + */ +public class Support extends MailreaderSupport { + + /** + *

    Double check that there is not a valid User logon.

    + * + * @return True if there is not a valid User logon + */ + protected boolean isCreating() { + User user = getUser(); + return (null == user) || (null == user.getDatabase()); + } +} diff --git a/apps/mailreader/src/main/resources/mailreader2/Registration-validation.xml b/apps/mailreader/src/main/java/mailreader2/registration/Update-validation.xml similarity index 96% rename from apps/mailreader/src/main/resources/mailreader2/Registration-validation.xml rename to apps/mailreader/src/main/java/mailreader2/registration/Update-validation.xml index 03cba1e78..44d66bc19 100644 --- a/apps/mailreader/src/main/resources/mailreader2/Registration-validation.xml +++ b/apps/mailreader/src/main/java/mailreader2/registration/Update-validation.xml @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/mailreader/src/main/java/mailreader2/registration/Update.java b/apps/mailreader/src/main/java/mailreader2/registration/Update.java new file mode 100644 index 000000000..57d335aac --- /dev/null +++ b/apps/mailreader/src/main/java/mailreader2/registration/Update.java @@ -0,0 +1,41 @@ +package mailreader2.registration; + +import mailreader2.Constants; + +/** + *

    Update a User object to the persistent store.

    + */ +public class Update extends Support { + + private String fixNull(String value) { + if (value == null) return null; + String buffer = value.trim(); + if (buffer.length() == 0) return null; + return buffer; + } + + public String execute() + throws Exception { + + boolean creating = Constants.CREATE.equals(getTask()); + creating = creating && isCreating(); // trust but verify + if (creating) return ERROR; + // FIXME: Any way to call the RegisrationSave validators from here? + String newPassword = fixNull(getPassword()); + String confirmPassword = fixNull(getPassword2()); + if (newPassword != null) { + boolean matches = ((confirmPassword != null) + && (confirmPassword.equals(newPassword))); + if (matches) { + getUser().setPassword(newPassword); + } else { + addActionError(getText("error.password.match")); + return INPUT; + } + } + + saveUser(); + + return SUCCESS; + } +} diff --git a/apps/mailreader/src/main/java/mailreader2/subscription/Delete.java b/apps/mailreader/src/main/java/mailreader2/subscription/Delete.java new file mode 100644 index 000000000..893916f01 --- /dev/null +++ b/apps/mailreader/src/main/java/mailreader2/subscription/Delete.java @@ -0,0 +1,15 @@ +package mailreader2.subscription; + +import mailreader2.Constants; + +/** + *

    Prepare to present a confirmation page before removing + * subscription.

    + */ +public class Delete extends Edit { + + public String execute() throws Exception { + setTask(Constants.DELETE); + return find(); + } +} diff --git a/apps/mailreader/src/main/resources/mailreader2/Subscription-validation.xml b/apps/mailreader/src/main/java/mailreader2/subscription/Edit-validation.xml similarity index 96% rename from apps/mailreader/src/main/resources/mailreader2/Subscription-validation.xml rename to apps/mailreader/src/main/java/mailreader2/subscription/Edit-validation.xml index bc422c8b9..df903c25b 100644 --- a/apps/mailreader/src/main/resources/mailreader2/Subscription-validation.xml +++ b/apps/mailreader/src/main/java/mailreader2/subscription/Edit-validation.xml @@ -1,11 +1,11 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/apps/mailreader/src/main/java/mailreader2/subscription/Edit.java b/apps/mailreader/src/main/java/mailreader2/subscription/Edit.java new file mode 100644 index 000000000..1baf3f976 --- /dev/null +++ b/apps/mailreader/src/main/java/mailreader2/subscription/Edit.java @@ -0,0 +1,16 @@ +package mailreader2.subscription; + +import mailreader2.Constants; + +/** + *

    Prepare to edit User Support.

    + */ +public class Edit extends Support { + + public String execute() throws Exception { + setTask(Constants.EDIT); + return find(); + } + + +} diff --git a/apps/mailreader/src/main/java/mailreader2/subscription/Input.java b/apps/mailreader/src/main/java/mailreader2/subscription/Input.java new file mode 100644 index 000000000..2053dd617 --- /dev/null +++ b/apps/mailreader/src/main/java/mailreader2/subscription/Input.java @@ -0,0 +1,17 @@ +package mailreader2.subscription; + +import mailreader2.Constants; + +/** + *

    Setup a temporary User Support object to capture input + * values.

    + */ +public class Input extends Support { + + public String execute() { + createInputSubscription(); + setTask(Constants.CREATE); + return SUCCESS; + } + +} diff --git a/apps/mailreader/src/main/resources/mailreader2/SubscriptionSave-validation.xml b/apps/mailreader/src/main/java/mailreader2/subscription/Save-validation.xml similarity index 96% rename from apps/mailreader/src/main/resources/mailreader2/SubscriptionSave-validation.xml rename to apps/mailreader/src/main/java/mailreader2/subscription/Save-validation.xml index 7d28623e3..9f2f6d793 100644 --- a/apps/mailreader/src/main/resources/mailreader2/SubscriptionSave-validation.xml +++ b/apps/mailreader/src/main/java/mailreader2/subscription/Save-validation.xml @@ -1,23 +1,23 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/mailreader/src/main/java/mailreader2/subscription/Save.java b/apps/mailreader/src/main/java/mailreader2/subscription/Save.java new file mode 100644 index 000000000..e24e53070 --- /dev/null +++ b/apps/mailreader/src/main/java/mailreader2/subscription/Save.java @@ -0,0 +1,38 @@ +package mailreader2.subscription; + +import mailreader2.Constants; + +/** + *

    Workaround class. Submitting to an alias doesn't seem to work.

    + */ +public final class Save extends Edit { + + public void prepare() { + super.prepare(); + // checkbox workaround + getSubscription().setAutoConnect(false); + } + + /** + *

    Examine the Task property and DELETE, CREATE, or save the User + * Support, as appropriate.

    + * + * @return SUCCESS + * @throws Exception on a database error + */ + public String execute() throws Exception { + + if (Constants.DELETE.equals(getTask())) { + removeSubscription(); + } + + if (Constants.CREATE.equals(getTask())) { + copySubscription(getHost()); + } + + if (hasErrors()) return INPUT; + + saveUser(); + return SUCCESS; + } +} diff --git a/apps/mailreader/src/main/java/mailreader2/subscription/Support.java b/apps/mailreader/src/main/java/mailreader2/subscription/Support.java new file mode 100644 index 000000000..ebdd5e901 --- /dev/null +++ b/apps/mailreader/src/main/java/mailreader2/subscription/Support.java @@ -0,0 +1,66 @@ +package mailreader2.subscription; + +import com.opensymphony.xwork2.Preparable; +import mailreader2.MailreaderSupport; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + *

    Provide an Edit method for retrieving an existing subscription, and a + * Save method for updating or inserting a subscription.

    + */ +public class Support extends MailreaderSupport + implements Preparable { + + /** + *

    Field to store list of MailServer types

    + */ + private Map types = null; + + /** + *

    Provide the list of MailServer types.

    + * + * @return List of MailServer types + */ + public Map getTypes() { + return types; + } + + /** + *

    Setup the MailerServer types and set the local Host property from + * the User Support (if any).

    + */ + public void prepare() { + + Map m = new LinkedHashMap(); + m.put("imap", "IMAP Protocol"); + m.put("pop3", "POP3 Protocol"); + types = m; + + setHost(getSubscriptionHost()); + + } + + /** + *

    Load User Support for the local Host property.

    + *

    + *

    Usually, the Host is being set from the request by a link to an Edit + * or Delete task.

    + * + * @return INPUT or Error, if Support is not found + */ + public String find() { + + org.apache.struts.apps.mailreader.dao.Subscription + sub = findSubscription(); + + if (sub == null) { + return ERROR; + } + + setSubscription(sub); + + return SUCCESS; + } +} diff --git a/apps/mailreader/src/main/resources/sql-map-config.xml b/apps/mailreader/src/main/resources/sql-map-config.xml index 6ffeda2ab..394415187 100644 --- a/apps/mailreader/src/main/resources/sql-map-config.xml +++ b/apps/mailreader/src/main/resources/sql-map-config.xml @@ -1,25 +1,25 @@ + "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" + "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> - + - + - - - - - - - - - - - + + + + + + + + + + + - + \ No newline at end of file diff --git a/apps/mailreader/src/main/resources/sql/sql-map.xml b/apps/mailreader/src/main/resources/sql/sql-map.xml index 61b026e29..e6ea17ba9 100644 --- a/apps/mailreader/src/main/resources/sql/sql-map.xml +++ b/apps/mailreader/src/main/resources/sql/sql-map.xml @@ -1,10 +1,10 @@ + "http://ibatis.apache.org/dtd/sql-map-2.dtd"> + type="mailreader2.AppData"/> SELECT pk_registration AS registration_key, fk_locale AS locale_key, - username, password, fullname, email_from, email_replyto + username, password, fullname, email_from, email_replyto FROM registration WHERE pk_registration=#registration_key#; @@ -45,7 +45,7 @@ UPDATE registration SET fk_locale=#locale_key#, username=#username#, password=#password#, fullname=#fullname#, - email_from=#email_from#, email_replyto=#email_replyto# + email_from=#email_from#, email_replyto=#email_replyto# WHERE pk_registration=#registration_key#; @@ -53,36 +53,36 @@ SELECT COUNT(*) FROM subscription WHERE fk_registration=#registration_key# - AND subscription_host=#subscription_host#; + AND subscription_host=#subscription_host#; INSERT INTO subscription - (pk_subscription, fk_registration, fk_protocol, subscription_host, host_user, host_pass, host_auto) + (pk_subscription, fk_registration, fk_protocol, subscription_host, host_user, host_pass, host_auto) VALUES (#subscription_key#, #registration_key#, #protocol_key#, #subscription_host#, - #host_user#, #host_pass#, #host_auto#); + #host_user#, #host_pass#, #host_auto#); UPDATE subscription SET fk_registration=#registration_key#, fk_protocol=#protocol_key#, - subscription_host=#subscription_host#, host_user=#host_user#, host_pass=#host_pass#, host_auto=#host_auto# + subscription_host=#subscription_host#, host_user=#host_user#, host_pass=#host_pass#, host_auto=#host_auto# WHERE pk_subscription=#subscription_key#; diff --git a/apps/mailreader/src/main/resources/struts.xml b/apps/mailreader/src/main/resources/struts.xml index b2e772a51..2ab2a7bda 100644 --- a/apps/mailreader/src/main/resources/struts.xml +++ b/apps/mailreader/src/main/resources/struts.xml @@ -1,112 +1,169 @@ + "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" + "http://struts.apache.org/dtds/struts-2.0.dtd"> - + - - + + - - + + - + - - + + - - + + /pages/Error.jsp /pages/Error.jsp - Logon!input + Logon + Welcome + MainMenu + ChangePassword - - - - /pages/Welcome.jsp - - - - - /pages/Logon.jsp - Welcome - MainMenu - ChangePassword - + + + + - /pages/ChangePassword.jsp - - - - /pages/MainMenu.jsp - - - - /pages/Registration.jsp - MainMenu - - - - - - /pages/Registration.jsp - MainMenu - - - - - /pages/Subscription.jsp - Registration!input - - - - - /pages/Subscription.jsp - Registration!input - + /pages/ChangePassword.jsp Welcome + + /pages/Logon.jsp + + + + + /pages/MainMenu.jsp + + - /pages/tour.html + /pages/Tour.html + + + + + /pages/Welcome.jsp + + + + + /pages/registration.jsp + MainMenu + + + + /pages/registration.jsp + MainMenu + + + + + /pages/registration.jsp + + + + + /pages/Logon.jsp + MainMenu + + + + + + + + + /pages/subscription.jsp + + + + /pages/subscription.jsp + + + + /pages/subscription.jsp + + + + /pages/subscription.jsp + + Input + /registration + + + + + + diff --git a/apps/mailreader/src/main/webapp/WEB-INF/web.xml b/apps/mailreader/src/main/webapp/WEB-INF/web.xml index 72571326a..758310ab4 100644 --- a/apps/mailreader/src/main/webapp/WEB-INF/web.xml +++ b/apps/mailreader/src/main/webapp/WEB-INF/web.xml @@ -33,7 +33,7 @@ mailreader2.ApplicationListener - + index.html diff --git a/apps/mailreader/src/main/webapp/pages/ChangePassword.jsp b/apps/mailreader/src/main/webapp/pages/ChangePassword.jsp index 7d9861f49..d7bd5015c 100644 --- a/apps/mailreader/src/main/webapp/pages/ChangePassword.jsp +++ b/apps/mailreader/src/main/webapp/pages/ChangePassword.jsp @@ -16,7 +16,7 @@

    - "> + ">

    diff --git a/apps/mailreader/src/main/webapp/pages/Error.jsp b/apps/mailreader/src/main/webapp/pages/Error.jsp index 1d955f417..fbdc687f8 100644 --- a/apps/mailreader/src/main/webapp/pages/Error.jsp +++ b/apps/mailreader/src/main/webapp/pages/Error.jsp @@ -20,7 +20,7 @@

    Error Message

    - +

    diff --git a/apps/mailreader/src/main/webapp/pages/Logon.jsp b/apps/mailreader/src/main/webapp/pages/Logon.jsp index dce7f972b..b3e9102bd 100644 --- a/apps/mailreader/src/main/webapp/pages/Logon.jsp +++ b/apps/mailreader/src/main/webapp/pages/Logon.jsp @@ -9,10 +9,10 @@ type="text/css"/> - + - - + + @@ -21,8 +21,8 @@ - + diff --git a/apps/mailreader/src/main/webapp/pages/MainMenu.jsp b/apps/mailreader/src/main/webapp/pages/MainMenu.jsp index 9b958ecca..df6d75cf2 100644 --- a/apps/mailreader/src/main/webapp/pages/MainMenu.jsp +++ b/apps/mailreader/src/main/webapp/pages/MainMenu.jsp @@ -13,13 +13,21 @@

    + + + diff --git a/apps/mailreader/src/main/webapp/pages/Registration.jsp b/apps/mailreader/src/main/webapp/pages/Registration.jsp index 0889f3eff..9889114ca 100644 --- a/apps/mailreader/src/main/webapp/pages/Registration.jsp +++ b/apps/mailreader/src/main/webapp/pages/Registration.jsp @@ -14,10 +14,10 @@ type="text/css"/> - + - + @@ -33,29 +33,29 @@ + name="user.fullName"/> + name="user.fromAddress"/> + name="user.replyToAddress"/> - + + onclick="form.onsubmit=null"/> - + @@ -100,23 +100,27 @@ - - "> + + + + - +   - "> + + + + - - + - "> + + diff --git a/apps/mailreader/src/main/webapp/pages/Subscription.jsp b/apps/mailreader/src/main/webapp/pages/Subscription.jsp index cb48937a3..abf868304 100644 --- a/apps/mailreader/src/main/webapp/pages/Subscription.jsp +++ b/apps/mailreader/src/main/webapp/pages/Subscription.jsp @@ -17,10 +17,10 @@ type="text/css"/> - + - + @@ -35,31 +35,31 @@ + name="subscription.username"/> + name="subscription.password"/> + name="subscription.type"/> + name="subscription.autoConnect"/> + name="subscription.username"/> + name="subscription.password"/> + name="subscription.type" list="types"/> + name="subscription.autoConnect"/> - + diff --git a/apps/mailreader/src/main/webapp/pages/Welcome.jsp b/apps/mailreader/src/main/webapp/pages/Welcome.jsp index 7389acda1..85e25cac2 100644 --- a/apps/mailreader/src/main/webapp/pages/Welcome.jsp +++ b/apps/mailreader/src/main/webapp/pages/Welcome.jsp @@ -14,10 +14,14 @@

      -
    • ">
    • -
    • ">
    • +
    • + + +
    • +
    • + + +

    Language Options

    @@ -29,25 +33,31 @@ English
  • - + ja - ">Japanese -
  • +
    + Japanese +
  • - - - ">Russian + + ru + + Russian

  • -

    - " - alt=""/> -

    +

    + + " + alt=""/> + +

    -

    ">

    +

    + +

    diff --git a/apps/mailreader/src/main/webapp/pages/tour.html b/apps/mailreader/src/main/webapp/pages/tour.html index c27e9e85b..a6ceb4682 100644 --- a/apps/mailreader/src/main/webapp/pages/tour.html +++ b/apps/mailreader/src/main/webapp/pages/tour.html @@ -15,12 +15,12 @@

    - This article is meant to introduce a new user to Apache Struts 2 by + This article is meant to introduce a new user to Apache Struts 2 by "walking through" a simple, but functional, application. - The article includes code snippets, but for the best result, you might - want to install the MailReader application on your own development + The article includes code snippets, but for the best result, you might + want to install the MailReader application on your own development workstation and follow along. - Of course, the full source code to the MailReader is included in the + Of course, the full source code to the MailReader is included in the distribution. @@ -29,7 +29,7 @@

    The tour assumes the reader has a basic understanding of the Java - language, JavaBeans, web applications, and JavaServer Pages. For + language, JavaBeans, web applications, and JavaServer Pages. For background on these technologies, see the Key Technologies Primer. @@ -179,42 +179,42 @@


    web.xml - The Web Application Deployment Descriptor
    <?xml version="1.0" encoding="ISO-8859-1"?>
    -<!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>
    +    <!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>
     
    -  <display-name>Struts 2 MailReader</display-name>
    +    <display-name>Struts 2 MailReader</display-name>
     
    -  <filter>
    -    <filter-name>struts2</filter-name>
    -    <filter-class>
    -      org.apache.struts2.dispatcher.FilterDispatcher
    -    </filter-class>
    -   </filter>
    +    <filter>
    +        <filter-name>struts2</filter-name>
    +        <filter-class>
    +        org.apache.struts2.dispatcher.FilterDispatcher
    +        </filter-class>
    +        </filter>
     
    -  <filter-mapping>
    +    <filter-mapping>
         <filter-name>struts2</filter-name>
         <url-pattern>/*</url-pattern>
    -  </filter-mapping>
    +    </filter-mapping>
     
    -  <listener>
    +    <listener>
         <listener-class>
    -      org.springframework.web.context.ContextLoaderListener
    +    org.springframework.web.context.ContextLoaderListener
         </listener-class>
    -  </listener>
    +    </listener>
     
    -  <!-- Application Listener for MailReader database -->
    -  <listener>
    +    <!-- Application Listener for MailReader database -->
    +    <listener>
         <listener-class>
    -      mailreader2.ApplicationListener
    +    mailreader2.ApplicationListener
         </listener-class>
    -  </listener>
    +    </listener>
     
    -  <welcome-file-list>
    +    <welcome-file-list>
         <welcome-file>index.html</welcome-file>
    -  </welcome-file-list>
    +    </welcome-file-list>
     
    -  </web-app>
    + </web-app>

    @@ -246,10 +246,10 @@

    The actions are listed in one or more XML configuration files, the default configuration file being named "struts.xml". - When the application loads, the struts.xml, and any other files - it includes, are parsed, and the framework creates a set of - configuration objects. - Among other things, the configuration maps a request for a certain + When the application loads, the struts.xml, and any other files + it includes, are parsed, and the framework creates a set of + configuration objects. + Among other things, the configuration maps a request for a certain page to a certain action mapping.

    @@ -271,12 +271,12 @@
    MailReader's index.html
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    -<html><head>
    -  <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.do">
    -  </head>
    -  <body>
    +    <html><head>
    +    <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.do">
    +    </head>
    +    <body>
         <p>Loading ...</p>
    -</body></html>
    + </body></html>

    @@ -290,7 +290,7 @@

    When the client requests "Welcome.do", the request is passed to the "struts2" FilterDispatcher (that we registered in the web.xml file). - The FilterDispatcher retrieves the appropriate action mapping from the + The FilterDispatcher retrieves the appropriate action mapping from the configuration. If we just wanted to forward to the Welcome page, we could use a simple configuration element. @@ -298,8 +298,8 @@


    A simple "forward thru" action element
    <action name="Welcome">
    -  <result>/pages/Welcome.jsp</result>
    -</action>
    + <result>/pages/Welcome.jsp</result> + </action>

    @@ -356,8 +356,8 @@

    The Struts configuration lets us separate concerns and "say it once". - The configuration helps us "normalize" an application, - in much the same way we normalize a database schema. + The configuration helps us "normalize" an application, + in much the same way we normalize a database schema.


    @@ -392,33 +392,33 @@
    The Welcome Action class
    package mailreader2;
    -public class Welcome extends MailreaderSupport {
    +    public class Welcome extends MailreaderSupport {
     
    -  public String execute() {
    +    public String execute() {
     
         // Confirm message resources loaded
         String message = getText(Constants.ERROR_DATABASE_MISSING);
         if (Constants.ERROR_DATABASE_MISSING.equals(message)) {
    -      addActionError(Constants.ERROR_MESSAGES_NOT_LOADED);
    +    addActionError(Constants.ERROR_MESSAGES_NOT_LOADED);
         }
     
         // Confirm database loaded
         if (null==getDatabase()) {
    -      addActionError(Constants.ERROR_DATABASE_NOT_LOADED);
    +    addActionError(Constants.ERROR_DATABASE_NOT_LOADED);
         }
     
         if (hasErrors()) {
    -      return ERROR;
    +    return ERROR;
         }
         else {
    -      return SUCCESS;
    +    return SUCCESS;
         }
    -  }
    -}
    + } + }

    - Several common result names are predefined, + Several common result names are predefined, including ERROR, SUCCESS, LOGIN, NONE, and INPUT, so that these tokens can be used consistently across Struts 2 applications.

    @@ -437,10 +437,10 @@ public class Welcome extends MailreaderSupport {
    MailReader's global-result element
     <global-results>
    -  <result name="error">/pages/Error.jsp</result>
    -  <result name="invalid.token">/pages/Error.jsp</result>
    -  <result name="login" type="redirect-action">Logon!input</result>
    -</global-results>
    + <result name="error">/pages/Error.jsp</result> + <result name="invalid.token">/pages/Error.jsp</result> + <result name="login" type="redirect-action">Logon!input</result> + </global-results>

    @@ -466,10 +466,10 @@ public class Welcome extends MailreaderSupport {


    mailreader2.ApplicationListener
     <listener>
    -  <listener-class>
    +    <listener-class>
         mailreader2.ApplicationListener
    -  </listener-class>
    -</listener>
    + </listener-class> + </listener>

    @@ -492,14 +492,14 @@ public class Welcome extends MailreaderSupport {


    The "seed" user element from the MailReader database.xml
    <user username="user" fromAddress="John.User@somewhere.com"
    -  fullName="John Q. User" password="pass">
    +    fullName="John Q. User" password="pass">
         <subscription host="mail.hotmail.com" autoConnect="false"
    -      password="bar" type="pop3" username="user1234">
    +    password="bar" type="pop3" username="user1234">
         </subscription>
         <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
    -      type="imap" username="jquser">
    +    type="imap" username="jquser">
         </subscription>
    -</user>
    + </user>

    @@ -521,7 +521,7 @@ public class Welcome extends MailreaderSupport {


    struts.properties
    struts.custom.i18n.resources = resources
    -struts.action.extension = do
    + struts.action.extension = do

    @@ -530,23 +530,23 @@ struts.action.extension = do for a Resource Bundle named "resources.properties". The bundle might be embedded in a JAR, or found in the "WEB-INF/classes" folder, or anywhere else on the runtime classpath. - In the MailReader, we keep the original bundle in the - source tree under "src/main/". When the application is built, the - properties files are copied to "WEB-INF/classes", so + In the MailReader, we keep the original bundle in the + source tree under "src/main/". When the application is built, the + properties files are copied to "WEB-INF/classes", so that they are on the Java classpath.


    Message Resource entries used by the Welcome page
    index.heading=MailReader Application Options
    -index.logon=Log on to the MailReader Application
    -index.registration=Register with the MailReader Application
    -index.title=MailReader Demonstration Application
    -index.tour=A Walking Tour of the MailReader Demonstration Application
    + index.logon=Log on to the MailReader Application + index.registration=Register with the MailReader Application + index.title=MailReader Demonstration Application + index.tour=A Walking Tour of the MailReader Demonstration Application

    - If you change a message in the resource, and then rebuild and reload the + If you change a message in the resource, and then rebuild and reload the application, the change will appear throughout the application. If you provide message resources for additional locales, you can localize your application. @@ -562,45 +562,45 @@ struts.action.extension = do


    Welcome.jsp
    <%@ page contentType="text/html; charset=UTF-8" %>
    -<%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    -  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +    <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    +    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    -  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
         <head>
    -      <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    -      <title><s:text name="index.title"/></title>
    -      <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    -      type="text/css"/>
    +    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    +    <title><s:text name="index.title"/></title>
    +    <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    +    type="text/css"/>
         </head>
     
         <body>
    -      <h3><s:text name="index.heading"/></h3>
    +    <h3><s:text name="index.heading"/></h3>
     
    -      <ul>
    -        <li><a href="<s:url action="Registration!input"/>"><s:text
    -          name="index.registration"/></a></li>
    -        <li><a href="<s:url action="Logon!input"/>"><s:text
    -          name="index.logon"/></a></li>
    -      </ul>
    +    <ul>
    +    <li><a href="<s:url action="Registration!input"/>"><s:text
    +    name="index.registration"/></a></li>
    +    <li><a href="<s:url action="Logon!input"/>"><s:text
    +    name="index.logon"/></a></li>
    +    </ul>
     
    -      <h3>Language Options</h3>
    -      <ul>
    -        <li><a href="<s:url action="Welcome?request_locale=en"/>">English</a></li>
    -        <li><a href="<s:url action="Welcome?request_locale=ja"/>">Japanese</a></li>
    -        <li><a href="<s:url action="Welcome?request_locale=ru"/>">Russian</a></li>
    -      </ul>
    +    <h3>Language Options</h3>
    +    <ul>
    +    <li><a href="<s:url action="Welcome?request_locale=en"/>">English</a></li>
    +    <li><a href="<s:url action="Welcome?request_locale=ja"/>">Japanese</a></li>
    +    <li><a href="<s:url action="Welcome?request_locale=ru"/>">Russian</a></li>
    +    </ul>
     
         <hr />
     
         <p><s:i18n name="alternate">
         <img src="<s:text name="struts.logo.path"/>"
    -      alt="<s:text name="struts.logo.alt"/>"/>
    +    alt="<s:text name="struts.logo.alt"/>"/>
         </s:i18n></p>
     
         <p><a href="<s:url action="Tour" />"><s:text name="index.tour"/></a></p>
     
    -  </body>
    -</html>
    + </body> + </html>

    @@ -707,28 +707,28 @@ struts.action.extension = do


    Login.jsp
    <%@ page contentType="text/html; charset=UTF-8" %>
    -  <%@ taglib prefix="s" uri="http://struts.apache.org/tags"  %>
    -  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +    <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    +    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    -  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    -  <head>
    +    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +    <head>
         <title><s:text name="logon.title"/></title>
    -      <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    -        type="text/css"/>
    -  </head>
    -  <body onLoad="self.focus();document.Logon.username.focus()">
    +    <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    +    type="text/css"/>
    +    </head>
    +    <body onLoad="self.focus();document.Logon.username.focus()">
         <s:actionerror/>
         <s:form method="POST" validate="true">
    -      <s:textfield label="%{getText('username')}" name="username"/>
    -      <s:password label="%{getText('password')}" name="password"/>
    -      <s:submit value="%{getText('button.save')}"/>
    -      <s:reset value="%{getText('button.reset')}"/>
    -      <s:submit action="Logon!cancel" onclick="form.onsubmit=null"
    -        value="%{getText('button.cancel')}"/>
    +    <s:textfield label="%{getText('username')}" name="username"/>
    +    <s:password label="%{getText('password')}" name="password"/>
    +    <s:submit value="%{getText('button.save')}"/>
    +    <s:reset value="%{getText('button.reset')}"/>
    +    <s:submit action="Logon!cancel" onclick="form.onsubmit=null"
    +    value="%{getText('button.cancel')}"/>
         </s:form>
         <jsp:include page="Footer.jsp"/>
    -  </body>
    -</html>
    + </body> + </html>

    @@ -795,13 +795,13 @@ struts.action.extension = do


    <tr>
    -  <td class="tdLabel">
    +    <td class="tdLabel">
         <label for="Logon_username" class="label">Username:</label>
    -  </td>
    -  <td>
    +    </td>
    +    <td>
         <input type="text" name="username" value="" id="Logon_username"/>
    -  </td>
    -</tr>
    + </td> + </tr>

    @@ -814,12 +814,12 @@ struts.action.extension = do


    <#if (actionErrors?exists && actionErrors?size > 0)>
    -  <ul>
    +    <ul>
         <#list actionErrors as error>
    -      <li><span class="errorMessage">${error}</span></li>
    +    <li><span class="errorMessage">${error}</span></li>
         </#list>
    -  </ul>
    -</#if>
    + </ul> + </#if>

    @@ -830,12 +830,12 @@ struts.action.extension = do


    <#if (actionErrors?exists && actionErrors?size > 0)>
    -  <table>
    +    <table>
         <#list actionErrors as error>
    -      <tr><td><span class="errorMessage">${error}</span></td></tr>
    +    <tr><td><span class="errorMessage">${error}</span></td></tr>
         </#list>
    -  </table>
    -</#if>
    + </table> + </#if>

    @@ -918,29 +918,29 @@ struts.action.extension = do


    Validation file for Logon Action
    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
    -  "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
    -<validators>
    -  <field name="username">
    +    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
    +    <validators>
    +    <field name="username">
         <field-validator type="requiredstring">
         <message key="error.username.required"/>
    -  </field-validator>
    -  </field>
    -  <field name="password">
    +    </field-validator>
    +    </field>
    +    <field name="password">
         <field-validator type="requiredstring">
         <message key="error.password.required"/>
         </field-validator>
    -  </field>
    -</validators>
    +    </field>
    +    </validators>
     

    - You may note that the DTD refers to "XWork". - - Open Symphony XWork - is a generic command-pattern framework that can be used outside of a - web environment. In practice, Struts 2 is a web-based extension of the - XWork framework. + You may note that the DTD refers to "XWork". + + Open Symphony XWork + is a generic command-pattern framework that can be used outside of a + web environment. In practice, Struts 2 is a web-based extension of the + XWork framework.

    @@ -978,19 +978,19 @@ struts.action.extension = do


    Logon.java
    package mailreader2;
    -import org.apache.struts.apps.mailreader.dao.User;
    -public final class Logon extends MailreaderSupport {
    -public String execute() throws ExpiredPasswordException {
    -  User user = findUser(getUsername(), getPassword());
    -  if (user != null) {
    +    import org.apache.struts.apps.mailreader.dao.User;
    +    public final class Logon extends MailreaderSupport {
    +    public String execute() throws ExpiredPasswordException {
    +    User user = findUser(getUsername(), getPassword());
    +    if (user != null) {
         setUser(user);
    -  }
    -  if (hasErrors()) {
    +    }
    +    if (hasErrors()) {
         return INPUT;
    -  }
    +    }
         return SUCCESS;
    -  }
    -}
    + } + }

    @@ -1005,7 +1005,7 @@ public String execute() throws ExpiredPasswordException {

    Let's look at the relevant properties and methods from MailreaderSupport - and another base class, ActionSupport, namely + and another base class, ActionSupport, namely "getUsername", "getPassword", "findUser", "setUser", and "hasErrors".

    @@ -1029,20 +1029,20 @@ public String execute() throws ExpiredPasswordException {
    MailreaderSupport.getUsername() and getPassword()
    private String username = null;
    -public String getUsername() {
    -  return this.username;
    -}
    -public void setUsername(String username) {
    -  this.username = username;
    -}
    +    public String getUsername() {
    +    return this.username;
    +    }
    +    public void setUsername(String username) {
    +    this.username = username;
    +    }
     
    -private String password = null;
    -public String getPassword() {
    -  return this.password;
    -}
    -public void setPassword(String password) {
    -  this.password = password;
    -}
    + private String password = null; + public String getPassword() { + return this.password; + } + public void setPassword(String password) { + this.password = password; + }

    @@ -1053,16 +1053,16 @@ public void setPassword(String password) {


    MailreaderSupport.findUser
    public User findUser(String username, String password)
    -  throws ExpiredPasswordException {
    -  User user = getDatabase().findUser(username);
    -  if ((user != null) && !user.getPassword().equals(password)) {
    +    throws ExpiredPasswordException {
    +    User user = getDatabase().findUser(username);
    +    if ((user != null) && !user.getPassword().equals(password)) {
         user = null;
    -  }
    -  if (user == null) {
    +    }
    +    if (user == null) {
         this.addFieldError("password", getText("error.password.mismatch"));
    -  }
    -  return user;
    -}
    + } + return user; + }

    @@ -1090,18 +1090,18 @@ public void setPassword(String password) { When "findUser" returns, the Logon Action looks to see if a valid (non-null) User object is returned. A valid User is passed to the User property. - Although it is still a JavaBean property, + Although it is still a JavaBean property, the User property is not implemented in quite the same way as Username and Password.


    MailreaderSupport.setUser
    public User getUser() {
    -  return (User) getSession().get(Constants.USER_KEY);
    -}
    -public void setUser(User user) {
    -  getSession().put(Constants.USER_KEY, user);
    -}
    + return (User) getSession().get(Constants.USER_KEY); + } + public void setUser(User user) { + getSession().put(Constants.USER_KEY, user); + }

    @@ -1109,16 +1109,16 @@ public void setUser(User user) { "setUser" passes it to a Session property.

    -
    +
    MailreaderSupport.getSession() and setSession()
    private Map session;
    -public Map getSession() {
    -  return session;
    +    public Map getSession() {
    +    return session;
     
    -public void setSession(Map value) {
    -  session = value;
    -}
    -
    + public void setSession(Map value) { + session = value; + } +

    To look at the MailreaderSupport class, you would think the Session property is a plain-old Map. @@ -1159,8 +1159,8 @@ public void setSession(Map value) {

    if (action instanceof SessionAware) {
    -  ((SessionAware) action).setSession(context.getSession());
    -}
    + ((SessionAware) action).setSession(context.getSession()); + }

    The framework uses these "Interceptor" classes to create a front controller @@ -1217,7 +1217,7 @@ public void setSession(Map value) {


    Best Practice:
    -

    "Use a base class to define common functionality."

    +

    "Use a base class to define common functionality."


    @@ -1242,22 +1242,22 @@ public void setSession(Map value) {
    struts.xml Logon
    -
    <action name="Logon" class="mailreader2.Logon">
    -  <result name="input">/pages/Logon.jsp</result>
    -  <result name="cancel" type="redirect-action">Welcome</result>
    -  <result type="redirect-action">MainMenu</result>
    -  <result name="expired" type="chain">ChangePassword</result>
    -  <exception-mapping
    +
    <action name="Logon" class="mailreader2.registration.Retrieve">
    +    <result name="input">/pages/Logon.jsp</result>
    +    <result name="cancel" type="redirect-action">Welcome</result>
    +    <result type="redirect-action">MainMenu</result>
    +    <result name="expired" type="chain">ChangePassword</result>
    +    <exception-mapping
         exception="org.apache.struts.apps.mailreader.dao.ExpiredPasswordException"
    -  result="expired"/>
    -  <interceptor-ref name="guest"/>
    -</action>
    + result="expired"/> + <interceptor-ref name="guest"/> + </action>

    In the Logon action element, the first result element is named "input". If validation or authentification fail, - the Action class will return "input" and the framework will transfer control to the + the Action class will return "input" and the framework will transfer control to the "Logon.jsp" page.

    @@ -1290,10 +1290,10 @@ public void setSession(Map value) {
    struts.xml exception-mapping
    <global-exception-mappings>
    -  <exception-mapping
    +    <exception-mapping
         result="error"
         exception="java.lang.Exception"/>
    -</global-exception-mappings>
    + </global-exception-mappings>

    @@ -1308,34 +1308,34 @@ public void setSession(Map value) {


    Error.jsp
    <%@ page contentType="text/html; charset=UTF-8" %>
    -<%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    -  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +    <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    +    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    -  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    -  <head>
    +    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +    <head>
         <title>Unexpected Error</title>
    -  </head>
    -  <body>
    +    </head>
    +    <body>
         <h2>An unexpected error has occured</h2>
         <p>
    -      Please report this error to your system administrator
    -      or appropriate technical support personnel.
    -      Thank you for your cooperation.
    +    Please report this error to your system administrator
    +    or appropriate technical support personnel.
    +    Thank you for your cooperation.
         </p>
         <hr />
         <h3>Error Message</h3>
         <s:actionerror />
         <p>
    -      <s:property value="%{exception.message}"/>
    +    <s:property value="%{exception.message}"/>
         </p>
         <hr />
         <h3>Technical Details</h3>
         <p>
    -      <s:property value="%{exceptionStack}"/>
    +    <s:property value="%{exceptionStack}"/>
         </p>
         <jsp:include page="Footer.jsp"/>
    -  </body>
    -</html>
    + </body> + </html>

    @@ -1362,27 +1362,27 @@ public void setSession(Map value) {


    mailreader2.AuthenticationInterceptor
    package mailreader2;
    -import com.opensymphony.xwork2.interceptor.Interceptor;
    -import com.opensymphony.xwork2.ActionInvocation;
    -import com.opensymphony.xwork2.Action;
    -import java.util.Map;
    -import org.apache.struts.apps.mailreader.dao.User;
    +    import com.opensymphony.xwork2.interceptor.Interceptor;
    +    import com.opensymphony.xwork2.ActionInvocation;
    +    import com.opensymphony.xwork2.Action;
    +    import java.util.Map;
    +    import org.apache.struts.apps.mailreader.dao.User;
     
    -public class AuthenticationInterceptor implements Interceptor {
    -  public void destroy () {}
    -  public void init() {}
    -  public String intercept(ActionInvocation actionInvocation) throws Exception {
    +    public class AuthenticationInterceptor implements Interceptor {
    +    public void destroy () {}
    +    public void init() {}
    +    public String intercept(ActionInvocation actionInvocation) throws Exception {
         Map session = actionInvocation.getInvocationContext().getSession();
         User user = (User) session.get(Constants.USER_KEY);
         boolean isAuthenticated = (null!=user) && (null!=user.getDatabase());
         if (isAuthenticated) {
    -      return actionInvocation.invoke();
    +    return actionInvocation.invoke();
         }
         else {
    -      return Action.LOGIN;
    +    return Action.LOGIN;
         }
    -  }
    -}
    + } + }

    @@ -1402,29 +1402,29 @@ public class AuthenticationInterceptor implements Interceptor {


    struts.xml interceptors
    <interceptors>
    -  <interceptor name="authentication"
    -               class="mailreader2.AuthenticationInterceptor"/>
    -  <interceptor-stack name="user" >
    -      <interceptor-ref name="authentication" />
    -      <interceptor-ref name="defaultStack"/>
    -  </interceptor-stack>
    -  <interceptor-stack name="user-submit" >
    -      <interceptor-ref name="token-session" />
    -      <interceptor-ref name="user"/>
    -  </interceptor-stack>
    -  <interceptor-stack name="guest" >
    -      <interceptor-ref name="defaultStack"/>
    -  </interceptor-stack>
    -  <interceptor-stack name="guest-submit" >
    -      <interceptor-ref name="token-session" />
    -      <interceptor-ref name="guest"/>
    -  </interceptor-stack>
    -</interceptors>
    -<default-interceptor-ref name="user"/>
    + <interceptor name="authentication" + class="mailreader2.AuthenticationInterceptor"/> + <interceptor-stack name="user" > + <interceptor-ref name="authentication" /> + <interceptor-ref name="defaultStack"/> + </interceptor-stack> + <interceptor-stack name="user-submit" > + <interceptor-ref name="token-session" /> + <interceptor-ref name="user"/> + </interceptor-stack> + <interceptor-stack name="guest" > + <interceptor-ref name="defaultStack"/> + </interceptor-stack> + <interceptor-stack name="guest-submit" > + <interceptor-ref name="token-session" /> + <interceptor-ref name="guest"/> + </interceptor-stack> + </interceptors> + <default-interceptor-ref name="user"/>

    - The user stacks require that the client be authenticated. + The user stacks require that the client be authenticated. In other words, that a User object is present in the session. The actions using a guest stack can be accessed by any client. The -submit versions of each can be used with actions @@ -1434,7 +1434,7 @@ public class AuthenticationInterceptor implements Interceptor {

    Double Submits

    - A common problem with designing web applications is that users are impatient + A common problem with designing web applications is that users are impatient and response times can vary. Sometimes, people will press a submit button a second time. When this happens, the browser submits the request again, @@ -1469,11 +1469,11 @@ public class AuthenticationInterceptor implements Interceptor {

    Because the default interceptor stack will now authenticate the client, - we need to specify the standard "defaultStack" for the three - "guest actions", Welcome, Logon, and Register. - Requiring authentification by default is the better practice, since it - means that we won't forget to enable it when creating new actions. - Meanwhile, those pesky users will ensure that we don't forget to disable + we need to specify the standard "defaultStack" for the three + "guest actions", Welcome, Logon, and Register. + Requiring authentification by default is the better practice, since it + means that we won't forget to enable it when creating new actions. + Meanwhile, those pesky users will ensure that we don't forget to disable authentification for "guest" services.

    @@ -1508,30 +1508,30 @@ public class AuthenticationInterceptor implements Interceptor {
    MainMenu.jsp
    <%@ page contentType="text/html; charset=UTF-8" %>
    -<%@ taglib prefix="s" uri="http://struts.apache.org/tags"  %>
    -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    -  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    -  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    -  <head>
    +    <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    +    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    +    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +    <head>
         <title><s:text name="mainMenu.title"/></title>
    -      <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    -      type="text/css"/>
    -  </head>
    +    <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    +    type="text/css"/>
    +    </head>
     
    -  <body>
    -  <h3><s:text name="mainMenu.heading"/> <s:property
    +    <body>
    +    <h3><s:text name="mainMenu.heading"/> <s:property
         value="user.fullName"/></h3>
    -  <ul>
    +    <ul>
         <li><a href="<s:url action="Registration!input" />">
    -        <s:text name="mainMenu.registration"/>
    -      </a>
    +    <s:text name="mainMenu.registration"/>
    +    </a>
         </li>
         <li><a href="<s:url action="Logoff" />">
    -      <s:text name="mainMenu.logoff"/>
    -      </a>
    +    <s:text name="mainMenu.logoff"/>
    +    </a>
         </ul>
    -  </body>
    -</html>
    + </body> + </html>

    @@ -1576,19 +1576,19 @@ public class AuthenticationInterceptor implements Interceptor { to make it appears as though there are two distinct pages.

    -
    +
    Registration.jsp - head element
    <head>
    -  <s:if test="task=='Create'">
    +    <s:if test="task=='Create'">
         <title><s:text name="registration.title.create"/></title>
    -  </s:if>
    -  <s:if test="task=='Edit'">
    +    </s:if>
    +    <s:if test="task=='Edit'">
         <title><s:text name="registration.title.edit"/></title>
    -  </s:if>
    -  <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    +    </s:if>
    +    <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
         type="text/css"/>
    -</head>
    -
    + </head> +

    For example, if client is editing the form (task == 'Edit'), @@ -1605,7 +1605,7 @@ public class AuthenticationInterceptor implements Interceptor { The "test" tag is a convenient way to express presentation logic within your pages. Customized pages help to prevent user error, - and dynamic customization reduces the number of server pages your + and dynamic customization reduces the number of server pages your application needs to maintain, among other benefits.

    @@ -1621,13 +1621,13 @@ public class AuthenticationInterceptor implements Interceptor {
    <s:if test="task == 'Edit'">
    -  <div align="center">
    +    <div align="center">
         <h3><s:text name="heading.subscriptions"/></h3>
    -  </div>
    +    </div>
         <!-- ... -->
    -  </s:if>
    -<jsp:include page="Footer.jsp"/>
    -</body></html>
    + </s:if> + <jsp:include page="Footer.jsp"/> + </body></html>

    @@ -1650,136 +1650,142 @@ public class AuthenticationInterceptor implements Interceptor { So to display each subscription, we have to reach into the user object, and loop through the members of the subscription collection. Using the iterator tag, you can code it the way it sounds. -

    +


    Using iterator to list the Subscriptions
    <s:iterator value="user.subscriptions">
    -  <tr>
    +    <tr>
         <td align="left">
    -      <s:property value="host"/>
    +    <s:property value="host"/>
         </td>
         <td align="left">
    -       <s:property value="username"/>
    -   </td>
    -  <td align="center">
    -      <s:property value="type"/>
    -  </td>
    -  <td align="center">
    -     <s:property value="autoConnect"/>
    -  </td>
    -  <td align="center">
    -    <a href="<s:url action="Subscription!delete"><s:param name="host" value="host"/></s:url>">
    -      <s:text name="registration.deleteSubscription"/>
    +    <s:property value="username"/>
    +    </td>
    +    <td align="center">
    +    <s:property value="type"/>
    +    </td>
    +    <td align="center">
    +    <s:property value="autoConnect"/>
    +    </td>
    +    <td align="center">
    +    <a href="<s:url action="Subscription!delete"><s:param name="host"
    +    value="host"/></s:url>">
    +    <s:text name="registration.deleteSubscription"/>
         </a> 
    -    <a href="<s:url action="Subscription!edit"><s:param name="host" value="host"/></s:url>">
    -      <s:text name="registration.editSubscription"/>
    -     </a>
    -   </td>
    - </tr>
    -</s:iterator>
    + <a href="<s:url action="Subscription!edit"><s:param name="host" + value="host"/></s:url>"> + <s:text name="registration.editSubscription"/> + </a> + </td> + </tr> + </s:iterator>

    When the iterator renders, it generates a list of Subscriptions for the current User.

    -
    +
    -
    -

    Current Subscriptions

    -
    +
    +

    Current Subscriptions

    +
    - - - - +
    - Host Name - - User Name -
    + + + - - - - - - - - + + + + + + + + - - - - - - - - - - -
    + Host Name + + User Name + - Server Type - - Auto - - Action -
    - mail.hotmail.com - - user1234 - - pop3 - + Server Type + + Auto + + Action +
    + mail.hotmail.com + + user1234 + + pop3 + - false - - - Delete - -   - - Edit - -
    - mail.yahoo.com - - jquser - - imap - - false - - - Delete - -   - - Edit - -
    - Add + + false + + + + Delete + +   + + Edit + + + + + + mail.yahoo.com + + + jquser + + + imap + + + false + + + + Delete + +   + + Edit + + + + +Add -
    +
    -

    - Now look back at the code used to generate this block. -

    -

    - Notice anything nifty? -

    -

    - How about that the markup between the iterator tag is - actually simpler than the markup that we would use to render one row of the table? -

    -

    - Instead of using a qualified reference like "value=user.subscription[0].host", - we use the simplest possible reference: "value=host". - We didn't have to define a local variable, and reference that local in the loop code. - The reference to each item in the list is automatically resolved, no fuss, no muss. -

    -

    - Nice trick! -

    +

    + Now look back at the code used to generate this block. +

    + +

    + Notice anything nifty? +

    + +

    + How about that the markup between the iterator tag is + actually simpler than the markup that we would use to render one row of the table? +

    + +

    + Instead of using a qualified reference like "value=user.subscription[0].host", + we use the simplest possible reference: "value=host". + We didn't have to define a local variable, and reference that local in the loop code. + The reference to each item in the list is automatically resolved, no fuss, no muss. +

    + +

    + Nice trick! +

    The secret to this magic is the value stack. @@ -1839,7 +1845,7 @@ public class AuthenticationInterceptor implements Interceptor { the value for the field is pushed onto the value stack. As a result, if the client enters text into an Integer field, the framework can still redisplay whatever was entered. - An invalid input value is not stored in the field (even if it could be). + An invalid input value is not stored in the field (even if it could be). The invalid input is pushed onto the stack for the scope of the request.

    @@ -1858,12 +1864,12 @@ public class AuthenticationInterceptor implements Interceptor {

    pager.legend = Displaying {current} of {count} items matching {criteria}.
    -...
    -<s:text name="pager.legend">
    +    ...
    +    <s:text name="pager.legend">
         <s:param name="current" value="42" />
         <s:param name="count" value="314" />
         <s:param name="criteria" value="Life, the Universe, and Everything" />
    -</s:text>
    + </s:text>

    In the case of an "url" tag, @@ -1872,15 +1878,15 @@ public class AuthenticationInterceptor implements Interceptor {

    
    -  <s:url action="Subscription!edit"><s:param name="host" value="host"/></s:url>">
    +    <s:url action="Subscription!edit"><s:param name="host" value="host"/></s:url>">
     

    - can render a hyperlink like this: + can render a hyperlink like this:

    
    -  <a href="/struts2-mailreader/Subscription!edit.do?host=mail.yahoo.com">Edit</a>
    +    <a href="/struts2-mailreader/Subscription!edit.do?host=mail.yahoo.com">Edit</a>
     
    @@ -1888,7 +1894,7 @@ public class AuthenticationInterceptor implements Interceptor {

    At the foot of the Register page is a link for adding a subscription. Let's wind up the tour by following the Add link and then logging off. - Like the link for creating a Registration, Add points to an "Edit" action, + Like the link for creating a Support, Add points to an "Edit" action, namely "EditSubscription".

    --> @@ -1910,13 +1916,13 @@ public class AuthenticationInterceptor implements Interceptor { and follow the bouncing ball from page to action to page.

    -
    +
    struts.xml Subscription element
    -
    <action name="Subscription" class="mailreader2.Subscription">
    -  <result name="input">/pages/Subscription.jsp</result>
    -  <result type="redirect-action">Registration!input</result>
    -</action>
    -
    +
    <action name="Subscription" class="mailreader2.SubscriptionSupport">
    +    <result name="input">/pages/Subscription.jsp</result>
    +    <result type="redirect-action">Registration!input</result>
    +    </action>
    +

    The Edit link specified the Subscription action, @@ -1927,23 +1933,23 @@ public class AuthenticationInterceptor implements Interceptor { The "alternate" execute methods are called alias methods.

    -
    +
    Subscription edit alias
    public String edit() {
    -  setTask(Constants.EDIT);>
    -  return find();
    -}
    +    setTask(Constants.EDIT);>
    +    return find();
    +    }
     
    -public String find() {
    -  org.apache.struts.apps.mailreader.dao.Subscription
    +    public String find() {
    +    org.apache.struts.apps.mailreader.dao.Subscription
         sub = findSubscription();
    -   if (sub == null) {
    -       return ERROR;
    -   }
    -   setSubscription(sub);
    -   return INPUT;
    -}
    -
    + if (sub == null) { + return ERROR; + } + setSubscription(sub); + return INPUT; + } +

    The "edit" alias has two responsibilities. @@ -1972,18 +1978,18 @@ public String find() { around the MailReader DAO classes.

    -
    +
    MailreaderSupport findSubscription()
    public Subscription findSubscription() {
         return findSubscription(getHost());
    -}
    +    }
     
    -public Subscription findSubscription(String host) {
    +    public Subscription findSubscription(String host) {
         Subscription subscription;
         subscription = getUser().findSubscription(host);
         return subscription;
    -}
    -
    + } +

    This code is very simple @@ -2007,17 +2013,18 @@ public Subscription findSubscription(String host) { to ensure that we are passed a Host parameter.

    -
    +
    Subscription-validation.xml
    -
    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
    -<validators>
    -  <field name="host">
    +
    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
    +    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
    +    <validators>
    +    <field name="host">
         <field-validator type="requiredstring">
    -        <message key="error.host.required"/>
    +    <message key="error.host.required"/>
         </field-validator>
    -  </field>
    -</validators>
    -
    + </field> + </validators>
    +

    By keeping routine sety precautions out of the Action class, @@ -2029,75 +2036,75 @@ public Subscription findSubscription(String host) { the framework transfers control to the (you guessed it) Subscription page.

    -
    +
    Subscription.jsp
    <%@ page contentType="text/html; charset=UTF-8" %>
    -<%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    -"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    -  <head>
    +    <%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    +    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    +    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +    <head>
         <s:if test="task=='Create'">
    -        <title><s:text name="subscription.title.create"/></title>
    +    <title><s:text name="subscription.title.create"/></title>
         </s:if>
         <s:if test="task=='Edit'">
    -        <title><s:text name="subscription.title.edit"/></title>
    +    <title><s:text name="subscription.title.edit"/></title>
         </s:if>
         <s:if test="task=='Delete'">
    -        <title><s:text name="subscription.title.delete"/></title>
    +    <title><s:text name="subscription.title.delete"/></title>
         </s:if>
         <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    -          type="text/css"/>
    -  </head>
    -  <body onLoad="self.focus();document.Subscription.username.focus()">
    +    type="text/css"/>
    +    </head>
    +    <body onLoad="self.focus();document.Subscription.username.focus()">
     
         <s:actionerror/>
         <s:form method="POST" action="SubscriptionSave" validate="false">
    -      <s:token />
    -      <s:hidden name="task"/>
    -      <s:label label="%{getText('username')}" name="user.username"/>
    +    <s:token />
    +    <s:hidden name="task"/>
    +    <s:label label="%{getText('username')}" name="user.username"/>
     
    -      <s:if test="task == 'Create'">
    -        <s:textfield label="%{getText('mailHostname')}" name="host"/>
    -      </s:if>
    -      <s:else>
    -        <s:label label="%{getText('mailHostname')}" name="host"/>
    -        <s:hidden name="host"/>
    -      </s:else>
    +    <s:if test="task == 'Create'">
    +    <s:textfield label="%{getText('mailHostname')}" name="host"/>
    +    </s:if>
    +    <s:else>
    +    <s:label label="%{getText('mailHostname')}" name="host"/>
    +    <s:hidden name="host"/>
    +    </s:else>
     
    -      <s:if test="task == 'Delete'">
    -        <s:label label="%{getText('mailUsername')}"
    -                   name="subscription.username"/>
    -        <s:label label="%{getText('mailPassword')}"
    -                   name="subscription.password"/>
    -        <s:label label="%{getText('mailServerType')}"
    -                   name="subscription.type"/>
    -        <s:label label="%{getText('autoConnect')}"
    -                   name="subscription.autoConnect"/>
    -        <s:submit value="%{getText('button.confirm')}"/>
    -      </s:if>
    -      <s:else>
    -        <s:textfield label="%{getText('mailUsername')}"
    -                       name="subscription.username"/>
    -        <s:textfield label="%{getText('mailPassword')}"
    -                       name="subscription.password"/>
    -        <s:select label="%{getText('mailServerType')}"
    -                    name="subscription.type" list="types"/>
    -        <s:checkbox label="%{getText('autoConnect')}"
    -                      name="subscription.autoConnect"/>
    -        <s:submit value="%{getText('button.save')}"/>
    -        <s:reset value="%{getText('button.reset')}"/>
    -      </s:else>
    +    <s:if test="task == 'Delete'">
    +    <s:label label="%{getText('mailUsername')}"
    +    name="subscription.username"/>
    +    <s:label label="%{getText('mailPassword')}"
    +    name="subscription.password"/>
    +    <s:label label="%{getText('mailServerType')}"
    +    name="subscription.type"/>
    +    <s:label label="%{getText('autoConnect')}"
    +    name="subscription.autoConnect"/>
    +    <s:submit value="%{getText('button.confirm')}"/>
    +    </s:if>
    +    <s:else>
    +    <s:textfield label="%{getText('mailUsername')}"
    +    name="subscription.username"/>
    +    <s:textfield label="%{getText('mailPassword')}"
    +    name="subscription.password"/>
    +    <s:select label="%{getText('mailServerType')}"
    +        name="subscription.type" list="types"/>
    +    <s:checkbox label="%{getText('autoConnect')}"
    +        name="subscription.autoConnect"/>
    +    <s:submit value="%{getText('button.save')}"/>
    +    <s:reset value="%{getText('button.reset')}"/>
    +    </s:else>
     
    -      <s:submit action="Registration!input"
    -                value="%{getText('button.cancel')}"
    -                onclick="form.onsubmit=null"/>
    -  </s:form>
    +    <s:submit action="Registration!input"
    +    value="%{getText('button.cancel')}"
    +    onclick="form.onsubmit=null"/>
    +    </s:form>
     
    -  <jsp:include page="Footer.jsp"/>
    -  </body>
    -</html>
    -
    + <jsp:include page="Footer.jsp"/> + </body> + </html> +

    As before, we'll discuss the tags and attributes that are new to this page: @@ -2121,18 +2128,18 @@ public Subscription findSubscription(String host) { we created a new Action class for saving a Subscription.

    -
    +
    Subscription-validation.xml
    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
         "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
    -<validators>
    -  <field name="host">
    +    <validators>
    +    <field name="host">
         <field-validator type="requiredstring">
    -        <message key="error.host.required"/>
    +    <message key="error.host.required"/>
         </field-validator>
    -  </field>
    -</validators>
    -
    + </field> + </validators> +

    The validators follow the same type of inheritance path as the classes. @@ -2174,7 +2181,7 @@ public Subscription findSubscription(String host) {

    <s:select label="%{getText('mailServerType')}"
    -  name="subscription.type" list="types" />
    +    name="subscription.type" list="types" />
     

    @@ -2185,46 +2192,46 @@ public Subscription findSubscription(String host) { and populates a Types property in a method named "prepare".

    -
    +
    Subscription-validation.xml
    public class Subscription extends MailreaderSupport
    -  implements Preparable {
    +    implements Preparable {
     
    -  private Map types = null;
    -  public Map getTypes() {
    +    private Map types = null;
    +    public Map getTypes() {
         return types;
    -   }
    +    }
     
    -   public void prepare() {
    -     Map m = new LinkedHashMap();
    -       m.put("imap", "IMAP Protocol");
    -       m.put("pop3", "POP3 Protocol");
    -       types = m;
    -       setHost(getSubscriptionHost());
    +    public void prepare() {
    +    Map m = new LinkedHashMap();
    +    m.put("imap", "IMAP Protocol");
    +    m.put("pop3", "POP3 Protocol");
    +    types = m;
    +    setHost(getSubscriptionHost());
         }
     
         // ... 
    -
    +

    The default Interceptor stack includes the PrepareInterceptor, which observes the Preparable interface.

    -
    +
    PrepareInterceptor
    public class PrepareInterceptor extends AroundInterceptor {
     
    -  protected void after(ActionInvocation dispatcher, String result) throws Exception {
    -  }
    +    protected void after(ActionInvocation dispatcher, String result) throws Exception {
    +    }
     
    -  protected void before(ActionInvocation invocation) throws Exception {
    +    protected void before(ActionInvocation invocation) throws Exception {
         Object action = invocation.getAction();
    -     if (action instanceof Preparable) {
    +    if (action instanceof Preparable) {
             ((Preparable) action).prepare();
         }
    -  }
    -}
    + } + }

    The PrepareInterceptor ensures that the "prepare" method will always be called @@ -2251,7 +2258,7 @@ public Subscription findSubscription(String host) {

      <s:checkbox label="%{getText('autoConnect')}"
    -  name="subscription.autoConnect"/>
    + name="subscription.autoConnect"/>

    The Subscription object has a boolean AutoConnect property, @@ -2259,7 +2266,7 @@ public Subscription findSubscription(String host) { The problem is, if you clear a checkbox, the browser client will not submit anything. Nada. Zip. It is as if the checkbox control never existed. - The HTTP protocol has no way to affirm "false". + The HTTP protocol has no way to affirm "false". If the control is missing, we need to figure out it's been unclicked.

    @@ -2291,21 +2298,21 @@ public Subscription findSubscription(String host) { If the control is submitted, then the property is set to true.

    -
    +
    SubscriptionSave
    public final class SubscriptionSave extends Subscription {
     
    -  public void prepare() {
    +    public void prepare() {
         super.prepare();
         // checkbox workaround
         getSubscription().setAutoConnect(false);
    -  }
    +    }
     
    -  public String execute() throws Exception {
    +    public String execute() throws Exception {
         return save();
    -  }
    -}
    -
    + } + } +

    @@ -2315,22 +2322,22 @@ public Subscription findSubscription(String host) { SubscriptionSave will invoke the Subscription.save method.

    -
    +
    Subscription save method
    public String save() throws Exception {
     
    -  if (Constants.DELETE.equals(getTask())) {
    -   removeSubscription();
    -  }
    +    if (Constants.DELETE.equals(getTask())) {
    +    removeSubscription();
    +    }
     
    -  if (Constants.CREATE.equals(getTask())) {
    +    if (Constants.CREATE.equals(getTask())) {
         copySubscription(getHost());
    -  }
    +    }
     
    -  saveUser();
    -  return SUCCESS;
    -}
    -
    + saveUser(); + return SUCCESS; + } +

    The save method uses the Task property to handle @@ -2343,13 +2350,13 @@ public Subscription findSubscription(String host) { and then updates the application state.

    -
    +
    removeSubscription
    public void removeSubscription() throws Exception {
    -  getUser().removeSubscription(getSubscription());
    -  getSession().remove(Constants.SUBSCRIPTION_KEY);
    -}
    -
    + getUser().removeSubscription(getSubscription()); + getSession().remove(Constants.SUBSCRIPTION_KEY); + } +

    The copySubscription method is a bit more interesting. @@ -2387,17 +2394,17 @@ public Subscription findSubscription(String host) { and copy over the rest of the properties.

    -
    +
    copySubscription
    public void copySubscription(String host) {
    -  Subscription input = getSubscription();
    -  Subscription sub = createSubscription(host);
    -  if (null != sub) {
    +    Subscription input = getSubscription();
    +    Subscription sub = createSubscription(host);
    +    if (null != sub) {
         BeanUtils.setValues(sub, input, null);
         setSubscription(sub);
         setHost(sub.getHost());
    -  }
    -}
    + } + }

    Of course, this is not a preferred solution, @@ -2406,6 +2413,7 @@ public Subscription findSubscription(String host) {

    Summary

    +

    At this point, we've booted the application, logged on, reviewed a Registration record, and edited a Subscription. diff --git a/apps/mailreader/src/test/java/mailreader2/BaseSqlMapTest.java b/apps/mailreader/src/test/java/mailreader2/BaseSqlMapTest.java index a2deef54f..69f2c4096 100644 --- a/apps/mailreader/src/test/java/mailreader2/BaseSqlMapTest.java +++ b/apps/mailreader/src/test/java/mailreader2/BaseSqlMapTest.java @@ -19,7 +19,7 @@ public class BaseSqlMapTest extends TestCase { protected SqlMapClient sqlMap; - protected void initSqlMap(String configFile, Properties props) throws Exception { + protected void initSqlMap(String configFile, Properties props) throws Exception { Reader reader = Resources.getResourceAsReader(configFile); sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader, props); reader.close(); diff --git a/apps/mailreader/src/test/java/mailreader2/SqlMapTest.java b/apps/mailreader/src/test/java/mailreader2/SqlMapTest.java index cefcc4b6f..125e59637 100644 --- a/apps/mailreader/src/test/java/mailreader2/SqlMapTest.java +++ b/apps/mailreader/src/test/java/mailreader2/SqlMapTest.java @@ -48,47 +48,47 @@ public class SqlMapTest extends BaseSqlMapTest { public void setUp() throws Exception { super.setUp(); - input = new AppData(); + input = new AppData(); } public void testLOCALE_LIST() throws Exception { - AppData output = (AppData) sqlMap.queryForObject(Constants.LOCALE_LIST,null); + AppData output = (AppData) sqlMap.queryForObject(Constants.LOCALE_LIST, null); assertNotNull(output); } public void testREGISTRATION_INSERT_ASSERT_fail() throws Exception { input.setUsername(username); - Object output = sqlMap.queryForObject(Constants.REGISTRATION_INSERT_ASSERT,input); + Object output = sqlMap.queryForObject(Constants.REGISTRATION_INSERT_ASSERT, input); Long count = (Long) output; - assertTrue("Expected user to already exist",count.intValue()>0); + assertTrue("Expected user to already exist", count.intValue() > 0); } public void testREGISTRATION_INSERT_ASSERT() throws Exception { input.setUsername(username2); - Object output = sqlMap.queryForObject(Constants.REGISTRATION_INSERT_ASSERT,input); + Object output = sqlMap.queryForObject(Constants.REGISTRATION_INSERT_ASSERT, input); Long count = (Long) output; - assertTrue("Did not expected user to exist",count.intValue()==0); + assertTrue("Did not expected user to exist", count.intValue() == 0); } public void testREGISTRATION_INSERT() throws Exception { input.setRegistration_key(registration_key2); input.setLocale_key(locale_key); input.setUsername(username2); - input.setPassword(password2 ); + input.setPassword(password2); input.setFullname(fullname2); input.setEmail_from(email_from2); input.setEmail_replyto(email_replyto2); - sqlMap.insert(Constants.REGISTRATION_INSERT,input); + sqlMap.insert(Constants.REGISTRATION_INSERT, input); // Trust but verify input.setPassword(null); - AppData output = (AppData) sqlMap.queryForObject(Constants.REGISTRATION_PASSWORD,input); - assertEquals(password2,output.getPassword()); + AppData output = (AppData) sqlMap.queryForObject(Constants.REGISTRATION_PASSWORD, input); + assertEquals(password2, output.getPassword()); } - public void testREGISTRATION_PASSWORD() throws Exception { + public void testREGISTRATION_PASSWORD() throws Exception { input.setUsername(username); - AppData output = (AppData) sqlMap.queryForObject(Constants.REGISTRATION_PASSWORD,input); - assertEquals(password,output.getPassword()); + AppData output = (AppData) sqlMap.queryForObject(Constants.REGISTRATION_PASSWORD, input); + assertEquals(password, output.getPassword()); } public void testREGISTRATION_FULLNAME() throws Exception { @@ -96,13 +96,13 @@ public class SqlMapTest extends BaseSqlMapTest { AppData output = (AppData) sqlMap.queryForObject(Constants.REGISTRATION_FULLNAME, input); assertEquals(fullname, output.getFullname()); assertNull("Expected other fields to be null", output.getPassword()); - assertNull("Expected other fields to be null",output.getEmail_from()); + assertNull("Expected other fields to be null", output.getEmail_from()); } public void testREGISTRATION_EDIT() throws Exception { input.setRegistration_key(registration_key); AppData output = (AppData) sqlMap.queryForObject(Constants.REGISTRATION_EDIT, input); - assertNotNull("Registration not found!",output); + assertNotNull("Support not found!", output); assertEquals(fullname, output.getFullname()); assertEquals(email_from, output.getEmail_from()); assertEquals(email_replyto, output.getEmail_replyto()); @@ -111,36 +111,36 @@ public class SqlMapTest extends BaseSqlMapTest { public void testREGISTRATION_UPDATE() throws Exception { input.setRegistration_key(registration_key); input.setUsername(username2); - input.setPassword(password2 ); + input.setPassword(password2); input.setFullname(fullname2); input.setEmail_from(email_from2); input.setEmail_replyto(email_replyto2); - sqlMap.update(Constants.REGISTRATION_UPDATE,input); + sqlMap.update(Constants.REGISTRATION_UPDATE, input); // Trust but verify input.setPassword(null); - AppData output = (AppData) sqlMap.queryForObject(Constants.REGISTRATION_PASSWORD,input); - assertEquals(password2,output.getPassword()); + AppData output = (AppData) sqlMap.queryForObject(Constants.REGISTRATION_PASSWORD, input); + assertEquals(password2, output.getPassword()); } public void testREGISTRATION_UPDATE_fails() throws Exception { input.setRegistration_key(null); - sqlMap.update(Constants.REGISTRATION_UPDATE,input); + sqlMap.update(Constants.REGISTRATION_UPDATE, input); } public void testSUBSCRIPTION_INSERT_ASSERT_fail() throws Exception { input.setRegistration_key(registration_key); input.setSubscription_host(subscription_host); - Object output = sqlMap.queryForObject(Constants.SUBSCRIPTION_INSERT_ASSERT,input); + Object output = sqlMap.queryForObject(Constants.SUBSCRIPTION_INSERT_ASSERT, input); Long count = (Long) output; - assertTrue("Expected subscription to already exist",count.intValue()>0); + assertTrue("Expected subscription to already exist", count.intValue() > 0); } public void SUBSCRIPTION_INSERT_ASSERT() throws Exception { input.setSubscription_key(subscription_key2); input.setSubscription_host(subscription_host2); - Object output = sqlMap.queryForObject(Constants.SUBSCRIPTION_INSERT_ASSERT,input); + Object output = sqlMap.queryForObject(Constants.SUBSCRIPTION_INSERT_ASSERT, input); Long count = (Long) output; - assertTrue("Did not expect subscription to exist",count.intValue()==0); + assertTrue("Did not expect subscription to exist", count.intValue() == 0); } public void testSUBSCRIPTION_INSERT() throws Exception { @@ -151,27 +151,27 @@ public class SqlMapTest extends BaseSqlMapTest { input.setHost_user(host_user2); input.setHost_pass(host_pass2); input.setHost_auto(host_auto2); - sqlMap.insert(Constants.SUBSCRIPTION_INSERT,input); + sqlMap.insert(Constants.SUBSCRIPTION_INSERT, input); // Trust but verify - Object output = sqlMap.queryForObject(Constants.SUBSCRIPTION_INSERT_ASSERT,input); + Object output = sqlMap.queryForObject(Constants.SUBSCRIPTION_INSERT_ASSERT, input); Long count = (Long) output; - assertTrue("Expected subscription to NOW exist",count.intValue()>0); + assertTrue("Expected subscription to NOW exist", count.intValue() > 0); } - private void assertSubscription(AppData output) throws Exception { - assertEquals(host_user, output.getHost_user()); - assertEquals(host_pass, output.getHost_pass()); - assertEquals(protocol_name, output.getProtocol_name()); - assertEquals(host_auto,output.getHost_auto()); - assertFalse(output.isHost_auto_checkbox()); - } + private void assertSubscription(AppData output) throws Exception { + assertEquals(host_user, output.getHost_user()); + assertEquals(host_pass, output.getHost_pass()); + assertEquals(protocol_name, output.getProtocol_name()); + assertEquals(host_auto, output.getHost_auto()); + assertFalse(output.isHost_auto_checkbox()); + } public void testSUBSCRIPTION_LIST() throws Exception { input.setRegistration_key(registration_key); - Object output = sqlMap.queryForList(Constants.SUBSCRIPTION_LIST,input); - assertNotNull("Query failed!",output); + Object output = sqlMap.queryForList(Constants.SUBSCRIPTION_LIST, input); + assertNotNull("Query failed!", output); List list = (List) output; - assertEquals(SAMPLE_SIZE,list.size()); + assertEquals(SAMPLE_SIZE, list.size()); AppData row1 = (AppData) list.get(0); assertSubscription(row1); } @@ -179,7 +179,7 @@ public class SqlMapTest extends BaseSqlMapTest { public void testSUBSCRIPTION_EDIT() throws Exception { input.setSubscription_key(subscription_key); AppData output = (AppData) sqlMap.queryForObject(Constants.SUBSCRIPTION_EDIT, input); - assertNotNull("Subscription not found!",output); + assertNotNull("Support not found!", output); assertSubscription(output); } @@ -191,11 +191,11 @@ public class SqlMapTest extends BaseSqlMapTest { input.setHost_user(host_user2); input.setHost_pass(host_pass2); input.setHost_auto(host_auto2); - sqlMap.update(Constants.SUBSCRIPTION_UPDATE,input); + sqlMap.update(Constants.SUBSCRIPTION_UPDATE, input); // Trust but verify - Object output = sqlMap.queryForObject(Constants.SUBSCRIPTION_INSERT_ASSERT,input); + Object output = sqlMap.queryForObject(Constants.SUBSCRIPTION_INSERT_ASSERT, input); Long count = (Long) output; - assertTrue("Expected subscription to exist",count.intValue()>0); + assertTrue("Expected subscription to exist", count.intValue() > 0); } }