domingo, 2 de maio de 2010

Java - Manipulação de String

E ai pessoal, passei na SCJP e finalmente consegui tempo para terminar esse post ehehe :D ... Valeu ai a toda ajuda, mas agora voltando aos post queria falar um pouco sobre algo que me chamou muita atenção no estudo de Java - Manipulação de String. Parece simples né? Na verdade não é bem assim, vou justificar.

Todo mundo sabe que em Java você tem dois tipo de variáveis de referência, uma para tipos primitivos: int, float, double, boolean, char, shot e long(não sei se esqueci de algum) e outra que são referências aos objetos, isto é, as classes em si que você utiliza no seu dia a dia.

Essas classes em especial por padrão estendem a classe Object, isso é, todas os objetos no Java são derivados da classe Object (menos a propia Object ... obvio né ehehehe).

Mas tá e porque escrever um post sobre a classe String? Que que ela tem de diferente? Bom é que diferente dos outros objetos a uma String só pode ser criada uma vez, ela nunca poderá ser modificada. Então o que acontece quando um objeto String parece estar se modificando? Vamos ao exemplo:

String ola = "Ola!";

Vejamos, o que temos é uma variável de nome ola que serve se referência para um objeto String com valor "Ola!", até ai tudo bem né? Mas se continuarmos:

String olaAux = ola;
ola = ola.concat(" Como vai?");
if (ola.equals(olaAux))
      System.out.print("Igual");
else
      System.out.print("Diferente");


Uh que código mais tosco deve estar pensando hehehe ... Mas e ai, o que vai aparecer na saída? Resposta: "Diferente". Pode testar se não acreditar.

Intrigado? Bem isso é normal, mas lembre-se que comentei que uma variável String nunca pode ser modificada, então o que aconteceu? Simples, Quando criamos a variável se referência olaAux a atribuímos o valor de ola. Depois quando usamos o método concat adicionamos no final da String o valor " Como vai?", mas como String não pode ser mudada a JVM cria uma nova instância de String somando os dois valores "Ola!" e " Como vai!". Assim a variável ola passa a apontar para uma nova instância se String com valor "Ola! Como vai?", enquanto que olaAux continua apontando para "Ola!".

Vale destacar que a JVM cria uma lista da memória de todas as Strings que são criadas, isso quer dizer que no nosso exemplo foram criadas cinco Strings nessa lista. Cinco? Sim! Cada String criada no texto é adiciona na lista, são elas: "Ola!", " Como vai?", "Ola! Como vai?", "Igual" e "Diferente".

A JVM cria essa lista como uma forma de otimizar a utilização de memória, assim se diversas variáveis de String precisarem utilizar o mesmo conteúdo elas irão apontar para a mesma referência e não ficar criando novas instâncias todas as vezes que precisar.

Bom esse foi só um breve resumo, se quiserem mais detalhes o livro do SCJP tem um capitulo inteiro sobre Strings. Até mais!

segunda-feira, 29 de março de 2010

jQuery - Boas práticas com FreeMarker/Velocity

Primeiramente é bom estar escrevendo novamente hehehe. Faz tempo que queria postar algo mas sempre (por algum inconveniente ou destino) ficava sem tempo. Bom vamos lá ...
Antes de tudo tu já deves ou pelo menos tem uma noção de para que utilizamos ferramentas como Freemarker ou mesmo o Velocity? Não?? ... Eu gosto de falar deles com geradores de código HTML em tempo de execução, isto é, essas ferramentas me possibilitam criar componentes em código HTML a partir de um modelo pré-definido. Conseguiu entender agora? Se a reposta ainda é não fique tranquilo, isso é mais fácil do que parece.
Bom, nada melhor do que um exemplo não é? Então supondo que o modelo gere um código HTML onde eu tenho um Label (contendo a tescrição do item) e um Input (que receberá valores passados pelo usuário), algo mais ou menos assim:

O código Java por sua vez irá passar alguns váriáveis para o modelo. Neste exmplo vou usar o Velocity, segue:

VelocityContext context = new VelocityContext();
context.put("id", "my_velocity_id"); //id padrão
context.put("isEditable", true); //se o Input pode ser editado

context.put("text", "Descrição do Item"); //adicionado a Label
context.put("value", "Valor do Item"); //adicionado ao Input

