Reblog: Apresentando o Java EE

E então, não era só eu que estava lendo o livro do Antonio Goncalves sobre Java EE 6 no final de 2012 (e/ou início de 2013)! O Elias Dorneles também estava lendo e publicou um post interessante sobre o livro.

O único adendo que eu tenho a fazer é que no capítulo 11, quando fala sobre JSP, ele sugere usar <%!%> para declarar variáveis. Na verdade isso vai criar variáveis de instância do servlet e como servlets são singletons, a variável seria compartilhada por todas as requisições. Por isso seria melhor usar <%!%> apenas para métodos e declarar variáveis com <%%> mesmo (o que gerará variáveis locais a um método). Procurei isso na errata do livro e não encontrei, então estou postando aqui.

Operadores para BigDecimal e BigInteger em Java

Operadores para BigDecimal e BigInteger em Java

E de repente percebi que, apesar de não ser possível usar operadores como +, -, *, / com BigDecimal e BigInteger em Java, na linguagem de expressões (EL) do JSP e JSF eles aceitam esses operadores!

E por que em Java “normal” (fora de uma página web) temos que nos contentar com .add(), .subtract() etc.?

Java EE 6 para quem está com pressa

Eu sempre achei legal aprender linguagens de programação, novas maneiras de expressar ideias em código. E linguagens são relativamente fáceis de testar: digitar ou copiar um trecho de código e mandar compilar/rodar. Se tiver um REPL (uma linha de comando interativa), é melhor ainda.

Já coisas mais “enterprise” (cof, cof) eu sempre achei um saco. Java, Java EE e a infinita disponibilidade de frameworks para Java eram os grandes culpados. Às vezes realmente eram tecnologias pouco importantes mesmo, que cairiam no esquecimento afogados na própria complexidade, mas outras vezes surgem coisas bem legais mas que ainda assim não são tão acessíveis: de qualquer jeito, só para começar, a pessoa tem que instalar um ambiente com editor, compilador, interpretador/VM, um servidor web, um banco de dados, ferramenta de construção (Ant ou Maven, se não quiser ficar preso ao Eclipse, NetBeans, JDeveloper, etc.), JARs de algumas bibliotecas e frameworks extras, caso não esteja usando o Maven para baixá-los… Faz lembrar este vídeo: Java vs Ruby On Rails (não que eu conheça Rails, mas a parte Java é bem realista). Nem todas essas coisas são obrigatórias, mas a maior parte acaba sendo.

Mas como eu ia dizendo, às vezes tem coisas legais, depois de transpor a barreira inicial. E o Java EE 6 não é mais aquele inferno de XMLs de configuração que fazem qualquer um esquecer o objetivo do programa/tutorial que está construindo/seguindo enquanto configura coisas irrelevantes. Às vezes era fácil até de esquecer o que realmente é o Java EE: Java EE é o mesmo que EJB? JSP também é Java EE? E no que isso tudo me ajuda?

Então, para dar uma visão geral e ter condições de posteriormente ler algo mais aprofundado sem se perder, aqui vai um resumão:

Servlet: classe que responde a requisições HTTP. Declarada com @WebServlet ou no web.xml. Servlets são instanciados uma vez e acessados simultaneamente por todas as requisições (cuidado com variáveis de instância, elas serão compartilhadas por todos os clientes!). A partir de um servlet você pode despachar a requisição para um JSP (que também é um servlet) ou gerar dinamicamente toda resposta, seja HTML ou outra coisa (por exemplo, até mesmo gerando uma imagem para um captcha).

Filter: classe que é executada “ao redor” de uma requisição HTTP (ao redor de um servlet). Declarado com @WebFilter ou no web.xml.

web.xml: arquivo de configuração que fica dentro da pasta WEB-INF, que fica dentro de um arquivo war. Nele você configura servlets, filters e qualquer coisa em geral que construa sobre essa fundação. Tornou-se opcional por causa das novas anotações @WebServlet e @WebFilter, mas ainda tem bastante utilidade (por exemplo, escolher a ordem dos filters)

Os três itens acima são a base (mas não tudo) da parte web do Java EE. Se você já ouviu falar dos frameworks para construir sistemas web em Java, é [quase] certo que esses frameworks são ou contêm alguns servlets e/ou filters que dão um jeitão novo para o desenvolvimento. Esse “jeitão” que eu digo pode ser a troca dos JSPs por outra linguagem de marcação, ou um arquivo de configurações diferente, ou funcionalidades extras pré-empacotadas, etc.

JSP: página HTML com umas tags especiais para integração com o Java. No fim é compilado para um servlet por baixo dos panos. Então, cuidado ao usar variáveis declaradas entre <%! … %>, porque serão compartilhadas por todos os clientes — variáveis entre <% … %> e guardadas nos escopos “page” e “request” não têm esse problema. Algumas das tags especiais são as tags do JSTL. Possui também uma minilinguagem chamada EL (Expression Language) para fazer coisas como ${objeto.propriedade} no meio de uma página ou atributo de tag.

