Trying to build a Struts 2 app which directs the user to a page (Display.jsp
) that shows the color of a user defined RGB color configuration. I get the example from the Struts 2 Tutorial by Budi Karniawan. When I manually cut and paste the source code and build the app manually as an NB Web application, it runs fine although the RGB parameters throw validation errors despite being input in the correct format (I checked that I am inputting using comma separated numbers for the RGB co-ordinates ie: green is 0,255,0). The directory structure is:
Then I decided to import the project file (creating a Web Application from Existing Sources option). I used the ant build.xml
file to compile and run the application.
When I run the application through the app name:
http://localhost:8084/Budi7c
I get:
no Action mapped for namespace [/]
Then I append the action name mapped in struts.xml
http://localhost:8084/Budi7c/Design1.action
I get an HTTP 404. But the above Deisgn1.action reference worked when I tried to build the project manually. Can anyone please tell me the best way to correctly import and run this application given the following files? I would rather use an ant script and NOT MAVEN (since there seems to be a lot of issues building Struts 2 using Maven). I would just like to know a way to avoid the 404 error when trying to run struts actions.
If I try building the app manually, the input validation fails (even though I’m inputting the numbers and separating them with commas). If I try to import and use Ant to ensure a correct build, I end up with a 404.
The app is as follows:
web.xml
:
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Restrict direct access to JSPs. For the security constraint to work, the auth-constraint and login-config elements must be present --> <security-constraint> <web-resource-collection> <web-resource-name>JSPs</web-resource-name> <url-pattern>/jsp/*</url-pattern> </web-resource-collection> <auth-constraint/> </security-constraint> <login-config> <auth-method>BASIC</auth-method> </login-config> </web-app>
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.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="true" /> <package name="app07c" extends="struts-default"> <action name="Design1"> <result>/jsp/Design.jsp</result> </action> <action name="Design2" class="app07c.Design"> <result name="input">/jsp/Design.jsp</result> <result name="success">/jsp/Display.jsp</result> </action> </package> </struts>
Color.java
:
package app07c; import com.opensymphony.xwork2.ActionSupport; public class Color extends ActionSupport { private int red; private int green; private int blue; public int getBlue() { return blue; } public void setBlue(int blue) { this.blue = blue; } public int getGreen() { return green; } public void setGreen(int green) { this.green = green; } public int getRed() { return red; } public void setRed(int red) { this.red = red; } public String getHexCode() { return (red < 16? "0" : "") + Integer.toHexString(red) + (green < 16? "0" : "") + Integer.toHexString(green) + (blue < 16? "0" : "") + Integer.toHexString(blue); } }
Design.java
:
package app07c; import com.opensymphony.xwork2.ActionSupport; public class Design extends ActionSupport { private String designName; private Color color; public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } public String getDesignName() { return designName; } public void setDesignName(String designName) { this.designName = designName; } }
MyColorConverter.java
:
package app07c.converter; import java.util.Map; import org.apache.struts2.util.StrutsTypeConverter; import app07c.Color; import com.opensymphony.xwork2.conversion.TypeConversionException; public class MyColorConverter extends StrutsTypeConverter { public Object convertFromString(Map context, String[] values, Class toClass) { boolean ok = false; String rgb = values[0]; String[] colorComponents = rgb.split(","); if (colorComponents != null && colorComponents.length == 3) { String red = colorComponents[0]; String green = colorComponents[1]; String blue = colorComponents[2]; int redCode = 0; int greenCode = 0; int blueCode = 0; try { redCode = Integer.parseInt(red.trim()); greenCode = Integer.parseInt(green.trim()); blueCode = Integer.parseInt(blue.trim()); if (redCode >= 0 && redCode < 256 && greenCode >= 0 && greenCode < 256 && blueCode >= 0 && blueCode < 256) { Color color = new Color(); color.setRed(redCode); color.setGreen(greenCode); color.setBlue(blueCode); ok = true; return color; } } catch (NumberFormatException e) { } } if (!ok) { throw new TypeConversionException("Invalid color codes"); } return null; } public String convertToString(Map context, Object o) { Color color = (Color) o; return color.getRed() + "," + color.getGreen() + "," + color.getBlue(); } }
Design.jsp
:
<%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Color</title> <style type="text/css">@import url(css/main.css);</style> <style> .errorMessage { color:red; } </style> </head> <body> <div id="global" style="width:450px"> <h4>Color</h4> Please enter the RGB components, each of which is an integer between 0 and 255 (inclusive). Separate two components with a comma. For example, green is 0,255,0. <s:form action="Design2"> <s:textfield name="designName" label="Design Name"/> <s:textfield name="color" label="Color"/> <s:submit/> </s:form> </div> </body> </html>
Display.jsp
:
<%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Design Details</title> <style type="text/css">@import url(css/main.css);</style> <style type="text/css"> .colorSample { border:1px solid black; width:100%; height:100px; background:#<s:property value="color.hexCode"/>; } </style> </head> <body> <div id="global" style="width:250px"> <h4>Design details:</h4> Design name: <s:property value="designName"/> <br/>Color code: <s:property value="color"/> <div class="colorSample"/> </div> </body> </html>
I tried to change the web contents folder from /jsp
to /
so that project structure is the same as the directory structure. I then use the ant build script to compile and run the project and get the following stack:
ant -f C:\struts2\budi_ebook\struts2extractb\app07c -DforceRedeploy=false -Ddirectory.deployment.supported=true -Dnb.wait.for.caches=true run init: deps-module-jar: deps-ear-jar: deps-jar: Warning: Program Files (x86)F-SecureAnti-Virusaquariusfa.log modified in the future. Warning: Program FilesCommVaultSimpanaLog FilesCVD.log modified in the future. Warning: UsersManaarDCNTUSER.DAT modified in the future. Warning: UsersManaarDCntuser.dat.LOG1 modified in the future. Warning: UsersRedGuard_Admin.MANAARNETAppDataLocalTemp3output1375645810208 modified in the future. Warning: UsersRedGuard_Admin.MANAARNETAppDataLocalTemp3toolbar_log.txt modified in the future. Warning: WindowsTempavg_secure_search.log modified in the future. Warning: appManaarDCdiagrdbmsorcldworcldwtraceorcldw_dbrm_3148.trc modified in the future. Warning: appManaarDCdiagrdbmsorcldworcldwtraceorcldw_dbrm_3148.trm modified in the future. Warning: appManaarDCproduct11.2.0dbhome_1D5H9RBP1.ManaarNet.com_orclDWsysmanemdagntstmp.txt modified in the future. Warning: appManaarDCproduct11.2.0dbhome_1D5H9RBP1.ManaarNet.com_orclDWsysmanlogemagent.trc modified in the future. Warning: appManaarDCproduct11.2.0dbhome_1D5H9RBP1.ManaarNet.com_orclDWsysmanlogemoms.log modified in the future. Warning: appManaarDCproduct11.2.0dbhome_1D5H9RBP1.ManaarNet.com_orclDWsysmanlogemoms.trc modified in the future. Warning: appManaarDCproduct11.2.0dbhome_1oc4jj2eeOC4J_DBConsole_D5H9RBP1.ManaarNet.com_orclDWlogem-application.log modified in the future. Warning: inetpublogsLogFilesW3SVC1u_ex130804.log modified in the future. C:struts2budi_ebookstruts2extractbapp07cnbprojectbuild-impl.xml:841: java.lang.OutOfMemoryError: GC overhead limit exceeded at java.util.Arrays.copyOfRange(Arrays.java:2694) at java.lang.String.<init>(String.java:203) at java.lang.String.substring(String.java:1913) at java.util.StringTokenizer.nextToken(StringTokenizer.java:352) at org.apache.tools.ant.util.FileUtils.normalize(FileUtils.java:741) at org.apache.tools.ant.util.FileUtils.resolveFile(FileUtils.java:616) at org.apache.tools.ant.types.resources.FileResource.<init>(FileResource.java:60) at org.apache.tools.ant.util.SourceFileScanner$1.<init>(SourceFileScanner.java:96) at org.apache.tools.ant.util.SourceFileScanner.restrict(SourceFileScanner.java:95) at org.apache.tools.ant.taskdefs.Copy.buildMap(Copy.java:787) at org.apache.tools.ant.taskdefs.Copy.scan(Copy.java:744) at org.apache.tools.ant.taskdefs.Copy.iterateOverBaseDirs(Copy.java:666) at org.apache.tools.ant.taskdefs.Copy.execute(Copy.java:563) at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291) at sun.reflect.GeneratedMethodAccessor90.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106) at org.apache.tools.ant.Task.perform(Task.java:348) at org.apache.tools.ant.Target.execute(Target.java:392) at org.apache.tools.ant.Target.performTasks(Target.java:413) at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1399) at org.apache.tools.ant.Project.executeTarget(Project.java:1368) at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41) at org.apache.tools.ant.Project.executeTargets(Project.java:1251) at org.apache.tools.ant.module.bridge.impl.BridgeImpl.run(BridgeImpl.java:283) at org.apache.tools.ant.module.run.TargetExecutor.run(TargetExecutor.java:541) at org.netbeans.core.execution.RunClassThread.run(RunClassThread.java:153) BUILD FAILED (total time: 12 minutes 5 seconds)
Advertisement
Answer
Well here’s how I solved it. I used the Netbeans ‘Web Applications with Existing Sources’ to import the project. For some reason the imported project doesn’t register the ‘jsp’ directory. It just sees the JSP files in the Web Pages directory NOT Web Pages/jsp. So i simply removed the /jsp reference in the struts.xml. The app now runs fine and the validation errors are no longer there.
I’m happy with this answer to the extent that I can run the app, but I’m not happy that I fully understand how IDEs build these type of applications as the imported directory structure is clearly wrong (and missed the jsp folder). Would be grateful if anyone could shed further light on this or if I should post a separate question on the topic of building Struts2 in Netbeans