quarta-feira, 20 de julho de 2016

Databind com Jackson e com Google JSON em Java

Com a febre do "two way databind" do Angularjs o beck-end do Java precisa receber um arquivo ou um objeto JSON e transformar em um objeto Java para a camada de negócio. O objetivo do post é converter um JSON em objeto ou um objeto em JSON fazendo uma leitura ou escrita do arquivo ou do objeto JSON. O nome do processo de conversão de JSON para objeto é na verdade Marshal e o inverso Unmarshal.

Vamos criar no Eclipse um novo Projeto em File>>New>>Other>>Dinamyc Web Project com o nome de JaxonTest.




Next>>Next>> Clica em generate web.xml e fnaliza.




Com o botão direito do mouse sobre o projeto clicar em Configure>>Convert to Maven Project.


Vai ser criado o arquivo pom.xml e vamos adicionar as dependencias dentro da tag <dependecies>.


  1. <dependencies>
  2.   <dependency>
  3.    <groupId>com.fasterxml.jackson.core</groupId>
  4.    <artifactId>jackson-annotations</artifactId>
  5.    <version>2.6.3</version>
  6.   </dependency>
  7.   <dependency>
  8.    <groupId>com.fasterxml.jackson.core</groupId>
  9.    <artifactId>jackson-core</artifactId>
  10.    <version>2.6.3</version>
  11.   </dependency>
  12.   <dependency>
  13.    <groupId>com.fasterxml.jackson.core</groupId>
  14.    <artifactId>jackson-databind</artifactId>
  15.    <version>2.6.3</version>
  16.   </dependency>
  17.   <dependency>
  18.    <groupId>org.codehaus.jackson</groupId>
  19.    <artifactId>jackson-mapper-asl</artifactId>
  20.    <version>1.9.13</version>
  21.   </dependency>
  22.  </dependencies>


Agora basta clicar em Maven>>Update Project e as dependências serão baixadas automaticamente e poderão ser visualizadas dentro de Java Rersources>>Libraries>>Maven Dependencies.





Vamos criar tres pacotes agora model, read e write.





Vamos criar em model o arquivo User.java com três variáveis, getters and setters e contrutores:


  1. package br.marcelo.model;
  2. import java.util.List;
  3.  
  4.  
  5. public class User {
  6.  
  7.  
  8.  private String nome;
  9.  private int age;
  10.  private List<String> messages;
  11.  
  12.  public User() {
  13.   super();
  14.   // TODO Auto-generated constructor stub
  15.  }
  16.  public User(String nome, int age, List<String> messages) {
  17.   super();
  18.   this.nome = nome;
  19.   this.age = age;
  20.   this.messages = messages;
  21.  }
  22.  public String getNome() {
  23.   return nome;
  24.  }
  25.  public void setNome(String nome) {
  26.   this.nome = nome;
  27.  }
  28.  public int getAge() {
  29.   return age;
  30.  }
  31.  public void setAge(int age) {
  32.   this.age = age;
  33.  }
  34.  public List<String> getMessages() {
  35.   return messages;
  36.  }
  37.  public void setMessages(List<String> messages) {
  38.   this.messages = messages;
  39.  }
  40.   
  41. }



Vamos criar o primeiro exemplo em write.



  1. package br.marcelo.write;
  2.  
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7.  
  8. import org.codehaus.jackson.JsonGenerationException;
  9. import org.codehaus.jackson.map.JsonMappingException;
  10. import org.codehaus.jackson.map.ObjectMapper;
  11.  
  12. import br.marcelo.model.User;
  13.  
  14. public class Exemplo1 {
  15.  public static void main(String[] args) {
  16.  
  17.   ObjectMapper mapper = new ObjectMapper();
  18.   String curDir;
  19.   //For testing
  20.   User user = new User();
  21.  
  22.   user.setNome("Marcelo");
  23.   user.setAge(30);
  24.  
  25.   List<String> messages = new ArrayList<>();
  26.   messages.add("mensagem1");
  27.   messages.add("mensagem2");
  28.   user.setMessages(messages);
  29.  
  30.   try {
  31.    //Get current Directory
  32.    curDir = System.getProperty("user.dir");
  33.    //Convert object to JSON string and save into file directly
  34.    mapper.writeValue(new File(curDir+"\\user.json"), user);
  35.    System.out.println("Arquivo localizado em: "+curDir+"\\user.json");
  36.    
  37.    //Convert object to JSON string
  38.    String jsonInString = mapper.writeValueAsString(user);
  39.    System.out.println(jsonInString);
  40.    
  41.    //Convert object to JSON string and pretty print
  42.    jsonInString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
  43.    System.out.println(jsonInString);
  44.    
  45.    
  46.   } catch (JsonGenerationException e) {
  47.    e.printStackTrace();
  48.   } catch (JsonMappingException e) {
  49.    e.printStackTrace();
  50.   } catch (IOException e) {
  51.    e.printStackTrace();
  52.   }
  53.  
  54.  }
  55.  
  56.  
  57. }



