quinta-feira, 17 de dezembro de 2020

Contas Pagar/Receber - Parte XXX - Refatoração Diversas

 Introdução

Nesse trigésimo post vou refatorar para deixar o código coeso, colocando as regras em sua devida camada. Vou atualizar também para a versão 20.12.0-SNAPSHOT.

Atualizando Versão

A primeira alteração que vou fazer é atualizar para a versão 20.12.0-SNAPSHOT.
 pom.xml:

<properties>
<jarch-version>20.12.0-SNAPSHOT</jarch-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

persistence.xml (web, job e ws)

<jar-file>lib/contas-client-1.0.0.jar</jar-file>
<jar-file>lib/jarch-core-20.12.0-SNAPSHOT.jar</jar-file>
LancamentoObserver
Agora vou mover as regras de negócio que está dentro do LancamentoObserver, movendo para métodos dentro da camada Service. A primeira alteração é mover a codificação do evento @JArchEventCreateEntity para um método dentro do Service.
LancamentoObserver:

@Inject
private LancamentoService lancamentoService;

private void criacaoLancamento(@Observes @JArchEventCreateEntity LancamentoEntity lancamento) {
lancamentoService.configuraLancamentoInclusao(lancamento);
}
LancamentoService:

@JArchParameter
@Inject
private ParametroBancoDefault parametroBancoDefault;

@JArchParameter
@Inject
private ParametroCentroCustoDefault parametroCentroCustoDefault;

@JArchParameter
@Inject
private ParametroCategoriaDefault parametroCategoriaDefault;

@JArchParameter
@Inject
private ParametroPessoaDefault parametroPessoaDefault;

@JArchParameter
@Inject
private ParametroUtilizaBpmAutorizacaoLancamento parametroUtilizaBpmAutorizacaoLancamento;


public void configuraLancamentoInclusao(LancamentoEntity lancamento) {
lancamento.setAberto(true);
lancamento.setBanco(parametroBancoDefault.getValue());
lancamento.setCentroCusto(parametroCentroCustoDefault.getValue());
lancamento.setCategoria(parametroCategoriaDefault.getValue());
lancamento.setPessoa(parametroPessoaDefault.getValue());

boolean autorizado = !parametroUtilizaBpmAutorizacaoLancamento.getValue()
|| getUserInformation().get(UsuarioEntity.class).getCargo() != CargoType.OPERADOR;

lancamento.setAutorizado(autorizado);
}

Agora vou refatorar o código que está no evento de clonagem para dentro do Service.
LancamentoObserver:

private void clonaLancamento(@Observes @JArchEventCloneEntity LancamentoEntity lancamento) {
lancamentoService.configuraLancamentoClonagem(lancamento);
}

LancamentoService:

public void configuraLancamentoClonagem(LancamentoEntity lancamento) {
lancamento.setAberto(true);

boolean autorizado = !parametroUtilizaBpmAutorizacaoLancamento.getValue()
|| getUserInformation().get(UsuarioEntity.class).getCargo() != CargoType.OPERADOR;

lancamento.setAutorizado(autorizado);
}

Agora vou refatorar o código que está no evento de validação na inclusão ou alteração para dentro do Service.
LancamentoObserver:

private void validaDataInferiorDezAnos(@Observes @JArchEventValidInsertChange         LancamentoEntity lancamento) {
lancamentoService.validaInclusaoAlteracao(lancamento);
}

LancamentoService:

public void validaInclusaoAlteracao(LancamentoEntity lancamento) {
LocalDate vencimentoMinimo = LocalDate.now().minusYears(10).withMonth(1).withDayOfMonth(1);
if (lancamento.getVencimento().isBefore(vencimentoMinimo)) {
throw new ValidationException(BundleUtils.messageBundle("message.vencimentoPartirDe",
DateUtils.formatddMMyyyy(vencimentoMinimo)));
}
}

Agora vou refatorar o código que está no evento de após a inclusão ou alteração para dentro do Service.
LancamentoObserver:

private void atualizaAlertaMensagemInclusaoAlteracao(@Observes         @JArchEventInsertChange(momentPersistMerge = MomentType.AFTER)         LancamentoEntity lancamento) {
lancamentoService.atualizaAlertaMensagemInclusaoAlteracao();
}

