Vou palestrar no FISL este ano :D

fisl-logo.jpeg

Acabei de ver que saiu na terceira lista de palestras aprovadas do FISL a minha palestra: Grails - Agilidade, produtividade e código bonito ao alcance de todos!

Então nos vemos no FISL, espero que os que aparecerem por la assistam a minha palestra, vai estar bem legal :D
Não vai ser só aquele CRUD básico que é apresentado em todos os lugares, estou preparando um esquema bem legal para vocês :D

<updated>
Acabou de ser publicado na grade de horários, a palestra vai ser dia 19 de abril as 16h :D
Espero que pelo menos um ou dois de vocês apareçam por la para que eu não fique sozinho na sala :D
</updated>

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

Pare de perder tempo escrevendo documentação do código que você escreveu (parte 1)

time_graphic.jpg

Não, eu não estou completamente louco, e não acho que documentação para o código escrito seja uma coisa completamente inútil.
Mas eu acredito que documentação desatualizada é pior do que nenhuma documentação …
E não estou incentivando a escrita de código completamente sem documentação …
E por último, só para constar, eu estou falando de documentação da regra de negócio implementada e não o manual do usuário …

Ok, mas como deixar de perder tempo escrevendo a tal da documentação?
A solução que me vem a cabeça é BDD, ou seja, Behavior Driven Development, junto com a tão falada, documentação executável …

Mas isto existe?
Sim existe, e o pessoal doRuby On Rails já esta bastante acostumado com isto, utilizando o RSpec.
Mas este post não é sobre Ruby On Rails e nem sobre RSpec, e sim sobre o Easyb, que é uma biblioteca para escrita de “Documentação Executável” utilizando Groovy, muito fácil de utilizar para testar código Java …

Para começar com a brincadeira, vou ir ao site do projeto e fazer o download do último release (atualmente 0.7)
criar um projeto java novo no eclipse.
criar uma pasta de nome lib e copiar os seguintes jars para a pasta:commons-cli-1.1.jar easyb-0.7.3.jar groovy-all-1.5.0.jar (todos vem no zip do easyb)
criar mais uma source folder de nome behavior
(O meu eclipse esta com o plugin para edição de código groovy instalado)

Crio um build.xml para executar os testes (ainda não existe um plugin para o eclipse, mas sinceramente, não achei necessário)

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
<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="run_tests">
	<path id="all.path">
		<pathelement location="${basedir}/bin" />
		<pathelement location="${basedir}/bin-groovy" />
		<fileset dir="${basedir}/lib" includes="**/*.jar" />
	</path>
	<taskdef name="easyb" classname="org.disco.easyb.ant.BehaviorRunnerTask" classpathref="all.path" />
	<!-- ================================= 
          target: default              
         ================================= -->
	<target name="run_tests" description="--> description">
		<easyb failureProperty="easyb.failed">
			<classpath>
				<path refid="all.path" />
			</classpath>
			<behaviors dir="${basedir}/behavior">
				<include name="**/*Story.groovy" />
				<include name="**/*Specification.groovy" />
			</behaviors>
			<report location="story.txt" format="txtstory" />
			<report location="behavior.txt" format="txtbehavior" />
			<report location="easyb.xml" format="xmleasyb" />
		</easyb>
	</target>
</project>

Este build.xml declara a tag do easyb e executa todos os testes, alem de gerar os relatórios, que vocês vão gostar bastante …
Os tipos de relatórios variam bastante de acordo com a versão do easyb, a equipe de desenvolvimento esta melhorando bastante isto, eu estou utilizando aqui a versão do trunk do subversion, se quiserem baixar a mesma versão que uso aqui, podem baixar via git deste repositório : git clone git://github.com/urubatan/easyb.git
(Eu fiz um fork do projeto para adicioar algumas features, e ja estou enviando os patches para os desenvolvedores)

Agora vamos começar a brincadeira :D
Dentro do diretório behavior vou criar um diretório de nome users e um arquivo de nome PermitirRegistroDeUsuariosStory.groovy dentro deste último.
Ou seja, este arquivo vai conter os testes, e a documentação das regras de negócio sobre a criação de novos usuários no sistema …

Quero ter uma breve descrição da história nos meus relatórios, então adiciono uma tag description no inicio do arquivo (esta tag por enquanto só existe no meu fork).

1
2
3
description """Qualquer novo visitante do site deve poder se registrar no sistema, 
desde que as regras de validação definidas sejam atendidas.
Um usuário registrado podera alterar a sua senha sempre que desejar, mas a senha devera atender aos padrões minimos de segurança"""

