Vou fazer um teste pra uma vaga de programador java pra JSF, ajuda. (+jpa)

15 respostas
faeldix

Entao pessoal, finalmente apareceu uma boa oportunidade e eu quero muito essa vaga..
Ontem eu fiz uma prova escrita e consegui passar.. e hoje é o dia da prova pratica..

Que vai consistir na criação de um CRUD utilizando JSF 1.2 e algum outro framework à nossa escolha.. escolhi utilizar o JPA. OK
Mas ele disse tambem que a utilização de design patterns e boas práticas seriam bem avaliados.. entao eu criei um projeto aqui e queria saber da opiniao de vcs.

Organização do Projeto:

[img]http://img515.imageshack.us/img515/8418/projetoqx.png[/img]

queria que vocês avaliassem o meu SINGLETON:

package br.com.ceuma.persistence;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class EntityManagerFactorySingleton {
	
	private static final EntityManagerFactorySingleton singleton = new EntityManagerFactorySingleton();
	private static EntityManagerFactory fabrica = null;
	private final String unidadeDePesistencia;
	
	private EntityManagerFactorySingleton() {
		this.unidadeDePesistencia = new Configuracoes().getConfigution("unidade_de_persistencia");
		System.out.println("Criando Entity");
	}
	
	public static EntityManagerFactorySingleton getInstance(){
		
		return singleton;
	}

	public EntityManager getManager(){
		
		try {
			if(fabrica == null){
				fabrica = Persistence.createEntityManagerFactory(this.unidadeDePesistencia);
				return fabrica.createEntityManager();
			} else {
				return fabrica.createEntityManager();
			}
		} catch (Exception e) {
			System.err.println("ERRO: " + e.getMessage());
			return null;
		}
		
	}
	
	
}

essa classe é responsavel por criar EntityManagers.. ela utiliza uma outra classe utilitaria.. para ler um arquivo properties.. para preencher o metodo
Persistence.createEntityManagerFactory();

Eu creio que isso seja uma boa prática, particularmente nao acho interessante colocar esse tipo de informação no codigo diretamente.

package br.com.ceuma.persistence;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class Configuracoes {
	
	private InputStream stream;
	
	public Configuracoes() {
		stream = this.getClass().getResourceAsStream("config.properties");  
	}
	
	public String getConfigution(String configucao){
		
		Properties props = new Properties();
		
		try {
			props.load(stream);
			return props.getProperty(configucao);
		} catch (IOException e) {
			System.err.println("ERRO NA LEITURA DO ARQUIVO DE CONFIGURAÇÃO) " + e.getMessage());
			return null;
		}
		
	}

}

e agora o meu DAO

package br.com.ceuma.dao;

public interface DAO<T> {
	void save(T t);
	void remove(T t);
	T find(Long id);
	void update(T t);
}

meu BackingBean ja mapeado

package br.com.ceuma.model;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="tb_contato")
public class Contato {
	
	@Id @GeneratedValue
	private Long id;
	private String nome;
	@Column(unique=true)
	private String email;
	private String endereco;
	@Column(name="data_nascimento")
	private Date dataNascimento;
	
// getters & setters

a classe que implementa o DAO

package br.com.ceuma.dao;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceException;


import br.com.ceuma.model.Contato;
import br.com.ceuma.persistence.EntityManagerFactorySingleton;

public class ContatoDAO implements DAO<Contato> {
	
	private EntityManager manager;
	
	public ContatoDAO() {
		this.manager = EntityManagerFactorySingleton.getInstance().getManager();
	}
	
	public void save(Contato t) {
		
		EntityTransaction transacao = this.manager.getTransaction();
		transacao.begin();
		
		try {
			this.manager.persist(t);
			transacao.commit();
		} catch (Exception e) {
			System.err.println("ERRO AO SALVAR O OBJETO: " + t + "\n" + e.getMessage());
			transacao.rollback();
		} finally {
			this.manager.close();
		}
	}

	public void remove(Contato t) {
		EntityTransaction transacao = this.manager.getTransaction();
		transacao.begin();
		
		try {
			this.manager.remove(t);
			transacao.commit();
		} catch (Exception e) {
			System.err.println("ERRO AO REMOVER O OBJETO: " + t + "\n" + e.getMessage());
			transacao.rollback();
		} finally {
			this.manager.close();
		}
	}

	public Contato find(Long id) {
		EntityTransaction transacao = this.manager.getTransaction();
		transacao.begin();
		
		try {
			Contato contato = this.manager.find(Contato.class,id);
			transacao.commit();
			return contato;
		} catch (NoResultException e) {
			System.err.println("Sem resultados para a consulta: " + e.getMessage() );
			transacao.rollback();
			return null;
		} finally {
			this.manager.close();
		}
	}