LancamentoService:

public void atualizaAlertaMensagemInclusaoAlteracao() {
alertaFacade.atualizaAlertaSessao();
mensagemFacade.atualizaMensagemSessao();
}

Agora vou refatorar o código que está no evento de após a exclusão ou alteração para dentro do Service.
LancamentoObserver:

private void atualizaAlertaMensagemExclusao(@Observes @JArchEventDelete(momentRemove = MomentType.AFTER)         LancamentoEntity lancamento) {
lancamentoService.atualizaAlertaMensagemExclusao();
}

LancamentoService:

public void atualizaAlertaMensagemExclusao() {
alertaFacade.atualizaAlertaSessao();
mensagemFacade.atualizaMensagemSessao();
}

Agora vou refatorar o código que está no evento de após a inclusão que está instanciando o fluxo para dentro eo Service.
LancamentoObserver:

private void instanciaFluxoLancamentoOperador(@Observes         @JArchEventInsert(momentPersist = MomentType.AFTER)
LancamentoEntity lancamento) {
lancamentoService.instanciaFluxoLancamentoOperador(lancamento);
}

LancamentoService:

public void instanciaFluxoLancamentoOperador(LancamentoEntity lancamento) {

if (getUserInformation().get(UsuarioEntity.class).getCargo() != CargoType.OPERADOR) {
return;
}

if (!parametroUtilizaBpmAutorizacaoLancamento.getValue()) {
return;
}

runtimeService
.createProcessInstanceByKey(Constant.PROCESS_AVALIACAO_CONTA)
.businessKey(lancamento.getId().toString())
.setVariable(Constant.ID_MULTITENANT, getMultiTenant().get())
.setVariable(Constant.ID_OPERADOR, getUserInformation().get().getId())
.setVariable("descricao", lancamento.getDescricao())
.setVariable("valor", lancamento.getValor().doubleValue())
.setVariable("vencimento", lancamento.getVencimento())
.execute();
}

Agora vou refatorar o código que está no evento de ação dinâmica de avaliar conta para dentro do Service.
LancamentoObserver:

private void avaliacao(@Observes @JArchEventDynamicAfter(Constant.ID_AVALIAR_LANCAMENTO)         LancamentoEntity lancamento) {
lancamentoService.avaliacao(lancamento);
}

LancamentoService:

public void avaliacao(LancamentoEntity lancamento) {
UsuarioEntity usuarioLogado = getUserInformation().get(UsuarioEntity.class);

String variavelAprovacao;

if (usuarioLogado.getCargo() == CargoType.SUPERVISOR) {
variavelAprovacao = "aprovadoSupervisor";
} else if (usuarioLogado.getCargo() == CargoType.GERENTE) {
variavelAprovacao = "aprovadoGerente";
} else {
variavelAprovacao = "aprovadoDiretor";
}

taskService.complete(lancamento.getTask().get().getId(),
Map.of(variavelAprovacao, lancamento.isAprovado(),
"valorLancamento", lancamento.getValor().doubleValue()));
}

LancamentoService

Agora vou ajustar os métodos depreciados, clientJpaql() para getClientJpql().
LancamentoObserver:

public Collection<LancamentoEntity> contaPagarAbertoAte(LocalDate vencimento) {
return getClientJpql()
.where()
.equalsTo(LancamentoEntity_.aberto, true)
.and()
.equalsTo(LancamentoEntity_.tipoLancamento, TipoLancamentoType.PAGAR)
.and()
.equalsTo(LancamentoEntity_.autorizado, true)
.and()
.lessOrEqualsThan(LancamentoEntity_.vencimento, vencimento)
.collect()
.list();
}


public Collection<LancamentoEntity> contaPagarAbertoEm(LocalDate vencimento) {
return getClientJpql()
.where()
.equalsTo(LancamentoEntity_.aberto, true)
.and()
.equalsTo(LancamentoEntity_.tipoLancamento, TipoLancamentoType.PAGAR)
.and()
.equalsTo(LancamentoEntity_.autorizado, true)
.and()
.equalsTo(LancamentoEntity_.vencimento, vencimento)
.collect()
.list();
}