JSF: uma tentativa de fazer que sites se comportem como programas desktop, usando componentes e tentando de certa forma abstrair a existência das requisições HTTP. Não gosto muito, porque complica coisas simples (e complica coisas complicadas também — o ciclo de vida de uma requisição é um saco de entender). As páginas podem ser escritas em JSP ou Facelets (um Facelet é basicamente um XHTML com algumas coisas a mais) e costumam usar a EL na forma #{objeto.propriedade}.

JAX-RS: uma maneira diferente de atender requisições HTTP com algumas facilidades para fazer web services do tipo RESTful (REST significa simplesmente “HTTP do jeito que seu criador tinha realmente imaginado”), retornando JSON, XML ou outros formatos. Declarado com @Path na classe ou método. A configuração global do JAX-RS fica numa classe que herda de Application e é anotada com @ApplicationPath. A URL gerada será a concatenação do @ApplicationPath + @Path da classe + @Path do método (se houver).

JAX-WS: outro jeito de fazer web services, só que com mais XML (formato SOAP). Usa a anotação @WebService, entre outras.

CDI: você declara uma classe com @RequestScoped, ou @SessionScoped, ou @ApplicationScoped, ou o default @Dependent e em [quase] qualquer outro lugar do programa você declara um objeto dessa classe com @Inject em cima. E magicamente você obtém uma instância no escopo correto sem se preocupar como nem quando esse objeto foi criado (na verdade você obtém um objeto proxy que acessa o objeto verdadeiro no escopo correto). O objeto que recebe outros objetos por injeção deve ser instanciado pelo contêinter (servlet, EJB, managed bean do JSF, outro bean CDI, etc.), ou seja, o @Inject não funciona para objetos instanciados com new (a construção de objetos normais do Java não muda). Possui também outros recursos como eventos e interceptors. É necessário ter um arquivo beans.xml (mesmo vazio) no WEB-INF ou META-INF do seu pacote (war, jar) para usar os recursos do CDI no Java EE 6.

EJB: classe anotada com @Stateless, @Stateful ou @Singleton que é capaz de iniciar e terminar (com commit ou rollback) transações automaticamente entre outros recursos. As transações incluem bancos de dados (com JDBC ou JPA), serviço de envio mensagens (JMS) e timers. EJBs eram famosos por serem complicados antigamente, mas agora estão bem fáceis de usar, basta a anotação, e têm uns recursos novos como chamadas assíncronas. Assim como objetos do CDI, podem ter interceptors. Ao contrário de servlets, EJBs @Stateless não são acessados simultaneamente, o servidor contêiner faz um pool deles para atender as chamadas e por isso o código não precisa se preocupar com reentrância. Já os EJBs @Singleton, naturalmente, só são instanciados uma vez (por nodo num cluster), e têm suas próprias @anotações para controle concorrência.

JPA: você cria classes com @Entity e usa elas para representar linhas do banco de dados. A manipulação dessas @Entity‘s é feita com um EntityManager que pode ser obtido com @PersistenceContext. Com EJBs, tudo fica integrado e o contexto é automaticamente propagado, de modo que não é necessário ficar passando o EntityManager de um lado para o outro. Um EntityManager foi projetado para ser usado numa só operação (uma só thread, e muitas vezes apenas uma transação, embora também exista a opção EXTENDED para deixá-lo aberto para outra transação, que eu nunca usei). A configuração fica no META-INF/persistence.xml de um jar ou WEB-INF/classes/META-INF/persistence.xml de um war (achou estranho o WEB-INF/classes/META-INF? Eu também achei, mas está lá na especificação).

Interceptor: permite que você execute uma tarefa “ao redor” (@AroundInvoke) de chamadas de métodos (semelhante a um filtro). Essas chamadas têm que ser feitas a objetos obtidos com @Inject (CDI ou EJB), já que é o @Inject que cria o objeto proxy capaz de fazer a “mágica”. Afinal, chamadas de métodos em Java continuam sendo a mesma coisa de sempre.

JMS: permite enviar mensagens assíncronas de um sistema para outro. Não, não são e-mails (tem o JavaMail pra isso). Tem também os EJBs @MessageDriven para ajudar na tarefa.

Arquivo .jar (Java Archive): pacote compactado que contém classes Java. Existe também um tipo especial de jar para EJBs, mas no Java EE 6 os EJBs também podem ficar direto num arquivo war (na pasta WEB-INF/classes ou WEB-INF/lib)

Arquivo .war (Web Archive): pacote que contém JSPs e a pasta WEB-INF, que por sua vez contém o arquivo web.xml e as subpastas classes e lib.

Arquivo .ear (Enterprise Archive): pacote que pode conter pacotes war, jar  e mais algumas configurações.

Fazer deploy: pegar um pacote desses e colocar num servidor para ficar disponível pela web.

Context root: parte do endereço onde ficarão todas as coisas de um arquivo war. Por exemplo em http://example.com/my-web-app/index.jsp o context root é /my-web-app. O context-root pode ser o próprio nome do war ou pode ser configurado no application.xml do ear ou ainda pode ser configurado de uma forma específica ao servidor de aplicação (interface visual de administração, arquivo de configuração proprietário, etc.).