As histórias são compostas basicamente de 4 comandos:
scenario - define um cenário da história, ou seja, um bloco contendo os outros 3 comandos
given - define a situação inicial
when - define um gatilho, uma ação do usuário que ira disparar alguma ação do sistema, este comando é opcional
then - define o que o sistema deve fazer, e o que vai ser testado

alem destes existe o “and” que atualmente é um comando que não executa nada, serve apenas para deixar o código mais legivel, mas isto vai mudar na próxima versão, o and vai repetir o comando anterior, semelhante ao que acontece no RSpec.

Conhecendo estes comandos podemos começar a escrever a nossa documentação :D
Vou adicionar alguns cenários a minha história e alguns detalhes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
scenario "Um novo usuário precisa confirmar a senha", {
	given "Um novo usuário", {
	}
	when "O usuário preenche o nome de usuário e a senha, mas sem confirmar a mesma", {
	}
	then "A validação do usuário deve falhar", {
	}
	when "O usuário preenche o nome de usuário e confirma a senha corretamente", {
	}
	then "A validação do usuário deve passar",{
	}
}
scenario "Um nome de usuário deve ser único no sistema", {
	given "Um usuário com o formulário preenchido corretamente", {
	}
	then "O registro deve criar o usuário no sistema", {
	}
	when "O nome de usuário ja existe no sistema", {
	}
	then "O registro do usuário deve falhar",{
	}
}
}

Com isto, podemos ver no diretório do projeto os seguintes arquivos criados:
behavior.txt que até o momento esta em branco

story.txt que contem o seguinte texto:

  Story: permitir registro de usuarios
    Qualquer novo visitante do site deve poder se registrar no sistema,
desde que as regras de validação definidas sejam atendidas.
Um usuário registrado podera alterar a sua senha sempre que desejar, mas a senha devera atender aos padrões minimos de segurança

    scenario Um novo usuário precisa confirmar a senha
      given Um novo usuário
      when O usuário preenche o nome de usuário e a senha, mas sem confirmar a mesma
      then A validação do usuário deve falhar
      when O usuário preenche o nome de usuário e confirma a senha corretamente
      then A validação do usuário deve passar

    scenario Um nome de usuário deve ser único no sistema
      given Um usuário com o formulário preenchido corretamente
      then O registro deve criar o usuário no sistema
      when O nome de usuário ja existe no sistema
      then O registro do usuário deve falhar

e easyb.xml que contem uma versão XML dos dois relatórios combinados …
Se você prestar atenção no story.txt, substituindo as palavras em ingles que fazem parte da DSL do easyb, por palavras em portugues, esta é uma ótima documentação para ser validada com o cliente, e com a garantia de que não vai ficar desatualizada por que este é o código fonte dos testes, por tanto sera alterado sempre que a regra de negócio for alterada …

Como assim?
Vamos seguir trabalhando no sistema, agora que ja temos o “behavior”, ou seja, o comportamento definido, vou adicionar algum código a esta história que devera ser testada sempre junto com o build automatizado do sistema:

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
41
42
43
44
45
package users;
 
description """Qualquer novo visitante do site deve poder se registrar no sistema, 
desde que as regras de validação definidas sejam atendidas.
Um usuário registrado podera alterar a sua senha sempre que desejar, mas a senha devera atender aos padrões minimos de segurança"""
 
scenario "Um novo usuário precisa confirmar a senha", {
	given "Um novo usuário", {
		user = new User()
	}
	when "O usuário preenche o nome de usuário e a senha, mas sem confirmar a mesma", {
		user.setName "validName"
		user.setPassword "aPassword"
	}
	then "A validação do usuário deve falhar", {
		ensureThrows(PasswordValidationException){
			user.validate()
		}
	}
	when "O usuário preenche o nome de usuário e confirma a senha corretamente", {
		user.setName "validName"
		user.setPassword "aPassword"
		user.setPasswordConfirmation "aPassword"
	}
	then "A validação do usuário deve passar",{
		user.validate()
	}
}
scenario "Um nome de usuário deve ser único no sistema", {
	given "Um usuário com o formulário preenchido corretamente", {
		user = new User('userName','password','password')
		userManager = UserManager.getInstance()
	}
	then "O registro deve criar o usuário no sistema", {
		userManager.create(user)
	}
	when "O nome de usuário ja existe no sistema", {
		user = new User('userName','otherPassword','otherPassword')
	}
	then "O registro do usuário deve falhar",{
		ensureThrows(UserAlreadyExistsException){
			userManager.create(user)
		}
	}
}

Pronto, este é todo o código desta história, e foi apenas o que eu escrevi até agora.
Agora preciso criar as classes User, UserManager e implementar os métodos corretamente, para que os testes passem., por que no momento os testes não estão nem rodando, ja que estas classes não existem ainda …

