Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

jsf + Problema com o estado do objeto

Olá pessoal, estou com um problema aqui gostaria de contar com a ajuda de vocês.

Tenho um sistema onde o usuário cadastra um relatório, é algo semelhante a um gerenciador de conteúdo, o usuário pode ir salvando o relatório parcialmente (botão salvar) e quando ele concluir e corrigir o trabalho ele publica o relatório(botão publicar), após publicado(é publicado quando o atributo data publicação não é nulo) o relatório é disponibilizado na web e não pode mais sofrer alterações. O problema surgiu quando um usuário foi publicar o relatório e ocorreu algum erro, creio eu que a rede caiu por um instante, acontece que ao clicar em publicar o sistema seta o dataPublicacao,mas como houve erro o sistema não conseguiu fazer o upate do registro, e depois disso se eu clicar no botão salvar, como o dataPublicacao já está preenchido ele vai acabar publicando o relatório por engano, gerando um erro pois após clicar em salvar o comportamento esperado é que ele possa continuar editando o registro e que não publique nada para a web. Devo adicionar uma camada service no meio pra mediar a conversa com o repository e setar sempre dataPublicacao== null no método salvar?

Segue abaixo um modelo simplificado para ilustrar o problema:

@Entity
public class Relatorio implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

    @Temporal(TemporalType.DATE)
    private Date dataPublicacao;

    private String titulo;

    private String texto;

    @Transient
    public boolean isNovo(){

        return this.getId() == null;
    }

    @Transient
    public void publicar(){
        if(!isPublicado()){
        this.dataPublicacao = new Date();
        }else{
            throw new RuntimeException("relatorio já foi publicado");
        }
    }

    @Transient
    public boolean isPublicado(){

        return this.dataPublicacao != null;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getTexto() {
        return texto;
    }
    public void setTexto(String texto) {
        this.texto = texto;
    }
    public Date getDataPublicacao() {
        return dataPublicacao;
    }

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }
}
@Stateless
public class RelatorioRepository {

    @PersistenceContext(unitName="relatorioPU")
    private EntityManager manager;

    public Relatorio adicionar(Relatorio r){
        manager.persist(r);
        return r;
    }

    public Relatorio atualizar(Relatorio r){
        manager.merge(r);
        return r;
    }

    public Relatorio recuperar(Integer id){
        return manager.find(Relatorio.class,id);
    }

    public void remover(Integer id){

        Relatorio r = recuperar(id);
        if(r.isPublicado()){
            throw new RuntimeException("relatórios publicados não podem ser removidos");
        }
        manager.remove(r);
    }

    public List<Relatorio> todos(){

        return manager.createQuery("select r from Relatorio r",Relatorio.class).getResultList();
    }

}
@ManagedBean
@SessionScoped
public class RelatorioMB implements Serializable{

    private static final long serialVersionUID = 1L;

    @EJB
    private RelatorioRepository relatorios;
    private List<Relatorio> relatorioList;
    private Relatorio relatorio;

    public RelatorioMB(){
        this.relatorio= new Relatorio();
    }

    public String novo(){
        relatorio = new Relatorio();
        return null;
    }

    private void salvarOuAtualizar(){
        if(relatorio.isNovo()){
            relatorios.adicionar(relatorio);
        }else{
            relatorios.atualizar(relatorio);
        }
        recarregarRelatorio();
    }

    private void atualizarLista(){
        relatorioList = relatorios.todos();
    }

    public String  salvar(){
        salvarOuAtualizar();
        atualizarLista();
        FacesContext.getCurrentInstance()
        .addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,"Salvo com sucesso",""));
        return null;
    }

    public String publicar(){

        try {
            int  i = 0;
            System.out.println("passei no publicar");
            relatorio.publicar();
            //simula uma falha transitória na comunicação na rede ou banco
            if(i< 1){
                throw new RuntimeException("simulando um erro aleatório antes de conseguie persistir as alterações");
            }
            salvarOuAtualizar();
            atualizarLista();
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,"Ocorreu um erro inesperado",""));

        }
        return null;
    }

    public void remover(){
        relatorios.remover(relatorio.getId());
    }

    private void recarregarRelatorio(){

        relatorio = relatorios.recuperar(relatorio.getId());
    }

    public Relatorio getRelatorio() {
        return relatorio;
    }
    public void setRelatorio(Relatorio relatorio) {
        this.relatorio = relatorio;
    }
    public List<Relatorio> getRelatorioList() {
        return relatorioList;
    }

}
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<h:head>
    <title>Relatórios</title>
</h:head>
<h:body bgcolor="white">
<p:messages autoUpdate="true" />  
    <h:form id="form">
    <p:panel header="Cadastro de Relatórios">
        <f:facet name="footer" >
                    <div class="ui-panel-titlebar ui-widget-header ui-helper-clearfix ui-corner-all">
                            <p:commandButton value="Salvar" action="#{relatorioMB.salvar}"
                             update="lista"  />
            <p:commandButton value="Publicar" action="#{relatorioMB.publicar()}"
             update="form" process="@form"  />
            <p:commandButton value="Novo" action="#{relatorioMB.novo()}" update="form" process="@form">
            <p:resetInput target="form" />
            </p:commandButton>
                    </div>
                </f:facet>
        <h:panelGrid columns="2">
        <h:outputLabel value="Título:" />
            <h:inputText value="#{relatorioMB.relatorio.titulo}" disabled="#{relatorioMB.relatorio.publicado}" />
            <h:outputLabel value="Texto:" />
            <h:inputTextarea value="#{relatorioMB.relatorio.texto}"  disabled="#{relatorioMB.relatorio.publicado}"/>
        </h:panelGrid>
        </p:panel>
        <p:dataTable id="lista" value="#{relatorioMB.relatorioList}" var="relatorio"  >
        <p:column>
            <f:facet name="header">
                <p:outputLabel value="Cód"/>
            </f:facet>
            <h:outputText value="#{relatorio.id}" />
        </p:column>
            <p:column>
            <f:facet name="header">
                <p:outputLabel value="Título"/>
            </f:facet>
            <h:outputText value="#{relatorio.titulo}" />
        </p:column>
          <p:column style="width:32px;text-align: center">
             <p:commandButton update="form"  icon="ui-icon-search" title="View">
                <f:setPropertyActionListener value="#{relatorio}" target="#{relatorioMB.relatorio}" />
            </p:commandButton>
        </p:column>
    </p:dataTable>
    </h:form>
</h:body>
</html>
1 resposta
solução!

Olá Ricardo.. não sei se entendi bem a sua necessidade, mas talvez o que você possa fazer é realizar a atualização do relatório, ou seja, executa a rotina do salvarOuAtualizar antes de setar a data de publicação. Assim você teria a certeza de que o relatório já estaria salvo antes da "publicação".