Observer – Como criar e usar o Pattern Observer em Java usando jBoss Seam

Thursday, 6. October 2011

Criei um exemplo bem simples aqui pra ilustrar o funcionamento de um Observer em Java utilizando jBoss Seam.
 
Para isso eu criei um botão que vai chamar a função “teste” em minha Action:

<a4j:commandButton value="Juntar ao Processo"
actionListener="#{minhaAction.teste}"
ajaxSingle="true" />

Na minha Action criei a função e através do Events.instance().raiseEvent(
“hunrumclaudia”); eu chamei o evento “hunrumclaudia”, assim:

public void teste(){
System.out.println("asdfvvv");
Events.instance().raiseEvent(
"hunrumclaudia");
}

Para criar o Observer eu usei o import “org.jboss.seam.annotations.Observer” e criei um método com a anotação @Observer e o nome do evento que chamará este observer, no meu caso “hunrumclaudia”.

@Observer("hunrumclaudia")
public void observadorObservanteObservacao(){
System.out.println("ie ie, pegadinha do malandro");
}

A saída do console será:
11:02:53,333 INFO  [STDOUT] asdfvvv
11:02:53,334 INFO  [STDOUT] ie ie, pegadinha do malandro

Exemplo Composite + JSF2

Wednesday, 3. August 2011

Para criar um componente usando Composite no JSF2 é bem simples. Abaixo vou mostrar um componente que criei para um caso em específico, basta abstrair e usar para o que precisar.

No meu caso, o meu projeto fazia uso do primefaces, então caso você use alguma outra biblioteca, basta substituir pelos componentes correspondentes aos que eu usei do primefaces.

Mãos a obra:

Pra começar, existe um padrão em que deve ser criado uma pasta chamada “resources” dentro da “webapp”, e dentro dela a pasta que será a base de sua lib de componentes, no nosso caso: “telefone”.

Dentro da pasta “telefone” crie uma xhtml que será o seu componente em sí, telefone.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:cc="http://java.sun.com/jsf/composite"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:p="http://primefaces.prime.com.tr/ui">

<cc:interface>
	<cc:attribute name="telefoneExclusao" required="true" />
	<cc:attribute name="propertyListaTelefone" required="true" />
	<cc:attribute name="actionNovoTelefone"
		method-signature="void action()" />
	<cc:attribute name="actionExcluirTelefone"
		method-signature="void action()" />
</cc:interface>

<cc:implementation>

	<p:panel header="#{msg['label_componente_telefone_listaTelefones']}">

		<f:facet name="options">
			<p:menu>
				<p:menuitem value="#{msg['label_novo']}"
					action="#{cc.attrs.actionNovoTelefone}" ajax="false" />
			</p:menu>
		</f:facet>

		<p:dataTable value="#{cc.attrs.propertyListaTelefone}" var="item"
			id="listaTelefone" update="@form" >

			<p:column>
				<f:facet name="header">

				</f:facet>
				<p:inputMask mask="9999-9999" value="#{item.numero}" />
			</p:column>
			<p:column>
				<f:facet name="header">
					<h:outputText value="#{msg['label_ramal']}" />
				</f:facet>
				<p:inputMask mask="9999" value="#{item.ramal}" />
			</p:column>
			<p:column>
				<f:facet name="header">
					<h:outputText value="#{msg['label_observacao']}" />
				</f:facet>
				<p:inputText value="#{item.observacao}" />
			</p:column>
			<p:column>
				<f:facet name="header">
					<h:outputText value="#{msg['label_excluir']}" />
				</f:facet>
				<p:commandButton value="#{msg['label_excluir']}"
					action="#{cc.attrs.actionExcluirTelefone}">
					<f:setPropertyActionListener
						target="#{cc.attrs.telefoneExclusao}" value="#{item}" />
				</p:commandButton>
			</p:column>
		</p:dataTable>
	</p:panel>
</cc:implementation>
</html>

Algumas considerações devem ser feitas sobre meu componente acima, por exemplo:

value=#{msg['label_novo']}

Essa variável msg é um Helper que eu criei para buscar valores do meu Bundle, no caso de quem estiver fazendo isso do zero, basta usar value=”Novo” que vai funcionar perfeitamente.

Quanto a minha interface:

<cc:interface>
	<cc:attribute name="idTelefoneExclusao" required="true" />
	<cc:attribute name="propertyListaTelefone" required="true" />
	<cc:attribute name="actionNovoTelefone"
		method-signature="void action()" />
	<cc:attribute name="actionExcluirTelefone"
		method-signature="void action()" />
</cc:interface>

Você irá precisar passar para o componente <telefone:telefone> os seguintes atributos:

telefoneExclusaoactionNovoTelefoneactionExcluirTelefone

<f:setPropertyActionListener target="#{cc.attrs.telefoneExclusao}" value="#{item}" />

No meu TesteMBean.java criei as entidades e métodos a seguir:

	private List<TelefoneEntity> listaTelefone;
	private TelefoneEntity telefoneExclusao;

	@PostConstruct
	public void initialize() {
		if(conversation.isTransient())
			conversation.begin();

		listaTelefone = new ArrayList();
		TelefoneEntity o = new TelefoneEntity();

		o.setId(1L);
		o.setNumero("1231-2223");
		o.setObservacao("obs");
		listaTelefone.add(o);
	}

	public void excluirTelefone(){
		telefoneExclusao.getId(); // crie aqui seu metodo de excluir o telefone
	}

	public void novoTelefone(){
		if(listaTelefone == null){
			listaTelefone = new ArrayList();
		}
		TelefoneEntity o = new TelefoneEntity();

		o.setId(2L);
		o.setObservacao("novo");
		listaTelefone.add(o);
	}

Meu TesteMBean é apenas um exemplo, pois cada um deve implementar conforme as suas necessidades.

Por fim, para usar o componente basta apenas chamá-lo passando os parametros correspondentes aos que criamos.

<telefone:telefone
   propertyListaTelefone="#{testeMBean.listaTelefone}"
   actionExcluirTelefone="#{testeMBean.excluirTelefone}"
   actionNovoTelefone="#{testeMBean.novoTelefone}"
   telefoneExclusao="#{testeMBean.telefoneExclusao}" />

Não esquecendo de importar o componente lá no cabeçalho do xhtml:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.prime.com.tr/ui"
	xmlns:telefone="http://java.sun.com/jsf/composite/telefone">

Ele ficará assim:

Componente telefone

Componente Telefone

Exception – org.hibernate.PersistentObjectException: detached entity passed to persist

Monday, 1. August 2011

Ao usar meu entityManager para persistir alguma entidade, o Hibernate lançava a seguinte exceção:
org.hibernate.PersistentObjectException: detached entity passed to persist: bla bla bla bla bla

Pesquisando nas internets descobri que essa exceção é lançada pelo Hibernate quando você está trabalhando em uma entidade que ele ACHA que não está persistida no banco de dados. Ou que ao menos, se está no banco, não foi ele quem gravou.

O fato é que isso só acontecia quando eu mandava persistir uma entidade em que eu gostaria de efetuar um “UPDATE”.

Como todas as minhas classes de entidade extendem de AppEntity, foi só ajustar meu método genérico pra ficar como o abaixo:

@PersistenceContext
EntityManager entityManager;

public T persist(T entidade) {
   if(((AppEntity)entidade).getId()!=null){
      getEntityManager().merge(entidade);
   }else{
      getEntityManager().persist(entidade);
   }
   return entidade;
}

Simples, quando for uma nova entidade use o persist(entidade), quando for update use o merge(entidade).