	public void update(Contato t) {
		
		EntityTransaction transacao = this.manager.getTransaction();
		transacao.begin();
		
		try {
			this.manager.merge(t);
			transacao.commit();
		} catch (PersistenceException e) {
			System.err.println("Erro ao atualizar o objeto: " + e.getMessage() );
			transacao.rollback();
		} finally {
			this.manager.close();
		}
		
	}

}

organização das classes e outros arquivos:

[img]https://lh5.googleusercontent.com/-24NPAebizpA/T_Lv_XVpLCI/AAAAAAAADsM/IEzbxWtWoWM/s464/2.jpg[/img]

e agora a parte WEB.. eu escolhi utilizar o facelets tbm.. pq acho que ele é importante pra organização do trabalho.. acho bem 'elegante.'
segue o meu template:

<!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://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"> 

<head>
	<link rel="stylesheet" href="css/estilo.css" type="text/css"/>
	<title>Teste do UNICEUMA</title>
</head> 
<body> 
	<div id="all">
		
		<!-- FRAGMENTO DO TOPO -->
		
		<div id="topo">
			<ui:insert name="topo">
				<ui:include src="/fragmentos/topo.xhtml" />
			</ui:insert>
		</div>
		
		<!-- FRAGMENTO DO MENU -->
		
		<div id="menu">
			<ui:insert name="menu">
				<ui:include src="/fragmentos/menu.xhtml" />
			</ui:insert>
		</div>
		
		<!-- COTEUDO PRINCIPAL -->
		
		<div id="principal">
			<ui:insert name="principal">
			</ui:insert>
		</div>
		
		<!-- FRAGMENTO DO RODAPE -->
		
		<div id="rodape">
			<ui:insert name="rodape">
				<ui:include src="/fragmentos/rodape.xhtml" />
			</ui:insert>
		</div>
		