Criada a classe User:

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
41
42
43
44
45
46
package users;
 
public class User {
	private String name;
	private String password;
	private String passwordConfirmation;
 
	public User() {
		super();
	}
 
	public User(String name, String password, String passwordConfirmation) {
		super();
		this.name = name;
		this.password = password;
		this.passwordConfirmation = passwordConfirmation;
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String userName) {
		this.name = userName;
	}
 
	public String getPassword() {
		return password;
	}
 
	public void setPassword(String password) {
		this.password = password;
	}
 
	public String getPasswordConfirmation() {
		return passwordConfirmation;
	}
 
	public void setPasswordConfirmation(String passwordConfirmation) {
		this.passwordConfirmation = passwordConfirmation;
	}
 
	public void validate() {
		throw new RuntimeException();
	}
}

E a classe UserManager:

1
2
3
4
5
6
7
8
9
10
11
package users;
 
public class UserManager {
	private static UserManager instance = new UserManager();
	public static UserManager getInstance(){
		return instance;
	}
	public void create(User user){
		throw new RuntimeException();
	}
}

Os testes agora executam mas falham.

Implementando corretamente o método “validate” da classe User, ja temos 2 testes passando:

1
2
3
4
	public void validate() throws PasswordValidationException {
		if(password==null || passwordConfirmation==null || !password.equals(passwordConfirmation))
			throw new PasswordValidationException();
	}

E agora, finalizando a implementação do método create da classe UserManager.

1
2
3
4
5
6
7
8
	public void create(User user) throws InvalidUserException, PasswordValidationException, UserAlreadyExistsException{
		if(user==null)
			throw new InvalidUserException();
		user.validate();
		if(users.containsKey(user.getName()))
			throw new UserAlreadyExistsException();
		users.put(user.getName(), user);
	}

Todos os testes passam, e o nosso código funciona perfeitamente.

Claro que a DSL do easyb é bem mais completa que isto, é possível testar apenas a especificação de uma classe em vez de uma história completa (eu uso histórias para as regras de negócio importantes para o cliente, e especificações para classes internas do sistema), existem diversos “ensure” para validar o estado desejado, tudo isto vocês podem ver na página do projeto: http://www.easyb.org

E como eu falei antes, este é o código dos testes do sistema, desta forma, quando o usuário solicitar uma alteração, se altera o teste, depois se altera o código.
Quando o seu chefe pedir para você documentar o código escrito até agora, você executa os testes, e copia os txts gerados e envia para ele por e-mail.
Os testes você seria obrigado a escrever de qualquer forma, ja que acredito eu que se você leu até aqui, você acredita que testes de código são importantes.
Como você iria escrever os testes de qualquer forma, agora você precisa fazer uma coisa a menos, que é documentar aquilo que escreveu, por que algum dia você vai querer tirar férias, e outro desenvolvedor vai precisar alterar o código que você escreveu :D

Depois de ler até aqui, o que você acha do easyb?
O que você acha de Behavior Driven Development?
Você concorda comigo, quando digo que o easyb tornou possível BDD em Java? (Sim eu sei que existe o JBehave, mas eu acho o trabalhoso demais, e sei que é possível trabalhar com BDD utilizando qualquer xUnit, mas ai eu perco muito da vantagem da documentação executável)
Você vai pelo menos testar isto no seu próximo projeto?

Eu estou escrevendo alguns pequenos patches e enviando para eles sempre que sinto falta de alguma coisa, e fora isto o projeto vai ter diversas melhorias bastante significativas em pouco tempo!
Parabens aos desenvolvedores, e viva o Groovy, tornando o desenvolvimento Java mais divertido e menos trabalhoso!

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

Javascript não intrusivo com Lowpro e Prototype

Como eu disse que iria fazer, e fui cobrado no último rails podcads brasil, segue um post sobre o lowpro.
Isto não vai ser exatamente um tutorial, apenas uma coleção de dicas sobre esta excelente extensão para o prototype[bb], o Lowpro.
O Lowpro ja foi até transformado em um plugin para o rails, o UJS Rails Plugin, mas sinceramente, eu prefiro adicionar a meia duzia de linhas de javascript no meu application.js mesmo do que usar outro plugin só pra isto :D

Mas seguindo o baile, tudo o que vou escrever neste post, vocês podem usar com ou sem o rails, só sera necessário o prototype e o lowpro, inclusive o lowpro ja tem até uma versão que funciona junto com o jQuery[bb] para os que não gostam do prototype :D

Mas seguindo com o assunto deste post, o que vocês acham de adicionar alguns recursos Javascript e até mesmo AJAX[bb] em uma página pronta sem mexer no HTML gerado? nem para adicionar Javascript nos onclick, onblur, onXXX …
Na verdade, sera necessário adicionar pelo menos 3 linhas:

1
2
3
<script src="prototype.js" type="text/javascript" charset="utf-8"></script>
<script src="lowpro.js" type="text/javascript" charset="utf-8"></script>
<script src="meuarquivodescripts.js" type="text/javascript" charset="utf-8"></script>

A última linha, ou seja o “meuarquivodescripts.js” define o arquivo onde vamos trabalhar :D

Um dos recursos que eu acho mais espetaculares no lowpro, é o suporte a comportamentos …
Como assim?
imagine a seguinte situação:
Tenho uma página pronta, é uma página de listagem, e no final da tabela tem um link para a criação de um novo item, hoje toda a página é atualizada quando clico neste link, mas eu quero que apenas a parte da tablea seja substituida pelo formulário, em vez de recarregar a tela toda …
Bom isto é muito fácil de fazer :D
E não vamos precisar de praticamente nenhum código …
Claro, precisamos de alguma forma de identificar o link de adicionar novo objeto na tabela, então, consideremos que este e todos os links que quisermos que sejam abertos por ajax no lugar da tabela, tenham a classe “my_ajax_link”, e consideremos que a tabela esta dentro de uma DIV com ID ‘minha_tabela’…
Se isto for verdade, podemos fazer o seguinte:

1
Event.addBehavior({ 'a.my_ajax_link' : Remote.Link({update:'minha_tabela'}) });

Com isto, todos os links que tenham a classe “my_ajax_link” quando clicados vão ser executados via ajax, e vão substituir o conteúdo do elemento de id “minha_tabela” …

OK, mas é só isto que eu posso fazer com o tal de lowpro? E estes tais de comportamentos?

Na verdade o negócio é bem mais flexivel que isto :D
Vamos ver mais alguns exemplos …
Se você quiser executar algum código no momento em que a página aparecer para o usuário (não é no onload, o onload só é executado depois de toda a página carregada :D )
Basta fazer algo assim:

1
2
3
Event.onReady(function() {
  $$('h1').first().innerHTML += ' (Version ' + LowPro.Version + ')'; 
});

Isto vai mostrar a versão do Lowpro dentro da primeira tag H1 da página :D
O Event.onReady executa um código qualquer no momento em que o DOM da página estiver carregado, o que é bem antes de carregas as imagens, por exemplo, e o onload só sera executado depois de tudo carregado …

Outro exemplo bem simples:
Eu quero que quando o usuário colocar o mouse sobre um link ele fique verde, quando tirar o mouse ele volte a cor padrão, e quando clicar o link incremente um contador dizendo quantas vezes ele ja foi clicado …

Para isto precisamos criar um comportamento …

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var LinkBehavior = Behavior.create({
  initialize : function() {
    this.count = 0;
  },
  onmouseover : function() {
    this.element.addClassName('goo');
  },
  onmouseout : function() {
    this.element.removeClassName('goo');
  },
  onclick : function() {
    this.element.innerHTML = 'Clicks: ' + ++this.count;
    return false;
   }
});

O que vai fazer os nossos links mudarem de cor é a classe “goo”, por tanto para que as cores mudem como eu disse antes, é preciso criar a classe “goo” em algum arquivo css carregado pela página.

Mas só este código apenas cria uma classe “comportamento” que define que o objeto que tiver este comportamento vai receber a classe “goo” no evento onmouseover, tera esta classe removida no evento onmouseout e vai ter o conteúdo alterado quando clicado.

Para que isto funcione com todos os links da página, precisamos adicionar este comportamento aos links da página …

1
Event.addBehavior({ 'a' : LinkBehavior });

Pronto, agora todos os links vão ter o comportamento especificado pela classe.

Claro que alterar assim todos os links de uma página não é a coisa mais útil do mundo, mas se compararmos este último exemplo com o anterior, podemos ver que o lowpro, utiliza css selectors para identificar onde os behaviors devem ser aplicados …
Como assim?

  • a - todas as tags a
  • a.meulink - todas as tags a que tenham a classe “meulink”
  • a#link - a tag a com ID link
  • #qualquerid - qualquer tag mas que tenha o ID “qualquerid”
  • .qualquerclasse - qualquer tag que tenha a classe “qualquerclasse”

Tudo bem, esta melhorando, mas eu não curti esta idéia de ter que criar uma classe para definir o que eu quero que aconteça quando o usuário clicar em um link, não tem como fazer tudo isto com uma linha de código só?
Na verdade tem :D

1
Event.addBehavior({'a#bung:click' : function () {alert('Você Clicou no link');return false;}})

O que estamos fazendo agora é ligar uma função javascript ao evento onclick da tag a com ID bung.