Neste exemplo utilizamos ObjectMapper() para a criação do arquivo, o objeto user é criado e enviado para o diretório determinado. Segue a saida do console em JSON:


{"nome":"Marcelo","age":30,"messages":["mensagem1","mensagem2"]}
{
  "nome" : "Marcelo",
  "age" : 30,
  "messages" : [ "mensagem1", "mensagem2" ]
}



Agora vamos ler o arquivo criado utilizando o mesmo formato no Exemplo2.java no pacote read.


  1. package br.marcelo.read;
  2.  
  3. import java.io.File;
  4. import java.io.IOException;
  5.  
  6. import com.fasterxml.jackson.core.JsonGenerationException;
  7. import com.fasterxml.jackson.databind.JsonMappingException;
  8. import com.fasterxml.jackson.databind.ObjectMapper;
  9.  
  10. import br.marcelo.model.User;
  11.  
  12. public class Exemplo2 {
  13.  
  14.  public static void main(String[] args) {
  15.   Exemplo2 obj = new Exemplo2();
  16.   obj.run();
  17.  }
  18.  
  19.  private void run() {
  20.   ObjectMapper mapper = new ObjectMapper();
  21.  
  22.   String curDir;
  23.   try {
  24.    //Get current Directory
  25.    curDir = System.getProperty("user.dir");
  26.    // Convert JSON string from file to Object
  27.    User user = mapper.readValue(new File(curDir+"\\user.json"), User.class);
  28.    System.out.println(user);
  29.  
  30.    //Pretty print
  31.    String prettyStaff1 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
  32.    System.out.println(prettyStaff1);
  33.    
  34.    
  35.   } catch (JsonGenerationException e) {
  36.    e.printStackTrace();
  37.   } catch (JsonMappingException e) {
  38.    e.printStackTrace();
  39.   } catch (IOException e) {
  40.    e.printStackTrace();
  41.   }
  42.  }
  43.  
  44. }

No Exemplo3 vamos receber o objeto em um objeto do tipo Object() que pode ser qualquer tipo de objeto.


  1. package br.marcelo.read;
  2.  
  3. import java.io.File;
  4. import java.io.IOException;
  5.  
  6. import com.fasterxml.jackson.core.JsonGenerationException;
  7. import com.fasterxml.jackson.databind.JsonMappingException;
  8. import com.fasterxml.jackson.databind.ObjectMapper;
  9.  
  10.  
  11.  
  12. public class Exemplo3 {
  13.  
  14.  public static void main(String[] args) {
  15.   Exemplo3 obj = new Exemplo3();
  16.   obj.run();
  17.  }
  18.  
  19.  private void run() {
  20.   ObjectMapper mapper = new ObjectMapper();
  21.  
  22.   String curDir;
  23.   try {
  24.    // Get current Directory
  25.    curDir = System.getProperty("user.dir");
  26.    // Convert JSON string from file to Object
  27.    Object object = mapper.readValue(new File(curDir + "\\user.json"), Object.class);
  28.    System.out.println(object);
  29.    
  30.    //System.out.println(object.getClass().getName());
  31.    
  32.    // Pretty print
  33.    String prettyStaff1 = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
  34.    System.out.println(prettyStaff1);
  35.  
  36.   } catch (JsonGenerationException e) {
  37.    e.printStackTrace();
  38.   } catch (JsonMappingException e) {
  39.    e.printStackTrace();
  40.   } catch (IOException e) {
  41.    e.printStackTrace();
  42.   }
  43.  }
  44.  
  45. }

