Como salvar no DB um arquivo enviado numa requisição?

Olá, estou tendo um probleminha com NullPointerException ao enviar um arquivo pra minha servlet salvar no db.

A dúvida é a seguinte, no meu bean, eu to com um método setFoto( Blobo foto), e quando eu populo meu bean com uma API da jakarta, dá esse erro aqui (no console do eclipse):

java.lang.IllegalArgumentException: Cannot invoke br.unisc.model.Contato.setFoto - argument type mismatch
	at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:1778)
	at org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:1759)
	at org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1648)
	at org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:1677)
	at org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:1022)
	at org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:811)
	at org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:298)
	at br.unisc.utils.BeanUtilities.populateBean(BeanUtilities.java:31)
	at br.unisc.utils.BeanUtilities.populateBean(BeanUtilities.java:24)
	at br.unisc.control.Controller.doPost(Controller.java:51)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
	at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
	at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
	at java.lang.Thread.run(Unknown Source)
java.lang.IllegalArgumentException: Cannot invoke br.unisc.model.Contato.setFoto - argument type mismatch
	at org.apache.commons.beanutils.PropertyUtilsBean.invokeMethod(PropertyUtilsBean.java:1778)
	at org.apache.commons.beanutils.PropertyUtilsBean.setSimpleProperty(PropertyUtilsBean.java:1759)
	at org.apache.commons.beanutils.PropertyUtilsBean.setNestedProperty(PropertyUtilsBean.java:1648)
	at org.apache.commons.beanutils.PropertyUtilsBean.setProperty(PropertyUtilsBean.java:1677)
	at org.apache.commons.beanutils.BeanUtilsBean.setProperty(BeanUtilsBean.java:1022)
	at org.apache.commons.beanutils.BeanUtilsBean.populate(BeanUtilsBean.java:811)
	at org.apache.commons.beanutils.BeanUtils.populate(BeanUtils.java:298)
	at br.unisc.utils.BeanUtilities.populateBean(BeanUtilities.java:31)
	at br.unisc.utils.BeanUtilities.populateBean(BeanUtilities.java:24)
	at br.unisc.control.Controller.doPost(Controller.java:51)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
	at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
	at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
	at java.lang.Thread.run(Unknown Source)

E no tomcat dá esse erro (porque não consegui preencher a propriedade do objeto para mim persistir na base):

exception 

java.lang.NullPointerException
	com.mysql.jdbc.PreparedStatement.setBlob(PreparedStatement.java:257)
	br.unisc.dao.generic.ContatoGeneric.save(ContatoGeneric.java:63)
	br.unisc.control.Controller.doPost(Controller.java:53)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

Já vi que tem merda no parâmetro. A questão é, como eu faço pra inserir no meu bean, o arquivo que está sendo enviado na requisição??
Vou ter que salvar esse arquivo em disco, e depois lê-lo e salvar no bean pra mim persistir na base?

Antes que alguém me diga, que é melhor salvar no disco, e guardar somente o caminho e o nome, já vou adiantando que isso foi especificação, e eu não posso fugir disso.
Gostaria mto de dar um upload no server e trabalhar somente com os paths, sei que é mais veloz, mas eu não posso fugir da especificação…

Obrigado à todos que coloborarem.

Segue abaixo os códigos, se quiserem ver…

Controller.java

package br.unisc.control;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import br.unisc.dao.generic.ContatoGeneric;
import br.unisc.model.Contato;
import br.unisc.utils.BeanUtilities;

public class Controller extends javax.servlet.http.HttpServlet {

