Problema com o Struts.xml - Struts 2

Fala galera, tudo bom?
Sou iniciante no Struts 2 e em frameworks Java e estou com o seguinte problema:
Aparentemente o projeto não reconhece meu arquivo struts.xml… Ao tentar configurar interceptadores fica apontando o erro:

[quote]Fev 03, 2014 5:50:12 PM org.apache.catalina.core.StandardContext filterStart
SEVERE: Exception starting filter struts2
Unable to load configuration. - [unknown location]
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:502)
at org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:74)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.init(StrutsPrepareAndExecuteFilter.java:57)
at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:281)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:262)
at org.apache.catalina.core.ApplicationFilterConfig.(ApplicationFilterConfig.java:107)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4656)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5312)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:657)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:536)
at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1462)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:791)
at org.apache.catalina.manager.ManagerServlet.check(ManagerServlet.java:1445)
at org.apache.catalina.manager.ManagerServlet.deploy(ManagerServlet.java:860)
at org.apache.catalina.manager.ManagerServlet.doGet(ManagerServlet.java:357)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
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:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:581)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1822)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: Unable to load configuration. - [unknown location]
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:70)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:446)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:490)
… 45 more
Caused by: Unable to locate parent package [default] - [unknown location]
at org.apache.struts2.convention.PackageBasedActionConfigBuilder.getPackageConfig(PackageBasedActionConfigBuilder.java:1022)
at org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildConfiguration(PackageBasedActionConfigBuilder.java:668)
at org.apache.struts2.convention.PackageBasedActionConfigBuilder.buildActionConfigs(PackageBasedActionConfigBuilder.java:348)
at org.apache.struts2.convention.ClasspathPackageProvider.loadPackages(ClasspathPackageProvider.java:53)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:260)
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67)
… 47 more

[quote]

E pelo que entendi, o fato de não localizar o diretório pai seria causado pela ausência das instruções contidas no struts.xml…
Provavelmente é algo bobo, ainda sou iniciante nessa área :frowning:

Segue alguns códigos que podem apontar o problema:

web.xml

<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" 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_3_0.xsd"> <session-config> <session-timeout> 30 </session-timeout> </session-config> <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> <welcome-file-list> <welcome-file>Index</welcome-file> </welcome-file-list> </web-app>

struts.xml

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

/WEB-INF/content/formulario-login.jsp /WEB-INF/content/Tarefas/formulario.jsp [/code]

listarTarefaAction.java (Contém a ação que utilizaria o interceptador de acesso)

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package br.com.gbd.action;

import br.com.gbd.hibernate.HibernateUtil;
import br.com.gbd.hibernate.Tarefas;
import br.com.gbd.hibernate.TarefasDAO;
import java.util.List;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.hibernate.Session;

/**
*

  • @author Henrique
    */
    @ParentPackage(“default”)
    public class ListarTarefasAction {
    private List tarefas;

    @Action(value = “listaTarefas”, results = {
    @Result(name = “ok”, location = “Tarefas/lista.jsp”)}, interceptorRefs= {
    @InterceptorRef(“seguranca”)
    })

    public String execute() {
    TarefasDAO dao = new TarefasDAO();
    Session s = HibernateUtil.getSession();
    s.beginTransaction();
    List tarefas = dao.buscarTarefas(“id”);
    this.tarefas = tarefas;
    s.close();
    return “ok”;
    }
    public List getTarefas() {
    return tarefas;
    }
    }
    [/code]

AutorizadorInterceptor.java

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package br.com.gbd.interceptor;

import br.com.gbd.hibernate.Usuarios;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

/**
*

  • @author Henrique
    */
    public class AutorizadorInterceptor implements Interceptor {

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
    Usuarios usuarioLogado = (Usuarios) invocation.getInvocationContext().
    getSession().get(“usuarioLogado”);
    if (usuarioLogado == null) {
    return “naoLogado”;
    }
    return invocation.invoke();
    }

    @Override
    public void destroy() {
    }

    @Override
    public void init() {
    }
    }
    [/code]

