Hello,
I have a simple web application to learn how the controller works in Struts 
framework. The build is deployed to Tomcat 11.0.5. The application has two 
simple JSP files PgStudent.jsp (configured as the welcome page) and 
PgRegistration.jsp. Each page has two buttons to let user go back and forth 
between the two pages. It loads the welcome page PgStudent fine, but any 
request will encounter web error 404, like this one: There is no Action mapped 
for namespace [/] and action name [viewRegistration] associated with context 
path [/s2ex1], or from localhost_access log: 0:0:0:0:0:0:0:1 - - 
[06/Jun/2025:12:12:28 -0400] "POST /s2ex1/viewRegistration HTTP/1.1" 404 829.
Please help see where I do it wrong. Namespace is specified in JSP files, but 
it always sees namespace as /. I am attaching the project file structure and 
the list of the files:
Project Files Structure
s2ex1    lib        caffeine-3.1.8.jar        freemarker-2.3.34.jar        
jakarta.servlet-api-5.0.0.jar (to compile only)        ognl-3.3.5.jar        
struts2-core-7.0.3.jar        xwork-core-2.3.35.jar    src        s2ex1         
   RegistrationAction.java            StudentAction.java    WebContent        
jsp            PgRegistration.jsp            PgStudent.jsp        WEB-INF       
     struts.xml            web.xml    build.xml
List of the 7 files
1. struts.xml<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC 
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"    
"https://struts.apache.org/dtds/struts-2.0.dtd";><struts> <constant 
name="struts.devMode" value="true"/>  <!-- student namespace -->    <package 
name="student" namespace="/student" extends="struts-default">        <action 
name="viewStudent" class="s2ex1.StudentAction" method="viewStudent">            
<result name="viewStudent">/jsp/PgStudent.jsp</result>        </action>         
       <action name="updateStudent" class="s2ex1.StudentAction" 
method="updateStudent">            <result 
name="viewStudent">/jsp/PgStudent.jsp</result>        </action>    </package>
 <!-- registration namespace -->    <package name="registration" 
namespace="/registration" extends="struts-default">        <action 
name="viewRegistration" class="s2ex1.RegistrationAction" 
method="viewRegistration">            <result 
name="viewRegistration">/jsp/PgRegistration.jsp</result>        </action>
        <action name="register" class="s2ex1.RegistrationAction" 
method="register">            <result 
name="viewRegistration">/jsp/PgRegistration.jsp</result>        </action>    
</package></struts>
2. web.xml<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"          
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee                         
     https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"          
