3

Desenvolvimento dirigido a testes vale a pena?

-

Paralelamente ao meu trampo Java EE, estou desenvolvendo um sisteminha para controle financeiro em Rails. E tudo o que vejo de errado, ou que poderia ser melhor aqui na empresa, estou tentando levar no meu projeto. E uma das coisas é o TDD. Evidentemente testes unitários deveriam ser prioridade em qualquer sistema de informação, mas sabemos que na realidade, as vezes a diretoria pressiona, e você tem que correr com o codigo e deve deixar algo de lado, para encaixar no prazo. Geralmente esse “algo” que fica de lado, é o teste. Com rails/ruby, é possível explorar mais ainda o TDD. Pelo fato de ser uma linguagem dinâmica, é possivel você criar o teste antes do código. Parece estranho né ? Mas isso te força a sempre codificar pensando no teste e sempre testar pensando no código. E acredite, isto faz uma enorme diferença.

Temos alguns sistemas legados aqui na empresa, que não tiveram esta preocupação com o teste. Devido, provavelmente ao que relatei no parágrafo anterior. E agora estamos com muito receio de refatorar o código, pois não temos a segurança que uma boa suite de teste nos daria. Ai você me diz: “Simples! Faça a tal suite de testes, e depois refatora!”. Entretanto, o sistema não foi feito pensando em testes, não foi concebido para ser unitariamente testado. Com isso temos o codigo de negocio completamente vinculado ao acesso ao banco, o que torna praticamente impossível a utilização de uma camada de mocks. Ou seja, estamos em maus lençóis.

0

Como injetar POJOs em um SessionBean via Spring?

-

É fato que a especificação EJB3 trouxe uma enorme facilidade para o desenvolvimento de aplicações Java EE, porém, ainda sinto falta de algumas simplicidades, como por exemplo: “Como injetar um POJO em um SessionBean?” Ok, mas porque eu iria querer fazer isso ? E outra, fiquei sabendo que tem injeção de dependência em EJB3 via annotations, pra que colocar outro container de IoC, como o Spring ?

Ótimas perguntas! Então, vamos lá:

Em primeiro lugar, o IoC do EJB3 só funciona para recursos controlados pelo container, tais como: EJBs, Datasources, Filas, Topicos, etc. Ou seja, se você quiser injetar um POJO, no seu SessionBean, infelizmente não existe uma annotation @POJO, para fazer isso.

Com isso, podemos concluir que para tirar proveito da IoC do seu servidor de aplicação Java EE favorito, você deveria transformar todos os seus objetos de negócio em objetos gerenciados pelo container (traduzindo, EJB), mas isso nem sempre é desejado ou permitido (no caso de você utilizar uma classe ou jar de terceiros, ou compartilhar um modulo com outro projeto que não utiliza EJB). Então, o que fazer ? Simples: AOP!

AOP ?!?! Sim, mas calma, a solução é bem mais simples do que parece. Basta criar uma annotation (@Spring, por exemplo) e implementar o seu próprio interceptor, que irá carrega o seu xml do spring com as definições dos beans (seu applicationContext.xml) e injetá-los, onde estiver marcado com a annotation criada.

A sua annotation poderia ser:

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Spring {
        String bean();
}

A mágica:

Aqui vai um exemplo bem simples de interceptor que carrega as configurações do applicationContext, e sai injetado os beans do spring onde tiver uma propriedade anotada com @Spring:

public class SpringInterceptor {

	// AplicationContext - Spring
	private static ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml");

	@PostConstruct
	// O Método anotado com PostConstructor deve receber um parametro (InvocationContext),
	// nao deve lançar exceção e o retorno deve ser void
	public void init(InvocationContext invocationContext) {

		// Obtém o session bean que terá as propriedades injetadas
		Object o = invocationContext.getTarget();

		Field[] fields = o.getClass().getDeclaredFields();
		try {
			for (int i = 0; i < fields.length; i++) {

				if (fields[i].isAnnotationPresent(Spring.class)) {
					// Seta o atributo como acessível (sim, quebra o encapsulamento =p )
					fields[i].setAccessible(true);
					// Obtém o nome do Bean e o busca no contexto do spring (ApplicationContext)
					Spring springAnnotation = fields[i].getAnnotation(Spring.class);
					// Injeta o SpringBean(POJO) na propriedade do SessionBean
					fields[i].set(o, appCtx.getBean(springAnnotation.bean()));
				}
			}
		} catch (Exception e) {
                        // Tá, isso pode ser bem melhor ;p
			e.printStackTrace();
		}
	}
}

