Search code examples
jsppropertiesstruts2struts-tags

Why is jsp not seeing default attribute in property file?


I am doing this beginner Struts2 login tutorial And i got it working, except, when the Login page is accessed it doesn't first find the attributes for the labels. So instead of: enter image description here

I get Login page:

enter image description here And error page:

enter image description here

It does however find the attribute when the login is successful by using a simple property tag <s:property value="username" />
enter image description here

What am i overlooking here?

Login.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Struts 2 - Login Application</title>
</head>

<body>
<h2>Struts 2 - Login Application</h2>
<s:actionerror />
<s:form action="login.action" method="post">
    <s:textfield name="username" key="label.username" size="20" />
    <s:password name="password" key="label.password" size="20" />
    <s:submit method="authenticate" key="label.login" align="center" />
</s:form>
</body>
</html>

Welcome.jsp (when login is successful)

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Welcome</title>
</head>

<body>
    <h2>Howdy, <s:property value="username" />...!</h2>
</body>
</html>

login.xml included by struts.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC 
'-//Apache Software Foundation//DTD Struts Configuration 2.0//EN' 
'http://struts.apache.org/dtds/struts-2.0.dtd'>

<struts>
      <constant name="struts.custom.i18n.resources"
        value="Credentials" />
    <package name="Login" namespace="/login" extends="struts-default">
        <action name="login"
    method ="authenticate"
            class="Login.LoginAction">
            <result name="success">/login/Welcome.jsp</result>
            <result name="error">/login/Login.jsp</result>
        </action>
    </package>
</struts>

LoginAction class:

package Login;
import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport{
    private String username;
    private String password;

    public String authenticate() {

     if (this.username.equals("admin") 
                && this.password.equals("admin123")) {
            return "success";
        } else {
            addActionError(getText("error.login"));
            return "error";
        }
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Property File Credentials.properties

label.username= Username
label.password= Password
label.login= Login
error.login= Invalid Username/Password. Please try again.

File structure:
enter image description here


Solution

  • You can put all resources for all actions in default struts resource bundel, or dived each action resources in its own packge.

    I suggest the first approach which eliminates lots of duplications and you can use jrc-editor to easily manage all your resource bundels.

    So in your sample after running the server the file must be copied to WEB-INF/classes/resources/ then

    <constant name="struts.custom.i18n.resources"
            value="resources/login/Credentials.properties" />
    

    PS: you can have

    <constant name="struts.custom.i18n.resources"
            value="resources/login/Credentials.properties,resources/login/Otherfile.properties" />