POO - 2014-2

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar

Diário de aulas

Aula 1 - 30/07/14: Apresentação da disciplina e Introdução ao Java
  1. Introdução ao Java
    1. Surgimento
Aula 2 - 31/07/14: Introdução ao Ambiente de Desenvolvimento Integrado - IDE
Aula 3 - 06/08/14: Revisão dos conceitos: classes, métodos e atributos
Aula 4 - 07/08/14: Revisão portas lógicas, estruturas de controle, repetição e vetores.
  1. Revisão
    1. Revisão Portas .E. e .OU.
    2. Revisão Estruturas de Controle (if e switch).
    3. Revisão Estruturas de Repetição (for e while).
    4. Revisão Vetores.


Aula 5 - 13/08/14: Revisão exercícios.

Media:AulaRevisao.pdf

Aula 6 - 14/08/14: Sobre carga de métodos e palavras reservadas: this, static e final.

Slides aula 6

Aula 7 - 20 e 21/08/14: Trabalho


Trabalho para fazer:

Pense em um problema para resolver utilizando os conceitos aprendidos em sala de aula. O problema deve ser simples, uma calculadora, um relógio, um carro, qualquer coisa.

Para resolução deve-se seguir os seguintes passos.

Quantidade mínima de atributos: 4-8 sendo que é necessário um vetor[]. Para o atributo vetor é necessário poder (adicionar, remover, listar e verificar existência).

Pense em atributos estáticos (static) e normais quando e porque usar.

Utilize sempre que possível this para referenciar variáveis locais a classe.

Quantidade mínima de métodos:

Construtor padrão e construtor modificado.
3 - Métodos para recuperar informação (usar getNomeDoMetodo()).
3 - Métodos para definir informações (usar setNomeDoMetodo(parâmetros)). 

UML:

Desenhar o diagrama de classes.

Entrega: A definir.

  • obs: utilizar exemplos diferentes dos aprendidos em sala

Programas:

Utilizar o seguinte programa para geração do diagrama de classe.
http://www.genmymodel.com/
Aula 8 - 28/08/14: Estrutura de dados HashMap<Integer, Classe>

Baixar projeto e descompactar.

Abrir com o NetBeans.

Analisar o arquivo Main.java do pacote herancaAgregacao


Projeto Até Aula 8

Aula 9 - 11/09/14: Composição, Agregação, Variáveis Primitivas e Escopo de Variáveis

Variáveis Primitivas, Escopo de Variáveis e Operadoes.

Agregação e Composição.


Aula 10 - 17/09/14: A classe Serializable. Leitura e Escrita em arquivos
Utilize uma das classes que aprendemos, e tente transformá-la para serializable. 
As classes podem sem: Motor, Bicicleta, Triângulo, Calculadora, etc...
Após isso, salve o objeto em um arquivo e recupere as informações, faça uma chamada a algum método.


Slides Aula java.io.Serializable.


Para Exercício 2 (ver slides):

public static void main(String[] args) {
       Principal2 p = new Principal2();
       System.out.println("Chamando salvarEmDisco.");
       p.salvarEmDisco();
       System.out.println("Chamando lerDoDisco.");
       p.lerDoDisco();
}
Aula 11 - 18/09/14: Sockets.
  1. Lembrar de definir o diretório de trabalho no NetBeans;
  2. Lembrar de criar o arquivo socketData.txt dentro do diretório de trabalho.

Projeto Servidor.

Slides Aula Cliente Servidor.

Aula 12 - 24/09/14: Sockets, Servidor de eco.

Baixe o servidor e cliente de eco. Crie um projeto no NetBeans com o nome ecoServer. Insira os dois .java dentro da pasta src. Leia a descrição do código abaixo, entenda e modifique conforme o necessário.

 Servidor e Clientes de Eco  


Vamos entender o código do CLIENTE.

Declara a criação de um novo socket e dá o nome de echoSocket. O construtor do socket necessita que passe como parâmetro o hostName e número da porta.

Socket echoSocket = new Socket(hostName, portNumber);

