KEMBAR78
Leaner microservices with Java 10 | PPTX
Leaner microservices with
Java 10, Spring Boot 2,
and Docker
arto.santala@solita.fi
Who am I?
• Arto Santala
• Work as software architect in Solita, producing tailored
solutions to accelerate customer business
• More than 20 years of experience making customers
dreams come true with application of proper technologies
and methodologies
• Guilty of writing a lot of horrible code in the 90’s that
should be burned with fire. Always aiming to improve.
• Passionate about agile and automation. Trying to make
every moment worthy of living.
Java 8 as platform
• Java 8 is product of more than 20 years of development. Every
release, more and more have been added, nothing has never
been removed
• Today Java 8 is a heavy platform with a lot of libraries that you
will never need
• Midi instruments, 1995 version of java.util.Date, Corba IIOP, applets,
AWT, …
• Heavier images, larger memory footprint, more attack area for
vulnerabilities
Java 8 + Spring Boot Helloworld
Java 9 as platform
• Modular JDK, Modular source code, Modular run-time images, Module system, Modular
application packaging, Java platform module system, etc
• Also: Jshell, new HTTP client (HttpRequest/HttpResponse), Process API, Pub/Sub
framework, immutable set/list, Optional to Stream, etc
module fi.solita.java9training.api {
requires fi.solita.java9training.services;
exports fi.solita.java9training.api;
}
Set<String> mySet = Set.of(”val1", ”val2", ”val3");
List<String> myList = List.of(”val1”,”val2”,”val3”);
Java 10 as platform
• Not such a revolution, just a bit of evolution
• Hard transition from Java 8 to Java 9
• Easy transition from Java 9 to 10 and 11
• GA is out there now – but do note the short support lifetime for both Java 9 and 10
var item1 = ”HELLO”;
var list1 = List.of(item1,”WORLD”);
Java 10 + Spring Boot Helloworld
Still fat, but getting better!
Pssst, minimal Java 10 + Apache Spark web services
JSHELL REPL
JLINK
jlink --module-path $JAVA_HOME/jmods --verbose --add-modules
java.base,java.logging,java.xml,jdk.unsupported,java.sql,java.naming,java.desktop,java.man
agement,java.security.jgss,java.instrument --compress 2 --no-header-files --output jdk-9-
minimal-osx --no-man-pages
Jlink is a new tool that allows to link modules and even JRE together as a platform specific
executable.
For example, you can generate a custom JRE with just the modules you need to run Spring
Boot, like this:
Much less attack surface, less to update, less disk use, less memory use, faster startup, etc
Java Support Roadmap
http://www.oracle.com/technetwork/java/eol-135779.html
Maven source level
<properties>
<maven.compiler.source>10</maven.compiler.source>
<maven.compiler.target>10</maven.compiler.target>
</properties>
Maven compiler plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<release>10</release>
</configuration>
<dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<!-- Use newer version of ASM -->
<version>6.1.1</version>
</dependency>
</dependencies>
</plugin>
Spring Boot 2
• Spring Boot 1.x is not going to support Java 9 or above, ever
• Spring Boot 2 is out there, with support to Java 9 (and to some extent also
10)
• Easiest to get started with Spring Initializr at https://start.spring.io/
Quick (stupid) test
@RestController
public class HelloController {
@RequestMapping(method = RequestMethod.GET)
public Map getGreeting() {
var now = Instant.now();
return Map.of("message", String.format("It's %s", now));
}
}
Typical pitfalls with Java 9/10
• package javax.xml.bind.annotation.adapters is not visible
• More and more core modules are missing from core of core, so you need to either add them via
command line switches, or declare module dependencies – or just as dependencies
• --add-modules java.xml.bind
• Illegal reflective access by org.springframework.cglib.core.ReflectUtils
• Java 9/10 is starting to be more precise on accessing non-public APIs, so primarily you should find
libraries that are not accessing internal APIs
• Ironically, with Spring you can make this warning go away by setting –illegal-access=deny
• In some cases. as short-term solution you can also play with --add-
exports $module/$package=$readingmodule and --add-opens $module/$package=$readingmodule to
open up types and members for deep reflection of also private internals
• So mostly, just make sure dependencies and modules are declared properly, and find libraries
that play nicely with Java 9/10/11 and do not leverage the deprecated internals
• In future, more and more modules and packages will go out of core, so get used to this
Typical pitfalls with Java 9/10
• IllegalArgumentException at testCompilation/test phase
• Maven compiler/surefire might be using older version of ASM, which can be fixed like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<release>10</release>
</configuration>
<dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>6.1.1</version> <!-- Use newer version of ASM -->
</dependency>
</dependencies>
</plugin>
Other non-default (EE) modules
• java.activation with javax.activation package
• java.corba with javax.activity, javax.rmi, javax.rmi.CORBA, andorg.omg.* packages
• java.transaction with javax.transaction package
• java.xml.bind with all javax.xml.bind.* packages
• java.xml.ws with javax.jws, javax.jws.soap, javax.xml.soap, and alljavax.xml.ws.* packages
• java.xml.ws.annotation with javax.annotation package
• Java 11 will remove all these, so it will not be enough to just --add-modules forever, you
need to find the actual libraries and declare as real, external dependencies
XML modules will go out from core
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
Evaluating old code
• java --list-modules
• jdeps --jdk-internals -R --class-path 'libs/*' $project
• --illegal-access=$value option, where $value can be:
• permit: Access to all JDK-internal APIs is permitted to code on the class path. For reflective access,
a single warning is issued for the first access to each package. (Default is Java 9, but will be
removed in a future release.)
• warn: Behaves like permit but a warning is issued for each reflective access.
• debug: Behaves like warn but a stack trace is included in each warning.
• deny: The option for those who believe in strong encapsulation:
• All illegal access is forbidden by default.
• jar –file=mylib.jar --describe-modules
• To figure out automatic module name for the .jar
Typical pitfalls with Spring Boot 2
• Security module has changed a lot: Now you only get what you declare, unlike previously
when there were a lot of defaults
• Spring Data APIs have changed a lot: Now there’s a lot more of Optional use for return
values, and more descriptive names for methods
• Later version of Flyway, not checksum compatible with old version possibly
• References to old versions of Spring modules, or third party modules that depend on 1.x
versions
Docker
• Docker is a lovely way to start experimenting with Java 9/10 without installing it on your
own machine
• docker run -it solita/jdk10
• You can map folders to Docker so you can access files in them, such as .jar files, libraries,
etc – you can also expose ports where services run to host machines
• docker run -it -p 8080:8080 -v `pwd`:/root solita/jdk10
• This is just an example, you can take a look and create your own docker images
• How about two-phased Docker image, one step will build the modular JRE, second will
package your .jar with it?
Two-phase dockerfile example
FROM solita/jdk10 as packager
# First stage: JDK 10 with modules required for Spring Boot
RUN /opt/jdk-10/bin/jlink 
--module-path /opt/jdk-10/jmods 
--verbose 
--add-modules
java.base,java.logging,java.xml,jdk.unsupported,java.sql,java.naming,java.desktop,java.management,java.secu
rity.jgss,java.instrument 
--compress 2 
--no-header-files 
--output /opt/jdk-10-minimal
# Second stage, add only our custom jdk9 distro and our app
FROM solita/jdk10
COPY --from=packager /opt/jdk-10-minimal /opt/jdk-10-minimal
COPY target/*.jar /opt/
ENV JAVA_HOME=/opt/jdk-10-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"
EXPOSE 8080
CMD java -jar /opt/*.jar
Exercise resources
• https://github.com/crystoll/spring-boot-java10/
• https://hub.docker.com/r/solita/jdk10/
• https://hub.docker.com/r/solita/jdk11-ea/
• http://dev.solita.fi/2018/01/24/Java9-modules-Spring-Boot-2-Docker.html
• http://dev.solita.fi/2018/03/02/Update-to-Java11.html
Other Resources
• https://hub.docker.com/_/openjdk/
• https://hub.docker.com/r/solita/jdk10/
• https://stackoverflow.com/questions/48204141/replacements-for-
deprecated-jpms-modules-with-java-ee-apis/
• https://blog.frankel.ch/migrating-to-java-9/1/
• https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-with-Java-9
• https://github.com/dsyer/spring-boot-java-9
Hackathexerciseon
Hackathexerciseon
• Let’s try to build something with all this
• Idea: API for registering thumbs up/thumbs down signals for presentation
• Presentations have a name, and we register thumbs-up/thumbs-down entries for them
• Let’s assume presentations have shorter code that can be used to refer to it.
• Anyone can give as many entries as they like, not limited in this exercise
• API should also let us know total number of thumbs-up/thumbs-down for a presentation, and could
let us know most highly/lowly rated presentations
• Extra exercise:
• Simple UI for pressing thumbs-up/thumbs-down for a presentation
• Another UI for showing outcomes
• Websockets, real-time tracking of +/-
• CI pipeline, AWS Fargate/EKS deployment, self-healing capabilities, go crazy
Hackathexerciseon
• So, form small groups, experiment with either larger challenge or some
substeps
• Pull JDK10 docker image, or install JDK 10 locally, try jshell, jlink, syntax
• Create Spring Boot 2.0 initializr project, compile and run with JDK 10
• Create some API and Services, to push it further. Include db?
• Minimize the JDK 10 environment, see if it still runs. How are the resources doing? Can
you measure them? Can you compare them?
• Ask questions, try things, break things
Thanks!
ARTO SANTALA
Software Architect
arto.santala@solita.fi
+358505747452
Leaner microservices with Java 10

Leaner microservices with Java 10

  • 1.
    Leaner microservices with Java10, Spring Boot 2, and Docker arto.santala@solita.fi
  • 2.
    Who am I? •Arto Santala • Work as software architect in Solita, producing tailored solutions to accelerate customer business • More than 20 years of experience making customers dreams come true with application of proper technologies and methodologies • Guilty of writing a lot of horrible code in the 90’s that should be burned with fire. Always aiming to improve. • Passionate about agile and automation. Trying to make every moment worthy of living.
  • 3.
    Java 8 asplatform • Java 8 is product of more than 20 years of development. Every release, more and more have been added, nothing has never been removed • Today Java 8 is a heavy platform with a lot of libraries that you will never need • Midi instruments, 1995 version of java.util.Date, Corba IIOP, applets, AWT, … • Heavier images, larger memory footprint, more attack area for vulnerabilities
  • 4.
    Java 8 +Spring Boot Helloworld
  • 5.
    Java 9 asplatform • Modular JDK, Modular source code, Modular run-time images, Module system, Modular application packaging, Java platform module system, etc • Also: Jshell, new HTTP client (HttpRequest/HttpResponse), Process API, Pub/Sub framework, immutable set/list, Optional to Stream, etc module fi.solita.java9training.api { requires fi.solita.java9training.services; exports fi.solita.java9training.api; } Set<String> mySet = Set.of(”val1", ”val2", ”val3"); List<String> myList = List.of(”val1”,”val2”,”val3”);
  • 6.
    Java 10 asplatform • Not such a revolution, just a bit of evolution • Hard transition from Java 8 to Java 9 • Easy transition from Java 9 to 10 and 11 • GA is out there now – but do note the short support lifetime for both Java 9 and 10 var item1 = ”HELLO”; var list1 = List.of(item1,”WORLD”);
  • 7.
    Java 10 +Spring Boot Helloworld Still fat, but getting better! Pssst, minimal Java 10 + Apache Spark web services
  • 8.
  • 9.
    JLINK jlink --module-path $JAVA_HOME/jmods--verbose --add-modules java.base,java.logging,java.xml,jdk.unsupported,java.sql,java.naming,java.desktop,java.man agement,java.security.jgss,java.instrument --compress 2 --no-header-files --output jdk-9- minimal-osx --no-man-pages Jlink is a new tool that allows to link modules and even JRE together as a platform specific executable. For example, you can generate a custom JRE with just the modules you need to run Spring Boot, like this: Much less attack surface, less to update, less disk use, less memory use, faster startup, etc
  • 10.
  • 11.
  • 12.
  • 13.
    Spring Boot 2 •Spring Boot 1.x is not going to support Java 9 or above, ever • Spring Boot 2 is out there, with support to Java 9 (and to some extent also 10) • Easiest to get started with Spring Initializr at https://start.spring.io/
  • 14.
    Quick (stupid) test @RestController publicclass HelloController { @RequestMapping(method = RequestMethod.GET) public Map getGreeting() { var now = Instant.now(); return Map.of("message", String.format("It's %s", now)); } }
  • 15.
    Typical pitfalls withJava 9/10 • package javax.xml.bind.annotation.adapters is not visible • More and more core modules are missing from core of core, so you need to either add them via command line switches, or declare module dependencies – or just as dependencies • --add-modules java.xml.bind • Illegal reflective access by org.springframework.cglib.core.ReflectUtils • Java 9/10 is starting to be more precise on accessing non-public APIs, so primarily you should find libraries that are not accessing internal APIs • Ironically, with Spring you can make this warning go away by setting –illegal-access=deny • In some cases. as short-term solution you can also play with --add- exports $module/$package=$readingmodule and --add-opens $module/$package=$readingmodule to open up types and members for deep reflection of also private internals • So mostly, just make sure dependencies and modules are declared properly, and find libraries that play nicely with Java 9/10/11 and do not leverage the deprecated internals • In future, more and more modules and packages will go out of core, so get used to this
  • 16.
    Typical pitfalls withJava 9/10 • IllegalArgumentException at testCompilation/test phase • Maven compiler/surefire might be using older version of ASM, which can be fixed like this: <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <release>10</release> </configuration> <dependencies> <dependency> <groupId>org.ow2.asm</groupId> <artifactId>asm</artifactId> <version>6.1.1</version> <!-- Use newer version of ASM --> </dependency> </dependencies> </plugin>
  • 17.
    Other non-default (EE)modules • java.activation with javax.activation package • java.corba with javax.activity, javax.rmi, javax.rmi.CORBA, andorg.omg.* packages • java.transaction with javax.transaction package • java.xml.bind with all javax.xml.bind.* packages • java.xml.ws with javax.jws, javax.jws.soap, javax.xml.soap, and alljavax.xml.ws.* packages • java.xml.ws.annotation with javax.annotation package • Java 11 will remove all these, so it will not be enough to just --add-modules forever, you need to find the actual libraries and declare as real, external dependencies
  • 18.
    XML modules willgo out from core <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.0</version> </dependency>
  • 19.
    Evaluating old code •java --list-modules • jdeps --jdk-internals -R --class-path 'libs/*' $project • --illegal-access=$value option, where $value can be: • permit: Access to all JDK-internal APIs is permitted to code on the class path. For reflective access, a single warning is issued for the first access to each package. (Default is Java 9, but will be removed in a future release.) • warn: Behaves like permit but a warning is issued for each reflective access. • debug: Behaves like warn but a stack trace is included in each warning. • deny: The option for those who believe in strong encapsulation: • All illegal access is forbidden by default. • jar –file=mylib.jar --describe-modules • To figure out automatic module name for the .jar
  • 20.
    Typical pitfalls withSpring Boot 2 • Security module has changed a lot: Now you only get what you declare, unlike previously when there were a lot of defaults • Spring Data APIs have changed a lot: Now there’s a lot more of Optional use for return values, and more descriptive names for methods • Later version of Flyway, not checksum compatible with old version possibly • References to old versions of Spring modules, or third party modules that depend on 1.x versions
  • 21.
    Docker • Docker isa lovely way to start experimenting with Java 9/10 without installing it on your own machine • docker run -it solita/jdk10 • You can map folders to Docker so you can access files in them, such as .jar files, libraries, etc – you can also expose ports where services run to host machines • docker run -it -p 8080:8080 -v `pwd`:/root solita/jdk10 • This is just an example, you can take a look and create your own docker images • How about two-phased Docker image, one step will build the modular JRE, second will package your .jar with it?
  • 22.
    Two-phase dockerfile example FROMsolita/jdk10 as packager # First stage: JDK 10 with modules required for Spring Boot RUN /opt/jdk-10/bin/jlink --module-path /opt/jdk-10/jmods --verbose --add-modules java.base,java.logging,java.xml,jdk.unsupported,java.sql,java.naming,java.desktop,java.management,java.secu rity.jgss,java.instrument --compress 2 --no-header-files --output /opt/jdk-10-minimal # Second stage, add only our custom jdk9 distro and our app FROM solita/jdk10 COPY --from=packager /opt/jdk-10-minimal /opt/jdk-10-minimal COPY target/*.jar /opt/ ENV JAVA_HOME=/opt/jdk-10-minimal ENV PATH="$PATH:$JAVA_HOME/bin" EXPOSE 8080 CMD java -jar /opt/*.jar
  • 23.
    Exercise resources • https://github.com/crystoll/spring-boot-java10/ •https://hub.docker.com/r/solita/jdk10/ • https://hub.docker.com/r/solita/jdk11-ea/ • http://dev.solita.fi/2018/01/24/Java9-modules-Spring-Boot-2-Docker.html • http://dev.solita.fi/2018/03/02/Update-to-Java11.html
  • 24.
    Other Resources • https://hub.docker.com/_/openjdk/ •https://hub.docker.com/r/solita/jdk10/ • https://stackoverflow.com/questions/48204141/replacements-for- deprecated-jpms-modules-with-java-ee-apis/ • https://blog.frankel.ch/migrating-to-java-9/1/ • https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-with-Java-9 • https://github.com/dsyer/spring-boot-java-9
  • 25.
  • 26.
    Hackathexerciseon • Let’s tryto build something with all this • Idea: API for registering thumbs up/thumbs down signals for presentation • Presentations have a name, and we register thumbs-up/thumbs-down entries for them • Let’s assume presentations have shorter code that can be used to refer to it. • Anyone can give as many entries as they like, not limited in this exercise • API should also let us know total number of thumbs-up/thumbs-down for a presentation, and could let us know most highly/lowly rated presentations • Extra exercise: • Simple UI for pressing thumbs-up/thumbs-down for a presentation • Another UI for showing outcomes • Websockets, real-time tracking of +/- • CI pipeline, AWS Fargate/EKS deployment, self-healing capabilities, go crazy
  • 27.
    Hackathexerciseon • So, formsmall groups, experiment with either larger challenge or some substeps • Pull JDK10 docker image, or install JDK 10 locally, try jshell, jlink, syntax • Create Spring Boot 2.0 initializr project, compile and run with JDK 10 • Create some API and Services, to push it further. Include db? • Minimize the JDK 10 environment, see if it still runs. How are the resources doing? Can you measure them? Can you compare them? • Ask questions, try things, break things
  • 28.

Editor's Notes

  • #12 If IntelliJ fails to recognize ’var’, you can do File-Invalidate Caches/Restart
  • #13 You may need to do the same with Surefire plugin
  • #25 https://stackoverflow.com/questions/49398894/unable-to-compile-simple-java-10-project-with-maven/49398936
  • #29 https://twitter.com/SolitaOy https://www.facebook.com/Solita https://www.linkedin.com/company/solita-oy/ https://www.youtube.com/user/SolitaOy