O Segredo:

Note que toda a lógica do interceptor está no método anotado com @PostConstruct, ou seja o pós-construtor do interceptor. Na verdade este nosso interceptor não intercepta nenhuma chamada. Ele apenas é construído, e na sua construção, injeta os pojos que definimos no arquivo applicationContext.xml. Legal né?

Modo de usar:

Para usar, você tem que indicar, no seu SessionBean, que irá utilizar o interceptor criado:

@Stateless
@Interceptors(value = SpringInterceptor.class)
public class MySessionBean implements MySession {

	@Spring(bean="MyBean")
	private MyBean MyBeanImpl;

        ...
}

Neste caso, a nossa annotation funciona apenas para propriedades (Fields), mas é facilmente expansível para métodos, o que fica como "lição de casa".

0

Vários JBoss na mesma máquina

-

Várias vezes já precisei subir mais de um JBoss na mesma máquina. E para fazer isso eu saia alterando as portas utilizadas pelo servidor em vários arquivos xml. Porém, o JBoss não utiliza somente as portas 8080 e 1099 (que são as mais comuns), o que torna árdua, desgastante e deselegante esta tarefa. Ai juntamos a isso o problema de cada nova versão de jboss disponibilizar as configurações em arquivos diferente e conseguimos algo bem caótico.
Porém, esses dias descobri um truqe bem legal. Você pode subir uma nova instância de JBoss em outro IP dentro da mesma máquina. Basta passar o argumento -b na linha de comando ao iniciar o JBoss (run.bat / run.sh). Ficaria assim:

$JBOSS_HOME/bin/run.sh -c minha_app_1 -b 127.0.0.2
$JBOSS_HOME/bin/run.sh -c minha_app_2 -b 127.0.0.3

Com isso teremos duas instancias de JBoss rodando na mesma máquina e sem conflitos de porta. Mas vale uma ressalva, apenas a sua maquina enxerga esses 2 Jboss, não há como fazer acesso remoto a eles, pois em qual IP você faria lookup ?

0

Rails 2.0 – Rotas aninhadas

-

Estava eu seguindo o tutorial “Rolling with Rails 2.0″ do Akita, quando me deparei com um pequeno problema envolvendo autenticação com o plugin restful_authentication. No tutorial, o Akita “migra” o famoso “Webblog in 15 minutes” para rails 2.0, inclusive usando as características restful desta versão.

Porém, na hora de falar sobre autenticação, o Akita apenas cita o plugin restful_authentication e parte para a autenticação básica via http, me deixando sem rumo…

Confesso que foi super simples utilizar o plugin. Há muita documentação sobre isso na net, porém, eu não conseguia criar rotas aninhadas em 2 níveis, do tipo:

localhost:3000/users/1/posts/3/comments

Porém, tava deificil encontrar como fazer isso, mas finalmente achei. Basta fazer isso no routes.rb:

  map.resources :users do |user|
    user.resources :posts do |post|
      post.resources :comments
    end
  end

Com isso, teremos as seguintes rotas:

  • user_posts_path
  • new_user_post_path
  • user_posts_comments_path

E assim resolvi o meu problema! Bom, por ter dado tanto trabalho, talvez alguém também precise disso. Fica ai a dica

0

Dica JMX

-

