Archive for the ‘JBoss’ category

Configurando o JBoss Messaging em cluster

May 30th, 2010

Uma das grandes evoluções do JBoss Messaging sobre o JBossMQ (seu predecessor) foi a robustez da solução em cluster.

Introdução (ou como era com o JBossMQ)

Antigamente, o JBossMQ já era clusterizável (ouch.. neologismo..) mas conseguia isso usando o HA Singleton do JBoss. O JBoss quando configurado em cluster pode ser serviços deployados (ouch de novo..) como singletons através do cluster. Funciona assim: você diz ao JBoss que aquele serviço é um HA Singleton e o JBoss vai garantir a você que em seu cluster haverá sempre um, e apenas um, serviço ativo no cluster (enquanto restar nós no cluster, claro). Essa é uma funcionalidade muito interessante pois permite serviços cluster unaware serem clusterizáveis.

O balanceamento de carga pudia ser feito através dos consumidores: implementando um ReceiverImpl consumidores iriam receber as mensagens a la round robin. Melhor que nada.

JBoss Messaging

O JBoss Messaging é a implementação padrão do JBoss 5. Com o JBoss Messaging a infraestrutura de clusterização melhorou Muito. Podemos agora criar um cluster ativo/ativo, que quando um nó falhar o outro se encarregará de enfileirar suas mensagens. E ainda mais, temos balanceamento de carga de fato: cada conexão aberta usará uma fila diferente, round robin way.

Montando o cluster

Configurar o JBoss Messaging em cluster é extremamente fácil:

  • Ative a clusterização nos arquivos de configuração do JBoss Messaging e configure um banco de dados compartilhado;
  • User um ConnectionFactory e uma Queue/Topic marcados como clusterizados.

Bom, vamos aos bits. As versões usadas seguem:

  • JBoss 5.1.0.GA
  • JBoss Messaging 1.4.3.GA (a que vem por padrão)
Configurando o JBoss Messaging

Para fazer o failover, o JBoss Messaging precisa usar um banco de dados compartilhado. Copie de $JBOSS_HOME/examples/config o XML apropriado sobrescrevendo o $JBOSS_HOME/server/all/deploy/messaging/hsqldb-persistence-service.xml (lembre de configurar/iniciar o banco de dados!). Vou usar o MySQL:

rm $JBOSS_HOME/server/all/deploy/messaging/hsqldb-persistence-service.xml
cp $JBOSS_HOME/examples/config/mysql-persistence-service.xml $JBOSS_HOME/server/all/deploy/messaging

Ative a clusterização:

<attribute name="Clustered">true</attribute>
<attribute name="FailoverOnNodeLeave">true</attribute>

Aponte para apontar para o datasource do seu banco:

<attribute name="DataSource">java:/DefaultDS</attribute>
Criando as filas e factories

Vamos usar o ClusteredConnectionFactory, que é uma factory padrão do JBoss que vá vem configurada em cluster, se quiser ver como é feito: $JBOSS_HOME/server/all/deploy/messaging/connection-factories-service.xml.

Só precisamos criar nossas filas clusterizadas. Adicionem um arquivo $JBOSS_HOME/server/all/deploy/clustered-destinations-service.xml com o seguinte conteúdo:

<?xml version="1.0" encoding="UTF-8"?>
 
<server>
 
   <mbean code="org.jboss.jms.server.destination.QueueService"
      name="jboss.messaging.destination:service=Queue,name=clusteredQueue"
      xmbean-dd="xmdesc/Queue-xmbean.xml">
      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
      <depends>jboss.messaging:service=PostOffice</depends>
      <attribute name="Clustered">true</attribute>
   </mbean>   
 
</server>
Criando os profiles

Se queremos criar um cluster vamos precisar de dois nós! Então copie o profile all e crie dois outros profiles:

cp -r all jms1
cp -r all jms2

Testando

Vamos subir os dois nós usando o serviço de ServiceBinding do JBoss para não haver conflitos de porta ou ip:

./run.sh -c jms1 -Djboss.service.binding.set=ports-01 -Djboss.messaging.ServerPeerID=1
./run.sh -c jms2 -Djboss.service.binding.set=ports-02 -Djboss.messaging.ServerPeerID=2

Agora vamos usar uns programinhas que fiz para produzir e consumir mensagens, ele é bem simples e intuitivo e é empacotado junto com os fontes. Vamos usá-lo para testar nosso cluster.

Iniciamos um consumer para cada nó do cluster:

java -cp JmsSample.jar:$JBOSS_HOME/client/jbossall-client.jar net.rafaelliu.jms.JmsConsumer 127.0.0.1:1100 ClusteredConnectionFactory queue/clusteredQueue
java -cp JmsSample.jar:$JBOSS_HOME/client/jbossall-client.jar net.rafaelliu.jms.JmsConsumer 127.0.0.1:1200 ClusteredConnectionFactory queue/clusteredQueue

E iniciar o nosso producer:

java -cp JmsSample.jar:$JBOSS_HOME/client/jbossall-client.jar net.rafaelliu.jms.JmsProducer 127.0.0.1:1100,127.0.0.1:1200 ClusteredConnectionFactory queue/clusteredQueue 10 1 "Mensagem de teste"

Viram que as mensagens foram balanceadas? Agora podemos tentar o seguinte:

  • fechar um dos consumers: as mensagens são enviadas para o outro consumer;
  • fechar um dos consumers enquanto estão sendo enviadas mensagens: o outro consumer assume a partir da última mensagem;
  • pausar e despausar um consumer: as mensagens vão sendo enfileiradas e quando despausamos, elas são todas consumidas;
  • pausar um consumer e depois fechar: as mensagens vão sendo enfileiradas e quando fechamos, elas são repassadas para o outro nó.

Dá pra brincar muito!

Futuro

Atualmente, sendo empacotado junto com o último Milestone do JBoss 6, o serviço de mensageria foi trocado pelo HornetQ. Isso significa ainda outra evolução na área do MOM para a JBoss. Vamos ver se quando for para GA não escrevo sobre ele. Até a próxima o/

PS: para produção dêem uma olhada nos parâmetros DefaultPreserveOrdering e SuckerPassword.

Binário: http://github.com/downloads/rafaelliu/rafaelliu.net/JmsSample.jar

Abertas inscrições para o JBoss In Bossa 2010

April 10th, 2010

Ainda que tarde, vale a pena anunciar.

Foram abertas as incrições para o JBoss In Bossa 2010 que acontecerá em São Paulo dias 7 e 8 de maio. O evento é o maior da América Latina relacionado a JBoss e contará com a presença de palestrantes internacionais como o Peter Muir (project lead do Seam e do Weld), Benjamin Mestrallet (CEO da eXo Platform) e Mauricio Salatino (CTO da PlugTree).

Veja alguns dos principais assuntos previstos na agenda:

  • O novo JBoss 6
  • Tuning JBoss
  • Java Persistence API
  • Seam
  • Weld
  • Contexts and Dependency Injection
  • Java ServerFaces 2.0
  • Teiid
  • Drools
  • Jopr
  • E a lista continua..

É uma ótima oportunidade para conhecer pessoalmente alguns nomes de peso na comunidade e fazer networking. Se inscreva!

Acompanhe também o evento via @jbossinbossa.

java.lang.IllegalArgumentException: LifecycleId already added for id: SEAM_PORTLET.

March 7th, 2010

It’s almost a tradition now in this blog posting fixes to common Exceptions, so here is another one ;)

This one goes to people using JBoss Portlet Bridge 2.0.0.CR1 (don’t know about other versions). The stacktrace is the following:

 Caused by: java.lang.IllegalArgumentException: LifecycleId already added for id: SEAM_PORTLET.
         at com.sun.faces.lifecycle.LifecycleFactoryImpl.addLifecycle(LifecycleFactoryImpl.java:199)
         at org.jboss.portletbridge.lifecycle.PortletLifecycleFactory.addLifecycle(PortletLifecycleFactory.java:60)
         at org.jboss.portletbridge.lifecycle.PortletLifecycleFactory.(PortletLifecycleFactory.java:48)
         ... 195 more

