Portais em 1 minuto

January 4th, 2010 by rafaelliu No comments »

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.

Novidade

December 28th, 2009 by rafaelliu 2 comments »

O blog está de hospedagem nova! Depois de alguns problemas com o host passado, mudei para o Helio Host. Estou bem satisfeito até agora (é gratuito, custa nada dar uma divulgada..). Aproveitando o clima de mudança mudei também o tema, agora menos dark.

Feliz natal e ano novo a todos!

Conferência Internacional de Segurança de Aplicações (AppSec Brasil 2009)

October 22nd, 2009 by rafaelliu No comments »

Acontecerá nos dias de 27 a 30 de outubro:

A comunidade Comunidade TI-Controle e o Centro de Informática da Câmara dos Deputados apresentam a Conferência Internacional de Segurança de Aplicações, que será realizada com o apoio do OWASP (Open Web Application Security Project) em Brasília, capital do Brasil. A conferência consistirá de dois dias de treinamentos, seguidos de dois dias de plenárias em trilha única.

Mais informações: AppSec Brasil 2009

Atraso de vida: IE6

October 22nd, 2009 by rafaelliu No comments »

Sou o mais novo participante da campanha. Instalei até plugin do WP

2644891323_e5fb590a93

Deployment no GateIn

September 17th, 2009 by rafaelliu 2 comments »

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 by rafaelliu No comments »

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:

Dual head com o OpenOffice Impress (fenomenal!!!)

August 26th, 2009 by rafaelliu No comments »

Às vésperas de dar um treinamento JBoss, eis que encontro:  Sun Presenter Console. Fiquei tão excitado com a descoberta que usei o jargão reservado aos esportes por falta de palavra melhor. Tive que postar.

O Sun Presenter Console é uma extensão para o OpenOffice Impress que ajuda [muito] em apresentações em dual head (monitor do notebook e projetor, por exemplo).  Foi no Keynote da Apple e no Powerpoint da Microsoft que primeiro vi essa funcionalidade. Admito que o mais perto que cheguei de conhecê-la foi ver algum palestrante usando-a, mas não creio que seja tão completos quando é essa extensão para o OpenOffice Impress. Com ele é possível pôr a apresentação num monitor em fullscreen e em outro mostrar informações como o slide atual, o próximo slide, as notas para aquele slide e uma lista de thumbnails de slides. Perfeito!!!

Isso mostra a competência e a força de competitividade da comunidade. Devo dizer que deu um certo orgulho, mesmo sendo apenas entusiasta Open Source :p

EDIT: pra não ficar só na conversa, aqui vão uns screenshots do segundo monitor (no primeiro estaria a apresentação)

referência: GullFOSS

Criando um MBean no JBoss

August 20th, 2009 by rafaelliu 8 comments »

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

Implementando testes com mock objects

July 20th, 2009 by rafaelliu No comments »

Ok, estou convencido que usar mock objects é uma boa idéia mas como faço isso? A princípio não é qualquer código que está pronto para ser testado usando-se mocks, ele precisa ser escrito de uma forma a possibilitar isso.

No geral escrever código de tal forma que seja testável é uma boa prática e indica que ele segue alguns princípios de projeto que o tornam fracamente acoplado, aumentam sua manutenibilidades, etc.

Vejamos um exemplo de código que deva ser alterado para se tornar testável:

public class CustomerFacade {
 
	private CustomerDao customerDao;
 
	public CustomerFacade() {
		customerDao = new CustomerDaoImpl();
	}
 
	public void hireCustomer(Custumer custumer) { ... }
 
	public void fireCustomer(Custumer custumer) { ... }
 
}

Como já devo ter dito, não sou muito bom de exemplos.. Mas acho que esse ai está bem ilustrativo, embora para alguns DAO possa parecer meio arcaico. Deixei as reticências para a imaginação de vocês.

Existem 3 formas de se alterar esse código, as duas primeiras se usam de técnicas de bom projeto e melhoram a qualidade do software:

1. Dependency Injection (DI)

