8. [TD]: A camada [metier]
Palavras-chave: arquitetura multicamadas, Spring, injeção de dependências.
![]() |
8.1. Support
![]() | ![]() |
A pasta [support / chap-08] contém o projeto Eclipse deste capítulo.
8.2. Configuração do Maven
![]() |
O projeto [elections-metier-dao-jdbc] será baseado no projeto [elections-dao-jdbc-01]. Vamos instalar o arquivo JAR desse último projeto no repositório local do Maven:
![]() |
Feito isso, a configuração do Maven para o projeto Eclipse [elections-metier-dao-jdbc] é a seguinte:
![]() |
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st.elections</groupId>
<artifactId>elections-metier-dao-jdbc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.7.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- DAO -->
<dependency>
<groupId>istia.st.elections</groupId>
<artifactId>elections-dao-jdbc-01</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<scope>test</scope>
</dependency>
<!-- Teste do Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- plugins -->
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>config.AppConfig</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
<!-- para a instalação do artefato do projeto no repositório local do Maven -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
</plugin>
</plugins>
</build>
</project>
- linhas 21-25: a dependência do arquivo JAR do projeto [elections-jdbc-01]. Essas linhas são copiadas diretamente do arquivo [pom.xml] do projeto que queremos importar:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st.elections</groupId>
<artifactId>elections-dao-jdbc-01</artifactId>
<version>0.0.1-SNAPSHOT</version>
...
- linhas 26-37: as dependências necessárias para os testes. Embora estejam presentes no arquivo [pom.xml] do projeto [elections-jdbc-01], somos obrigados a reinseri-las, pois seu atributo [<scope>test</scope>] faz com que elas não tenham sido incluídas no JAR colocado no repositório Maven local;
8.3. Configuração do Spring
![]() |
package elections.metier.config;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
@Import({ elections.dao.config.AppConfig.class })
@EnableCaching
@ComponentScan(basePackages = { "elections.metier.service" })
public class MetierConfig {
}
- linha 7: importamos todos os beans definidos na camada [DAO];
- linha 8: ativa-se o cache. Não se redefine o bean [CacheManager], pois ele já está definido na camada [DAO];
- linha 9: a camada [métier] define novos beans no pacote [elections.metier.service];
8.4. A interface [IElectionsMetier]
![]() |
A camada [metier] terá a interface apresentada no parágrafo 4.2. A relembramos:
public interface IElectionsMetier {
public ListeElectorale[] getListesElectorales();
public int getNbSiegesAPourvoir();
public double getSeuilElectoral();
public void recordResultats(ListeElectorale[] listesElectorales);
public ListeElectorale[] calculerSieges(ListeElectorale[] listesElectorales);
}
8.5. A classe de implementação [ElectionsMetier]
![]() |
Essa classe implementa a interface [IElectionsMetier]. A implementação proposta terá a seguinte estrutura:
package elections.metier.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import elections.dao.entities.ListeElectorale;
import elections.dao.service.IElectionsDao;
@Component
public class ElectionsMetier implements IElectionsMetier {
// o ponto de acesso à camada [dao] instanciada por [Spring]
@SuppressWarnings("unused")
@Autowired
private IElectionsDao electionsDao;
// cálculo dos assentos obtidos
@Override
public ListeElectorale[] calculerSieges(ListeElectorale[] listesElectorales) {
throw new RuntimeException("[calculerSieges] not yet implemented");
}
// listas concorrentes
@Override
public ListeElectorale[] getListesElectorales() {
throw new RuntimeException("[getListesElectorales] not yet implemented");
}
// salvamento dos resultados
@Override
public void recordResultats(ListeElectorale[] listesElectorales) {
throw new RuntimeException("[recordResultats] not yet implemented");
}
// número de cadeiras a serem preenchidas
@Override
public int getNbSiegesAPourvoir() {
throw new RuntimeException("[getNbSiegesAPourvoir] not yet implemented");
}
// limiar eleitoral
@Override
public double getSeuilElectoral() {
throw new RuntimeException("[getSeuilElectoral] not yet implemented");
}
}
- linha 10: a classe [ElectionsMetier] é um componente Spring;
- linha 11: a classe [ElectionsMetier] implementa a interface [IElectionsMetier];
- linhas 15-16: injeção Spring de uma referência na camada [DAO];
- linhas 37 e 44: o número de cadeiras a serem preenchidas e o limite eleitoral estão ocultos;
Tarefa a ser realizada: escreva a classe [ElectionsMetier]. Utilize os comentários, quando houver. Não tente interceptar (try / catch) as exceções do tipo [ElectionsException] que são propagadas da camada [DAO]. Vamos deixá-las subir até a camada [UI]. Como a classe [ElectionsException] é um tipo de exceção não controlada, não há obrigação de tratá-la por meio de um (try / catch).
8.6. A classe de teste
![]() |
A classe de teste JUnit terá a seguinte forma:
package tests;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import dao.config.AppConfig;
import dao.entities.ElectionsException;
import metier.service.IElectionsMetier;
@SpringApplicationConfiguration(classes = MetierConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class Test01 {
// camada [métier]
@Autowired
static private IElectionsMetier electionsMetier;
/**
* vérification 1 : méthode de calcul des sièges on fixe en dur les listes
*/
@Test
public void calculSieges1() {
// cria-se a tabela das 7 listas de candidatos (nome, votos)
// calcula-se o número de cadeiras de cada uma das listas
// verifica-se os resultados (assentos, votos, elimina-se)
// temporário
throw new RuntimeException("[calculSieges1] not yet implemented");
}
/**
* vérification 2 : méthode de calcul des sièges on demande les listes à la
* couche [metier] puis on fixe en dur les voix
*/
@Test
public void calculSieges2() {
// o quadro com as 7 listas de candidatos é gravado no banco de dados
// fixa-se o número de votos
// calcula-se o número de cadeiras obtidas por cada uma das listas
// verifica-se os resultados (assentos, votos, elimina-se)
// temporário
throw new RuntimeException("[calculSieges2] not yet implemented");
}
/**
* vérification 3 méthode de calcul des sièges on provoque une exception
*/
@Test(expected = ElectionsException.class)
// escrever um teste que provoque uma exceção do tipo [ElectionsException]
public void calculSieges3() {
// cria-se uma tabela com 25 listas de candidatos, cada uma com 1 voto
// as 25 listas terão o mesmo número de votos (4%)
// cálculo dos assentos — normalmente, deve-se obter um ElectionsException
// com um limite eleitoral de 5%
// provisório
throw new RuntimeException("[calculSieges3] not yet implemented");
}
/**
* enregistrement des résultats de l'élection
*/
@Test
public void ecritureResultatsElections() {
// cria-se a tabela das 7 listas candidatas
// definem-se os votos de forma fixa
// calcula-se o número de cadeiras obtidas por cada uma das listas
// os resultados são registrados no banco de dados
// revisam-se as listas no banco de dados
// verifica-se os resultados (assentos, votos, elimina-se)
// provisório
throw new RuntimeException("[ecritureResultatsElections] not yet implemented");
}
}
Tarefa a ser realizada: escreva os quatro métodos de teste com a ajuda dos comentários. Lembre-se de que, quando esses métodos forem executados, o campo [electionsMetier] da linha 19 já terá sido inicializado. Verifique se o teste JUnit é aprovado.
8.7. Criação do arquivo da camada [metier]
Assim como foi feito para a camada [DAO], colocamos o arquivo do projeto [elections-metier-dao-jdbc] no repositório Maven local:
![]() |
Observação: essa operação pode falhar se o seu projeto Eclipse estiver associado a um JRE (Java Runtime Environment) em vez de um JDK (Java Development Kit). Para verificar isso, siga as instruções do parágrafo 3.1. Se você constatar que possui um JRE em vez de um JDK, associe seu projeto a um JDK, conforme indicado neste parágrafo.
8.8. Conclusion
Vale lembrar a arquitetura geral do aplicativo [Elections] que estamos desenvolvendo:
![]() |
Já construímos as camadas [metier] e [dao]. Agora, vamos construir a camada [ui]. Proporemos duas implementações para essa camada:
- uma implementação “de console”
- uma implementação com interface gráfica