Agora vou ajustar o método depreciado, find() para getClientJpql().find().
LancamentoService:

public void autorizaConta(Long idLancamento) {
LancamentoEntity lancamento = getClientJpql().find(idLancamento);
lancamento.setAutorizado(true);
change(lancamento);
}

Métodos Depreciados 

Agora vou ajustar os métodos depreciados:
De clientJpaql() para getClientJpql()
De count() para getClientJpql().count()
De searchUniqueFilter() para getClientJpql().searchUniqueFilter()
De ICrudListAction para ICrudListController

SonarLint
Agora vou chamar o SonarLint para verificar as sugestões de melhorias no LancamentoService. 

1. A primeira sugestões que ele propôs foi que existem dois métodos duplicados, sugerindo deixar somente um. Então vou renomear o método atualizaAlertaMensagemExclusao() para atualizaAlertaMensagem() e vou excluir o atualizaAlertaMensagemInclusaoAlteracao().

2. Agora ele está sugerindo que isPresent() em um Optional para acessar o valor.

lancamento
.getTask()
.ifPresent(t -> taskService.complete(t.getId(),
Map.of(variavelAprovacao, lancamento.isAprovado(),
"valorLancamento", lancamento.getValor().doubleValue())));
3. Agora está sugerindo para utilizar o Boolean.TRUE.

if (!Boolean.TRUE.equals(parametroUtilizaBpmAutorizacaoLancamento.getValue())) {
return;
}

4. Agora está sugerindo para utilizar o try resources. 

public StreamedContent downloadComprovanteBaixa(LancamentoEntity lancamento) {
Document document = new Document();
try {
File file = File.createTempFile("comprovante", ".pdf");
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
PdfWriter.getInstance(document, fileOutputStream);
document.open();
document.add(new Paragraph("Comprovante de Pagamento Conta " + lancamento.getTipoLancamento().getDescription()));
document.add(new Paragraph("Codigo......: " + lancamento.getCodigo()));
document.add(new Paragraph("Descrição...: " + lancamento.getDescricao()));
document.add(new Paragraph("Banco.......: " + lancamento.getBanco().getCodigo() + " - " + lancamento.getBanco().getNome()));
document.add(new Paragraph("Centro Custo: " + lancamento.getCentroCusto().getCodigo() + " - " + lancamento.getCentroCusto().getDescricao()));
document.add(new Paragraph("Categoria...: " + lancamento.getCategoria().getCodigo() + " - " + lancamento.getCategoria().getDescricao()));
document.add(new Paragraph("Pessoa......: " + CpfCnpjUtils.formataCpfCnpj(lancamento.getPessoa().getCpfCnpj()) + " - " + lancamento.getPessoa().getNome()));
document.add(new Paragraph("Vencimento..: " + DateUtils.formatddMMyyyy(lancamento.getVencimento())));
document.add(new Paragraph("Valor.......: " + NumberUtils.formatMoney(lancamento.getValor())));
document.add(new Paragraph("Código de autenticação: " + Md5Utils.generate(NumberUtils.formatZeroLeft(lancamento.getId(), 10))));
document.close();
return new DefaultStreamedContent(new FileInputStream(file), FileType.PDF.getContentType(), "comprovante.pdf");
}
} catch (DocumentException | IOException ioe) {
throw new ValidationException("Erro na geração do comprovante...");
} finally {
document.close();
}
}

5. E por último está pedindo para acertar a chamada do código depreciado new DefaultStreamedContent.

try (FileInputStream fileInputStream = new FileInputStream(file)) {
return DefaultStreamedContent
.builder()
.stream(() -> fileInputStream)
.contentEncoding(FileType.PDF.getContentType())
.name("comprovante.pdf")
.build();
}
Referência Circular
Com as refatorações anteriores causei um problema de referência circular do CDI. Agora minha classe LancamentoService faz uma injeção ao AlertaFacade e o MensagemFacade, e por sua vez tanto o AlertaFacade quando o MensagemFacade faz uma injeção ao LancamentoService. Para resolver isso vou mover os métodos do AlertaFacade e MensagemFacade para o LancamentoService, vou excluir as classes AlertaFacade e o MensagemFacade e ajustar os pontos na aplicação que faziam referência as essas classes para utilizar o LancamentoService.
LancamentoService.java:

