Archive for the ‘JBoss’ Category

Bem, esta é uma dica que apesar de simples, muita gente não conhece. O Hibernate pode ser configurado para gerar estatísticas de uso da SessionFactory. Em meus projetos já é comum rodar estas estatísticas uma vez que o projeto entra em homologação e ate mesmo em produção. Estas estatísticas vão ajudá-lo em alguns pontos:

  • Encontrar queries que podem estar consumindo muito tempo
  • Identificar possíveis objetos que podem ser colocados em cache
  • Verificar se os caches de 2nd level estão realmente sendo utilizados
  • Identificar possíveis campos que podem ser definidos como índices em suas tabelas

Por maior que seja nosso esforço como arquitetos de software, é muito difícil prevermos quais consultas serão mais usadas, quais objetos deveremos manter em cache, e quando sua equipe for grande, por mais que você tente, peça, xingue, sempre vai existir um desenvolvedor que não executa as queries no Hibernate tools e verifica se o SQL gerado é realmente a versão mais otimizada. Se eu ganhasse 1 real para cada join desnecessário que já encontrei em queries de projetos quando faço revisão de código, eu provavelmente poderia adiantar minha aposentadoria.

Fica aqui então uma forma de como verificar as estatísticas do hibernate. A abordagem que vou adotar é de disponibilizar um ManagedBean que irá exportar como serviço o HibernateStatistics. Vamos lá.

A aplicação de exemplo a ser monitorada, é uma aplicação de aprovação de horas (usando seam + jbpm_ que foi demonstrada neste blog neste link

Primeiro precisamos da nossa interface de MBean:

package com.furiousbob.hibernate.stats;
 
public interface HibernateStatsMBean {
	public void start() throws Exception;
	public void stop() throws Exception;
	public void create()throws Exception;
	public void destroy();
}

Bem, alguns poderão questionar aqui que poderíamos usar o ServiceMBeanSupport do JBoss, mas eu preferi manter a forma tradicional de mbeans ;)

Agora nossa implementação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.furiousbob.hibernate.stats;
 
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.naming.InitialContext;
import javax.persistence.EntityManager;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.jmx.StatisticsService;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.system.ServiceMBeanSupport;
 
 
public class HibernateStats implements HibernateStatsMBean {
 
	private final String  SessionFactoryName = "java:/AprovacaoHorasSessionFactory";
 
 
	public void start() throws Exception {
		InitialContext ctx = new InitialContext();
		SessionFactory sessionFactory = (SessionFactory)ctx.lookup(SessionFactoryName);
		MBeanServer server = MBeanServerLocator.locateJBoss();
		ObjectName on = new ObjectName("Hibernate:type=statistics,application=AprovacaoHoras");
		StatisticsService service = new StatisticsService();
		service.setSessionFactory(sessionFactory);
		server.registerMBean(service, on);
	}
 
	public void stop() throws Exception {
		MBeanServer server = MBeanServerLocator.locateJBoss();
		ObjectName on = new ObjectName("Hibernate:type=statistics,application=AprovacaoHoras");
		server.unregisterMBean(on);
	}
 
	public void create() throws Exception {
	}
 
	public void destroy() {
	}

Como podem notar é realmente muito simples registrar o servico de stats do Hibernate. Note que estamos usando o nome da SessionFactory de forma fixa dentro do código, você poderia por exemplo, definir isto como um atributo de seu MBean de forma que este código possa ser usado em várias aplicações. O nome do MBean também reflete o nome da aplicação a ser monitorada, e é outro candidato a se tornar uma propriedade configurável.

A última parte de nosso exemplo é o arquivo jboss-service.xml que deve ser colocado na pasta META-INF de sua aplicação

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<server>
 