	</div>
</body> 
</html>

entao.. queria saber o que vocês acharam.. o que vcs acham que eu poderia fazer pra melhorar..
como estao minhas 'boas praticas'.. e se vcs puderem me ajudar a deixar esse projeto ai o mais OO possivel, seria magnifico tbm.

desde ja agradeco MESMO..

edit: pessoal, irei comentar todo o codigo ainda..

15 Respostas

rmendes08

Cara, acho que o seu código está bom, bem próximo das práticas que vemos por aí. Agora, eu acho que você não deve ficar comentando o seu código não. Código bom é aquele que se explica por si. Comentar demais acaba poluindo o código e dificulta a leitura.

N

faeldix , primeiramente boa sorte no teste.

Só por efeito de curiosidade e também poderá ser útil pra mim futuramente, quais são os requisitos dessa vaga?

Obrigado.

douglaskd

meu comentário não tem nada a ver com seu código, acho que ficou muito bom

achei esse método getConfigution, só um erro bobo de gramática…rs

victorcosta

Eu adoro System.out.println, mas é feio, o correto seria usar log

E meu Java tá meio ultrapassado mas acho q também tá errado o DAO dar commit e rollback. Em aplicações você vai ter logicas de negócio que envolvem mais de uma operação salvar, deletar, etc, e a unidade de transação tem que englobar todas essas operações juntas. O begin, commit, rollback tem que estar em volta da lógica de negócio como um todo

faeldix

victorcosta:
Eu adoro System.out.println, mas é feio, o correto seria usar log

E meu Java tá meio ultrapassado mas acho q também tá errado o DAO dar commit e rollback. Em aplicações você vai ter logicas de negócio que envolvem mais de uma operação salvar, deletar, etc, e a unidade de transação tem que englobar todas essas operações juntas. O begin, commit, rollback tem que estar em volta da lógica de negócio como um todo

faz super sentido o que vc falou… como vc faria entao?
vou pensar numa forma aqui pra vc avaliar!

rmendes08

faeldix:
victorcosta:
Eu adoro System.out.println, mas é feio, o correto seria usar log

E meu Java tá meio ultrapassado mas acho q também tá errado o DAO dar commit e rollback. Em aplicações você vai ter logicas de negócio que envolvem mais de uma operação salvar, deletar, etc, e a unidade de transação tem que englobar todas essas operações juntas. O begin, commit, rollback tem que estar em volta da lógica de negócio como um todo

faz super sentido o que vc falou… como vc faria entao?
vou pensar numa forma aqui e digo…

Me vêm 3 opções à cabeça:

1 - abrir e fechar transações manualmente em cada método de negócio;
2 - utilizar um padrão como Open Session In View ou Open Session In Phase Listener
3 - utllizar um interceptador para métodos de negócio que abra e feche as transações

Com certeza, a opinião 3 é a mais limpa, mas é difícil de implementar se você não conta com EJB’s ou DI conteiner. A opção 1 é a mais suja, pois mistura controle de transações com regras de negócio, mas é muito mais simples para se implementar e não tem erro! A opção 2 é um meio termo, mas eu não gosto muito desses padrões não.

faeldix

rmendes08:
faeldix:
victorcosta:
Eu adoro System.out.println, mas é feio, o correto seria usar log

E meu Java tá meio ultrapassado mas acho q também tá errado o DAO dar commit e rollback. Em aplicações você vai ter logicas de negócio que envolvem mais de uma operação salvar, deletar, etc, e a unidade de transação tem que englobar todas essas operações juntas. O begin, commit, rollback tem que estar em volta da lógica de negócio como um todo

faz super sentido o que vc falou… como vc faria entao?
vou pensar numa forma aqui e digo…

Me vêm 3 opções à cabeça:

1 - abrir e fechar transações manualmente em cada método de negócio;
2 - utilizar um padrão como Open Session In View ou Open Session In Phase Listener
3 - utllizar um interceptador para métodos de negócio que abra e feche as transações

Com certeza, a opinião 3 é a mais limpa, mas é difícil de implementar se você não conta com EJB’s ou DI conteiner. A opção 1 é a mais suja, pois mistura controle de transações com regras de negócio, mas é muito mais simples para se implementar e não tem erro! A opção 2 é um meio termo, mas eu não gosto muito desses padrões não.

pois é… a primeira que me veio a cabeca foi criar um getTransacao e utilizar ele no ContatoBean… mas ai eu ia ter que jogar excessoes pra pilha de baixo… e ter que tratar erros no bean… ia ficar pessimo… alguma outra ideia?

F

Uma coisa rápida.
Isso:

if(fabrica == null){
    fabrica = Persistence.createEntityManagerFactory(this.unidadeDePesistencia);  
    return fabrica.createEntityManager();  
} else {  
    return fabrica.createEntityManager();  
}

Tá repetindo o return desnecessariamente.

if(fabrica == null)
    fabrica = Persistence.createEntityManagerFactory(this.unidadeDePesistencia);  
return fabrica.createEntityManager();
faeldix

fasts:
Uma coisa rápida.
Isso:

if(fabrica == null){
    fabrica = Persistence.createEntityManagerFactory(this.unidadeDePesistencia);  
    return fabrica.createEntityManager();  
} else {  
    return fabrica.createEntityManager();  
}

Tá repetindo o return desnecessariamente.

if(fabrica == null) fabrica = Persistence.createEntityManagerFactory(this.unidadeDePesistencia); return fabrica.createEntityManager();

boa… obrigado cara…

faeldix

pessoal.. o que vcs acham?

package br.com.ceuma.dao;

import javax.persistence.EntityTransaction;

public interface DAO<T> {
	void save(T t);
	void remove(T t);
	T find(Long id);
	void update(T t);
	public void finalizar();
	public void finalizar(Exception e);
}
package br.com.ceuma.dao;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import br.com.ceuma.model.Contato;
import br.com.ceuma.persistence.EntityManagerFactorySingleton;

public class ContatoDAO implements DAO<Contato> {
	
	private EntityManager manager;
	private EntityTransaction transacao;
	
	public ContatoDAO() {
		this.manager = EntityManagerFactorySingleton.getInstance().getManager();
		manager.getTransaction().begin();
	}
	
	public void finalizar(){
		this.transacao.commit();
	}
	
	public void finalizar(Exception e){
		this.transacao.rollback();
	}
	
	public void save(Contato t) {
			this.manager.persist(t);
	}

	public void remove(Contato t) {
			this.manager.remove(t);
	}

	public Contato find(Long id) {
			Contato contato = this.manager.find(Contato.class,id);
			return contato;
	}

	public void update(Contato t) {
			this.manager.merge(t);
	}

}
package br.com.ceuma.bean;

import javax.faces.event.ActionEvent;

import br.com.ceuma.dao.DAO;
import br.com.ceuma.model.Contato;
import br.com.ceuma.dao.ContatoDAO;

public class ContatoBean {
	
	private DAO<Contato> myDAO;
	private Contato contato;
	
	public ContatoBean() {
		DAO<Contato> dao = new ContatoDAO();
		this.myDAO = dao;
	
		this.contato = new Contato();
	}