StringWriter w = new StringWriter();
Velocity.mergeTemplate("myTemplate.vm", "UTF-8", context, w);

E por sua vez temos o código do arquivo myTemplate.vm:
<center>
     <div style="border:1px solid black; padding: 2px 2px 2px 2px">
        <label id="${id}_label_">${text}</label> <input id="${id}_input_" value="${value}" />
     </div>
</center>

Espero que você que estava meio em dúvida se tinha entendido ou não tenha compreendido como isso funciona. Senão não adianta continuar hahaha ... brincadeira.
Exemplinho até agora foi bonito mas não falamos nada de jQuery, bom se você prestou atenção viu que meu código Java está passando um parâmetro que não está sendo utilizado no Velocity. Consegue descobrir? ... hehehe ... se olhar bem verá que tem o parâmtro isEditable não é usado de modo algum no myTemplate.vm. Mas então para que serve? Bom se você lembra o assunto do tópico verá que queremos usar jQuery no nosso Velocity, para isso vamos usar o parâmetro isEditable para gerar um código JavaScript e modificar o nosso Input, tudo isso usando uma linha do jQuery :D ... segue o novo myTemplate.vm:
<center>
     <div style="border:1px solid black; padding: 2px 2px 2px 2px">
        <label id="${id}_label_">${text}</label> <input id="${id}_input_" value="${value}" />
     </div>
</center>
## Se isEditable for false
#if (!${isEditable})
  <script type="text/javascript">
     ## modo normal de utilizar no Velocity -- funciona!
     $("#"+"${id}_input_").attr("readonly","readonly");
  </script>
#end

Repare que em vez de eu usar o seletor do jQuery como uma só string acabei separando em duas: "#" e "${id}_input_". Isso porque se o # ficar ao lado do $ a API não irá gerar corretamente a tag, causando um transtorno e que sem dúvida o fará perder muito tempo.
Note que # e $ são palavras a ferramenta também utiliza internamente. Por isso alguns sites aconselham que em vez de usar: $(seletor), utilizar a forma extença jQuery(seletor).


quarta-feira, 24 de fevereiro de 2010

jQuery - Usando Seletores

Primeiramente você deve se perguntar é qual a vantagem em usar os seletores do jQuery? Alguns vão lhe responder que são mais rápidos, mas na verdade depende do seletor que você usar e também em qual browser está executando a aplicação.

Uma boa leitura para essas dúvidas sobre a performance pode ser vista em: 101 on jQuery Selector Performa. Nela o autor testa os usos de seletores usando id, class e tags-name. Mas pelo que entendi dos resultados ele testou esse seletores com uma versão mais antiga do jQuery. Pelo que se nota nas ultimas atualizações os seletores estão cada vez mais rápidos, como vemos no comparativos das versões 1.3.2, 1.4.1 e 1.4.2:




Mas continuando, a baixo segue a lista de seletores que podemos utilizar:

SeletorExemploDescrição