   <mbean name="MyApp:Hibernate=Stats" code="com.furiousbob.hibernate.stats.HibernateStats">
 		<depends>jboss:service=Naming</depends>
 		<depends>persistence.units:ear=AprovacaoHoras.ear,unitName=AprovacaoHoras</depends>
   </mbean>
</server>

Este arquivo irá informar que nosso Mbean possui uma dependência com a PersistenceUnit. E esta também deve sofrer uma pequena modificação, devemos adicionar as propriedades abaixo em nosso arquivo de configuração de persistencia:

<property name="hibernate.generate_statistics" value="true"/>
<property name="hibernate.session_factory_name" value="java:/AprovacaoHorasSessionFactory"/>

Agora precisamos de empacotar nossas classes como um Service ARchive (SAR). Um SAR é nada mais que um JAR com o jboss-service.xml em seu META-INF. Ao final da operação você deverá ter um arquivo SAR com a seguinte estrutura:

vinicius@cybertron:~/workspace/HibernateStats/dist$ jar -tvf HibernateStats.sar
     0 Wed Mar 04 09:09:40 BRT 2009 META-INF/
   106 Wed Mar 04 09:09:38 BRT 2009 META-INF/MANIFEST.MF
   305 Wed Mar 04 09:02:46 BRT 2009 META-INF/jboss-service.xml
     0 Wed Mar 04 09:03:02 BRT 2009 com/
     0 Wed Mar 04 09:03:02 BRT 2009 com/furiousbob/
     0 Wed Mar 04 09:03:02 BRT 2009 com/furiousbob/hibernate/
     0 Wed Mar 04 09:03:02 BRT 2009 com/furiousbob/hibernate/stats/
  2082 Wed Mar 04 09:03:34 BRT 2009 com/furiousbob/hibernate/stats/HibernateStats.class
   290 Wed Mar 04 09:03:02 BRT 2009 com/furiousbob/hibernate/stats/HibernateStatsMBean.class

Agora, acesse seu jmx-console de você deverá encontrar uma tela contendo um link para seu novo mbean. Existem dois mebans novos o primeiro:

AprovacaoHoras:Hibernate=Stats é o seu MBean que registra o serviço de stats

Hibernate:application=AprovacaoHoras,type=statistics: é o serviço de stats que você poderá coletar as métricas

Pronto, agora basta acessar o serviço e começar a coletar algumas métricas de seu Hibernate.

Aproveitem

Depois de um longo período de hibernação (me desculpem aos que liam o blog), mas estou muito envolvido em projetos de governança SOA, espero poder blogar cedo.

Mas um evento em particular me forçou vir ao menos falar sobre ele. Saiu finalmente o JBoss AS 5.0. O que eu imaginava ser um feito quase impossível (estava imaginando quem iria sair primeiro, o AS 5.0 ou o Duke Nukem Forever ).

Bem, esta ai (http://www.jboss.org/feeds/post/jbossas_5_0_0_ga_released) JBoss AS 5.0, totalmente compativel com a spec 5.0. Com o novo VFS, com JBoss messaging e com o novo MC (nem tudo eh perfeito ne?)

Grande abraço e bons códigos

Poxa vida, tava preparando um post sobre RecordProcessor, e sai a versão nova do Jboss Seam ontem, e com ela um novo Identity Manager, e desta vez com suporte a LDAP!!!!
Bem, desta vez vou dividir em mais partes o post, nesta primeira parte vou focar apenas na configuração do Apache Directory Server (LDAP) e na autenticação com seam.

Pré requisitos:

Configurando o LDAP

Bem, o primeiro passo é criar uma aplicação com Seam, usando o bom e velho seam-gen. Veja este post para maiores informações.
Instale o Apache Directory Studio usando o update-site para eclipse e marque as opções Studio e Directory Server (isso vai lhe permitir iniciar um servidor LDAP de dentro do eclipse)

Bem, com o plugin configurado, abra a perspectiva de Servers do Directory Studio e crie um novo servidor, assim como na figura abaixo:

Servidor de LDAP do Directory Studio (clique para fullsize)

Servidor de LDAP do Directory Studio (clique para fullsize)

Inicie o servidor, clique com o botão direito sobre o mesmo, e então LDAP Browser -> New Connection. Isto vai conecta-lo ao servidor de LDAP, na aba esquerda “LDAP Browser” você pode agora criar os usuários e roles.

Bem, vamos criar uma árvore onde abaixo de nosso domain (dc), existe uma Organizational Unit (ou) para users e outra para roles.

Clique com o botão da direita em dc=example,dc=com e depois new entry. Selecione uma nova entrada e na tela de object classes “Organization Unit” e Add…

Adicionando uma OU (clique para fullsize)

Adicionando uma OU (clique para fullsize)

Na próxima tela no RDN use ou e roles como na figura abaixo:

Definindo o OU (clique para fullsize)

Definindo o OU (clique para fullsize)

Bem, agora repita este passo e crie uma ou com nome de users.

Bem, agora é preciso criar um usuário, basta seguir as telas abaixo:

Criando um usuário (clique para fullsize)

Criando um usuário (clique para fullsize)

Você deve adicionar os objetos Person e extensibleObject em sua entrada:

Adicionando extensible Object (clique para fullsize)

Adicionando extensible Object (clique para fullsize)

Na próxima tela é importante que seu DN fique da seguinte maneira : uid=$USER,ou=users,dc=example,dc=com pois esta é a string de pesquisa usada pelo componente do Seam no LDAP, então adicione apenas uid no seu RDN como na figura abaixo:

Cuidado com RDN... (clique para fullsize)

Cuidado com RDN... (clique para fullsize)

Na próxima tela você terá que adicionar dois campos a mais que são obrigatórios (CN=Common Name e SN=Surname) adicione um nome e sobrenome. Além disto, você deve adicionar um atributo member que vai apontar para o role que seu usuário participa.

Para adicionar um atributo clique no ícone mostrado na figura abaixo:

Clique no ícone em destaque (segundo da esquerda pra direita)

Clique no ícone em destaque (segundo da esquerda pra direita)

Agora escolha member:

Adicionando um member em nossa entrada (clique para fullsize)

Adicionando um member em nossa entrada (clique para fullsize)

Além disto você vai precisar de um userpassword:

Adicionando atributo userPassword

Adicionando atributo userPassword

No final, sua entrada deve se paracer com a figura abaixo:

Resultado final da entrada de um usuário (clique para fullsize)

Resultado final da entrada de um usuário (clique para fullsize)

Ok, o usuário esta configurado (a propósito, criei o usuário bob com senha bob :P )

Para cada novo role de um usuário, basta adicionar um novo atributo member para o usuário em questão

Agora podemos partir para o seam :)

Configurando o Identity Management

Configura o identityManagement é muito simples. IdentityManagement é uma classe que delega a um IdentityStore (no nosso caso LDAP), então você precisa configura o ldapIdentityStore e um security-identity-manager

Agora basta adicionar o ldapIdentityStore e security-identity-manager:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<security:ldap-identity-store name="ldapIdentityStore"
   			server-address="localhost"
   			server-port="10389"
   			user-DN-prefix="uid="
   			user-DN-suffix=",ou=users,dc=example,dc=com"
   			user-context-DN="ou=users,dc=example,dc=com"
   			user-password-attribute="userPassword"
   			role-context-DN="ou=roles,dc=example,dc=com"
   			role-DN-prefix="cn="
   			role-DN-suffix=",ou=roles,dc=example,dc=com"
   			bind-DN="uid=admin,ou=system"
   			bind-credentials="secret"
   			user-role-attribute="member"
   			user-object-classes="person,uidObject">
   </security:ldap-identity-store>
 