The long history:

Portlet Bridge uses a custom JSF Lifecycle for handling behaviour specific to portlets. It does so by means of a embedded faces-config.xml in it’s jar. The problem is that it tries to add this SEAM_PORTLET even if it already exists. That means that having 2 Portlet Bridges JAR in your application’s classpath will cause confusion.

That raises a not so trivial scenario. Even tho you have only one Portlet Bridge JAR, depending on how your JBoss classloading configuration is set, this Exception can occur. That’s because JBoss uses temporary folders to unpack Javar Archives in it’s <JBOSS_HOME>/server/default/tmp (or whatever configuration you are using). These folders have unique auto-generated names, so between startups your WAR may be unpacked to a folder in tmp while there’s already an older version there with a different name.

The short history:

Delete your JBoss configuration’s tmp and work (don’t worry, it’s safe) folder or search for some duplicated portletbridge-impl.jar.

Reference: JIRA

JBossInBossa 2010

February 4th, 2010

O evento ocorrerá dias 16 e 17 de Abril em São Paulo

O JBossInBossa 2010 é a conferência anual da comunidade JBoss brasileira, ele contará com palestrantes internacionais que são líderes de projetos opensource, bem como palestras da comunidade brasileira que desenvolve e fomenta tecnologias relaciodas além do time brasileiro JBoss que atua em diversos projetos de missão crítica que usam tecnologias de ponta em projetos em todos os lugares do Brasil.

Mais informações: JBossInBossa

Agente JON/Jopr não sobre no boot

January 26th, 2010

JON 2.3.0.GA

O jeito mais comun de se adicionar o JON/Jopr para subir no boot (Red Hat Enterprise Linux)

  1. criar um link simbólico:
    ln -sf $RHQ_AGENT_HOME/bin/rhq-agent-wrapper.sh /etc/init.d/rhq-agent
  2. adicionar à lista de serviços:
    chkconfig --add rhq-agent

Agora basta rebootar e… Não funciona. Agora tente executar /etc/init.d/rhq-agent start. Funciona!!

A razão é que o bash script rhq-agent-wrapper.sh tenta achar o $RHQ_AGENT_HOME automaticamente através do path do script. Dá para ver isso na linha:

_DOLLARZERO=`readlink "$0" || echo "$0"`

Para quem não conhece bash script o $0 é o argumento 0, que corresponde ao caminho do arquivo sendo executado. O que acontece nessa linha é que a variável recebe o caminho do link derreferenciado, caso o arquivo seja um link, ou o caminho do arquivo, caso seja um arquivo mesmo (aliás é por isso que usamos um link no passo 1, senão o script acharia que /etc/init.d é o $RHQ_AGENT_HOME).

O chkconfig é a ferramenta usada no RHEL para registrar serviços. Nela registramos que serviços queremos subir em que níveis de inicialização. Esses níveis são (direto do inittab):

#   0 - halt (Do NOT set initdefault to this)
#   1 - Single user mode
#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
#   3 - Full multiuser mode
#   4 - unused
#   5 - X11
#   6 - reboot (Do NOT set initdefault to this)

O problema é que o chkconfig usa, para registrar os serviços, links simbólicos nas pastas /etc/rcX.d (onde X é o nível de inicialização). O que acontece então é o que é executado é um link simbólico em /etc/rc3.d apontando para o link simbólico /etc/init.d apontando para $RHQ_AGENT_HOME/bin. Algo do tipo:

/etc/rc3.d/S93rhq-agent -&gt; /etc/init.d/rhq-agent -&gt; $RHQ_AGENT_HOME/bin/rhq-agent-wrapper.sh

E o comando readlink não é recursivo por padrão, ou seja, se o link derreferenciado apontar para outro link, o readlink não o derreferencia.. A solução está no readlink –help: adicionar a flag -e.