	private static final long serialVersionUID = 1L;


	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException {
		doPost( request, response );
	}  	
	
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
		throws ServletException, IOException {
		String action = request.getParameter( "action" );
		String address = "";
		/**
		 * <pre>Encaminha o pedido para jsp principal</pre>
		 */
		if ( action == null ) {
			address = "/index.jsp";
		
		/**
		 * <pre>Encaminha o pedido para a jsp de cadastro</pre>
		 */
		} else if( action.equals("newContato") ) {
			address = "/WEB-INF/jsp/newcontato.jsp";
		/**
		 * <pre>Recebe o pedido do formulário
		 * e salva o contato no DB.</pre>
		 */
		} else if( action.equals("saveContato") ) {
			if( request.getParameter("nome") == null || request.getParameter("nome").equals("")) {
				address = "/WEB-INF/jsp/newcontato.jsp";
			} else {
				Contato contato = new Contato();
				BeanUtilities.populateBean(contato, request);
				
				ContatoGeneric cg = new ContatoGeneric();
				cg.save(contato);
				address = "/index.jsp";
			}
		/**
		 * <pre>Encaminha o pedido para a jsp que lista
		 * os contatos em uma lista. </pre>
		 */
		} else if( action.equals("listContatos") ) {
			ArrayList contatos = new ArrayList();
			ContatoGeneric gc = new ContatoGeneric();
			contatos = (ArrayList) gc.getContatos( false );
			HttpSession session = request.getSession();
			session.setAttribute("contatos", contatos );
			address = "/jsp/listcontatos.jsp";
		/**
		 * <pre>Encaminha o pedido
		 * para a jsp responsável por alterar os
		 * dados na db. </pre>
		 */
		} else if( action.equals("editContato") ) { 
			ContatoGeneric gc = new ContatoGeneric();
			Contato contato = new Contato();
			contato = gc.selectById( Integer.parseInt( request.getParameter("idContato") ) );
			request.setAttribute("contato", contato );
			address = "/WEB-INF/jsp/editcontato.jsp";
		/**
		 * <pre>Recebe o pedido e salva as alterações
		 * do objeto no DB.</pre>
		 */
		} else if( action.equals("updateContato") ) {
			Contato contato = new Contato();
			BeanUtilities.populateBean( contato, request );
			ContatoGeneric gc = new ContatoGeneric();
			gc.update( contato );
			address = "/index.jsp";
		} else {
			address = "/index.jsp";;
		}
		
		RequestDispatcher rd = request.getRequestDispatcher( address );
		rd.forward( request, response );
	}   	  	    
}

ContatoGeneric.java

/*
 * ContatoGeneric.java
 * Criado em: 27/05/2006 - 19:37:21
 * Copyright (c) 2006, Misael Silveira
 * All rights reserved.
 */
/**
 * @author Misael Silveira
 * @version $Id: $
 */
package br.unisc.dao.generic;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

import br.unisc.dao.ContatoDAO;
import br.unisc.db.DataBase;
import br.unisc.model.Contato;

public class ContatoGeneric implements ContatoDAO {
	
	public static final int SELECT_BY_NOME 			= 0;
	public static final int SELECT_BY_SOBRENOME 	= 1;
	public static final int SELECT_BY_EMAIL 		= 2;
	public static final int SELECT_BY_CIDADE 		= 3;
	public static final int SELECT_BY_BAIRRO 		= 4;	
		
	public void save(Contato contato) {
		try {
			
			String sql = "INSERT INTO contato SET " +
					"id_usuario = ?, " +
					"nome = ?, " +
					"sobrenome = ?, " +
					"apelido = ?, " +
					"email = ?, " +
					"tel_residencial = ?, " +
					"tel_trabalho = ?, " +
					"celular = ?, " +
					"endereco = ?, " +
					"bairro = ?, " +
					"cidade = ?, " +
					"cep = ?, " +
					"foto = ?";
			
			DataBase db = new DataBase();
			Connection conn = db.open();
			PreparedStatement pstm = conn.prepareStatement( sql );
			
			pstm.setInt( 1, contato.getId_usuario() );
			pstm.setString( 2, contato.getNome() );
			pstm.setString( 3, contato.getSobrenome() );
			pstm.setString( 4, contato.getApelido() );
			pstm.setString( 5, contato.getEmail() );
			pstm.setString( 6, contato.getTel_residencial() );
			pstm.setString( 7, contato.getTel_trabalho() );
			pstm.setString( 8, contato.getCelular() );
			pstm.setString( 9, contato.getEndereco() );
			pstm.setString( 10, contato.getBairro() );
			pstm.setString( 11, contato.getCidade() );
			pstm.setString( 12, contato.getCep() );
			pstm.setBlob( 13, contato.getFoto() );
			
			pstm.execute();
			
			pstm.close();
			conn.close();
			db.close();
			
			
		} catch( SQLException ex ) {
			System.err.println( "Erro ao persistir contato na base de dados!" );
			ex.printStackTrace();
		}

	}

