Problema ao atualizar formulário usando Servlet

Estou fazendo um crud básico em java para por em prática meus conhecimentos sobre servlets. Só me resta agora o servlet de altera, onde justamente estou tendo problemas. Recebo o seguinte erro abaixo na hora que tento alterar. Ele aponta para a linha 25 onde recupero o valor do id do formulário.

java.lang.NumberFormatException: null
	at java.base/java.lang.Long.parseLong(Long.java:655)
	at java.base/java.lang.Long.parseLong(Long.java:817)
	at br.com.henrique.servelets.Editar.doGet(Editar.java:25)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)

index.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"
        import="br.com.henrique.dao.DAO, br.com.henrique.model.Pessoa"%>
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html lang="pt-br">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>

        <style type="text/css">
            .botao{
                text-decoration: none;
                color: black;
                padding: 5px 10px 5px 10px;
                background-color: white;
                border: 1px solid black;
                height: 10px;
                margin-left: 70px;
            }
        </style>
    </head>
    <body style="width: 100%; height: 100%;">

        <div style="width: 25%; margin: 0 auto;" >
            <h1>Cadastro de Pessoa!</h1>
            <form action="Cadastro" method="post">
                <div>
                    <label for="id">ID: </label>
                    <input id="id" type="number" name="id" disabled="true value="<c:out value="${id}"/>" required="">
                </div><br>
                <div>
                    <label for="nome1">Primeiro Nome: </label>
                    <input id="nome1" type="text" name="primeiroNome" value="<c:out value="${primeiroNome}"/>" required="">
                </div><br>
                <div>
                    <label for="nome2">Segundo Nome: </label>
                    <input id="nome2" type="text" name="segundoNome" value="<c:out value="${segundoNome}"/>" required="">
                </div><br>
                <div>
                    <label for="idade">Idade: </label>
                    <input id="idade" type="number" name="idade" value="<c:out value="${idade}"/>" required="">
                </div><br>
                <div>
                    <label for="sexo">Sexo: </label>
                    <input id="sexo" type="text" name="sexo" value="<c:out value="${sexo}"/>" required="">
                </div><br>

                <div>
                    <input value="Cadastrar" type="submit" required="">

                    <a class="botao" style="margin-left: 70px;" href="Editar">Editar</a>

                </div>

            </form><br>
            <c:if test = "${param.primeiroNome != null}" >
                <c:out value="${'<h4 style=color:green;> Pessoa Cadastrada Com Sucesso!</h4>'}" escapeXml="false"></c:out>
            </c:if>
        </div>
        <jsp:useBean class="br.com.henrique.dao.DAO" id="dao"></jsp:useBean>
            <div>
                <table style="width: 100%;" border="1">
                    <tr><th>ID</th><th>Primeiro Nome</th> <th>Segundo Nome</th> <th>Idade</th> <th>Sexo</th><th>Excluir</th><th>Editar</th></tr>
                        <c:forEach  items="${dao.listar()}" var="pessoa">
                    <tr><td><c:out value="${pessoa.id}"/></td><td><c:out value="${pessoa.getPrimeiroNome()}"/></td><td><c:out value="${pessoa.getSegundoNome()}"/></td>
                        <td><c:out value="${pessoa.getIdade()}"/></td><td><c:out value="${pessoa.getSexo()}"/></td><td><a href='Excluir?id=<c:out value="${pessoa.getId()}"/>'>Excluir</a></td>
                        <td><a href='MudarCampo?id=<c:out value="${pessoa.getId()}"/>'>Editar</a></td></tr>
                    </c:forEach>

            </table>
        </div>

    </body>
</html>

Servlet para mudar os campos do formulário(Ao clicar em editar na tabela, ele irá setar no formulário os valores da tabela para fazer a alteração)

package br.com.henrique.servelets;