Para o próximo exemplo vamos adicionar ao arquivo pom.xml uma nova dependência:


  1. <dependency>
  2.    <groupId>com.googlecode.json-simple</groupId>
  3.    <artifactId>json-simple</artifactId>
  4.    <version>1.1.1</version>
  5.   </dependency>


Vamos atualizar novamente o projeto em Maven>>Update Project e a nova dependência poderá ser visualizada nas Libraries.


No Exemplo4.java o objeto é recebido em um objeto do tipo JSONObject.


  1. package br.marcelo.read;
  2.  
  3. import java.io.FileNotFoundException;
  4. import java.io.FileReader;
  5. import java.io.IOException;
  6. import java.util.Iterator;
  7. import java.util.List;
  8.  
  9. import org.json.simple.JSONObject;
  10. import org.json.simple.parser.JSONParser;
  11. import org.json.simple.parser.ParseException;
  12.  
  13. public class Exemplo4 {
  14.  
  15.  public static void main(String[] args) {
  16.   JSONObject jsonObject;
  17.   //Cria o parse de tratamento
  18.   JSONParser parser = new JSONParser();
  19.   //Variaveis que irao armazenar os dados do arquivo JSON
  20.   String nome;
  21.   Long age;
  22.   List<String> messages;
  23.   String curDir;
  24.  
  25.   try {
  26.    // Get current Directory
  27.    curDir = System.getProperty("user.dir");
  28.    //Salva no objeto JSONObject o que o parse tratou do arquivo
  29.    jsonObject = (JSONObject) parser.parse(new FileReader(
  30.      curDir + "\\user.json"));
  31.    
  32.    /*//Salva nas variaveis os dados retirados do arquivo
  33.    name = (String) jsonObject.get("nome");
  34.    age = (Long) jsonObject.get("age");
  35.    messages = (List<String>) jsonObject.get("messages");*/
  36.    
  37.     for (Iterator it = jsonObject.keySet().iterator(); it.hasNext();) {  
  38.               Object key = it.next();  
  39.               Object item = jsonObject.get(key);  
  40.               System.out.println(key+":"+item);
  41.     }      
  42.  
  43.    
  44.  
  45.   }
  46.   //Trata as exceptions que podem ser lançadas no decorrer do processo
  47.   catch (FileNotFoundException e) {
  48.    e.printStackTrace();
  49.   } catch (IOException e) {
  50.    e.printStackTrace();
  51.   } catch (ParseException e) {
  52.    // TODO Auto-generated catch block
  53.    e.printStackTrace();
  54.   }
  55.  }
  56.  
  57. }



Referencias:
http://www.mkyong.com/java/jackson-2-convert-java-object-to-from-json/

http://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/

http://stackoverflow.com/questions/18429468/correct-set-of-dependencies-for-using-jackson-mapper


Java é Java!

 Quando eu era estudante não entendia porque o programador batia no peito e sentia orgulhoso ao dizer que programava em Java. O ego do programador Java sempre me transmitia de uma pessoa algumas vezes não muito agradável e que acha que sabe tudo. Comecei a trajetória com PL/SQL, quando era secundarista, e depois com PHP, no inicio da faculdade. O PL/SQL foi substituido pelo PHP nos aplicativos WEB porque o código do PL/SQL exibia as variáveis na opção de exibir código fonte. Trabalhei com API's que imprimiam no browser via comando "http.print('');" em PL/SQL.

Quando comecei a trabalhar com PHP percebia que o desenvolvimento em PHP era muito mais rápido apesar do Java ser um pouco mais seguro e verboso e por isso mais lento de se desenvolver. Você faz uma linha em PHP para escrever três em Java para executar uma mesma operação e isso me parecia lento.  

Quando comecei a trabalhar com Java falei aos programadores mais antigos que não achava que Java fosse tudo aquilo que se falava. Acabei ouvindo frases como "você não sabe o que está falando" e também ouvi uma que nunca que esqueci: "quando você começar a andar pelas empresas e ver o cenário de caos você vai entender o que é o Java". Bom, o cenário de caos apareceu.