public class ComunicacaoObserver {

@Inject
private LancamentoService lancamentoService;

private void inclusaoAlteracao(@Observes @JArchEventInsertChange(momentPersistMerge = MomentType.AFTER) CommunicationEntity communicationEntity) {
lancamentoService.atualizaAlertaMensagem();
}

private void exclusao(@Observes @JArchEventDelete(momentRemove = MomentType.AFTER) CommunicationEntity communicationEntity) {
lancamentoService.atualizaAlertaMensagem();
}
}
ComunicacaoObserver.java:

public class ComunicacaoObserver {

@Inject
private LancamentoService lancamentoService;

private void inclusaoAlteracao(@Observes @JArchEventInsertChange(momentPersistMerge = MomentType.AFTER) CommunicationEntity communicationEntity) {
lancamentoService.atualizaAlertaMensagem();
}

private void exclusao(@Observes @JArchEventDelete(momentRemove = MomentType.AFTER) CommunicationEntity communicationEntity) {
lancamentoService.atualizaAlertaMensagem();
}
}
LoginObserver.java:

public class LoginObserver {

private void login(@Observes @JArchEventLoginAfter UsuarioEntity usuario, LancamentoService lancamentoService) {
lancamentoService.atualizaAlertaMensagem();

if (usuario.getCargo().equals(CargoType.DIRETOR) || usuario.getCargo().equals(CargoType.GERENTE)) {
JsfUtils.getSession().setMaxInactiveInterval(600);
}
}
}
SessionListener.java:

@WebListener
public class SessionListener implements HttpSessionListener {

@Inject
private TenantService tenantFacade;

@Inject
private LancamentoService lancamentoService;

@Inject
private UsuarioService usuarioFacade;

@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
tenantFacade.configTenant(JsfUtils.getServerName());
usuarioFacade.criaUsuarioAdmin();
lancamentoService.atualizaAlertaMensagem();
}

@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
LogUtils.warning("SESSION TIMEOUT !!!");
}
}
Conclusão
Nesse post fiz a atualização do projeto para a versão mais atual do JARCH (na publicação desse Post), e algumas melhorias no código. Melhorias no código devem ser frequentemente aplicadas, principamente quando o código sofre constantes alterações ou implementações. Uma boa prática de programação é sempre manter o código mais simples possível, ser auto documentado, utilização de boas práticas de programação orientada a objetos, buscando sempre a coesão e desacoplamento.

Até mais,

quarta-feira, 2 de dezembro de 2020

Versão 20.11.0-Final

  

Introdução

Nesse post vou mostrar as principais novidades da versão 20.11.0, algumas correções e pequenas alterações.

Implementações

Segue abaixo as implementações dessa versão:
- Atualizado GCA para usar JavaFX 15 com Java 11
- Melhoria na API de JPQL para utilizar SetAttribute no lugar de PluralAttribute

Alterações

Além das implementações descritas acima foram feitas algumas alterações:
- Depreciado o método clientJpql() do BaseService e BaseDao, utilizar o getClientJpql() em seu lugar
- Alterado o método generateConditionWhereJpaql() do ConditionSearchType para generateConditionWhereJpql()
Depreciado as classes Jpaql para ajustar a nomenclatura para Jpql
- Depreciado classes Base e Crud do Facade, utilizar Service
Depreciado classes Base e Crud do Manager, utilizar Dao
Depreciado as classes Base e Crud das Actions, utilizar Controller
- Movido diversas classes do pacote br.com.jarch.crud.action para br.com.jarch.crud.controller
- Adicionado os métodos BaseService.getDao(), BaseDataController.getService() e BaseListController.getService() e depreciados os getFacade() e getManager()
- Acerto na API de Communication para utilizar a nova convenção de nomes (Controller, Service e Dao)
- Ajustes nos XHTML's para ainda contemplar a nomenclatura de Action (Login, AlteraSenha, Menu)

Correções