JNDI: um negócio para seu programa pegar coisas globais que o servidor disponibiliza através de caminhos especiais (ex.: java:global/isso/aquilo” ou java:comp/env/isso/aquilo”). Ficou bem menos necessário usar diretamente o JNDI quando surgiram as anotações @Inject e @Resource (ufa, ainda bem).

Coisas legais de aprender

Acabei percebendo que as coisas que eu gosto de aprender e as que eu não gosto freqüentemente (acordo ortográfico, só em 2016, agora!) seguem um padrão:

Coisas legais:

À medida que eu me aprofundo, eu exclamo em pensamento: “É mesmo! Isso segue a lógica do que eu aprendi agora há pouco! Eu poderia até ter deduzido sozinho!”. Teoricamente poderia haver uma certa frustração por não ter deduzido sozinho tal assunto, mas isso é muito menor do que o fascínio de ver que “tudo se encaixa”, que tudo faz sentido quando visto como um todo, e que com umas poucas regras tudo pode ser combinado de diversas maneiras.

Coisas chatas:

À medida que eu me aprofundo, eu resmungo em pensamento: “Tá, mas se X funciona assim, como é Y? Ah, tem uma regra específica pra Y… Então Z seria de tal e tal jeito? Ah não, Z não funciona como X nem Y: tem uma exceção para esse caso, por causa de algo que só será explicado no nível avançado. Por enquanto eu tenho que aceitar que Z é um caso especial…”

Escrevi pensando em geral sobre idiomas e linguagens de programação, mas isso deve se aplicar a outras coisas também.

Curiosidades sobre ASCII

Primeiro, uma saudação Unicode: feliz ano da meia-risca (en dash, –): U+2013!
(ou, se preferirem decimal 2013 = 0x7dd, feliz ano da letra NKo “Fa”!)

Agora, de volta ao ASCII. O ASCII, curiosamente pronunciado como “áski” (contrariando nossa conhecida regra do c antes de i…), é um padrão de codificação de letras e símbolos bastante antigo e usado até hoje, principalmente como base para outras codificações. É interessante que ele não foi criado especialmente para computadores: na verdade ele foi criado numa época em que os telégrafos tinham também bastante importância. A idade e a origem estadunidense são aparentes ao vermos que tem apenas 7 bits (128 valores possíveis), não tem nenhuma letra acentuada, e alguns caracteres de controle que praticamente não se usam mais (pra que serve mesmo o caracter 0x17, “end of transmission block”?). Dada a sua idade, é uma sorte que ele tenha letras minúsculas, porque na época era comum economizar bits usando só letras maiúsculas… E eu aqui reclamando da falta de acentos nele!

Apesar de tudo isso, o ASCII tem uns detalhes de design muito interessantes quando se olha os valores hexadecimais de seus caracteres:

  • Os dígitos de 0 a 9 são codificados com valores de 0x30 a 0x39
  • As letras maiúsculas começam em 0x41 e as minúsculas em 0x61 (se nosso alfabeto tivesse só 15 letras, caberia direitinho até 0x4f e 0x6f, mas como não tem, Z e z acabaram ficando em 0x5a e 0x7a)
  • Olhando a tabela, vemos seqüências de três caracteres como [ \ ] e { | }. Por que não colocar os pares de colchetes e chaves juntos na tabela? Olhe os códigos [ = 0x5b, ] = 0x5d, { = 0x7b, } = 0x7d. Viram? O b abre e o d fecha, como um espelho!
  • Tá certo que o par de parênteses ( e ) é 0x28 e 0x29, e o par 0x6b e 0x6d caiu nas letras k e m, mas mesmo assim é legal ver os pares que fizeram com os colchetes e chaves!

Li em algum lugar que a barra invertida \ foi inventada para poder fazer /\ e \/, que poderiam ser usados como operadores AND e OR da linguagem de programação Algol (se chegou a ser usado assim, não sei). No fim, acabou servindo como um separador de pastas, como caracter de “escape” (que dá ou tira propriedades especiais ao próximo caracter, para quem não está acostumado com o termo) e como um dos primeiros caracteres a cair quando se precisa de alguma letra especial (a posição na tabela já foi usada como Ø, ¥, Ñ, etc., pelo menos até resolverem começar a usar o oitavo bit para caracteres extras). Os colchetes e chaves também foram reaproveitados para esse propósito (ver ISO/IEC 646, o subconjunto invariante do ASCII sobre o qual eram feitas modificações).

A existência no ASCII de acentos sem letra embaixo, como ^, ` dá a entender que em alguns dispositivos ou sistemas da época era possível voltar com backspace e colocar um acento em cima de uma letra (e, de novo, li em algum lugar (que eu não lembro) que era isso mesmo). Pena que agora só sirvam para falar sobre os acentos ou como símbolos de linguagens de programação. Ainda bem que agora com o Unicode, esses desperdícios com caracteres inúteis não são mais problema e temos coisas legais como flechinhas e muitas letras acentuadas ←→×÷ŭŝś. :-)