javastruts2model-drivenstruts2-convention-pluginaction-mapping

HTTP 404 - There is no Action mapped for namespace [/modeldriven] and action name [datosUsuario] associated with context path [/FormularioMD]


I'm a beginner to struts2. I created a dynamic web project on eclipse so as to using struts 2. There are something wrong with it, and i just don not know why. the Console output is:

There is no Action mapped for namespace [/modeldriven] and action name [datosUsuario] associated with context path [/FormularioMD]. - [unknown location]
    at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:185)
    at org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:63)
    at org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:37)
    at com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58)
    at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:554)
    at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81)
    at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
    at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:306)
    at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:323)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1719)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

I have the following directory structure:

Resources
--src
  --action and model.
WebContent
--modeldriven
  --nuevo-usuario.jsp
  --datos-usuario.jsp
--WEB-INF
  --lib
  --web.xml

My JSP file to input data:

<%@taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<s:form action="datosUsuario">
    <s:textfield name="nombre" label="Nombre" />
    <s:textfield name="username" label="Username" />
    <s:password name="password" label="Password" />
    <s:textfield name="edad" label="Edad" />
    <s:textfield name="fechaNacimiento" label="Fecha de Nacimiento" />
    <s:submit value="Enviar" />
</s:form>
</body>
</html>

My action class, NOTE: I using annotations:

package com.java.rmo.controladores;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;

import com.java.rmo.modelos.Usuario;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

@Namespace(value = "/modeldriven")
@Action(value = "datosUsuario", results={
        @Result(name="success", location="/modeldriven/datos-usuario.jsp")
})
public class UsuarioAction extends ActionSupport implements ModelDriven<Usuario> {

    private Usuario usuario = new Usuario();

     public Usuario getModel(){
            return usuario;
     }

     @Override
     public String execute() throws Exception {
         return SUCCESS;
     }
}

My JSP file to show result:

<%@taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
Nombre: <strong><s:property value="nombre" /></strong> <br />
Username: <strong><s:property value="username" /></strong> <br />
Password: <strong><s:property value="password" /></strong> <br />
Edad: <strong><s:property value="edad" /></strong> <br />
Fecha de Nacimiento: <strong><s:property value="fechaNacimiento" /></strong>
</body>
</html>

My web.xml file:

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

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>struts2HelloWord</display-name>

<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>

So, can anybody help me?, thank's.


Solution

  • The Convention plugin, as the name suggests, works using naming conventions.

    It searches for certain packages, and inside them, it looks for actions with certain names, or implementing a specific interface.

    From the documentation:

    By default, the Convention plugin will find all action classes that implement com.opensymphony.xwork2.Action or whose name ends with the word Action in specific packages.

    These packages are located by the Convention plugin using a search methodology. First the Convention plugin finds packages named struts, struts2, action or actions. Any packages that match those names are considered the root packages for the Convention plugin. Next, the plugin looks at all of the classes in those packages as well as sub-packages and determines if the classes implement com.opensymphony.xwork2.Action or if their name ends with Action (i.e. FooAction)

    Since your package is:

    package com.java.rmo.controladores;

    the Convention plugin won't search for anything inside it.

    You have two options:

    I'd personally go with the first solution... stick to the default, and avoid yourself possible problems or unwanted side effects.