import br.com.henrique.dao.DAO;
import br.com.henrique.model.Pessoa;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = “MudarCampo”, urlPatterns = {"/MudarCampo"})
public class MudarCampo extends HttpServlet {

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    
    DAO dao = new DAO();
    long id = Long.parseLong(request.getParameter("id"));
    Pessoa pessoa = dao.listarPorId(id);
    request.setAttribute("id", id);
    request.setAttribute("primeiroNome", pessoa.getPrimeiroNome());
    request.setAttribute("segundoNome", pessoa.getSegundoNome());
    request.setAttribute("idade", pessoa.getIdade());
    request.setAttribute("sexo", pessoa.getSexo());
    
    request.getRequestDispatcher("/index.jsp").forward(request, response);
   
}

}

Servlet para Editar

package br.com.henrique.servelets;

import br.com.henrique.dao.DAO;
import br.com.henrique.model.Pessoa;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "Editar", urlPatterns = {"/Editar"})
public class Editar extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        try {
            long id = Long.parseLong(request.getParameter("id"));
            String primeiroNome = request.getParameter("primeiroNome");
            String segundoNome = request.getParameter("segundoNome");
            int idade = Integer.parseInt(request.getParameter("idade"));
            String sexo = request.getParameter("sexo");
            DAO dao = new DAO();

            Pessoa pessoa = dao.listarPorId(id);
            pessoa.setPrimeiroNome(primeiroNome);
            pessoa.setSegundoNome(segundoNome);
            pessoa.setIdade(idade);
            pessoa.setSexo(sexo);
            dao.alterar(pessoa);

        } catch (RuntimeException ex) {
           
            ex.printStackTrace();
        }

        request.getRequestDispatcher("/index.jsp").forward(request, response);
    }

}

Se o erro estiver nessa linha, provavelmente o id não está vindo na request. Reparei que o campo com o id no formulário está como disabled, e, se não me engano, campos disabled não são enviados no request. Tente alterar para readonly.

Na verdade estava faltando passar o parâmetro para o id value="<c:out value="${id}"/>". O erro sumiu, porém estou recebendo outro erro.

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value : br.com.henrique.model.Pessoa.primeiroNome
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
	at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:844)
	at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:820)
	at br.com.henrique.dao.DAO.alterar(DAO.java:95)
	at br.com.henrique.servelets.Editar.doGet(Editar.java:28)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:359)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1735)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value : br.com.henrique.model.Pessoa.primeiroNome
	at org.hibernate.engine.internal.Nullability.checkNullability(Nullability.java:111)
	at org.hibernate.engine.internal.Nullability.checkNullability(Nullability.java:55)
	at org.hibernate.action.internal.AbstractEntityInsertAction.nullifyTransientReferencesIfNotAlready(AbstractEntityInsertAction.java:116)
	at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:72)
	at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:645)
	at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:282)
	at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:263)
	at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:317)
	at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:330)
	at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:287)
	at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
	at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:123)
	at org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:271)
	at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:243)
	at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:175)
	at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:70)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
	at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:833)
	... 27 more
Hibernate: 
    select
        pessoa0_.id as id1_0_,
        pessoa0_.idade as idade2_0_,
        pessoa0_.primeiroNome as primeiro3_0_,
        pessoa0_.segundoNome as segundon4_0_,
        pessoa0_.sexo as sexo5_0_ 
    from
        tbl_Pessoa pessoa0_

Classe Pessoa

package br.com.henrique.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "tbl_Pessoa")
public class Pessoa implements Serializable {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Column(nullable = false)
    private String primeiroNome;
    @Column(nullable = false)
    private String segundoNome;
    @Column(nullable = false)
    private int idade;
    @Column(nullable = false)
    private String sexo;

    public Pessoa() {
    }

    public Pessoa(String primeiroNome, String segundoNome, int idade, String sexo) {
        this.primeiroNome = primeiroNome;
        this.segundoNome = segundoNome;
        this.idade = idade;
        this.sexo = sexo;
    }

