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>