Diretórios:

Estou seguindo uma apostila da Caelum: FJ21.

Muito Obrigado! E caso tenha erros ou má práticas de programação por favor me informem :slight_smile:


Agora que vi que possui uma área dedicada apenas para Java Web, por favor, alguém poderia mover minha dúvida para a área correta? Obrigado.

Você está misturando as coisas,.
Quando você opta pelo uso do struts.xml, não deve usar as annotations.
Além disso, deve manter o struts.xml na pasta src do projeto, para que o struts 2 consiga ler as configurações nele contidas.
Eu, particularmente, não utilizaria o arquivo xml. Prefiro as annotations.

[quote=drsmachado]Você está misturando as coisas,.
Quando você opta pelo uso do struts.xml, não deve usar as annotations.
Além disso, deve manter o struts.xml na pasta src do projeto, para que o struts 2 consiga ler as configurações nele contidas.
Eu, particularmente, não utilizaria o arquivo xml. Prefiro as annotations.[/quote]

Como estou usando o Netbeans e não sei ao certo qual diretório é equivalente ao src, movi o arquivo para a pasta src navegando através dos diretórios mesmo.
Não entendi muito bem o que estou misturando… como seria a maneira correta? Não é necessário utilizar o xml também?
Acho que meu arquivo struts.xml não está sendo reconhecido, pois ao tentar acessar a ação AddTarefa declarada dentro do xml recebo o erro informando ação não mapeada.

Desculpe o incomodo…

Veja bem, se você coloca qualquer annotation em seu Action, não precisa do struts.xml.
O erro não ocorre por conta da não leitura do struts.xml, mas, por que você nomeou o ParentPackage como “default”

@ParentPackage("default") 

E este não existe. Para corrigir isso, sugiro que exclua o struts.xml e altere o Action para

@ParentPackage("struts-default")
@Namespace("/")

Isso deverá ajudar.

[quote=drsmachado]Veja bem, se você coloca qualquer annotation em seu Action, não precisa do struts.xml.
O erro não ocorre por conta da não leitura do struts.xml, mas, por que você nomeou o ParentPackage como “default”

@ParentPackage("default") 

E este não existe. Para corrigir isso, sugiro que exclua o struts.xml e altere o Action para

@ParentPackage("struts-default")
@Namespace("/")

Isso deverá ajudar.[/quote]

Darlan acho que entendi porém, estou seguindo uma apostila da Caelum e nela é feito de maneira semelhante a que fiz. Sem querer abusar de sua boa vontade (e já abusando!!), separei algumas dúvidas que não consegui solucionar Googlando.

  1. É possível utilizar os XML junto com as annotations? Vi no seu blog que as annotations possuem limitações e não existe uma com função equivalente para todas tags do xml.

  2. Considerando que exclui meu struts.xml, como eu informaria ao Struts2 todas as informações que estavam presentes em minhas tags xml? Me refiro as referentes ao interceptador

  3. Utilizando os diretórios do Netbeans, sabe me informar qual é o local correto para salvar o struts.xml? Ao criar um projeto novo com exemplo Struts 2 o arquivo xml ficou salvo no caminho: src/java/struts.xml

  4. Tentando desacoplar uma ação que chama um jsp (Always Link) inseri o seguinte código em meu struts.xml:

<package name="default" extends="struts-default"> <action name="tarefaForm" > <result>/WEB-INF/content/formulario-tarefas.jsp</result> </action> </package>
Mas quando chamo pela ação da que não foi mapeada… por isso achei que meu struts.xml estava com problemas ou no lugar errado.

Segue um Link com a apostila, creio que você já domine tudo presente nela mas é um excelente material: http://pt.slideshare.net/KIQMoretto/caelum-javawebfj21-15677789?from_search=2

Sei que provavelmente são perguntas bobas, mas não foi falta de procurar no Google… realmente estou com algumas dificuldades, creio que com o tempo eu consiga superar isso.