	public Contato getContato() {
		return contato;
	}

	public void setContato(Contato contato) {
		this.contato = contato;
	}
	
	public void salvar(ActionEvent ev){
		
		try {
			this.myDAO.save(getContato());
			this.myDAO.finalizar();
		} catch (Exception e) {
			this.myDAO.finalizar(e);
		} finally {
			this.myDAO = new ContatoDAO();
		}
	}
	
}

so uma duvida.. durante o ciclo de vida do JSF o Bean (mapeado) é destruido ao fim das requições?
pq se nao.. eu tiraria esse finally..

victorcosta

Se você usar a opção 1 do rmendes08, pode fazer assim para não repetir o código de abrir e fechar transação, e ainda estaria usando parte do Command Pattern, já que o avaliador disse que patterns eram bem vindos :D

package guj;

@SuppressWarnings("serial")
public class ServiceException extends RuntimeException {
	
	public ServiceException(Exception e) {
		super(e);
	}

}
package guj;

import java.util.concurrent.Callable;

public class Service {
	
	protected <T> T transaction(Callable<T> command) {
		System.out.println("Inicia Transação");
		try {
			T result = command.call();
			System.out.println("Commita Transação");
			return result;
		} catch (Exception e) {
			System.out.println("Rollbacka Transação");
			throw e instanceof ServiceException ? (ServiceException) e : new ServiceException(e);
		}
	}
	
	protected void transaction(Runnable command) {
		System.out.println("Inicia Transação");
		try {
			command.run();
			System.out.println("Commita Transação");
		} catch (Exception e) {
			System.out.println("Rollbacka Transação");
			throw e instanceof ServiceException ? (ServiceException) e : new ServiceException(e);
		}
	}

}
package guj;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

public class PessoaService extends Service {
	
	public List<Object> listar() {
		return transaction(new Callable<List<Object>>() {
			public List<Object> call() {
				System.out.println("- Listar Pessoas");
				return new ArrayList<Object>();
			}
		});
	}
	
	public void salvar(final Object pessoa) {
		transaction(new Runnable() {
			public void run() {
				System.out.println("- Salvar " + pessoa);
			}
		});
	}
	
	public static void main(String[] args) throws Exception {
		PessoaService service = new PessoaService();
		service.listar();
		service.salvar("Victor");
	}

}

Você pode criar suas interfaces de Command ao invés de reusar Runnable e Callable pra manter o mesmo padrão de nome do método implementado. E mudar as exceções pra Checked se quiser. Exceções da lógica de negócio vão extender de ServiceException

Aprender algum framework pra não ter que fazer isso tudo é uma opção também, se tiver tempo :P

faeldix

victorcosta:

Você pode criar suas interfaces de Command ao invés de reusar Runnable e Callable pra manter o mesmo padrão de nome do método implementado. E mudar as exceções pra Checked se quiser. Exceções da lógica de negócio vão extender de ServiceException

Aprender algum framework pra não ter que fazer isso tudo é uma opção também, se tiver tempo :P

achei um pouco complicado… quero o mais simples possivel…
pq até pra explicar seria complicad… mas obrigado victor…

vou guardar esse codigo… pq pareceu bem funcional

faeldix

Pessoal… queria agradecer a ajuda de todos… mas infelizmente acho que dessa vez nao vai dar…

A provinha era fazer um sistema com jsf 1.2 + alguns outros frameworks a nossa escolha…
escolhi trabalhar com o JPA pra acelerar o processo… a prova era pra ser feita em 3hrs… mas nao consegui concluir nesse tempo

Era um sisteminha de vendas com cadastro de clientes, vendedor, produtos e tinhamos que criar uma forma de fazer vendas e decrementar os produtos
no banco de dados… infelizmente eu fui inventar :frowning: ai como tive que desfazer algumas coisas isso levou muito tempo… infelizmente foi assim…

Mas nao recebi a resposta ainda… talvez ainda dê… mas nao tenho mais esperancas…
Mas serviu pra mostrar que eu preciso muitoooooooooo ainda trabalhar essa parte de Orientação a Objetos… ela foi quem realmente quebrou minhas pernas :frowning:

Mas enfim… obrigado a todos…
Obrigado mesmo…

C

Calma, podem gostar da parte que você fez mesmo que não tenha concluído, e chamá-lo para a empresa. Você podia fazer algum tipo consulta na net ou outro material? T+

faeldix

nao podia… ate os templates de xmls eu tinha que fazer… (perdi muito tempo nisso)

Criado 3 de julho de 2012
Ultima resposta 5 de jul. de 2012
Respostas 15
Participantes 7