O mais simples e limpo. Foi a forma usada para injetar os mocks no exemplo do post passado:

public class CustomerFacade {
 
	private CustomerDao customerDao;
 
	public void setCustomerDAO(CustomerDao customerDao) {
		this.customerDao = customerDao;
	}
 
	public void hireCustomer(Custumer custumer) { ... }
 
	public void fireCustomer(Custumer custumer) { ... }
}

Basta agora, na hora de testar injetar não o componente real, mas seu mock.

public class CustomerFacadeTest {
    private Mockery context = new Mockery();
 
    public CustomerFacadeTest() {
    	context = new Mockery();
    }
 
    @Test
    public void testHire() throws Exception {
        // set up mock
    	final CustomerDao customerDao = context.mock(CustomerDao.class);
 
        // test state
    	CustomerFacade customerFacade = new CustomerFacade();
    	customerFacade.setCustomerDAO(customerDao);
 
        // expectations
        context.checking(new Expectations(){{
	        oneOf(customerDao).save(12);
        }});
 
        // execute
        customerFacade.hireCustomer(new Custumer(12));
 
        // verify
        context.assertIsSatisfied();
    }
 
}

2. Factory Method

Uma técnica um pouco mais embolada mas que ainda assim trás melhorias para o código consiste na extração de um Factory Method:

public class CustomerFacade {
 
	private CustomerDao customerDao;
 
	public CustomerFacade() {
		customerDao = createCustomerDao();
	}
 
	protected CustomerDao createCustomerDao() {
		return new CustomerDaoImpl();
	}
 
	public void hireCustomer(Custumer custumer) { ... }
 
	public void fireCustomer(Custumer custumer) { ... }
 
}

Notem que o createCustomerDao() é protected, isso porque na hora de usá-lo nos testes vamos estender essa classe e sobrescrever o createCustomerDao() para retornar um mock:

public class CustomerFacadeTest {
    private Mockery context = new Mockery();
 
    public CustomerFacadeTest() {
    	context = new Mockery();
    }
 
    @Test
    public void testHire() throws Exception {
        // set up mock
    	final CustomerDao customerDao = context.mock(CustomerDao.class);
 
        // test state
    	CustomerFacade customerFacade = new CustomerFacade() {
 
		@Override
		protected CustomerDao createCustomerDao() {
			// return the mock instead!!
			return customerDao;
		}
 
    	};
 
        // expectations
        context.checking(new Expectations(){{
	        oneOf(customerDao).save(12);
        }});
 
        // execute
        customerFacade.hireCustomer(new Custumer(12));
 
        // verify
        context.assertIsSatisfied();
    }
 
}

3. Aspect Oriented Programming

Essa é uma técnica workaround, e é para quando realmente não há jeito de usar-se as outras técnicas. Com ela não é preciso alterar código algum, apenas criar um point cut que intercepte a instanciação do CustomerDaoImpl. O test case é o seguinte:

public class CustomerFacadeTest {
	private Mockery context = new Mockery();
	private CustomerDaoImpl customerDao;
 
	public CustomerFacadeTest() {
		context = new Mockery();
		// so we can mock a concrete class
		context.setImposteriser(ClassImposteriser.INSTANCE);
 
		customerDao = context.mock(CustomerDaoImpl.class);
	}
 
	// returns the mock instance in test context
	public CustomerDaoImpl getCustomerDao() {
		return customerDao;
	}
 
	@Test
	public void testHire() throws Exception {
		// test state
		CustomerFacade customerFacade = new CustomerFacade();
 
		// expectations
		context.checking(new Expectations(){{
			oneOf(customerDao).save(12);
		}});
 
		// execute
		customerFacade.hireCustomer(new Custumer(12));
 
		// verify
		context.assertIsSatisfied();
	}
 
	public String print() {
		return("adasda");
	}
 
}

E criando-se o aspecto em AspectJ:

public aspect InstanciatingAspect{
 
	// intercept only from CustomerFacadeTest
	pointcut testing(Object test) :
		this(test) &&
		execution(public void CustomerFacadeTest.*());
 
	// intercept CustomerDaoImpl instantiations
	pointcut instanciateCustomerDao(Object test) :
		cflow(testing(test)) &&
		call(CustomerDaoImpl.new(..));
 
	Object around(Object test) : instanciateCustomerDao(test) {
		// get a hold of the mock instance made public by our test case
		CustomerDaoImpl customerDaoImpl = ((CustomerFacadeTest) test).getCustomerDao();
		// return the mock reference instead
		return customerDaoImpl;
	}
}

Como visto, a única dificuldade é que o aspecto deve retornar uma instância do mock que tenha sido criada no contexto do test case.Para tanto instanciamos o mock no test case e o tornamos acessível através do getCustomerDao(). Feito isso, ao interceptarmos no aspecto a criação do CustomerDaoImpl() nós a substituímos pela referência obtida do test case.

Série de trabalhos: Mock Objects

May 2nd, 2009 by rafaelliu 6 comments »

Estou fazendo dois trabalhos atualmente: sobre Mock Objects (como preparatório para Service Simulation, se tudo der certo) e sobre WSS. Por isso, e também para receber alguns inputs (que seriam muito bem vindos) vou postar algumas coisas da minha pesquisa aqui no blog. E nesse post explico o que são Mock Objects.

Mock Objects são objetos que simulam outros objetos. São principalmente usados em testes de unidade. Existem vários frameworks de Mock Objects mas pessoalmente prefiro o jMock. Abaixo mostro um exemplo de um teste de unidade usando-se TestNG 5.9 e jMock 2.5:

public class PublisherTest {
	private Mockery context = new Mockery();
 
	public PublisherTest() {
		context = new Mockery();
		// para podermos mockar uma classe
		context.setImposteriser(ClassImposteriser.INSTANCE);
	}
 
	@Test
	public void testOneSubscriberReceivesAMessage() {
		// configura mock
		Subscriber subscriber = context.mock(Subscriber.class);
		Expectations expect = new Expectations();
		String message = "message";
 
		// configura estado do objeto
		Publisher publisher = new Publisher();
		publisher.add(subscriber);
 
		// expectativas
		expect.never(subscriber).receive(message);
 
		context.checking(expect);
 
		// executa
		publisher.publish(message);
 
		// verifica
		context.assertIsSatisfied();
	}
 
}

Usamos mocks em cenários onde precisamos testar um objeto que depende de outros. Qual o problema de dependências? O objetivo dos testes de unidade é testar objetos em isolado, mas se usássemos um Subscriber real erros nele poderiam fazer falhar o teste do Publisher (ver figura abaixo). Por isso usamos mocks.

Teste usando-se objetos reais

Teste usando-se objetos reais

Teste usando-se mocks

Teste usando-se mocks

Com mocks podemos não só substituir algum objeto, mas também controlar todas as interações que são feitas com ele: verificar chamadas de métodos, valores de parâmetros, definir valores de retorno, etc. No código acima estamos por exemplo esperando uma chamada ao método receive do subscriber.

Dito o objetivo que motivou a criação dessa técnica, existem outros que vieram a ser supridos por mocks:

  • Abstrair camadas mais baixas do sistema, tanto por elas não estarem prontas quanto por querermos trabalhar offline.
  • Centralizar a configuração de estado no próprio mock ao invés de espalhá-las pelos testes de unidade.
  • Simular condições difíceis de reproduzir, como o lançamento de uma excessão mais esdrúxula ou um valor retorno raro.
  • Verificar mais rapidamente quando um erro ocorre (fail fast), indicando em que passo do comportamento esperado foi errado ao invés de apenas dizer que o estado final do objeto não condiz com o esperado.

Algo muito interessante vindo do uso de mocks é o Need-Driven Development (NDD), mas não pretendo falar dele aqui. Quando sair meu trabalho disponibilizo no blog, mas quem tiver curiosidade pode me escrever, é sempre bom trocar idéias :)