Todos os posts de Vitor Zachi

Um pouco sobre Multitenancy

No último semestre do curso tivemos as apresentações dos trabalhos finais. Na ocasião, comentei um pouco sobre multitenancy e seus impactos em uma aplicação java já existente, propondo um framework que facilite a adaptação e programação nessa situação. O Hibernate 4 já possui algo desenvolvido nesse sentido, dando suporte a multitenancy com bases de dados separadas, mas parece que vários avanços estão por vir, podendo até ter suporte a multitenancy com a base de dados compartilhada.

Em anexo a este post, está uma versão em PDF do Trabalho de Conclusão de Curso, onde pode-se encontrar mais informações a respeito do assunto.

Cursores em MySql

No desenvolvimento e manutenção de sistemas, é comum que apareçam algumas funcionalidades ou mudanças que impliquem em alterar a estrutura existente do banco de dados. Nos sistemas que já estão em produção, já não se pode mais eliminar a base de dados e iniciar novamente, pois não podemos deixar que os dados do cliente “desapareçam”.

Em muitas dessas modificações de estrutura do banco, é necessário “transferir” dados de determinadas tabelas para outras, ou fazer alguma operação para que a nova estrutura do banco de dados também se adapte ao sistema. Uma das formas para se efetuar esses ajustes é programando e executando scripts SQL.

Para tratar de uma coleção de dados(vinda de um select, por exemplo), nos utilizamos de cursores. Tive a necessidade de ajustar uma base de dados MySql, e tive de escrever uma rotina para se utilizar de duas tabelas e gerar dados para uma outra tabela. Achei um tanto burocrático, sem contar que nem o exemplo contido na documentação funcionou.

A fim de evitar que passem pelas mesmas dificuldades que passei, vou disponibilizar a estrutura com a qual tive sucesso.

delimiter ;
drop procedure if exists insereDados;

delimiter |

create procedure insereDados()
 begin

 DECLARE done INT DEFAULT 0;
 DECLARE var1, var2, var3 BIGINT;

 DECLARE curs CURSOR FOR (
	SELECT dado1, dado2, dado3 FROM TABELA
	);

 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

 OPEN curs;

 REPEAT

 	FETCH curs INTO var1, var2, var3;
		IF NOT done THEN
			INSERT INTO OUTRA_TABELA(campo1, campo2, campo3) VALUES(var1, var2, var3);
		END IF;
 UNTIL done END REPEAT;

 CLOSE curs;

 end
|

delimiter ;

call insereDados();
drop procedure if exists insereDados;

 

Lembrando que a ordem de declaração de delimitadores, variáveis e cursores deve ser seguida rigorosamente. Vale lembrar também que estaremos criando uma procedure (que para funcionar deverá ser chamada), portanto ela ficará armazenada no banco, a menos que você exclua ela. Para resolver isto, aproveitei e criei mais duas linhas(as duas últimas) onde estou chamando a procedure criada e depois de sua execução estou eliminando-a.

Um post rápido que espero que sirva de ajuda para quem precisa fazer coisas mais “cabulosas” com o banco de dados MySql.

p:graphicImage não atualiza com ajax…

Mais uma dica rápida e interessante, dessa vez na área de JSF, para quem programa utilizando Primefaces…

Às vezes temos alguma(s) imagen(s) em nossos cadastros(por exemplo, a foto de um cliente). Para renderizar as imagens na tela, utilizamos o componente <p:graphicImage />.

Acontece que se, caso quisermos atualizar a imagem utilizando ajax, a imagem insiste em não atualizar. Problema de sete cabeças?? Não!!

Eis o macete: o componente p:graphicImage possui um atributo chamado cache, que por default está setado como true. Ou seja, quando mandamos atualizar com ajax, a imagem será resgatada do cache. Então, para conseguirmos atualizar a imagem com ajax, setamos o atributo cache=”false”, obrigando a atualização da imagem e a correta exibição.

É isso aí pessoal, até a próxima!!

Evitando erro de “Wrong permissions on configuration file” no XAMPP

