The main idea is to show how to start building the application from a starting reference point, run the application, identify and fix the errors that keep coming at each step. The hard fact is that there are no short cut steps or a set of rules that can be followed to migrate your application to Struts 1.2.
A starting point can be 2 build a basic Struts 1.2 application with the required jar files, and from there you can build your application step by step to bring it up to date with the latest Struts and Java releases.
We use the "getquote" project which we have built using Struts 1.1.
On the way, we can also see the new features in Struts 2 and the scripts used in Struts 1.1 which are now no longer needed.
For the build we can use the version of struts as of Dec '25. i.e. - Struts 7.1.1
For the JDK, I am using Java version 21, though Java release 25 is also available as of Dec '25.
You can download it from the link below
I am using Claude AI to resolve the errors that I get at compile and run time.
I make the folder structure as described in my earlier posts and do a build.We start off with a set of standard jar files from Struts 2 (version 7.1.1) given below
commons-fileupload2-core-2.0.0-M4.jar
commons-io-2.20.0.jar
commons-lang3-3.19.0.jar
commons-logging-1.3.5.jar
commons-logging-api-1.1.jar
freemarker-2.3.34.jar
javassist-3.29.0-GA.jar
ognl-3.3.5.jar
servlet-api.jar
struts2-core-7.1.1.jar
xwork-core-2.3.35.jarBuilding your first Struts application
Make changes to index.jsp, result file quote.jsp, struts.xml and web.xml.
In the localhost.2025-11-05.log I get error
I get 12 errors as shown below.
E:\install\tomcat\tomcat11013\webapps\getquote>ant
Buildfile: build.xml
[echo] 111111...
compile-single:
[echo] Compiling LookupForm.java ...
[javac] Compiling 2 source files to E:\install\tomcat\tomcat11013\webapps\getquote\WEB-INF\classes
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:7: error: package org.apache.struts.action does not exist
[javac] import org.apache.struts.action.Action;
[javac] ^
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:8: error: package org.apache.struts.action does not exist
[javac] import org.apache.struts.action.ActionForm;
[javac] ^
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:9: error: package org.apache.struts.action does not exist
[javac] import org.apache.struts.action.ActionForward;
[javac] ^
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:10: error: package org.apache.struts.action does not exist
[javac] import org.apache.struts.action.ActionMapping;
[javac] ^
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:12: error: cannot find symbol
[javac] public class LookupAction extends Action {
[javac] ^
[javac] symbol: class Action
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:19: error: cannot find symbol
[javac] public ActionForward execute (ActionMapping mapping,
[javac] ^
[javac] symbol: class ActionMapping
[javac] location: class LookupAction
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:20: error: cannot find symbol
[javac] ActionForm form,
[javac] ^
[javac] symbol: class ActionForm
[javac] location: class LookupAction
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:19: error: cannot find symbol
[javac] public ActionForward execute (ActionMapping mapping,
[javac] ^
[javac] symbol: class ActionForward
[javac] location: class LookupAction
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupForm.java:4: error: package org.apache.struts.action does not exist
[javac] import org.apache.struts.action.ActionForm;
[javac] ^
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupForm.java:5: error: package org.apache.struts.action does not exist
[javac] import org.apache.struts.action.ActionMapping;
[javac] ^
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupForm.java:7: error: cannot find symbol
[javac] public class LookupForm extends ActionForm {
[javac] ^
[javac] symbol: class ActionForm
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupForm.java:17: error: cannot find symbol
[javac] public void reset (ActionMapping mapping, HttpServletRequest request) {
[javac] ^
[javac] symbol: class ActionMapping
[javac] location: class LookupForm
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:15: warning: [removal] Double(double) in Double has been deprecated and marked for removal
[javac] return new Double (25.00);
[javac] ^
[javac] 12 errors
[javac] 1 warning
The above errors are because I am importing packages from Struts 1.
For the Struts 2 framework we import com.opensymphony.xwork2.ActionSupport;
In LookupForm.java and LookupAction.java we replace the following Struts 1 packages
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
with the below Struts 2 package
import com.opensymphony.xwork2.ActionSupport;
I now run the ant script and the errors have come down to 6.
compile-single:
[echo] Compiling LookupForm.java ...
[javac] Compiling 2 source files to E:\install\tomcat\tomcat11013\webapps\getquote\WEB-INF\classes
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:9: error: cannot find symbol
[javac] public class LookupAction extends Action {
[javac] ^
[javac] symbol: class Action
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:16: error: cannot find symbol
[javac] public ActionForward execute (ActionMapping mapping,
[javac] ^
[javac] symbol: class ActionMapping
[javac] location: class LookupAction
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:17: error: cannot find symbol
[javac] ActionForm form,
[javac] ^
[javac] symbol: class ActionForm
[javac] location: class LookupAction
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupAction.java:16: error: cannot find symbol
[javac] public ActionForward execute (ActionMapping mapping,
[javac] ^
[javac] symbol: class ActionForward
[javac] location: class LookupAction
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupForm.java:6: error: cannot find symbol
[javac] public class LookupForm extends ActionForm {
[javac] ^
[javac] symbol: class ActionForm
[javac] E:\install\tomcat\tomcat11013\webapps\getquote\src\src\LookupForm.java:16: error: cannot find symbol
[javac] public void reset (ActionMapping mapping, HttpServletRequest request) {
[javac] ^
[javac] symbol: class ActionMapping
[javac] location: class LookupForm
We now add some jar files from struts 2 to find the missing jar.
I add servlet-api.jar and compile .. I still get the same set of errors.
I put these errors in Claude AI and I get the following output..
Below is the information I get.
Key Differences:
No ActionForm - properties go directly in the action
No ActionMapping/ActionForward - return String values like "success"
No HttpServletRequest/Response in execute() - use interceptors or inject if needed
With the information , I make the following changes in my code and compile it. Put the getter and setter methods in the LookupAction.
import com.opensymphony.xwork2.ActionSupport;
LookupAction now extends only ActionSupport and does not require ActionForm, ActionMapping, HttpServletRequest and HttpServletResponse parameters.
There is no need to throw any Exceptions as in Struts 1.1 .. throws IOException, ServletException
The execute method also does not require an ActionForward and expects a String object like success or failure.
After resolving a few syntax errors my final code is below.
package src;
import java.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import com.opensymphony.xwork2.ActionSupport;
public class LookupAction extends ActionSupport {
private Double price = null;
private String symbol;
private String target = new String ("success");
protected Double getQuote ( String symbol) {
if ( symbol.equalsIgnoreCase ("SUNW") ) {
return new Double (25.00);
}
return null;
}
public void validate() {
if (symbol == null || symbol.trim().length() == 0) {
addFieldError("symbol", "Symbol is required");
}
}
public String getSymbol(){
return (symbol);
}
public void setSymbol (String symbol) {
this.symbol = symbol;
}
public Double getPrice(){
return (price);
}
public void setPrice (Double price) {
this.price = price;
}
public String execute (){
price = getQuote(symbol);
//Set the target to failure
if (price == null) {
target = new String ("failure");
}
else {
target = new String ("success");
}
return target;
} //execute
}
Make changes to index.jsp, result file quote.jsp, struts.xml and web.xml.
Changes and file structure will be shared.
Now start the tomcat server. I get the below error in /logs/catalina.2025-11-05.log.
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/getquote]]
at org.apache.catalina.util.LifecycleBase.handleSubClassException(LifecycleBase.java:404)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:179)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:564)
... 34 more
Caused by: java.lang.NoClassDefFoundError: org/apache/logging/log4j/Logger
at java.base/java.lang.Class.getDeclaredFields0(Native Method)
at java.base/java.lang.Class.privateGetDeclaredFields(Class.java:3475)
at java.base/java.lang.Class.getDeclaredFields(Class.java:2544)
at org.apache.catalina.startup.WebAnnotationSet.loadFieldsAnnotation(WebAnnotationSet.java:199)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationFilterAnnotations(WebAnnotationSet.java:111)
at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:69)
at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:314)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:971)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:288)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:109)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4334)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:164)
... 35 more
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.Logger
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1225)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1056)
add log4j-api-2.25.2.jar and log4j-core-2.24.1.jar jar files to the CATALINA_HOME/webapps/getquote/WEB-INF/lib folder.
Shutdown the webserver, cleanup the "work" folder and restart the web server.
Now the web server is starting correctly and the "getquote" application has got deployed without any errors.
We now run the application from broswer
http://localhost:8080/getquote/index.jsp
and now I get a run time error on the browser
HTTP Status 404 – Not Found
Type Status Report
Message JSP file [/getquote/index.jsp] not found
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Caused by: java.lang.ClassNotFoundException: org.apache.commons.text.StringSubstitutor
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1225)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1056)
... 75 more
05-Nov-2025 17:00:44.588 INFO [main] org.apache.catalina.core.ApplicationContext.log SessionListener: contextDestroyed()
05-Nov-2025 17:00:44.588 INFO [main] org.apache.catalina.core.ApplicationContext.log ContextListener: contextDestroyed()
05-Nov-2025 17:00:52.902 INFO [main] org.apache.catalina.core.ApplicationContext.log ContextListener: contextInitialized()
05-Nov-2025 17:00:52.903 INFO [main] org.apache.catalina.core.ApplicationContext.log SessionListener: contextInitialized()
05-Nov-2025 17:00:52.909 INFO [main] org.apache.catalina.core.ApplicationContext.log ContextListener: attributeAdded('StockTicker', 'async.Stockticker@4648ce9')
05-Nov-2025 17:00:55.522 SEVERE [main] org.apache.catalina.core.StandardContext.filterStart Exception starting filter [struts2]
java.lang.NoClassDefFoundError: org/apache/commons/text/StringSubstitutor
I put this message in Claude and he tells me that some jar files are missing. Namely - commons-text-1.14.0.jar jar file.
I add it and restart the server.
In catalina.2025-11-05.log I get error
05-Nov-2025 17:48:39.017 SEVERE [main] org.apache.catalina.core.StandardContext.startInternal One or more Filters failed to start. Full details will be found in the appropriate container log file
05-Nov-2025 17:48:39.039 SEVERE [main] org.apache.catalina.core.StandardContext.startInternal Context [/getquote] startup failed due to previous errors
05-Nov-2025 17:48:39.089 INFO [main] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [E:\install\tomcat\tomcat11013\webapps\getquote] has finished in [3,123] ms
In localhost.2025-11-05.log I get error NoClassDefFoundError: com/github/benmanes/caffeine/cache/Caffeine
Caused by: java.lang.NoClassDefFoundError: com/github/benmanes/caffeine/cache/Caffeine
at org.apache.struts2.ognl.OgnlCaffeineCache.(OgnlCaffeineCache.java:43)
at org.apache.struts2.ognl.DefaultOgnlCacheFactory.buildOgnlCache(DefaultOgnlCacheFactory.java:58)
at org.apache.struts2.ognl.DefaultOgnlCacheFactory.buildOgnlCache(DefaultOgnlCacheFactory.java:47)
at org.apache.struts2.ognl.OgnlUtil.(OgnlUtil.java:85)
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
... 120 more
Caused by: java.lang.ClassNotFoundException: com.github.benmanes.caffeine.cache.Caffeine
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1225)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1056)
... 125 more
This error is quite obvious and I add the caffeine jar to my lib folder.
Add the caffeine-3.2.2.jar.
Restart the web server and run the getquote application on the browser.
http://localhost:8080/getquote/ gives below error
HTTP Status 500 – Internal Server Error Type Exception Report Message An exception occurred processing [/index.jsp] at line [35] Description The server encountered an unexpected condition that prevented it from fulfilling the request. Exception org.apache.jasper.JasperException: An exception occurred processing [/index.jsp] at line [35] 32: <!-- Begin Struts form --> 33: <s:form action="lookup"> 34: <s:textfield name="symbol" label="Symbol"/> 35: <s:submit value="Lookup"/> 36: </s:form> 37: </body> 38: </html> Stacktrace: org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:566) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:456) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:330) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:281) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.handleRequest(StrutsPrepareAndExecuteFilter.java:151) org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.tryHandleRequest(StrutsPrepareAndExecuteFilter.java:137) org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:125) Root Cause java.lang.NullPointerException: Cannot invoke "java.util.List.add(Object)" because "tags" is null org.apache.struts2.components.UIBean.evaluateParams(UIBean.java:835) org.apache.struts2.components.UIBean.end(UIBean.java:566) org.apache.struts2.views.jsp.ComponentTagSupport.doEndTag(ComponentTagSupport.java:36) org.apache.jsp.index_jsp._jspx_meth_s_005ftextfield_005f0(index_jsp.java:251) org.apache.jsp.index_jsp._jspx_meth_s_005fform_005f0(index_jsp.java:215) org.apache.jsp.index_jsp._jspService(index_jsp.java:170) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:64) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:428) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:330) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:281) jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.handleRequest(StrutsPrepareAndExecuteFilter.java:151) org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.tryHandleRequest(StrutsPrepareAndExecuteFilter.java:137) org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:125)
This is because the struts framework is trying to initialize the tag system and is not able to get the required tag classes or file.
Since this issue is related to struts tags, as a temporary solution to get the code to work, we change the struts tags to html tags
<s:form action="lookup">
<s:textfield name="symbol" label="Symbol"/>
<s:submit value="Lookup"/>
</s:form>
We change it as below
<form action="lookup" method="post"> <label for="symbol">Symbol:</label> <input type="text" name="symbol" id="symbol"/> <input type="submit" value="Lookup"/> </form>This resolves the error due to struts tags, but now the LookupAction is unable to get the value for "symbol". We get error as below
Symbol received: null 17:31:38.564 [http-nio-8080-exec-8] ERROR org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler - Exception occurred during processing request: Cannot invoke "String.equalsIgnoreCase(String)" because "<parameter1>" is null java.lang.NullPointerException: Cannot invoke "String.equalsIgnoreCase(String)" because "<parameter1>" is null at src.LookupAction.getQuote(Unknown Source) ~[classes/:?] at src.LookupAction.execute(Unknown Source) ~[classes/:?] at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] at ognl.OgnlRuntime.invokeMethodInsideSandbox(OgnlRuntime.java:1245) ~[ognl-3.3.5.jar:?] at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:1230) ~[ognl-3.3.5.jar:?] at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1958) ~[ognl-3.3.5.jar:?] at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68) ~[ognl-3.3.5.jar:?] at org.apache.struts2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:101) ~[struts2-core-7.1.1.jar:7.1.1] at org.apache.struts2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:93) ~[struts2-core-7.1.1.jar:7.1.1] at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:2034) ~[ognl-3.3.5.jar:?] at ognl.ASTMethod.getValueBody(ASTMethod.java:97) ~[ognl-3.3.5.jar:?] at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[ognl-3.3.5.jar:?] at ognl.SimpleNode.getValue(SimpleNode.java:258) ~[ognl-3.3.5.jar:?] at ognl.Ognl.getValue(Ognl.java:586) ~[ognl-3.3.5.jar:?] at org.apache.struts2.ognl.OgnlUtil.ognlGet(OgnlUtil.java:424) ~[struts2-core-7.1.1.jar:7.1.1] at org.apache.struts2.ognl.OgnlUtil.callMethod(OgnlUtil.java:400) ~[struts2-core-7.1.1.jar:7.1.1] at org.apache.struts2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:447) ~[struts2-core-7.1.1.jar:7.1.1]
Pay note to the message that comes on the console when you compile the java code.
You will be getting an error like
[javac] Note: Annotation processing is enabled because one or more processors were found
[javac] on the class path. A future release of javac may disable annotation processing
[javac] unless at least one processor is specified by name (-processor), or a search
[javac] path is specified (--processor-path, --processor-module-path), or annotation
[javac] processing is enabled explicitly (-proc:only, -proc:full).
[javac] Use -Xlint:-options to suppress this message.
[javac] Use -proc:none to disable annotation processing.
This indicates that the compiler detected annotation processors on your classpath and automatically enabled annotation processing for security reasons. i.e. there are libraries with annotation processors in your dependencies.However this automatic behaviour may change in future Java versions.
In an earlier HelloWorld Struts 2 build I have got the below error
org.apache.catalina.startup.Catalina.start Server startup in [6010] milliseconds
19:20:56.810 [http-nio-8080-exec-2] ERROR org.apache.struts2.interceptor.parameter.ParametersInterceptor - Parameter injection for method [setName] on Action [com.HelloWorldExample] rejected. Ensure it is annotated with @StrutsParameter with an appropriate 'depth'.
This error indicates that Struts2 is blocking parameter injection for security reasons. It is a security feature introduced in Struts 2.5+ to prevent parameter manipulation attacks.In the action class we are using setter methods and the Struts 2 ParameterInterceptor rejected it because the method isn't properly annotated.
To resolve this we add a @StrutsParameter annotation before each setter method to accept these parameters.
We now build the code and run the "getquote" application.
The source code and additional details for building your application in Struts 1.2.7 is in the link below.
And now we get the response as below
God's Word for the day
My child, treat yourself well, according to your means,
and present worthy offerings to the Lord.
Remember that death does not tarry,
and the decree of Hades has not been shown to you.
Do good to friends before you die,
and reach out and give to them how much as you can.
Do not deprive yourself of a day's enjoyment;
do not let your share of desired good pass you by.
Sirach 14:7-10
Do Not Worry
Therefore I tell you, do not worry about your life,
what you will eat or what you will drink,
Or about your body, what you will wear.
Is not life more than food and clothing?
Look at the birds of the air; they neither sow not reap, nor gather into barns,
And yet your heavenly Father feeds them.
Are you not of more value than they?
Mathew 6:25-26


No comments:
Post a Comment