Além das alterações descritas acima esta versão contempla algumas correções:
- Correção no e:inputAddress no carregamento dos campos pelo CEP no modo de inclusão
- Correção na verificação de task assumido para verificar se não é o próprio usuario que está executando
- Ajuste na tela de visualização de mensagem para desabilitar a ação de excluir quando a mensagem estiver arquivada
- Alterado o equals do BaseEntity para saber tratar quando uma instância é um proxy

Conclusão

Essa versão contempla algumas melhorias e correções. É recomendável a atualização para essa nova versão.

Até mais,

quarta-feira, 18 de novembro de 2020

Contas Pagar/Receber - Parte XXIX - Atualizando para Versão 20.11.0 do JARCH

Introdução

Nesse vigésimo nono post vou atualizar a versão do JARCH para 20.11.0. Essa versão mudou a nomenclatura de alguns classes base do JARCH.

Atualizando a Versão
A primeira alteração é ajustar o pom.xml e os persistence.xml para utilizar a versão 20.11.0, então no pom.xml do projeto:
pom.xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>br.com.jarch.contas</groupId>
<artifactId>contas</artifactId>
<version>1.0.0</version>
<name>contas</name>
<packaging>pom</packaging>

<properties>
<jarch-version>20.11.0-SNAPSHOT</jarch-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
persistence.xml (módulo job)
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="contas-job-pu" transaction-type="JTA">
<jta-data-source>java:/ds/contas/job</jta-data-source>
<jar-file>lib/contas-client-1.0.0.jar</jar-file>
<jar-file>lib/jarch-core-20.11.0-SNAPSHOT.jar</jar-file>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="hibernate.query.startup_check" value="false"/>
persistence.xml (módulo web)
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="contas-web-pu" transaction-type="JTA">
<jta-data-source>java:/ds/contas/web</jta-data-source>
<jar-file>lib/contas-client-1.0.0.jar</jar-file>
<jar-file>lib/jarch-core-20.11.0-SNAPSHOT.jar</jar-file>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
persistence.xml (módulo ws)
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="contas-ws-pu" transaction-type="JTA">
<jta-data-source>java:/ds/contas/ws</jta-data-source>
<jar-file>lib/contas-client-1.0.0.jar</jar-file>
<jar-file>lib/jarch-core-20.11.0-SNAPSHOT.jar</jar-file>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="hibernate.query.startup_check" value="false"/>
Refatoração Action's
A nomenclatura Action era utilizada para referenciar o Controller da arquitetura MVC,  então todos as classes do JARCH que eram controllers foram alteradas de Action para Controller. Então vou alterar todas as actions que estendem de CrudListAction para CrudListController.
BancoListAction.java:
package br.com.jarch.contas.web.banco;

import br.com.jarch.annotation.JArchViewScoped;
import br.com.jarch.contas.client.banco.BancoEntity;
import br.com.jarch.contas.client.banco.BancoFacade;
import br.com.jarch.crud.controller.CrudListController;

@JArchViewScoped
public class BancoListAction extends CrudListController<BancoEntity, BancoFacade> {

@Override
public String getPageData() {
return "bancoData.jsf";
}
}
Agora vou alterar todas as actions que estendem de CrudDataAction para CrudDataController.
BancoDataAction.java:
package br.com.jarch.contas.web.banco;

import br.com.jarch.annotation.JArchViewScoped;
import br.com.jarch.contas.client.banco.BancoEntity;
import br.com.jarch.contas.client.banco.BancoFacade;
import br.com.jarch.crud.controller.CrudDataController;

@JArchViewScoped
public class BancoDataAction extends CrudDataController<BancoEntity, BancoFacade> {

@Override
public String getPageList() {
return "bancoList.jsf";
}

}
Agora vou alterar todas as actions que estendem de BaseFilterSelectAction para BaseFilterSelectController.
BancoFilterSelectAction.java:
package br.com.jarch.contas.web.banco;

import br.com.jarch.contas.client.banco.BancoEntity;
import br.com.jarch.annotation.JArchViewScoped;
import br.com.jarch.crud.controller.BaseFilterSelectController;
import javax.annotation.Generated;

@JArchViewScoped
@Generated(value = "br.com.jarch.apt.generate.implicit.EntityProcessor", date = "08/11/2020 19:54:59")
public class BancoFilterSelectAction extends BaseFilterSelectController<BancoEntity> {
}