Muito Obrigado.

É possível sim, mas não o mais indicado. Se você vai usar o xml, fique apenas com ele.
Sugiro que mude para o eclipse, até onde lembro, as apostilas da caelum todas estão baseadas nesta IDE e, se você pretende trabalhar com java mesmo, vai precisar utilizá-lo. É raro lugares onde você possa utilizar netbeans.
eu trabalho há quase 4 anos só com o eclipse, não me recordo “de cabeça” de qual a estrutura das pastas do netbeans.

Entendi… Essa parte do Netbeans realmente necessito repensar.

Seguindo suas dicas consegui localizar o erro. Na verdade o código oferecido pela apostila estava correto e como eu imaginava o Struts não estava conseguindo identificar o seu arquivo de configurações (struts.xml). Procurando pelo erro no Google acabei encontrando algumas soluções incorretas e acabei bagunçando mais ainda meu código.
Algumas conclusões que tive e acho importante repassar:

-Ao contrário do que eu pensava, não é necessário informar no web.xml a localização do struts.xml.

-Sobre o diretório correto do struts.xml: Além do IDE Netbeans, estou utilizando também o Maven. Isso acabou me confundindo um pouco do local correto para armazenar o arquivo de configurações do Struts 2. No meu caso, solucionei os problemas jogando o struts.xml para o diretório:

-Algumas das configurações que fiz utilizando o xml não possuem annotations equivalentes (), ou seja, tive que manter o arquivo xml. , , são exemplos de configurações presentes apenas no xml.

-As vezes é interessante utilizar xml mesmo tento um projeto quase 100% annotations. Algumas coisas realmente são mais simples de se trabalhar utilizando as tags.

Segue como ficaram meus arquivos:

web.xml

<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" 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_3_0.xsd"> <session-config> <session-timeout> 30 </session-timeout> </session-config> <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> <welcome-file-list> <welcome-file>Index</welcome-file> </welcome-file-list> </web-app>

struts.xml

[code]

/WEB-INF/content/formulario-login.jsp /WEB-INF/content/formulario-tarefas.jsp [/code]

AutorizadorInterceptor.java

[code]package br.com.gbd.interceptor;
import br.com.gbd.hibernate.Usuarios;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;

public class AutorizadorInterceptor implements Interceptor {

 @Override
public String intercept(ActionInvocation invocation) throws Exception {
    Usuarios usuarioLogado = (Usuarios) invocation.getInvocationContext().
            getSession().get("usuarioLogado");
    if (usuarioLogado == null) {
        return "naoLogado";
    }
    return invocation.invoke();
}

@Override
public void destroy() {
}

@Override
public void init() {
}

}
[/code]

Exemplo de ação utilizando interceptadores:
ListarTarefasAction.java

[code]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.
    */
    package br.com.gbd.action;

import br.com.gbd.hibernate.HibernateUtil;
import br.com.gbd.hibernate.Tarefas;
import br.com.gbd.hibernate.TarefasDAO;
import com.opensymphony.xwork2.ActionSupport;
import java.util.List;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.hibernate.Session;

/**
*

  • @author Henrique
    */
    @ParentPackage(“default”)
    public class ListarTarefasAction extends ActionSupport{
    private List tarefas;

    @Action(value = “listaTarefas”, results = {
    @Result(name = “ok”, location = “Tarefas/lista.jsp”)}, interceptorRefs= {@InterceptorRef(“seguranca”)})

    public String execute() {
    TarefasDAO dao = new TarefasDAO();
    Session s = HibernateUtil.getSession();
    s.beginTransaction();
    List tarefas = dao.buscarTarefas(“id”);
    this.tarefas = tarefas;
    s.close();
    return “ok”;
    }
    public List getTarefas() {
    return tarefas;
    }
    }
    [/code]

Muito Obrigado pela ajuda, caso tenha cometido algum equivoco em minha conclusão por favor me informe.
O projeto está rodando perfeitamente, apostila Caelum completa com sucesso.