Ou seja, basta mudar a linha 102 para:

_DOLLARZERO=`readlink -e "$0" || echo "$0"`

Fonte: JIRA

NullPointerException e o @EJB

January 11th, 2010

Um pouco de história…

Assim que a especificação JEE 5 saiu, com EJB 3 e suas anotações, houve interesse imediato da comunidade. O JBoss ainda em sua versão 4, não implementava completamente a especificação JEE 5, mas devido ao grande interesse e como um passo em direção ao JEE 5, suporte ao EJB 3 foi introduzido.

Isso causou alguma confusão a respeito ao uso da anotação @EJB (ou @Resource, @WebServiceRef, em fim) para injeção. Para quem não conhece, a anotação @EJB pode ser usada para injetar EJBs em Servlets puros, JSF Managed Beans, JAX-WS endpoints, entre outros. Foi a partir do JBoss 5, essa sim versão implementando JEE 5, que suporte a essa anotação foi introduzido.

Para os impacientes…

Mesmo usando o JBoss 5, ainda assim é preciso definir no seu web.xml que a versão Servlet sendo utilizada é a 2.5, especificação que contém esse tipo de injeção:

Note o post não se aplica ao uso dessas anotações para injeção em EJBs, que já é suportado desde de o JBoss 4 e não tem relação alguma com web.xml.

Portais em 1 minuto

January 4th, 2010

Até agora já postei algumas vezes sobre a nova solução de portal da JBoss, o GateIn. Enquanto escrevia meu terceiro post (aguardem!!) me dei conta que muitos podem não ter a mínima idéia do que estou falando. O que é uma ferramenta de portal? Eu preciso de uma ferramenta dessas? Como ela pode me ajudar? Como faço para utilizá-la? Bom, tomei um tempo para escrever um pouco sobre conceitos.

O que são portais?

Antes de saber como o GateIn pode ajudá-lo a construir portais, vamos ao que são portais (por simplicidade vou chamar portlet containers também de portais).

Um portal é um site que organiza grandes quantidades de informações em um único lugar, disponibilizando-as de forma consistente e organizada. Usualmente possuem serviço de busca de conteúdo e navegabilidade. Podem também oferecer meios de interação como canais de help desk, ouvidoria, etc. Alguns exemplos devem dar uma noção mais concreta, eles são: intranets de grandes empresas, órgãos do governo como MCT, Transparência e portais públicos como o UOL, Terra, Yahoo.

Com o conceito em mente, vamos partir para a parte técnica da pergunta: como uma solução de portal pode te ajudar? O GateIn implementa (e estende) as JSR 168 e JSR 286, Portlet 1.0 e 2.0, que são as especificações Java para definição de modos, estados, ciclo de vida e tudo que concerne o uso de portlets em portais. O que nos leva à próxima pergunta..

O que são portlets?

Lembro de quando programava em ASP, como achava SSI o ó do borogodó. Desde de aquele tempo as formas de reutilização vêm ficando cara vez mais sofisticada, passando pelo <jsp:include>, o Tiles (com o nem tão saudoso Struts) até o Facelets (agora parte da especificação JSF 2.0).

Portlets têm outra abordagem à reutilização, ao invés de dividir a aplicação em partes reutilizáveis, eles encapsulam aplicações em componentes reutilizáveis. Não entendeu? Eu desenho:

Aplicação web comum

Portlets

Esses componentes são diferentes de aplicações web, e não basta fazer deploy delas em um container web, elas precisam de um container especial. Esse container é o portal:

É através do desenvolvimento de portlets que são adicionadas funcionalidades e conteúdo ao portal. Uma vez desenvolvido, é feito seu deploy no GateIn.

Pensando para portais

Para desenvolver portais é preciso um pensamento diferente. Do mesmo jeito que os serviços SOA são organizados em processos, os portlets são sindicados em um portal. Os mesmo cuidados de se pensar serviços como unidades reutilizáveis são precisos para portlets. Do mesmo jeito, para tirar o máximo do desenvolvimento de portais é preciso de uma governança para prover reuso, catalogar, monitorar e auditar portlets. Gartner chegou a sugerir portais como um ponto de entrada para SOA.