	public void update(Contato contato) {
	try {
			
			String sql = "UPDATE contato SET " +
					"id_usuario = ?, " +
					"nome = ?, " +
					"sobrenome = ?, " +
					"apelido = ?, " +
					"email = ?, " +
					"tel_residencial = ?, " +
					"tel_trabalho = ?, " +
					"celular = ?, " +
					"endereco = ?, " +
					"bairro = ?, " +
					"cidade = ?, " +
					"cep = ?, " +
					"foto = ? " +
					"WHERE id_contato = ? ";
			
			DataBase db = new DataBase();
			Connection conn = db.open();
			PreparedStatement pstm = conn.prepareStatement( sql );
			
			pstm.setInt( 1, contato.getId_usuario() );
			pstm.setString( 2, contato.getNome() );
			pstm.setString( 3, contato.getSobrenome() );
			pstm.setString( 4, contato.getApelido() );
			pstm.setString( 5, contato.getEmail() );
			pstm.setString( 6, contato.getTel_residencial() );
			pstm.setString( 7, contato.getTel_trabalho() );
			pstm.setString( 8, contato.getCelular() );
			pstm.setString( 9, contato.getEndereco() );
			pstm.setString( 10, contato.getBairro() );
			pstm.setString( 11, contato.getCidade() );
			pstm.setString( 12, contato.getCep() );
			pstm.setBlob( 13, contato.getFoto() );
			pstm.setInt( 14, contato.getId_contato() );
			
			pstm.execute();
			
			pstm.close();
			conn.close();
			db.close();
			
			
		} catch( SQLException ex ) {
			System.err.println( "Erro ao persistir contato na base de dados!\n" );
			ex.printStackTrace();
		}

	}

	public void delete(Contato contato) {
		try {
			String sql = "DELETE FROM contato WHERE id_contato = ?";
			DataBase db = new DataBase();
			Connection conn = db.open();
			PreparedStatement pstm = conn.prepareStatement( sql );
			pstm.setInt(1,  contato.getId_contato() );
			
			pstm.execute();
			
			pstm.close();
			conn.close();
			db.close();
			
			
		} catch ( SQLException ex ) {
			System.err.println("Erro ao remover contato da base de dados!\n");
			ex.printStackTrace();
		}

	}

	public List getContatos(boolean ordenados ) {
		ArrayList contatos = new ArrayList();
		
		try {
			String sql = "SELECT * from contato";
			if(ordenados) {
				sql += " ORDER BY nome";
			} else {
				sql += " ORDER BY id_contato";
			}
			
			DataBase db = new DataBase();
			Connection conn = db.open();
			PreparedStatement pstm = conn.prepareStatement( sql );
			ResultSet rs = pstm.executeQuery();
			
			while( rs.next() ) {
				Contato contato = new Contato();
				contato.setId_contato( rs.getInt( "id_contato") );
				contato.setId_usuario( rs.getInt( "id_usuario") );
				contato.setNome( rs.getString("nome") );
				contato.setSobrenome( rs.getString( "sobrenome") );
				contato.setApelido( rs.getString("apelido") );
				contato.setEmail( rs.getString("email") );
				contato.setTel_residencial( rs.getString( "tel_residencial" ) );
				contato.setTel_trabalho( rs.getString("tel_trabalho") );
				contato.setCelular( rs.getString( "celular") );
				contato.setEndereco( rs.getString("endereco") );
				contato.setBairro( rs.getString( "bairro") );
				contato.setCidade( rs.getString( "cidade") );
				contato.setCep( rs.getString("cep") );
				contato.setFoto( rs.getBlob("foto") );
				
				contatos.add( contato );				
				
			}
			rs.close();
			pstm.close();
			conn.close();
			db.close();
		} catch ( SQLException ex ) {
			System.err.println("Erro ao listar contatos!! \n");
			ex.printStackTrace();
		}
		
		return contatos;
	}