Obtém a saída do socket e abre um canal de escrita (PrintWriter).

PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);

Inverso do anterior, obtém a entrada do socket e abre um canal de leitura (BufferedReader)

BufferedReader in = new BufferedReader( new InputStreamReader(echoSocket.getInputStream()));

Para enviar dados através do socket, usa-se o PrintWriter. Para obter a resposta do servidor de eco, usa-se BufferedReader.

BufferedReader stdIn = new BufferedReader( new InputStreamReader(System.in))

A próxima parte interessante é o laço (while). O laço lê uma linha por vez do fluxo de entrada padrão do usuário (teclado) e imediatamente envia para o servidor. Para isso escreve-se no PrintWriter conectado ao socket, a saber out.println(userInput);.

String userInput;
while ((userInput = stdIn.readLine()) != null) {
   out.println(userInput);
   System.out.println("echo: " + in.readLine());
}


Passos necessários:

# 1 Abrir o socket.
# 2 Abrir o fluxo de entrada e saída do socket.
# 3 Ler de e Escrever para no fluxo conforme o protocolo utilizado.
# 4 Fechar o fluxo.
# 5 Fechar o socket.

Vamos entender o código do SERVIDOR.

ServerSocket inicia tentativa de escutar a porta definida, caso não seja possível uma excessão é lançada (ex.: caso a porta já esteja em uso).

ServerSocket serverSocket = new ServerSocket(portNumber);

É preciso alterar o código do servidor para que int portNumber = Integer.parseInt(args[0]); Ou seja definido estaticamente, ou através do argumento (args[0]) como está. Se não quiser fazer alterações use: java echoServer 5000

Se o servidor conseguiu fazer a ligação com a porta definida, o objeto do servidor (ServerSocket) é criado com sucesso e o servidor continua no próximo passo. Que é aceitar a conexão com o cliente. O método serverSocket.accept() vai esperar até que uma conexão seja estabelecida (somente uma).

Socket clientSocket = serverSocket.accept();

Os métodos PrintWriter e BufferedReader seguem a mesma lógica de PrintWriter e BufferedReader do cliente.

PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader( new InputStreamReader(clientSocket.getInputStream()));

O laço while, retorna ao cliente todos dados recebidos.


Como a comunicação acontece:

POO-20142-IMGClienteServerEcho.png

Para testar:

Compile os códigos.

Execute o servidor usando: java EchoServer <port number>

Execute o cliente usando: java EchoClient <host name> <port number>

Ou Execute $telnet localhost 5000 onde 5000 é a porta definida na criação do servidor.

Para verificar utilize: $ netstat -na|head -n 20 e verifique se a porta que você endereçou está aberta. Para filtrar de forma mais refinada utilize: netstat -na|grep :<portNumber> onde <portNumbe> deve ser substituido pela porta utilizada.

Lembrando que a porta deve ser a mesma.

Logo após executar o cliente digite algo e pressione enter.

Se você recebeu de volta o que escreveu, está ok.

Faça as atividades.

Atividades:

Lembrando da aula de escrita e leitura de arquivos:

Faça com que cada mensagem enviada pelo cliente de eco seja salva em disco (no servidor).

Faça com que a mensagem seja salva no servidor em um arquivo chamado reqEco.txt.


Possível Solução, verifique através do arquivo:

 Projeto Servidor, possível Solução.

Ou altere o código do servidor, o método while:

String inputLine;
           while ((inputLine = in.readLine()) != null) {
               out.println(inputLine);
               try {
                   OutputStream os = new FileOutputStream("meusDados.txt");
                   OutputStreamWriter osw = new OutputStreamWriter(os);
                   BufferedWriter bw = new BufferedWriter(osw);
                   bw.write("Info: " + inputLine);
                   bw.close();
               } catch (IOException ex) {
                   System.err.println("erro: " + ex.toString());
               }
               out.println("Informação Salva!");
               System.out.println("Informação: "+inputLine+ " salva!");
           }


Se a versão do Java for menor que 1.7 ocorrerá incompatibilidade. Para resolver, faça o downgrade do código. Utilize o try sem os ();