Muita gente(inclusive eu…), após instalar o XAMPP no seu linux, altera as permissões de todos os arquivos do XAMPP e deixa tudo com permissão total para todos (777). E na hora de dar um “start” no serviço mysql ou acessar o phpMyAdmin recebe uma bela mensagem que diz “Wrong permissions on configuration file, should not be world writable!”.

Que bonito!! É uma bela reclamação para o nosso chmod com permissão 777. E agora, como arrumar isso??

Não sei o seu caso, mas para mim foi simples. Ao iniciar, o phpMyAdmin necessita que pelo menos dois arquivos não estejam editáveis. São eles: “config.inc.php” e “my.cnf”. Para resolver, dei permissão 644 para esses dois arquivos e … feitooooo!!! O phpMyAdmin voltou a funcionar.

Por hoje é só, pessoal! Até a próxima.

Disponibilizando ViewScope para Spring

spring e jsf

Quem trabalha com JSF sabe que existem escopos para seus Managed Beans, e que eles devem ser bem definidos conforme o papel de cada Managed Bean na aplicação. Esse tal de “escopo” define o tempo de vida desse objeto(o Managed Bean) dentro da aplicação.

A partir do JSF 2.0 foi implementado um novo tipo de escopo, chamado de ViewScope. Este novo escopo veio para suprir a necessidade de se ter um tempo de vida dos Managed Beans um pouco maior do que o Request e menor que o Session. O uso do ViewScope é muito recomendado pois evita que um ManagedBean fique instanciado durante a sessão inteira do usuário(caso do SessionScope) mesmo que não esteja mais sendo usado, e possibilita guardar dados enquanto o usuário não troca de página(UIViewRoot), mesmo utilizando requisições ajax(o que não é possível com o RequestScope).

Grande parte das aplicações possuem frameworks, como o Spring, para gerenciar seus Beans. Logicamente, devem ser utilizadas as configurações do framework para o gerenciamento dos mesmos. No caso do Spring, (ainda) não existe um escopo com a mesma lógica do ViewScope do JSF, mas como todo bom framework, pode-se customizar um tipo de escopo e fazer uso dele normalmente na aplicação. É claro que para isso é necessário implementá-lo.

Na empresa onde trabalho utilizamos Spring e tivemos a necessidade de modificar alguns escopos de Session para View. Encontramos um post(em inglês) que fala sobre isso e exemplifica como implementar e disponibilizar um “ViewScope” para o Spring.

Segue aí os passos para implementar seu ViewScope para o Spring.

1. Implementar a classe responsável pelo gerenciamento dos Beans:

import java.util.Map;

import javax.faces.context.FacesContext;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
import org.springframework.web.context.request.FacesRequestAttributes;

public class ViewScope implements Scope {

	public static final String VIEW_SCOPE_CALLBACKS = "viewScope.callbacks";

	public synchronized Object get(String name, ObjectFactory<?> objectFactory) {
		Object instance = getViewMap().get(name);
		if (instance == null) {
			instance = objectFactory.getObject();
			getViewMap().put(name, instance);
		}
		return instance;
	}

	public Object remove(String name) {
		Object instance = getViewMap().remove(name);
		if (instance != null) {
			Map<String, Runnable> callbacks = (Map<String, Runnable>) getViewMap().get(VIEW_SCOPE_CALLBACKS);
			if (callbacks != null) {
				callbacks.remove(name);
			}
		}
		return instance;
	}

	public void registerDestructionCallback(String name, Runnable runnable) {
		Map<String, Runnable> callbacks = (Map<String, Runnable>) getViewMap().get(VIEW_SCOPE_CALLBACKS);
		if (callbacks != null) {
			callbacks.put(name, runnable);
		}
	}

	public Object resolveContextualObject(String name) {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		FacesRequestAttributes facesRequestAttributes = new FacesRequestAttributes(facesContext);
		return facesRequestAttributes.resolveReference(name);
	}

	public String getConversationId() {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		FacesRequestAttributes facesRequestAttributes = new FacesRequestAttributes(facesContext);
		return facesRequestAttributes.getSessionId() + "-" + facesContext.getViewRoot().getViewId();
	}

