Olá galera!
Inventei de começar a brincar com o struts 2 (primeira framework que utilizo para desenvolver).
Primeiramente vou mostrar o meu código e gostaria de que me auxiliassem na resolução do erro (e gostaria de umas dicas também para melhorar meu código, pois não comecei há muito tempo…)
Primeiramente a classe abstrata User (modelo)
package br.com.search4help.model;
abstract public class User{
private String matricula;
private String cpf;
private String nome;
private String email;
private String login;
private String password;
private String checkPassword;
public String getCheckPassword() {
return checkPassword;
}
public void setCheckPassword(String checkPassword) {
this.checkPassword = checkPassword;
}
private boolean chamadoAberto;
private boolean admin;
public boolean isAdmin() {
return admin;
}
public void setAdmin(boolean admin) {
this.admin = admin;
}
public User(){
this.chamadoAberto = false;
}
public String getMatricula() {
return matricula;
}
public void setMatricula(String matricula) {
this.matricula = matricula;
}
public String getCpf() {
return cpf;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isChamadoAberto() {
return chamadoAberto;
}
public void setChamadoAberto(boolean chamadoAberto) {
this.chamadoAberto = chamadoAberto;
}
}
É abstrata pois existem mais de um tipo de usuário.
Em seguida a classe Funcionario (extends User)
package br.com.search4help.model;
public class Funcionario extends User{ //obtém atributos e comportamentos de um User; falta implementar outras funcionalidades específicas.
public Funcionario(){
this.setAdmin(false);
}
}
A classe ConexaoInterceptor (Interceptador que abre e fecha conexões com o banco) [é correto utilizar um interceptador para este fim? Pensei em um filtro, porém não descobri como fazer a minha action pegar os dados da conexão através da sessão… :(]
package br.com.search4help.interceptor;
import java.sql.Connection;
import br.com.search4help.jdbc.ConnectionFactory;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class ConexaoInterception implements Interceptor{
/**
*
*/
private static final long serialVersionUID = 1L;
private Connection connection;
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init() {
// TODO Auto-generated method stub
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
this.connection = ConnectionFactory.getConnection();
invocation.getInvocationContext().getSession().put("conexao",connection);
System.out.println("conexão aberta por interceptor");
invocation.invoke();
this.connection.close();
System.out.println("conexão fechada por interceptor");
return "ok";
}
}
A classe funcionarioDAO (que está parcialmente implementada… mas o que importa mesmo é a sua superclasse Logable, onde está o método que me dá dor de cabeça…)
package br.com.search4help.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import br.com.search4help.model.Funcionario;
public class FuncionarioDAO extends Logable{
public FuncionarioDAO(Connection connection){
super(connection);
}
public boolean abrirChamado(Funcionario func) throws SQLException{
try{
PreparedStatement stmt = this.connection.prepareStatement("");
return true;
}catch(SQLException e){
e.printStackTrace();
return false;
}
}
}
A index.jsp, onde o usuário fornece o login e a senha para entrar
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!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>
<div>
<form name="formulario" action="loginFuncionario" method="POST">
<table border="1" cellpadding="5" cellspacing="0">
<thead>
<tr>
<th colspan="2" scope="col">Search4help :: Login</th>
</tr>
</thead>
<tbody>
<tr>
<td align="right">Login: </td><td><input type="text" name="funcionario.login" size="20" /></td>
</tr>
<tr>
<td>Password:</td><td><input type="password" name="funcionario.password" size="20" /></td>
</tr>
<tr>
<td colspan="2" align="right"><input type="submit" name="submit" value="Entrar" /></td>
</tr>
</tbody>
</table>
</form>
</div>
</body>
</html>
Segue abaixo a minha Action, a classe LoginAction, que tenta utilizar o método “isAccessGranted” para jogar na sessão um usuário válido através do login e senha fornecidos pelo usuário da index.jsp.
package br.com.search4help.action;
import java.sql.Connection;
import java.sql.SQLException;
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 br.com.search4help.dao.AdminDAO;
import br.com.search4help.model.Funcionario;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
@ParentPackage("default")
public class LoginAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
private Funcionario funcionario;
private Connection connection;
@Action(value = "loginFuncionario", results = {
@Result(name = "ok", location = "/admin/index.jsp"),
@Result(name = "invalido", location = "/index.jsp") }, interceptorRefs = {
@InterceptorRef("conexao")
}
)
public String execute() throws SQLException {
try {
this.connection = (Connection) ActionContext.getContext().getSession().get("conexao"); //<--pega a conexão gerada pelo interceptor que está na sessão.
if ((new AdminDAO(connection).isAccessGranted(funcionario))) {//<-- AQUI É A LINHA QUE DISPARA O NullPointerException!!
ActionContext.getContext().getSession().put("usuarioLogado",funcionario);//<-- caso OK, joga o usuário na sessão.
System.out.println("funcionario registrado na sessão");
} else {
System.out.println("erro durante abertura de sessão");
return "invalido";
}
return "ok";
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
public Connection getConnection() {
return connection;
}
public void setConnection(Connection connection) {
this.connection = connection;
}
public Funcionario getFuncionario() {
return funcionario;
}
public void setFuncionario(Funcionario funcionario) {
this.funcionario = funcionario;
}
}
E finalmente a classe Logable que dispara o NullPointerException: a classe abstrata Logable (trata-se de uma DAO… acredito que poderia fazer dela uma interface, porém a implementação deve ser exatamente a mesma para todos os que herdarem o método “isAccessGranted”, o que acham?)
package br.com.search4help.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import br.com.search4help.model.Funcionario;
import br.com.search4help.model.User;
abstract public class Logable {
public Connection connection;
public Logable(Connection connection){ //<-- Construtor com injeção de dependencia... depende de um Connection
this.connection = connection;
}
public boolean isAccessGranted(User user) throws SQLException{
try{
String sql = "SELECT * FROM tbl_funcionario WHERE login=? and password=?"; // <-- verifica a existência de um usuário pelo login e password.
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1,user.getLogin());
stmt.setString(2,user.getPassword());
ResultSet rs = stmt.executeQuery();
while(rs.next()){
return true;
}
return false;
}catch(SQLException e){
e.printStackTrace();
return false;
}catch(NullPointerException e){
System.out.println("O usuário é nulo");
e.printStackTrace();
return false;
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>search4help</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<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>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>br.com.search4help.controller.ServletLoginFuncionario</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>logout</servlet-name>
<servlet-class>br.com.search4help.controller.ServletLogout</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>logout</servlet-name>
<url-pattern>/logout.do</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>function</servlet-name>
<servlet-class>br.com.search4help.controller.ServletFunction</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>function</servlet-name>
<url-pattern>/admin/function.do</url-pattern>
</servlet-mapping>
<filter>
<filter-name>filtroLogin</filter-name>
<filter-class>br.com.search4help.controller.FiltroLogin</filter-class>
</filter>
<filter-mapping>
<filter-name>filtroLogin</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>filtroConexao</filter-name>
<filter-class>br.com.search4help.controller.FiltroConexao</filter-class>
</filter>
<filter-mapping>
<filter-name>filtroConexao</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<session-config>
<session-timeout>3</session-timeout>
</session-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>
<!-- configs iniciais padrão do Struts 2 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<constant name="struts.devMode" value="false" />
<!-- mapeamento de minhas classes e respostas (forwards) -->
<package name="default" extends="convention-default">
<interceptors>
<interceptor name="conexao" class="br.com.search4help.interceptor.ConexaoInterception">
</interceptor>
</interceptors>
</package>
</struts>
É isso galera…
gostaria de saber o por quê do NullPointerException, uma vez que o struts deveria instanciar e popular o “funcionario” e passar para o método através dos atributos e dos getters e setters da action… (correto???)
agradeço!