    public Pessoa(String primeiroNome, String segundoNome, String sexo) {      
        this.primeiroNome = primeiroNome;
        this.segundoNome = segundoNome;
        this.sexo = sexo;
    }
   

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getPrimeiroNome() {
        return primeiroNome;
    }

    public void setPrimeiroNome(String primeiroNome) {
        this.primeiroNome = primeiroNome;
    }

    public String getSegundoNome() {
        return segundoNome;
    }

    public void setSegundoNome(String segundoNome) {
        this.segundoNome = segundoNome;
    }

    public int getIdade() {
        return idade;
    }

    public void setIdade(int idade) {
        this.idade = idade;
    }

    public String getSexo() {
        return sexo;
    }

    public void setSexo(String sexo) {
        this.sexo = sexo;
    }
        
}

Servlet

package br.com.henrique.servelets;

import br.com.henrique.dao.DAO;
import br.com.henrique.model.Pessoa;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "Editar", urlPatterns = {"/Editar"})
public class Editar extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
      
        try {
            long id = Long.parseLong(request.getParameter("id"));
            String primeiroNome = request.getParameter("primeiroNome");
            String segundoNome = request.getParameter("segundoNome");
            String sexo = request.getParameter("sexo");
           
            DAO dao = new DAO();

            Pessoa pessoa = dao.listarPorId(id);
            pessoa.setPrimeiroNome(primeiroNome);
            pessoa.setSegundoNome(segundoNome);
            pessoa.setSexo(sexo);
            dao.alterar(pessoa);
            

        } catch (RuntimeException ex) {
           
            ex.printStackTrace();
        }

        request.getRequestDispatcher("/index.jsp").forward(request, response);
    }

}

Se a propriedade está assim:

 @Column(nullable = false)
private String primeiroNome;

Significa que ela não pode receber NULL ao ser salvo/alterado no banco.

E pelo erro:

not-null property references a null or transient value : br.com.henrique.model.Pessoa.primeiroNome

Um valor, possivelmente, NULL foi passado para o campo no momento em que foi tentado salvar/alterar no banco.

Amigo, dei uma mudada na lógica da servlet e consegui alterar. No formulário JSP contém um input para pegar o valor do id e assim fazer a alteração se solicitado. Agora ele está alterando o objeto. Mas não está cadastrando, retorna o seguinte erro java.lang.NumberFormatException: For input string: "". E realmente este erro é aceito pois quando cadastro, o campo id fica em branco… Como você pode ver no código abaixo, ele só dispara o erro quando quero cadastrar, justamente por conta dessa linha Long id = Long.parseLong(request.getParameter("id"));. Quando é pra fazer uma alteração, essa variável id é preenchida e a alteração é feita, mas quando é um cadastro esse campo fica em branco e ele dispara o erro que mandei acima.

Servlet

package br.com.henrique.servelets;

import br.com.henrique.dao.DAO;
import br.com.henrique.model.Pessoa;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/salvar")
public class Salvar extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        Long id = Long.parseLong(request.getParameter("id"));
        String primeiroNome = request.getParameter("primeiroNome");
        String segundoNome = request.getParameter("segundoNome");
        int idade = Integer.parseInt(request.getParameter("idade"));
        String sexo = request.getParameter("sexo");

        Pessoa pessoa = new Pessoa(id, primeiroNome, segundoNome, idade, sexo);
        DAO repositorio = new DAO();
       
        try {
            if (pessoa.getId() == null) {
                repositorio.salvar(pessoa);
               

            } else {
                repositorio.alterar(pessoa);
              
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        request.getRequestDispatcher("/index.jsp").forward(request, response);

    }
}

Vc deve tratar isso:

String idParam = request.getParameter("id");
Long id = null;

// Se o id vier preenchido, significa que é uma alteração
if (idParam != null && !"".equals(idParam)) {
  id = Long.parseLong(idParam);
}
1 curtida

Funcionou. Estava quebrando a cabeça para saber como validar isso. Obrigado mesmo!