	private Map<String, Object> getViewMap() {
		return FacesContext.getCurrentInstance().getViewRoot().getViewMap();
	}
}

2. Para poder “destruir” o Bean é necessário colocá-lo em algum local em que seja possível recuperá-lo posteriormente. A classe acima implementa o método registerDestructionCallback, responsável por registrar uma chamada de destruição ao Bean. Essa chamada será armazenada no viewMap da ViewRoot(nossa página que será mostrada), dentro de um Map para que possamos acessá-lo através de uma chave que será o nome do Bean. Graças ao mecanismo de Listeners, conseguimos inserir um novo objeto(no nosso caso um novo Map) dentro do viewMap da página.

Com a implementação da classe abaixo estaremos tratando de dois eventos simultaneamente: assim que o viewMap é construído(na inicialização da página ou PostConstructViewMapEvent) inserimos nosso “repositório” de Beans com ViewScope e seus respectivos destrutores, que será utilizado pelo método registerDestructionCallback, e pouco antes dele ser destruído(PreDestroyViewMapEvent) resgatamos os Beans com ViewScope inseridos no nosso “repositório” criado anteriormente e chamamos seus destrutores.

import java.util.HashMap;
import java.util.Map;

import javax.faces.component.UIViewRoot;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.PostConstructViewMapEvent;
import javax.faces.event.PreDestroyViewMapEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.ViewMapListener;

public class ViewScopeCallbackRegistrer implements ViewMapListener {

	public void processEvent(SystemEvent event) throws AbortProcessingException {
		if (event instanceof PostConstructViewMapEvent) {
			PostConstructViewMapEvent viewMapEvent = (PostConstructViewMapEvent) event;
			UIViewRoot viewRoot = (UIViewRoot) viewMapEvent.getComponent();
			viewRoot.getViewMap().put(ViewScope.VIEW_SCOPE_CALLBACKS, new HashMap<String, Runnable>());
		} else if (event instanceof PreDestroyViewMapEvent) {
			PreDestroyViewMapEvent viewMapEvent = (PreDestroyViewMapEvent) event;
			UIViewRoot viewRoot = (UIViewRoot) viewMapEvent.getComponent();
			Map<String, Runnable> callbacks = (Map<String, Runnable>) viewRoot.getViewMap().get(ViewScope.VIEW_SCOPE_CALLBACKS);
			if (callbacks != null) {
				for (Runnable c : callbacks.values()) {
					c.run();
				}
				callbacks.clear();
			}
		}
	}

	public boolean isListenerForSource(Object source) {
		return source instanceof UIViewRoot;
	}
}

3. Disponibilizar a nossa classe ViewScope para o Spring, inserindo o código abaixo no seu applicationContext.xml:

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
    <property name="scopes">
        <map>
            <entry key="view">
                <bean class="seupackage.ViewScope"/>
            </entry>
        </map>
    </property>
</bean>

4. Registrar nossa classe ViewScopeCallbackRegistrer nos listeners do Faces, inserindo o código abaixo no faces-config.xml:

<system-event-listener>
    <system-event-listener-class>seuPackage.ViewScopeCallbackRegistrer</system-event-listener-class>
    <system-event-class>javax.faces.event.PostConstructViewMapEvent</system-event-class>
    <source-class>javax.faces.component.UIViewRoot</source-class>
</system-event-listener>

<system-event-listener>
    <system-event-listener-class>seuPackage.ViewScopeCallbackRegistrer</system-event-listener-class>
    <system-event-class>javax.faces.event.PreDestroyViewMapEvent</system-event-class>
    <source-class>javax.faces.component.UIViewRoot</source-class>
</system-event-listener>

Basta agora utilizar a anotação @Scope(“view”) sobre seus Managed Beans e eles passarão a ter o comportamento do @ViewScope, mas agora gerenciados pelo Spring.

Bons códigos!!!

Fonte: http://www.harezmi.com.tr/spring-view-scope-for-jsf-2-users/

Formatando campos monetários no JSF com jQuery