Dessa forma:

try { ... } 
catch () { ... }

Ao invés de:

try ( ... ) { ... } 
catch () { ... }
           


Aula 13 - 25/09/14, 01/10/2014: Sockets, Servidor de eco, continuação.
Pré-requisito: Ler, fazer e entender aulas 10 e 12.

Modificações no servidor.

1

Faça com que ao digitar "quit" ou "exit" a conexão e o servidor sejam fechados. 
Faça o tratamento das palavras reservadas quit e exit, para que as mesmas não sejam salvas.

Possível solução para a modificação 1:

Tratamento para não salvar palavras reservadas (quit, exit...)

if(!inputLine.equalsIgnoreCase("quit") 
   && !inputLine.equalsIgnoreCase("exit") 
   && !inputLine.equalsIgnoreCase("saveData")                        
   && !inputLine.equalsIgnoreCase("cleanData") 
   && !inputLine.equalsIgnoreCase("showData") ){
   buffer[i++] = inputLine.toString();
   System.out.println("Bufferizando: \""+inputLine.toString()+ "\"");
}

Tratamento para término do servidor.

if(inputLine.equalsIgnoreCase("exit") || 
   inputLine.equalsIgnoreCase("quit")){
   System.exit(0);
}




2

Transforme em um método privado a parte que faz a gravação dos dados dentro do while (servidor).
O método deve retornar um boolean informando se a gravação foi efetuada com sucesso.
Verifique o método FileOutputStream() para ver se é possível salvar concatenando o arquivo
ao invés de apagar como está sendo feito.  


Possível solução para a modificação 2:

Método privado para salvar dados no disco. Esse método deve estar na mesma classe do servidor. Perceba que o método recebe dois parâmetros, o primeiro consiste do dado a ser salvo, e o segundo onde deve ser salvo.

O método deve ser chamado da seguinte forma:

salvaDadoNoDisco(buffer[x], "arquivo.txt");

Sendo que buffer[x] é o elemento do vetor que contém a informação a ser salva. O segundo parâmetro "arquivo.txt" contém o nome do arquivo onde deve ser salvo o dado.

private static boolean salvaDadoNoDisco(String inputLine, String file) {
   try {
       OutputStream os = new FileOutputStream(file, true);
       OutputStreamWriter osw = new OutputStreamWriter(os);
       BufferedWriter bw = new BufferedWriter(osw);
       bw.write("\n" + inputLine.toString());
       bw.close();
       return true;
   } catch (IOException ex) {
       System.err.println("erro: " + ex.toString());
       return false;
   }
}




3

Crie um vetor chamado "buffer" com 4 posições. 
Nele devem ser armazenadas as informações que o cliente enviar por telnet (somente as válidas, ou seja, não salvar as palavras reservadas nem dados vazios). 
Quando o cliente enviar o comando "SaveData" os dados contidos no buffer devem ser salvos em disco.
Quando o buffer encher, deve-se salvar automaticamente os dados em disco. 
Obs.: somente os valores devem ser salvos em disco.

4

Para os apaixonados que terminaram a etapa anterior, adicione a palavra reservada "showData".
O cliente ao digitar "showData", todas as informações contidas no arquivo devem ser retornadas ao cliente. 

5

Finalizando, adicione a palavra reservada "cleanData", quando o servidor receber o comando
"cleanData" o conteúdo do arquivo meusDados.txt deve ser apagado. 

Aula 14 - 02/10/2014: Classe java.lang.String.

É necessário ler a apostila ou outras fontes para resolução.

Baixe o arquivo abaixo, crie um projeto no NetBeans e resolva o que está comentado.

Exercício manipulação de String

Obs.: o exercício está comentado dentro do código java. Abra e veja.

