Java Magazine Edição 56
A edição de número 56 da revista Java Magazine conta com um novo artigo meu. É a continuição, embora tardia, do primeiro artigo publicado na edição 44, que falava sobre a criação de workflows em Java com o OSWorkflow.
Neste novo artigo eu me aprofundo mais o assunto, dado detalhes de como integrar o OSWorkflow ao Quartz e a mecanismos de persistência. Interessado no assunto? Então, acesse este link para ver o resumo das matérias desta edição e compra a revista!
Compiz + Kubuntu e Bordas no KDE
Uso continuamente o Compiz Fusion. Gosto de frescuras no Desktop. Seja para trabalho ou lazer, o Compiz Fusion está sempre ativado. No Kubuntu, contudo, reparei umas bordas esquisitas ao redor dos menus, inclusive do K Menu. A screenshot abaixo exemplifica.
A forma mais simples que encontrei para resolver este problema foi desativando as sombras para este tipo de menu. É simples, basta executar o Sistema de Configuração do Compiz (CCSM) e na opção Effects -> Decoração de Janela mudar a opção Shadow Windows para any !dock. Observe a imagem abaixo.
Tags: Linux
Singletons em Javascript
Você já pensou em escrever uma classe considerando o padrão de projeto Singleton? Provavelmente você leu em algum lugar de que é impossível. Bem, não é bem assim. Talvez não haja uma maneira igual à da linguagem Java. Mas, de certa forma, é possível. Em um post anterior, eu comentei sobre uma nova forma de escrever classes em Javascript, e é usando esta forma que dá para escrever um Singleton. Veja este código:
Singleton = function() { // variáveis e método privados. var variavelprivada = 0; function funcaoprivada() { } // variáveis e métodos públicos. return { metodo: function() { alert("singleton"); } }; }();
Há uma pequena modificação com relação ao código do post anterior. Observe na última linha, logo após as chaves, os dois parênteses. O que aconteceu, então? Para entender melhor, é preciso compreender bem a linguagem Javascript. Já discuti em outros posts alguns destes detalhes. Inclusive, destaquei as diversas maneiras que você pode usar para escrever classes. Lembre-se que ao fazer algo do tipo f = function() {}, você já está, de certa forma, definindo uma classe. Você pode fazer, var objeto = new f(); e terá uma instância da classe f.
Com relação ao exemplo que escrevi, em um primeiro momento, você definiu uma classe com métodos privados e públicos. Quando você colocou os dois parênteses no final, você executou a função, fazendo que ela retornasse um Array de métodos (que define sua classe). Porque isto é um Singleton? Você não pode fazer new Singleton, porque, de fato, você não definiu uma classe que poderia ser instanciada. Para chamar os métodos, basta fazer Singleton.metodo(). Neste caso, você tem uma única instância da sua classe, satisfazendo ao que solicita o padrão de projeto.
Tags: Javascript, Programação, webVaio VGN C260E e Kubuntu 7.10
A pouco mais de 1 ano comprei um novo notebook. Mais um Sony Vaio. Desta vez, o modelo VGN C260E. Porque mais um Sony Vaio? Porque é o melhor. Bonito, elegante, alta qualidade, sem comentários. Para acessar a página de suporte da Sony para este modelo, clique aqui. Comprei no MercadoLivre, com o vendedor EletronicaNet. Aliás, foi uma negociação tranqüila, trata-se de uma loja, que vendeu, inclusive, com nota fiscal. Na época, o comprei por 3.999,99 reais. Mas vejo que já é possível comprá-lo, na mão do mesmo vendedor, por até 3.000,00 reais.
Trata-se de um ótimo notebook. Nunca tive problemas. É muito rápido, a tela tem um brilho muito bom, provavelmente devido à tecnologia XBRITE-ECO. As cores são muito vivas, fortes, chama a atenção! O desempenho é de dar inveja a muitos desktops. Os 2GB de memória fazem a diferença, e o processador Intel Core 2 Duo é extremamente silencioso e eficiente. Nunca tive problemas com gargalos, mesmo rodando diversas aplicações Java com o Compiz-Fusion ativado. As especificações fornecidas pela Sony, para esta notebook, são:
- Processador Intel Core 2 Duo T5600 - 1.83GHz.
- Memória Cache L2 2MB Advanced Smart Cache
- Memória Principal - DDR2 2GB PC2-4200
- Disco Rígido - Serial ATA 160GB 5400rpm
- Driver de CDRW/DVDRW
- Expansão para leitura de cardão MMC, SD e outros tantos.
- Áudio - Não especifica exatamente. Só diz “Windows Compatible”.
- Display - 13.3″ resolucão máxima 1280×800. Tecnologia XBRITE- ECO WXGALCD.
- Placa de vídeo - Intel Graphics Media Accelerator 950. 224MB. Chipset Intel 945GM.
- Rede Ethernet.
- Modem Integrated V92/V.90
- Rede Wireless - Intel PRO / Wireless 3945ABG Network Connection
- Acompanhado de um Windows Vista (blergh)
Deixei o Gentoo. Já usei Slackware, que, aliás, foi minha primeira distribuição. Resolvi mudar para avaliar outras distros, ver se acho uma que atenda mais ao meu gosto. Pensei no Fedora. Cheguei a acessar o site deles, mas a única opção para download era uma imagem de DVD. Eu estava com pressa, não podia aguardar mais de 6 horas para iniciar a instalação. Resolvi testar, mais uma vez, o Kubuntu.
Mais uma vez, porque eu já tinha instalado e usado por cerca de 4 meses, até que removi e voltei ao Gentoo. Motivo: o Kubuntu tinha sido o único Linux que desde que comecei a usar esse S.O., há cerca de 10 anos, conseguiu travar uma máquina de forma similar ao Windows. Porque tentar o Kubuntu de novo? Apesar disto, eu tinha gostado. Era fácil de usar, intuitivo, etc. Talvez tivesse sido só a versão de algum pacote que criou todo o problema!
Baixei o Kubuntu 7.10, direto do site http://www.kubuntu.org, através do Mirror da Universidade Federal do Paraná (UFPR). A parte interessante do Kubuntu é sua instalação através de um LiveCD, o que lhe permite acessar a Internet enquanto o programa de instalação faz seu trabalho.
Ao chegar à opção de particionamento de disco, você deve perceber que existe uma partição “oculta”, com formato NTFS. Trata-se da área na qual a Sony armazena o Recovery do Windows Vista. Minha sugestão? Não apague esta partição. Por mais que você abomine o Windows, lembre-se que um dia você pode vir a vender seu notebook e nem todos gostam de usar Linux, logo…
Alguns periféricos e programas funcionaram sem necessidade de intervenção, digamos, manual. São eles:
- Placa Wireless: perfeitamente. Desde o início ela é detectada sem problemas. Mas observe que o Kubuntu usa um driver sem suporte nativo do projeto;
- Placa de Som: perfeitamente. Som em boa altura, sem distorções;
- Placa de vídeo: A instalação coloca o driver intel. Mudei para i840 e ficou melhor, aparentemente;
- Placa Ethernet: aparentemente, sim. Ainda não testei, pois só uso wireless :);
- Conexões USB: perfeitamente. Reconhece sem problemas os pendrives;
- Modem: não testei, ainda.
Vale destacar também que as opções de Suspend e Hibernate funcionaram bem. Para falar a verdade, foi a primeira vez que vi estas funções trabalhando tão bem. Já havia tentado no Slackware e no Gentoo, mas sem sucesso.
Gostou da screenshot acima? Nela você pode ver o AWN Manager, funcionando como um docker similar ao do OS X. A decoração das janelas fica a cargo do Compiz-Fusion com o gerenciador Emerald, usando o tema Mac4Lin. O papel de parede você pode obter no Deviantart, mais especificamente neste link. O tema de ícones é o Buuf.
Quanto aos softwares? Até o momento, o Firefox funciona normalmente com os plugins para Java, MPlayer e Flash. Eclipse funcionando perfeitamente também. Tudo obtido através do Adept Manager de forma bastante simples.
Veja abaixo a saída do comando lspci para esta máquina:
- Host bridge: Intel Corporation Mobile 945GM/PM/GMS, 943/940GML and 945GT Express Memory Controller Hub (rev 03)
- VGA compatible controller: Intel Corporation Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller (rev 03)
- Display controller: Intel Corporation Mobile 945GM/GMS/GME, 943/940GML Express Integrated Graphics Controller (rev 03)
- Audio device: Intel Corporation 82801G (ICH7 Family) High Definition Audio Controller (rev 02)
- PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 1 (rev 02)
- PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 2 (rev 02)
- PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 3 (rev 02)
- PCI bridge: Intel Corporation 82801G (ICH7 Family) PCI Express Port 4 (rev 02)
- USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #1 (rev 02)
- USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #2 (rev 02)
- USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #3 (rev 02)
- USB Controller: Intel Corporation 82801G (ICH7 Family) USB UHCI Controller #4 (rev 02)
- USB Controller: Intel Corporation 82801G (ICH7 Family) USB2 EHCI Controller (rev 02)
- PCI bridge: Intel Corporation 82801 Mobile PCI Bridge (rev e2)
- ISA bridge: Intel Corporation 82801GBM (ICH7-M) LPC Interface Bridge (rev 02)
- IDE interface: Intel Corporation 82801G (ICH7 Family) IDE Controller (rev 02)
- IDE interface: Intel Corporation 82801GBM/GHM (ICH7 Family) SATA IDE Controller (rev 02)
- SMBus: Intel Corporation 82801G (ICH7 Family) SMBus Controller (rev 02)
- Ethernet controller: Marvell Technology Group Ltd. 88E8036 PCI-E Fast Ethernet Controller (rev 16)
- Network controller: Intel Corporation PRO/Wireless 3945ABG Network Connection (rev 02)
- CardBus bridge: Texas Instruments PCIxx12 Cardbus Controller
- FireWire (IEEE 1394): Texas Instruments PCIxx12 OHCI Compliant IEEE 1394 Host Controller
- Mass storage controller: Texas Instruments 5-in-1 Multimedia Card Reader (SD/MMC/MS/MS PRO/xD)
Javascript e Orientação a Objetos
Gosto muito de Javascript. Ponto. Há aqueles que odeiam e dizem ser uma linguagem horrível. Infelizmente, se você é um programador Web, deveria se acostumar com esta linguagem e aprender a usá-la da melhor forma possível. Ah, e documente seu código, assim como você faz em suas classes Java, C#, Python ou Ruby. Em grande parte dos projetos que trabalhei, o código em Javascript era renegado. É como se fosse algo indesejado, mas que era necessário.
Que desprezo, hein?! O coitado faz toda validação da tela para você, inclui comportamentos legais que impressionam o cliente, como um botão que muda de cor, e você ainda chama o coitado de “linguagem horrível”? Reveja seus conceitos.
Mas… meu objetivo agora é compartilhar uma nova forma que encontrei para programar em Javascript. Sempre preferi programar com orientação a objetos. É mais elegante, mais reutilizável, etc e tal. Mas Javascript tem um problema: não dá para ter métodos e atributos privados. Não dava… Eis que existe uma forma elegante de se fazer isto. Em outro post eu relatei diversas formas para se criar uma classe em Javascript. Mas faltou uma! E exatamente a que achei mais elegante. Veja o código abaixo:
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 | MinhaClasse = function(parametroConstrutor) { // Aqui vamos colocar os métodos e atributos privados. var umAtributoPrivado = "Eu Sou um Atributo Privado e Você Não me Pega!!"; // Um método privado. function umMetodoPrivado() { // Daqui você tem acesso à variável passada para o construtor da classe. var mensagem = "Eu Sou um Método Privado!"; mensagem += "E o parâmetro passado para o construtor foi: "; mensagem += parametroConstrutor; alert(mensagem); } // A partir daqui é tudo público! return { umAtributoPublico: "Eu Sou um Atributo Público!!!", umMetodoPublico: function() { var mensagem = "Eu Sou um Método Público!"; mensagem += "E o parâmetro passado para o construtor foi: " mensagem += parametroConstrutor; alert(mensagem); }, chamarOMetodoPrivado: function() { // Daqui você pode chamar os métodos privados! umMetodoPrivado(); } }; } var teste = new MinhaClasse("Será que Vai?"); // COMENTA E DESCOMENTA LINHA A LINHA para ver passo a passo funcionando! teste.umMetodoPrivado(); // Erro!! Diz que não acha a função. //alert(teste.umAtributoPrivado); // Vai apresentar um alert com "undefined". //alert(teste.umAtributoPublico); // FUNCIONOU HEIN!!! //teste.umMetodoPublico(); // FUNCIONOU HEIN!!! //teste.chamarOMetodoPrivado(); // FUNCIONOU HEIN!! |
Viu que bacana? Você tem uma área para declarar métodos e atributos privados, assim como uma área para métodos públicos. E o código também fica bem organizado.
DWR e Hibernate
Ao utilizar estas duas ferramentas, deve-se tomar cuidado com alguns detalhes. No projeto em que trabalho temos um relacionamento entre duas classes, de um para muitos. É o relacionamento citado no post anterior a este, mas vou repetir. Temos a classe Documento que possui uma coleção de Signatarios.
A questão é que a classe Signatario contém um identificador composto, composite-id. Este identificador é representado por outra classe, chamada SignatarioPK. Nesta classe existe um relacionamento com Documento, do tipo Many To One.
1 2 3 4 5 6 7 8 | @Entity @Table(name="SIGNATARIO") public class Signatario { @EmbbededId private SignatarioPK pk; } |
A classe SignatarioPK ficou assim:
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 | @Embeddable public class SignatarioPK implements Serializable { private Usuario usuario; private Documento documento; @ManyToOne(fetch=FetchType.EAGER) @Cascade(value={org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) @JoinColumn(name="IDDOCUMENTO") public Documento getDocumento() { return documento; } public void setDocumento(Documento documento) { this.documento = documento; } @ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name="IDUSUARIO") public Usuario getUsuario() { return usuario; } public void setUsuario(Usuario usuario) { this.usuario = usuario; } } |
Vamos ao problema. Toda nossa aplicação foi feita com DWR, portanto, esta ferramenta cria nossos objetos, de forma automática, a partir das informações do formulário. Cria, inclusive, os relacionamentos. Portanto, ele vai criar uma instância de Documento, depois uma instância de Signatario, uma instância de SignatarioPK, uma instância de Usuario e, aqui está o problema, uma nova instância de Documento para “setar” no relacionamento que existe entre SignatarioPK e Documento.
Quando mandamos salvar este objeto, criado da forma como citei, o registro na tabela fica com o campo referente ao identificador do documento como NULL. O correto seria o DWR ter usado a primeira instância de Documento que foi criada, para ter tipo uma referência circular: um documento que tem Signatários que tem o mesmo documento.
Por exemplo, em código, o que o DWR está fazendo é isto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Documento doc = new Documento(); Signatario signatario = new Signatario(); SignatarioPK pk = new SignatarioPK(); Usuario usuario = new Usuario(); usuario.setId("valor do formulário"); // Criou uma nova instância de Documento. Era pra ter usado a variável doc acima. Documento doc2 = new Documento(); doc2.setId("valor do formulário"); pk.setUsuario(usuario); pk.setDocumento(doc2); signatario.setPk(pk); doc.getSignatarios.add(signatario); |
Mas o correto seria isto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Documento doc = new Documento(); doc.setId("valor do formulário"); Signatario signatario = new Signatario(); SignatarioPK pk = new SignatarioPK(); Usuario usuario = new Usuario(); usuario.setId("valor do formulário"); pk.setUsuario(usuario); pk.setDocumento(doc); signatario.setPk(pk); doc.getSignatarios.add(signatario); |
Entendeu?
Tags: dwr, hibernate, Java
Hibernate e Entidades órfãs
Cometi um pequeno erro ao tentar definir um mapeamento entre duas entidades, o que acabou tornando o atributo DELETE_ORPHAN sem efeito. Trata-se de um mapeamento entre uma entidade denominada Documento e outra Signatario. Um Documento possui uma coleção de Signatários.
A classe Signatario tem como chave primária o identificador do usuário (idusuario) e o identificador do documento (iddocumento). A tabela, no Oracle, possui os campos iddocumento e idusuario, ambos como chave primária. Tenho, então, três classes: Usuario, Documento e Signatario. Para mapear o ID da classe Signatario foi necessário recorrer às composite-id do Hibernate.
1 2 3 4 5 6 7 | @Entity @Table(name="SIGNATARIO") public class Signatario { @EmbbededId private SignatarioPK pk; } |
A classe SignatarioPK ficou assim:
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 | @Embeddable @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class SignatarioPK implements Serializable { private Usuario usuario; private Documento documento; @ManyToOne(fetch=FetchType.EAGER) @Cascade(value={org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) @JoinColumn(name="IDDOCUMENTO") public Documento getDocumento() { return documento; } public void setDocumento(Documento documento) { this.documento = documento; } @ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name="IDUSUARIO") public Usuario getUsuario() { return usuario; } public void setUsuario(Usuario usuario) { this.usuario = usuario; } } |
Quando eu crio um documento, crio também os signatários e coloco na coleção. Configurei o Hibernate para incluir os signatários automaticamente no banco de dados, já fazendo o relacionamento entre as duas tabelas. O problema é que ao remover um objeto da coleção e solicitar ao Hibernate para salvar o objeto Documento, ele define o campo iddocumento, da tabela Signatarios, como NULL.
Na classe Documento, a coleção está mapeada da seguinte forma:
1 2 3 4 5 6 7 | @OneToMany @Cascade(value={org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) @JoinColumn(name = "IDDOCUMENTO") public Collection getSignatarios() { return signatarios; } |
O erro ocorre, pois o mapeamento acima referencia uma JoinColumn específica. Mas o objeto filho (Signatarios) é formado por duas chaves primárias. Portanto, para que o Hibernate remova seus “órfãos”, este mapeamento deve ser assim:
1 2 3 4 5 6 | @OneToMany(mappedBy="pk.documento") @Cascade(value={org.hibernate.annotations.CascadeType.DELETE_ORPHAN, org.hibernate.annotations.CascadeType.ALL}) public Collection getSignatarios() { return signatarios; } |
Feito isto, o mapeamento funciona da forma como eu queria.
Tags: hibernate, Java
Redes de Sensores Sem Fio
Estou a poucos passos da conclusão do curso de Especialização Avançada em Sistemas Distribuídos da Universidade Federal da Bahia. Restam poucos dias até a conclusão e apresentação do trabalho. A algum tempo eu havia criado um blog para discutir o assunto, mas a falta de tempo não me permitiu atualizá-lo constantemente.
Agora estou incluindo, aos poucos, os resultados que obtive durante esta pesquisa. Aos interessados nesta área, sugiro visitar o site http://sensores.wordpress.com/. Qualquer dúvida, sugestões ou críticas, entre em contato.
Tags: redes, sensores
“Getting Things Done” na Prática
Comumente conhecido por GTD, o conjunto de práticas sugeridas por David Allen tem bastantes adeptos. Tive meu primeiro contato com esta sigla no blog Efetividade.net, do Augusto, também mantenedor do BR-Linux. Já faz algum tempo que tento adotar alguma prática que facilite minha vida quando o assunto são “coisas a fazer”. Normalmente penso em muitas coisas, imagino muitos projetos “legais” que posso fazer, como um software que faz isso e aquilo, ou estudar mais isso e aquilo outro.
Nesta época, pensei: “Vou comprar um Palm. Será a solução para os meus problemas!”. Puro engano. O simples fato de possuir uma ferramenta de alta tecnologia não alivia o stress diário de ter que trabalhar com muitas informações. O que aconteceu? Meu Palm Tungsten E ficou cheio de poeira.
Inicialmente depositei toda a culpa pelo fato de o Palm não estar sendo eficiente como ferramenta de organização devido à dificuldade de transporte: vendi o Tungsten E e comprei um Treo 680. Agora sim? Que nada. Agora eu tinha um super telefone cheio de funcionalidades que apenas servia para atender telefonemas.
É fato. Eu estou precisando é de técnicas, ferramentas e muita vontade. O GTD está sendo minha primeira tentativa neste sentido. Comprei o livro. Gostei.
Tags: gtd, organizaçãoJava Magazine
A edição número 44 da Java Magazine veio com um artigo de minha autoria. Falava sobre a utilização de Workflows em Java. Mais especificamente, sobre a utilização do OSWorkflow. Sugiro que comprem, o artigo tá legal. :). Agora em janeiro, todavia, Leonardo Galvão saiu da revista, deixando de ser o editor-chefe. A função agora é exercida pelo Eduardo Spínola, que reforçou o convite para contribuir com novos artigos.
Aceitei, logicamente. Escrever para a Java Magazine, para mim, é uma grande honra. Gosto muito da revista, e assinei desde o primeiro exemplar. Tenho todas, até hoje. Todas bem conservadas, aliás. Escrevi um novo artigo complementando o anterior. Continuo a explicação de funcionalidades mais avançadas do OSWorkflow, como integração com o Quartz para gerenciamento de tarefas agendadas.
O artigo já foi enviado para revisão, estou apenas aguardando o retorno dos editores com as sugestões de melhoria. Espero que o artigo seja aprovado e publicado. Agora é só aguardar.
Tags: artigos, Java, revistas