Em nossas aplicações é comum a necessidade de trabalhar com valores monetários(dinheiro). O Java não possui um tipo específico para trabalhar com tipos monetários, ficando a cargo do programador decidir se irá utilizar classes do tipo Float ou Integer ou qualquer outra.

Mas uma coisa é certa: não interessa se nas suas classes Java é utilizado Double, Integer, Float ou BigDecimal. Para o usuário, que vai ver a tela final do sistema, é necessário apresentá-la de forma intuitiva e que o mesmo não precise pensar muito para descobrir o que cada componente faz na tela.

Nesse post iremos demonstrar como utilizar um plugin do jQuery(jQuery Price Format) para formatar os campos que terão valores monetários em uma página JSF.

Partimos do princípio de que o(a) leitor(a) esteja um pouco familiarizado com JSF. Neste exemplo vamos utilizar o tipo Float para armazenar nosso valor monetário, mas poderia ser qualquer outra. Este valor será armazenado diretamente no Managed Bean.

package br.com.exemplo.ManagedBean;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class ExemploMonetarioMB {

	private Float valorMonetario = 0f;

	public String mostraValor() {
		return "mostraValor.xhtml";
	}

	public Float getValorMonetario() {
		return valorMonetario;
	}

	public void setValorMonetario(Float valorMonetario) {
		this.valorMonetario = valorMonetario;
	}

}

Vamos precisar do jQuery e do plugin jQuery Price Format. Após o download dos mesmos, criamos uma pasta chamada “js” dentro de WebContent/resources para colocarmos nossos arquivos JavaScript. Precisamos agora chamar os arquivos “.js” para a nossa página.

<h:outputScript name="jquery.min.js" library="/js" />
<h:outputScript name="jquery_price.js" library="/js" />

Na tela temos somente um campo que irá conter o valor digitado pelo usuário.

<h:form>
    <h:outputLabel value="Digite o valor:" />
    <h:inputText value="#{exemploMonetarioMB.valorMonetario}" converter="dinheiroConverter" styleClass="monetario" />
    <h:commandButton value="Ok" action="#{exemploMonetarioMB.mostraValor}" />
</h:form>

Graças  ao jQuery, com um comando conseguimos formatar mais de um componente, caso houvesse, utilizando o seletor de classe. Colocamos uma classe(neste caso “monetario”, mas poderia ser qualquer outra) nos componentes que queremos formatar com o jQuery Price Format, e chamamos a função assim que a página estiver carregada, utilizando “(document).ready”.

<script type="text/javascript">

	 jQuery(document).ready(function(){
		jQuery('.monetario').priceFormat({
			prefix:'R$ '
		});
	});
</script>

Agora, está faltando somente implementar o nosso Converter, que será responsável por fazer a conversão dos valores da tela para o Java e vice-versa.

package br.com.exemplo.converter;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

@FacesConverter(forClass = Float.class, value = "dinheiroConverter")
public class DinheiroConverter implements Converter {

	@Override
	public Object getAsObject(FacesContext context, UIComponent component,
			String value) {
		if (value != null && !value.equals("")) {
			String str = value.trim();

			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < str.length(); i++) {
				char ch = str.charAt(i);
				if (Character.isDigit(ch) || ch == '.') {
					sb.append(ch);
				}
			}

			return new Float(sb.toString());
		}
		return null;
	}

	@Override
	public String getAsString(FacesContext context, UIComponent component,
			Object value) {
		if (value != null) {
			String prefixoMoeda = "R$ ";
			StringBuilder s = new StringBuilder(value.toString());
			if (s.substring(s.indexOf(String.valueOf('.'))).length() == 2) {
				s.append("0");
			}

			for (int i = s.indexOf(String.valueOf('.')) - 3; i > 0; i -= 3) {
				s.insert(i, ',');
			}
			return prefixoMoeda + " " + s.toString();
		}
		return "";
	}
}

Dessa forma, tem-se como resultado a tela de inserção do valor:

E após clicar em “Ok” mostramos os valores da forma nativa, em nosso caso Float, e utilizando o Converter:

 

Você pode baixar o projeto(para Eclipse) neste link.