Coloquei aqui numerado:

   #1 Separe os nomes da frase f1 utilizando o caracter : como separador
   e mostre os valores separados.
   #2 Substitua na frase f2 a palavra Java por C++    
   #3 Verifique na frase f2 se existe a palavra Java
   #4 Verifique na frase f2 se existe a palavra C++
   #5 Verifique se a frase f3 inicia com Meu pé
   #6 Verifique se a frase f3 inicia com Me
   #7 Verifique se a frase f3 termina com lima.
   #8 Verifique se a frase f3 termina com ma.    
   #9 Faça com que a frase f4 fique com todas as palavras em maiúsculas.    
   #10 Faça com que a frase f5 fique com todas as palavras em minúsculas.    
   #11 Retornar o valor ASCII de cada elemento do vetor ascii
   #12 Verificar igualdade da frase f6, respeitando maiúsculas e minúsculas (utilizar a palavra João)
   #13 e sem respeitar maiúsculas e minúsculas (utilizar a palavra João)
Aula 15 - 22/10/2014: Servidor Eco + Cliente + Interação Servidor-Servidor.

Após terminar o servidor de eco

1 - Quando o usuário entrar com o comando "saveData localSalvar.txt" as informações no buffer devem ser salvas no segundo parâmetro do comando saveData. Caso contrário devem ser salvar no local padrão.

2 - Utilização do cliente. O cliente deve interpretar os comandos: "ExportFile nomeDoArquivo.txt" Quando o cliente entrar com o comando "ExportFile nomeDoArquivo.txt" o cliente deve buscar localmente pelo arquivo, ler todo seu conteúdo e posteriormente enviar todas informações para o servidor. As informações deve ser repassadas para o servidor utilizando o mesmo nome.


Prova 2 - 29/10/2014. Com possível solução e código dos alunos.


EcoServer para usar na prova



Trabalho 1 - 05/11/2014. Abstração Locadora de filmes

Pense em uma abstração para uma locadora de filmes.

Deve ser possível armazenar informações a respeito dos clientes, funcionários e filmes.

Uma vez inseridas as informações essas devem perdurar, ou seja, não devem ser perdidas.

Os dados salvos pela aplicação devem estar sob a pasta "dataBase".

Desenhar o Diagrama de classes, as classes devem conter nomes no singular.


Sobre Inserção dos Dados:

Deve-se poder inserir as informações a respeito dos clientes, funcionários e filmes. 
Pode-se utilizar a classe scanner ou outra para fazer a captura dos dados. 
Os métodos para captura dos dados do cliente, dos funcionário e filmes, 
devem estar em uma única classe. 
Você pode pensar em uma classe única chamada CapturaDados.


Sobre padronização para entrega:

Colocar o diagrama de classes em um arquivo PDF contendo: Nome completo, curso e data.
Colocar o projeto em um arquivo ZIP junto com o arquivo PDF.
O nome dos arquivos devem ser no formato: seuNome-seuSobreNome.zip e seuNome-seuSobreNome.pdf.
Dentro do ZIP deve conter somente os arquivos .java e .pdf salvo excessão abaixo.
Caso alguma informação seja necessária para a execução / configuração, a mesma deve estar contida em um arquivo chamado Leiame.txt dentro do arquivo seuNome-seuSobreNome.zip.


Sobre Entrega:

Data: 06/11/2014 - Final da aula. 
# Entregou no prazo A, um dia de atraso B, dois dias C, três dias D. 

Critérios de avaliação:

# Diagrama de classes.
# Seguiu as especificações definidas A, deixou uma B, duas C, três D.
# Codificação correta das classes. 
# Gravação dos objetos.
# Leitura dos objetos.
# Execução de todas funcionalidades A, deixou uma B, duas C, três D.


Sobre as funcionalidades:

# Inserção dos dados dos clientes. 
# Inserção dos dados dos funcionários. 
# Inserção dos dados dos filmes. 
# Gravação das informações dos clientes em disco. 
# Gravação das informações dos funcionários em disco. 
# Gravação das informações dos filmes em disco. 
# Quando o programa iniciar, as informações salvas devem ser recuperadas e impressas na tela.



OBS.: Vejam como funciona a estrutura de dados Map, hashMap e similares.


Trabalho Final - Início: 13/11/2014, Entrega: 04/12/2014. Abstração Locadora de Filmes