   <security:identity-manager identity-store="#{ldapIdentityStore}"></security:identity-manager>

Pronto, você pode inclusive remover seu authenticator agora :) O Seam cuida desta nova forma de autenticação para você.

Dos descritores acima quero falar apenas de dois pontos (ta tarde pra caralho e quero dormir :| ). Bem, o server-port não existe no XSD do seam, parece ser um bug pois o componente tem o atributo e você pode usar, eu já fui fominha e abri um bug mas podem usar sem problemas. Outro ponto é o atributo enabled que quando usado (nao foi nosso caso), deve ter o valor TRUE e não true, sabe por que? Abaixo um trecho do LDAPIdentityStore

431
if (LDAP_BOOLEAN_TRUE.equals(value)) return true;

O valor LDAP_BOOLEAN_TRUE é “TRUE” ou seja, se você usar “true” minúsculo vai levar graxa na cara.

Bom, agora, quando voce acessar sua aplicação e for na tela de login, ja vai estar usando o LDAP. Não precisou mexer em xhtml, nem em classe alguma. Não é uma beleza?

Pessoal, esse post eu fiz questão de varar a noite, primeiro porque só esta feature já é um motivo para vocês usarem Seam, segundo porque sou fominha e queria postar antes de qualquer um :D

O próximo post vou continuar daqui, vou mostrar como usar o IdentityStore para adicionar users via web no LDAP (sem você escrever uma linha de código), como funciona o novo mecanismo de permissions e como mesclar LDAP e banco de dados para armazenar permissions no banco de dados.

Inté