	public Contato selectById(int idContato) {
		try {
			String sql = "SELECT * from contato WHERE id_contato = ?";
			DataBase db = new DataBase();
			Connection conn = db.open();
			PreparedStatement pstm = conn.prepareStatement( sql );
			
			pstm.setInt(1, idContato );
			
			ResultSet rs = pstm.executeQuery();
			
			if( rs.next() ) {
				Contato contato = new Contato();
				contato.setId_contato( rs.getInt( "id_contato") );
				contato.setId_usuario( rs.getInt( "id_usuario") );
				contato.setNome( rs.getString("nome") );
				contato.setSobrenome( rs.getString( "sobrenome") );
				contato.setApelido( rs.getString("apelido") );
				contato.setEmail( rs.getString("email") );
				contato.setTel_residencial( rs.getString( "tel_residencial" ) );
				contato.setTel_trabalho( rs.getString("tel_trabalho") );
				contato.setCelular( rs.getString( "celular") );
				contato.setEndereco( rs.getString("endereco") );
				contato.setBairro( rs.getString( "bairro") );
				contato.setCidade( rs.getString( "cidade") );
				contato.setCep( rs.getString("cep") );
				contato.setFoto( rs.getBlob("foto") );
				
				rs.close();
				pstm.close();
				conn.close();
				db.close();
				
				return contato;
			}
			rs.close();
			pstm.close();
			conn.close();
			db.close();

		} catch ( SQLException ex ) {
			System.err.println( "Erro ao executar query! \n" );
			ex.printStackTrace();
		} 
		
		return null;
	}

	public List selectContatosByOpcao(int opcao, boolean ordenados, String value) {
		
		ArrayList contatos = new ArrayList();
		
		try {
			String sql = "SELECT * FROM contato WHERE ";
			
			switch( opcao ) {
				case SELECT_BY_NOME: 
					sql += " nome = ?";
					break;
					
				case SELECT_BY_SOBRENOME: 
					sql += " sobrenome = ?";
					break;
										
				case SELECT_BY_EMAIL:
					sql += " email = ?";
					break;
					
				case SELECT_BY_CIDADE:
					sql += " cidade = ?";
					break;
					
				case SELECT_BY_BAIRRO:
					sql += " bairro = ?";
					break;
				
				default:
					sql += " nome = ?";
					break;
			}
			
			if(ordenados) {
				sql += " ORDER BY nome";
			} else {
				sql += " ORDER BY id_contato";
			}
			
			DataBase db = new DataBase();
			Connection conn = db.open();
			PreparedStatement pstm = conn.prepareStatement( sql );
			pstm.setString(1, value );
			
			ResultSet rs = pstm.executeQuery();
			
			while( rs.next() ) {
				Contato contato = new Contato();
				contato.setId_contato( rs.getInt( "id_contato") );
				contato.setId_usuario( rs.getInt( "id_usuario") );
				contato.setNome( rs.getString("nome") );
				contato.setSobrenome( rs.getString( "sobrenome") );
				contato.setApelido( rs.getString("apelido") );
				contato.setEmail( rs.getString("email") );
				contato.setTel_residencial( rs.getString( "tel_residencial" ) );
				contato.setTel_trabalho( rs.getString("tel_trabalho") );
				contato.setCelular( rs.getString( "celular") );
				contato.setEndereco( rs.getString("endereco") );
				contato.setBairro( rs.getString( "bairro") );
				contato.setCidade( rs.getString( "cidade") );
				contato.setCep( rs.getString("cep") );
				contato.setFoto( rs.getBlob("foto") );
				
				contatos.add( contato );				
				
			}
			rs.close();
			pstm.close();
			conn.close();
			db.close();
		} catch ( SQLException ex ) {
			System.err.println("Erro ao listar contatos!! \n");
			ex.printStackTrace();
		}
		
		return contatos;
	}

}

Contato.java

/*
 * Contato.java
 * Criado em: 21/05/2006 - 15:18:27
 * Copyright (c) 2005, Misael Silveira
 * All rights reserved.
 */
/**
 * @author Misael Silveira
 * @version $Id: $
 */
package br.unisc.model;

import java.io.FileInputStream;
import java.sql.Blob;

public class Contato {
	
	private int id_contato;
	private int id_usuario;
	private String nome;
	private String sobrenome;
	private String apelido;
	private String email;
	private String tel_residencial;
	private String tel_trabalho;
	private String celular;
	private String endereco;
	private String bairro;
	private String cidade;
	private String cep;
	private Blob foto;
	