E como é possível ver (talver não tão fácil por que a letra do código aqui no blog é meio pequena, o parâmetro apra a função addBehavior é um objeto, esta sendo utilizada a sintaxe de objetos JSON para passar os parâmetros, por tanto, isto quer dizer que podemos fazer algo parecido com isto:

1
2
3
4
5
Event.addBehavior({
  'a#bung:click' : function () {alert('Você Clicou no link');return false;},
  'a.ajax_link' : Remote.Link({update:'qualquerid'}),
  '.mudacoreconta': LinkBehavior 
})

Ou seja, passar diversos itens a cada chamada do Event.addBehavior.
Outra coisa interessante, é que novas chamadas, vão empilhar métodos na fila se chamada, ou seja, este código:

1
2
3
Event.addBehavior({'a#bung:click' : function () {alert('Você Clicou no link');return false;}})
Event.addBehavior({'a#bung:click' : function () {alert('Você Clicou no link novamente');return false;}})
Event.addBehavior({'a#bung:click' : function () {alert('Você Clicou no link');return false;}})

Vai mostrar 3 mensagens quando o link for clicado.

Uma outra coisa interessante do lowpro é que ele pode aplicar os comportamentos em objetos que forem carregados por uma chamada ajax também, para isto precisamos de mais uma linha de código (pode ser executada no inicio da aplicação)

1
Event.addBehavior.reassignAfterAjax = true;

Isto configura o lowpro para reaplicar os eventos após cada chamada AJAX.

Claro que podemos misturar isto com outras bibliotecas Javascript, por exemplo no meu pet project de planejamento doméstico, eu tenho o seguinte código no application.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var WindowedForm = Behavior.create({
   onclick : function() {
    if (remote_window){
      remote_window.destroy();
    }
    remote_window = new UI.Window({ theme: 'leopard', width: 600, height: 300, focus : true, minimize : false });
    remote_window.setAjaxContent(this.element.href, {method: 'get'});
    remote_window.center();
    remote_window.activate();
    remote_window.show(true);
    return false;
  } 
});
remote_window = false;
 
Event.addBehavior({ 'a.action_form' : WindowedForm });

Isto faz com que todos os links que tenham a classe action_form sejam abertos em uma janela modal criada pela biblioteca “prototype-ui”.

Ahh, e para finalizar com chave de ouro, uma dica para quem usa rails e will_paginate para a paginação, o código que vou mostrar agora utiliza a lowpro para fazer com que a paginação da will_paginate passe a funcionar via AJAX :D

1
2
3
Event.addBehavior({
  'div.pagination a' : Remote.Link({update:'nomedadiv'})
})

Pronto, só isto, agora é só fazer a action correspondente retornar apenas a tabela e não a página toda quando for uma requisição AJAX, e colocar uma div com ID “nomedadiv” na volta da tabela :D

E por último mas não menos importante, não esqueça de alterar o código no servidor para retornar ou Javascript para ser executado, ou a parte do HTML desejado, mas sem as tags html,head,body, …

O lowpro facilita muito o trabalho no client, mas as respostas as chamadas AJAX continuam necessitando ser implementadas adequadamente.

Bom, espero que este post ajude alguem :D
Quaisquer dúvidas podem perguntar por aqui mesmo :D

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

Tutorial de Grails do RSJUG - Neste sábado

Anuncio :D

Tutorial Desenvolvimento rápido de aplicações com Grails

Durante o tutorial será desenvolvida uma aplicação completa utilizando
o framework Grails[bb], contendo não apenas um CRUD como pode ser
encontrado na internet com facilidade, mas implementando lógica de
negócio no lugar correto, utilizando plugins do grails para facilitar
o trabalho, escrevendo testes para a aplicação, e o melhor de tudo,
qualquer participante com um notebook podera acompanhar o tutorial
passo a passo e aproveitar muito mais a oportunidade de descobrir como
desenvolver uma aplicação pode ser rápido e divertido.

Depois da aplicação básica desenvolvida, serão adicionados recursos
AJAX utilizando apenas Javascript não intrusivo, garantindo assim que
a aplicação tera recursos modernos para os browsers que suportarem
isto, e continuara funcionando para os usuários que não possuem
javascript habilitado, e tudo isto em apenas uma manha!

Data: 23/02/2008
Horário: 8:00
Custo: R$15 público em geral e R$10 associados SUCESU ou SEPRORGS
Local: Auditório do SEPRORGS.
Rua Felipe Camarão 690/404 - Bom Fim - Porto Alegre-RS

Inscrições : www.rsjug.org/eventos

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

Aberto o Call 4 Papers para os 3 que o RSJUG ira realizar no primeiro semestre de 2008!

A todos os que quiserem palestrar em algum dos eventos do RSJUG até a metade deste ano, agora é a hora de levantar a mão :D
os eventos serão:
23/02 pela manhã: Tutorial de aproximadamente 3h
12/04 pela manhã: Tutorial de aproximadamente 3h
31/05 dia todo: Seminário com palestras de 1h cada e 2 tutoriais de aproximadamente 3h cada.

Quem quiser colaborar com a comunidade Java, e de quebra ainda ficar conhecido, segue o e-mail oficial do Call 4 Papers:

Caros usuários de JAVA do Rio Grande do Sul,

É com grande satisfação que viemos por meio deste publicar o
calendário de atividades do RSJUG para o primeiro semestre do ano de
2008:
- 23/02 pela manhã: Tutorial de aproximadamente 3h
- 12/04 pela manhã: Tutorial de aproximadamente 3h
- 31/05 dia todo: Seminário com palestras de 1h cada e 2 tutoriais de
aproximadamente 3h cada.

Realizaremos no período de 17/01 a 18/02 um CALL4Papers. O objetivo é
receber da comunidade Java submissões de palestras, tutoriais e cases
de negócio para serem apresentados em 2008.

Para participar, preencha e envie o formulário abaixo para
call4papers@rsjug.org. Sua proposta será avaliada pela comissão de
conteúdo a qual entrará em contato para requisitar maiores
informações se necessário.

- Formulário -
Nome:
Email:
Telefone:
Currículo resumido:
Tipo da apresentação*:
Título da apresentação:
Descrição do conteúdo:

* Escolha um item na lista:
- Palestra: apresentação de 1h aproximadamente sobre um tema técnico,
realizada de maneira resumida e introdutória.
- Tutorial: apresentação de 3h aproximadamente sobre um tema técnico,
realizada de maneira profunda e ampla.
- Case de Negócio: apresentação de 1h aproximadamente sobre a
implementação a nível comercial da tecnologia proposta no tema.
- Painel: debate aberto aos espectadores sobre o tema proposto. Tem
aproximadamente 2h de duração e é composto por 3 ou mais painelistas.

Desde já o RSJUG agradece a sua participação,
Coordenação RSJUG

Vocês podem enviar quantas propostas de palestra quiserem para o endereço: call4papers@rsjug.org.

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

Dicas para quem ainda não fez a 3a parte da SCEA 5 Beta

Bom, fiz ontem a tarde a 3a e última parte da prova
A única coisa que não gostei é que o resultado só sai dia 15 de fevereiro :(

Mas mesmo assim, esta é a única certificação até agora que parece mostrar alguma coisa, a primeira parte da prova é bem fácil para quem ja trabalha com Arquitetura mesmo …
A segunda parte da prova, que é a criação do projeto de um sistema não é difícil, o problema do beta foi ter apenas 2 semanas para fazer isto, e para mim foram duas semanas bem conturbadas, eu estava de mudança para uma cidade visinha, e mais alguns outros compromissos ja assumidos, no final consegui no máximo 20h para trabalhar em um projeto que estava estimado para algo entre 40 e 60h, espero ter feito bem o suficiente para passar, mas mesmo assim valeu a experiência …

Ja a terceira parte da prova, é basicamente para mostrar que foi você mesmo que fez o projeto …
Por tanto, mesmo que realmente tenha sido você, não faça como eu, de uma lida no que você enviou antes de ir fazer a prova, acho que esta é a melhor dica …

E principalmente, anote o por que você faz cada escolha, isto vai te ajudar na hora da prova …

Bom, agora é só esperar dia 15 de fevereiro :D
Boa sorte para mim e para vocês que estão lendo este post também :D

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

Mais dois cursos abertos da Tech Office

A Tech Office esta com mais dois cursos abertos, um agora em dezembro e um em janeiro.

Spring Framework 2.0 | 4ª. edição

Atendendo a pedidos, a Tech Office It promove no dia 15 de dezembro, em Porto Alegre, a quarta edição do curso express Spring Framework 2.0, voltado a programadores Java. Esta edição, servirá como introdução a uma abordagem mais detalhada de como utilizar este conjunto de componentes para facilitar o desenvolvimento de aplicações JavaEE. Durante o curso, será desenvolvida uma livraria virtual que poderá ser utilizada posteriormente como exemplo ou como base para o desenvolvimento de uma nova aplicação. Com carga horária de 8 horas/aula, o treinamento será 100% prático e ministrado em laboratório pelo consultor Mauro do Valle.

Ruby On Rails | 2ª. Turma

E para entrar o ano de 2008 com todo o gás, a Tech Office It promove de 14 a 18 de janeiro, a segunda turma do curso Ruby on Rails com 20 horas/aula presenciais, voltado a desenvolvedores Ruby que desejam conhecer mais sobre Rails e desenvolvedores de outras linguagens que tenham interesse em ingressar no RoR. O curso objetiva auxiliar o aluno a entender o Ruby on Rails e possibilitar a criação de aplicações o utilizando, além de expor suas vantagens e limitações. Como todos os cursos presenciais da Tech Office It, com alunos desenvolverão exemplos que servirão como base para aplicações futuras.

Para informações e inscrições sobre os cursos, acesse www.techoffice.com.br ou envie um e-mail para cursos@techoffice.com.br, além do telefone 51.3012.8241.

Mas se vocês quiserem se inscrever para o curso de Spring Framework é bom correr, por que o curso vai ser em uma semana :D

Se você gostou deste post, lembre-se de assinar o RSS feed do blog, para ser notificado de novos posts!

Java + Flex = Aplicação bonita e rápida e backend confiável!

Vocês provavelmente ja ouviram falar do Adobe Flex.
O Flex é um SDK para desenvolver aplicações Ricas para Internet, estas aplicações irão rodar no Flash Player que ja esta presente em quase todos os browsers que acessam a internet hoje.
Uma aplicação Flex, gera um arquivo SWF e este arquivo se comunica com um servidor, e este servidor pode ser um Adobe Lifecycle Data Server, mas vocês também podem utilizar Java e Open Source :D

Estes 2/3 exemplos rodam sem nenhum software pago, as únicas coisas necessárias são:
Flex SDK - O Flex SDK é gratuito e a versão 3 vai ser Open Source também.
Um Servlet Container - Eu estou utilizando o Tomcat
– Para o primeiro exemplo é só isto :D
E para os outros dois exemplos, também será necessário baixar os seguintes softwares:
OpenAMF - Uma implementação do protocolo AMF0 (Flex Remoting) em Java
RemoteObjectAMF0 - Uma implementação da tag RemoteObject que suporta a versão 0 do AMF (OpenAMF ainda não suporta a versão 3 e o Flex 2 por padrão utiliza a versão 3)

Então, comecemos criando uma aplicação Web Java na sua IDE favorita, crie um servlet de nome TestServlet, eu vou utilizar JAXB para renderizar XML, mas vocês podem utilizar qualquer outra coisa, se você quiser utilizar JAXB também, o schema que eu utilizei para este exemplo esta abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/example" xmlns:tns="http://www.example.com/example" elementFormDefault="qualified">
    <element name="TestSVo" type="tns:TestList"></element>
        <complexType name="TestSVoType">
    	<attribute name="id" type="int"></attribute>
    	<attribute name="name" type="string"></attribute>
    	<attribute name="other" type="string"></attribute>
    </complexType>
    <complexType name="TestList">
    	<sequence minOccurs="1" maxOccurs="unbounded">
    		<element name="all" type="tns:TestSVoType"></element>
    	</sequence>
    </complexType>
</schema>

Este Schema é para um XML parecido com este:

1
2
3
4
5
<TestSVo>
<all id="0" name="foo" other="bar"/>
<all id="1" name="foo1" other="bar1"/>
...
</TestSVo>

Agora é preciso gerar os stubs para o JaxB ou utilize qualquer outra ferramenta que gere um XML parecido com este.
Generate the stubs for the XML generation using JaxB or use any other tool to generate a XML with this schema.

Como em qualquer outra aplicação Java WEB, eu vou começar poluindo meu código com XML (o web.xml neste caso):

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
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd ">
	<servlet>
		<servlet-name>testServlet</servlet-name>
		<servlet-class>....servlet.TestServlet</servlet-class>
	</servlet>
	<servlet>
		<servlet-name>AdvancedGateway</servlet-name>
		<servlet-class>org.openamf.AdvancedGateway</servlet-class>
		<init-param>
			<description>
				Location of the OpenAMF config file.
			</description>
			<param-name>OPENAMF_CONFIG</param-name>
			<param-value>/WEB-INF/openamf-config.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>AdvancedGateway</servlet-name>
		<url-pattern>/gateway2</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>testServlet</servlet-name>
		<url-pattern>/TestServlet</url-pattern>
	</servlet-mapping>
	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>
	<welcome-file-list>
		<welcome-file>teste.html</welcome-file>
	</welcome-file-list>
</web-app>

Para o primeiro exemplo, apenas o TestServlet é utilizado, para os outros o AdvancedGateway que será utilizado …

Agora vamos começar codificando o Servlet:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
 
/**
 * Servlet implementation class for Servlet: TestServlet
 * 
 */
public class TestServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet
{
	static final long serialVersionUID = 1L;
	private JAXBContext jc;
	private Marshaller marc;
	private Unmarshaller unmarc;
	private ObjectFactory factory;
 
	public TestServlet()
	{
		super();
		factory = new ObjectFactory();
		try {
			jc = JAXBContext.newInstance("....servlet");
			marc = jc.createMarshaller();
			unmarc = jc.createUnmarshaller();
		} catch (JAXBException e) {
			e.printStackTrace();
		}
 
	}
 
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		float v = Float.parseFloat(request.getParameter("v"));
		float v1 = Float.parseFloat(request.getParameter("v1"));
		response.getWriter().print(v * v1);
	}
 
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
		IOException
	{
		System.out.println("List called");
		TestList res = new TestList();
		for(int i=0;i<40;i++){
			res.getAll().add(new TestSVoType(i,"Téste ã " + i));
		}
		JAXBElement<TestList> elem = factory.createTestSVo(res);
		System.out.println(elem.toString());
		try {
			marc.marshal(elem, response.getWriter());
		} catch (JAXBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

O método doGet deste servlet é uma calculadora, ele apenas multiplica dois parâmetros recebidos e imprime o resultado.
Já o doPost imprime um XML como o mostrado anteriormente, o conteúdo é praticamente estático, mas isto é só um exemplo :D

Agora vamos começar a brincar com Flex …
Crie um arquivo de nome xmltest.mxml na pasta raiz da sua aplicação WEB.

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
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	 layout="vertical"	backgroundColor="#F4F4F4">
	 <mx:HTTPService id="calc" method="GET" url="http://localhost:8080/teste/TestServlet" >
	 </mx:HTTPService>
	 <mx:HTTPService id="list" method="POST" url="http://localhost:8080/teste/TestServlet" >
	 </mx:HTTPService>
	<mx:Script>
		<![CDATA[
			import mx.controls.DataGrid;
            import mx.controls.Alert;
        ]]>
	</mx:Script>
	<mx:Panel width="80%" height="531" title="Teste">
		<mx:Label width="100%" color="blue"
			text="Type two numbers and press calculate." />
		<mx:TextInput id="v1" text="3" />
		<mx:TextInput id="v2" text="5" />
		<mx:Label id="lbl"  text="{calc.lastResult}"/>
		<mx:Button label="Calculate" click="calc.send({v:v1.text,v1:v2.text});" />
		<mx:DataGrid dataProvider="{list.lastResult.TestSVo.all}" width="100%" height="195" change="Alert.show(DataGrid(event.currentTarget).selectedItem.other)">
			<mx:columns>
				<mx:DataGridColumn headerText="Id" dataField="id" />
				<mx:DataGridColumn headerText="Nome" dataField="name" />
			</mx:columns>
		</mx:DataGrid>
		<mx:Button label="List" click="list.send({v:v1.text,v1:v2.text})" />
	</mx:Panel>
</mx:Application>

A interface com o código java neste exemplo é feita via HTTP padrão, utilizando as tags mx:HTTPService, a primeira faz um GET para a URL e por tanto chama a nossa calculadora, a segunda faz um post, buscando o XML do exemplo Java …

Quando o primeiro botão (Calculate) é clicado, o primeiro serviço é chamado [calc.send(parameters)] e o texto na primeira label é atualizado de acordo com o binding configurado.
Quando o segundo botão é clicadl (List) o segundo serviço é chamado [list.send(params)] e os dados da grid serão atualizados automaticamente.

É só isto :D
Dica: se você utilizar list.send sem parâmetros, a tag HTTPservice dispara um GET e não um POST, ou pelo menos foi o que aconteceu com o Flex 2, eu não testei com FLex 3 ainda …

Esta abordagem é bastante simples e não necessita de muito código, mas não parece muito com OOP …


E o Flex tem um suporte excelente a Remoting, então, o que vocês acham de criar um POJO em Java e usa-lo como um objeto remoto no código Flex?
Gostou da idéia?

Então vamos escrever a classe TestService com as duas mesmas operações (calc e list)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.ArrayList;
import java.util.List;
 
public class TestService
{
	public float calc(float v, float v1){
		System.out.format("%f X %f\n", v, v1);
		return v * v1;
	}
 
	public List<TestVo> list(){
		System.out.println("List called");
		ArrayList<TestVo> res = new ArrayList<TestVo>();
		for(int i=0;i<40;i++){
			res.add(new TestVo(i,"Testé  ã " + i));
		}
		return res;
	}
}

E agora não sera necessária toda aquela parafernalha XML (bom, pelo menos a parte de código que criamos antes), podemos utilizar um Value Object simples :D

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
public class TestVo
{
	private String name;
	private int id;
	public TestVo(int id, String name)