Apesar de mostrar somente o Banco como exemplo a aplicação da alteração precisa ser em todo o projeto.
Refatoração Facade
A nomenclatura Facade era utilizada para referenciar o Business Objeto (BO) não tem nada a ver com o design pattern Facade (GoF). Então a nomenclatura Facade passou a ser Service,  então todos as classes do JARCH que eram BO's foram alteradas de Facade para Service. Agora vou alterar todas as classes que estem de CrudFacade para CrudService.
BancoFacade.java:
package br.com.jarch.contas.client.banco;

import br.com.jarch.crud.service.CrudService;

public class BancoFacade extends CrudService<BancoEntity, IBancoManager> {

}
Apesar de mostrar somente o Banco como exemplo a aplicação da alteração precisa ser em todo o projeto.
Refatoração (I)Manager
A nomenclatura Manager era utilizada para referenciar o Repository (DAO). Então a nomenclatura Manager passou a ser Dao,  então todos as classes do JARCH que eram Repository's foram alteradas de Manager para Dao. Agora vou alterar todas as classes que estendem de Manager para Dao.
IBancoManager.java:
package br.com.jarch.contas.client.banco;

import br.com.jarch.crud.dao.ICrudDao;

public interface IBancoManager extends ICrudDao<BancoEntity> {

}
BancoManager.java:
package br.com.jarch.contas.client.banco;

import br.com.jarch.crud.dao.CrudDao;

public class BancoManager extends CrudDao<BancoEntity> implements IBancoManager {

}
Apesar de mostrar somente o Banco como exemplo a aplicação da alteração precisa ser em todo o projeto.
Refatoração Classes Projeto Action
Agora que já acertei as estensões de todas classes vou ajustar as nomenclaturas do projeto. Primeiro vou alterar as classes que estão com o nome Action para Controller.
BancoListController.java:
package br.com.jarch.contas.web.banco;

import br.com.jarch.annotation.JArchViewScoped;
import br.com.jarch.contas.client.banco.BancoEntity;
import br.com.jarch.contas.client.banco.BancoFacade;
import br.com.jarch.crud.controller.CrudListController;

@JArchViewScoped
public class BancoListController extends CrudListController<BancoEntity, BancoFacade> {

@Override
public String getPageData() {
return "bancoData.jsf";
}
}
bancoList.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:e="http://jarch.com.br/ui/extension">
<ui:composition template="/paginas/templates/templateListaV2.xhtml">
<ui:define name="panelBodyTemplateLista">
<e:form>
<e:divTitle
title="#{e:bundle('label.lista')} - #{e:bundle('label.banco')}"
description="#{e:bundle('label.manter')} #{e:bundle('label.banco')}"/>
<e:divListFilter
title="#{e:bundle('label.filtro')} - #{e:bundle('label.banco')}"
actionList="#{bancoListController}"
update="@(.list-datatable)"/>
<e:divListDatatable id="listEntityDataTableBanco"
title="#{e:bundle('label.lista')} - #{e:bundle('label.banco')}"
actionList="#{bancoListController}" />
</e:form>
</ui:define>
</ui:composition>
</html>
BancoDataController.java:
package br.com.jarch.contas.web.banco;

import br.com.jarch.annotation.JArchViewScoped;
import br.com.jarch.contas.client.banco.BancoEntity;
import br.com.jarch.contas.client.banco.BancoFacade;
import br.com.jarch.crud.controller.CrudDataController;

