Erro CRUD banco de dados Postgres/Java

Olá pessoal, Estou estudando JSP/Servlets e esta dando um erro ao fazer um salvamento no BD postgres, quando executo minha aplicação desktop salva normal, mas quando reutilizo o mesmo cod para uma Servlet da erro no meu PreparedStatement, só que n dava erro antes. estranho isso.
Segue o erro acabixo ---------------------------------------------------------------------------------------------

ago 25, 2020 4:50:02 PM org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() for servlet [br.com.caelum.servlet.AdicionaContatoServlet] in context with path [/EstudosLivroJavaWebJspServlets] threw exception
java.lang.NullPointerException
at br.com.caelum.jdbc.dao.ContatoDao.adiciona(ContatoDao.java:26)
at br.com.caelum.servlet.AdicionaContatoServlet.service(AdicionaContatoServlet.java:54)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:475)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:651)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:500)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:754)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1376)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)

meu code de salvar q funciona de boa no mode descktop mas n funciona no apache

@WebServlet("/adicionaContatoServlet")
public class AdicionaContatoServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
// busca o writer
PrintWriter out = response.getWriter();
// buscando os parâmetros no request
String nome = request.getParameter(“nome”);
String endereco = request.getParameter(“endereco”);
String email = request.getParameter(“email”);
String dataEmTexto = request
.getParameter(“dataNascimento”);
Calendar dataNascimento = null;
// fazendo a conversão da data

	try {
	Date date =
	new SimpleDateFormat("dd/MM/yyyy").parse(dataEmTexto);
	dataNascimento = Calendar.getInstance();
	dataNascimento.setTime(date);
	} catch (ParseException e) {
	out.println("Erro de conversão da data");
	return; //para a execução do método
	}
	// monta um objeto contato
	Contato contato = new Contato();
	
	contato.setNome(nome);
	contato.setEndereco(endereco);
	contato.setEmail(email);
	contato.setDataNascimento(dataNascimento);
	
	// salva o contato
	ContatoDao dao = new ContatoDao();
	dao.adiciona(contato);
	// imprime o nome do contato que foi adicionado
	out.println("<html>");
	out.println("<body>");
	out.println("Contato " + contato.getNome() +
	" adicionado com sucesso");
	out.println("</body>");
	out.println("</html>");
	
	
}

}

Classe DAO

package br.com.caelum.jdbc.dao;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
//import java.util.Date;
import java.util.List;

import br.com.caelum.jdbc.ConnectionFactory;
import br.com.caelum.jdbc.modelo.Contato;

public class ContatoDao {
private Connection connection;

public ContatoDao() {
	this.connection = new ConnectionFactory().getConnection();
}

public boolean adiciona(Contato contato) {
	try {
		String sql = "INSERT INTO contatos (nome, email, endereco, dataNascimento) VALUES (?,?,?,?)";
		PreparedStatement stmt = connection.prepareStatement(sql);
		
		stmt.setString(1, contato.getNome());
		stmt.setString(2, contato.getEmail());
		stmt.setString(3, contato.getEndereco());
		stmt.setDate(4, new Date(contato.getDataNascimento().getTimeInMillis()));
		
		stmt.execute();
		stmt.close();
		connection.close();
		return true;
	} catch (SQLException e) {
		e.printStackTrace();
	}
	return false;
}

Class Factory

package br.com.caelum.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;

public class ConnectionFactory {

public Connection getConnection() {
	try {
		String user = "postgres";
		String password = "admin";
		String url = "jdbc:postgresql://localhost:5432/postgres";
		return DriverManager.getConnection(url, user, password);
	} catch (Exception e) {
		// TODO: handle exception
	}
	return null;
}

}

a unica diferença é que meu cod agora esta dentro do metodo Service da HTTPSERVLET, n sei se isso muda algo.

Eu pesquisei o erro na internet e algumas pessoas disseram que resolveram atualizando o Tomcat. Qual versão vc tá usando?

@valdecir_luciano Mostra essa tua classe

package br.com.caelum.jdbc.dao;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
//import java.util.Date;
import java.util.List;

import br.com.caelum.jdbc.ConnectionFactory;
import br.com.caelum.jdbc.modelo.Contato;

public class ContatoDao {
private Connection connection;

public ContatoDao() {
	this.connection = new ConnectionFactory().getConnection();
}

public boolean adiciona(Contato contato) {
	try {
		String sql = "INSERT INTO contatos (nome, email, endereco, dataNascimento) VALUES (?,?,?,?)";
		PreparedStatement stmt = connection.prepareStatement(sql);
		
		stmt.setString(1, contato.getNome());
		stmt.setString(2, contato.getEmail());
		stmt.setString(3, contato.getEndereco());
		stmt.setDate(4, new Date(contato.getDataNascimento().getTimeInMillis()));
		
		stmt.execute();
		stmt.close();
		connection.close();
		return true;
	} catch (SQLException e) {
		e.printStackTrace();
	}
	return false;
}

Mostra essa aqui

package br.com.caelum.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;

public class ConnectionFactory {

public Connection getConnection() {
	try {
		String user = "postgres";
		String password = "admin";
		String url = "jdbc:postgresql://localhost:5432/postgres";
		return DriverManager.getConnection(url, user, password);
	} catch (Exception e) {
		// TODO: handle exception
	}
	return null;
}

}

Verifica essa url de conexão pode ser que ele não esteja conectando, o erro pode estar no usuário , senha ou nome do banco, ou então se o banco esta ativo, ele tá disparando uma exceção dai esse método retorna NULL, por isso o NullPointerException ocorre qndo vc chama o metodo adiciona da classe ContatoDao

Obrigado pelo empenho em me ajudar. Vou dar uma olhada aqui.