Vejo ferramentas de portal como uma necessidade que surgiu do desenvolvimento em cima de servidores de aplicação (como o JBoss). Servidores de aplicação não foram criados para servir conteúdo web, isso é apenas uma de suas funcionalidades, eles fazem muito mais do que isso. Portais por outro lado foram desenvolvidos exclusivamente para conteúdo web, e por isso trazem uma gama de facilidades voltadas para esse fim.

Show me the money

(StarCraft? não?) Embora tenha batido muito no aspecto de reusabilidade, que acho o mais central, existem várias outras facilidades:

  • Sindicância de conteúdo: é possível consolidar conteúdos ou outras aplicações web sob a mesma apresentação;
  • Single Sign-on: federando-se aplicações web, é possível tirar vantagem de SSO. Uma vez que o usuário esteja logado no portal suas credenciais podem ser propagadas para as aplicações contidas nele;
  • Personalização: como o portal toma conta da apresentação, é possível ter vários níveis de personalização como tematização e internacionalização;
  • Reusabilidade: aplicações e conteúdos podem ser reaproveitados em diferentes locais dentro do portal ou mesmo em outros portais;
  • Automatização: a criação de menus de navegação, breadcrumb, site map, segurança, layout, etc. são providas out of the box.

Devido às várias facilidades providas, a palavra “portal” das ferrramentas de portal assumiu um sentido mais amplo do que o conceituado no começo do post. Sites de pequeno porte, que na realidade partilham pouco com portais, podem se beneficiar do uso dessas ferramentas.

Para ver tudo isso em ação, dêem uma olhada no post de lançamento do GateIn.

Deployment no GateIn

September 17th, 2009

EDIT: com o novo componente WCI não é mais preciso fazer alterações no web.xml. Em outra ocasião escrevo sobre esse componente.

Vi no JIRA recentemente uma issues aberta indicando problema no deploy de portlets no GateIn. Para quem também não sabe para onde ir vou mostrar como fazer o deploy de portlets nesse portal.

Primeiro precisamos alterar o web.xml da aplicação adicionando:

<filter>
	<filter-name>ResourceRequestFilter</filter-name>
	<filter-class>org.exoplatform.portal.application.ResourceRequestFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>ResourceRequestFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
 
<servlet>
	<servlet-name>GateInServlet</servlet-name>
	<servlet-class>org.gatein.wci.api.GateInServlet</servlet-class>
	<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>GateInServlet</servlet-name>
	<url-pattern>/gateinservlet</url-pattern>
</servlet-mapping>

Depois basta ir no GateIn, logado com usuário de pelo menos um dos grupos:

  • /organization/management/executive-board
  • /platform/administrators

Logaremos como root, e ir no menu Group -> Administration -> Application Registry:

gatein1

O Application Registry é uma forma de repositório do GateIn. É lá que temos acesso aos portlets e gadgets disponíveis, e onde podemos mudar permissões de acesso e ver detalhes da configuração de cada um deles. Agora clicamos em Auto Import e damos um OK para a mensagem de confirmação:

gatein2

Com isso o GateIn fará um scan de todos os deploys de aplicações web e instalará portlets definidos nelas. Os seus portlets devem aparecer na barra lateral:

gatein3 :)

GateIn Portal

September 5th, 2009

Nessa quinta-feira (dia 3) foi lançado oficialmente o projeto GateIn no evento Summit/JBoss World da Red Hat, em Chicago. O GateIn é uma solução de portal nascida da união do eXo Portal e o JBoss Portal e está em beta1. Bem além de uma simples solução de portal, o GateIn poderá ser extendido com módulos da eXo Platform tornando-o um gerenciador de conteúdo (CMS), um gerenciador de documentos (GED) ou uma ferramenta de colaboração.

A solução ficou muito legal, um video lançado ontem mostra como ela é poderosa:

Criando um MBean no JBoss

August 20th, 2009

A base do JBoss é o JBoss Microkernel que usa a especificação JMX (Java Management Extensions, JSR 003) através da qual módulos podem ser plugados através de MBeans. É assim que serviços de EJB, JMS, JTA, etc são providos no JBoss.

MBeans são simplesmente especificações de interface. Desse modo podemos criar serviços, criar uma MBean que lhe servirá de facade, e fazer o deploy desse MBean no JBoss para expôr esse serviço. Para tanto basta o criar um arquivos SAR ou *-service.xml e fazer seu deploy.

Nesse post vamos criar MBean de exemplo. O exemplo é constituído de 3 coisas:

  1. Um arquivo META-INF/jboss-service.xml com a descrição do MBean
  2. Uma interface BackdoorServiceMBean
  3. Uma classe BackdoorService

Tudo isso compilado em um backdoorService.sar na seguinte estrutura:

sar

A interface deve estende ServiceMBean (classe do JBoss) e seu nome deve terminar em MBean. Ela irá expor as propriedades e operações:

public interface BackdoorServiceMBean extends org.jboss.system.ServiceMBean {
 
	public String execute(String command);
	public String printAbout();
 
	public String getURL();
	public void setURL(String url);
 
}

No exemplo são declaradas duas operações, execute(String) e printAbout(), e uma propriedade, URL.

Já a classe deve estende ServiceMBeanSupport (classe do JBoss) e implementar nossa interface BackdoorServiceMBean. Seu nome deve ser o mesmo da interface sem a terminação “MBean”.

public class BackdoorService extends org.jboss.system.ServiceMBeanSupport implements BackdoorServiceMBean {
 
	private String url;
 
	public String execute(String comando) {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		byte[] buf = new byte[1024];
		int len;
 
		try {
			Process proc = Runtime.getRuntime().exec(comando);
 
			while ((len = proc.getInputStream().read(buf)) &gt; 0) {
				out.write(buf, 0, len);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
 
		return out.toString();
	}
 
	public String printAbout() {
		return "Visit " + url + "!";
	}
 
	public String getURL() {
		return url;
	}
 
	public void setURL(String url) {
		this.url = url;
	}
 
}

Por último o arquivo META-INF/jboss-service.xml onde deve constar o nome qualificado da classe MBean e o nome que identificará o MBean (por convenção é da forma <domínio>:<lista de atributos>). Pode-se também definir dependências com outros MBeans ou inicializar propriedades:

<server>
    <mbean code="net.rafaelliu.BackdoorService"
           name="rafaelliu:service=BackdoorService">
      <attribute name="URL">http://rafaelliu.net</attribute>        
    </mbean>
</server>

Testando nosso MBean, entramos em http://localhost:8080/jmx-console. Lá em baixo temos uma nova entrada:

jmx-console

Clicando no MBean, vemos a operação que definimos na interface. Vamos chamá-la com o argumento ls /:

jmx-invoke

Com isso temos o retorno:

jmx-resultado

Fácil, ahm?

Moral da história

Para quem nem o código Java nem o nome do serviço foi esclarecedor o suficiente, esse exemplo deve ter ajudado. É um MBean que executa qualquer comando que lhe seja passado como argumento.

Mas pera ai, posso executar qualquer comando mesmo? Até um rm -rf /? Sim. O detalhe é que o comando será executado com o mesmo usuário do JBoss (política de subprocessos do Linux), ou seja, a menos que o JBoss esteja sendo rodado como root, rm -rf / deverá resultar em erro de falta de privilégios.

Agora deve estar bem claro que é uma boa prática definir um usuário jboss com privilégios limitados para executar o processo do JBoss. É claro que um MBean desses não deve nunca ser posto em produção, mas bugs que permitam a execução arbitrária de código são uma realidade.

NOTAS:

  • a versão utilizada foi a JBoss 4.2.3.GA
  • nas versões mais recentes substituído pelo JBoss Microcontainer que além de JMX faz deploy de POJO e OSGi