O trabalho final é continuação do trabalho 1, sendo assim, todas funcionalidades e características do trabalho 1 devem ser mantidas, salvo especificação contrária.


Funcionalidades:

# Inserção / Remoção / Atualização dos dados dos clientes. 
# Inserção / Remoção / Atualização dos dados dos funcionários. 
# Inserção / Remoção / Atualização dos dados dos filmes. 
# Gravação das informações dos clientes em disco. 
# Gravação das informações dos funcionários em disco. 
# Gravação das informações dos filmes em disco. 
# Busca por nome de cliente, funcionário ou título de filmes. 
# Listagem por categoria (filme, cliente, funcionário).
# Quando o programa iniciar uma tela/texto com opções deve aparecer para o cliente.
# Deve ser possível efetuar / devolver uma locação.
# Deve ser possível listar as locações sem pendência e com pendência.


Sobre Entrega:

Data: 04/12/2014 - até 12:00. 
# Entregou no prazo A, um dia de atraso B, dois dias C, três dias D. 


Aula 16 - 27/11/2014. Threads e Tratamento de Excessões


Código com exemplo de Threads

Slides Professor Emerson Ribeiro

Exemplo Barbearia


Exercícios:

Imagine um Sistema Consumidor/Fornecedor.

O fornecedor irá inserir informações em um período de tempo determinado.

O consumidor recuperará os dados em um período pré estabelecido.

Imagine três threads, uma sendo a principal (main), as outras duas o consumidor e fornecedor.

A thread principal conterá a estrutura de dados utilizada para armazenar as informações, vamos supor notícias.

A estrutura de dados será manipulada pelo(s) fornecedor(es) e consumidor(es). É necessário os métodos gets e sets.


Obs.:

O fornecedor inserirá um dado a cada 2,7", pesquise por: Thread.sleep();.
Deve-se informar qual dado está sendo inserido (utilize um método randômico e insira caracteres aleatórios ou frases).
O consumidor recuperará um dado no período de 1,2".
Ao recuperar o dado mostre-o na tela e remova.


Após implementado e funcionando teste da seguinte forma, C -> Consumidor e F -> Fornecedor, 4 F - 3 C, significa 4 threads para o fornecedor e 3 para o consumidor.

1 F - 1 C
2 F - 2 C
4 F - 3 C
8 F - 4 C
16 F - 5 C


Necessário tratar concorrência.

Informar ocorrência de excessões.


Pesquisar:

Thread Interference - Interferência entre threads. 
Memory Consistency Errors - Erros de consistência em memória.
Synchronized Methods - Métodos sincronizados.

Leitura complementar:

http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html


Prova Recuperação - 11/12/2014. Prova recuperação.

String.zip

Projetos

Para carregar os projetos abaixo, primeiramente você deve baixar e descompactar o arquivo .zip.

Logo após descompactar você entre no NetBeans e siga os passos:

Arquivo -> Abrir Projeto -> e vá até onde você descompactou o arquivo.zip e clique em cima duas vezes.

Pronto, seu projeto é para ter sido importado.


Links Úteis

Apostila Caleum e outros


Exemplos de Código

private static HashMap<Integer, Cliente> mC = new HashMap<>();


public static void removeElemento(int key){
       mC.remove(key);
}
public static void showAll() {
       //Listar todos elementos de um mapa, note a utilização da
       //variável key.
       for (Integer key : mC.keySet()) {
           System.out.print("ID: "
                   + key);
           System.out.print("\tNome: "
                   + mC.get(key).getPessoa().getNome());
           System.out.print("\tCPF: "
                   + mC.get(key).getPessoa().getCPF());
           System.out.println("\tStatus: "
                   + mC.get(key).getStatus());
       }
}

public static String verificaExistencia(String inNome) {
       //Busca pela existência de um elemento. 
       //Essa busca foi feita pelo nome, mas poderia ser por outro tipo.
       //Retorna na primeira ocorrência... 
       for (Integer key : mC.keySet()) {
           if (mC.get(key).getPessoa().getNome().equalsIgnoreCase(inNome)) {
               return "Sim";
           }
           
       }
       return "Não";
}