A Cada dia que passa eu me surpreendo com uma nova “ferramenta” ou utilidade do JMX-Console do JBoss. Desta vez eu estava com um problema na minha aplicação em que as conexões com o banco, de repente, ficavam todas ocupadas, e com isso subia uma exceção falando que a aplicação esperou por 30 segundos, e mesmo assim não conseguiu obter nenhuma conexão do pool. Puts! Foi um parto. Revisei todos os meus DAOs para ver se estava fechando corretamente as conexões. Verifiquei os mapeamentos no spring para ver se algum DAO estava como singleton e por conta disso acabar segurando uma conexão (uma vez que havia um objeto connection dentro do meu DAO abstrato) e mesmo assim nada… Não sabia e não tinha ideia de onde estava ficando pendente a conexão. Eis que surgiu uma luz no fim do túnel. Estava olhando o JBoss console e encontrei 2 MBeans/Serviços que me ajudaram muito o ManagedConnectionPool, e o TransactionManager.
Ambos podem ser iniciado a partir do jmx-console da sua aplicação, basta procurar por esses nomes lá. Com eles, consegui descobrir que ao abrir uma conexão com o banco em um SessionBean (que apenas fazia uma consulta), a mesma ficava atrelada à transação, e ao acessar um WebService dentro desta transação com um tempo de resposta demorado, corria o perigo de esgotar as minhas conexões, dado um acesso concorrente. Depois desta constatação, bastou mudar o tipo de transação do session bean para NOT_SUPPORTED que tudo começou a funcionar.

Portanto, ai vai a dica: ManagedConnectionPool, e TransactionManager, podem te ajudar muito a encontrar possíveis problemas de esgotamento do pool de conexões e deadlocks de transações (respectivamente).

0

Rails 2.0 “O que há de novo” – Parte 1

-

Tá, eu sei que cheguei tarde na onda do Rails 2.0, e só vi que mudou muita coisa, quando tentei atualizar um sisteminha antigo que fiz em Rails 1.X para a nova versão e não consegui. Tá certo que usei muita coisa Deprecated, bem como alguns plugins que não evoluíram e tal, mas nem “compilar” o código foi foda… Mas isso me levou a estudar um pouco mais sobre o Rails 2.0 e ver o que tinha mudado. Fiquei impressionado com o tamanho do change log. Por isso surgiu a idéia de criar uma série de artigos explicando o que mudou e o ganho disso.

Para começar, vamos falar de “Sexy Migrations” e outras atualizações no ActiveRecord.
Em poucas palavras, “Sexy Migrations” é apenas um formato mais elegante e enxuto de se declarar os seus arquivos de migrations. Antes, você faria assim:

create_table :people do t
t.column, “account_id”, :integer
t.column, “first_name”, :string, :null => false
t.column, “last_name”, :string, :null => false
t.column, “description”, :text
t.column, “created_at”, :datetime
t.column, “updated_at”, :datetime
end

E agora, pode fazer assim:

create_table :people do t
t.integer :account_id t.string :first_name, :last_name, :null => false
t.text :description
t.timestamps
end

Atente para “t.timestamps”. Ele é um “atalho” para você criar os campos created_at e updated_at. Ficou bem mais enxuto e intuitivo, não ?

Desempenho:
No rails 2.0, o ActiveRecord sofreu algumas alterações para um maior ganho de desempenho. Foi adicionado um simples cache de consultas ao banco. Com isso, consultas (queries) similares serão reconhecidas e retornarão os objetos que estão no cache, ao invés de ir até o banco. Algo que lembra o que o Hibernate faz com grande sucesso. O desempenho dos “fixtures” foi drasticamente melhorando, o que implica em um ganho de 50% ou mais em relação a versão anterior, ao rodar suites de testes que utilizam “fixtures”.

Serialização em JSON:
Exato, agora é possível serializar o seu model para a sintaxe JSON. Mas porque eu iria querer algo assim ? Talvez para trabalhar com Javascript (AJAX) de forma mais prazerosa do que com XML ? Acredito que sim! E veja como é ridiculamente simples:

Person.to_json

E você terá a representação em JSON do seu model.

Bom, por hoje é só. Tentarei, ainda essa semana, escrever um pouco mais sobre as melhorias do Rails 2.0. (Digo tentarei, porque ainda tenho o meu trampo, meus projetos pessoais em rails, e mais meu videogame que ocupam muito do meu tempo, rs…)