Continuo achando que o PHP é mais rápido para pequenos sites, mas tudo depende também do cenário. Hoje, existe uma euforia criada pelo "two way data bind do Angularjs" que parece ser interessante. Porém o PL/SQL se mostrou extremamente fraco para desenvolvimento em equipe. Existem duas grandes questões para essa fraqueza que seriam as ferramentas utilizadas para SVN e GIT que na grande maioria não possuem uma opção de merge que funcione como a do Eclipse (mesmo as Eclipse based) e a segunda seria o problema da Integração Contínua e quem já programou em Java sabe do que estou falando.

Na pratica arquivos são alterados e jogados diretamente em produção e o GIT acaba não sendo atualizado e isso jamais aconteceria com o Java porque o processo de Integração Continua garante que o arquivo alterado seja atualizado primeiro na base de homologação, depois seja testado e atualizado na base produtiva. No PHP a Integração Continua talvez nem faça sentido já que não é necessário criar um arquivo *.WAR. Mas como compilar o código para criar uma nova base em PL/SQL puro? E como fazer com os dados? Não encontrei nenhuma forma eficiente, mesmo que se fizesse utilizando Shellscript. E se a rede for baseada em Windows então?

A escolha da linguagem também depende do cenário, da necessidade ou possibilidade de investimento, se a aplicação vai ficar restrita em uma rede interna ou se vai ficar em rede aberta, se deve rodar no browser ou no desktop, no computador, no tablet, no celular ou em algum coletor de dados. Para tanto o Java é a única linguagem que oferece suporte para qualquer aplicação seja no Windows, no Linux ou no Mac.

Comparado o Java com o PHP, pode ser que com PHP seja mais rápido fazer uma aplicação pequena, mas se aplicação depender de muitas conexões somente o Java poderá gerenciar um Pool de conexões para um grande volume de usuários. E tem ainda a questão das Threads (processamento concorrente) que só existem em Java. Mesmo a comunicação via Serial/USB possui uma biblioteca rxtx específica em Java, a única linguagem que chega mais perto com exceção de C é o Python, porém o Java depois que fecha uma conexão via rxtx em uma porta bloqueia outras requisições na mesma porta ate o encerramento da mesma e o Python permite que vários aplicativos se comuniquem nesta mesma porta utilizada o que pode gerar um "crush" de informações.

O Ruby on Rails quando foi lançado ganhou mercado por já ser Orientado a Objetos e por ser 20 vezes mais rápido que o Java em alguns testes. Foi quando lançaram a segunda versão do compilador e as aplicações começaram a parar porque o compilador havia sido alterado e alguns comandos não possuíam mais suporte. E quando lançaram a terceira versão do compilador aconteceu novamente.

Voltando ao Java, na verdade a grande pergunta que todo o desenvolvedor Java faz a si mesmo e aos companheiros é: "afinal, se você tivesse que iniciar um projeto Java hoje, que tecnologias você usaria?" e essa é a grande questão.

Há um ano atrás eu provavelmente jamais escolheria o Angularjs, porém o tempo tem se mostrado a favor e muitas empresas estão decidindo utilizar o Angularjs no front-end com o Java no back-end. Foi lançado recentemente a versão 2.0 e parece que ambas as versões podem funcionar simultaneamente e o fato do código ser mantido pela Google traz um pouco de tranquilidade. Já no back-end se desenvolveu uma nova forma de trabalhar e ao invés de se programar com um simples MVC está sendo usado Rest antes da camada de modelo. O próprio Spring pode ser desbravado com ou sem o Hibernate e agora existe a opção do Rest junto a tudo isso. Como o Angularjs trabalha com a opção de envio de um único objeto em JSON para o back-end então existe a necessidade de se transformar o JSON em um objeto para a camada de service e essa opção pode ser dada por algumas bibliotecas como JAXB na camada service ou outra opção JAX-RS na camada de modelo.

O fato é que Java é Java. E a pergunta continua: "afinal, se você tivesse que iniciar um projeto Java hoje, que tecnologias você usaria?"