*$(’*');Este seletor retorna todos os elementos do DOM.
#id$(’#id’);Este seletor retorna todos os elementos que contenham o mesmo do ID passado.
.class$(’.class’)Este seletor retorna todos os elementos que possuam o class name passado.
element$(’element’)Este seletor retorna todos os elementos do mesmo tipo de acordo com o tag name. Ex de tag name: table, ul, li, a etc.
a, b, c. … n$(’th, td, .class, #id’)Este método pode ser usado para selecionar multiplos elementos.
parent child$(’li a’)Seleciona todos os "a" elementos que estão contidos no elemento "li".
a > b$(’table > tr’);Irá selecionar todos "tr" elementos que são filhos de "table".
a + b$(’li + a’);Seleciona todos os "a" elementos que estão imediatamente após os elementos "li".
a ~ b$(’p ~ ul’);Seleciona todos os elementos "ul" que vierem depois de "p".
:first$(’ul li:first’);Retorna o primeiro elemento.
:last$(’ul li:last’);Retorna o último elemento.
:not(a)$(’input:not(:checked)’);Retorna todos os "input" elementos que não estão "checked".
:has(a)$(’div:has(p)’);Retorna todos os "div" elementos que contenham "p".
:odd$(’ul li:odd’);Retorna todos os elementos impares da lista.
:even$(’ul li:even’);Retorna todos os elementos pares da lista.
:eq(n)$(’ul li:eq(n)’);Retorna o "n" elemento.
:gt(n)$(’ul li:gt(n)’);Retorna todos os elementos que estão após "n".
:lt(n)$(’ul li:lt(n)’);Retorna todos os elementos que estão antes de "n"
:header$(’:header’);Retorna todos elementos que são titulos. Ex; h1, h2, etc.
:animated$(’ul:animated’);Retorna todos os "ul" elementos que são com uma animação em processo.
:contains(text)$(’:contains(hello)’);Retorna todos os elementos que contenham o texto "hello".
:empty$(’:empty’);Retorna todos os elementos que não contenham filhos.
:parent$(’li:parent’);Retorna o elemento pai do elemento "li".
:hidden$(’ul:hidden’);Retorna todos os "ul" que estão escondidos (hidden)>
:visible$(’ul:visible’);Retorna todos os "ul" que são visíveis
[attribute]$(’[href]‘);Retorna todos os elementos que contenham o atributo "href".
[attribute=value]$(’[rel=external]‘);Retorna todos os elementos que contenham o atributo "ret" com o valor "external".
['attribute!=value']$(’[rel!=external]‘);Retorna todos os elementos que contenham o atributo "ret" sendo que o valor não pode ser "external".
[attribute^=value]$(’[class^=open]‘);Retorna todos os elementos que contenham o atributo "class" e que valor desse inicie com "open".
[attribute$=value]$(’[id$=-wrapper]‘);Retorna todos os elementos que contenham o atributo "id" e que valor desse termine com "-wrapper".
[attribute*=value]$(’[class*=offer]‘);Retorna todos os elementos que contenham o atributo "class" e que valor desse possua a string "offer".
:input$(’:input’);Retorna somentos os elementos de input, isto é: input, select, textarea e button
:text$(’:text’);Retorna somente os elementos de tipo "text".
:password$(’:password’);Retorna somente os elementos de tipo "password".
:radio$(’:radio’);Retorna somente os elementos de tipo "radio".
:checkbox$(’:checkbox’);Retorna somente os elementos de tipo "checkbox".
:submit$(’:submit’);Retorna somente os elementos de tipo "submit"
:image$(’:image’);Retorna somente os elementos de tipo "image"
:reset$(’:reset’);Retorna somente os elementos de tipo "rest".
:file$(’:file’);Retorna somente os elementos de tipo "file".
:button$(’:button’);Retorna somente os elementos do tipo "button".
:enabled$(’:enabled’);Retorna todos os elementos que estão "enabled".
:selected$(’:selected’);Retorna os elementos que está selected da lista de select.
:disabled$(’:disabled’);Retorna todos os elementos que estão "disabled".
:checked$(’:checked’);Retorna os elementos que estão "checked" (radio ou checkbox).



terça-feira, 23 de fevereiro de 2010

Maven - Estrutura básica de um POM

Dando continuação ao Maven vamos começar a pensar em algo mais, por exemplo, vou mostrar como construí o POM base dos meus projetos, chamado de: Gaia Parent.

Primeiramente num projeto Maven precisa-se de basicamente 3 coisas:
- groupId: indica a qual grupo de projetos este projeto faz parte;
- artifactId: caracteriza o projeto atual;
- version: indica a versão na qual este projeto se encontra.

No Gaia Parent:
- groupId: net.sf.gaia
- artifactId: gaia-parent
- version: 1.0

Logo teriamos basicamente o seguinte XML:
<project>
    <modelVersion>
4.0.0</modelVersion>
    <artifactId>
gaia-parent</artifactId>
    <groupId>
net.sf.gaia</groupId>
    <version>
1.0</version>
   
    <name>
Gaia Parent</name>
    <description>
Parent pom for Gaia Projects</description>
    <packaging>
pom</packaging>
</project>
Esse simples XML já define o projeto do Gaia Parent no Maven, onde não será gerado um jar no final da compilação. Veja que a tag packaging define se o projeto será apenas (como dizer? ...) um projeto de definições (pom). Se eu possuí-se códigos Java e necessitá-se que no final do processo de compilação fosse gerado um jar, teria que alterar a tag para: jar.

Mas se alguém tentar compilar este projeto nesse momento verá que ele não tem nenhuma serventia, pois não nos diz nada!

Bom, como nada? Bem é simples, o projeto Gaia Parent tem como função ser o projeto pai de todos os meus projetos. Como assim? Resposta simples: "Eu quis assim!"

Continuando, como sendo sendo um projeto na qual todos meus outros projetos farão uso eu preciso que ele possua algo que todos possam usar e que não atrapalhe a compilação dos projetos. Por isso estruturei que o Gaia Parent armazena-se principalmente a lista de repositórios de onde todos os projetos possam buscar suas dependências sem nenhum problema.

Não vou postar toda a lista de dependência, até porque ela é bem grandinha. Mas se você fizer questão de ver ou mesmo tiver o interesse de adicionar algumas no seu projeto, sugiro que olhe o POM que está versionado no SVN: download.

E para que não está com tanto saco assim de baixar o POM e olhar detalhadamente fica a versão mais compacta a baixo:
<project>
    <modelVersion>
4.0.0</modelVersion>
    <artifactId>
gaia-parent</artifactId>
    <groupId>
net.sf.gaia</groupId>
    <version>
1.0</version>
   
    <name>
Gaia Parent</name>
    <description>
Parent pom for Gaia Projects</description>
    <packaging>
pom</packaging>
   
    <repositories>
        <repository>
            <id>
ibiblio</id>
            <name>
ibiblio Maven 2 Repository</name>
            <url>
http://mirrors.ibiblio.org/pub/mirrors/maven2</url>
        </repository>
       
        <repository>
            <id>
ibiblio legacy</id>
            <name>
ibiblio Maven 1 Repository</name>
            <url>
http://mirrors.ibiblio.org/pub/mirrors/maven</url>
            <layout>
legacy</layout>
        </repository>
   
        <repository>
            <id>
central</id>
            <name>
Maven2 Central Repository</name>
            <url>
http://repo1.maven.org/maven2</url>
        </repository>
       
        <repository>
            <id>
codehaus-repository</id>
            <name>
codehaus maven2 repository</name>
            <url>
http://repository.codehaus.org</url>
        </repository>
       
        <repository>
            <id>
MMBase</id>
            <name>
MMBase Maven 2 Repository</name>
            <url>
http://www.mmbase.org/maven2</url>
        </repository>
       
        <repository>
            <id>
Geotools</id>
            <name>
Geotools Maven 2 Repository</name>
            <url>
http://maven.geotools.fr/repository</url>
        </repository>

        <repository>
            <id>
CMS</id>
            <name>
CMS Container repository</name>
            <url>
http://www.cmscontainer.org/files/maven/</url>
            <layout>
legacy</layout>
        </repository>
       
       
<!-- Gaia developer repository for any gaia artifacts -->
        <repository>
            <id>
Gaia-repo</id>
            <name>
Gaia Developer Repository</name>
            <url>
https://gaia-framework.svn.sourceforge.net/svnroot/gaia-framework/gaia-repository</url>
            <releases> <checksumPolicy>
ignore</checksumPolicy> </releases>
            <snapshots> <enabled>
false</enabled> </snapshots>
        </repository>
    </repositories>
</project>


sexta-feira, 19 de fevereiro de 2010

Maven - Introdução

Finalmente um assunto que eu gosto :D. O Apache Maven ou simplemente Maven. Que ele faz? Resposta bonita: "gerencia e automatiza projetos Java".Se fizerem uma rápida busca na net vão ver várias comparações entre o Ant e o Maven, mas para não se confundirem pensem no Ant como um script (similar a um .bat ou um .sh). É comum em ambientes de compilação a utilização dessas duas ferramentas. Em se tratando em definir um ambiente de compilação, o Maven ganha na sua facilidade comparado ao Ant.

O Maven tem sua estrutura definida num arquivo XML, conhecido como Project Object Model (POM). Ele descreve todo o processo de construção de um projeto, suas dependências (bibliotecas que o projeto utiliza), componentes e a sua sequência de construção. O Maven contém tarefas pré-definidas que realizam funções bem conhecidas como compilação e geração de jar.

Uma característica chave do Maven é que ele é construído para trabalhar em rede. O controle de dependência do projeto é transparente ao programador, pois quando iniciado a compilação a ferramenta verifica se há necessidade de baixar um novo jar ou atualizar a sua versão (tudo isso está definido no POM), baixando esse jar de um repositório externo (há vários repositórios de jars free) ou mesmo de um repositório corporativo.

Estrutura de pastas padrão que o Maven aceita (todos os novos projetos que utilizam Maven fazem uso dessa estrutura ... mas ela pode também ser configurada).

 pom.xml           -- Arquivo de configuração do projeto
  src/                  -- pasta raiz
    |
    |---main/           -- tronco principal
    |    |
    |    |---java/      -- código fonte Java
    |    |---resources/   --   recursos (arquivos de configuração, imagens, etc)
    |    |               

    |    |---webapp/    -- aplicação web Java
    |                     
    |---test/           --  tronco de testes unitários e de integração
    |    |---java/      -- código fonte dos testes do JUnit
    |    |---resources/ -- recursos dos testes

Exemplo de projetos que utilizam Maven:
  Glassfish: https://glassfish.dev.java.net/
  JBoss: http://www.jboss.org/
  PDFBox: http://pdfbox.apache.org/
  Velocity: http://velocity.apache.org/
  Axis: http://ws.apache.org/axis/
  CXF: http://cxf.apache.org/
  Felix: http://felix.apache.org/

... o Tomcat tem um projeto começado no Maven ... mas ainda não o adota

Java - Pré-Processadores

Bom antes de tudo o que é um pré-processador? Bem, eu vejo ele como um "if else" do compilador, como assim? Tipo se o argumento que eu passar estiver definido na VM então aquele trecho de código é carregado senão carrega outro ou no para ser mais extremo não carrega nada.

Pré-processadores não são usados no J2SE, pelo menos eu nunca vi! Mas no J2ME não é muito difícil de ver implementações de código que não possuam um ou mais instruções de um pré-processador, ainda mais quando a aplicação é feita para rodar em aparelhos diferentes com APIs nada parecidas.

Para declarar o uso de pré-processador basta iniciar a linha com //# e em seguida escrever o argumento. Como um exemplo sempre é bom e facilita as coisas, segue:

//#ifdef XMOBILE
public class MyApp extends MyCanvas {
//#else
public class MyApp extends Canvas {
//#endif

Veja que esse exemplo é uma quebra em quem está acostumado basicamente com o puro Java. Nesse exemplo acima vemos que se XMOBILE não estiver definido a classe MyApp estenderá Canvas ao invés de MyCanvas, isso muda ela completamente, consegue ver?

Veja que se eu quisesse ser mais radial poderia escolher qual os pacotes que eu vou incluir e quais eu não vou:

//#define MIDP2
//#ifdef MIDP2
import javax.microedition.media.*;
import javax.microedition.media.control.*;
import javax.microedition.media.control.ToneControl;
//#endif
//#ifdef NOKIAUI
import com.nokia.mid.sound.*;
import com.nokia.mid.ui.*;
//#endif
//#ifdef MOTOROLA
import com.motorola.multimedia.*;
//#endif
import javax.microedition.lcdui.*;
import java.io.*;

Veja que agora eu primeiramente defino o que vou usar e depois testo. Isso é só para salientar e melhorar o entendimento sobre o funcionamento. Também não deve se limitar em achar que o //#define MIDP2 deve ser inserido sempre antes do teste, isto é, na mesma classe. Não! Ele pode ser definido a qualquer momento da execução. Uma boa prática é inseri-los na classe que é carregada primeiro pelo MIDlet.

quinta-feira, 18 de fevereiro de 2010

Jad - Decompilador Java

Quem nunca ficou curioso quando após compilar uma classe Java, olhar para o .class gerado e se perguntar: "será que tem como voltar?" Bom meus amigos tem!

Um exemplo é o Jad (JAva Decompiler). Eles é um programa que faz o serviço sujo de decompilar um .class para um .jad (que na verdade é o .java "diferente" ehehe).

Você pode simplesmente baixar o Jad e executa-lo pela linha de comando:
      joppi@joppi:~$ jad MyTest.class

Vai ver que no mesmo diretório apareceu um MyTest.jad, se quiser pode renomear para MyTest.java que não vai ter problema. Esse arquivo já é um arquivo Java semelhante ao original. Sim semelhante!

O Jad também conta com uma interface gráfica, o JadClipse. Sim é um plugin do eclipse! Qualquer dúvida clique aqui ou se preferir ir direto pode usar o update do Eclipse: http://jadclipse.sf.net/update ou baixar o jar no site: http://sourceforge.net/projects/jadclipse.