version="5.0">
    <filter>        <filter-name>struts2</filter-name>        
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>        <filter-name>struts2</filter-name>        
<url-pattern>/*</url-pattern>    </filter-mapping>
    <!-- Set PgStudent.jsp as the default page -->    <welcome-file-list>       
  <welcome-file>jsp/PgStudent.jsp</welcome-file>    
</welcome-file-list></web-app>
3. PgRegistration.jsp<%@ taglib prefix="s" uri="/struts-tags" %><html><head>    
<title>Registration Records</title></head><body>    <h2>Registration 
Records</h2>
    <s:form namespace="/registration" action="register" method="post">        
<s:submit value="Register for Class"/>    </s:form>
    <s:form namespace="/student" action="viewStudent" method="post">        
<s:submit value="Return to Student Section"/>    </s:form></body></html>
4. PgStudent.jsp<%@ taglib prefix="s" uri="/struts-tags" %>
<html><head>    <title>Student Info</title></head><body>    <h2>Student - 
Contact Information</h2>
    <s:form namespace="/student" action="updateStudent" method="post">        
<s:submit value="Update Contact Info"/>    </s:form>
    <s:form namespace="/registration" action="viewRegistration" method="post">  
      <s:submit value="View Registrations"/>    </s:form></body></html>
5. RegistrationAction.javapackage s2ex1;
import jakarta.servlet.http.HttpServletRequest;//import 
jakarta.servlet.http.HttpSession;
import org.apache.struts2.ActionSupport;import 
org.apache.struts2.action.ServletRequestAware;
public class RegistrationAction extends ActionSupport implements 
ServletRequestAware {    private static final long serialVersionUID = 
-4447001525367432296L;    private HttpServletRequest request;
    @Override    public void withServletRequest(HttpServletRequest request) {   
     this.request = request;    }     public HttpServletRequest 
getWithServletRequest() {        return this.request;    }     public String 
viewRegistration() {        return "viewRegistration";    }    public String 
register() {        return "viewRegistration";    }    public String 
viewStudent() {        return "viewStudent";    }}
6. StudentAction.javapackage s2ex1;
import jakarta.servlet.http.HttpServletRequest;//import 
jakarta.servlet.http.HttpSession;
import org.apache.struts2.ActionSupport;import 
org.apache.struts2.action.ServletRequestAware;
public class StudentAction extends ActionSupport implements ServletRequestAware 
{    private static final long serialVersionUID = -4056538155914479859L;    
private HttpServletRequest request;
    @Override    public void withServletRequest(HttpServletRequest request) {   
     this.request = request;    } 
    public HttpServletRequest getWithServletRequest() {        return 
this.request;    }         public String viewStudent() {        return 
"viewStudent";    }        public String updateStudent() {        return 
"viewStudent";    }        public String viewRegistration() {        return 
"viewRegistration";    }}
7. build.xml<project name="s2ex1" default="war" basedir=".">        <!-- Define 
global properties -->    <property name="src.dir" value="src"/>    <property 
name="web.dir" value="WebContent"/>    <property name="build.dir" 
value="build"/>    <property name="classes.dir" value="${build.dir}/classes"/>  
  <property name="war.file" value="s2ex1.war"/>     <!-- All external libraries 
-->    <property name="lib.dir" value="${basedir}/lib"/>
    <!-- Clean -->    <target name="clean">        <delete dir="${build.dir}"/> 
       <delete file="${war.file}"/>    </target>
    <!-- Compile Java sources -->    <target name="compile">        <mkdir 
dir="${classes.dir}"/>        <javac          srcdir="${src.dir}"          
destdir="${classes.dir}"          includeantruntime="false"         source="21" 
        target="21"        >            <classpath>                <fileset 
dir="${lib.dir}">                    <include name="*.jar"/>                
</fileset>            </classpath>        </javac>    </target>
    <!-- Prepare WAR directory -->    <target name="prepare">        <mkdir 
dir="${build.dir}/WebContent"/>        <copy todir="${build.dir}/WebContent">   
         <fileset dir="${web.dir}"/>        </copy>        <copy 
file="WebContent/WEB-INF/struts.xml" todir="${build.dir}/WebContent/WEB-INF"/>  
      <copy todir="${build.dir}/WebContent/WEB-INF/classes">            
<fileset dir="${classes.dir}"/>        </copy>     <copy 
todir="${build.dir}/WebContent/WEB-INF/lib">         <fileset 
dir="${lib.dir}/">             <include name="struts2-core-7.0.3.jar"/>         
    <include name="freemarker-2.3.34.jar"/>                <include 
name="ognl-3.3.5.jar"/>         <include name="caffeine-3.1.8.jar"/>         
<include name="xwork-core-2.3.35.jar"/> </fileset>     </copy>    </target>
    <!-- Create WAR file -->    <target name="war" depends="clean, compile, 
prepare">        <mkdir dir="${build.dir}/WebContent"/>        <war 
destfile="${war.file}" webxml="${build.dir}/WebContent/WEB-INF/web.xml">        
    <fileset dir="${build.dir}/WebContent"/>        </war>        <echo 
message="Build file created: ${war.file}"/>    </target>
</project>
Thank you,Joseph H.

Reply via email to