SE 8 Janario Oliveira | @janarioliver Michael Nascimento Santos | @mr_ _m Michel Graciano | @mgraciano Apresentao Michael Nascimento Santos 14 anos de experincia com a plataforma Java e programador h 20 anos Committer do OpenJDK Membro da organizao do SouJava JavaOne Rock Star Speaker Co-lder da JSR-310 (Date & Time API - java.time) e expert em mais 6 JSRs, inclusive a que definiu o Java SE 6 Lder, arquiteto e desenvolvedor na TecSinapse Janario Oliveira Mais de 4 anos de experincia com a plataforma Java Contribuies ativas em projetos opensource como Hibernate, JBoss AS, NetBeans entre outros Desenvolvedor na TecSinapse Apresentao Michel Graciano Atualmente Arquiteto de Sistemas na Betha Sistemas e com mais de 10 anos de experincia com a plataforma Java Membro ativo de projetos open source como o NetBeans e genesis J fez apresentaes no JavaOne USA e Brasil, bem como em algumas edies do TDC Floripa e JustJava. Apresentao Agenda Introduo rpida Migrando aplicaes para Java SE 8 O que podemos migrar automaticamente Tentando aprofundar o uso dos novos recursos Dificuldades e perdas de performance Concluso Q&A Disclaimer Nosso cdigo e testes foram realizados com o b97(30/06/2013) do Lambda #java8mundoreal Introduo rpida Introduo 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 Principais JSRs 294: Improved Modularity Support in the JavaTM Programming Language (Jigsaw) 308: Annotations on Java Types (no tem API prtica ainda) 310: Date and Time API 335: Lambda Expressions for the JavaTM Programming Language 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, porm melhor JSR 310: Date and Time Imutvel e thread-safe Utilize sempre as classes mais especficas para o problema YearMonth - Ms 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); 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" )); JSR 310: Date and Time Outras classes de domnio Year Month - enum DayOfWeek - enum OffsetDate OffsetTime Period Instant Duration Clock Nova API de formatao Diversos outros conceitos: Temporals Adjusters Queries Units JSR 335: Lambda Expressions Permite programao funcional, com maior nvel de reutilizao de cdigo 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 ); } JSR 335: Lambda Expressions Permite programao funcional, com maior nvel de reutilizao de cdigo e escrita concisa pessoas.stream() .filter(pessoa -> pessoa.getSexo() == Sexo.MASCULINO) .mapToInt(Pessoa::getIdade) .max() .ifPresent(PessoaProcessor::trataIdade); JSR 335: Lambda Expressions Permite programao funcional, com maior nvel de reutilizao de cdigo e escrita concisa pessoas.parallelStream() .filter(pessoa -> pessoa.getSexo() == Sexo.MASCULINO) .mapToInt(Pessoa::getIdade) .max() .ifPresent(PessoaProcessor::trataIdade); Migrando aplicaes para Java SE 8 Migrando aplicaes para Java SE 8 Foram migradas duas aplicaes: Um BI customizado para indstria automobilstica com diversos grficos e relatrios Uma aplicao 24x7 que ser lanada em breve Ambas com grande utilizao do Guava, o que facilitou muito a migrao para utilizao de Lambda Expressions Guava(code.google.com/p/guava-libraries) - Framework utilitrio com suporte a programao funcional Forte utilizao do Joda-Time, em especial o YearMonth por serem grficos que acumulam dados estatsticos mensais Iniciamos h 8 meses e muita coisa vem sendo melhorada neste perodo 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 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 O que podemos migrar automaticamente Benfica principalmente para projetos Java SE Usam mais Functional Interfaces (interfaces de um mtodo abstrato apenas), boas candidatas migrao Runnable, listeners do Swing etc. so exemplos Projetos Java EE s se beneficiaro mais se usarem alguma biblioteca funcional Ns usamos :-) Tentando aprofundar o uso dos novos recursos Guava nos ajudou na migrao automtica, mas agora precisvamos eliminar para testar a API As operaes funcionais mais comuns do Guava tem equivalente quase direto no Java SE 8: filter -> filter transform -> map limit -> limit E o resto? Tentando aprofundar o uso dos novos recursos Como converter o resultado de uma operao funcional para uma List? List<String> names = brands.stream() .map(Brand::getName) .collect(toList()); Atravs de collectors (implementaes padro em Collectors) que fazemos a maior parte das "terminal operations", i.e., converter de um stream para outra collection ou classe "sintetizadora" do resultado Tentando aprofundar o uso dos novos recursos Como gerar um Map<Long,Brand>? //Padro throwingMerger: java.lang.IllegalStateException: Duplicate key Map<Long,Brand> brandById = brands.stream() .collect(toMap(Brand::getId, identity())); Mas e se houver colises? Um parmetro adicional, quando especificado, define a estratgia de "merge": BinaryOperator<T> T apply(T u, T v) (u,v) -> u; //firstWinsMerger () mtodo removido no b97 (u,v) -> v; //lastWinsMerger () mtodo removido no b97 Tentando aprofundar o uso dos novos recursos Mas e quando preciso de uma lista com colises? Map<Holding,List<Brand>> brandByHolding = brands.stream() .collect(groupingBy(Brand::getHolding)); Tentando aprofundar o uso dos novos recursos Como agregar elementos de uma coleo retornada pelo objeto do stream? List<Dealer> branches = dealers.stream() .flatMap(dealer -> dealer.getBranches().stream()) .collect(toList()); Tentando aprofundar o uso dos novos recursos Novos mtodos teis em Map: //Java 7 Long l = totalByYearMonth.get(yearMonth); long total = l == null ? 0L : l; //Java 8 long total = totalByYearMonth. getOrDefault(yearMonth, 0L); Tentando aprofundar o uso dos novos recursos Novos mtodos 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); Date and Time Formatador - por ser thread-safe possvel defini-lo em uma varivel esttica e utilizar em diversos ponto public static final DateTimeFormatter ANO_MES_FORMATTER = DateTimeFormatter. ofPattern("MMM/yyyy", new Locale("pt", "BR")); Date and Time A API prover diversos mtodos e formas para que seja efetuado clculos com data YearMonth start = YearMonth.now(); YearMonth end = YearMonth.now().plusMonths(1); int days = ChronoUnit.DAYS.between(start.atDay(1), end.atEndOfMonth()) .getDays(); Date and Time Mtodos para comparaes YearMonth yearMonth = YearMonth.of(year, month); if (yearMonth.isAfter(YearMonth.now())) { //processa data futura... } Date and Time (Hibernate) Alguns lugares temos a persistncia de LocalDate e LocalDateTime, como persistir com JPA(Hibernate)? UserType interface UserType { boolean isMutable();//no /** 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 ); } 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; } ... Date and Time (Hibernate) E mais mtodos: ... @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; } } 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) 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) Dificuldades Dificuldades Dificuldades Dificuldades Nossos estressados membros do EG, especialmente nosso amigo Brian, s vezes do respostas "delicadas" Porm ele pede desculpas em pvt depois, acreditem ou no :-) Nem sempre muito fcil achar os mtodos na API e precisa-se do apoio da lista Pelo menos eles respondem muito rpido! Alguns mtodos que mostramos que existem na API hoje foram resultados dessas discusses Inclusive o getOrDefault, pro qual o Brian tambm deu uma resposta delicada de primeira, mas t a agora A API mudou de forma incompatvel diversas vezes durante esse perodo, fazendo com que s vezes perdssemos 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 Formatao e estilo A formatao e estilo do cdigo 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()); Suporte a Stream de Maps Suporte a Stream de Maps NO TEM! Suporte a Stream de Maps Foi discutido pelo EG, mas descartado por exigir classes especficas e ser melhor suportado com tuplas Tnhamos na nossa base vrios casos funcionais de Map com Guava e tivemos que converter para entrySet().stream() to feio que no daria tempo de vocs entenderem na palestra ( srio!) Vamos pensar seriamente se vale a pena manter na nossa base de cdigo com Java SE 8 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 }); Stream para array Como converter? Stream.toArray(IntFunction<A[]> generator) Pessoa[] p = pessoas.stream() //.filter .map ... .toArray((value) -> { return new Pessoa[value]; }); Stream para array Como converter? Stream.toArray(IntFunction<A[]> generator) Pessoa[] p = pessoas.stream() //.filter .map ... .toArray(Pessoa[]::new); //modo idiomtico Acessos a recursos Java EE Algumas APIs Java EE, direta ou indiretamente, acreditam que podem controlar a instncia "mgica" disponvel via ThreadLocal (ex: FacesContext.getCurrentInstance()) Com Lambda, elas falham miseravelmente com parallelStream() Solues? No 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 criao do mecanismo de execuo de parallelStream() (Michael j cansou de fazer isso... boa sorte!) Parar de brincar com tecnologias no suportadas oficialmente :-) Ns inclumos uma abstrao no meio (porque o Janario t com preguia : -p) Problemas - Spring Spring(ASM) [SPR-10292] O ASM no 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 lanado na verso 4.0 utilizamos em nossos testes a verso snapshot. Nestes meses continuamos nossa migrao validando pelos testes de integrao Problemas - Spring Spring - JDK (DocumentBuilderFactory(b92)) No build 92 do JDK exista uma restrio de segurana que no permitia a requisio, durante a validao, 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. Solues: System property -Djavax.xml.accessExternalSchema=all Chamada via api DocumentBuilderFactory.setAttribute("http://javax. xml.XMLConstants/property/accessExternalSchema", "all"); No ocorre mais na ltima verso testada b97 Problemas - Spring Necessrio utilizar o snapshot (enquanto no sair a verso final) Problemas - JBoss(Jandex) Jandex (Java Annotation Indexer) JANDEX-14 - Um indexador de anotaes No conseguia interpretar classes com bytecode que continham expresses 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 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) No sabemos se um bug no JDK ou no JBoss Utilizamos a verso customizada neste ponto em especfico para evitar este erro. Problemas - Lombok Lombok Issue #145 ainda em aberto desde 15/02/2013 :-( Processor do Lombok no compatvel com o JavaC do Java SE 8 Incompatvel 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 no utilizarmos em nossos projetos, nosso amigo Michel Graciano utiliza. Performance Compilao
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) -> {...}); Microbenchmark - Caliper For each - AtomicInteger 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) -> { ... }); Microbenchmark - Caliper For each - Fatorial Execuo Concluso Migrar aplicaes do mundo real para o Java SE 8 hoje possvel - se voc realmente souber Java e se elas tiverem testes As novas funcionalidades podem realmente tornar seu cdigo bem mais legvel Ganhos de performance podem ser obtidos - mas sempre mea seu cdigo com ferramentas como Caliper, JMeter e um bom profiler Vrios mtodos 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 migrao use Java 7 (pra comeo 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 :-) Obrigado! Janario Oliveira | @janarioliver Michael Nascimento Santos | @mr_ _m Michel Graciano | @mgraciano Agradecimentos Michel Graciano (@mgraciano) - Sem dvida uma grande ajuda na coleta e organizao do contedo destes slides Q&A Janario Oliveira | @janarioliver Michael Nascimento Santos | @mr_ _m Michel Graciano | @mgraciano