0
Migrando aplicações do
mundo real para o Java
SE 8
Janario Oliveira | @janarioliver
Michael Nascimento Santos | @mr_ _m
Mi...
Apresentação
● Michael Nascimento Santos
○ 14 anos de experiência com a plataforma Java e programador há 20
anos
○ Committ...
● Janario Oliveira
○ Mais de 4 anos de experiência com a plataforma Java
○ Contribuições ativas em projetos opensource com...
● Michel Graciano
○ Atualmente Arquiteto de Sistemas na Betha Sistemas e com mais de
10 anos de experiência com a platafor...
Agenda
● Introdução rápida
● Migrando aplicações para Java SE 8
○ O que podemos migrar automaticamente
○ Tentando aprofund...
Disclaimer
Nosso código e testes foram realizados com
o b97(30/06/2013) do Lambda
#java8mundoreal
Introdução rápida
Introdução aos principais conceitos e
tecnologias do Java SE 8
JSR 337: Java SE 8
● Datas
○ 2013/09/05 Developer Preview
○ 2014/01/23 Release Candidate
○ 2014/03/18 Final Release
● Prin...
JSR 310: Date and Time
● Spec Leads:
○ Stephen Colebourne - criador do Joda-Time
○ Michael Nascimento Santos
○ Roger Riggs...
JSR 310: Date and Time
● Imutável e thread-safe
● Utilize sempre as classes mais específicas para o problema
● YearMonth -...
JSR 310: Date and Time
● LocalDateTime - Data com hora sem time-zone
LocalDateTime dataTDCMeioDia = LocalDateTime. of(data...
JSR 310: Date and Time
● Outras classes de domínio
○ Year
○ Month - enum
○ DayOfWeek - enum
○ OffsetDate
○ OffsetTime
○ Pe...
JSR 335:
Lambda Expressions
● Permite programação funcional, com maior nível de reutilização de código
e escrita concisa
i...
JSR 335:
Lambda Expressions
● Permite programação funcional, com maior nível de reutilização de código
e escrita concisa
p...
JSR 335:
Lambda Expressions
● Permite programação funcional, com maior nível de reutilização de código
e escrita concisa
p...
Migrando aplicações
para Java SE 8
Migrando aplicações para
Java SE 8
● Foram migradas duas aplicações:
○ Um BI customizado para indústria automobilística co...
O que podemos migrar
automaticamente
● NetBeans 8 Nightly Builds está em desenvolvimento e já oferece algumas
Hints para o...
O que podemos migrar
automaticamente
● NetBeans 8 Nightly Builds está em desenvolvimento e já oferece algumas
Hints para o...
O que podemos migrar
automaticamente
● Benéfica principalmente para projetos Java SE
○ Usam mais Functional Interfaces (in...
Tentando aprofundar o uso
dos novos recursos
● Guava nos ajudou na migração automática, mas agora precisávamos
eliminar pa...
Tentando aprofundar o uso
dos novos recursos
● Como converter o resultado de uma operação funcional para uma List?
List<St...
Tentando aprofundar o uso
dos novos recursos
● Como gerar um Map<Long,Brand>?
//Padrão throwingMerger: java.lang.IllegalSt...
Tentando aprofundar o uso
dos novos recursos
● Mas e quando preciso de uma lista com colisões?
Map<Holding,List<Brand>> br...
Tentando aprofundar o uso
dos novos recursos
● Como agregar elementos de uma coleção retornada pelo objeto do
stream?
List...
Tentando aprofundar o uso
dos novos recursos
● Novos métodos úteis em Map:
//Java 7
Long l = totalByYearMonth.get(yearMont...
Tentando aprofundar o uso
dos novos recursos
● Novos métodos úteis em Map:
//Java 7
Map<Brand,Long> totalByBrand = totalBy...
Date and Time
● Formatador - por ser thread-safe é possível defini-lo em uma variável
estática e utilizar em diversos pont...
Date and Time
● A API prover diversos métodos e formas para que seja efetuado cálculos
com data
YearMonth start = YearMont...
Date and Time
● Métodos para comparações
YearMonth yearMonth = YearMonth.of(year, month);
if (yearMonth.isAfter(YearMonth....
Date and Time (Hibernate)
● Alguns lugares temos a persistência de LocalDate e LocalDateTime, como
persistir com JPA(Hiber...
Date and Time (Hibernate)
● Criar duas classes muito parecidas ou uma classe abstrata que
implementa o comportamento parec...
Date and Time (Hibernate)
● E mais métodos:
...
@Override public default Object deepCopy(Object value) {
return value;
}
@...
● LocalDateTimeType
public class LocalDateTimeType implements ImmutableUserType {
@Override public int[] sqlTypes() {
retu...
● LocalDateTimeType
...
@Override
public void nullSafeSet(PreparedStatement st, Object value,
int index, SessionImplemento...
Dificuldades
Dificuldades
Dificuldades
Dificuldades
● Nossos estressados membros do EG, especialmente nosso amigo Brian,
às vezes dão respostas "delicadas"
○ Por...
Formatação e estilo
● A formatação e estilo do código afeta bastante a legibilidade (mais do que
nunca):
List<String> emai...
Suporte a Stream de Maps
Suporte a Stream de Maps
NÃO TEM!
Suporte a Stream de Maps
● Foi discutido pelo EG, mas descartado por exigir classes específicas e ser
melhor suportado com...
Stream para array
● Como converter?
● Stream.toArray(IntFunction<A[]> generator)
Pessoa[] p = pessoas.stream()
//.filter ....
Stream para array
● Como converter?
● Stream.toArray(IntFunction<A[]> generator)
Pessoa[] p = pessoas.stream()
//.filter ....
Stream para array
● Como converter?
● Stream.toArray(IntFunction<A[]> generator)
Pessoa[] p = pessoas.stream()
//.filter ....
Acessos a recursos Java EE
● Algumas APIs Java EE, direta ou indiretamente, acreditam que podem
controlar a instância "mág...
Problemas - Spring
● Spring(ASM) [SPR-10292]
○ O ASM não conseguia interpretar o bytecode gerado
java.lang.IllegalArgument...
Problemas - Spring
● Spring - JDK (DocumentBuilderFactory(b92))
○ No build 92 do JDK exista uma restrição de segurança que...
Problemas - Spring
● Necessário utilizar o snapshot (enquanto não sair a versão final)
Problemas - JBoss(Jandex)
● Jandex (Java Annotation Indexer) JANDEX-14 - Um indexador de
anotações
○ Não conseguia interpr...
Problemas - JBoss x JDK
● ConcurrentSkipListSet - Ao adicionar os processors em um o mesmo fica
com chamadas infinitas ao ...
Problemas - Lombok
● Lombok
○ Issue #145 ainda em aberto desde 15/02/2013 :-(
○ Processor do Lombok não é compatível com o...
Performance
Compilação
Microbenchmark - Caliper
● For each - AtomicInteger em uma lista
//ForEachClassic
for (Integer integer : list) {
atomicInt...
Microbenchmark - Caliper
For each - AtomicInteger
Microbenchmark - Caliper
For each - Fatorial em todos valores de 0 a 2000
private final IntFunction<Integer> factorial = i...
Microbenchmark - Caliper
For each - Fatorial
Execução
Conclusão
● Migrar aplicações do mundo real para o Java SE 8 hoje é possível - se
você realmente souber Java e se elas tiv...
Obrigado!
Janario Oliveira | @janarioliver
Michael Nascimento Santos | @mr_ _m
Michel Graciano | @mgraciano
Agradecimentos
● Michel Graciano (@mgraciano) - Sem dúvida
uma grande ajuda na coleta e
organização do conteúdo destes sli...
Q&A
Janario Oliveira | @janarioliver
Michael Nascimento Santos | @mr_ _m
Michel Graciano | @mgraciano
Upcoming SlideShare
Loading in...5
×

Migrando aplicações do mundo real para o java se 8

1,288

Published on

Slides tdc2013 - Trilha Java

Published in: Technology
1 Comment
2 Likes
Statistics
Notes
  • Código do Caliper Microbenchmark comparando fors
    https://github.com/Janario/jdk8-tests/blob/master/src/main/java/jdk8/performance/ForEach.java
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
1,288
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
20
Comments
1
Likes
2
Embeds 0
No embeds

No notes for slide

Transcript of "Migrando aplicações do mundo real para o java se 8"

  1. 1. Migrando aplicações do mundo real para o Java SE 8 Janario Oliveira | @janarioliver Michael Nascimento Santos | @mr_ _m Michel Graciano | @mgraciano
  2. 2. Apresentação ● Michael Nascimento Santos ○ 14 anos de experiência com a plataforma Java e programador há 20 anos ○ Committer do OpenJDK ○ Membro da organização do SouJava ○ JavaOne Rock Star Speaker ○ Co-líder da JSR-310 (Date & Time API - java.time) e expert em mais 6 JSRs, inclusive a que definiu o Java SE 6 ○ Líder, arquiteto e desenvolvedor na TecSinapse
  3. 3. ● Janario Oliveira ○ Mais de 4 anos de experiência com a plataforma Java ○ Contribuições ativas em projetos opensource como Hibernate, JBoss AS, NetBeans entre outros ○ Desenvolvedor na TecSinapse Apresentação
  4. 4. ● Michel Graciano ○ Atualmente Arquiteto de Sistemas na Betha Sistemas e com mais de 10 anos de experiência com a plataforma Java ○ Membro ativo de projetos open source como o NetBeans e genesis ○ Já fez apresentações no JavaOne USA e Brasil, bem como em algumas edições do TDC Floripa e JustJava. Apresentação
  5. 5. Agenda ● Introdução rápida ● Migrando aplicações para Java SE 8 ○ O que podemos migrar automaticamente ○ Tentando aprofundar o uso dos novos recursos ● Dificuldades e perdas de performance ● Conclusão ● Q&A
  6. 6. Disclaimer Nosso código e testes foram realizados com o b97(30/06/2013) do Lambda
  7. 7. #java8mundoreal
  8. 8. Introdução rápida Introdução aos principais conceitos e tecnologias do Java SE 8
  9. 9. JSR 337: Java SE 8 ● Datas ○ 2013/09/05 Developer Preview ○ 2014/01/23 Release Candidate ○ 2014/03/18 Final Release ● Principais JSRs ○ 294: Improved Modularity Support in the JavaTM Programming Language (Jigsaw) ○ 308: Annotations on Java Types (não tem API prática ainda) ○ 310: Date and Time API ○ 335: Lambda Expressions for the JavaTM Programming Language
  10. 10. JSR 310: Date and Time ● Spec Leads: ○ Stephen Colebourne - criador do Joda-Time ○ Michael Nascimento Santos ○ Roger Riggs ● Baseado e muito semelhante ao Joda-Time, porém melhor
  11. 11. JSR 310: Date and Time ● Imutável e thread-safe ● Utilize sempre as classes mais específicas para o problema ● YearMonth - Mês e ano YearMonth.of(2013, Month.JULY); ● LocalDate - Data sem hora ou time-zone LocalDate.now(); LocalDate dataTDC = LocalDate.of(2013, Month.JULY, 12); ● LocalTime - Hora sem data ou time-zone LocalTime meiaNoite = LocalTime.MIDNIGHT; LocalTime onzeHoras = LocalTime.of(11, 0); assert meiaNoite.isBefore(onzeHoras);
  12. 12. JSR 310: Date and Time ● LocalDateTime - Data com hora sem time-zone LocalDateTime dataTDCMeioDia = LocalDateTime. of(dataTDC, LocalTime.NOON); LocalDateTime dataTDCOnzeHoras = dataTDC.atTime(11, 0); assert dataTDCMeioDia. minusHours(1).equals(dataTDCOnzeHoras ); ● OffsetDateTime - Data com hora offset e sem time-zone OffsetDateTime. of(dataTDCMeioDia, ZoneOffset. ofHours(-3)); ● ZonedDateTime - Data com hora e time-zone ZonedDateTime. of(dataTDCMeioDia, ZoneId.of( "America/Sao_Paulo" ));
  13. 13. JSR 310: Date and Time ● Outras classes de domínio ○ Year ○ Month - enum ○ DayOfWeek - enum ○ OffsetDate ○ OffsetTime ○ Period ○ Instant ○ Duration ○ Clock ● Nova API de formatação ● Diversos outros conceitos: ○ Temporals ○ Adjusters ○ Queries ○ Units
  14. 14. JSR 335: Lambda Expressions ● Permite programação funcional, com maior nível de reutilização de código e escrita concisa int maiorIdadeDePessoaDoSexoMasculino = -1; for (Pessoa pessoa : pessoas) { if (pessoa.getSexo() == Sexo.MASCULINO) { int idade = pessoa.getIdade(); if (idade > maiorIdadeDePessoaDoSexoMasculino ) { maiorIdadeDePessoaDoSexoMasculino = idade; } } } if (maiorIdadeDePessoaDoSexoMasculino != -1) { trataIdade (maiorIdadeDePessoaDoSexoMasculino ); }
  15. 15. JSR 335: Lambda Expressions ● Permite programação funcional, com maior nível de reutilização de código e escrita concisa pessoas.stream() .filter(pessoa -> pessoa.getSexo() == Sexo.MASCULINO) .mapToInt(Pessoa::getIdade) .max() .ifPresent(PessoaProcessor ::trataIdade);
  16. 16. JSR 335: Lambda Expressions ● Permite programação funcional, com maior nível de reutilização de código e escrita concisa pessoas.parallelStream() .filter(pessoa -> pessoa.getSexo() == Sexo.MASCULINO) .mapToInt(Pessoa::getIdade) .max() .ifPresent(PessoaProcessor ::trataIdade);
  17. 17. Migrando aplicações para Java SE 8
  18. 18. Migrando aplicações para Java SE 8 ● Foram migradas duas aplicações: ○ Um BI customizado para indústria automobilística com diversos gráficos e relatórios ○ Uma aplicação 24x7 que será lançada em breve ● Ambas com grande utilização do Guava, o que facilitou muito a migração para utilização de Lambda Expressions ○ Guava(code.google.com/p/guava-libraries) - Framework utilitário com suporte a programação funcional ● Forte utilização do Joda-Time, em especial o YearMonth por serem gráficos que acumulam dados estatísticos mensais ● Iniciamos há 8 meses e muita coisa vem sendo melhorada neste período
  19. 19. O que podemos migrar automaticamente ● NetBeans 8 Nightly Builds está em desenvolvimento e já oferece algumas Hints para o Java SE 8 (Refactor > Inspect and Transform): ○ Hint: Convert to Lambda
  20. 20. O que podemos migrar automaticamente ● NetBeans 8 Nightly Builds está em desenvolvimento e já oferece algumas Hints para o Java SE 8 (Refactor > Inspect and Transform): ○ Hint: Use Functions Operations
  21. 21. O que podemos migrar automaticamente ● Benéfica principalmente para projetos Java SE ○ Usam mais Functional Interfaces (interfaces de um método abstrato apenas), boas candidatas à migração ○ Runnable, listeners do Swing etc. são exemplos ● Projetos Java EE só se beneficiarão mais se usarem alguma biblioteca funcional ○ Nós usamos :-)
  22. 22. Tentando aprofundar o uso dos novos recursos ● Guava nos ajudou na migração automática, mas agora precisávamos eliminar para testar a API ● As operações funcionais mais comuns do Guava tem equivalente quase direto no Java SE 8: ○ filter -> filter ○ transform -> map ○ limit -> limit ● E o resto?
  23. 23. Tentando aprofundar o uso dos novos recursos ● Como converter o resultado de uma operação funcional para uma List? List<String> names = brands.stream() .map(Brand::getName) .collect(toList()); ● Através de collectors (implementações padrão em Collectors) é que fazemos a maior parte das "terminal operations", i.e., converter de um stream para outra collection ou classe "sintetizadora" do resultado
  24. 24. Tentando aprofundar o uso dos novos recursos ● Como gerar um Map<Long,Brand>? //Padrão throwingMerger: java.lang.IllegalStateException: Duplicate key Map<Long,Brand> brandById = brands.stream() .collect(toMap(Brand::getId, identity())); ● Mas e se houver colisões? ○ Um parâmetro adicional, quando especificado, define a estratégia de "merge": BinaryOperator<T> T apply(T u, T v) (u,v) -> u; //firstWinsMerger () método removido no b97 (u,v) -> v; //lastWinsMerger () método removido no b97
  25. 25. Tentando aprofundar o uso dos novos recursos ● Mas e quando preciso de uma lista com colisões? Map<Holding,List<Brand>> brandByHolding = brands.stream() .collect(groupingBy(Brand::getHolding));
  26. 26. Tentando aprofundar o uso dos novos recursos ● Como agregar elementos de uma coleção retornada pelo objeto do stream? List<Dealer> branches = dealers. stream() .flatMap(dealer -> dealer.getBranches().stream()) .collect(toList());
  27. 27. Tentando aprofundar o uso dos novos recursos ● Novos métodos úteis em Map: //Java 7 Long l = totalByYearMonth.get(yearMonth); long total = l == null ? 0L : l; //Java 8 long total = totalByYearMonth. getOrDefault(yearMonth, 0L);
  28. 28. Tentando aprofundar o uso dos novos recursos ● Novos métodos úteis em Map: //Java 7 Map<Brand,Long> totalByBrand = totalByBrandByYearMonth.get(yearMonth); if (totalByBrand == null) { totalByBrandByYearMonth.put(yearMonth, totalByBrand = new HashMap<>()); } Long t = totalByBrand.get(brand); totalByBrand.put(brand, t == null ? total : t + total); //Java 8 totalByBrandByYearMonth .putIfAbsent(yearMonth, new HashMap<>()) .merge(brand, total, Long::sum);
  29. 29. Date and Time ● Formatador - por ser thread-safe é possível defini-lo em uma variável estática e utilizar em diversos ponto public static final DateTimeFormatter ANO_MES_FORMATTER = DateTimeFormatter. ofPattern("MMM/yyyy", new Locale("pt", "BR"));
  30. 30. Date and Time ● A API prover diversos métodos e formas para que seja efetuado cálculos com data YearMonth start = YearMonth.now(); YearMonth end = YearMonth.now().plusMonths(1); int days = ChronoUnit.DAYS.between(start.atDay(1), end.atEndOfMonth()) .getDays();
  31. 31. Date and Time ● Métodos para comparações YearMonth yearMonth = YearMonth.of(year, month); if (yearMonth.isAfter(YearMonth.now())) { //processa data futura... }
  32. 32. Date and Time (Hibernate) ● Alguns lugares temos a persistência de LocalDate e LocalDateTime, como persistir com JPA(Hibernate)? UserType interface UserType { boolean isMutable();//não /** It is not necessary to copy immutable objects */ Object deepCopy (Object value); /** should perform a deep copy if the type is mutable */ Serializable disassemble (Object value); /** should perform a deep copy if the type is mutable */ Object assemble (Serializable cached, Object owner ); /** For immutable objects it is safe to simply return the first parameter */ Object replace (Object original, Object target, Object owner ); }
  33. 33. Date and Time (Hibernate) ● Criar duas classes muito parecidas ou uma classe abstrata que implementa o comportamento parecido das duas? Nenhuma; default methods public interface ImmutableUserType extends UserType { @Override public default boolean equals(Object x, Object y) { return Objects.equals(x, y); } @Override public default int hashCode(Object x) { return Objects.hashCode(x); } @Override public default boolean isMutable() { return false; } ...
  34. 34. Date and Time (Hibernate) ● E mais métodos: ... @Override public default Object deepCopy(Object value) { return value; } @Override public default Serializable disassemble(Object value) { return (Serializable) value; } @Override public default Object assemble(Serializable cached, Object owner) { return cached; } @Override public default Object replace(Object original, Object target, Object owner) { return original; } }
  35. 35. ● LocalDateTimeType public class LocalDateTimeType implements ImmutableUserType { @Override public int[] sqlTypes() { return new int[] { Types.TIMESTAMP}; } @Override public Class<LocalDateTime> returnedClass () { return LocalDateTime. class;} @Override public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) { Timestamp persistValue = (Timestamp) rs.getObject(names [0]); if (rs.wasNull()) { return null; } return persistValue. toLocalDateTime (); } ... Date and Time (Hibernate)
  36. 36. ● LocalDateTimeType ... @Override public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session ) { if (value == null) { st.setNull(index, sqlTypes ()[0]); } else { Timestamp timestamp = Timestamp .valueOf((LocalDateTime) value); st.setObject(index, timestamp, sqlTypes ()[0]); } } } Date and Time (Hibernate)
  37. 37. Dificuldades
  38. 38. Dificuldades
  39. 39. Dificuldades
  40. 40. Dificuldades ● Nossos estressados membros do EG, especialmente nosso amigo Brian, às vezes dão respostas "delicadas" ○ Porém ele pede desculpas em pvt depois, acreditem ou não :-) ● Nem sempre é muito fácil achar os métodos na API e precisa-se do apoio da lista ○ Pelo menos eles respondem muito rápido! ● Alguns métodos que mostramos que existem na API hoje foram resultados dessas discussões ○ Inclusive o getOrDefault, pro qual o Brian também deu uma resposta delicada de primeira, mas tá aí agora ● A API mudou de forma incompatível diversas vezes durante esse período, fazendo com que às vezes perdêssemos 1 dia inteiro só para deixar tudo recompilando com lambda de novo :-( ○ When you're living on the bleeding edge, you should not be surprised when you do, in fact, bleed
  41. 41. Formatação e estilo ● A formatação e estilo do código afeta bastante a legibilidade (mais do que nunca): List<String> emailsOrdenados = pessoas.stream().filter((Pessoa pessoa) -> pessoa.getDataNascimento ().isBefore(dezAnosAtras)).map((Pessoa pessoa) -> pessoa.getEmail()).sorted((String o1, String o2) -> o1 .compareToIgnoreCase (o2)).collect(Collectors.toList()) ; ● Versus: List<String> emailsOrdenados = pessoas.stream() .filter(pessoa -> pessoa.getDataNascimento ().isBefore (dezAnosAtras)) .map(Pessoa::getEmail) .sorted(String::compareToIgnoreCase ) .collect(toList());
  42. 42. Suporte a Stream de Maps
  43. 43. Suporte a Stream de Maps NÃO TEM!
  44. 44. Suporte a Stream de Maps ● Foi discutido pelo EG, mas descartado por exigir classes específicas e ser melhor suportado com tuplas ● Tínhamos na nossa base vários casos funcionais de Map com Guava e tivemos que converter para entrySet().stream() ● É tão feio que não daria tempo de vocês entenderem na palestra (é sério!) ● Vamos pensar seriamente se vale a pena manter na nossa base de código com Java SE 8
  45. 45. Stream para array ● Como converter? ● Stream.toArray(IntFunction<A[]> generator) Pessoa[] p = pessoas.stream() //.filter .map ... .toArray((value) -> {//IntFunction > R apply(int value) //O que retornar? //new Pessoa[0] como em List.toArray?? //new Pessoa[10] acho que vai ter 10 ??? //new Pessoa[]{}; //java.lang.IndexOutOfBoundsException: does not fit });
  46. 46. Stream para array ● Como converter? ● Stream.toArray(IntFunction<A[]> generator) Pessoa[] p = pessoas.stream() //.filter .map ... .toArray((value) -> { return new Pessoa[value]; });
  47. 47. Stream para array ● Como converter? ● Stream.toArray(IntFunction<A[]> generator) Pessoa[] p = pessoas.stream() //.filter .map ... .toArray(Pessoa[]::new); //modo idiomático
  48. 48. Acessos a recursos Java EE ● Algumas APIs Java EE, direta ou indiretamente, acreditam que podem controlar a instância "mágica" disponível via ThreadLocal (ex: FacesContext.getCurrentInstance()) ● Com Lambda, elas falham miseravelmente com parallelStream() ● Soluções? ○ Não usar parallelStream() :-( ○ Criar na thread principal e sair passando ○ Fazer patch do seu container preferido (se o seu container vem de uma empresa de 3 letrinhas, ele é todo baseado em threads pra isso... boa sorte!) ○ Perturbar o Brian na lista para que haja uma SPI de criação do mecanismo de execução de parallelStream() (Michael já cansou de fazer isso... boa sorte!) ○ Parar de brincar com tecnologias não suportadas oficialmente :-) ● Nós incluímos uma abstração no meio (porque o Janario tá com preguiça : -p)
  49. 49. Problemas - Spring ● Spring(ASM) [SPR-10292] ○ O ASM não conseguia interpretar o bytecode gerado java.lang.IllegalArgumentException at org.springframework.asm.ClassReader.<init>(Unknown Source) ● Reportado pelo Michael em 13/02/2013 ● Solucionado 23/04/2013 ● Será lançado na versão 4.0 utilizamos em nossos testes a versão snapshot. ● Nestes meses continuamos nossa migração validando pelos testes de integração
  50. 50. Problemas - Spring ● Spring - JDK (DocumentBuilderFactory(b92)) ○ No build 92 do JDK exista uma restrição de segurança que não permitia a requisição, durante a validação, de urls de namespace de xmls org.xml.sax.SAXException: schema_reference: Failed to read schema document 'spring-beans-3.1.xsd', because 'http' access is not allowed. ● Soluções: ○ System property -Djavax.xml.accessExternalSchema=all ○ Chamada via api DocumentBuilderFactory.setAttribute("http://javax. xml.XMLConstants/property/accessExternalSchema", "all"); ● Não ocorre mais na última versão testada b97
  51. 51. Problemas - Spring ● Necessário utilizar o snapshot (enquanto não sair a versão final)
  52. 52. Problemas - JBoss(Jandex) ● Jandex (Java Annotation Indexer) JANDEX-14 - Um indexador de anotações ○ Não conseguia interpretar classes com bytecode que continham expressões lambda (invokedynamic constant pool tag 18) java.lang.IllegalStateException: Unknown tag! pos=1 poolCount = 61 at org.jboss.jandex.Indexer.processConstantPool(Indexer.java:603) ● Reportado pelo Janario em 16/05/2013 ● Pull request aceito 22/05/2013 (https://github.com/wildfly/jandex/pull/12) - Janario Oliveira
  53. 53. Problemas - JBoss x JDK ● ConcurrentSkipListSet - Ao adicionar os processors em um o mesmo fica com chamadas infinitas ao compareTo do objeto adicionado. org.jboss.as.server.deployment.RegisteredDeploymentUnitProcessor.compareTo(RegisteredDeploymentUnitProcessor.java:41) org.jboss.as.server.deployment.RegisteredDeploymentUnitProcessor.compareTo(RegisteredDeploymentUnitProcessor.java:28) java.util.concurrent.ConcurrentSkipListMap.findPredecessor(ConcurrentSkipListMap.java:696) java.util.concurrent.ConcurrentSkipListMap.doPut(ConcurrentSkipListMap.java:843) java.util.concurrent.ConcurrentSkipListMap.putIfAbsent(ConcurrentSkipListMap.java:2325) java.util.concurrent.ConcurrentSkipListSet.add(ConcurrentSkipListSet.java:241) org.jboss.as.server.DeployerChainAddHandler.addDeploymentProcessor(DeployerChainAddHandler.java:60) ● Não sabemos se é um bug no JDK ou no JBoss ● Utilizamos a versão customizada neste ponto em específico para evitar este erro.
  54. 54. Problemas - Lombok ● Lombok ○ Issue #145 ainda em aberto desde 15/02/2013 :-( ○ Processor do Lombok não é compatível com o JavaC do Java SE 8 ○ Incompatível com NetBeans 7.4, já que o JavaC do Java SE 8 é utilizado pelo IDE para os parsings internos (Editor por exemplo) ● Reportado 15/02/2013 - Jan Lahoda ● Continua em aberto ● Apesar de não utilizarmos em nossos projetos, nosso amigo Michel Graciano utiliza.
  55. 55. Performance
  56. 56. Compilação
  57. 57. Microbenchmark - Caliper ● For each - AtomicInteger em uma lista //ForEachClassic for (Integer integer : list) { atomicInteger. accumulateAndGet (integer, Integer ::sum); } //ForEachStream list.stream().forEach((integer) -> { ... }); //ForEachArrayList list.forEach((integer) -> {...}); //ForEachParallelStream list.parallelStream ().forEach((integer) -> {...});
  58. 58. Microbenchmark - Caliper For each - AtomicInteger
  59. 59. Microbenchmark - Caliper For each - Fatorial em todos valores de 0 a 2000 private final IntFunction<Integer> factorial = i -> { return i == 0 ? 1 : i * factorial.apply(i - 1); }; //ForEachClassic for (Integer integer : list) { factorial. apply(integer); } //ForEachStream list.stream().forEach((integer) -> { ... }); //ForEachArrayList list.forEach((integer) -> { ... }); //ForEachParallelStream list.parallelStream ().forEach((integer) -> { ... });
  60. 60. Microbenchmark - Caliper For each - Fatorial
  61. 61. Execução
  62. 62. Conclusão ● Migrar aplicações do mundo real para o Java SE 8 hoje é possível - se você realmente souber Java e se elas tiverem testes ● As novas funcionalidades podem realmente tornar seu código bem mais legível ● Ganhos de performance podem ser obtidos - mas sempre meça seu código com ferramentas como Caliper, JMeter e um bom profiler ● Vários métodos e novos idiomas aceleram o desenvolvimento ● O Spring 4.0.0-SNAPSHOT *por enquanto* funciona, ao passo que o JBoss, só com hacks ● Para facilitar a sua migração use Java 7 (pra começo de conversa), adote o Guava e o backport da JSR 310 para Java 7 (https://github. com/ThreeTen/threetenbp) ● Siga as listas e participe ativamente das mesmas ● Se você acha que seria capaz de fazer as coisas descritas nessa palestra - e gostaria de ter tempo pago pela empresa para isso -, mande seu cv para recrutamento@tecsinapse.com.br :-)
  63. 63. Obrigado! Janario Oliveira | @janarioliver Michael Nascimento Santos | @mr_ _m Michel Graciano | @mgraciano
  64. 64. Agradecimentos ● Michel Graciano (@mgraciano) - Sem dúvida uma grande ajuda na coleta e organização do conteúdo destes slides
  65. 65. Q&A Janario Oliveira | @janarioliver Michael Nascimento Santos | @mr_ _m Michel Graciano | @mgraciano
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×