@JArchViewScoped
public class BancoDataController extends CrudDataController<BancoEntity, BancoFacade> {

@Override
public String getPageList() {
return "bancoList.jsf";
}

}
bancoData.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:a="http://jarch.com.br/ui"
xmlns:e="http://jarch.com.br/ui/extension">
<ui:composition template="/paginas/templates/templateDadosV2.xhtml">
<ui:define name="panelBodyTemplateDados">
<e:form>
<e:divTitle
title="#{e:bundle('label.banco')} - #{bancoDataController.labelAction}"
description="#{e:bundle('label.manter')} #{e:bundle('label.banco')}"/>
<e:divDataMaster
title="#{e:bundle('label.banco')}"
actionData="#{bancoDataController}">
<a:panelGrid columns="1">
<h:panelGroup>
<a:outputLabel value="#{e:bundle('label.codigo')}" for="idBancoCodigo"/>
<br/>
<a:inputText id="idBancoCodigo" styleClass="input-code"
disabled="#{bancoDataController.blockedMaster}" label="#{e:bundle('label.codigo')}"
value="#{bancoDataController.entity.codigo}" required="true"/>
</h:panelGroup>
</a:panelGrid>
<a:panelGrid columns="1">
<h:panelGroup>
<a:outputLabel value="#{e:bundle('label.nome')}" for="idBancoNome"/>
<br/>
<a:inputText id="idBancoNome" styleClass="input-description-large"
disabled="#{bancoDataController.blockedMaster}" label="#{e:bundle('label.nome')}"
value="#{bancoDataController.entity.nome}" required="true"/>
</h:panelGroup>
</a:panelGrid>

</e:divDataMaster>
</e:form>
</ui:define>
</ui:composition>
</html>
BancoFilterSelectAction.java:
@JArchViewScoped
@Generated(value = "br.com.jarch.apt.generate.implicit.EntityProcessor", date = "08/11/2020 19:54:59")
public class BancoFilterSelectController extends BaseFilterSelectController<BancoEntity> {
}
Apesar de mostrar somente o Banco como exemplo a aplicação da alteração precisa ser em todo o projeto.
Refatoração Classes Projeto Facade
Agora vou alterar as classes que estão com o nome Facade para Service.
BancoService.java:
package br.com.jarch.contas.client.banco;

import br.com.jarch.crud.service.CrudService;

public class BancoService extends CrudService<BancoEntity, IBancoManager> {

}
Apesar de mostrar somente o Banco como exemplo a aplicação da alteração precisa ser em todo o projeto.
Refatoração Classes Projeto Manager
Agora vou alterar as classes que estão com o nome Manager para Dao.
IBancoDao.java:
package br.com.jarch.contas.client.banco;

import br.com.jarch.crud.dao.ICrudDao;

public interface IBancoDao extends ICrudDao<BancoEntity> {

}
BancoDao.java:
package br.com.jarch.contas.client.banco;

import br.com.jarch.crud.dao.CrudDao;

public class BancoDao extends CrudDao<BancoEntity> implements IBancoDao {

}
Apesar de mostrar somente o Banco como exemplo a aplicação da alteração precisa ser em todo o projeto.

Demais Alterações
1. As classes de parâmetros precisam ser ajustadas para apontar para a nomenclatura nova (Action para Controller, Facade para Service e Manager para Dao).
2. Vou extrair os Controller's (antigo Action's) do BPM que estão no módulo client para o módulo web. Vou criar um pacote chamado br.com.jarch.contas.web.bpmn dentro do módulo web e mover o AutorizacaoLancamentoListTaskController.java e BpmListController.java do módulo client para o módulo web.
3. Alterar o método getFilterSelection() das classes ParametroBancoDefault, ParametroCategoriaDefault, ParametroCentroCustoDefault e ParametroPessoaDefault alterando o Action para Controller na string de retorno.
4. Ajustar todas as classes JpqlBuilder para utilizar o ClientJpql e ClientJpqlBuilder no lugar do ClientJpaql e ClientJpaqlBuilder (Remover o "a" no nome da classe).
5. Refatorar a chamada de clientJpaql() para getClientJpql().
6. Refatorar a chamada de ComunicationFacade para ComunicationService.

Conclusão
Nesse post fiz a atualização do projeto para a versão mais atual do JARCH (na publicação desse Post), e algumas melhorias no código. Melhorias no código devem ser frequentemente aplicadas, principamente quando o código sofre constantes alterações ou implementações. Uma boa prática de programação é sempre manter o código mais simples possível, ser auto documentado, utilização de boas práticas de programação orientada a objetos, buscando sempre a coesão e desacoplamento.

Segue o link dessa video aula: https://youtu.be/xA3alw6_2UQ
Até mais,


Versão 23.3.0-Final

      Introdução Nesse post vou mostrar as principais novidades da versão 23.3.0, algumas correções e pequenas alterações. Alterações Além d...