	/**
	 * @return Returns the apelido.
	 */
	public String getApelido() {
		return apelido;
	}
	
	/**
	 * @return Returns the bairro.
	 */
	public String getBairro() {
		return bairro;
	}
	
	/**
	 * @return Returns the celular.
	 */
	public String getCelular() {
		return celular;
	}
	
	/**
	 * @return Returns the cep.
	 */
	public String getCep() {
		return cep;
	}
	
	/**
	 * @return Returns the cidade.
	 */
	public String getCidade() {
		return cidade;
	}
	
	/**
	 * @return Returns the email.
	 */
	public String getEmail() {
		return email;
	}
	
	/**
	 * @return Returns the endereco.
	 */
	public String getEndereco() {
		return endereco;
	}
	
	/**
	 * @return Returns the foto.
	 */
	public Blob getFoto() {
		return foto;
	}
	
	/**
	 * @return Returns the id_contato.
	 */
	public int getId_contato() {
		return id_contato;
	}
	
	/**
	 * @return Returns the id_usuario.
	 */
	public int getId_usuario() {
		return id_usuario;
	}
	
	/**
	 * @return Returns the nome.
	 */
	public String getNome() {
		return nome;
	}
	
	/**
	 * @return Returns the sobrenome.
	 */
	public String getSobrenome() {
		return sobrenome;
	}
	
	/**
	 * @return Returns the tel_residencial.
	 */
	public String getTel_residencial() {
		return tel_residencial;
	}
	
	/**
	 * @return Returns the tel_trabalho.
	 */
	public String getTel_trabalho() {
		return tel_trabalho;
	}
	
	/**
	 * @param apelido The apelido to set.
	 */
	public void setApelido(String apelido) {
		this.apelido = apelido;
	}
	
	/**
	 * @param bairro The bairro to set.
	 */
	public void setBairro(String bairro) {
		this.bairro = bairro;
	}
	
	/**
	 * @param celular The celular to set.
	 */
	public void setCelular(String celular) {
		this.celular = celular;
	}
	
	/**
	 * @param cep The cep to set.
	 */
	public void setCep(String cep) {
		this.cep = cep;
	}
	
	/**
	 * @param cidade The cidade to set.
	 */
	public void setCidade(String cidade) {
		this.cidade = cidade;
	}
	
	/**
	 * @param email The email to set.
	 */
	public void setEmail(String email) {
		this.email = email;
	}
	
	/**
	 * @param endereco The endereco to set.
	 */
	public void setEndereco(String endereco) {
		this.endereco = endereco;
	}
	
	/**
	 * @param foto The foto to set.
	 */
	public void setFoto( Blob foto ) {
		this.foto = foto;
	}
	
	/**
	 * @param id_contato The id_contato to set.
	 */
	public void setId_contato(int id_contato) {
		this.id_contato = id_contato;
	}
	
	/**
	 * @param id_usuario The id_usuario to set.
	 */
	public void setId_usuario(int id_usuario) {
		this.id_usuario = id_usuario;
	}
	
	/**
	 * @param nome The nome to set.
	 */
	public void setNome(String nome) {
		this.nome = nome;
	}
	
	/**
	 * @param sobrenome The sobrenome to set.
	 */
	public void setSobrenome(String sobrenome) {
		this.sobrenome = sobrenome;
	}
	
	/**
	 * @param tel_residencial The tel_residencial to set.
	 */
	public void setTel_residencial(String tel_residencial) {
		this.tel_residencial = tel_residencial;
	}
	
	/**
	 * @param tel_trabalho The tel_trabalho to set.
	 */
	public void setTel_trabalho(String tel_trabalho) {
		this.tel_trabalho = tel_trabalho;
	}

}

Você certamente tem um campo do tipo file na sua página não?

Eu não achei no seu código o trecho onde é lido o conteúdo desse campo.

Mas tudo bem, pro seu servlet poder “pegar” esse arquivo informado lá na página JSP você pode usar um componente pra auxiliá-lo.

Pesquise sobre commons-upload, blz?

Eu até agora só usei o componente do struts pra isso pois pra pegar via request sem um componente é bem complexo, foi o que me informou a galera aqui do serviço.

Boa sorte aí…