Ext.Links
-Lang&VM specs
-API
-Adpot OpenJDK prebuilt binaries
https://hg.openjdk.java.net/jdk/jdk
-OpenJDK@Mercurial
- @[https://wiki.openjdk.java.net/]
- @[https://openjdk.java.net/]

-JAVA MIND-MAP
-(Active) Java JVM List
-Eclipe Tools for [QA]
-Excellent Java Blog (spanish)
-JAVA Enhancements proposals
-Douglas Craigs Schmidt Java Lessons:
-Awesome Java

-@[https://java-source.net/] Collections of Production-ready software developed with Java,
   from DDBBs, caches, servers, ...


Who-is-Who
(Forcibly incomplete but still quite pertinent list of core developers and companies)
- James Arthur Gosling:  Founder and lead-designer of the Java Programming Language
  @[https://en.wikipedia.org/wiki/James_Gosling]

- Joshua J. Bloch:
  @[https://en.wikipedia.org/wiki/Joshua_Bloch]
  - Author of the book "Effective Java" (a must read)
    and co-author of two other books:
    - Java Puzzlers (2005)
    - Java Concurrency in Practice (2006)
  - Led the design and implementation of numerous
    Java platform features, including the
    Java Collections Framework, the java.math package,
    and the assert mechanism.

- Julien Viet:
 @[http://www.julienviet.com/]
  Core developer of VertX, crash (http://www.crashub.org/),
  and many other interesting Java software.
  @[https://github.com/vietj?utf8=%E2%9C%93&tab=repositories&q=&type=source]

- Ben Evans:
  - jClarity Co-founder.
  - Java Champion, author, speaker, consultant
  - voting member on Java’s governing
  - Author of 5 books
    - “The Well-Grounded Java Developer”,
    - new editions of “Java in a Nutshell”,
    - “Java: The Legend” and “Optimizing Java”.
    - Track lead for Java / JVM at InfoQ.
  @[https://www.jbcnconf.com/2019/infoTalk.html?id=5c64983638da16483151bb37]
  IMPLEMENTING A SIMPLE JVM IN JAVA AND RUST
  ... I will explain how we might start to implement a JVM from scratch.. then
   we will show how the Rust programming language provides a good alternative
   implementation language for our simple JVM. We will showcase some basic Rust
   language features and show how they can be used to provide a version of our
   JVM that is much cleaner and easier to understand, even if you've never
   seen Rust code before!"""

- Emmanuel Bernard: Distinguished Engineer and Chief Architect Data at
  Red Hat (middleware). His work is Open Source. He is most well known for his
  contributions and lead of the Hibernate projects as well as his contribution
  to Java standards. His most recent endeavour is Quarkus (A Kubernetes Native
  Java stack tailored for GraalVM and OpenJDK HotSpot, crafted from the best of
  breed Java libraries and standards).

- https://community.oracle.com/community/groundbreakers/java/java-champions
- https://blogs.oracle.com/java/new-java-champions-in-2017
What's new
v.14
https://www.infoq.com/news/2019/12/java14-feature-freeze/
 └ More container awareness...
   - NUMA container support added to hotspot (JDK-8198715)
   - Add Container MBean to JMX (JDK-8199944)

v 12,13 @[https://www.infoq.com/news/2019/06/java13-feature-freeze/] @[https://developers.redhat.com/blog/2019/06/27/shenandoah-gc-in-jdk-13-part-1-load-reference-barriers/] @[https://developers.redhat.com/blog/2019/06/28/shenandoah-gc-in-jdk-13-part-2-eliminating-the-forward-pointer-word/] @[https://developers.redhat.com/blog/2019/07/01/shenandoah-gc-in-jdk-13-part-3-architectures-and-operating-systems/] └ More container awareness... - add container support to jhsdb command (JDK-8205992) - Flight Recorder impovements for containers (JDK-8203359) - Improve containe support when Join Contolles option is used (JDK-8217766) - Impove systemd slice memory limit suppot (JDK-8217338) - JFR jdk.CPUInformation event epots incorrect info. when running in Docker container (JDK-8219999)
v.11(LTS) 2018/09 @[https://www.journaldev.com/24601/java-11-features] @[https://www.infoq.com/news/2018/09/java11-released] - More container awaeness... - Remove -XX:+UnlockExperimentalVMOptions, -XX:+UseGroupMemoryLimitFoHeap (JDK-8194086) - jcmd -l and jps commands do not list JVMs in Docker containers (JDK-8193710) - Container Metrics (-XshowSettings:system) (JDK-8204107) - Update CPU count algorithm when both cpu shares and quotas are used (JDK-8197867) --XX:+PrefectContainerQuotaForCPUCount new major features: - Autocompilation(JEP 330). Next code will execute: $ java someFile.java - New string methods: - isBlank(): true for Empty or only white spaces strings - lines() : returns string[] that collects all substrings split by lines. System.out.println( "JD\nJD\nJD".str.lines().collect(Collectors.toList()) ); - strip() : similar to trim() but unicode-aware stripLeading() stripTrailing() - repeat(int n) : repeats string n times. - Local-Variable Syntax for Lambda Parameters (JEP 323) (var s1, var s2) -˃ s1 + s2 - While it's possible to just skip the type in the lambda it becomes a need when for annotations like @Nullable - Nested Based Access Control (fix some issues when using (discouraged-)reflection. - Dynamic Class-File Constants(JEP 309) - class-file format now extends support a new constant pool form: -ºCONSTANT_Dynamicº, reduce the cost and disruption of developing new forms of materializable class-file constraints. - Epsilon: A No-Op Garbage Collector(JEP 318): - Experimental - Unlike the JVM GC which is responsible for allocating memory and releasing it, Epsilon only allocates memory. Useful for: -ºExtremely short lived jobsº - Performance testing - Memory pressure testing - VM interface testing - Last-drop latency improvements - Last-drop throughput improvements - Remove the JavaEE and CORBA Modules(JEP 320): java.xml.ws, java.xml.bind, java.activation, java.xml.ws.annotation, java.corba, java.transaction, java.se.ee, jdk.xml.ws, jdk.xml.bind RºWARNº: EE modules contain the support for JAXB and SOAP, still in relatively widespread use. - Check carefully whether build scripts need to be modified. - Flight Recorder(JEP 328) - profiling tool gathering diagnostics and profiling data - negligible performance overhead (˂1%): -ºCan be used in productionº - HTTP Client (JEP 321) - HTTP/1.1,ºHTTP/2 and WebSocketsº - Designed to improve overall performance of sending requests by a client and receiving responses from the server. - TLS 1.3 - Convenient Reading/Writing Strings to/from Files - readString() - writeString() Path path = Filesº.writeStringº( Files.createTempFile("test", ".txt"), "This was posted on JD"); System.out.println(path); String s = Filesº.readStringº(path); System.out.println(s); //This was posted on JD - ChaCha20,Poly1305 Crypto (JEP 329) - implemented in the SunJCE provider. - Improve (string and array)Aarch64 processor Intrinsics(JEP 315) - implement also new intrinsics for (java.lang.Math) sin, cos, and log functions. - ZGC:(JEP 333) - Scalable Low-Latency Garbage Collector - Experimental - low latency GC. - sub-10ms pause times, less than 15% perf.penalty. - Deprecate Nashorn JS Engine(JEP 335)
v.10 (2018/03) - More container awareness... - Improve heap memory allocations (JDK-8196595): o --XX:InitialRAMPercentage, --X:MaxRAMPercentage and -XX:MinRAMPercentage --XX:InitialRAMFraction , --X:MaxRAMFraction and -XX:MinRAMFraction Rºdeprecatedº - Total number of CPUs available to the Java Process calculated from --cpus, --cpu-shares, --cpu-quota (JDK-8146115) o Use --XX:-UseContainerSupport to return to the old behaviour o # processors that the HVM will use internally -XX:ActiveProcessorCount - Attach in linux became elative to /proc/pid/root and namespace aware (jcmd, jstack,...) - Application Data-Class Sharing (JEP ???) - extends existing Class-Data Sharing ("CDS") for allowing application classes to be placed in the shared archive in order to improve startup and footprint. - Parallel Full GC for G1 - improves G1 worst-case latencies - Garbage Collector Interface - improves source code isolation of different GCs. - Consolidate JDK Forest into a Single Repository - Local-Variable Type Inference - declarations of local variables with initializers - introducesºvarº - Remove Native-Header Generator Tool (javah) superseded by superior functionality in javac. - Thread-Local Handshakes: - Allows to execute a callback on threads without performing a global VM safepoint. Makes it both possible and cheap to stop individual threads and not just all threads or none. - Time-Based Release Versioning - Root Certificates, providing a default set of root CAs in the JDK. - Heap Allocation on Alternative Memory Devices: - enables the HotSpot VM to allocate the Java object heap on an alternative memory device, such as an NV-DIMM, specified by the user. - Experimental Java-Based JIT Compiler Graal: - Linux/x64 platform only - Additional Unicode Language-Tag Extensions - Removed Features and Options:
v.9(2017/09) └ --XX:ParallerGCThreads and --XX:CICompilerCount are set based on Containers CPU limits (can be overriden) - Calculated from --cpuset-cpus └ Memory Configuration for containers -XX:+UnlockExperimentalVMOptions -XX:+UseGroupMemoryLimitFoHeap - set -XX:MaxRAMFraction to 2 (default is 4) - Java Platform Module System: - based on Project Jigsaw - divides the JDK into a set of modules for combining at run, compile, or build time. - enabling understanding of dependencies across modules. - allows developers to more easily assemble and maintain sophisticated applications. - allows to scale down to smaller devices. - improves security and performance. - aspects include: - application packaging - JDK modularization - reorganizing source code into modules. - Build system is enhanced to compile modules and enforce module boundaries at build time. (Java 9 allows illegal reflective access to help migration) - ahead-of-time (AoT) compilation (experimental) - improve startup time, with limited impact on peak performance. -ºREPL (read-eval-print loop)º - jShell: interactively evaluates statements "a la script". - tab completion - automatic addition of needed terminal semicolons. - jShell API for IDE integration. - jShell: interactively evaluates statements "a la script". - Streams API Enhancements - Java 8 Stream API allows processing data declaratively while leveraging multicore architectures. - Java 9 adds methods to conditionally take and drop items from Stream, iterate over Stream elements, and create a stream from a nullable value while expanding the set of Java SE APIs that can serve as Streams sources. - Code cache can be divided in Java 9 - code cache can now be divided into segments to improve performance and allow extensions such as fine-grained locking resulting in improved sweep times - (Datagram Transport Layer Security) DTLS security API - prevent eavesdropping, tampering, and message forgery in client/server communications. - Java 9 deprecates and removes: - Applet API and appletviewer (alternative: Java Web Start) - Concurrent Mark Sweep (CMS) GC. - JVM TI (Tool Interface) hprof (Heap Profiling) agent, superseded in the JVM. - jhat tool, obsoleted by superior heap visualizers and analyzers.
JAVA 8 └ 8u131 First version to support Containers RºWARNº: Do not use any version below that. (TODO) @[https://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html] @[https://www.qwant.com/?q=what+new+java+8]
Inside the JVM
@[https://www.artima.com/insidejvm/ed2/index.html]
JVM Implementations
@[https://blog.joda.org/2018/09/time-to-look-beyond-oracles-jdk.html]

In practical terms, there is only one set of source code for the JDK. 
The source code is hosted in Mercurial at OpenJDK.

Anyone can take that source code, produce a build and publish it on a 
URL. But there is a distinct certification process that should be 
used to ensure the build is valid.

Certification is run by the Java Community Process, which provides a 
Technology Compatibility Kit (TCK, sometimes referred to as the JCK). 
If an organization produces an OpenJDK build that passes the TCK then 
that build can be described as "Java SE compatible".

Note that the build cannot be referred to as "Java SE" without the 
vendor getting a commercial license from Oracle. For example, builds 
from AdoptOpenJDK that pass the TCK are not "Java SE", but "Java SE 
compatible" or "compatible with the Java SE specification". Note also 
that certification is currently on a trust-basis - the results are 
not submitted to the JCP/Oracle for checking and cannot be made 
public. 

To summarise, the OpenJDK + Vendor process turns one sourcebase into 
many different builds. 

- Oracle Java
- OpenJ9      (Eclipse "IBM")
  └ https://en.wikipedia.org/wiki/OpenJ9
  └ Prebuilt binaries available at AdoptOpenJDK
  └ Compared to Oracle's HotSpot VM, i touts higher
    start-up performance and lower memory consumption 
    at a similar overall throughput.
  └ JIT with all optimization levels.
- OpenJDK
- GraalVM
- Bellsoft Liberica:
  - $free TCK verified OpenJDK distribution for x86, ARM32 and ARM64.
- Azul Systems
- Sap Machine
  JDK for Java 10 and later under the GPL+CE license. 
  They also have a commercial closed-source JVM
- Amazon Corretto:
  zero-cost build of OpenJDK with long-term support that passes the 
  TCK. It is under the standard GPL+CE license of all OpenJDK builds. 
  Amazon will be adding their own patches and running Corretto on AWS

BºJIT compiler optimization levels:º
  - cold
  - warm
  - hot
  - very hot (with profiling)
  - scorching.
    ^^^^^^^^
  The hotter the optimization level, the better the 
  expected performance, but the higher the cost in terms of 
  CPU and memory.

Memory
  JVM MEMORY
(REF)
JAVA MEMORY MODEL:

         │    STACK ("SMALL")          │ HEAP  ("HUGE")
         │ private to each Thread      │ Shared by Threads
─────────┼─────────────────────────────┼──────────────────
Contain  │ - references to heap objects│ - objects
         │ - value types               │ - instance fields
         │ - formal method params      │ - static fields
         │ - exception handler params  │ - array elements

* 1: Ref(erence) types on the stack point to real object in HEAP memory.

Reference Types regarding how the object on the heap is eligible for garbage collection
┌─────────┬───────────────────────────────────────────────────────────────────────────
│ STRONG  │ - Most popular.
│         │ - The object on the heap it is not garbage collected
│         │   while there is a strong reference pointing to it, or if it is
│         │   strongly reachable through a chain of strong references.
├─────────┼───────────────────────────────────────────────────────────────────────────
│ WEAK    │ - most likely to not survive after the next garbage collection process.
│         │ - Is created like
│         │    WeakReference˂StringBuilder˃ reference =
│         │     = new WeakReference˂˃(new StringBuilder());
│         │ - ºEx.use case: caching:º
│         │   We let the GC remove the object pointed to by the weak reference,
│         │   after which a null will be returned
│         │   See JDK implementation at
│         │   @[https://docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html]
├─────────┼───────────────────────────────────────────────────────────────────────────
│ SOFT    │ - used for more memory-sensitive scenarios
│         │ - Will be garbage collected only when the application is running low on memory.
│         │ - *Java guarantees that all soft referenced objects
│         │   are cleaned up before throwing OutOfMemoryError*
│         │ - is created as follows:
│         │   SoftReference˂StringBuilder˃ reference = new SoftReference˂˃(new StringBuilder());
├─────────┼───────────────────────────────────────────────────────────────────────────
│ PHANTOM │ - Used to schedule post-mortem cleanup actions, since we know for
│         │   sure that objects are no longer alive.
│         │ - Used only with a reference queue, since the .get() method of
│         │   such references will always return null.
│         │ - ºThese types of references are considered preferable to finalizersº
└─────────┴───────────────────────────────────────────────────────────────────────────
Force string pool reuse
- Strings are immutable.
- Stored on the heap
- Java manages a string pool in memory,
  reusing strings whenever possible.

String string01 = "297",                                string01 == string02 : true
       string02 = "297",                                string01 == string03 : Rºfalseº *1
       string03 = new Integer(297).toString(),          string01 == string04 : true  *2
       string04 = new Integer(297).toString()º.intern()º; *2

º1: RºPool reuse does not work for dynamically created strings*
*2: If we consider that the computed String will be used quite often,
    we can force the JVM to add it to the string pool by adding the
    .intern() method at the end of computed string:
"MARK&SWEEP"
JVM analyzes the variables from the stack and "marks" all the objects that need to be kept alive.
Then, all the unused objects are cleaned up.

The more garbage there is, and the fewer that objects are marked alive, the faster the process is.

To optimize even more heap memory actually consists of multiple parts (Java 8+):

  ┌──────────┼─────────────────────────────────────
  │ HEAP     │
  │ SPACES   │
  ├──────────┼─────────────────────────────────────
  │ Eden     │ * object are place here upon creation.
  │          │ * "small" ─→ gets full quite fast.
  │          │ * GC runs on the Eden space and marks objects as alive
  ├──────────┼─────────────────────────────────────
  │ S0       │ * Eden Objects surviving 1st GC are moved here
  │          │
  ├──────────┼─────────────────────────────────────
  │ S1       │ * Eden Objects surviving 2nd GC are moved here
  │          │ * S0   Objects surviving     GC are moved here
  ├──────────┼─────────────────────────────────────
  │ Old      │ * Object survives for "N" rounds of GC (N depends on
  │          │   implementation), most likely that it will survive
  │          │   forever, and get moved here
  │          │ * Bigger than Eden and S0,S1. GC doesn't run so often
  ├──────────┼─────────────────────────────────────
  │ Metaspace│ * metadata about loaded classes
  │          │   (PermGen Before Java 8)
  ├──────────┼─────────────────────────────────────
  │ String   │
  │   pool   │
  └──────────┴─────────────────────────────────────
GC Types
- default GC type is based on the underlying hardware
- programmer can choose which one should be used


   GC TYPE     | Description  / Use-Cases
+--------------+-----------------------------------------------------------------------------
|Serial GC     | - Single thread collector.
|              | - ºHalt all app threads while executingº
|              | - Mostly applies to ºsmall apps with small data usageº
|              | - Can be enabled through : Oº-XX:+UseSerialGCº
+--------------+-----------------------------------------------------------------------------
|Parallel GC   | - Multiple threads used for GC
|              | - ºHalt all app threads while executingº
|              | - Also known as throughput collector
|              | - Can be enabled through : Oº-XX:+UseParallelGCº
+--------------+-----------------------------------------------------------------------------
|Mostly        | - works concurrent to the application, "mostly" not halting threads
|Concurrent GC | - "mostly": There is a period of time for which the threads are paused.
|              |    Still, the pause is kept as short as possible to achieve the best GC performance.
|              | - 2 types of mostly concurrent GCs:
|              |   * Garbage First - high throughput with a reasonable application pause time.
|              |                   - Enabled with the option: Oº-XX:+UseG1GCº
|              |   º Concurrent Mark Sweep: app pause is kept to minimum. ºDeprecated as Java9+*
|              |                   - Enabled with the option: Oº-XX:+UseConcMarkSweepGCº
+--------------+-----------------------------------------------------------------------------

See also:
@[https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/sizing.html]
Optimization Tips
- To minimize the memory footprint, limit the scope of the variables as much as possible.

- Explicitly refer to null obsolete references making them eligible for GC.

- Avoid finalizers. They slow down the process and they do not guarantee anything.
  Prefer phantom references for cleanup work.

- Do not use strong references where weak or soft references apply.
 ºThe most common memory pitfalls are caching scenarios,when dataº
 ºis held in memory even if it might not be needed.º

- Explicitly specify heap size for the JVM when running the application:
  -  allocate a reasonable initial and maximum amount of memory for the heap.
   OºInitial heap size -Xms512m º – set initial heap     size to  512 megabytes
   OºMaximum heap size -Xmx1024mº – set maximum heap     size to 1024 megabytes
   OºThread stack size -Xss128m º – set thread stack     size to  128 megabytes
   OºYoung genera.size -Xmn256m º – set young generation size to  256 megabytes

REF: @[https://dzone.com/articles/heap-memory-in-java-performance-testing?utm_source=www.oficina24x7.com]
    - Initial Heap Size: -Xms: ˃= 1/64th of physical memory || reasonable minimum.
    - Maximum Heap Size: -XmX: ˂= 1/4 th of physical memory || 1GB.
                         ^^^^^
                  - Set -Xms equal to -Xmx to prevent pauses caused by heap expansion
                  ☞BºSetting Xms/Xmx increase GC predictabilityº.
    
    JVM settings are recommended for:
    PRODUCTION TIER       REPLICA SERVERS           STANDALONE
    -server               -server                   -server
    -Xms24G -Xmx24G        -Xms4G -Xmx4G            -Xms32G -Xmx32G
    └───────────────────────────┬─────────────────────────────────┘
                      PRODUCTION/REPLICA/STANDALONE:
    
                      -XX:PermSize=512m
                      -XX:+UseG1GC
                      -XX:MaxGCPauseMillis=200     ← soft goal (JVM) best effort
                      -XX:ParallelGCThreads=20     ← value depends on hosting hardware
                      -XX:ConcGCThreads=5          ← value depends on hosting hardware
                      -XX:InitiatingHeapOccupancyPercent=70 ← Use 0 to force constant 
                                                              GC cycles
    
    Rº WARN, WARN, WARN:º
    Rº There are 600+ arguments that you can pass to JVM to fine-tune GC and memory º
    Rº If you include other aspects, the number of JVM arguments will easily cross  º
    Rº 1000+. º
       (Or why Data Scientist end up using Python)


- If app OutOfMemoryError-crashes, extra info about memory leak can be obtained through
  Oº–XX:HeapDumpOnOutOfMemoryº, creating a heap dump file

- Use Oº-verbose:gcº to get the garbage collection output.

- Eclipse Memory Analyzer Manual:
@[https://help.eclipse.org/2019-06/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Fwelcome.html&cp=62]
String
final String formatedNumber = String.format("%4d",100);
See also: [[Format String Checker?]]

String[] args = ...
Strings.join(List.of(args),"'")); // ← String array to CSV.
java.time
java.time.*
- JDK 1.8+
- "deprecates" java.util.(Date|Calendar|TimeZome)
- All the classes are IMMUTABLE and THREAD-SAFE
Oºimport java.time.Instant;º
Oºimport java.time.ZonedDateTime;º
Oºimport java.time.ZoneId;º
Oºimport java.util.concurrent.TimeUnit;º
...
OºInstantºBºtimestampº = OºInstantº.now();              // Create from system clock
          Bºtimestampº.plus(Duration.ofSeconds(10));    // Add 10 seconds

  │OºInstantº to String                 │ OºInstantº from String
  │(format with time-zone)              │ (parse string)
  ├─────────────────────────────────────┼───────────────────────────────────────────────────
  │OºZonedDateTimeº zdt1 =              │
  │     OºZonedDateTimeº.of             │ String sExpiresAt="2013-05-30T23:38:23.085Z";
  │       (                             │ OºZonedDateTimeºzdt2 = OºZonedDateTimeº.parse(sExpiresAt);
  │         2017, 6, 30           ,     │
  │         1, 2, 3               ,     │ OºInstantºi1 = OºInstantº.from(zdt1),
  │         (int) TimeUnit.             │           i2 = OºInstantº.from(zdt2);
  │               MILLISECONDS.         │
  │               toNanos(100),         │
  │         ZoneId.of("Europe/Paris")   │
  │       );          ^^^               │
  │     Ex: "Z","-02:00","Asia/Tokyo",..│
  │String s1 = zdt1.toString();         │
          ^^
  2017-06-30T01:02:03.100+02:00[Europe/Madrid]

java.text.DateFormat:
date  (none)           DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())
      short            DateFormat.getDateInstance(DateFormat.SHORT, getLocale())
      medium           DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale())
      long             DateFormat.getDateInstance(DateFormat.LONG, getLocale())
      full             DateFormat.getDateInstance(DateFormat.FULL, getLocale())
      SubformatPattern new SimpleDateFormat(subformatPattern, getLocale())

time  (none)           DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())
      short            DateFormat.getTimeInstance(DateFormat.SHORT, getLocale())
      medium           DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale())
      long             DateFormat.getTimeInstance(DateFormat.LONG, getLocale())
      full             DateFormat.getTimeInstance(DateFormat.FULL, getLocale())
      SubformatPattern new SimpleDateFormat(subformatPattern, getLocale())

ºCompatibility with Java ˂=1.7º
- (java.util.) Date, Calendar and TimeZone
  "buggy" classes/subclasses were used.
  ^^^^^^^
  - Calendar class was NOT type safe
  - Mutable non-threadsafe classes
  - Favored programming errors
    (unusual numbering of months,..)

- Next compatibility conversion methods were added in 1.8:
  - Calendar.toInstant()
  - GregorianCalendar.toZonedDateTime()
  - GregorianCalendar.from(ZonedDateTime) (Using default local)
  - Date.from(Instant)
  - Date.toInstant()
  - TimeZone.toZoneId()

ºjava.time. Package summaryº
                   Description
-----------------------------------------------------------------------------------
Clock              A clock providing access to the current instant, date and
                   time using a time-zone.
-----------------------------------------------------------------------------------
Duration           A time-based amount of time, such as '34.5 seconds'.
-----------------------------------------------------------------------------------
Instant            An instantaneous point on the time-line.
-----------------------------------------------------------------------------------
LocalDate          A date without a time-zone in the ISO-8601 calendar system,
                   such as 2007-12-03.
-----------------------------------------------------------------------------------
LocalDateTime      A date-time without a time-zone in the ISO-8601 calendar
                   system, such as 2007-12-03T10:15:30.
-----------------------------------------------------------------------------------
LocalTime          A time without a time-zone in the ISO-8601 calendar system,
                   such as 10:15:30.
-----------------------------------------------------------------------------------
MonthDay           A month-day in the ISO-8601 calendar system, such as --12-03.
-----------------------------------------------------------------------------------
OffsetDateTime     A date-time with an offset from UTC/Greenwich in the ISO-8601
                   calendar system, such as 2007-12-03T10:15:30+01:00.
-----------------------------------------------------------------------------------
OffsetTime         A time with an offset from UTC/Greenwich in the ISO-8601
                   calendar system, such as 10:15:30+01:00.
-----------------------------------------------------------------------------------
Period             A date-based amount of time in the ISO-8601 calendar system,
                    such as '2 years, 3 months and 4 days'.
-----------------------------------------------------------------------------------
Year               A year in the ISO-8601 calendar system, such as 2007.
-----------------------------------------------------------------------------------
YearMonth          A year-month in the ISO-8601 calendar system, such as 2007-12
-----------------------------------------------------------------------------------
ZonedDateTime      A date-time with a time-zone in the ISO-8601 calendar system,
                   such as 2007-12-03T10:15:30+01:00 Europe/Paris.
-----------------------------------------------------------------------------------
ZoneId             A time-zone ID, such as Europe/Paris.
-----------------------------------------------------------------------------------
ZoneOffset         A time-zone offset from Greenwich/UTC, such as +02:00.
-----------------------------------------------------------------------------------


Enum               Description
-----------------------------------------------------------------------------------
DayOfWeek          A day-of-week, such as 'Tuesday'.
-----------------------------------------------------------------------------------
Month              A month-of-year, such as 'July'.
-----------------------------------------------------------------------------------

Exception          Description
-----------------------------------------------------------------------------------
DateTimeException  Exception used to indicate a problem while calculating a date-time.

Java 9
- A number of parsing and formatting changes have been incorporated in Java 9 to
bring the functionality closer to Unicode Locale Data Markup Language (LDML).
These changes have been supervised by Stephen Colebourne, creator of the popular
 date-time library JodaTime, precursor of the new java.time component in Java 8.
Abiding by the Unicode standard will provide better interoperability with other
non-Java systems.

- LDML is the language used by the Unicode Common Locale Data Repository (CLDR),
  a project of the Unicode Consortium to gather and store locale data from
  different parts of the world, enabling application developers to better adapt
  their programs to different cultures. Among other things, LDML deals with dates,
  times, and timezones, and more particularly with date formatting and parsing.
  The following is an extract of new features coming in Java 9 that bring java.time
  closer to the LDML specification:

  - JDK-8148947, DateTimeFormatter pattern letter ‘g’: the letter ‘g’, as
    specified in LDML, indicates a “Modified Julian day”; this is different from a
    normal Julian day in the sense that a) it depends on local time, rather than GMT,
    and b) it demarcates days at midnight, as opposed to noon.
  - JDK-8155823, Add date-time patterns 'v' and 'vvvv’: ‘v’ and ‘vvvv’ are LDML
    formats to indicate “generic non-location format”, e.g. “Pacific Time”, as
    opposed to the “generic location format” with specifies a city, like
    “Los Angeles Time”.
  - JDK-8148949, DateTimeFormatter pattern letters ‘A’, ’n’, ’N’: although LDML
    doesn’t specify formats ’n’ and ’N’, it does specify ‘A’, but the current
    behaviour in Java doesn’t match that of the spec. ‘A’ is meant to represent the
    total number of milliseconds elapsed in the day, with variable width, but
    currently Java treats this as fixed with: if ‘AA’ is specified as a pattern, it
    will fail to parse any value that is further than 99 milliseconds in the day.
    ’n’ and ’N’ are just Java extensions to the standard to represent nanoseconds
    within the second, and nanoseconds within the day, respectively.
  - JDK-8079628, java.time DateTimeFormatter containing "DD" fails on three-digit
    day-of-year value: similar to the previous problem, but with ‘D’ representing
    days within a year. If one specifies “DD” as a pattern, it will fail to parse
    “123” as the 123th day of the year.
- As previously mentioned, a better alignment with the LDML will ease
  interoperability across systems, since there are multiple technologies that
  have adopted the LDML to some degree. Microsoft .NET uses LDML for general
  interexchange of locale data, and there are packages available for Node.js
  and Ruby, just to mention a few.
TimeUnit
@[https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/TimeUnit.html]
- JDK 1.5+
- Represents time durations at a given unit of granularity and
  provides utility methods to convert across units, and to perform
  timing and delay operations in these units.
Enums: DAYS HOURS MICROSECONDS MILLISECONDS MINUTES NANOSECONDS SECONDS

  void      sleep(long timeout)
  void  timedJoin(Thread thread, long timeout)
  void   timedWait(Object obj, long timeout)
  ...
ANNOTATIONS
ºpredefined annotation types in java.lang:º
- @Deprecated
- @Override
- @SuppressWarnings
- @SafeVarargs (SDK 1.? +) applied to a method/constructor,
                           asserts that the code does not perform
                           potentially unsafe operations
                           on its varargs parameter.
                           removing  related warnings

ºAnnotation types are a form of interfaceº
DECLARATION(interface is preceded by the @ sign) │ USAGE
  @Documented                                    │
  @interface ClassPreamble {                     │   @ClassPreamble (
     String   author        ()              ;    │      author         = "John Doe"      ,
     String   date          ()              ;    │      date           = "3/17/2002"     ,
     int      currentRev    () default 1    ;    │      currentRev     = 6               ,
     String   lastModified  () default "N/A";    │      lastModified   = "4/12/2004"     ,
     String   lastModifiedBy() default "N/A";    │      lastModifiedBy = "Jane Doe"      ,
     String[] reviewers     ()              ;    │      reviewers      = {"Alice", "Bob"}
  }                                              │   )
                                                 │ public class Generation3List extends Generation2List {
                                                 │     // ...
                                                 │ }
EXAMPLES
new @Interned MyObject();              ← Class instance creation expression

myString = (@NonNull String) str;      ← Type cast (1.8+)

class UnmodifiableList˂T˃ implements   ← implements clause
      @Readonly List˂@Readonly T˃
      { ... }

void monitorTemperature() throws       ← throws exception declaration
@Critical TemperatureException { ... }

@SuppressWarnings(value = "unchecked") ← Predefined standard annotations
void myMethod() { ... }
@SuppressWarnings({"unchecked", "deprecation"})
void myMethod() { ... }
META-ANNOTATTONS
(Annotations applying to other annotations)

º@Retentionº
RetentionPolicy.SOURCE: retained only in source (ignored by the compiler)
RetentionPolicy.CLASS : retained by compiler    (ignored by the JVM)
RetentionPolicy.RUNTIME:retained by JVM, can be queried at Runtime

º@Documentedº                     º@Repeatableº
- indicates that whenever the     - (1.8+)
  specified annotation is used    - targeted annotation can be applied
  those elements should be          more than once to the same
  documented using the Javadoc      declaration or type use.
  tool. (By default, annotations    Ex:
  are not included in Javadoc.)     @Author(name = "Jane Doe")
                                    @Author(name = "John Smith")
                                    class MyClass { ... }


º@Targetº                          º@Inheritedº
º(field,type,class..)º             - targeted annotation type can be inherited
- restrict targeted java-language    from the super class. (false by default.)
  elements where the annotation      When the user queries the annotation type
  can be applied:                    and the class has no annotation for this
  - ElementType.ANNOTATION_TYPE      type, the class'superclass is queried for
  - ElementType.CONSTRUCTOR          the annotation type.
  - ElementType.FIELD
  - ElementType.LOCAL_VARIABLE
  - ElementType.METHOD
  - ElementType.PACKAGE
  - ElementType.PARAMETER
  - ElementType.TYPE (1.8+)
SLF4j Logging
Simple Log Facade or abstraction for various logging frameworks
(e.g. java.util.logging, logback, log4j) allowing the end user
to plug in the desired logging framework at deployment time.

Bº(.../src/main/resources/)logback.xmlº
  ˂?xml version="1.0" encoding="UTF-8"?˃
  ˂configuration˃
    ˂root level="ALL"˃                                  ← Apply to all packages/levels
      ˂!-- ˂jmxConfigurator /˃ --˃
      ˂appender Bºname="APPENDER_FILE"ºclass="ch.qos.logback.core.rolling.RollingFileAppender"˃
          ˂file˃log˂/file˃
          ˂rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"˃
              ˂!-- daily rollover --˃
              ˂fileNamePattern˃%d{yyyy-MM-dd}.log.zip˂/fileNamePattern˃
              ˂maxFileSize˃1MB˂/maxFileSize˃
              ˂!-- keep 2 days' worth of history capped at 1MB total size --˃
              ˂maxHistory˃2˂/maxHistory˃
              ˂totalSizeCap˃2MB˂/totalSizeCap˃
          ˂/rollingPolicy˃
          ˂encoder˃
            ..(see encoder for APPENDER_STDOUT ..)
          ˂/encoder˃
      ˂/appender˃

      ˂appender Gºname="APPENDER_STDOUT"ºclass="ch.qos.logback.core.ConsoleAppender"˃
        ˂encoder˃
          ˂pattern˃%d{HH:mm:ss.SSS} | %-5level | %thread | %logger{1} |
    %m%n%rEx{full,                                      ←☞ filter "Noise" in stack trace. ºREF 1º
              java.lang.reflect.Method,                 ← remove Java reflection
              sun.reflect,
              org.apache.catalina,                      ← remove catalina engine
              org.springframework.aop,                  ← remove "almost" whole Spring framework
              org.springframework.security,             ←
              org.springframework.transaction,          ←
              org.springframework.web,                  ←
              net.sf.cglib,                             ← remove CGLIB classes.
              ByCGLIB                                   ←
            }
            ˂/pattern˃
        ˂/encoder˃
      ˂/appender˃
    ˂/root˃

    ˂root level="WARN"˃                                 ← Aply to all packages/WARN+ logs
        ˂appender-ref Bºref="APPENDER_FILE"  º/˃
        ˂appender-ref Gºref="APPENDER_STDOUT"º/˃
    ˂/root˃
  
    ˂logger name="my.company."          level="INFO" /˃ ← Detail level for packages
    ˂logger name="my.company.package01" level="DEBUG"/˃
    ˂logger name="org.eclipse.jetty"    level="WARN" /˃
 
  ˂/configuration˃   
  ºREF 1º: @[https://www.nurkiewicz.com/2011/09/logging-exceptions-root-cause-first.html]
           @[http://logback.qos.ch/manual/layouts.html]

˂/configuration˃

Bºpom.xmlº
  ˂dependency˃*
    ˂groupId˃org.slf4j˂/groupId˃
    ˂artifactId˃slf4j-api˂/artifactId˃
    ˂version˃1.7.21˂/version˃
  ˂/dependency˃
  ...
  ˂dependency˃
    ˂groupId˃ch.qos.logback˂/groupId˃
    ˂artifactId˃logback-classic˂/artifactId˃            ← add Bºlogbackº facade
    ˂version˃1.1.7˂/version˃
  Rº˂exclusions˃º
      ˂exclusion˃
        ˂groupId˃org.slf4j˂/groupId˃                    ←  Avoid error next start-up:
        ˂artifactId˃slf4j-jdk14˂/artifactId˃               "SLF4J: Class path contains multiple SLF4J bindings."
      ˂/exclusion˃                                         "   slf4j-jdk14-1.7.21.jar!...StaticLoggerBinder.class"
  Rº˂/exclusions˃º                                         "logback-classic-1.1.7.jar!...StaticLoggerBinder.class"
  ˂/dependency˃

BºExample Ussageº
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  ...
    class MyClass {
      private static final Logger log =
         LoggerFactory.getLogger(AbstractRequestHandler.class);
      ...
      if (log.isDebugEnabled()) {  ←······················· composed string "Lorem ipsum..."is built 
          log.debug("Lorem ipsum... @{} {}",  ←············ before calling log.debug.
                    "param1", "param2");                    "wrapper" if(log.isDebugEnabled())  avoid 
      }                                                     unnecesary string processing (saving can 
      ...                                                   be "huge" if log.debug is inside a loop. 


MDC: "Better Way of Logging" @[https://dzone.com/articles/mdc-better-way-of-logging-1] RºPROBLEMº: How do we related logs together originating from a (single user, single data-flow) that are processed by different threads, HTTP requests (think of Single Page Apps), or component? GºSOLUTIONº: Use mapped diagnostic context (MDC). BºMapped Diagnostic Contextº: - Built into the logging framework, it is supported by log4j, log4j2, and SL4J/logback. - Allows to capture custom ºkey/valueº diagnostic data, accessible to the appender when the log message is actually written. - MDC structure isºinternally attachedºto the executing threadº in the same way a ThreadLocal variable would be. BºMDC How To:º - At the start of the thread, fill MDC with custom information (MDC API also allows to remove info later on if it doesn't apply) - Log the message - MDCºSummarized APIº: public class MDC { publicºstaticºvoid put (String key, String val); // ← Add to ºcurrent Threadº publicºstaticºString get (String key); ºContext Mapº publicºstaticºvoid remove(String key); publicºstaticºvoid clear(); // ← Clear all entries } NOTE: child threads does not automatically inherit a copy of the current diagnostic context. - Best pattern for microservices: - Ex: //ºSTEP 1:ºOverride Qºinterceptor layerº ^^^^^^^^^^^^^^^^^ // """single place where call // execution passes through""". public class ServiceInterceptor extendsQºHandlerInterceptorAdapterº{ private final staticºLogger LOGGERº= Logger.getLogger(ServiceInterceptor.class); Qº@Overrideº public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object object) throws Exception { MDC.put("userId" , request.getHeader("UserId" )); MDC.put("sessionId ", request.getHeader("SessionId")); MDC.put("requestId" , request.getHeader("RequestId")); } //ºSTEP 2:ºChange log appender pattern to retrieve variables // stored in the MDC. ˂appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"˃ ˂layout˃ ˂Pattern˃%X{userId} %X{sessionId} %X{requestId} - %m%n˂/Pattern˃ ˂/layout˃ ˂/appender˃ Log output will look some like: 17:53:25,496 http─8080─20 INFO Service1.execute(77) U1001 ┌ sessId01 ┌ reqId_1_1 req service 1 17:53:25,497 http─8080─26 INFO Service1.execute(77) U1002 │ sessId02 ┐ │ reqId_2_1┐ req service 1 17:53:25,550 http─8080─26 INFO Service1.execute(112) U1002 │ sessId02 ┤ │ reqId_2_1┤ Req data 17:53:25,555 http─8080─20 INFO Service1.execute(112) U1001 ├ sessId01 │ ├ reqId_1_1│ Req data 17:53:25,617 http─8080─27 INFO Service2.execute(50) U1001 ├ sessId01 │ ┌│ reqId_1_2│ req service 2 17:53:25,615 http─8080─27 INFO Service2.execute(89) U1001 ├ sessId01 │ │├ reqId_1_1│ req data 17:53:25,637 http─8080─29 INFO Service2.execute(50) U1002 │ sessId02 ┤ ││ reqId_2_2│┐ req service 2 17:53:25,665 http─8080─29 INFO Service2.execute(89) U1002 │ sessId02 ┤ ││ reqId_2_1┤│ req data 17:53:25,568 http─8080─20 INFO Service1.execute(120) U1001 ├ sessId01 │ └│ reqId_1_2││ req OK 17:53:25,584 http─8080─26 INFO Service1.execute(120) U1002 │ sessId02 ┤ │ reqId_2_1┘│ req OK 17:53:25,701 http─8080─27 INFO Service2.execute(113) U1001 ├ sessId01 │ └ reqId_1_1 │ req OK ... ... ... ... ... : ... : ... : ... 17:53:25,710 http─8080─29 INFO Service2.execute(113) U1002 sessId02 ┘ reqId_2_2 ┘ req OK ...
Functional
Lambdas
Sytnax:
(parameters) -˃ expression
(parameters) -˃  { statements; }

// takes a Long, returns a String
Function˂Long, String˃ f = (l) -˃ l.toString();

// takes nothing, gives you Thread
Supplier˂Thread˃ s = Thread::currentThread;

//  takes a string as the parameter
Consumer˂String˃ c = System.out::println;

// use lambdas in streams
new ArrayList˂String˃().stream()....

// peek: Debug streams without changes
peek ( e -˃ System.out.println(e)). ...

// map: Convert every element into something
map ( e -˃ e.hashCode())...

// filter (hc -˃ (hc % 2) == 0) ...

// collect all values from the stream
collect(Collectors.toCollection(TreeSet::new))
java.utility.function
@[https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html]
@[https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html]
- JDK 1.8+
- Incomplete but good enough to cover the "shape" of many lambda expressions and
 method references representing abstract concepts like functions, actions, or predicates
- The @FunctionalInterface is used to capture design intent (not needed by compiler).
- In documenting functional interfaces, or referring to variables typed as
  functional interfaces, it is common to refer directly to those abstract concepts,
  for example using "this function" instead of "the function represented by this object".
- Each functional interface has a single abstract method, called the functional method for that
  functional interface, to which the lambda expression's parameter and return types are matched or adapted.
- Functional interfaces can provide a target type in multiple contexts, such as assignment context, method invocation,
  or cast context:
  |Predicate˂String˃ p = String::isEmpty;           // Assignment context
  |stream.filter(e -˃ e.getSize() ˃ 10)...          // Method invocation context
  |stream.map((ToIntFunction) e -˃ e.getSize())...  // Cast context

Defined functions in 1.8
────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────
           Interface Summary                │           Interface Description
────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────────────
                  BiConsumer‹T,U›           │opt. accepting two input arguments and returns no result
  (|Double|Int|Long)Consumer‹T›             │opt. accepting a single (Object|double|int|long)input argument and returns no result
Obj(Double|Int|Long)Consumer‹T›             │opt. accepting an object-valued and a (double|int|long)-valued argument, and returns no result
────────────────────────────────────────────│────────────────────────────────────────────────────────────────────────────────
        (|Double|Long|Int)Function‹(T,)R›   │func. that accepts an (T|double,long,int) argument and produces a result
       (|Double|Long)ToIntFunction          │func. that accepts a (T|double|long)argument and produces an int-valued result
(ToDouble|ToLong|ToInt|)BiFunction‹(T,)U,R› │func. that accepts two arguments and produces an (T,double,long,int) result.
           To(Double|Long)Function‹T›       │func. that produces a (double|long)-valued result
(Int|Long|Double)To(Int|Long|Double)Function│func. that accepts a (int|long|double) argument and produces a (int|long|double) result
────────────────────────────────────────────│────────────────────────────────────────────────────────────────────────────────
 (|Int|Long|Double)UnaryOperator‹T›         │op. on a single (T|int|long|double) operand that produces a result of the same type
(Double|Long|Int|)BinaryOperator‹T›         │op. upon two (T|int|long|double) operands and producing a result of the same type
────────────────────────────────────────────│────────────────────────────────────────────────────────────────────────────────
                BiPredicate‹T,U›            │predicate (boolean-valued function) of two arguments
(|Int|Long|Double)Predicate‹T›              │predicate (boolean-valued function) of one (T|int|long|double) argument
────────────────────────────────────────────│────────────────────────────────────────────────────────────────────────────────
(|Boolean|Int|Long|Double)Supplier(‹T›)     │supplier of (T|Boolean|Int|long|double) results
────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────
Collections
UUID: 78f67bbf-3150-4c06-a48c-9b61ff350aea
Collection Decission Tree
                                  ┌──────────┐
                                  │  Allows  │
                    ┌─── YES ─────┤Duplicates├──  NO  ───────┐
                    │   List to   └──────────┘  Set to       │
                    │  be selected              be selected  │
                    │                                        v
                    v                                    ┌───────────┐☜ order established at
        ┌─────────────────────┐                          │ Maintains │  write time
        │  Unknown number     │                          │ºINSERTIONº│
   ┌─NO─┤of elements will be  ├YES─┐           ┌───YES───┤  ºORDERº? ├──NO──┐  order requested
   │    │added and/or index   │    │           │         └───────────┘      │  at read time
   │    │based search will not│    │           v                            ↓  ☟
   │    │be frequent?         │    │     QºLinkedHashSetº           ┌────────────┐
   │    └─────────────────────┘    │                                │ Mantains   │
   v                               v                           ┌─NO─┤ºREAD ORDERº├YES┐
BºArrayListº           BºLinkedListº                           │    │(alpha,...)?│   │
                                                               │    └────────────┘   │
                                                               │                     │
                                                               v                     v
                                                          QºHashSetº           QºTreeSetº

   Comparative
Standard Rºnon-concurrentº SDK:
       ┌──────────────────────────────────────────────────────────────────────────────────────────
       │                                IMPLEMENTATIONS
       ├──────────────────────────────────────────────────────────────────────────────────────────
       │ Hash Table        │ Resizable Array   │Balanced Tree │ Linked List │ HashTable+LinkedList
       │                   │                   │              │             │
┌──────┼───────────────────┼───────────────────┼──────────────┼─────────────┼─────────────────────
│˂Set˃ │ HashSet           │                   │  TreeSet     │             │ LinkedHashSet
│      │                   │                   │              │             │
├──────┼───────────────────┼───────────────────┼──────────────┼─────────────┼─────────────────────
│˂List˃│                   │ ArrayList         │              │ LinkedList  │
│      │                   │ Vector            │              │ LinkedList  │
├──────┼───────────────────┼───────────────────┼──────────────┼─────────────┼─────────────────────
│˂Map˃ │ HashMap,Hashtable │                   │  TreeMap     │             │ LinkedHashMap
└──────┴───────────────────┴───────────────────┴──────────────┴─────────────┴─────────────────────
ºINTERFACESº
@[http://download.oracle.com/javase/6/docs/api/java/util/HashSet.html]
@[http://download.oracle.com/javase/6/docs/api/java/util/TreeSet.html]
@[http://download.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html]
@[http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html]
@[http://download.oracle.com/javase/6/docs/api/java/util/LinkedList.html]
@[http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html]
@[http://download.oracle.com/javase/6/docs/api/index.html]
@[http://download.oracle.com/javase/6/docs/api/java/util/TreeMap.html]
@[http://download.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html]


ref
┌─────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┐
│Collection       │ Thread-safe                ┃          YOUR DATA              ┃           OPERATIONS    ALLOWED       │
│                 │ alternative                ┃─────────────────────────────────┃───────────────────────────────────────┤
│class            │                            ┃Individu│Key-val.│Duplica│Primite┃ Iteration Order │Fast │ Random Access │
│                 │                            ┃elements│  pairs │element│support┃FIFO │Sorted│LIFO│'has'│By  │By   │By  │
│                 │                            ┃        │        │support│       ┃     │      │    │check│Key │Val  │Idx │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│HashMap          │ ConcurrentHashMap          ┃        │YES     │       │       ┃     │      │    │YES  │ YES│     │    │
│                 │                            ┃        │        │       │       ┃     │      │    │     │    │     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│SortedMap        │ ?                          ┃        │YES     │       │       ┃     │      │    │?    │ YES│     │    │
│                 │                            ┃        │        │       │       ┃     │      │    │     │    │     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│NavigableMap @1  │ ?                          ┃        │YES     │       │       ┃     │      │    │?    │ YES│     │    │
│                 │                            ┃        │        │       │       ┃     │      │    │     │    │     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│HashBiMap(Guava) │ Maps.syncrhonizedBiMap     ┃        │YES     │       │       ┃     │      │    │YES  │ YES│YES  │    │
│                 │ (new HashBiMap())          ┃        │        │       │       ┃     │      │    │     │    │     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│ArrayListMultimap│ Maps.synchronizedMultiMap  ┃        │YES     │YES    │       ┃     │      │    │YES  │ YES│     │    │
│   (Guava)       │ (new ArrayListMultimap())  ┃        │        │       │       ┃     │      │    │     │    │     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│LinkedHashMap    │ Collections.syncrhonizedMap┃        │YES     │       │       ┃YES  │      │    │YES  │ YES│     │    │
│                 │ (new LinkedHashMap())      ┃        │        │       │       ┃     │      │    │     │    │     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│TreeMap          │ ConcurrentSkipListMap      ┃        │YES     │       │       ┃     │YES   │    │YES  │ YES│     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│Int2IntMap       │                            ┃        │YES     │       │YES    ┃     │      │    │YES  │ YES│     │YES │
│(Fastutil)       │                            ┃        │        │       │       ┃     │      │    │     │    │     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│ArrayList        │ CopyOnWriteArrayList       ┃YES     │        │YES    │       ┃YES  │      │YES │     │    │     │YES │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│HashSet          │ Collections.newSetFromMap  ┃YES     │        │       │       ┃     │      │    │YES  │    │YES  │    │
│                 │ (new ConcurrentHashMap())  ┃        │        │       │       ┃     │      │    │     │    │     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│IntArrayList     │                            ┃YES     │        │YES    │YES    ┃YES  │      │YES │     │    │     │YES │
│(Fastutil)       │                            ┃        │        │       │       ┃     │      │    │     │    │     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│PriorityQueue    │ PriorityBlockingQueue      ┃YES     │        │YES    │       ┃     │YES   │    │     │    │     │    │
┼─────────────────┼────────────────────────────┃────────┼────────┼───────┼───────┃─────┼──────┼────┼─────┼────┼─────┼────┤
│ArrayDeque       │ ArrayBlockingQueue         ┃YES     │        │YES    │       ┃YES  │      │YES │     │    │     │    │
└─────────────────┴────────────────────────────┃────────┴────────┴───────┴───────┃─────┴──────┴────┴─────┴────┴─────┴────┘

 Collection class │  Random access by idx/key │ Search/Contains │ Instert
 ─────────────────┼───────────────────────────┼─────────────────┼───────────
 ArrayList        │  O(1)                     │ O(n)            │ O(n)
 HashSet          │  O(1)                     │ O(1)            │ O(1)
 HashMap          │  O(1)                     │ O(1)            │ O(1)
 TreeMap          │  O(log(n))                │ O(log(n))       │ O(log(n))

@1 NavigableMap: SortedMap with additional methods for finding entries
                 by their ordered position in the key set.
                 So potentially this can remove the need for iterating
                 in the first place - you might be able to find the
                 specific entry you are after using the higherEntry,
                 lowerEntry, ceilingEntry, or floorEntry methods. The
                 descendingMap method even gives you an explicit method
                 of reversing the traversal order.
Initialization
ºINITIALIZING A LISTº
final List˂String˃ myList =                  ← final forbid re-asigning the list,
      Arrays.asList("one", "two", "three");     but its content is still mutable
      myList.add("four");

final List˂String˃ myInmmutableList =        ← inmutable version (thread safe)
      Collections.unmodifiableList(myList);

ºINITIALIZING A MAPº
final Map˂String,String˃ myMap =             ← Mutable map (even if 'final' used)
      new HashMap˂String,String˃();
        myMap.put("k1", "k2");
        myMap.put("v1", "v2");
final Map˂String,String˃ myInmutableMap =    ← Inmutable version of map
      Collections.unmodifiableMap(temp);

final HashMap˂String,String˃ data =          ← Java 7+
      HashMapBuilder.build(
          "k1","v1",                         ← must have an even number of elements
          "k2","v2");

final Map˂String, String˃ test =             ← Java 9+
      Map.of("k1", "k2", "v1", "v2");        ← must have an even number of elements

final Map˂String, String˃ test2 =            ← Java 9+
      Map.ofEntries( entry("k1", "k2"),...);

final Map˂String, String˃ test =             ← Guava ImmutableMap
      ImmutableMap.of("k1","v1", ...);         works only with up to 5 key/value pairs

final Map˂String, String˃ test =             ← Guava ImmutableMap alternative
      ImmutableMap.˂String, String˃builder()
      .put("k1", "v1")
      .put("k2", "v2")
      ...
      .build();
Walk-over/iterate
ºfor collection walkº
 │for (
 │     int idx = 0;
 │     idx ˂ºcollectionºOº.lengthº;
 │     idx++) {
 │  //r*WARN:
 │  //  - Very slow for LinkedLists*
 │  //  - Faster for other List implementations
 │  type array_element =ºcollectionºOº.get(idx);º
 │}

 │for (                                                │ for (
 │     Iterator iterator =ºcollectionºOº.iterator()º;  │      iterable_type iterable_element Oº:collectionº
 │     Oºiterator.hasNext();º) {                       │     ) {
 │  //ºBest option when removing/modifying elementsº/  │   //ºBest option when NOT remov./modify. elementsº
 │  type type = (type) Oºiterator.next()º;             │   ...
 │}                                                    │ }


ºSTREAMS (Java 8+)º
ºcollectionºOº.forEachº((Oºitº) -˃ {
    System.out::println(Oºitº)
});
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 Shorter alternative:
ºcollectionºOº.forEachº(System.out::println);

ºWALK-OVER/ITERATE A MAPº

ºentrySet Java 5+º                         | ºUSING ITERATORSº                           | ºUSING FOR-EACHº
 Map˂String, String˃ map = ...             |  Iterator˂Map.Entry˂Integer, Integer˃˃ºitº= |  long i = 0;
 for (                                     |      map.entrySet()Oº.iterator()º;          |  for (
      Map.Entry˂String, String˃ Oºentryº : |  while (ºitºOº.hasNext()º) {                |       Map.Entry˂Integer, Integer˃ pair :
     ºmapºOº.entrySet()º)                  |      Map.Entry˂Integer, Integer˃ pair =     |         ºmyMapºOº.entrySet()º) {
 {                                         |       ºitºOº.next()º;                       |    log.debug( "{}:{}"      ,
   log.debug( "{}:{}"          ,           |    log.debug( "{}:{}"      ,                |             pair.getKey()  ,
            Oºentryº.getKey()  ,           |             pair.getKey()  ,                |             pair.getValue() );
            Oºentryº.getValue());          |             pair.getValue() );              |  }
 }                                         |  }

ºforEach (java 8+)º                        |ºiterating over keySetº          | ºfor + Map.Entryº
 final long[] i = {0};                     | long i = 0;                     |  for (
 ºmapºOº.forEachº((k, v) -˂ i[0] += k + v);| Iterator˂Integer˃ itr2 =        |     Iterator˂Map.Entry˂Integer, Integer˃˃
                                           |    mapOº.keySet().iterator()º;  |        entries = map.entrySet().iterator() ;
                                           | while (itr2.hasNext()) {        |     entries.hasNext();
                                           |     Integer key = itr2.next();  |     ) {
                                           |     i += key + map.get(key);    |   Map.Entry˂Integer, Integer˃
                                           | }                               |      entry = entries.next();
                                                                             |   log.debug( "{}:{}"      ,
                                                                             |           entry.getKey()  ,
                                                                             |           entry.getValue() );
                                                                             |  }
|ºStream API (1.8+)º              |ºStream API parallel (1.8+)º
| final long[] i = {0};           | final long[] i = {0};
| ºmapºOº.entrySet().stream()º    | ºmapºOº.entrySet().stream()º.
|  .forEach(                      |   parallel()*.forEach(e -˃
|    ...e.getKey(), e.getValue()  |    ... e.getKey() , e.getValue()
| );                              | )
java.util.Collections
Utility class
@[https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html]
- Utility class with static methods that operate on or return collections

Collections.EMPTY_LIST // The empty (immutable) list
Collections.EMPTY_MAP  // The empty (immutable) map
Collections.EMPTY_SET  // The empty (immutable) set

Enumeration  Collections.emptyEnumeration()  // Returns an enumeration that has no elements.
Iterator     Collections.emptyIterator()     // Returns an iterator that has no elements.
List         Collections.emptyList()         // Returns the empty list (immutable)                                              .
ListIterator Collections.emptyListIterator() // Returns a list iterator that has no elements.
Map          Collections.emptyMap()          // Returns the empty map (immutable)                                              .
Set          Collections.emptySet()          // Returns the empty set (immutable)                                              .



boolean      Collections.addAll(Collection c, T... elements)           Adds all elements to collection 'c'
Queue        Collections.asLifoQueue(Deque deque)                      deque → LIFO Queue view
int          Collections.binarySearch(List list, T key)                Searches key into List using binary search.
int          Collections.binarySearch(List list, T key, Comparator c)  Searches key into List using binary search an comparator.

Collection   Collections.checkedCollection(Collection c, Class type)   Returns a dynamically typesafe view of input collection/list/...
List         Collections.checkedList(List list, Class type)
Map          Collections.checkedMap
                         (Map m, Class keyType, Class valueType)
Set          Collections.checkedSet(Set s, Class type)
SortedMap    Collections.checkedSortedMap
                         (SortedMap m, Class keyType, Class valueType)


SortedSet    Collections.checkedSortedSet(SortedSet s, Class type)
void         Collections.copy(List dest, List src)                     Copies src list elements to dest list
boolean      Collections.disjoint(Collection c1, Collection c2)        true if c1/c2 have no elements in common.

Enumeration  Collections.enumeration(Collection c)                     Returns an enumeration over the specified collection.

void         Collections.fill(List list, T obj)                        Replaces all of the elements of the specified list with the specified element.
int          Collections.frequency(Collection c, Object o)             Returns the number of elements in the specified collection equal to the specified object.
int          Collections.indexOfSubList(List source, List target)      Returns the starting position of the first occurrence of the specified target list within the specified source list, or -1 if there is no such occurrence.
int          Collections.lastIndexOfSubList(List source, List target)  Returns the starting position of the last occurrence of the specified target list within the specified source list, or -1 if there is no such occurrence.
ArrayList    Collections.list(Enumeration e)                           Returns an array list containing the elements returned by the specified enumeration in the order they are returned by the enumeration.
T            Collections.max(Collection coll)                          Returns the maximum element of the given collection, according to the natural ordering of its elements.
T            Collections.max(Collection coll, Comparator comp)         Returns the maximum element of the given collection, according to the order induced by the specified comparator.
T            Collections.min(Collection coll)                          Returns the minimum element of the given collection, according to the natural ordering of its elements.
T            Collections.min(Collection coll, Comparator comp)         Returns the minimum element of the given collection, according to the order induced by the specified comparator.
List         Collections.nCopies(int n, T o)                           Returns an immutable list consisting of n copies of the specified object.
Set          Collections.newSetFromMap(Map map)                        Returns a set backed by the specified map.
boolean      Collections.replaceAll(List list, T oldVal, T newVal)     Replaces all occurrences of one specified value in a list with another.
void         Collections.reverse(List list)                            Reverses the order of the elements in the specified list.
Comparator   Collections.reverseOrder()                                Returns a comparator that imposes the reverse of the natural ordering on a collection of objects that implement the Comparable interface.
Comparator   Collections.reverseOrder(Comparator cmp)                  Returns a comparator that imposes the reverse ordering of the specified comparator.
void         Collections.rotate(List list, int distance)               Rotates the elements in the specified list by the specified distance.
void         Collections.shuffle(List list)                            Randomly permutes the specified list using a default source of randomness.
void         Collections.shuffle(List list, Random rnd)                Randomly permute the specified list using the specified source of randomness.
Set          Collections.singleton(T o)                                Returns an immutable set containing only the specified object.
List         Collections.singletonList(T o)                            Returns an immutable list containing only the specified object.
Map          Collections.singletonMap(K key, V value)                  Returns an immutable map, mapping only the specified key to the specified value.
void         Collections.sort(List list)                               Sorts the specified list into ascending order, according to the natural ordering of its elements.
void         Collections.sort(List list, Comparator c)                 Sorts the specified list according to the order induced by the specified comparator.
void         Collections.swap(List list, int i, int j)                 Swaps the elements at the specified positions in the specified list.
Collection   Collections.synchronizedCollection(Collection c)          Returns a synchronized (thread-safe) collection backed by the specified collection.
List         Collections.synchronizedList(List list)                   Returns a synchronized (thread-safe) list backed by the specified list.
Map          Collections.synchronizedMap(Map m)                        Returns a synchronized (thread-safe) map backed by the specified map.
Set          Collections.synchronizedSet(Set s)                        Returns a synchronized (thread-safe) set backed by the specified set.
SortedMap    Collections.synchronizedSortedMap(SortedMap m)            Returns a synchronized (thread-safe) sorted map backed by the specified sorted map.
SortedSet    Collections.synchronizedSortedSet(SortedSet s)            Returns a synchronized (thread-safe) sorted set backed by the specified sorted set.
Collection   Collections.unmodifiableCollection(Collection c)          Returns an unmodifiable view of the specified collection.
List         Collections.unmodifiableList(List list)                   Returns an unmodifiable view of the specified list.
Map          Collections.unmodifiableMap(Map m)                        Returns an unmodifiable view of the specified map.
Set          Collections.unmodifiableSet(Set s)                        Returns an unmodifiable view of the specified set.
SortedMap    Collections.unmodifiableSortedMap(SortedMap m)            Returns an unmodifiable view of the specified sorted map.
SortedSet    Collections.unmodifiableSortedSet(SortedSet s)            Returns an unmodifiable view of the specified sorted set.
Fastutil
- Fast and compact type-specific collections for Java
  Great default choice for collections of primitive types,
  like int or long. Also handles big collections with more than 2
  31 elements well.
Eclipse Collections
(Originated from Goldman Sachs gs-collection:
 @[https://github.com/goldmansachs/gs-collections])
- Features you want with the collections you need
  Previously known as gs-collections, this library
  includes almost any collection you might
  need: primitive type collections, multimaps,
  bidirectional maps and so on.
Guava Collections
- Google Core Libraries for Java 6+
  Perhaps the default collection library for Java
  projects. Contains a magnitude of convenient
  methods for creating collection, like fluent
  builders, as well as advanced collection types
˂˂Enumeration˃˃(1.0) vs ˂˂Iterator˃˃(1.7)
@[https://stackoverflow.com/questions/948194/difference-between-java-enumeration-and-iterator]

- both interfaces will give successive elements

- Iterators allow the caller to remove elements from
  the underlying collection during the iteration with
  well-defined semantics.
  (additional remove method)
- Iterators Method names have been improved.

- Iterators are fail-fast:
  - If thread A changes the collection, while
       thread B is traversing it, the iterator implementation
       will try to throw a ConcurrentModificationException
       (best effort since it can not always be guaranteed)
  - The fail-fast behavior of iterators can be used only to
    detect bugs sin the best effort doesn't warrant its trigger.
  - newer 'concurrent' collections will never throw it.
    Reading thread B will traverse the collection "snapshot" at
    the start of read.



-ºIterator should be preferred over Enumerationº
  taking the place of Enumeration in collections framework


  Enumeration     │ Iterator
  ────────────────┼────────────
  hasMoreElement()│ hasNext()
  nextElement()   │ next()
                  │ remove() ← optional: not implemented in many classes
NIO
NIO (1.4+)
- Replaced OLD blocking IO based on [ byte/char, read-or-write streams ]
┌──────────┐     ┌──────────────┐                                  
│ºCORE NIOº│     │ºNON─BLOCKINGº│                                  
├──────────┴───┐ ├──────────────┴────────────────────────────────┐ 
│ ─BºCHANNELS º│ │· a thread requests a channel the intention    │ 
│  ─ read/write│ │  to read/write data into a buffer:            │ 
│ ─BºBUFFERS  º│ │  · While the channel moves data into/from     │ 
│ ─BºSELECTORSº│ │   the buffer, the thread continues another job│ 
└──────────────┘ │  · When data is ready, the thread is notified │ 
                 └───────────────────────────────────────────────┘ 
Channel  : File,Datagram/UDP,Socket/TCP,ServerSocket,...           
Buffer of: Byte|Char|Double|Float|Int|Long|Short|MappedByte)Buffer 
                                                                   
                                                                   
┌───────────────┐
│ ºNON─CORE NIOº│
├───────────────┴─────────────────────────────────────────────────────┐
│ ─ components like Pipe and FileLock can be considered               │
│   "utility classes" supporting the first three ones.                │
│                                                                     │
│ ─ "SELECTORS" objects monitor one+ channels for events              │
│   (connection opened, data arrived, ..):                            │
│   ─ Thus, a single thread can monitor multiple channels for data.   │
│     (Very handy if app has many connections/Channels/clients open   │
│     but with low traffic on each connection.                        │
│   ─ To use selectors:                                               │
│     ─ Instantiate the selector                                      │
│     ─ Register one+ channels with it                                │
└─────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────────────────────────┐
│ºBUFFERº                                                                                          │
│ ºATTRIBUTESº                                            ºMETHODSº                                │
│          ┌─────────────────┬───────────────────────────┐ ┌─────────────┬───────────────────────┐ │
│          │ºwriteºmode      │ ºreadºmode                │ │rewind()     │                       │ │
│ ┌────────┼─────────────────┴───────────────────────────┤ │             │                       │ │
│ │capacity│ fixed size of memory block implementing     │ ├─────────────┼───────────────────────│ │
│ │        │ the buffer                                  │ │clear()      │                       │ │
│ ├────────┼─────────────────┬───────────────────────────┤ │compact()    │                       │ │
│ │position│ starts at 0,    │ starts at 0 (after "flip")│ ├─────────────┼───────────────────────│ │
│ │        │ increase at each│ increase at each          │ │mark()       │"bookmark position"    │ │
│ ├────────┼─────────────────┼───────────────────────────┤ │reset()      │ and return "bookmark" │ │
│ │   limit│ element written │ element read              │ ├─────────────┼───────────────────────│ │
│ │        │ == capacity     │ == last written position  │ │equals()     │using only the         │ │
│ └────────┴─────────────────┴───────────────────────────┘ │compareTo()  │remaining-to-read bytes│ │
│                                                          │             │for the computation    │ │
│                                                          └─────────────┴───────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────────────────────────────────
│ºSEQUENCE TO READ/WRITE DATAº                  ┌───────┐
│try (  /* try-with 1.7+ */                     │SUMMARY│
│  RandomAccessFile GºaFileº =                  ├───────┴──────────────────────────
│    new RandomAccessFile("nio-data.txt", "rw") │-1 ) Write data into the Buffer
│) throws IOException {                         │-2 ) Call buffer.ºflip()º
│  FileChannel BºinChannelº =                   │     switch writing/reading mode
│    GºaFileº.getChannel();                     │-3 ) Read data out of the Buffer
│                                               │-4a) buffer.clear();  ← alt1: clear all buffer
│  ByteBuffer Oºbufº=                           │-4b) buffer.compact() ← alt2: clear only data read
│      ByteBuffer.allocate(48 /*capacity*/);    ├────────────────────────────────────
│                                               │ channelIn → (data) → buffer
│                                               │ buffer    → (data) → channelOut
│  int ºbytesReadº=                             └────────────────────────────────────
│       BºinChannelº.read(Oºbufº);  // ← Oºbufº now
│                                          in write mode
│Rºwhileº (ºbytesReadº != -1)
│Rº{º
│    Oºbufº.ºflipº();               // ← Oºbufº now
│    while(Oºbufº.hasRemaining()){         in read mode
│        System.out.print(
│           (char) Oºbufº.get()     // ← alt.1: read 1 byte
│        );                                     at a time
│        // channel2.write(Oºbufº)  // ← alt.2: read data
│    }                                         in channel2
│    Oºbufº.clear();                // ← make buffer
│                                        ready-for-writing
│    ºbytesReadº = BºinChannelº     // ← Oºbufº now
│                    .read(Oºbufº);        in write mode
│Rº}º
│}
└──────────────────────────────────────────────────────────────────────────────────────────────────

┌────────────────┐
│ºSCATTER-GATHERº│
├────────────────┴─────────────────────────────────┬──────────────────────────────────────────────────┐
│ ºscattering channel readº                        │ºscattering-write to channelº                     │
│ - channel → read to → buffer1, buffer2, ....     │ - buffer1, buffer2, ...→ write to → channel      │
│ - Ex:                                            │ - ex:                                            │
│   ByteBuffer header = ByteBuffer.allocate(128);  │   ByteBuffer header = ByteBuffer.allocate(128);  │
│   ByteBuffer body   = ByteBuffer.allocate(1024); │   ByteBuffer body   = ByteBuffer.allocate(1024); │
│   ByteBuffer[] OºbufferArrayº = { header, body };│   ByteBuffer[] OºbufferArrayº = { header, body };│
│ Bºchannelº.read(OºbufferArrayº);                 │ Bºchannelº.write(OºbufferArrayº);                │
│            ^^^^                                  │                                                  │
│ fill up one buffer before moving on to the next  │                                                  │
│ (*not suited for undefined size messages)        │                                                  │
└──────────────────────────────────────────────────┴──────────────────────────────────────────────────┘

BºCHANNEL-TO-CHANNELº
 -ºIf one the the channels is FileChannelº:
   - FileChannelºtransferTo()/transferFrom()º can be used to move data between channels
   RºWARN:ºSome SocketChannel implementations may transfer only the data the SocketChannel
     has ready in its internal buffer here and now
   ┌─────────┐
   │Examples.│
   ├─────────┴───────────────────────────────────┬─────────────────────────────────────────────┐
   │  FileChannelGºfromChannelº=                 │  FileChannelGºfromChannelº=                 │
   │     (new RandomAccessFile("from.txt", "rw"))│     (new RandomAccessFile("from.txt", "rw"))│
   │     .getChannel(),                          │     .getChannel(),                          │
   │  FileChannel BºtoChannelº=                  │  FileChannel BºtoChannelº=                  │
   │     (new RandomAccessFile(  "to.txt", "rw"))│     (new RandomAccessFile(  "to.txt", "rw"))│
   │     .getChannel();                          │     .getChannel();                          │
   │  long count    =GºfromChannelº.size();      │  long count    = ;                          │
   │BºtoChannelºº.transferFromº(                 │GºfromChannelºº.transferToº(                 │
   │     GºfromChannelº,                         │      0 /*position*/,                        │
   │       0       , // posit.in dest-file to    │    GºfromChannelº.size() /*count*/,         │
   │                 // start writing from       │    BºtoChannelº);                           │
   │       maxCount  /* max-bytes to transfer*/  │                                             │
   │  );                ^^^^^^^^^                │                                             │
   │                    constrained by data      │                                             │
   │                    in source                │                                             │
   └─────────────────────────────────────────────┴─────────────────────────────────────────────┘
API tree
JDK 8
./java/nio/
           Bits ByteOrder CharBufferSpliterator
           ByteBufferAs(Char|Double|Float|...)Buffer(B|L|...
           (|Float|Double|StringChar)Buffer
           HeapByteBuffer Heap(Byte|Char|...)Buffer(R) HeapCharBuffer
           (Int|Long|...)Buffer
           (Mapped|Direct)ByteBuffer(R)
           Direct(Byte|Char|Double|...)Buffer

./java/nio/channels/
                    Channel Channels CompletionHandler FileLock MembershipKey Pipe Selector SelectionKey
                    Asynchronous(|Byte)Channel
                    AsynchronousChannelGroup
                    AsynchronousFileChannel
                    AsynchronousServerSocketChannel
                    AsynchronousSocketChannel
                    (Byte|Datagram|File|GatheringByte|Interruptible|Multicast|
                     Network|ReadableByte|ScatteringByte|SeekableByte|Selectable|
                     ServerSocket|Socket|WritableByte)Channel
                   /spi/Abstract(Interruptible|Selectable)Channel
                        Abstract(SelectionKey|Selector)
                        (AsynchronousChannel|Selector)Provider

./java/nio/charset/
                   Charset(|Decoder|Encoder) StandardCharsets
                   CoderResult CodingErrorAction
                  /spi/CharsetProvider

./java/nio/file/attribute/AclEntry(|Flag|Permission|Type)
                          (|AclFile|BasicFile|DosFile|File|
                            FileOwner|FileStore|PosixFile|
                            UserDefinedFile)AttributeView
                          (BasicFile|DosFile|PosixFile)Attributes
                          FileAttribute FileTime
                          GroupPrincipal

                          UserPrincipal(LookupService)
./java/nio/file/
                AccessMode CopyMoveHelper CopyOption DirectoryStream Files
                LinkOption LinkPermission Path        PathMatcher        Paths
                SecureDirectoryStream
                File(Store|System|Systems|TreeIterator|TreeWalker|VisitOption|Visitor|VisitResult)
                SimpleFileVisitor
                OpenOption    Standard(Copy|Open)Option
                StandardWatchEventKinds
                StandardWatchEventKinds$StdWatchEventKind
                TempFileHelper
                Watchable      Watch(Event|Key|Service)
                spi/FileSystemProvider
                    FileTypeDetector
SELECTORS
@[https://docs.oracle.com/javase/7/docs/api/java/nio/channels/Selector.html]

- A Selector allows a single thread to manage multiple channels 
  (network connections), by examining which ones are ready for 
  connect,accept,read,write

- A channel that "fires an event" is also said to be "ready" for that event.

ºREGISTERING A SELECTORº                              │ºUSING SELECTORSº
ºAND ASSIGNING CHANNELSº                              │
    │  Selector BºselectoRº = Selector.open();        │ ºSTEP 1º
    │  channel.configureBlocking(false);              │  call one of the select() methods
    │          ^^^^^^^^^^^^^^^^^^^^^^^^               │  (upon registering 1+ channels)
    │   //     non-blocking-mode required             │  int select(long mSecTimeout) ← block until channel/s ready
    │   // RºWARN:º FileChannel can NOT be switched   │             └────(optional)┘
    │   //   into NON-blocking mode and so            │  int selectNow()              ← Don't block even if none read
    │   //   they can NOT be used with selectors.     │  └┬┘
┌───→GºSelectionKey keyº = channel.register(          │  indicates how many channels became ready since last select() call.
│   │    Bºselectorº,                                 │
│   │    SelectionKey.OP_READ |                       │ ºSTEP 2º
│   │    SelectionKey.OP_WRITE);                      │  examine ready channels returned by select like:
│   │                 ^^^^^^^                         │  Set˂SelectionKey˃ selectedKeys =
│   │                 Or-set of interest:             │                    BºselectoRº.OºselectedKeys()º;
│   │                 OP_CONNECT / OP_ACCEPT          │  Iterator˂SelectionKey˃ keyIterator =
│   │                 OP_READ    / OP_WRITE           │                    selectedKeys.iterator();
│   │  ^^^^^^^^^^^^^^^^                               │  while(keyIterator.hasNext()) {
│   │                                                 │    GºSelectionKey keyº= keyIterator.next();
│ ┌─→Gºkeyº.attach(extraInfoObject);                  │      //  "cast to proper channel"
│ │ │  Object attachedObj =                           │             if (Gºkeyº.isAcceptable ()) {
│ │ │     selectionKey.attachment();                  │        ... connection accepted by ServerSocketChannel
│ │ │                                                 │      } else if (Gºkeyº.isConnectable()) {
│ │ │                                                 │        ... connection established with remote server
│ │ │ // After selection                              │      } else if (Gºkeyº.isReadable   ()) {
│ │ │ // ^^^^^^^^^^^^^^^                              │        ... channel ready for reading
│ │ │ // explained later                              │      } else if (Gºkeyº.isWritable   ()) {
│ │ │                                                 │        ... channel ready for writing
│ │ │ // Alternative 1:                               │      }
│ │ │ int OºreadySetº= Gºkeyº.readyOps();             │      keyIterator.remove();
│ │ │ boolean isAcceptable  =                         │  }
│ │ │         OºreadySetº ⅋ SelectionKey.OP_ACCEPT;   │ ºSTEP 3º
│ │ │ ...                                             │Bºselectorº.close()
│ │ │ // Alternative 2:                               │            ^^^^^
│ │ │ Gºkeyº.isAcceptable();                          │   must be called after finishing ussage,
│ │                                                   │   invalidating all SelectionKey instances
│ └─── (optional) user attached object,               │   registered with this Selector.
│      handy way to recognize a given                 │   The channels themselves are not closed.
│      channel, provide extra info
│      (buffer/s,...)
│
└─── Gºkeyº can be queried like:
       intOºinterestSetº = Gºkeyº.interestOps()*;
       boolean isInterestedInAccept
           = OºinterestSetº ⅋ SelectionKey.OP_ACCEPT;

  NOTE:
  - A thread blocked by a call to select() can be forced to leave the select() method,
     even if no channels are yet ready by having a different thread call
     the BºselectoRº.ºwakeup()º method on the Selector which the first thread has
     called select() on:
     - The thread waiting inside select() will then return immediately.
     - If a different thread calls wakeup() and no thread is currently
       blocked inside select(), the next thread that calls select()
       will "wake up" immediately.
FileChannel
- Java NIO FileChannel: channel connected to a file allowing to
      read data from  and write data to a file.
- A FileChannel canNOT be set into non-blocking mode:
  It always runs in blocking mode

- Reading from FileChannel (Writting to buffer):
  |/* You cannot open a FileChannel directly,
  | * first you obtain a FileChannel via an (Input|Output)Stream or a RandomAccessFile
  | */
  |RandomAccessFile GºaFileº     = new RandomAccessFile("data/nio-data.txt", "rw");
  |// Reading from channel
  |try (  /* try-with 1.7+ */
  |  RandomAccessFile GºaFileº = new RandomAccessFile("data/nio-data.txt", "rw")
  |) throws IOException {
  |  FileChannel BºinChannelº = GºaFileº.getChannel();
  |
  |  ByteBuffer Oºbufº = ByteBuffer.allocate(48 /* capacity*/);
  |
  |  int ºbytesReadº = BºinChannelº.read(Oºbufº); // Oºbufº now in write mode
  |  while (ºbytesReadº != -1) {
  |    Oºbufº.flip();                            // Oºbufº now in read mode
  |    while(Oºbufº.hasRemaining()){
  |        // alt. read data directly, 1 byte at a time
  |        System.out.print((char) Oºbufº.get());
  |        // alt. read data in channel
  |        // anotherChannel.write(Oºbufº)
  |    }
  |
  |    Oºbufº.clear(); //make buffer ready for writing
  |    ºbytesReadº = BºinChannelº.read(Oºbufº); // Oºbufº now in write mode
  |  }

- Writing to a FileChannel (reading from buffer)
  | String newData = "......" + System.currentTimeMillis();
  | ByteBuffer Oºbufº = ByteBuffer.allocate(48);
  | Oºbufº.clear();
  | Oºbufº.put(newData.getBytes());
  | Oºbufº.flip(); // change buffer from write to read
  | ºwhile(Oºbufº.hasRemaining()) {º channelOº.writeº(Oºbufº); º}º
  | channel.close();


- FileChannel Position
  | long pos = fileChannel.position(); // obtain current position
  | fileChannel.position(pos +123); // change position

   - If you set the position after the end of the file,
     and try to read from the channel, you will get -1
   - If you set the position after the end of the file,
     and write to the channel, the file will be expanded
     to fit the position and written data. This may result
     in a "file hole", where the physical file on
     the disk has gaps in the written data.

- FileChannel Size
  | long fileSize = fileChannel.size();
                                ^^^^^^
                            size of the file
                            connected to channel

- FileChannel (file) Truncate
  | fileChannel.truncate(1024 /*length*/);

- FileChannel Force:
  flushes all unwritten data from the channel and OS cache to the disk
  | channel.force(true /* flush also file meta-data like permissions....*/);
Pipe
- Pipe: one-way data connection between two threads
  └"=="  source channel   ← One threads writes to sink
        +  sink channel   ← One threads reads from source
  Ex:
    ByteBuffer Oºbufº = ByteBuffer.allocate(48);
    Oºbufº.clear();
    Oºbufº.put(newData.getBytes());
  
    // WRITING TO PIPE
    Pipe pipe = Pipe.open();
    Pipe.SinkChannel sinkChannel = pipe.sink();
    String newData = "..." + System.currentTimeMillis();
    Oºbufº.flip();
    while(Oºbufº.hasRemaining()) { sinkChannel.write(Oºbufº); }
  
    // READING FROM A PIPE
    To read from a Pipe you need to access the source channel. Here is how that is done:
    Pipe.SourceChannel sourceChannel = pipe.source();
    int ºbytesReadº = BºinChannelº.read(buf2);
SocketChannel
  There are two ways a SocketChannel can be created:
  
  // Opening a SocketChannel
  SocketChannel socketChannel = SocketChannel.open();
  socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
  
  // Reading (writing to buffer)
  ByteBuffer Oºbufº = ByteBuffer.allocate(48);
  int ºbytesReadº = socketChannel.read(Oºbufº); // If -1 is returned, the end-of-stream is reached (connection is closed)
  
  // Writing to a SocketChannel
  String newData = "..." + System.currentTimeMillis();
  ByteBuffer Oºbufº = ByteBuffer.allocate(48);
  Oºbufº.clear();
  Oºbufº.put(newData.getBytes());
  Oºbufº.flip();
  while(Oºbufº.hasRemaining()) { channel.write(Oºbufº); }
  
  socketChannel.close();
Non-blocking Mode
- socketChannelº.configureBlocking(false)º;
- Calls to connect(), read() and write() will not block
- In non-blocking mode connect() calls may return before
  the connection is established:
  - To determine whether the connection is established
    use finishConnect() like this:

  | socketChannel.configureBlocking(false);
  | socketChannel.connect(
  |   new InetSocketAddress("http://jenkov.com", 80));
  |
  | while(! socketChannel.finishConnect() ){
  |     //wait, or do something else...
  | }

NOTE: non-blocking works much better with Selector's
ServerSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

serverSocketChannel.socket().bind(new InetSocketAddress(9999));
serverSocketChannel.configureBlocking(false);

while(true){
    SocketChannel socketChannel =
            serverSocketChannel.accept(); // in blocking mode waits until incoming connection arrives
    if(socketChannel != null /* always false in blocking mode */){
        //do something with socketChannel...
    }

    //do something with socketChannel...
}

serverSocketChannel.close()
Datagram Channel
- Since UDP is a connection-less network protocol, you cannot just
  by default read and write to a DatagramChannel like you do from
  other channels. Instead you send and receive packets of data

  | DatagramChannel channel = DatagramChannel.open();
  | channel.socket().bind(new InetSocketAddress(9999));
  |
  | ByteBuffer Oºbufº = ByteBuffer.allocate(48);
  | Oºbufº.clear();
  | // WARN: if read data is bigger than buffer size remaining data is discarded silently
  | channel.receive(Oºbufº);
  |
  | // Write to channel
  | String newData = "..." + System.currentTimeMillis();
  | Oºbufº.clear();
  | Oºbufº.put(newData.getBytes());
  | Oºbufº.flip();
  |
  |
  | // WARN:  No notice is received about packet delivery (UDP does not make any guarantees)
  | int bytesSent = channel.send(Oºbufº, new InetSocketAddress("jenkov.com", 80));
  |
  | // Alternatively you can "Connect" to a Specific Address. Since UDP is connection-less,
  | // connecting to a remote address just means that the DatagramChannel can only send/receive
  | // data packets from a given specific address.
  | channel.connect(new InetSocketAddress("jenkov.com", 80));
  | int ºbytesReadº = channel.read(Oºbufº);
  | int bytesSent = channel.write(Oºbufº);
NonBlocking Server
REF:
- @[http://tutorials.jenkov.com/java-nio/non-blocking-server.html]
- @[https://github.com/jjenkov/java-nio-server]
- Non-blocking IO Pipelines:
read-write pipeline: ºchannelInº → selector → component → ... → componentN → ºchannelOutº
read-only  pipeline: ºchannelInº → selector → component → ... → componentN
write-only pipeline:                        component → ... → componentN → ºchannelOutº
Note: It is the component that initiates reading of data from the Channel via the Selector
read-pipeline read from stream/channelIn and split data into messages like:

Data   → Message → Message
Stream   Reader    Stream

-ºA blocking Message Reader/Writer is simpler, since itº
 ºhas never to handle situations where no data was readº
 ºfrom the stream, or where only a partial message wasº
 ºread from the stream and message parsing needs to beº
 ºresumed later.º
-ºThe drawback of blocking is the requirement of separateº
 ºthreads for each parallel stream, which is a problem if theº
 ºserver has thousands of concurrent connectionsº
- Each thread will take between 320K (32 bit JVM) and
  1024K (64 bit JVM) memory for its stack
- Queue messages can be used to reduce the problem. However,
  this design requires that the inbound client  streams
  send data reasonably often and input is processed fast.
   If the inbound client stream may be inactive for longer periods
  attached to hidden clients, a high number of inactive
  connections may actually block all the threads in the thread
  pool.
  That means that the server becomes slow to respond or even
  unresponsive.
- A non-blocking IO pipeline can use a single thread to
  read messages from multiple non-blocking streams.
    When in non-blocking mode, a stream may return 0 or more
  bytes when you attempt to read data from it.
  When you call select() or selectNow() on the Selector it
  gives you only the SelectableChannel instances ("connected
  clients") that actually has data to read.

OºComponent ──→ STEP 1: select() ──→ Selector ←──┬─→ Channel1º
Oº    ↑                                │         ┼─→ Channel2º
Oº    └───← STEP 2: ready channels ←───┘         └─→ Channel3º


- Reading Partial Messages: Data sent by "ready" channels can
  contain fractions/incomplete messages:
  - The Message Reader looks needs to check if the data block
    contains at least one full message, adn storing partial ones.
    (maybe using one Message Reader per Channel to avoid mixing messages)
  - To store Partial Messages two design should be considered:
    - copy data as little as possible for better performance
    - We want full messages to be stored in consecutive byte to
      make parsing messages easier
  - Some protocol message formats are encoded using a TLV format
    (Type, Length, Value).
    Memory management is much easier since we known immediately
    how much memory to allocate for the message. No memory is
    wasted at the end of a buffer that is only partially used.
  - The fact that TLV encodings makes memory management easier is
    one of the reasons why HTTP 1.1 is such a terrible protocol.
    That is one of the problems trying to be fixed in HTTP 2.0 where
    data is transported in LTV encoded frames.
  - Writing Partial Messages: channelOut.write(ByteBuffer) in
    non-blocking mode gives no guarantee about how many of the
    bytes in the ByteBuffer is being written. The method returns
    how many bytes were written, so it is possible to keep track
    of the number of written bytes.
  - Just like with the Message Reader, a Message Writer is used
    per channel to handle all the details.
   (partial writes, message queues, resizable buffers, protocol aware tricks,...)

-ºAll in all a non-blocking server ends up with three "pipelines" itº
 ºneeds to execute regularly:º
  - The read pipeline which checks for new incoming data from
    the open connections.
  - The process pipeline which processes any full messages received.
  - The write pipeline which checks if it can write any outgoing
    messages to any of the open connections
Path (1.7+)
- Represents a file/directory path in the FS
- Similar to java.io.File but with some minor differences.
// Ussage
import java.nio.file.Path;
import java.nio.file.Paths;

Path path = Paths.get("/var/lib/myAppData/myfile.txt");
System.out.println("Current dir:"+Paths.get(".").toAbsolutePath());
Files
- java.nio.file.Files provides several methods for manipulating FS files/directories:
- uses Path instances:

boolean pathExists = ºFiles.existsº(pathInstance,
            new LinkOption[]{ LinkOption.NOFOLLOW_LINKS});

Path newDir = ºFiles.createDirectoryº(path);

ºFiles.copyº(sourcePath, destinationPath);
ºFiles.copyº(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);

ºFiles.moveº(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);

ºFiles.deleteº(path);

Files.walkFileTree(Paths.get("data"), new FileVisitor() {
  @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
    // ...  return FileVisitResult.CONTINUE; // CONTINUE TERMINATE SKIP_SIBLINGS SKIP_SUBTREE
  }

  @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
    // ...  return FileVisitResult.CONTINUE; // CONTINUE TERMINATE SKIP_SIBLINGS SKIP_SUBTREE
  }

  @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
    // ...  return FileVisitResult.CONTINUE; // CONTINUE TERMINATE SKIP_SIBLINGS SKIP_SUBTREE
  }

  @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
    // ...  return FileVisitResult.CONTINUE; // CONTINUE TERMINATE SKIP_SIBLINGS SKIP_SUBTREE
  }
});
Asyncrhonous FileChannel 1.7+
read/write data from/to files asynchronously

Path path = Paths.get("data/test.xml");
AsynchronousFileChannel fileChannel =
    AsynchronousFileChannel.open(path, StandardOpenOption.READ);

// Reading Data, Alt 1: Via a Future
  Future operation = fileChannel.read(/*ByteBuffeR*/buffer, 0 /*start position to read from */);
  while(!operation.isDone());  // WARN: not a very efficient use of the CPU
  buffer.flip();
  byte[] data = new byte[buffer.limit()];
  buffer.get(data);
  System.out.println(new String(data));
  buffer.clear();

// Reading Data Alt 2: Via a CompletionHandler
fileChannel.read(buffer, position, buffer, new CompletionHandler() {
    @Override
    public void completed(Integer numBytesRead, ByteBuffer attachment) {
        // NOTE: attachment is a reference to the third parameter passed to .read read()
        System.out.println("numBytesRead = " + numBytesRead);
        attachment.flip();
        byte[] data = new byte[attachment.limit()];
        attachment.get(data);
        System.out.println(new String(data));
        attachment.clear();
    }

    @Override
    public void failed(Throwable exc, ByteBuffer attachment) { ...  }
});

// Writing data:
AsynchronousFileChannel fileChannel =
    AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);

// Writing Data: Alt 1: Via a Future
  ...
  Future operation = fileChannel.write(buffer, position);
  buffer.clear();
  while(!operation.isDone());

// Writing Data: Alt 2: Via CompletionHandler
...
  fileChannel.write(buffer, position, buffer, new CompletionHandler˂Integer, ByteBuffer˃() {

      @Override public void completed(Integer result, ByteBuffer attachment) { /* ... */ }
      @Override public void failed   (Throwable exc , ByteBuffer attachment) { /* ... */ }
  });
OkHTTP
@[https://square.github.io/okhttp/]

- Code recipes available at
@[https://square.github.io/okhttp/recipes/]
  - modern http client for Java 8+ and Android 5.0+ (API level 21+). 

- "efficient by default".

- HTTP/2 support allows all requests to the same host to share a socket.
- Connection pooling reduces request latency (if HTTP/2 isn’t available).
- Transparent GZIP shrinks download sizes.
- Response caching avoids the network completely for repeat requests.

- OkHttp perseveres when the network is troublesome: it will silently recover
  from common connection problems.
BºIf target service has multiple IP addresses OkHttp will attempt alternate
  addresses if the first connect failsº.
BºThis is necessary for IPv4+IPv6 and for services hosted in redundant data centersº.

   OkHttp supports modern TLS features (TLS 1.3, ALPN, certificate pinning). It
  can be configured to fall back for broad connectivity.

- request/response API is designed with ºfluent builders and immutabilityº
-.support for synch and sync+callback API.


- Ex: Balancing connections with OKHttp:
  https://medium.com/wandera-engineering/kubernetes-network-load-balancing-using-okhttp-client-54a2db8fc668
okIO
complements java.nio
@[https://github.com/square/okio]
- makes it much easier to access, store, and process your data.
- It started as a component of OkHttp, the capable HTTP client
  included in Android. It's well-exercised and ready to solve new problems.
Debug&Profile
jcmd
man 1 jcmd

- Sends diagnostic command requests to a running JVM.

- It must be used on the same machine on which the JVM is running and 
have the same effective user and group identifiers that were used to 
launch the JVM.

- Ussage Summary:
  $ jcmd [-l]  # ← print list of running Java PIDs.
  
  $ jcmd pid|main-class PerfCounter.print  ← Send diagnostic command PerfCounter.print to PID JVM
                                             $ jcmd help to see the list of available diagnostic command

  $ jcmd pid|main-class -f filename        ←  file from which to read diagnostic commands to send to JVM

  $ jcmd pid|main-class command[ arguments]

 Ex:
 $º$ jcmd $PID º
  → The following commands are available:
  → Compiler.CodeHeap_Analytics
  → Compiler.codecache
  → Compiler.codelist
  → Compiler.directives_add
  → Compiler.directives_clear
  → Compiler.directives_print
  → Compiler.directives_remove
  → Compiler.queue
  → GC.class_histogram
  → GC.class_stats
  → GC.finalizer_info
  → GC.heap_dump
  → GC.heap_info
  → GC.run
  → GC.run_finalization
  → JFR.check
  → JFR.configure
  → JFR.dump
  → JFR.start
  → JFR.stop
  → JVMTI.agent_load
  → JVMTI.data_dump
  → ManagementAgent.start
  → ManagementAgent.start_local
  → ManagementAgent.status
  → ManagementAgent.stop
  → Thread.print
  → VM.class_hierarchy
  → VM.classloader_stats
  → VM.classloaders
  → VM.command_line
  → VM.dynlibs
  → VM.flags
  → VM.info
  → VM.log
  → VM.metaspace
  → VM.native_memory
  → VM.print_touched_methods
  → VM.set_flag
  → VM.stringtable
  → VM.symboltable
  → VM.system_properties
  → VM.systemdictionary
  → VM.uptime
  → VM.version
  → help

JVisualVM (standard on the JDK)
@[https://visualvm.github.io/]
- displays memory usage and other useful things:
- Visual tool integrating commandline JDK tools and
  lightweight profiling capabilities.
- RºWARN: Deprecated by Flight Recorder?º
  @[https://stackoverflow.com/questions/40272599/do-java-mission-control-and-flight-recorder-deliver-same-functionality-as-visual]
  Flight Recorder works both for development and production
  while JVisualVM has performance hits

Deadlock analysis
@[https://avaldes.com/java-thread-deadlock-example-and-thread-dump-analysis-using-visualvm/]
Flight Recorder
https://www.youtube.com/watch?v=azshjd5Vsv0
- created originally in 1998 by students from the Royal 
  Institute of Technology in Stockhoml as part of the JRockit JVM 
  distribution by Appeal Virtual Machines.
- built directly into the JDK, it Bºcan monitor performance accuratelyº. 
  with about only Bº2% overhead(production friendly)º. 
  ┌─────────────────────┐
  │ JRE      ┌────────┐ │                      Mission Control (Visual Console) 
  │          │ JFR    ----→ myRecording.jfr  → |JMC| (it can also connect
  │          │ engine │ │   - compact log of          directly to running JVM)
  │          └────────┘ │   OºJVM eventsº
  └─^───────────────────┘
  ┌─┴───────────────────────────────────────
  $ java ... Oº-XX:StartFlightRecordingº ...


  - As a result the metrics provided by default in JFR are aimed more 
    towards the JVM's raw operations, vs high-level metrics like 
    request/response times like:
    - advanced garbage collection analysis:
       Unlike common tools report garbage collection statistics,
       JFR details on what garbage was collected and who threw it away.
       allowing developers to improve performance by:
       - identifying what to improve,
       - realize when tunning garbage collection is the wrong solution.

- Free of use starting with Java 11+
- Backported to OpenJDK 8
  @[https://www.infoq.com/news/2019/11/jfr-openjdk-8/]
- (JEP 328)


CRaSH shell
Features:
- Connect to any JVM running CRaSH through SSH, telnet or web.
- Monitor and/or use virtual machine resources:
  JMX, database access, threads, memory usage, ...
- Embed CRaSH and expose services via a command line interface.
- Hot reload provides rapid development.
- Officially embedded as Spring Boot remote shell.

Eclipse Mem.Analizer
@[https://www.eclipse.org/mat/]
"""he Eclipse Memory Analyzer is a fast and feature-rich Java heap
  analyzer that helps you find memory leaks and reduce memory consumption.

  Use the Memory Analyzer to analyze productive heap dumps with hundreds of
  millions of objects, quickly calculate the retained sizes of objects, see
  who is preventing the Garbage Collector from collecting objects, run a
  report to automatically extract leak suspects.
"""

It can provide reports and warnings similar to:
  (REF: @[https://www.youtube.com/watch?v=5joejuE2rEM])
  The classloader/component "sum.misc.Launcher$AppClassLoader@0x123412"
  occupies 607,654,123(38,27%) bytes.
RºThe memory is accumulated in one instanceº of
  java.util.LinkedList$Entry loaded by 'system class loader'
SystemTap+Java
@[https://laurent-leturgez.com/2017/12/22/profiling-java-application-with-systemtap/]
[root@spark ~]# yum install systemtap systemtap-runtime-java

JAVA                                              SystemTap Profiling script
package com.premiseo;                             #!/usr/bin/env stap

import java.lang.*;                               global counter,timespent,t
import java.io.BufferedReader;
import java.io.InputStreamReader;                 probe begin {
import java.io.IOException;                         printf("Press Ctrl+C to stop profiling\n")
                                                    counter=0
class Example {                                     timespent=0
   public static void                             }
     loop_and_wait(int n)
         throws InterruptedException{             probe java("com.premiseo.Example").class("Example").method("loop_and_wait")
         System.out.println(                      {
            "Waiting "+n+"ms... Tick");             counter++
         Thread.sleep(n);                           t=gettimeofday_ms()
     }                                            }

   public static void main(String[] args) {       probe java("com.premiseo.Example").class("Example").method("loop_and_wait").return
      System.out.println("PID = "+                {
          java.lang.management.                     timespent+=gettimeofday_ms()-t
              ManagementFactory.                  }
                  getRuntimeMXBean().
                     getName().split("@")[0]);    probe end {
      System.out.println(                            printf("Number of calls for loop_and_wait method: %ld \n",    counter)
              "Press key when ready ...");           printf("Time Spent in method loop_and_wait: %ld msecs \n", timespent)
                                                  }
      try {                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        BufferedReader in =                       profiling loop_and_wait:
           new BufferedReader(                    counts number of times the
              new InputStreamReader(System.in));  loop_and_wait method has been called,
        String next = in.readLine();              and the time spent in this method execution.
      } catch (IOException ioe) {
        ioe.printStackTrace();
      }

      try {
        for (int i=0;i˂10;i++) {
           loop_and_wait(1000);
        }
      } catch (InterruptedException ie) {
        ie.printStackTrace();
      }
   }
}
Fast Thread
@[https://fastthread.io/]
- Java Thread Dump Analyzer
- Troubleshoot JVM crashes, slowdowns, memory leaks, freezes, CPU Spikes
- Instant RCA (don't wait for Vendors)
- Machine Learning
- Trusted by 4000+ enterprises
Free Service
gceasy.io
@[https://gceasy.io/]
- machine learning guided Garbage collection log analysis tool.
  GCeasy has in-built intelligence to auto-detect problems in the JVM ⅋ Android
  GC logs and recommend solutions to it.
  - Solve Memory ⅋ GC problems in seconds
  - Get JVM Heap settings recommendations
  - Machine Learning Algorithms
  - Trusted by 4,000+ enterprises
  - Free
  - A perfect DevOps tool!
    Made by the developers, for the developers
libperfagent (perf agent)
Extracted from:
  "Apache Spark @Scale: A  production use case"
@[https://engineering.fb.com/core-data/apache-spark-scale-a-60-tb-production-use-case/]
  ...  Tools we used to find performance bottleneck
  - Spark Linux Perf/Flame Graph support: Although the two tools 
    above are very handy, they do not provide an aggregated view of CPU 
    profiling for the job running across hundreds of machines at the same 
    time. On a per-job basis, Bºwe added support for enabling Perf º
  Bºprofiling (via libperfagent for Java symbols) and can customize the º
  Bºduration/frequency of sampling. The profiling samples are aggregatedº
  Bºand displayed as a Flame Graph across the executors using our       º
  Bºinternal metrics collection framework.                              º
Uber JVM Profiler: Tracing at scale
@[https://eng.uber.com/jvm-profiler/]
Our JVM Profiler supports a variety of use cases, most notably making 
it possible to instrument arbitrary Java code. Using a simple 
configuration change, the JVM Profiler can attach to each executor in 
a Spark application and collect Java method runtime metrics. Below, 
we touch on some of these use cases:
- Right-size executor: We use memory metrics from the JVM Profiler 
  to track actual memory usage for each executor so we can set the 
  proper value for the Spark “executor-memory” argument.
- Monitor HDFS NameNode RPC latency: We profile methods on the 
  class org.apache.hadoop.hdfs...ClientNamenodeProtocolTranslatorPB 
  in a Spark application and identify long latencies on NameNode calls. 
  We monitor more than 50 thousand Spark applications each day with 
  several billions of such RPC calls.
- Monitor driver dropped events: We profile methods like 
  org.apache.spark.scheduler.LiveListenerBus.onDropEvent to trace 
  situations during which the Spark driver event queue becomes too long 
  and drops events.
- Trace data lineage: We profile file path arguments on the method 
org.apache.hadoop.hdfs...getBlockLocations and 
org.apache.hadoop.hdfs...addBlock 

Uber JVM Profiler provides a Java Agent to collect various metrics 
and stacktraces for Hadoop/Spark JVM processes in a distributed way, 
for example, CPU/Memory/IO metrics.

Uber JVM Profiler also provides advanced profiling capabilities to 
trace arbitrary Java methods and arguments on the user code without 
user code change requirement. This feature could be used to trace 
HDFS name node call latency for each Spark application and identify 
bottleneck of name node. It could also trace the HDFS file paths each 
Spark application reads or writes and identify hot files for further 
optimization.

This profiler is initially created to profile Spark applications 
which usually have dozens of or hundreds of processes/machines for a 
single application, so people could easily correlate metrics of these 
different processes/machines. It is also a generic Java Agent and 
could be used for any JVM process as well.
Concurrent Programming
External Links
@[https://cs.nyu.edu/~lerner/spring12/Preso03-JavaPrimitives.pdf]
1uSec Thread sync
REF:
@[https://software.rajivprab.com/2018/04/29/myths-programmers-believe-about-cpu-caches/]
"""
  ...
- If caches are so in-sync with one another, why do we need volatiles at all in
  languages like Java?

  That’s a very complicated question that’s better answered elsewhere, but
  let me just drop one partial hint. Data that’s read into CPU registers, is
  not kept in sync with data in cache/memory. The software compiler makes all
  sorts of optimizations when it comes to loading data into registers, writing it
  back to the cache, and even reordering of instructions. This is all done
  assuming that the code will be run single-threaded. Hence why any data that is
  at risk of race-conditions, needs to be manually protected through concurrency
  algorithms and language constructs such as atomics and volatiles.

 ☞In the case of Java volatiles, part of the solution is to force all
  reads/writes to bypass the local registers, and immediately trigger cache
  reads/writes instead. As soon as the data is read/written to the L1 cache, the
  hardware-coherency protocol takes over and provides guaranteed coherency across
  all global threads. Thus ensuring that if multiple threads are reading/writing
  to the same variable, they are all kept in sync with one another. And this is
  how you can achieve inter-thread coordination in as little as 1ns.
"""
Concurrency Basics
- Concurrency problems arise from the desire to use CPU resources more efficiently. Non concurrent
  applications (single threaded/single process) are complete Touring machines that can potentially
  solve any problem with enough time and memory. In practice having a CPU assigned to single thread
  will be very inneficient since the CPU will stand-by while the thread is waiting for input/output
  operations. Also, many algorithms allows to split processed data in isolated regions that can be
  processed in parallel by different CPU/CPU cores
- Concurrent tries to solve the problem of multiple independents CPUs or threads accesing share
  resources (memory)
- Locks is the simples concurrent primite to protect code or data from concurrent
  access in situations where there are many threads of execution. Locks can be classified like:
  | According to lock ussage:
  |    Cooperative   A thread is encouraged (but not forced) to cooperate with other
  |                  threads by adquiring a lock before accessing the associated data
  |
  |    Mandatory     a thread trying to access an already locked resource will throw
  |                  an exception
  | _________________________________________________
  | According to lock rescheduing strategy:
  |    Blocking      The OS block the thread requesting the lock and rescheduled another thread
  |
  |    Spinlock      The thread waits in a loop until the requested lock becomes available.
  |                  It's more efficient if threads are blocked for very short time (smaller than
  |                  the time needed by the OS to reschedule another thread into the current CPU)
  |                  It's inneficient if the lock is held for a long time since a CPU core is
  |                  waisted on the spinlock loop
  | _________________________________________________
  | According to granularity: (measure of the ammount of data the lock is protecting)
  |    Coarse        Protect large segments of data (few locks). Results in less lock overhead
  |                  for a single thread, but worse performance for many threads running concurrently
  |                  (most thread will be lock-contended waiting for share resource access)
  |
  |    Fine          Protect small amounts of data. Require more lock instances reducing lock
                     contention

- Locks require CPU atomic instructions for efficient implementations suchs as
    "test-and-set", "fetch-and-add", or "compare-and-swap", whether there are blocking
    (managed by the OS) or spinlocks (managed by the thread)
- Uniprocessors can just disable interruptions to implement locks, while multiprocessors
  using shared-memory will require complex hardware and/or software support
-  ºMonitors wrap mutex-locks with condition variables (container of threads waitingº
   ºfor certain condition)º. They are implemented as thread-safe classes
monitors
-ºObject providing Mutual exclusion of threads to shared resourcesº
- simplest form of synchronization:
  alternatives include:
  - reads and writes of volatile variables
  @[https://avaldes.com/examining-volatile-keyword-with-java-threads-example/]
    typically used in applications when one thread will
    be making changes to the variables and the others all reading or
    consumers of the data. If you have multiple threads making changes to
    the data it will be best to stick with synchronized block or use
    java.util.concurrent library package.
    (volatile is actually simpler than monitors, but not universal)
    Important Points on Volatile Variables:
    - Volatile variables areºnot cached in registers or in cachesº:
     ºAll read and writes are done in main memory, never done thread-locallyº
    - Example Ussage: status flags used in spin loops
    - Volatile keywordºguarantees visibility and orderingº
  - use of classes in the java.util.concurrent package
- Monitors also have the ability to wait(block a thread) for a certain condition
  to become true, and signal other threads that their condition has been met
-ºMonitors provide a mechanism for threads to temporarily give up exclusive access inº
 ºorder to wait for some condition to be met, before regaining exclusive access and  º
 ºresuming their taskº
- each java object can be used as a monitor.
- Methods/blocks of code requiring mutual exclusion must be explicitly marked with the
Oºsynchronized keywordº:
  - The synchronized statement computes a reference to an object;
    it then attempts to perform a lock action on that object's monitor and does not
    proceed further until the lock action has successfully completed.
    After the lock action has been performed, the body of the synchronized statement
    is executed. If execution of the body is ever completed, either normally or abruptly,
    an unlock action is automatically performed on that same monitor.
  - RºWARNº: The Java programming language neither prevents nor requires detection
    of deadlock conditions.
- Instead of explicit condition variables, each monitor(/object) is equipped with
  a single wait queue in addition to its entrance queue.
- All waiting is done on this singleOºwait queueº and allOºnotify/notifyAllº
  operations apply to this queue.

ºmonitorº   enter
 ┌───┬─────── │ ──┐   - Wait sets are manipulated solely and atomically
 │  notified  v   │     through the methods
 │ ─────→         │    ºObject.waitº     : move     running thread    → wait-queue
 │   │        O   │    ºObject.notifyº   : move     thread  wait-queue → enter-queue
 │ O │        O   │    ºObject.notifyAllº: move all threads wait-queue → enter-queue
 │ O ├─────── │ ──┴─┐   Interrupt??      : put thread into to monitor enter-queue
 │ O │        v     │
 │  ←──wait   O     │  - In timed-waits  : internal action removes thread to enter-queue?
 │   │     (Running │                      after at least milliseconds plus nanoseconds
 └───┤      thread) │  - Implementations are permitted (but discouraged),
     │              │    to perform "spurious wake-ups"
     │    leave     │
     └────── │ ─────┘  O = Thread (Instruction Pointer + Stack Pointer + ...?)
             v

CountDownLatch
java.util.concurrent
@[https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html]

- Object allowing 1+ threads to wait until a 1+ operations are completed in other threads.

- A CountDownLatch is a versatile synchronization tool and can be 
  used for a number of purposes. A CountDownLatch initialized with a 
  count of one serves as a simple on/off latch, or gate: all threads 
  invoking await wait at the gate until it is opened by a thread 
  invoking countDown(). A CountDownLatch initialized to N can be used 
  to make one thread wait until N threads have completed some action, 
  or some action has been completed N times.

- A useful property of a CountDownLatch is that it doesn't require 
  that threads calling countDown wait for the count to reach zero 
  before proceeding, it simply prevents any thread from proceeding past 
  an await until all threads could pass.

- Sample usage: Here is a pair of classes in which a group of worker threads use two countdown latches:
  The first is a start signal that prevents any worker from proceeding until the driver is ready for them to proceed;
  The second is a completion signal that allows the driver to wait until all workers have completed.

  -  Ex. 1:
     class Driver { // ...

       class Worker implements Runnable {
         private final CountDownLatch OºstartSignalº;
         private final CountDownLatch BºdoneSignalº;
         Worker(CountDownLatch OºstartSignalº, CountDownLatch BºdoneSignalº) {
          Oºthis.startSignal = startSignalº;
          Bºthis.doneSignal  = doneSignalº;
         }
         public void run() {
            try {
            OºstartSignalº.await();
              doWork();
            BºdoneSignalº.countDown();   // ← Decrease count
            } catch (InterruptedException ex) {} // return;
         }

         void doWork() { ... }
       }

       void main() throws InterruptedException {
         CountDownLatch OºstartSignalº= newºCountDownLatch(1);º// ← initialized with a given count
         CountDownLatch BºdoneSignalº = newºCountDownLatch(N);º// ← "
                                                             // ← Consider alsoºCyclicBarrierº(reset after count),
         for (int i = 0; i ˂ thread_number ; ++i) {
           new Thread(
                new Worker(
                    OºstartSignalº,
                    BºdoneSignalº
           )).start();
         }
         ...
       OºstartSignalº.countDown();      // ← Decrease count. count cannot be reset.
         doSomethingElse();
       BºdoneSignalº.await();           // ← block until current count reaches zero
                                            Thread is released. Any subsequent invocations
                                            return immediately.
       }
     }

  -  Ex. 2:
     - divide problem into N parts
     - describe each part with a Runnable executing a portion,
     - queue all Runnables to an Executor.
     - When all sub-parts are complete, coordinating-thread will "pass" through await.

     class Driver2 { // ...
       class WorkerRunnable implements Runnable {
         private final CountDownLatch OºdoneSignalº;
         WorkerRunnable(
            CountDownLatch OºdoneSignalº, ...) {
          Oºthis.doneSignal = doneSignalº;
         }

         public void run() {
            try {
              doneSignal.countDown();
            } catch (InterruptedException ex) {} // return;
         }

         void doWork() { ... }
       }
       void main() throws InterruptedException {
         CountDownLatchOºdoneSignalº= new CountDownLatch(N);
         Executor e = ...

         for (int i = 0; i ˂ N; ++i) // create and start threads
           e.execute(new WorkerRunnable(OºdoneSignalº, i));

       OºdoneSignalº.await();           // wait for all to finish
       }
     }
Scheduling: Runnables|Callables Executors
@[https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html]
 ┌────────────┐ │ ┌───────────────┐  │
 │˂˂Runnable˃˃│ │ │˂˂Callable˂V˃˃˃│  │          ˂˂Executor˃˃
 │────────────│ │ │───────────────│  │               ↑
 │+run()      │ │ │+call()        │  │       ˂˂ExecutorService˃˃  ← managed collection of threads
 └────────────┘ │ └───────────────┘  │               ↑              available to execute tasks
       ^        │ (util.concurrent)  │    ┌──────────┴──────────────┐
       │        │                    │    │                         │
 ┌────────────┐ │ Allows to return   │ AbstractExecutorService  ˂˂ScheduledExecutorService˃˃
 │   Thread   │ │ a result/Exception │    ↑                         ↑
 │────────────│ │ to the thread      │ ThreadPoolExecutor           │
 │+run()      │ │ triggering the     │    ↑                         │
 │+start()    │ │ Callable           │ ScheduledThreadPoolExecutor ─┘
 │+sleep()    │ │                    │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 │....        │ │                    │ Prefered to "old" java.util.timer:
 │────────────│ │                    │  - Timer can be sensitive to system clock changes
 └────────────┘ │                    │  - Timer has only one execution thread. Long-running
                                          task can delay other tasks. ScheduledThreadPoolExecutor
                                          can be configured with "N" threads.
                                        - Runtime exceptions thrown kill the Timer thread.
                                          ScheduledThreadExecutor catches Runtime Ex,
                                          and allows to handle them by overriding afterExecute
                                          method from ThreadPoolExecutor). Onley the Task throwing
                                          the exception will be canceled.

- ˂˂ExecutorService˃˃(Thread Pool) ussage:
  - Alt 1: use an implementation of the interface,
           such as ThreadPoolExecutor or ScheduledThreadPoolExecutor.
           an the ˂˂ExecutorService˃˃Instance.execute(/*Runnable */runnableInstance)
           to add a Runnable task to thread pool.
           -  Will execute the task at some time in the
              future in a new thread, in a thread pool, or
              in the calling thread, depending on the implementation
           ˂˂java.util.concurrent.ExecutorService˃˃
           + public     void      shutdown(); // Initiates orderly shutdown of pool
           + public ˂T˃ Future˂T˃ submit(Callable˂T˃ task); // schedule callable task for execution

  - Alt 2: Use factory methods in the 'Executors' class:
          - Write worker thread class implementing ˂˂Runnable˃˃ run()
          Executors.newSingleThreadExecutor()
          Executors.newFixedThreadPool(int numThreads)
          Executors.newCachedThreadPool(): // ← unbounded pool, with automatic reclamation
          Executors.newSingleThreadScheduledExecutor()
          Executors.newScheduledThreadPool(int size)

BºExamplesº:
ºEx: CallableThreadPoolTestº                                                 ºEx: ThreadPoolTestº
 import java.util.concurrent.Callable;                                       │import java.util.concurrent.ExecutorService;
 import java.util.concurrent.*;                                              │import java.util.concurrent.Executors;
 ...                                    ┌──→public classºMyCallableThreadº   │...
 int numWorkers = 10;                   │  │    implements Callable˂String˃{ │ExecutorService pool =
 ExecutorService pool =                 │  │  MyCallableThread(int id)       │  Executors.newFixedThreadPool(10);
     Executors.newCachedThreadPool();   │  │  {                              │MyWorker[] workers =
ºMyCallableThread workers[]º =       ───┘  │    ...                          │  new MyWorker[numWorkers];
     new MyCallableThread[numWorkers];     │  }                              │for (int i = 0; i ˂ numWorkers; ++i)
 Future futures[] = new Future[numWorkers];│                                 │  pool.execute(new MyWorker(i+1));
                                           │  public String call() {         │pool.shutdown();
 for (int i = 0; i ˂ numWorkers; ++i) {    │    Thread.sleep(1000));
    workers[i] = new MyCallableThread(i+1);│    return ""+id;
    futures[i] = pool.submit(workers[i]);  │  }
 }                                         │}
 for (int i = 0; i ˂ numWorkers; ++i) {
   try {
     System.out.println(
       futures[i].get() + " ended");
   } catch (InterruptedException ex) {
     ex.printStackTrace();
   } catch (ExecutionException ex) {
     ex.printStackTrace();
   }
 }
ForkJoinPool (1.7+)
REF: @[http://tutorials.jenkov.com/java-util-concurrent/java-fork-and-join-forkjoinpool.html]
- java.util.concurrent.ForkJoinPool  Scheduler is similar to "ExecutorService"
   but ☞Bº"it makes it easy for tasks to recursively split  work into smaller ones"º

- Bulding blocks:
  -ºForkº: Task (=="thread") that "Splits itself" into smaller subtasks,
           executing concurrently.
  
  -ºJoinº: End children tasks (=="threads") and merge results (if any).

                              ┌Task04··· CPU1 ·········┐end
                ┌Task02(fork)º┤º                 ┌────º┴º────┐
                │             └Task05··· CPU2 ···┘end º^º    │
   Task01(fork)º┤º                                    ºjoin ˃├º Task ...CPU1 ...
           ^    │             ┌Task06··· CPU3 ······┐end ºvº │
           │    └Task03(fork)º┤º                    └────º┬º─┘
           │             ^    └Task07··· CPU4 ···········─┘
           │             │                                
           │             │                               
         - There is an overhead in forks and maintaing new threads.
           Forking makes sense only for long running tasks with 
           intensive use of CPU
         - Task01, 02, 03 ºwaitº for subtasks to finish execution.

BºCreating new ForkJoinPoolº
  ForkJoinPool BºforkJoinPoolº = new ForkJoinPool(4);
                                               ^
                                  Desired level of paralellism
                                 (Desired number of threads/CPUs)


BºSubmiting tasks to ForkJoinPool schedulerº
  (very similar to how it is done in the ExecutorService). 
   
   You can submit two types of tasks:
   - QºRecursiveActionº: task not returning any result.
   - GºRecursiveTask  º: task     returning a   result.


import java.util.ArrayList;                       │import java.util.ArrayList;
import java.util.List;                            │import java.util.List;
import java.util.concurrent.RecursiveAction;      │import java.util.concurrent.RecursiveTask;
                                                  │
// QºCreating new RecursiveActionº                │// GºCreating new RecursiveTaskº
public class QºMyRecursiveActionº                 │public class GºMyRecursiveTaskº
extends QºRecursiveActionº {                      │extends GºRecursiveTaskº˂Long˃ {
  private long workLoad = 0;                      │  private long workLoad = 0;
  public MyRecursiveAction(long workLoad) {       │
      this.workLoad = workLoad;                   │  public MyRecursiveTask(long workLoad) {
  }                                               │      this.workLoad = workLoad;
                                                  │  }
  @Override                                       │
  protected void compute() {                      │  protected Long compute() {
    if(this.workLoad ˂ 16) {                      │    if(this.workLoad ˂ 16) {
      // 16 is a ºTunnable Threshold parameterº   │      // 16 is a ºTunnable Threshold parameterº
      // Do workload in current thread            │      // Process work in current thread
      return                                      │      return workLoad * 3;
    }                                             │    }
    List˂MyRecursiveAction˃ subtasks =            │    List˂MyRecursiveTask˃ subtasks =              
       Arrays.asList                              │       Arrays.asList
       ( new MyRecursiveAction(this.workLoad / 2),│       ( new MyRecursiveTask(this.workLoad / 2),
         new MyRecursiveAction(this.workLoad / 2) │         new MyRecursiveTask(this.workLoad / 2) 
       );                                         │       );
                                                  │
    for(RecursiveAction subtask : subtasks)       │    for(MyRecursiveTask subtask : subtasks)
      subtaskOº.fork()º;                          │        subtaskOº.forkº();                        
      //       ^^^^^^^                            │        //       ^^^^^^^                       
      //   Oºwork split into subtasks to beº      │        //   Oºwork split into subtasks to beº               
      //   Oºscheduled for executionº             │        //   Oºscheduled for executionº
  }                                               │
                                                  │    long result = 0;
}                                                 │    for(MyRecursiveTask subtask : subtasks) {
                                                  │        result += subtaskOº.joinº(); 
                                                  │    }
                                                  │    return result;
                                                  │  }
                                                  │}
                                                  │
 ºUSSAGE:º                                        │ºUSSAGE:º
QºMyRecursiveActionºmyRecursiveAction =           │GºMyRecursiveTaskºmyRecursiveTask =
     new MyRecursiveAction(24);                   │     new MyRecursiveTask(128);
                                                  │  long mergedResult = 
BºforkJoinPoolºOº.invoke(myRecursiveAction);º     │BºforkJoinPoolºOº.invoke(myRecursiveTask)º;
                                                  │  System.out.println("mergedResult = " + mergedResult);    


-RºForkJoinPool Detractorsº
  - @[http://coopsoft.com/ar/CalamityArticle.html]
Completable Future
@[https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html]
(Java 8+)
Esquematically:

        LOCAL SYSTEM
          ┌───────────────────────────────────────────────────────┐
          │               ┌·······(RPE Loop)··················┐   │
          │               ↓                                   ·   │
          │   ºInput º  Parse    Create      Parse  Create  → ... │
 │INPUT│  │  →ºThreadº:  Data → │Future│  →  Data →│Future│       │
 │DATA │  │    (RPEL)                                             │
          │                        │                  │           │
          │┌───────────────────────┘                  │           │
          ││ ┌────────────────────────────────────────┘           │
          ││ │ ºI/O   º   External  RºWait   º Handle    |Future| │
          ││ └→ºThreadº:  Request  →RºResposeº→Respose → .complete│
          ││                     ↓                                │
          ││   ºI/O   º          ·               ↑                │
          │└──→ºThreadº:         ·               ·                │
          └──────────────────────·───────────────·────────────────┘
                                 ·               ·      
                                 ·               ·      
                                 ·               ·      
                             ┌───↓───────────────↑─┐
                             │REMOTE SYSTEM        │
                             │                     │
                             └─────────────────────┘
- A Future that may be explicitly completed (setting its value and status),
  and may be used as a CompletionStage, supporting dependent functions and
  actions that trigger upon its completion.
- When two or more threads attempt to complete, completeExceptionally, or
  cancel a CompletableFuture, only one of them succeeds.

ºBarriers (OºallOf*):
  CompletableFuture˂Void˃[] future_list
    = new CompletableFuture[list.size()];
  int idx=0;
  log.info("Connecting plugins ...");
  for (Object el : list) {
    final CompletableFuture˂Void˃
      connectFuture = new CompletableFuture˂˃();
    asyncMethod(connectFuture);
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    The async Method at some moment must call the
    complete()
    ...
  }
  return CompletableFuture. OºallOfº(future_list);

Extracted from:
@[http://www.baeldung.com/java-completablefuture]
In asynchronous computation, actions are represented as callbacks, 
handling errors might occur at any step.

- Future: (Java 5+)
  -Represent an asynchronous computation
- CompletableFuture: (Java 8+)
  - Extends Future with methods to combine and handle errors
  - Extends the CompletionStage interface
    - Contract for an asynchronous computation step that
      can be combined with other steps.
  - About 50 different methods for composing, combining, executing 
    async computation

Using CompletableFuture as a Simple Future (no-arg constructor)

In the example below we have a method that creates a 
CompletableFuture instance, then spins off some computation in 
another thread and returns the Future immediately.

  1  public Future˂String˃ calculateAsync() throws InterruptedException {
  2      Future˂String˃ result = new CompletableFuture˂˃();
  3
  4      Executors.newCachedThreadPool().submit(() -˃ {
  5          Thread.sleep(500);
  6          completableFuture.complete("Hello");
  7          return null;
  8      });
  9
  10     return completableFuture;
  11 }
  Line 2: Alternatively when the result of computation is known:
          Future result = CompletableFuture.
             completedFuture("Hello");

  Line 6: Alternatively completableFuture.cancel(false);
  Line 5: any other mechanism can be used to compute


  1 Future completableFuture = calculateAsync();
  2
  3 // ...
  4
  5 String result = completableFuture.get();
  6 assertEquals("Hello", result);

Line 5: get() blocks until .complete("...") is called in other thread
Line 5: get()can raise
           ExecutionException: error during computation
           InterruptedException: thread executing method interrupted

4. CompletableFuture with Encapsulated Computation Logic
   (runAsync -˂˂Runnable˃˃-, supplyAsync -˂˂Supplier˃˃-)

˂˂Supplier˃˃: generic functional interface with single method 
              (zero arguments, returns value)

  1 CompletableFuture˂String˃ future
  2   = CompletableFuture.supplyAsync(/*supplier lambda*/ () -˃ "Hello")
  3 .thenApply(/* "processor" lambda */ s -˃ s + " World") // ← returns CompletableFuture
  4 .thenAccept(/*consumer lambda */
  5    s -˃ System.out.println("Computation returned: " + s));
    Line 4: Alternatively (ignrore result)
    .thenRun(/*Runnable lambda*/ () -˃ System.out.println("Computation finished."));

5. Combining Futures (monadic design pattern in functional languages)

  1 CompletableFuture˂String˃ completableFuture
  2   = CompletableFuture.supplyAsync(() -˃ "Hello")
  3     .thenCompose(
  4           s -˃ CompletableFuture.supplyAsync(() -˃ s + " World"));
  4
  5 assertEquals("Hello World", completableFuture.get());

6. Execute two independent Futures and do something with their results

  1 CompletableFuture future
  2   = CompletableFuture.supplyAsync(() -˃ "Hello")
  3     .thenCombine(CompletableFuture.supplyAsync(
  4       () -˃ " World"), (s1, s2) -˃ s1 + s2));
  5
  6 assertEquals("Hello World", future.get());

(Simpler case - nothing to do with resulting value-)
  2   = CompletableFuture.supplyAsync(() -˃ "Hello")
  3   .thenAcceptBoth(CompletableFuture.supplyAsync(
  4      () -˃ " World"), (s1, s2) -˃ log(s1 + s2));

7. Running Multiple Futures in Parallel:
   -  wait for all to execute and process combined results

  1  CompletableFuture˂String˃ future1
  2    = CompletableFuture.supplyAsync(() -˃ "Hello");
  3  CompletableFuture˂String˃ future2
  4    = CompletableFuture.supplyAsync(() -˃ "Beautiful");
  5  CompletableFuture˂String˃ future3
  6    = CompletableFuture.supplyAsync(() -˃ "World");
  7
  8  CompletableFuture˂Void˃ combinedFuture
  9    = CompletableFuture.allOf(future1, future2, future3);
  10
  11 // ...
  12
  13 combinedFuture.get();
  14
  15 String combined = Stream.of(future1, future2, future3)
  16   .map(CompletableFuture::join)
  17   .collect(Collectors.joining(" "));
  18 assertEquals("Hello Beautiful World", combined);

    Line 16: join() is similar to get, but throws unchecked exception 
    if the Future does not complete normally.

8. Handling Errors

   Instead of catching an exception in a syntactic block, the 
CompletableFuture class allows you to handle it in a special handle 
method. This method receives two parameters: a result of a 
computation (if it finished successfully) and the exception thrown 
(if some computation step did not complete normally).



Capture async exception:

  1  CompletableFuture˂String˃ completableFuture
  2    =  CompletableFuture.supplyAsync(() -˃ {
  3        ... if(errorDetected)
  4               throw new RuntimeException("Computation error!");
  6        return "Hello ";
  7    })}).handle((s, t) -˃ s != null ? s : "Hello, Stranger!");
  8
  9  assertEquals("Hello, Stranger!", completableFuture.get());
Alt:
  1  completableFuture.completeExceptionally(
  2    new RuntimeException("Calculation failed!"));
  3  ...
  4  completableFuture.get(); // ExecutionException

9. Async Methods
 - The methods without the Async postfix run next execution stage 
   using a calling thread.

 - The Async method without the Executor argument runs a step using 
   the common fork/join pool implementation of Executor that is accessed 
   with the ForkJoinPool.commonPool() method.

 - The Async method with an Executor argument runs a step using the 
   passed Executor.

 Ex.: process result of computation with a Function instance
  1 CompletableFuture completableFuture
  2   = CompletableFuture.supplyAsync(() -˃ "Hello");
  3
  4 CompletableFuture future = completableFuture
  5   .thenApplyAsync(s -˃ s + " World");
  6
  7 assertEquals("Hello World", future.get());

    Line 5: under the hood the application of a function is wrapped 
    into a ForkJoinTask instance (for more information on the fork/join 
    framework, see the article ?Guide to the Fork/Join Framework in 
    Java?).  This allows to parallelize your computation even more and 
    use system resources more efficiently.
Guava ListenableFuture
@[https://github.com/google/guava/wiki/ListenableFutureExplained]
- Concurrency is a hard problem, but it is significantly simplified by
  working with powerful and simple abstractions. To simplify matters,
  Guava extends the Future interface of the JDK with ListenableFuture.

- """We strongly advise that you always use ListenableFuture instead
  of Future in all of your code, because:
  - Most Futures methods require it.
  - It's easier than changing to ListenableFuture later.
  - Providers of utility methods won't need to provide Future and ListenableFuture
      variants of their methods.


Listenable vs
CompletableFutures
@[https://stackoverflow.com/questions/38744943/listenablefuture-vs-completablefuture]
          ListenableFuture                           │               CompletableFuture
─────────────────────────────────────────────────────┼───────────────────────────────────────────────────
                                                     │ It is different from ListenableFuture in that it
                                                     │ can be completed from any thread that wants it to complete
─────────────────────────────────────────────────────┼───────────────────────────────────────────────────
ListenableFuture listenable = service.submit(...);   │ CompletableFuture completableFuture =
  Futures.addCallback(listenable,                    │     new CompletableFuture();
                      new FutureCallback˂Object˃() { │ completableFuture.whenComplete(new BiConsumer() {
    @Override                                        │   @Override
    public void onSuccess(Object o) {                │   public void accept(Object o, Object o2) {
        //handle on success                          │       //handle complete
    }                                                │   }
                                                     │ }); // complete the task
    @Override                                        │ completableFuture.complete(new Object())
    public void onFailure(Throwable throwable) {     │
       //handle on failure                           │ When a thread calls complete on the task,
    }                                                │ the value received from a call to get() is
  })                                                 │ set with the parameter value if the task is
                                                     │ not already completed.

  ..."CompletableFuture is dangerous because it exposes ºcompeteº 
     methods."
  ..."CompletableFuture would have been good if it extended Future 
     and did not expore toCompletableFuture,... and they could have named 
     it something meaningful like ChainableFuture "
Loom Project: Ligthweight threads
@[https://developers.redhat.com/blog/2019/06/19/project-loom-lightweight-java-threads/]
@[https://openjdk.java.net/jeps/353]

-ºMISSION:º
  - make concurrency simple(r) again!

- Threads, provided by Java from its first day, are a convenient concurrency
  construct 
Rºputting aside the separate question of communication among threads
Rºwhich is being supplanted by less convenient abstractions because theirº
Rºcurrent implementation as OS kernel threads is insufficient for meetingº
Rºmodern demands, and wasteful in computing resources that are particularlyº
Rºvaluable in the cloud.º

- Project Loom will introduce BºFIBERS:
  - lightweight, JVM managed, efficient threadsº,
  - A fiber is composed of:
    -Gº1 schedulerº   : Already in place for Java through the excellent scheduler
                      ºForkJoinPoolº
    -Rº1 continuationº: To be implemented in Loom.

RELATED:
@[http://www.linuxplumbersconf.org/2013/ocw/system/presentations/1653/original/LPC%20-%20User%20Threading.pdf]

@[https://www.infoq.com/presentations/continuations-java/]
Ron Pressler discusses and compares the various techniques of dealing with concurrency
and IO in both:
- pure functional (monads, affine types)
- imperative      (threads, continuations, monads, async/await)
and shows why delimited continuations are a great fit for the imperative style.

Bio
Ron Pressler is the technical lead for Project Loom, which aims to add delimited
continuations, fibers and tail-calls to the JVM

Quasar
Java Fibers
- fast threads for java and Kotlin
@[http://docs.paralleluniverse.co/quasar/]

NOTE: To be superseded by Prj. Loom?
Extracted from @[https://github.com/puniverse/quasar/issues/305]
My understanding is that Ron is currently busy working for/with Oracle on
project Loom which should bring "native" Fiber/lightweight continuation
support directly into JVM without the need of auxiliary library like Quasar.
fast Inter-thread communication
@[https://www.infoq.com/articles/High-Performance-Java-Inter-Thread-Communications]
- The story begins with a simple idea: create a developer friendly, 
  simple and lightweight inter-thread communication framework without 
  using any locks, synchronizers, semaphores, waits, notifies; and no 
  queues, messages, events or any other concurrency specific words or 
  tools.
  Just get POJOs communicating behind plain old Java interfaces.
Async/Reactive Programming
Labmdas Intro
- addition of lambda expressions in Java 8 provides for functional APIs in Java
  and simplifies development of non-blocking style APIs
  (low-level CompletableFuture or higher level ReactiveX).

  The conventional computing model of a Touring machine takes for granted
  that data is already available to be processed.

  In the Internet era, data is arriving at random and we don't want to block
  our CPU in an infinite loop waiting for such data to arrive.

  The conventional approach is to let the OS scheduler to divide the CPU
  into threads or processes sharing the hardware at defined intervals.
  While this approach works well for standard load scenarios, it fails for
  "moderm" workloads with thousands or tens of thousands of simultaneous
  clients accessing the server. Each new OS thread requires some extra
  memory on the OS kernel (about 2Kilobytes per Thread, and even more
  per Process). Switching from thread to thread or process to process becomes
  expensive or prohibitive with that number of concurent I/O flows.
  This is even worse when our server is virtualized with many other
  competing VMs running on the same physical server.

  Async programming will try to reause the same thread by many different
  clients or flows of I/O data providing a much better ussage of hardware
  resources and avoiding unnecesary context-switches between threads or
  processes.

  The term "reactive" refers to programming models that are built around
  reacting to change — network component reacting to I/O events, UI controller
  reacting to mouse events, etc. In that sense non-blocking is reactive because
  instead of being blocked we are now in the mode of reacting to notifications
  as operations complete or data becomes available.

  Spring Reactive Streams is a small spec, also adopted in Java 9, that defines
  the interaction between asynchronous components with back pressure. For
  example a data repository — acting as Publisher, can produce data that an
  HTTP server — acting as Subscriber, can then write to the response. The main
  purpose of Reactive Streams is to allow the subscriber to control how fast or
  how slow the publisher will produce data.

  Reactive Streams is of interest to low-level reusable libraries but
  no final applications are better suites using a higher level and richer
  (functional) API like Java8+ Collection-Stream API or more ingeneral APIs
  like those provided by ReactiveRX.

  Reactive programming can also be compared with the way data flows in Unix
  pipelines when handling text files. In the next Unix command there is a
  file input (it can be a real file in the hard-disk or a socket receiving
  data) and the different commands in the pipe consume STDIN and result to
  STDOUT for further processing.
  $ cat input.csv | grep "...." | sort | uniq | ... ˃  output.csv
  Reactive Java frameworks are ussually much fasters since everything executes
  on the same process (a Unix pipeline requires the help of the underlying
  OS to work), and the type of input/output data can be any sort of Java
  object (not just file text).
java.util.concurrent.Flow(1.9+)
@[https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/Flow.html]
- JDK 1.9+
- Reactive Streams was adopted by the JDK in the form of the java.util.concurrent.Flow API.
- It allows two different libraries that support asynchronous streaming to connect to each other,
    with well specified semantics about how each should behave, so that backpressure, completion, cancellation
    and error handling is predictably propagated between the two libraries.
- There is a rich ecosystem of open source libraries that support Reactive Streams,
    and since its inclusion in JDK9, there are a few in development implementations that are
    targetting the JDK, including the incubating JDK9 HTTP Client,
    and the Asynchronous Database Adapter (ADBA)
    effort that have also adopted it
- (See also What can Reactive Streams offer to EE4J)
RxJava
@[https://github.com/ReactiveX/RxJava]

ReactiveX provides a set of very-well thought-out cross-language abstraction to
implement the reactive patterns.

ºObservable/Operators/Observersº
@[http://reactivex.io/documentation/contract.html]
@[http://reactivex.io/documentation/observable.html]
                                         ⇑
                                    ˂˂Subscriber˃˃
                                    unsubscribe  : - Observable can opt to stop
                                                   event-emission if no more clients
                                                   are subcribed
 Loop-of-Observable-emitted-events:                - unsubscription will cascade back
    Observable → ˂˂IObserver˃˃: onNext(event)      through the chain of operators
    observer → observer  : handle event            applying to associated Observable.
    ^^^^^^^^
    also called
    "subscriber"
    "watcher"
    "reactor"  ("reactor pattern")
 end-loop
 Observable → ˂˂handlerInstance˃˃: onCOmpleted()
 observer → observer  : handle event

 RºWARN:º There is no canonical naming standard in RXJava


 ºObservable˂T˃º → operator1 → ... → operatorN → ºObserverº
Oºpushesºobjects                                  Subscribes to
 (events) from                                    the observable
 any source                                       events
 (ddbb, csv,...)                                  .onNext()
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   .onCompleted()
            Learning which operators to use       .onError()
            for a situation and how to combine    .onSubscribe(Disposable d);
            them is the key to master RxJava      ^
            them is the key to mastering RxJava   │
┌─────────────────────────────────────────────────┘
├─onSubscribe(Disposible): Free any resources created by the rxJava pipeline.
├─onNext()     : passes each item, one at a time,   to the ºObserverº
├─onCompleted(): communicates a completion event    to the ºObserverº
└─onError()    : communicates an error up the chain to the ºObserverº
                 where the Observer typically defines how to handle it.
                 Unless retry() operator is used to intercept the error,
                 the Observable chain typically terminates, and no
                 more emissions will occur.
                 See also Gºoperators 'Catch' and 'Retry'º

By default, Observables execute work on the immediate thread,
which is the thread that declared the Observer and subscribed it.
Not all Observables will fire on the immediate thread, (Observable.interval(),...)

ºcreating a source Observable:º
  Observable˂String˃ source00 = Observableº.justº("value1",...,"valueN");
  Observable˂String˃ source00 = Observableº.fromCallableº(() -˃ 1/0);
                                            ^^^^^^^^^^^^        ^^^
                                            Similar to .just() but errors
                                            are captured by the rxJava "pipeline"

  Observable˂String˃ source01 = Observableº.createº( emitter -˃
  {
        try {
    emitterº.onNextº(myList.get(0));
    emitter .onNext (myList.get(1));
    ...
    emitterº.onComplete()º; // ← Optional
        } catch(Throwable e) {
    emitterº.onError(e)º;
        }
  } );
  Observable˂String˃  source02 = Observableº.fromIterableº(myIterableList);
  Observable˂Integer˃ source03 = Observableº.rangeº(1,10);
  Observable˂String˃  source04 = Observableº.intervalº(1, TimeUnit.SECONDS);
                                             ^^^^^^^^
                                             Since it operates on a timer →
                                             needs to run on separate thread
                                             and will run on the computation
                                             Scheduler by default

  Observable˂String˃  source05 = Observableº.fromFutureº(myFutureValue);
  Observable˂String˃  source06 = Observableº.emptyº();
                                             ^^^^^
                                             calls onComplete() and ends

  Observable˂String˃  source07 = Observableº.deferº( () -˃ Observable.range(start,count));
                                             ^^^^^
                                      Advanced factory pattern.
                                      allows a separate state for each observer
  Observable˂String˃  source08 = Observableº.fromCallableº( () -˃ Observable.range(start,count));

ºcreating Single/Maybe/Completable "Utility" Observables:º
 ┌─────────────────────────────┬────────────────────────────────┬─────────────────────────────────┐
 │ Single.just("Hello")        │ Maybe.just("Hello")            │ Completable.fromRunnable(       │
 │ .subscribe(...);            │   .subscribe(...);             │   () -˃ runProcess() )          │
 │                             │                                │ .subscribe(...);                │
 ├─────────────────────────────┼────────────────────────────────┼─────────────────────────────────┤
 │ Emits a single item         │ Emits (or not)a single item    │  does not receive any emissions │
 ├─────────────────────────────┼────────────────────────────────┼─────────────────────────────────┤
 │ºSingleObserverº             │ ºMaybeObserverº                │ ºCompletableObserverº           │
 │ .onSubscribe(Disposable d); │  .onSubscribe(Disposable d);   │  .onSubscribe(Disposable d);    │
 │ .onSuccess(T value);        │  .onSuccess(T value);          │  .onComplete();                 │
 │ .onSuccess(Throwable error);│  .onSuccess(Throwable error);  │  .onError(Throwable error);     │
 │                             │  .onComplete();                │                                 │
 └─────────────────────────────┴────────────────────────────────┴─────────────────────────────────┘

ºCreate Test-oriented observablesº
   Observableº.neverº();
   Observableº.errorº();

ºDerive Observables from source:º
Observable˂Integer˃ lengths  =  sourceº.mapº   (String::length);
Observable˂Integer˃ filtered = lengthsº.filterº(i -˃ i  = 5);

ºcreating an Observer:º
(Lambdas in the source Observable .subscribe can be used in place)
Observer˂Integer˃ myObserver = new Observer˂Integer˃() {
  @Override public void onSubscribe(Disposable d) { //... }
  @Override public void onNext(Integer value)     { log.debug("RECEIVED: " + value); }
  @Override public void onError(Throwable e)      { e.printStackTrace();}
  @Override public void onComplete()              { log.debu("Done!"); }
};

BºCold/Hot Observablesº
  └ Cold: - Repeat the same content to different observers.
          - Represent sort-of inmmutable data.
          - A "cold" Observable waits until an observer subscribes to it
            an observer is guaranteed to see the whole sequence of events
  └ Hot : "Broadcast" to all observers at the same time.
          - A "hot" Observable may begin emitting items as soon as it is created.
          - An observer connecting "later" will loose old emissions.
          - Representºreal-time eventsº. They are time-sensitive.
          - Emissions will start when first observers calls connect().
          - a cold/hot observable can generate a new hot observable by
            calling publish() that will return a hot ConnectableObservable.
            Helpful to avoid the replay of data on each subscrived Observer.
  
          - NOTE: A "Connectable" Observable: does NOT begin emitting items
              until its Connect method is called, whether or not any observers
              have subscribed to it.
  
BºAbout Nullº
 └ In RxJava 2.0, Observables ☞GºNO LONGER SUPPORT EMITTING null VALUESº☜ !!!

BºDecision Treeº (Choosing the right Operator for a task)
  (REF: @[http://reactivex.io/documentation/operators.html#tree])
  └ Alphabetical List of Observable Operators
  @[http://reactivex.io/documentation/operators.html#alphabetical

BºCore APIº
  └ºrx.Observableº"==" [Java 8 Stream + CompletableFuture + "Back-presure" measures ]
    @[http://reactivex.io/documentation/observable.html]    └──────────────┬──────┘
                                                                           │
                                                            probably an intermediate
                                                            buffer for incomming/outgoing
                                                            messages that acts async.
                                                            when not full, and sync when
                                                            full.
    - ºrx.Singleº: specialized version emiting a single item
  
  └ºrx.Operatorsº:
    - Compose Observables in a chain
    - gives the real "reactive" power
    - operators allow to transform, combine, manipulate, and work
      with the sequences of items emitted by Observables.
    - declarative programming
      -ºAVOID THE THE DRAWBACKS OF CALLBACK-NESTING("callback hell")º
      - Most operators operate on an Observable and return an Observable.
        Each operator in the chain modifies the Observable that results
        from the operation of the previous operator. Order matters.
        (the Builder Pattern, also supported, is non-ordered)
  └ºrx.Subjectº:
  @[http://reactivex.io/documentation/subject.html]
    sort of "bridge or proxy" is available in some implementations
    that acts both as an observer and as an Observable.
  └ºrx.Schedulerº:
  @[http://reactivex.io/documentation/scheduler.html]
    - Needed when using multithreading into the
      cascade of Observable operators.
    - By default, the chain of Observables/operators
      will notify its observers ºon the same threadº
     ºon which its Subscribe method is calledº
    Operator|SubscribeOn         |ObserveOn
    --------+--------------------+---------
            |sets an Scheduler on|sets an Scheduler used
            |which the Observable|by the Observable to
            |should operate.     |send notifications to
            |                    |its observers.
    Scheduler "==" Thread


External links: - Rx Workshop: Introduction @[https://channel9.msdn.com/Series/Rx-Workshop/Rx-Workshop-Introduction] - Introduction to Rx: IObservable @[http://introtorx.com/Content/v1.0.10621.0/02_KeyTypes.html#IObservable] - Mastering observables (from the Couchbase Server documentation) @[https://developer.couchbase.com/documentation/server/3.x/developer/java-2.0/observables.html] - 2 minute introduction to Rx by Andre Staltz (“Think of an Observable as an asynchronous immutable array.”) @[https://medium.com/@andrestaltz/2-minute-introduction-to-rx-24c8ca793877] - Introducing the Observable by Jafar Husain (JavaScript Video Tutorial) @[https://egghead.io/lessons/rxjs-introducing-the-observable] - Observable object (RxJS) by Dennis Stoyanov @[http://xgrommx.github.io/rx-book/content/observable/index.html] - Turning a callback into an Rx Observable by @afterecho @[https://afterecho.uk/blog/turning-a-callback-into-an-rx-observable.html]
Ops.classification 1 ºOperators creating new Observablesº @[http://reactivex.io/documentation/operators.html#creating] ºCreate º create Observable from scratch programmatically ºDefer º do not create the Observable until the observer subscribes, and create a fresh Observable for each observer ºEmpty º create Observables that have very precise and limited behavior ºNever º " ºThrow º " ºFrom º create some object or data structure ºInterval º create Observable that emits a sequence of integers spaced by a particular time interval ºJust º convert an object or a set of objects into an Observable that emits that or those objects ºRange º create an Observable that emits a range of sequential integers ºRepeat º create an Observable that emits a particular item or sequence of items repeatedly ºStart º create an Observable that emits the return value of a function ºTimer º create an Observable that emits a single item after a given delay ºOperators Transforming Items:º @[http://reactivex.io/documentation/operators.html#transforming] ºBuffer º periodically gather items from input into bundles and emit these bundles rather than emitting the items one at a time ºFlatMap º transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable ºGroupBy º divide an Observable into a set of Observables that each emit a different group of items from the original Observable, Gºorganized by keyº ºMap º transform each input-item by applying a function ºScan º apply a function to each item emitted by an Observable, sequentially, and emit each successive value ºWindow º periodically subdivide items from an Observable into Observable windows and emit these windows rather than emitting the items one at a time ºOperators selectively filtering emitted events from a source Observableº @[phttp://reactivex.io/documentation/operators.html#filtering] ºDebounce º only emit an item from an Observable if a particular timespan has passed without it emitting another item ºDistinct º suppress duplicate items emitted by an Observable ºElementAtº emit only item n emitted by an Observable ºFilter º emit only those items from an Observable that pass a predicate test ºFirst º emit only the first item, or the first item that meets a condition, from an Observable ºIgnoreElements º do not emit any items from an Observable but mirror its termination notification ºLast º emit only the last item emitted by an Observable ºSample º emit the most recent item emitted by an Observable within periodic time intervals ºSkip º suppress the first n items emitted by an Observable ºSkipLast º suppress the last n items emitted by an Observable ºTake º emit only the first n items emitted by an Observable ºTakeLast º emit only the last n items emitted by an Observable ºOperators Combining multiple source Observables into a new single Observableº @[http://reactivex.io/documentation/operators.html#combining] ºAnd º combine sets of items emitted by two or more Observables by means ºThen º of Pattern and Plan intermediaries ºWhen º ºCombineLatest º when an item is emitted by either of two Observables, combine the latest item emitted by each Observable via a specified function and emit items based on the results of this function ºJoin º combine items emitted by two Observables whenever an item from one Observable is emitted during a time window defined according to an item emitted by the other Observable ºMerge º combine multiple Observables into one by merging their emissions ºStartWithº emit a specified sequence of items before beginning to emit the items from the source Observable ºSwitch º convert an Observable that emits Observables into a single Observable that emits the items emitted by the most-recently- emitted of those Observables ºZip º combine multiple Observables emissions together via a function function → emit single items for each input tuple ºOperators handling Errors and helping to recover from error-notificationsº @[http://reactivex.io/documentation/operators.html#error] ºCatch º recover from an onError notification by continuing the sequence without error ºRetry º if a source Observable sends an onError notification, resubscribe to it in the hopes that it will complete without error ºUtility Operators "toolbox"º @[http://reactivex.io/documentation/operators.html#utility] ºDelay º shift the emissions from an Observable forward in time by a particular amount ºDo º register an action to take upon a variety of Observable lifecycle events ºMaterialize º represent both the items emitted and the notifications sent ºDematerializeº as emitted items, or reverse this process ºObserveOn º specify the scheduler on which an observer will observe this Observable ºSerialize º force an Observable to make serialized calls and to be well-behaved ºSubscribe º operate upon the emissions and notifications from an Observable ºSubscribeOn º specify the scheduler an Observable should use when it is subscribed to ºTimeIntervalº convert an Observable that emits items into one that emits indications of the amount of time elapsed between those emissions ºTimeout º mirror the source Observable, but issue an error notification if a particular period of time elapses without any emitted items ºTimestamp º attach a timestamp to each item emitted by an Observable ºUsing º create a disposable resource that has the same lifespan as the Observable ºConditional and Boolean Operators evaluating one or moreº Observables or items emitted by Observables @[http://reactivex.io/documentation/operators.html#conditional] ºAll º determine whether all items emitted by an Observable meet some criteria Mathematical and Aggregate Operators @ ºAmb º given two or more source Observables, emit all of the items from only the first of these Observables to emit an item @[http://reactivex.io/documentation/operators.html#mathematical] ºContains º determine whether an Observable emits a particular item or not Average, Concat, Count, Max, Min, Reduce, and Sum C ºDefaultIfEmptyº emit items from the source Observable, or a default item if the source Observable emits nothing onverting Observables @ ºSequenceEqual º determine whether two Observables emit the same sequence of items ºSkipUntil º discard items emitted by an Observable until a second Observable emits an item To C ºSkipWhile º discard items emitted by an Observable until a specified condition becomes false ºConnectable Observable Operatorsº [http://reactivex.io/documentation/operators.html#connectable] @ ºTakeUntil º discard items emitted by an Observable after a second Observable emits an item or terminates ºTakeWhile º discard items emitted by an Observable after a specified condition becomes false ºConnect º ºPublish º ºRefCount º ºReplay º ºMathematical and Aggregate Operatorsº - Operators that operate on the entire sequence of items emitted by an Observable ºAverage º calculates the average of numbers emitted by an Observable and emits this average ºConcat º emit the emissions from two or more Observables without interleaving them ºCount º count the number of items emitted by the source Observable and emit only this value ºMax º determine, and emit, the maximum-valued item emitted by an Observable ºMin º determine, and emit, the minimum-valued item emitted by an Observable ºReduce º apply a function to each item emitted by an Observable, sequentially, and emit the final value ºSum º calculate the sum of numbers emitted by an Observable and emit this sum ºBackpressure Operatorsº a variety of operators that enforce particular flow-control policies @[http://reactivex.io/documentation/operators/backpressure.html] - backpressure operators ºstrategiesº for coping with Observables that produce items more rapidly than their observers consume them ºConnectable Observable Operatorsº Specialty Observables that have more precisely-controlled subscription dynamics ºConnect º instruct a connectable Observable to begin emitting items to its subscribers ºPublish º convert an ordinary Observable into a connectable Observable ºRefCountº make a Connectable Observable behave like an ordinary Observable ºReplay º ensure that all observers see the same sequence of emitted items, even if they subscribe after the Observable has begun emitting items ºOperators to Convert Observablesº ºToº convert an Observable into another object or data structure
Ops.classification 2 - Basic Operators: - Suppressing operators: - filter, take, skip, takeWhile/skipWhile, distinct, distinctUntilChanged - Transforming operators: - map, cast, startWith, defaultIfEmpty, switchIfEmpty, sorted, deplay,repeat, scan - Reducing operators: - count, reduce, all, any, contains - Collection operators: - toList, toSortedList, toMap, toMultiMap, collect - Error recovery Operators - onErrorReturn, onErrorReturnItem, onErrorResumeNext, retry - Action ("stream life-cicle") Operators: - doOnNext, doOnComplete, doOnError, doOnSubscribe, doOnDispose - Combining Observables: - Merging: - merge, mergeWith - flatMap - Concatenation: - concat, concatWith - concatMap - Ambiguous: - amb - Zipping - Combine Latest: - withLatestFrom - Grouping: - groupBy - Multicasting, Replaying and Caching: ( Multicasting is helpful in preventing redundant work being done by multiple Observersand instead makes all Observers subscribe to a single stream, at least to the point wherethey have operations in common) - "Hot" operators. (TODO) - Automatic connection: - autoConnect, refCount, share - replay - cache -Subjects - Just like mutable variables are necessary at times even though you should strive forimmutability, Subjects are sometimes a necessary tool to reconcile imperative paradigmswith reactive ones. - PublishSubject - Serializin Subject - BehaviourSubject - ReplaySubject - AsyncSubject - UnicastSubject Custom Ops @[http://reactivex.io/documentation/implement-operator.html]
Awaitility(Async→Sync) Tests
@[https://github.com/awaitility/awaitility]
- Awaitility: DSL allowing to express async results (test expectations) easely. 
  removing complexity of handling threads, timeouts, concurrency issues, ...
  that obscured test code.

- Ex 1:
  @Test
  public void updatesCustomerStatus() {
    // Publish a (async) message to a message broker:
    messageBroker.publishMessage(updateCustomerStatusMessage);
  Bºawait().atMost(5, SECONDS).until(customerStatusIsUpdated())º;
    ...
  }
Spring Reactor
Spring-Async
@[https://ordina-jworks.github.io/reactive/2016/12/12/Reactive-Programming-Spring-Reactor.html]
@[https://spring.io/blog/2013/05/13/reactor-a-foundation-for-asynchronous-applications-on-the-jvm]
@[https://spring.io/guides/gs/async-method/]
"""Why Reactor when there's already RxJava2?
   RxJava2 is java 6 while for Reactor the Spring team decided to go all in
   and focus only on Java 8. This means that you can make use of all the new
   and fancy Java 8 features.

   If you are going to use Spring 5, Reactor might be the better option.

   But if you are happy with your RxJava2, there is no direct need to migrate to Reactor."""
VertX
Who-is-Who
(Forcibly incomplete but still quite pertinent list of core developers and companies)
Tim Fox     :  Initiated VertX in 2012
Julien Viet :  Project lead (as of 2020), RedHat, Marseille
             @[https://github.com/vietj]
             @[http://blog.julienviet.com/]
               He is also core develoepr of Crash @[http://www.crashub.org/]

Julien Ponge:@[https://julien.ponge.org/]
               Author of VertX in Action
Many others :@[https://github.com/eclipse-vertx/vert.x/graphs/contributors]
Vert.X Summary
REF:
- Vert.X guide for java devs @[https://github.com/vert-x3/vertx-guide-for-java-devs]
- VertX maven starter        @[https://github.com/vert-x3/vertx-maven-starter]
- Examples for amqp-bridge,  @[https://github.com/vert-x3/vertx-examples]
  grpc, core, docker,
  gradle*/maven*, ignite, jca,
  jdbc.  kafka, kotlin, mail,
  metrics, mqtt, openshift3,
  reactjs-server-side-rendering,
   redis, resteasy, rx,
  service-discovery,
  service-proxy, shell, spring,
  sync, unit, web/web-client ...
- Webºserver examplesº       @[https://github.com/vert-x3/vertx-examples/tree/master/web-examples/src/main/java/io/vertx/example/web]
  angular*, auth, authjdbc,
  authorisation,
  blockinghandler, chat,
  cookie, cors,
  custom_authorisation, form,
  helloworld, http2, , jwt,
  mongo, react, realtime, rest,
  sessions, staticsite,
  templating, upload, vertxbus
- Web/ºJDBCºserver examples @[https://github.com/vert-x3/vertx-examples/blob/master/web-examples/src/main/java/io/vertx/example/web/jdbc/Server.java]

verticle
REF: @[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/intro/README.adoc]
-ºreusable unitº of Bºdeploymentº
                      ^^^^^^^^^^
                  - Can be passed some Gºconfigurationº like
                    credentials, network address,...
                  - can be deployed several times
                  - A verticle can deploy other verticles.

Oºverticleº1 ←────→ event─loop 1 ←──────→   1 Thread
  ^                 ^^^^^                     ^^^^^^
  │                 "input" event like        Must not handle I/O thread-blocking
  │                 network buffers,          or CPU intensive operations
  │                 timing events,            'executeBlocking' can be used
  │                 verticles messages, ...   to offload the blocking I/O operations
  │                                           from the event loop to a worker thread
  │
˂˂io.vertx.core.AbstractVerticle˃˃ Base Class
@[https://vertx.io/docs/apidocs/io/vertx/core/AbstractVerticle.html]
-Oº.start()º ← life-cycle sync/async method to be overrided
-Oº.stop ()º ← life-cycle sync/async method to be overrided
-Oº.vertxº   ← - Points to the BºVert.x environment where the verticle is deployedº
   ^^^^^^    · - provides methods to create HTTP/TCP/UDP/... servers/clients.
             ·   Ex:
             ·   │ io.vertx.core.http.HttpServer server  = thisOº.vertxº.createHttpServer();
             · - provides access to the event bus.
             ·   Ex:
             ·    ºSENDINGºVERTICLE:                        │ºRECEIVINGºVERTICLE:
             ·   ┌──────────────────────────────────────────┼────────────────────────────────────────
             ·   │ ...                                      │ ...
             ·   │Oºvertxº.eventBus()                       │ public void onMessage(
             ·   │   .request(wikiDbQueue,                  │          Message message)
             ·   │       jsonObject, options ,              │ {
             ·   │                   ^^^^^^^                │   String action = message.
             ·   │                   headers                │                headers().get("action");
             ·   │                  +payload codecs         │
             ·   │                  +tiemouts               │   switch (action) {
             ·   │       ^^^^^^^^^^  ^^^^^^^                │     case "action1":
             ·   │// Ussually jsonObject contains the data  │       ...
             ·   │// and an "action" header the action to   │       message.reply(
             ·   │// be executed by the receiving verticle  │           new JsonObject()
             ·   │       reply -˃ {                         │           .put("key1", value1));
             ·   │     if (reply.succeeded()) {             │       break;
             ·   │       ...                                │     case ...:
             ·   │     } else {                             │       ...
             ·   │       ...                                │     default:
             ·   │     }                                    │       message.fail(
             ·   │   });                                    │         ErrorCodes.BAD_ACTION.ordinal(),
             ·   │                                          │         "Bad action: " + action);
             ·   │                                          │   }
             ·   │                                          │ }

-Oº.config()º← - accessors to some deployment configuration to allow passing G*external configuration*
                 Ex:
                 │ public static final String CONFIG_WIKIDB_QUEUE = "wikidb.queue";
                 │ ...
                 │ wikiDbQueue =Oºconfig()º.getString(CONFIG_WIKIDB_QUEUE, "wikidb.queue");
                 │                             ^^^^^^                      ^^^^^^^^^^^^^^
                                       or Integers, booleans               Default param
                                       complex JSON data, ...              if first is null

import io.vertx.core.AbstractVerticle;
public class MainVerticle extends AbstractVerticle {

  @Override
  public void start(Future˂Void˃ startFuture) {
                    ^^^^^^^^^^^^^^^^^^^^^^^^
                    No params for the sync version
    startFuture.complete();
  }
}

Event Bus
- main tool for communication between verticles using *messages*
  and one of:
  - point-to-point messaging
  - request-response messaging
  - publish / subscribe for broadcasting messages

   verticle 01                                      verticle 02
  (HTTP server)             event─bus              (DDBB client)
   │                          ║ ║                        │
   ├─── user 1234 ? ─────────→║ ║                        │
   │                          ║ ║─────── user 1234 ? ──→ │
   │                          ║ ║                        ├── ....─→
   │                          ║ ║                        │←─ ....
   │                          ║ ║←────── user 1234 ? ────┤
   │←── user 1234   ──────────║ ║                        │
        ^^^^^^^^^             ║ ║
  Message are free-form
  strings. (JSON recomended    ^
  for multi─language support   │
                               │

                  - It can be accessed through (simple)
                    TCP protocol for 3rd party apps
                    or exposed over general-purpose
                    messaging bridges (AMQP, Stomp,...)
                  - Support cluster support sending
                    messages to verticles deployed⅋running
                    in different application nodes
                  - a O*SockJS* bridge allows web applications
                    to seamlessly communicate over the event bus
                    from JavaScript running in the browser by
                    receiving and publishing messages just like
                    any verticle would do.

threading conf

By default Vert.x attaches CPU-core-thread 1˂--˃2 event loops
VertX Threading Strategies:
   Incoming network data -˃ accepting thread"N":
   accepting thread "N" -˃ event-loop thread: +event with data

When a verticle opens a network server and is deployed more than once,
then the events are being distributed to the verticle instances in a
round-robin fashion which is very useful for maximizing CPU usage with
lots of concurrent networked requests.
Testing
@[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-4/README.adoc]
@[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-4/src/test/java/io/vertx/guides/wiki/http/SampleHttpServerTest.java]

└ Ex.1:
  @RunWith(VertxUnitRunner.class)  ← annotation to JUnit tests to allow vertx-unit features
  public class SampleHttpServerTest {
  
    private B*Vertx vertx*;
  
    @Before public void prepare() { B*vertx*= Vertx.vertx(); }
  
    @After public void finish(TestContext O*context*) {
      vertx.close(O*context*.asyncAssertSuccess());
    }
  
    @Test
    public void start_http_server
           (TestContext O*context*) {
                          ^^^^^^^
                // provided by the runner
                // provides access to basic assertions,
                // a context to store data,
                // and several async-oriented helpers
  
      Async Q*async* = O*context*.async();
  
      vertx
        .createHttpServer().requestHandler(
           req -˃ req.response().putHeader("Content-Type", "text/plain").end("Ok")
        )
        .listen(
          8080,
        O*context*.asyncAssertSuccess(
          server -˃ {
            WebClient webClient = WebClient.create(vertx);
            webClient.get(8080, "localhost", "/").send(ar -˃ {
              if (ar.succeeded()) {
                HttpResponse˂Buffer˃ response = ar.result();
              O*context*.assertTrue(response.headers().contains("Content-Type"));
              O*context*.assertEquals("text/plain", response.getHeader("Content-Type"));
              O*context*.assertEquals("Ok", response.body().toString());
              Q*async*.complete();
              } else {
              Q*async*.resolve(Promise.failedPromise(ar.cause()));
              }
            });
          }));
    }
  }

└ Ex.2: check/test that a timer task has been called once,
        and that a periodic task has been called 3 times.
      @[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-4/src/test/java/io/vertx/guides/wiki/database/WikiDatabaseVerticleTest.java]

  RunWith(VertxUnitRunner.class)
  public class WikiDatabaseVerticleTest {
    private Vertx vertx;
    @Before public void prepare(TestContext context) { vertx = ...       }
    @After  public void finish(TestContext context)  { vertx.close(...); }
  
    @Test /*(B*timeout=5000*)*/
    public void async_behavior(TestContext context) { // <1>
      Vertx vertx = Vertx.vertx();
      Async a1 = context.async();
      Async a2 = context.async(3); // ← works as a countdown that
                                        completes successfully after 3 calls.
      vertx.setTimer(100, n -> a1.complete());
      vertx.setPeriodic(100, n -> a2.countDown());
    }
  
    @Test
    public void crud_operations(TestContext context) {
      Async async = context.async();
  
      service.createPage(..., ...,
        context.asyncAssertSuccess(v1 -> {
          service.fetchPage(...,
            context.asyncAssertSuccess(json1 -> {
              context.assertTrue(json1.getBoolean("found"));
              context.assert...;
              ...
              async.complete();  // <1>
            }));
        }));
      async.awaitSuccess(B*5000*);
    }
  }
HTTPS AAA
@[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-7/README.adoc]
Maven Bootstrap
@[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-1/README.adoc]
@[https://github.com/vert-x3/vertx-guide-for-java-devs/tree/3.8/step-1]

Ex: minimally viable wiki written with Vert.x

   └ Features:
     - server-side rendering
     - data persistence through a JDBC connection
       and async ddbb access

   └ Dependencies:
     - Vert.x web: "elegant" APIs to deal with routing, request payloads, etc.
     - Vert.x JDBC client: asynchronous API over JDBC.
     - other libreries for HTML/md rendering

                                          ┌ o configured pom.xml:
 $º$ URL="https://github.com/vert-x3" º   │   - Maven Shade Plugin configured to create a single  
 $º$ URL="${URL}/vertx─maven─starter" º ←─┤     "fat" Jar archive with all required dependencies  
 $º$ git clone ${URL} project01       º   │   - Exec Maven Plugin to provide the exec:java goal   
 $º$ cd project01                     º   │     that in turns starts the application through the  
                                          │     Vert.x io.vertx.core.Launcher class.              
                                          │     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                          │     (equivalent to running using the vertx cli tool)
                                          │
                                          │ o sample verticle
                                          │
                                          │ o unit tests
                                          │
                                          └ o redeploy.sh: auto compile+redeploy on code changes.
                                              (adjust $VERTICLE in script to match main verticle)
 $º$ mvn package exec:java           º ← check that maven install is correct


Tip: The SQL database modules supported by the Vert.x project do not currently
   offer anything beyond passing SQL queries (e.g., an object-relational mapper)
   as they focus on providing asynchronous access to databases.
   However, nothing forbids using more advanced modules from the community,
   and we especially recommend checking out projects like this jOOq generator
   for VertX
   @[https://github.com/jklingsporn/vertx-jooq]

$ mvn clean package
$ java -jar target/project01-SNAPSHOT-fat.jar
Create HttpServer
REF:@[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-1/src/main/java/io/vertx/guides/wiki/MainVerticle.java]

   import io.vertx.ext.web.handler.BodyHandler;
   public class MainVerticle ºextends io.vertx.core.AbstractVerticleº {
      ...
      private io.vertx.core.http.HttpServer server = vertx.createHttpServer(); // vertx defined in Parent Class

      @Override
      public void start(Future startFuture) {
          Json.mapper.registerModule(new JavaTimeModule());
          FileSystem vertxFileSystem = vertx.fileSystem();
          vertxFileSystem.readFile("swagger.json", readFile -> {
              if (readFile.succeeded()) {
                  // Swagger swagger = new SwaggerParser().parse(readFile.result().toString(Charset.forName("utf-8")));
                  // SwaggerManager.getInstance().setSwagger(swagger);
                  Router router = Router.router(vertx);
                  router.get  (ROUTE_ENTITY01+"/:id")                              .handler(this:: GetEntity01Handler);
                  router.post (ROUTE_ENTITY01       ).handler(BodyHandler.create()).handler(this::PostEntity01Handler);
                                                              └───────┬───────────┘         └───────────┬───────────┘
                                                decode POST req.body (forms,...) to         function signature:
                                                Vert.x buffer objects                       void functionName(ºRoutingContext contextº)
                  router.delete(ROUTE_ENTITY01+"/:id")                              .handler(this::DeleEntity01Handler);
                  log.info("Starting Server... Listening on "+RC.host+":"+RC.port);         
                  vertx.createHttpServer(_getHTTPServerOptions()).                          
                          requestHandler(router::accept).listen(
                           8080,                                  ← Different deployments can share the port. Vertx will round-robin
                           /* AsyncResult */ar -˃ { //
                            if (ar.succeeded()) {
                              LOGGER.info("HTTP server running on port 8080");
                              startFuture.complete();
                            } else {
                              LOGGER.error("Could not start a HTTP server", ar.cause());
                              startFuture.fail(ar.cause());
                            }
                          });
              } else {
                  startFuture.fail(readFile.cause());
              }
          });
      }
    }
Reusable Verticles
@[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-2/README.adoc]

- resulting verticles will not have direct references to each other 
  as they will only agree on destination names in the event bus as well 
  as message formats.
- messages sent on the event bus will be encoded in JSON.

- Ex:
@[https://github.com/vert-x3/vertx-guide-for-java-devs/tree/3.8/step-2/src/main/java/io/vertx/guides/wiki]
 HttpServerVerticle.java
 WikiDatabaseVerticle.java
 MainVerticle.java      ← its sole purpose is to bootstrap the app
                          and deploy other verticles.
 @[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-2/src/main/java/io/vertx/guides/wiki/MainVerticle.java]
  package io.vertx.guides.wiki;

  public class MainVerticle extends AbstractVerticle {
    @Override
    public void start(Promise promise) {
      Promise promise01 = Promise.promise();
      vertx.deployVerticle(new WikiDatabaseVerticle(), promise01);
      promise01.future().compose(id -> {
        Promise promise02 = Promise.promise();
        vertx.deployVerticle(
          "io.vertx.guides.wiki.HttpServerVerticle",  // <4>
          new DeploymentOptions().setInstances(2),    // <5>
          promise02);
        return promise02.future();
      }).setHandler(ar -> {
        if (ar.succeeded()) {
          promise.complete();
        } else {
          promise.fail(ar.cause());
        }
      });
    }
  }
VertX Cont
RxJava Integration
@[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-7/README.adoc]
  
Vertx+Jooq
@[https://github.com/jklingsporn/vertx-jooq]
Vertx+k8s
@[http://escoffier.me/vertx-kubernetes/]
Client-Side
SockJS
@[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-10/README.adoc]
- SockJS:
  - Event-bus bridge allowing web apps to seamlessly communicate over
  - event bus from JavaScript running in the browser by receiving and publishing
  - messsages just like any verticle would do
Angular Client
@[https://github.com/vert-x3/vertx-guide-for-java-devs/blob/3.8/step-9/README.adoc]
Other frameworks
JavaLite
- lightweight system for processing asynchronous jobs. 
- Use Cases:
  - website that needs to run batch process in background
  - We receive batch of inputs to be processed in a "best-effort"
    but replay as-soon-as-possible to client that we have the
    input batch ready for processing.

- easy-to-use "Wrapper" on top o Apache Artemis (ActiveMQ "next Gen")
  the Async adds an abstraction layer based on a Command Pattern,
  which makes it trivial to add asynchronous processing.

- Embedded broker instance with reasonable defaults

- Ex:
  Asyncºasyncº= new Async(            ←BºCREATE one or more Queuesº
            "/opt/project1",          ← place to store persistent messages
            false,
            new QueueConfig(
               "MESSAGES_QUEUE",      ← queue 1 name
               new CommandListener(), 
               5)                     ← number of listeners(threads) to
            ,
            new QueueConfig(
                  "ERRORS_QUEUE",     ← queue 2 name (No limit in the number o 
                  new ErrorListener(),                queues)
               5)
            );
       ºasyncº.start();

   public class HelloCommand             ←BºCreate a commandº
       extends Command {
       private String message;
   
       public HelloCommand(String message) {
         this.message = message;
       }
   
       public HelloCommand() {}          ← Rºnecessary (forbid finals)º
   
       @Override
       public void execute() {
           System.out.println(message);
       }
   }


   for(int i = 0; i < 100; i++){         ←Bºsending commands asyncº
      async.send(
        "MESSAGES_QUEUE",
        new HelloCommand("Hello Number "+ i));
   }
   Output will be similar to
   → Hello Number 0
   → Hello Number 1
   → ...

   List topCommands             ←BºPeek (vs Consume) 3 "top"º
      = ºasyncº.getTopCommands(            commands from "ERROR_QUEUE"
           3, "ERROR_QUEUE"); 


- Commands can be read and processed synchronously (one-by-one)
  from an individual queue one at the time without a listener.
  Ex: Qºyou do not want to process errors automaticallyº. To do so:

  ErrorCommand errorCommand =           ←BºConsume messageº
       (ErrorCommand)receiveCommand("ERROR_QUEUE");
  ... // Process manually

BºText vs Binary messagesº
  - To be compatible with JMS the  communication protocol is limited t
    - javax.jms.TextMessage   ← Default mode.
    - javax.jms.BytesMessage  ← async.setBinaryMode(true);

    In both cases, the Rºserialization of a command is first done to XMLº
    with the use of XStream.
  - If a given command has transient field that must NOT  be serialized,
    use the field annotation @XStreamOmitField to ignore it.

  -RºWARN:º Do not switch from mode to mode while having persistent 
            messages stored in your queues.

BºCommands with DB accessº
  - If queue processing requires a database connetion, DBCommandListener
    can be used:
    Async async = new Async(filePath, false, new 
        QueueConfig("MESSAGES_QUEUE", new 
        DBCommandListener(                 ← If JNDI connection is setup, the 
         "java:comp/env/jdbc/conn01"), 5)    listener will find and open it
   );                                        Use your tomcat/Jboss/... container
                                             documentation to set up it properly
    
Bº(Artemis) Config APIº
  - For complex app configuration, the underlying Artemis API
    can be used:
    org.apache.activemq.artemis.core.config.Condifuration 
       artemisCOnfig = async.getConfig();

- See also filequeue in this map. It's faster but doesn't support
  Queue to DDBBs.
FileQueue
@[https://github.com/stimulussoft/filequeue]
- KISS alternative using MVStore
@[http://www.h2database.com/html/mvstore.html]
- All producers and consumers run within a JVM.
- H2 MVStore DB used for storage.
- Queue items are BºPOJOs serialized into Json using jacksonº.
-Gºfaster than JavaLite due to performance shortcutº:
  -BºFile Queue will transfer queued items directly to consumersº
   Bºwithout hitting the database provided there are consumers  º
   Bºavailable, otherwise, message will be persistedº
-RºDoesn't support persistence to JNDI DDBBº
- fixed and exponential back-off retry is present.

BºPRE-SETUPº:
  - maven/gradle package dependency:
    com.stimulussoft:filequeue:1.1.4

BºUsageº:
  - Implement POJO extending FileQueueItem
  - Implement consume(FileQueueItem) on ˂˂Consumer˃˃ to process items
  - Instantiate a FileQueue object and call config() to configure
  - Call startQueue() to start the queue
  - Call stopQueue() to stop the queue processing
  - Call FileQueue.destroy() to shutdown all static threads (optional)

BºExample Implementation:º
  └ Queue Ussage example:
    FileQueue queue = FileQueue.fileQueue();
    FileQueue.Config config = FileQueue.
        config(
          queueName,
          queuePath,
          TestFileQueueItem.class,
          new TestConsumer()
        )
        .maxQueueSize(MAXQUEUESIZE)           // ← queueItem will block until an slot becomes 
                                                   available or ExceptionTimeout thrown
        .retryDelayAlgorithm(
           QueueProcessor.RetryDelayAlgorithm.EXPONENTIAL)
        .retryDelay(RETRYDELAY)
        .maxRetryDelay(MAXRETRYDELAY)
        .maxRetries(0);                       // ← Infinite retries
        .persistRetryDelay(                   // ← delay between DDBB scans.
           PERSISTENTRETRYDELAY);
    queue.startQueue(config);                 // ← Start queue
    for (int i = 0; i < ROUNDS; i++)
      queue.queueItem(                        // ← Submit items
        new TestFileQueueItem(i)
      );
    queue.stopQueue();                        // ← stopQueue

  └ Consumer implementation:
    static class TestConsumer implements Consumer {
    
        public TestConsumer() { }
    
        @Override
        public Result consume(FileQueueItem item) 
        throws InterruptedException {
                        try {
        TestFileQueueItem retryFileQueueItem = 
            (TestFileQueueItem) item;
        if (retryFileQueueItem.getTryCount() == RETRIES )
            return Result.SUCCESS;
        return Result.FAIL_REQUEUE;
                        } catch (Exception e) {
        logger.error(e.getMessage(), e);
        return Result.FAIL_NOQUEUE;
                        }
        }
    }

  └ FileQueueItem implementation:

    import com.stimulussoft.filequeue.*;
    
    static class TestFileQueueItem extends FileQueueItem {
      Integer id;
      public TestFileQueueItem() { super(); };
      private TestFileQueueItem(Integer id) {
          this.id = id;
      }
      @Override
      public String toString() { return String.valueOf(id); }
      public Integer getId() { return id; }
      public void setId(Integer id) { this.id = id; }
    }

  └ File Caching:
    - If there is the need to cache a file to disk or perform resource 
      availability checks prior to items being placed on the queue, 
      implement availableSlot() on the QueueCallback interface. This method 
      is called as soon as a slot becomes available, just before the item 
      is place on the queue. It may be used to cache a file to disk, or 
      perform resource availability pre-checks (e.g. disk space check).
QA
Cost of software failures
$312 billion per year: global cost of software bug (2013)
$300 billion dealing with the Y2K problem

$440 million loss by Knight Capital group Inc. in 30 minutes, August 2012
$650 million loss by NASA Mars missions in 1999; unit conversion bug
$500 million Arian 5 maiden flight in 1996; 64-bit to 16-bit conversion bug
"$Nightmare" billion Boeing 737Max

2011: Software caused 25% of all medical device recalls.
Checker framework
Java 8+
ºfix errors at compile timeº (vs later on at execution/runtime)
@[https://github.com/typetools/checker-framework]
@[https://checkerframework.org/manual/]
@[https://www.youtube.com/watch?v=6E1CSydgzQc]
@[https://www.baeldung.com/checker-framework]

º COMPARED TO ALTERNATIVES (SpotBugs, Infer  Jlint, PMD,...)º
                 ┌─────────────┬────────┬────────┐                 ┌──────────────────┬─────────────────────┐
                 │ Null Pointer│        │        │                 │ Verification     │ Bug─Finding         │
                 │    errors   │ False  │Annotat.│                 │ (ºChecker FWº,)  │ (Infer,StopBugs,    │
                 │             │        │        │                 │                  │  SonarQube,...      │
                 │Found│ Missed│warnings│written │  ┌──────────────┼──────────────────┼─────────────────────┤
  ┌──────────────┼─────┼───────┼────────┼────────┤  │Goal          │ prove that       │ find some bugs      │
  │ºChecker FW.º │9    │ 9     │  4     │  35    │  │              │ no bug exits     │ at "low cost"       │
  ├──────────────┼─────┼───────┼────────┼────────┤  ├──────────────┼──────────────────┼─────────────────────┤
  │StopBugs      │0    │ 9     │  1     │  0     │  │Check specifis│ user provided    │ infer likely specs  │
  ├──────────────┼─────┼───────┼────────┼────────┤  │specificat    │                  │                     │
  │Jlint         │0    │ 9     │  8     │  0     │  ├──────────────┼──────────────────┼─────────────────────┤
  ├──────────────┼─────┼───────┼────────┼────────┤  │False         │ None!!!          │ acceptable          │
  │PMD           │0    │ 9     │  0     │  0     │  │negatives     │                  │                     │
  ├──────────────┼─────┼───────┼────────┼────────┤  ├──────────────┼──────────────────┼─────────────────────┤
  │Eclipse 2017  │0    │ 9     │  8     │  0     │  │False         │ manually supress │ heuristics focus on │
  ├──────────────┼─────┼───────┼────────┼────────┤  │positives     │ warnings         │ most important bugs │
  │IntelliJ      │0    │ 9     │  1     │  0     │  ├──────────────┼──────────────────┼─────────────────────┤
  │+@NotNull 2017│3    │ 6     │  1     │ 925+8  │  │Downside      │ user burden      │ missed bugs         │
  └──────────────┴─────┴───────┴────────┴────────┘  └──────────────┴──────────────────┴─────────────────────┘

RºPROBLEM:º                                          │BºSOLUTION:º
   STANDARD JAVA TYPE SYSTEM IS NOT GOOD ENOUGH      │  Java 8+ allows to compile programs
   - Next example compile, but fail at runtime:      │  using Oº"PLUGGABLE TYPE SYSTEMs"º,
     Ex.1:                                           │  allowing to apply stricter checks
       System.console().readLine(); ←RºNullPointerº  │  than default ones in compiler like
     Ex.2:                                           │  Ex:
       Collections.emptyList()                       │  $ javac º-processor NullnessCheckerº MyFile.java
               .add("one"); ←RºUnsupported Operationº│
     Ex.3:                                           │   PLUGABLE TYPE SYSTEM COMPILATION SCHEMA:
       Date key1 = new Date();                       │           (1)           No errors (2)
       myMap.put(key1, "now");                       │    Source ───→ Compiler ────┬───→ Executable
       myMap.get(key1);    ←  returns "now"          │      ^            │         │(2)       ^
       key1.setSeconds(0); ←RºMutate keyº            │      │            v         v          │
       myMap.get(key1);    ←Rºreturns nullº          │      │         Standard  OºOptionalº   │ Guaranteed
                                                     │      │         Compiler  OºType    º───┘ Behaviour
                                                     │      │         Errors    OºChecker º
                                                     │      │                      │
                                                     │      │                      v
                                                     │      └────────────────── Warnings :
                                                     │
                                                     │     (2) plugable type system allows generation
                                                     │         of executable to allow CI continue the
                                                     │         pipeline with further tests (functional
                                                     │         testing, configuration testing, ...)

º ___ _   _ ____ _____  _    _     _        _  _____ ___ ___  _   _ º
º|_ _| \ | / ___|_   _|/ \  | |   | |      / \|_   _|_ _/ _ \| \ | |º
º | ||  \| \___ \ | | / _ \ | |   | |     / _ \ | |  | | | | |  \| |º
º | || |\  |___) || |/ ___ \| |___| |___ / ___ \| |  | | |_| | |\  |º
º|___|_| \_|____/ |_/_/   \_\_____|_____/_/   \_\_| |___\___/|_| \_|º

(See new releases/versions at
  @[https://search.maven.org/search?q=g:org.checkerframework])

 ºSTEP 01:º                           │ ºSTEP 02:º
──────────────────────────────────────┼────────────────────────────────────────────────────
  Add next pom.xml dependencies like: │  tweak ºmaven-compiler-pluginº to use
  ˂dependency˃                        │  Checker Framework as a pluggable Type System:
      ˂groupId˃                       │  ˂plugin˃
        org.checkerframework          │    ˂artifactId˃ºmaven-compiler-pluginº˂/artifactId˃
      ˂/groupId˃                      │    ˂version˃3.6.1˂/version˃
      ˂artifactId˃                    │    ˂configuration˃
        checker-qual                  │      ˂source˃1.8˂/source˃
      ˂/artifactId˃                   │      ˂target˃1.8˂/target˃
      ˂version˃2.11.0˂/version˃       │      ˂compilerArguments˃
  ˂/dependency˃                       │        ˂Xmaxerrs˃10000˂/Xmaxerrs˃
  ˂dependency˃                        │        ˂Xmaxwarns˃10000˂/Xmaxwarns˃
      ˂groupId˃                       │      ˂/compilerArguments˃
        org.checkerframework          │     º˂annotationProcessors˃º ← "==" javac -processor ...
      ˂/groupId˃                      │        ˂annotationProcessor˃
      ˂artifactId˃                    │      org.checkerframework.checker.nullness.NullnessChecker
        checker˂                      │         ˂/annotationProcessor˃
      /artifactId˃                    │         ˂annotationProcessor˃
      ˂version˃2.11.0˂/version˃       │      org.checkerframework.checker.interning.InterningChecker
  ˂/dependency˃                       │         ˂/annotationProcessor˃
  ˂dependency˃                        │         ˂annotationProcessor˃
      ˂groupId˃                       │      org.checkerframework.checker.fenum.FenumChecker
        org.checkerframework          │         ˂/annotationProcessor˃
      ˂/groupId˃                      │         ˂annotationProcessor˃
      ˂artifactId˃                    │      org.checkerframework.checker.formatter.FormatterChecker
        jdk8                          │         ˂/annotationProcessor˃
      ˂/artifactId˃                   │     º˂/annotationProcessors˃º
      ˂version˃2.11.0˂/version˃       │      ˂compilerArgs˃
  ˂/dependency˃                       │        ˂arg˃-AprintErrorStack˂/arg˃
                                      │        ˂arg˃-Awarns˂/arg˃
                                      │      ˂/compilerArgs˃
                                      │    ˂/configuration˃
                                      │  ˂/plugin˃

(ºSTEP 03:º Manually add extended type annotations to your java code)

º _   _ ____ ____    _    ____ _____ º
º| | | / ___/ ___|  / \  / ___| ____|º
º| | | \___ \___ \ / _ \| |  _|  _|  º
º| |_| |___) |__) / ___ \ |_| | |___ º
º \___/|____/____/_/   \_\____|_____|º

- BºAvoiding Nullsº

 ºCHECKS  ON TYPESº                              │ºCHECKS ON FUNCTION DECLARATIONº
                                                 │                   ┌────┬────┬───────────────────────────┐
                                                 │                   │FUNC│FUNC│DESCRIPTION                │
  private static int func1                       │                   │PRE─│POST│                           │
    (º@NonNullº String[] args)                   │                   │COND│COND│                           │
  {                                              │ ┌─────────────────┼────┼────┼───────────────────────────┤
      return args.length;                        │ │@RequiresNonNull │X   │    │variables areºexpectedº to │
  }                                              │ │                 │    │    │be non─null when invoked.  │
                                                 │ ├─────────────────┼────┼────┼───────────────────────────┤
  public static void main                        │ │@EnsuresNonNull  │    │X   │variables areºguaranteedºto│
    (º@Nullableº String[] args) {                │ │                 │    │    │be non─null on return.     │
      ...                                        │ ├─────────────────┼────┼────┼───────────────────────────┤
      func1(args);                               │ │@EnsuresNonNullIf│    │X   │variables areºguaranteedºto│
  }         ^^^^                                 │ │                 │    │    │benon─null on ret.true/fals│
      [WARNING] ... [argument.type.incompatible] │ └─────────────────┴────┴────┴───────────────────────────┘
       incompatible types in argument.           │
       ºfound    : nullº                         │
       ºrequiredº: @Initializedº@NonNullº...     │

- BºConvert String constants into Safe Enum with Fenumº
                                                (Fake enum)
  static final @Fenum("country") String ITALY = "IT";
  static final @Fenum("country") String US = "US";
  ...
  static final @Fenum("planet") String MARS = "Mars";
  static final @Fenum("planet") String EARTH = "Earth";
  ...

  void function1(@Fenum("planet") String inputPlanet){
      System.out.println("Hello " + planet);
  }

  public static void main(String[] args) {
      obj.greetPlanets(US);   ←----  [WARNING] ...
  }                                   incompatible types in argument.
                                       found   : @Fenum("country") String
                                       required: @Fenum("planet") String

- BºRegular Expressionsº
  @Regex(1) private static String FIND_NUMBERS = "\\d*";
  ^^^^^^^^^                                      ^^^^^^
  Force String variable                       [WARNING] ...
  to store a regex with                       incompatible types in assignment.
  at least one matching                         found   : @Regex String
  group                                         required: @Regex(1) String



- BºValidating tainted (non-trusted) inputº

  º@Untaintedº
   String validate (String sqlInput) {
      // Do any suitable checks, throw on error
      @SuppressWarnings("tainting")      ← "swear" that developer got sure
      @Untainted String result = ...;       of input correctness
      return result;
  }

  void execSQL(º@Untaintedº String sqlInput) {
      ...
  }

  public static void main(String[] args) {
      obj.execSQL(arg[0]);             ← warning at compile time
      obj.execSQL(validate(arg[0]));   ← "OK". validate un-tain the input
  }

- BºMark as Immutableº
 º@ImmutableºDate date = new Date();
  date.setSeconds(0);   ← Rºcompile-time errorº


-ºAvoiding (certain) concurrency errorsº

  Lock Checker enforces a locking discipline:
  "which locks must be held when a given operation occurs"

  CHECKS ON TYPES                             │ CHECKS ON FUNCTION DECLARATION
                                              │                 ┌────┬────┬───────────────────────────┐
  º@GuardedBy("lockexpr1","lockexpr2",...)º   │                 │FUNC│FUNC│DESCRIPTION                │
             int var1 = ....;                 │                 │PRE─│POST│                           │
   ^^^^^^^^^^                                 │                 │COND│COND│                           │
  a thread may dereference the value referred │┌────────────────┼────┼────┼───────────────────────────┤
  to by var1 only when the thread holds all   ││@Holding        │X   │    │All the given lock exprs   │
  the locks that ["lockexpr1",...] currently  ││(String[] locks)│    │    │are held at method call    │
  evaluates to.                               │├────────────────┼────┼────┼───────────────────────────┤
                                              ││@EnsuresLockHeld│    │X   │Ensures locks are locked on│
                                              ││(String[] locks)│    │    │return,ex. lock adquired by│
                                              ││                │    │    │ReentrantLock.lock().      │
                                              │├────────────────┼────┼────┼───────────────────────────┤
                                              ││@EnsuresLockHeld│    │X   │Ensures locks are locked on│
                                              ││(String[] locks)│    │    │return,ex.lock conditionaly│
                                              ││                │    │    │adquired by ReentrantLock  │
                                              ││                │    │    │.lock()                    │
                                              ││                │    │    │if method return true|false│
                                              │└────────────────┴────┴────┴───────────────────────────┘
  ºSIDE EFFECT SPECIFICATIONSº
  ┌────────────────────┬───────────────────────────────────────────────┐
  │º@LockingFreeº      │method does NOT acquire│release locks:         │
  │                    │· it is not synchronized,                      │
  │                    │· it contains NO synchronized blocks           │
  │                    │· it contains no calls to lock│unlock methods  │
  │                    │· it contains no calls to methods that are not │
  │                    │  themselves @LockingFree                      │
  │                    │(@SideEffectFree implies @LockingFree)         │
  ├────────────────────┼───────────────────────────────────────────────┤
  │º@ReleasesNoLocksº  │· method maintains a strictly                  │
  │                    │  nondecreasing lock hold count                │
  │                    │  on the current thread for any locks          │
  │                    │  held at method call.                         │
  ├────────────────────┼───────────────────────────────────────────────┤
  │º@EnsuresLockHeldº  │method adquires new locsk                      │
  │º@EnsuresLockHeldIfº│(default if no @LockingFree│@MayReleaseLocks│  │
  │                    │@SideEffectFree│@Pure used).                   │
  └────────────────────┴───────────────────────────────────────────────┘


-BºFormat String Checkerº
  - prevents use of incorrect format strings in System.out.printf,....

    void printFloatAndInt
         (º@Format({FLOAT, INT})º String Oºformatº)
    {
      System.out.printf(Oºformatº, 3.1415, 42);
    }
-ºI18n Format Checker examplesº
  MessageFormat.format("{0} {1}", 3.1415);
                                        ^
                              second argument missing
  MessageFormat.format("{0, time}", "my string");
                                    ^^^^^^^^^^^
                                    cannot be formatted
                                    as Time type.
  MessageFormat.format("{0, thyme}", new Date());
                            ^^^^^
                            unknown format type

  MessageFormat.format("{0, number, #.#.#}", 3.1415);
                                    ^^^^^
                              subformat is invalid.

-ºProperty File Checker!!!!º RºTODOº
  -ºIt ensures that used keys are found in the corresponding º
   ºproperty file or resource bundle.º

-ºGUI Effect Checkerº
  - It is difficult for a programmer to remember
    which methods may be called on which thread(s).
    (Main GUI thread or others)
   Checker types the method as if:
   - It accesses no UI elements (and may run on any thread);
   - It may access UI elements  (and must run on the UI thread)

-º(physical) Internation System UNIT annotationsº:
  @Acceleration: Meter Per Second Square @mPERs2
  @Angle       : Radians @radians
                 Degrees @degrees
  @Area        : square millimeters @mm2,
                 square meters @m2
                 square kilometers @km2
  @Current     : Ampere @A
  @Length      : Meters @m
                 millimeters @mm
                 kilometers @km
  @Luminance   : Candela @cd
  @Mass        : kilograms @kg
                     grams @g
  @Speed       : meters per second   @m
                 kilometers per hour @kmPERh
  @Substance   : Mole @mol
  @Temperature : Kelvin @K
                 Celsius @C
  @Time        : seconds @s
                 minutes @min
                 hours @h

-º@Unsigned/@Signedº← guarantees values are not mixed

-ºtype alias or typedefº
  share same representation as another type
  but is conceptually distinct from it.
  Ex 1: get sure that Strings representing addresses
        and passwords are NOT mixed
  Ex 2: get sure that integers used for meters are
        not mixed with integers used for centimeters.

  Example:
  @NonNull List˂String˃
  List˂@NonNull String˃
  @Regex String validation = "(Java|JDK) [7,8]"

  private String getInput(String parameterName){
   final String retval = @Tainted request.getParameter(parameterName);
   return retval;
  }

  private void runCommand(@Untainted String… commands){
   // the previously tainted String must be validated before being passed in here.
   ProcessBuilder processBuilder = new ProcessBuilder(command);
   Process process = processBuilder.start();
  }


SPARTA (anti-malware)
- Aimed at preventing malware from appearing in an app store.
- provides an information-flow type-checker customized to Android
  but can also be applied to other domains.
@[https://checkerframework.org/sparta/]
  The paper "Collaborative verification of information flow for a
  high-assurance app store" appeared in CCS 2014.
JavaDoc
-----------------------+-------------------------------------+-------------------------+-------   Example
Tag⅋ Parameter         | Usage                               | Applies to              | Since    /**
-----------------------+-------------------------------------+-------------------------+-------    * Short one line description.
@authorJohn Smith      | Describes an author.                | Class, Interface, Enum  |           * 

-----------------------+-------------------------------------+-------------------------+------- * Longer description. ... @versionversion | Provides software version entry. | Class, Interface, Enum | * ...here. | Max one per Class or Interface. | | *

-----------------------+-------------------------------------+-------------------------+------- * And even more explanations to follow @sincesince-text | Describes when this functionality | Class, Interface, Enum, | * in consecutive paragraphs | has first existed. | Field, Method | * -----------------------+-------------------------------------+-------------------------+------- * @author John Bla @seereference | Provides a link to other element | Class, Interface, Enum, | * @param variable Description .... | of documentation. | Field, Method | * @return Description .... -----------------------+-------------------------------------+-------------------------+------- */ @paramname descrip | Describes a method parameter. | Method | public int methodName (...) { -----------------------+-------------------------------------+-------------------------+------- // method body with a return statement @return description | Describes the return value. | Method | } -----------------------+-------------------------------------+-------------------------+------- @exceptionclass desc | Describes an exception that may | Method | -----------------------+-------------------------------------+-------------------------+------- @throwsclass desc | be thrown from this method. | | -----------------------+-------------------------------------+-------------------------+------- @deprecated descr | Describes an outdated method. | Class, Interface, Enum, | | | Field, Method | -----------------------+-------------------------------------+-------------------------+------- {@inheritDoc} | Copies the description from the | Overriding Method | 1.4.0 | overridden method. | | -----------------------+-------------------------------------+-------------------------+------- {@linkreference} | Link to other symbol. | Class, Interface, Enum, | | | Field, Method | -----------------------+-------------------------------------+-------------------------+------- {@value#STATIC_FIELD} | Return the value of static field. | Static Field | 1.4.0 -----------------------+-------------------------------------+-------------------------+------- {@codeliteral} | Formats literal text in the code | Class, Interface, Enum, | 1.5.0 | font. It is equivalent to | Field, Method | | {@literal} | Class, Interface, Enum, | 1.5.0 -----------------------+-------------------------------------+-------------------------+------- {@literalliteral} | Denotes literal text. The enclosed | Field, Method | | text is interpreted as not | | | containing HTML markup or nested | | | javadoc tags. | | -----------------------+-------------------------------------+-------------------------+-------

SonarQube

Alternatives
- alternatives to SonarQube include:
  - Facebook Infer @[http://fbinfer.com/]
    (Static analysis Java/C/...)
  - Scrutinizer:
  - StopBugs:
  - Eclipse Static Code Analasys:
    Eclipse → Properties → Java → Compiler → Errors/Warnings → Null analysis:
      Null pointer access
      Potential null pointer access
      Redundant null check:
        x Include 'assert' in null analysis
        x Enable annotation-based null analysis
          Violation of null specification
          Conflict between null annotations an null inference
          Unchecked conversion from non-annotated type to @NonNull type
          Problems detected by pessimistic analysis fro free type variables
          Unsafe "@Nonnull" interpretation of the free type variable from library
          Redundant null anotation:
          "@NonNull" parametere not annotated in overriding method
          Missing "@NonNullByDefault" annotation on package
          x Use default annotations for null specifications (configure)
          x Inherit null annotations
          x Enable syntatic null analisys for fields
      x Treat above errors like fatal compile erros (make compiled code not executable)
UUID: bdf38754-3114-4343-a768-e8d24027f91b
JDepend
@[https://github.com/clarkware/jdepend]
https://htmlpreview.github.io/?https://github.com/clarkware/jdepend/blob/master/docs/JDepend.html

 What Is It?
  -----------
  JDepend traverses Java class and source file directories and
  generatesºdesign-quality-metrics for each Java packageº
 ºin terms of its extensibility, reusability, and maintainabilityº
 ºto effectively manage and control package dependencies.º
Junit
@[https://www.infoq.com/news/2018/01/VSCodeJunit]
Amazon CodeGuru
- Powered by IA.
- CodeGuru consists of two components
– Amazon CodeGuru Profiler:
helps developers find an application’s most expensive lines
of code along with specific visualizations and recommendations 
on how to improve code to save money.
- Amazon CodeGuru Reviewer: 
helps enhance the quality of code by scanning for critical issues, 
identifying bugs, and recommending how to remediate them.

  ┌→ Write Code
  |    |
  |    v
  |  Review Code  ← CodeGuru Reviewer
  |    |
  |    v
  |  Test App     ← CodeGuru Profiler
  |    |
  |    v
  |  Deploy App
  |    |
  |    v
  |  Run App      ← CodeGuru Profiler
  |    |
  └----┘

- Profiler supports application written
in Java virtual machine (JVM) languages such as Clojure,
JRuby, Jython, Groovy, Kotlin, Scala, and Java.
- Reviewer’s bug-fixing recommendations currently support
Java code stored in GitHub, AWS CodeCommit, or Bitbucket. 
Exceptions
- (compiler) checked vs unchecked (Error, RuntimeException and their subclasses).
- Checked: All except Error, RuntimeException and their subclasses
- Error: Exceptional conditions external to the application.
java.lang.Object
│
└─ java.lang.Throwable   ← Only instances of this (sub/)class are thrown
│                       in JVM, can be thrown in throw statement or can
│                       be an argument in catch clause.
│
├─   java.lang.Exception
│    │
│    ├─Oºjava.lang.RuntimeExceptionº(non─checked)  ← Most common error raised by
│    │                                               developer code
│    │
│    └─  java.lang.*Exception       (checked ─A)   ←RºDon't useº. checked exceptions end up
│                                                     being converted to Runtime Excep.
│                                                     and bloats the code.
│
└─   java.lang.Error                (non─checked)  ← serious problems that app code
                                                    should not try to catch.
                                                    ThreadDeath error, though a "normal" condition,
                                                    is also a subclass of Error because most apps
                                                    should not try to catch it.

ºDump Exception stack trace to STDERR:º
StringWriter writer = new StringWriter();
PrintWriter printWriter = new PrintWriter( writer );
e.printStackTrace( printWriter );
printWriter.flush();
System.err.println(writer);


"Optional": Avoid Nulls
REF
import java.util.Optional;
Optional optional = Optional.ofNullable(a); // ← Create an optional
optional.map ( s -˃ "RebelLabs:" + s);               // ← Process the optional
optional.flatMap( s -˃ Optional.ofNullable(s));      // ← map a function that retunrs Optional
optional.ifPresent(System.out::println);             // ← run if the value is ther

optional.get();                                      // ← Alt 1: get the value or throw an exception
optional.orElse("Hello world!");                     // ← Alt 2: get the value or default

optional.filter( s -˃ s.startsWith("RebelLabs"));    // ← return empty Optional if not satisfied
JSR Annotations
 foRºDefect Detectionº
@[https://stackoverflow.com/questions/1476757/jsr305-vs-jsr308-java-type-anotations-which-is-going-to-be-the-standard]
Type Annotations
TODO: Compare how it compares/overlaps CheckerFramework

 º@NonNullº     compiler can determine cases where a      │º@(Un)Taintedº         Identity types of data that should
                code path might receive a null value,     │                       not be used together, such as remote
                without ever having to debug a            │                       user input being used in system
                NullPointerException. The compiler        │                       commands, or sensitive information in
                just print a warning, but it              │                       log streams
                continues to compile!!!                   │
                                                          │º@mº                   Units of measure ensures that numbers
 º@ReadOnlyº    compiler will flag any attempt to         │                       used for measuring objects are used
                change the object. This is similar to     │                       and compared correctly, or have
                Collections.unmodifiableList, but         │                       undergone the proper unit
                more general and verified at compile time.│                       conversion.
                                                          │
 º@Regexº       Provides compile-time verification        │º@FunctionalInterfaceº indicates that the type declaration
                that a String intended to be used as      │                       is intended to be a functional
                a regular expression is a properly        │                       interface, as defined by the Java
                formatted regular expression.             │                       Language Spec.
  
└ ºExamplesº:
  Annotation
  @NonNull List                              ← A non-null list of Strings.
  List<@NonNull String>                              ← A list of non-null Strings.
  @Regex String validation = "(Java|JDK) [7,8]"      ← Check at compile time that this String is a valid regular expression.
  private String getInput(String parameterName){     ← The object assigned to retval is tainted and not for use in sensitive operations.
    final String retval =
      @Tainted request.getParameter(parameterName);
    return retval;
  }

  private void runCommand(@Untainted String… commands){            Each command must be untainted. For example, the previously
    ProcessBuilder processBuilder = new ProcessBuilder(command);   tainted String must be validated before being passed in here.
    
    Process process = processBuilder.start();
  }
Annotation processors(Data Binding,Lombok,...)
See JSR 269 
Dependency injection
See JSR 330
@[http://www.theserverside.com/feature/Spring-vs-Guice-The-Clash-of-the-IOC-Containers]
A: t's important to realize that Dagger was created after Guice, by one
of Guice's creators ("Crazy Bob" Lee) after his move to Square:
- Spring was originally released in October 2002.
- Google originally publicly released Guice in March 2007.
- JSR-330 formalized javax.inject annotations in October 2009,
with heavy input from Google (Bob Lee), Spring, and other industry
players.
- Square originally released Dagger 1 publicly in May 2013.
- Google originally released Dagger 2 publicly in April 2015.
- Square marked Dagger 1 as deprecated 10 days ago,
on September 15, 2016.
Maven
External Links
- PUBLIC REPOSITORY:      @[https://mvnrepository.com/]
- Artifact Search Engine: @[http://search.maven.org/]
- Online doc from Maven : @[https://www.mvndoc.com]
Ex: Show Bouncy Castle doc by:
 - full index   : @[https://www.mvndoc.com/c/org.bouncycastle/bcpg-jdk15/index-all.html]
 - by package   : @[https://www.mvndoc.com/c/org.bouncycastle/bcpg-jdk15/index.html]

Basics

BºGOALº
- unit of work.
- A goal accepts configuration properties (parameters) to customize
its run-time behavior
- Ex: Compiler:compile defines a set of parameters to specify target
JDK version or switching on/off compiler optimizations
- An ºordered listº of goals can be attached to a Bºlifecycle phaseº.
Ex:
                             Executes next goals in order
mvn Bºpackageº  | resources:resources →
  ^Lifecicle  | compiler:compile →
              | resources:testResources →
              | compiler:testCompile →
              | surefire:test jar:jar

BºSNAPSHOTSº
Q: What exactly is a Maven Snapshot and why do we need it?
A:☞A snapshot version is one that has not been released (Oºfuture releaseº).
 The idea is that ºbeforeº a "1.0" release is done, there exists
 a 1.0Oº-SNAPSHOTº. That version is what might become 1.0. It's
 basically Oº"1.0 under development"º. This might be close to a real
 1.0 release, or pretty far (right after the 0.9 release, for ex.)

 The difference between a "real" version and a snapshot version is
 that ºsnapshots might get updatesº.  That means that downloading
 1.0-SNAPSHOT today might give a different file than downloading it
 yesterday or tomorrow.
 In contrast OºReleased versions are inmutablesº:
 updates to "1.0.0" requires new version "1.0.1".

 Snapshot dependencies should only exist during development.
ºReleased versions (i.e. no non-snapshot) should NEVER have aº
ºdependency on snapshotsº

˂repository˃
    ...
    ˂snapshots˃
        ˂enabled˃true˂/enabled˃
        ˂updatePolicy˃
          always|daily(default)|
          "X"minutes|never
        ˂/updatePolicy˃
    ˂/snapshots˃
˂/repository˃

BºStandard Lifecyclesº
ºCLEAN,DEFAULT,SITEº
| DEFAULT LIFECYCLE         | CLEAN LIFECYCLE | SITE LIFECYCLE
| process-resources         | TODO            | TODO
|  compile
|   process-classes
|    process-test-resources
|     test-compile
|      test
|       prepare-package
|        package
|         install

BºCompiling & Installingº
Command                           Description
$ mvn clean                         Remove the (current_working_directory/)target folder
$ mvn compile                       (goal list: clean→compile)
$ mvn clean package                 Compiles and generates the (JAR/WAR/...) package
$ mvn clean install                 (goal list: clean→compile→test→package→install_local )
                                # : skip tests
$ mvn clean install \               (goal list: clean→compile→     package→install_local )
-Dmaven.test.skip=true
$ mvn clean deploy                  Compile... and installs into remote ("corporate") server
                                ( clean→compile→test→package→install_local→install_pub )
-----------------------------------------------------------
Common options:
–U                   Force library (download) update
–P myProfileX        Execute profile myProfileX
–o                   offline mode. Search deps in local repo.
-Dgenerate.pom=true  Generates the pom locally for an artefact when installing
                  and compiling. Very useful to make offilne mode work properly.
-----------------------------------------------------------
help:active-profiles   : List (project|user|global)
                    active profile for the build
help:effective-pom     : Displays effective POM for
                      current build
help:effective-settings: Prints calculated settings
help:describe groupId artifactId: Describes plugin attributes

mvn exec Main
@[https://stackoverflow.com/questions/9846046/run-main-class-of-maven-project]

$ mvn  -Dexec.args="arg0 ..." ºexec:javaº -Dexec.mainClass="com.example.Main"
pom.xml
ºReuse constants:º
${project.groupId}         ← Reuse project groupId in POM
${project.artifactId}      ← Reuse project artifactId in POM
${project.version}         ← Reuse project version in POM

º${my.property.name}º ← Reuse properties in POM


˂project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"˃
˂modelVersion˃4.0.0˂/modelVersion˃
º˂!-- project coordinates { --˃º
˂groupId˃com.mycompany.mygroupid˂/groupId˃
˂artifactId˃myArtifactId˂/artifactId˃
º˂!-- packaging value := jar|war|ear|pom|maven-plugin|ejb|rar|par|aar|apklib|... --˃º
˂packaging˃jar˂/packaging˃
º˂!-- See @[https://semver.org/] (Semantic Versioning) for more info                     º
º  Version X.W.Z                                                                         º
º   X MAJOR  Must differ for non-compatible API changes,                                 º
º   W MINOR  W increase with new functionality backwards-compatible with X.(W-1) version º
º   Z PATCH  backwards-compatible bug fixes that does NOT add new functionality          º
--˃
˂version˃1.0-SNAPSHOT˂/version˃ º˂!-- Remember: SNAPSHOT refers to development/future release --˃º
º˂!-- } --˃º
˂name˃MyPackageDescriptiveName˂/name˃
˂url˃http://maven.apache.org˂/url˃
˂properties˃
    ˂maven.compiler.source˃1.8˂/maven.compiler.source˃
    ˂maven.compiler.target˃1.8˂/maven.compiler.target˃
˂/properties˃
˂dependencies˃

º˂!-- Typical dependencies for in-memory data-collection handling { --˃º
˂dependency˃
    ˂groupId˃com.google.guava˂/groupId˃
    ˂artifactId˃guava˂/artifactId˃
    ˂version˃21.0˂/version˃
˂/dependency˃
º˂!-- } --˃º

º˂!-- Typical dependencies for logging { --˃º
˂dependency˃
    ˂groupId˃ch.qos.logback˂/groupId˃
    ˂artifactId˃logback-classic˂/artifactId˃
    ˂exclusions˃
        ˂!-- Avoid problem:
        SLF4J: Class path contains multiple SLF4J bindings.
        SLF4J: Found binding in [jar:file:~/.m2/repository/org/slf4j/slf4j-jdk14/1.7.21/slf4j-jdk14-1.7.21.jar!/org/slf4j/impl/StaticLoggerBinder.class]
        SLF4J: Found binding in [jar:file:~/.m2/repository/ch/qos/logback/logback-classic/1.1.7/logback-classic-1.1.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
        --˃
        ˂exclusion˃
            ˂groupId˃org.slf4j˂/groupId˃
            ˂artifactId˃slf4j-jdk14˂/artifactId˃
        ˂/exclusion˃
    ˂/exclusions˃
    ˂version˃1.1.7˂/version˃
˂/dependency˃
º˂!-- } --˃º

º˂!-- Typical dependencies for JSON handling { --˃º
˂dependency˃
    ˂groupId˃com.fasterxml.jackson.core˂/groupId˃
    ˂artifactId˃jackson-core˂/artifactId˃
    ˂version˃2.8.8˂/version˃
˂/dependency˃

˂dependency˃
    ˂groupId˃com.fasterxml.jackson.core˂/groupId˃
    ˂artifactId˃jackson-databind˂/artifactId˃
    ˂version˃2.9.0.pr3˂/version˃
˂/dependency˃

˂dependency˃
    ˂groupId˃com.fasterxml.jackson.datatype˂/groupId˃
    ˂artifactId˃jackson-datatype-joda˂/artifactId˃
    ˂version˃2.8.8˂/version˃
˂/dependency˃

˂dependency˃
    ˂groupId˃org.web3j˂/groupId˃
    ˂artifactId˃core˂/artifactId˃
    ˂version˃3.2.0˂/version˃
˂/dependency˃
º˂!-- } --˃º

º˂!-- test dependencies (Not included in production system) { --˃º
º˂!-- Unit test dependencies { --˃º
˂dependency˃
  ˂groupId˃junit˂/groupId˃
  ˂artifactId˃junit˂/artifactId˃
  ˂version˃3.8.1˂/version˃
  ˂scope˃test˂/scope˃
˂/dependency˃
º˂!-- } --˃º

º˂!--  REST API (Functional) test dependencies { --˃º
˂dependency˃
    ˂groupId˃io.rest-assured˂/groupId˃
    ˂artifactId˃scala-support˂/artifactId˃
    ˂version˃3.0.6˂/version˃
    ˂scope˃test˂/scope˃
˂/dependency˃
˂dependency˃
    ˂groupId˃io.rest-assured˂/groupId˃
    ˂artifactId˃json-schema-validator˂/artifactId˃
    ˂version˃3.0.6˂/version˃
    ˂scope˃test˂/scope˃
˂/dependency˃
º˂!-- } --˃º
º˂ } --˃º


˂/dependencies˃
˂/project˃

Reactor(POM aggregate vs inherit) Maven supports both project inheritance (set a parent project) and aggregation (reactor mechanism). MVN reactor allows to execute a goal (build,...) over a set of projects. The reactor will determine the build order according to defined dependencies on each pom. MVN 2 improved reactor making it transparent to users. Anyway a plugin exists to customize the interaction with the reactor: maven-reactor-plugin If we launch compilation in a multi-module (like AbsisParentPom) and something goes wrong, we can always re-start from the last failed module with the '--resume-from' option like: $ mvn --resume-from=com.myCompany.myModule:MyArtifact clean install -P myProfile -DskipTests=true
Dependency Management
mvn dependency:analyze
list two things:
Dependencies used but not declared.
If found in the parent pom, there is no
problem when compiling, but must be
included at runtime on the server.

Dependencies declared but not used for
the scope provided (compile, provided…).
They can be in the parent pom too.
Noneless, can be needed at runtime.

mvn dependency:tree
Ex. Ussage:
$ mvn dependency:tree -Dscope=compile
                     ^^^^^^^^^^^^^^
                     do not show test/provided/... dependencies
→ ...
→ [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ tamperproof ---
→ [INFO]ºcom.myCompany:myProject:jar:1.0-SNAPSHOTº
→ [INFO] +- org.web3j:core:jar:4.3.0:compile
→ [INFO] |  +- org.web3j:abi:jar:4.3.0:compile
→ [INFO] |  |  \- org.web3j:utils:jar:4.3.0:compile
→ [INFO] |  |     \- org.bouncycastle:bcprov-jdk15on:jar:1.60:compile
→ [INFO] |  +- org.web3j:crypto:jar:4.3.0:compile
→ [INFO] |  |  \- org.web3j:rlp:jar:4.3.0:compile
→ [INFO] |  +- org.web3j:tuples:jar:4.3.0:compile
→ [INFO] |  +- com.github.jnr:jnr-unixsocket:jar:0.21:compile
→ [INFO] |  |  +- com.github.jnr:jnr-ffi:jar:2.1.9:compile
→ [INFO] |  |  |  +- com.github.jnr:jffi:jar:1.2.17:compile
→ [INFO] |  |  |  +- org.ow2.asm:asm:jar:5.0.3:compile
→ [INFO] |  |  |  +- org.ow2.asm:asm-commons:jar:5.0.3:compile
→ [INFO] |  |  |  +- org.ow2.asm:asm-analysis:jar:5.0.3:compile
→ [INFO] |  |  |  +- org.ow2.asm:asm-tree:jar:5.0.3:compile
→ [INFO] |  |  |  +- org.ow2.asm:asm-util:jar:5.0.3:compile
→ [INFO] |  |  |  +- com.github.jnr:jnr-a64asm:jar:1.0.0:compile
→ [INFO] |  |  |  \- com.github.jnr:jnr-x86asm:jar:1.0.2:compile
→ [INFO] |  |  +- com.github.jnr:jnr-constants:jar:0.9.11:compile
→ [INFO] |  |  +- com.github.jnr:jnr-enxio:jar:0.19:compile
→ [INFO] |  |  \- com.github.jnr:jnr-posix:jar:3.0.47:compile
→ ...

Related:

- JDepend traverses Java class and source file directories and
generatesºdesign-quality-metrics for each Java packageº
ºin terms of its extensibility, reusability, and maintainabilityº
ºto effectively manage and control package dependencies.º
[[bdf38754-3114-4343-a768-e8d24027f91b?]]
POM BEST PRACTICES:
  REF: @[http://geertschuring.wordpress.com/2011/02/23/maven-best-practices/]

- update pom dependency to latest version
  Ex. Update org.checkerframework.*:
$º$ mvn versions:use-latest-versions -Dincludes="org.checkerframework:*"º

- Replace references like ${artifactId} or ${pom.artifactId} with new
  º${project.artifactId}ºsyntax. This syntax follows the XML document
  structure, making it easy to remember and predict the value that the
  reference will result in.

- Try to avoid using inherited properties. Developers can easily forget
  that a certain property is used by a child POM and change the value
  breaking the build in an unexpected place. Secondly, its quite annoying
  not to be able to easily lookup a property without having to find
  and examine the parent POM.

- Use the dependency management section of the parent pom to define
  all dependency versions, but do not set a scope here so that all
  dependencies have scope compile by default.

- Use properties to define the dependency versions. This way you can
  get an overview of all versions quickly.

- Use the pluginmanagement section of parent pom to define versions for
  ºallº plugins that your build uses, even standard maven plugins like
  maven-compile-plugin and maven-source-plugin. This way your build will
  not suddenly behave differently when a new version of a plugin is released.

- When using a parent POM not located in the directory directly above
  the current POM define an empty relativePath element in your parent section.

- Use the dependency plugin to check your project for both unnecessary
  dependencies and undeclared-but-used-none-the-less dependencies.
  The goal is called ‘analyze’:
$º$ mvn dependency:analyze  º

- Make sure the pom files contain all the repository references needed
  to download all dependencies. If you want to use a local repository
  instead of downloadin strait from the internet then use the maven
  settings file to define mirrors for the individual repositories that
  are defined in the poms.

- If you use Nexus, then do not create repository groups containing both
  hosted and proxied repositories. This will dramaticly reduce the
  responsiveness because Nexus will check the remote locations of the
  proxied repositories even if a hosted repository contains the requested
  artifact.

- TODO:
@[http://www.sonatype.com/people/2009/01/maven-continuous-integration-best-practices/]
Recipies
-ºNew skeleton:º
$º$ mvn archetype:generate -DgroupId=my.groupId \        º
$º$   -DartifactId=myArtifact \                          º
$º$   -DarchetypeArtifactId=maven-archetype-quickstart \ º
$º$   -DinteractiveMode=false                            º

- ºShow ordered-by-phase list of goals executed:º
   (Very useful to skip slow/non-important goals like doc, style-checks,...)
$º$ mvn fr.jcgay.maven.plugins:buildplan-maven-plugin:list \ º
$º  -Dbuildplan.tasks=install º

- ºQuick local installº (bypass tests/style-checks/...)
$º$ mvn resources:resources \ compiler:compile \       º
$º   jar:jar \  install:install                        º

-ºAdd non-standard src dirº
  Useful when some tool auto-generates code outside the standard src/main/java diretory.
  ˂build˃
    ...
    ˂sourceDirectory˃src/main/generated_java˂/sourceDirectory˃
    
    ˂testDirectory˃src/functionalTest/java˂/testDirectory˃
  ˂/build˃
  
-ºAdd local jar dependencyº (vs. maven central repository)
  RºWARNº: discouraged, but sometimes needed
  ˂dependency˃
    ˂groupId˃   ...˂/groupId˃
    ˂artifactId˃...˂/artifactId˃
    ˂version˃   ...˂/version˃
    ˂scope˃...˂/scope˃
    ˂systemPath˃/local/path/in/my/file/system/myjar.jar˂/systemPath˃ ←
  ˂/dependency˃

-ºGenerate fat jar (jar with all dependencies included)º
  └ STEP 1: Add next profile lines to pom.xml with a fatjar profile containing 
            the custom options for the maven-assembly-plugin:
    ...
    ˂dependencies˃...˂/dependencies˃
    ˂build˃...˂/build˃
    
    ˂profiles˃
      ˂profile˃
        ˂id˃fatjar˂/id˃
       º˂activation˃º
       º    ˂property˃ ˂name˃fatjar˂/name˃ ˂/property˃º
       º˂/activation˃º
        ˂build˃
          ˂plugins˃
            ˂plugin˃
                ˂artifactId˃maven-assembly-plugin˂/artifactId˃
                ˂version˃3.0.0˂/version˃
                ˂configuration˃
                    ˂descriptorRefs˃
                        ˂descriptorRef˃jar-with-dependencies˂/descriptorRef˃
                    ˂/descriptorRefs˃
                    ˂archive˃
                        ˂manifest˃
                            ˂mainClass˃com.myComp.myApp˂/mainClass˃
                        ˂/manifest˃
                    ˂/archive˃
                ˂/configuration˃
                ˂executions˃
                   º˂execution˃               º
                   º    ˂id˃make-assembly˂/id˃º˂!-- this is used for inheritance merges --˃
                   º    ˂phase˃package˂/phase˃º˂!-- bind to the packaging phase --˃
                   º    ˂goals˃               º
                   º        ˂goal˃single˂/goalº˃
                   º    ˂/goals˃              º
                   º˂/execution˃              º
                ˂/executions˃
            ˂/plugin˃
          ˂/plugins˃
        ˂/build˃
      ˂/profile˃
  ˂/profiles˃
  └ STEP 2: Package with new profile active like:
  $º$ mvn clean compile package -Dmaven.test.skip=true -P fatjarº
                                                       ^^^^^^^^^
                                                       active profile

set Parent+Child poms
- Allows to inherit project dependency in children projects

  .../parent/pom.xml              │ .../parent/child1/pom.xml
  ─────────────────────────────── │ ──────────────────────────────────
  ˂modelVersion˃4.0.0             │ ˂parent˃
  ˂/modelVersion˃                 │   ˂groupId˃...˂/groupId˃
  ˂groupId˃....˂/groupId˃         │   ˂artifactId˃parent˂/artifactId˃
  ˂artifactId˃parent˂/artifactId˃ │   ˂version˃1˂/version˃
  ˂version˃0.1.0˂/version˃        │   ˂relativePath˃
  ˂packaging˃pom˂/packaging˃      │      ../pom.xml˂/relativePath˃
                                  │ ˂/parent˃
                                  │ ˂dependecies˃
  ˂modules˃                       │   ˂dependency˃
  ˂module˃./child1˂/module˃       │     ˂groupId˃...˂/groupId˃
  ˂module˃./child2˂/module˃       │     ˂artifactId˃...˂/artifactId˃
  ˂/modules˃                      │   ˂/dependency˃...
                                  │ ˂/dependecies˃
  ˂dependencyManagement˃           
    ˂dependencies˃                   
      ˂dependency˃                     
        ˂groupId˃...˂/groupId˃           
        ˂artifactId˃...˂/artifactId˃  
        ˂version˃X.Y.Z˂/version˃    ← NOTE: no need to repeat version/scope in childs          
        ˂scope˃compile˂/scope˃      ←
      ˂/dependency˃...                 
    ˂dependencies˃                   
  ˂/dependencyManagement˃

Install non-mavenized jar

$º$ mvn install:install-file -Dfile=path_to_local_file -DgroupId=˂groupId˃ \ º
$º  -DartifactId=˂artifactId˃ -Dversion=˂version˃ -Dpackaging=˂packaging˃    º
Maven Central
Publish artifacts to MVN Central
@[http://maven.apache.org/repository/guide-central-repository-upload.html]

Requirements

NOTE: OºOnly releases allowedº (Not snapshots)
˂?xml version="1.0" encoding="UTF-8"?˃
˂project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="... http://.../maven-v4_0_0.xsd"˃
˂modelVersion˃4.0.0˂/modelVersion˃

˂groupId˃com.u1.training˂/groupId˃
˂artifactId˃ossrh-demo˂/artifactId˃
˂version˃1.0˂/version˃
˂packaging˃jar˂/packaging˃

˂name˃${project.groupId}:${project.artifactId}˂/name˃
˂description˃demo deploy via OSSRH˂/description˃
˂url˃http://github.com/u1/ossrh-demo˂/url˃

˂licenses˃
˂license˃
  ˂name˃The Apache Software License, Version 2.0˂/name˃
  ˂url˃http://www.apache.org/licenses/LICENSE-2.0.txt˂/url˃
˂/license˃
˂/licenses˃

˂developers˃
˂developer˃
  ˂name˃Manfred Moser˂/name˃
  ˂email˃manfred@sonatype.com˂/email˃
  ˂organization˃Sonatype˂/organization˃
  ˂organizationUrl˃
    http://www.sonatype.com
  ˂/organizationUrl˃
˂/developer˃
˂/developers˃

˂scm˃
˂connection˃scm:git:git://github.com/u1/a.git˂/connection˃
˂developerConnection˃
  scm:git:ssh://github.com:u1/a.git
˂/developerConnection˃
˂url˃http://github.com/u1/a/tree/master˂/url˃
˂/scm˃

...

˂/project˃

- All projects except pom-packaging ones have to supply
OºJAR files containing Javadoc and sourcesº
- Supply Javadoc and Sources:  The naming convention is like:
artifactId"-"version"-"classifier"."packaging"
Ex:
my-artifact-id-1.4.7-sources.jar
my-artifact-id-1.4.7-javadoc.jar

- All files need to be signed with GPG/PGP including the
matching *.asc file. E.g.
example-application-1.4.7.pom          → example-application-1.4.7.pom.asc
example-application-1.4.7.jar          → example-application-1.4.7.jar.asc
example-application-1.4.7-sources.jar  → example-application-1.4.7-sources.jar.asc
example-application-1.4.7-javadoc.jar  → example-application-1.4.7-javadoc.jar.asc
- we discourage the usage of ˂repositories˃ and
˂pluginRepositories˃ and instead publish any required
components to the Central Repository

PGP Signature
- Allow to validate artifact at download against a public key server
- PGP signatures is required for artifacts (all files except checksums),
and matching public key uploaded to a server like
http://pgp.mit.edu
- Build tool integration

Publish Best patterns
- Use approved repository hosting location:
Apache Software Foundation (for all Apache projects)
FuseSource Forge (focused on FUSE related projects)
Nuiton.org

- User automatic publication in "forges" that provide hosting services

- OSS Repository Hosting
- Approved repository provided by Sonatype for OSS Project that want to
get their artifacts into Central Repository.
- Open an account as explained at
@[http://central.sonatype.org/pages/ossrh-guide.html]

Post-namespace registration
(e-mail received after Namespace correct registration)
[ Issue@Jira ]
Thad Watson resolved OSSRH-39644: Resolution: Fixed

Configuration has been prepared, now you can:
→ Deploy snapshot artifacts into repository
https://oss.sonatype.org/content/repositories/snapshots

→ Deploy release artifacts into the staging repository
https://oss.sonatype.org/service/local/staging/deploy/maven2
→ Promote staged artifacts into repository 'Releases'
→ Download snapshot and release artifacts from group
https://oss.sonatype.org/content/groups/public

→ Download snapshot, release and staged artifacts from
staging group
https://oss.sonatype.org/content/groups/staging
ºplease comment on this ticket when you promotedº
ºyour first release, thanks                     º

Test settings
@[https://www.apache.org/dev/publishing-maven-artifacts.html#test-your-settings]
- Make sure there are ºno dependencies on snapshotsº in the POMs to be released.
However, the project you want to stage must be a SNAPSHOT version
- Check that your POMs will not lose content when they are rewritten
during the release process:
- Verify that all pom.xml files have an SCM definition
- Do a dryRun release: Oºmvn release:prepare -DdryRun=trueº
Postcript: You may also wish to pass Oº-DautoVersionSubmodules=trueº
as this will save you time if your project is multi-moduled.
- Diff the original file pom.xml with the one called pom.xml.tag to
see if the license or any other info has been removed. This has been known
to happen if the starting ˂project˃ tag is ºNOTº on a single
line. The only things that should be different between these files are the
˂version˃ and ˂scm˃ elements. Any other changes you must
backport yourself to the original pom.xml file and commit before
proceeding with the release.

Deploy snapshot
@[https://www.apache.org/dev/publishing-maven-artifacts.html#publish-snapshot]
mvn deploy
...
[INFO] [deploy:deploy]
[INFO] Retrieving previous build number from apache.snapshots.https
...

Prepare release
@[https://www.apache.org/dev/publishing-maven-artifacts.html#prepare-release]
mvn release:clean
mvn release:prepare # creates new tag in SVN, automatically checking in.

Stage release for a vote
@[https://www.apache.org/dev/publishing-maven-artifacts.html#stage-release-vote]
mvn release:perform
# release will be automatically inserted in a temp staging dir
Troubleshooting
@[https://www.apache.org/dev/publishing-maven-artifacts.html#troubleshooting]

pom utils
@[https://github.com/kdgregory/pomutil]

Utilities to clean, organize, and restructure Maven POMs.

- POM Cleaner:
  "Cleans up" a single POM, normalizing plugin and dependency specifications,
  converting hardcoded versions to properties, consitently ordering top-level
  elements, and pretty-printing the output.
  There is also a version of this tool that runs as a web-app.

- Version Updater:
  Updates the version for a set of POMs, either to a specified version or the
  next sequential version.

- Dependency Check:
  Examines a project to find dependencies that are specified but unused, and
  those that are used but unspecified (ie, transitive dependencies that
  should be direct).
  Jib: Image Builder
Docker+mvn/gradle integration:
@[https://www.infoq.com/news/2018/08/jib]
@[https://github.com/GoogleContainerTools/jib]

- Build Java Container without Docker/Dockerfile
- Jib's build approach separates the Java application
  into multiple layers, so when there are any code changes,
  only those changes are rebuilt, rather than the entire application.
- these layers are layered on top of a distroless base image.
  containing only the developer's application and its runtime deps.

- ºDocker build flow º
        │JAR│ ← (build) ← │Project│
          │                                                              │Container │
          ├─────→ │Build Context│ →(build)→ │ Container Image │ →(push)→ │Image     │
          │                                 │ (docker cache)  │          │(registry)│
     │Dockerfile│

  ºJib Build Flow:º
                                                                         │Container │
     │Project│ ───────────────(Jib)─────────────────────────────────────→│Image     │
                                                                         │(registry)│
Gradle
Wrapper
REF: @[https://docs.gradle.org/current/userguide/gradle_wrapper.html]
- recommended way to execute any Gradle build
- invokes gradle with a declared version (vs randomnly installed one in OS).
  (robust builds)
- invokes with a declared version of Gradle.

- Workflow:
- set up a new Gradle project
- add Wrapper to new project
  (a gradle runtime must be instaled)
  $ gradle wrapper \
    --gradle-version 5.1 \      optional
    --distribution-type bin  \  optional
    --gradle-distribution-url ...  optional
    --gradle-distribution-sha256-sum  ... optional

The SHA256 hash sum used for verifying the downloaded Gradle distribution.

  → Task :wrapper
  →
  → BUILD SUCCESSFUL in 0s
  → 1 actionable task: 1 executed
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  .
  ├── build.gradle
  ├── settings.gradle
  ├──ºgradle                           º←  generated dir. to be added to git
  │  º└── wrapper                      º
  │  º    ├── gradle-wrapper.jar       º ← code for downloading the distro
  │  º    └── gradle-wrapper.propertiesº
  ├──ºgradlew    º   ← once generated, use it like $ ./gradlew build
  └──ºgradlew.batº
  gradle/wrapper/gradle-wrapper.properties  is generated
  with the information about the Gradle distribution:
   - server hosting the Gradle dist. Ex:
     distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip
   - type of Gradle dist.
     (default to -bin dist with only runtime -no sample code,docs,...)
   - The Gradle version used for executing the build.
     (default to local installed one)

- Check generated wrapper files to "git",
  including the (small) jar files.
- run a project with provided Wrapper
  ...
- upgrade the Wrapper to new Gradle version when desired.

- ºCustomizing the wrapperº
  - built-in wrapper task exposes numerous options
  to bend the runtime behavior to your needs.
  build.gradle.kts:
  build.tasks.wrapper {
    distributionType = Wrapper.DistributionType.ALL
  }

- HTTP Basic Authentication (r*WARN: use only with TLS connections)
  alt 1: ENV.VARS:
  systemProp.gradle.wrapperUser=username
  systemProp.gradle.wrapperPassword=password
  alt 2: gradle/wrapper/gradle-wrapper.properties
  distributionUrl=https://username:password@somehost/path/to/gradle-distribution.zip

- ºVerifying downloadº
  @gradle/wrapper/gradle-wrapper.properties:
  distributionSha256Sum=371cb9fbebbe9880d147f59bab36d61eee122854ef8c9ee1ecf12b82368bcf10

Multi-module Deployer
@[https://github.com/FlamingTuri/multi-module-deployer]
  (Java Example project available in github)
- library built to speed up the deployment of microservice based applications.
- build and run each application module
- configure deployment dependencies between modules
  by just creating and running a simple application.

└ Installation
  1) Add to your build.gradle the following function:
   def downloadLibFromUrl(String libSaveDir, String libName, String libUrl) {
       def folder = new File(libSaveDir)
       if (!folder.exists()) {
           folder.mkdirs()
       }
       def file = new File("$libSaveDir/$libName")
       if (!file.exists()) {
           ant.get(src: libUrl, dest: file)
       }
       getDependencies().add('compile', fileTree(dir: libSaveDir, include: libName))
   }
  
  2) the following code to your dependencies declaration:
   dependencies {
       /* ... */
       def libSaveDir = "${System.properties['user.home']}/.gradle/caches/modules-2/files-2.1"
       def version = '1.1.1'
       def libName = "multi-module-deployer-${version}.jar"
       def url = "https://github.com/FlamingTuri/multi-module-deployer/releases/download/v$version/$libName"
       downloadLibFromUrl(libSaveDir, libName, url)
   }

└ Usage example

  import multi.module.deployer.MultiModuleDeployer;
  import multi.module.deployer.moduleconfig.ModuleConfig;
  import multi.module.deployer.moduleconfig.ModuleConfigFactory;
  
  public class App {
    public static void main(String[] args) {
        MultiModuleDeployer multiModuleDeployer = new MultiModuleDeployer();
        // commands to run the first module
        String   linuxCmd = "linux commands to deploy first module";
        String windowsCmd = "windows commands to deploy first module";
        ModuleConfig firstModuleConfig =
          ModuleConfigFactory.httpModuleConfig(linuxCmd, windowsCmd, 8080, "localhost", "/api/...");
        // adds the first configuration to the deployment list
        multiModuleDeployer.add(firstModuleConfig);
  
        // commands to run the second module
        linuxCmd = "linux commands to deploy second module";
        windowsCmd = "windows commands to deploy second module";
        ModuleConfig secondModuleConfig = ModuleConfigFactory.httpModuleConfig(linuxCmd, windowsCmd, 3000, "localhost", "/api/...");
  
        // adds the second configuration to the deployment list
        // it will be started only after the first one is "ended"
        multiModuleDeployer.add(secondModuleConfig);
  
        // deploys the modules
        multiModuleDeployer.deploy();
    }
  }
What's New
- Gradle v6: 
@[https://www.infoq.com/news/2020/01/gradle-releases-version-6/]
DDBB/persistence
Jooq
 SQL made simple
@[https://www.jooq.org/]

- vertx-jooq
  jOOQ-CodeGenerator to create vertxified DAOs and POJOs.
  Now with JDBC, async and reactive support!
@[https://github.com/jklingsporn/vertx-jooq]
Hibernate
@[https://quarkus.io/guides/hibernate-orm-panache-guide]
OpenJPA
@[https://openjpa.apache.org/]
reladomo
(by Goldman Sachs)
@[https://github.com/goldmansachs/reladomo]
enterprise grade (ORM) object-relational mapping framework for Java with the following enterprise features:

- Strongly typed Bºcompile-timeº checked query language
- Bi-temporal chaining
- Transparent multi-schema support
- Full support for unit-testable code
c3p0
@[https://www.mchange.com/projects/c3p0/#what_is]

c3p0 is an easy-to-use library for making traditional JDBC drivers
"enterprise-ready" by augmenting them with functionality defined by the jdbc3
spec and the optional extensions to jdbc2. As of version 0.9.5, c3p0 fully
supports the jdbc4 spec.

In particular, c3p0 provides several useful services:

- A class whichs adapt traditional DriverManager-based JDBC drivers to the
  newer javax.sql.DataSource scheme for acquiring database Connections.
- Transparent pooling of Connection and PreparedStatements behind DataSources
  which can "wrap" around traditional drivers or arbitrary unpooled DataSources.

The library tries hard to get the details right:
- c3p0 DataSources are both Referenceable and Serializable, and are thus
  suitable for binding to a wide-variety of JNDI-based naming services.
- Statement and ResultSets are carefully cleaned up when pooled Connections
  and Statements are checked in, to prevent resource- exhaustion when clients use
  the lazy but common resource-management strategy of only cleaning up their
  Connections. (Don't be naughty.)
- The library adopts the approach defined by the JDBC 2 and 3 specification
  (even where these conflict with the library author's preferences). DataSources
  are written in the JavaBean style, offering all the required and most of the
  optional properties (as well as some non-standard ones), and no-arg
  constructors. All JDBC-defined internal interfaces are implemented
  (ConnectionPoolDataSource, PooledConnection, ConnectionEvent-generating
  Connections, etc.) You can mix c3p0 classes with compliant third-party
  implementations (although not all c3p0 features will work with external
  implementations of ConnectionPoolDataSource).
Snappy Fast de/compressor
@[https://github.com/xerial/snappy-java]
- Java port of the snappy http://code.google.com/p/snappy/
Cache
JCache
- Map-Like API optimized for caching.
- 1.0 drawbacks:
  - No async operations.
- Implemented by Hazelcast and others
JSON
JSON
- TODO: Patterns of JSON Matching:
  Streaming based, binding based, expression based.
@[https://dzone.com/articles/patterns-of-reading-json?edition=598293]
- REF:JSON processing public review
  @[https://www.infoq.com/news/2017/03/json-processing-public-review]

Public review of JSR 374:
- Java API for JSON Processing (JSON-P) version 1.1 is now open.
  This version is expected to be included in the release of J2EE 8 
  and keeps JSON-P current with JSON IETF standards. It includes 
  support for:
    - JSON Pointer
    - JSON Patch
    - JSON Merge Patch
    - Query and transformation operations
    - Java 8 streams and lambdas
- JSON-P was introduced in 2013 with the release of J2EE 7, as
  an alternative to Gson and Jackson. It was designed to parse, generate,
  and query standard JSON documents.
  SR-367: Java API for JSON Binding (JSON-B), will also be included in the 
  release of J2EE 8.

- Example:
  package com.mycomp.project1;
  
  import java.io.BufferedReader;
  import java.io.DataOutputStream;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.net.HttpURLConnection;
  import java.net.URL;
  import java.security.KeyManagementException;
  import java.security.NoSuchAlgorithmException;
  
  import javax.net.ssl.HttpsURLConnection;
  import javax.net.ssl.SSLContext;
  import javax.net.ssl.SSLSocketFactory;
  import javax.net.ssl.HostnameVerifier;
  import javax.net.ssl.SSLSession;
  import javax.net.ssl.TrustManager;
  import javax.net.ssl.X509TrustManager;
  
  import org.json.JSONObject;
  
  import java.security.cert.X509Certificate;
  import java.util.Date;
  
  import java.util.Scanner;
  
  public class TestAPI˂JSONArray˃ {
      static String userpass = "operator1:ecllqy";
      private static SSLSocketFactory sslSocketFactory = null;
  
      private JSONObject sendPost(String url, String post_body, String token) throws Exception
      {
          URL obj = new URL(url);
          String basicAuth = "Basic " +
              javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes());
  
          HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
  
          setAcceptAllVerifier((HttpsURLConnection)con); // TODO: WARN Add certificate validation.
  
          con.setRequestMethod("POST"); //add request header
          con.setRequestProperty("Content-Type", "application/json");
          con.setRequestProperty("Cache-Control", "no-cache");
          if (token.isEmpty()) { con.setRequestProperty("Authorization", basicAuth);
          } else               { con.setRequestProperty("Authorization", "Bearer "+token);
          }
          con.setDoOutput(true);
          DataOutputStream wr = new DataOutputStream(con.getOutputStream());
          wr.writeBytes(post_body);
          wr.flush();
          wr.close();
          int responseCode = con.getResponseCode();
  
          BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
          StringBuffer response = new StringBuffer();
          String inputLine; while ((inputLine = in.readLine()) != null) { response.append(inputLine); }
          in.close();
          return new JSONObject(response.toString()); //String myJSONStr
      }
  
  
      /*ºººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººººº*/
      /**
       * Overrides the SSL TrustManager and HostnameVerifier to allow
       * all certs and hostnames.
       * WARNING: This should only be used for testing, or in a "safe" (i.e. firewalled)
       * environment.
       *
       * @throws NoSuchAlgorithmException
       * @throws KeyManagementException
       */
      protected static void setAcceptAllVerifier(HttpsURLConnection connection) throws NoSuchAlgorithmException, KeyManagementException {
          // Create the socket factory.
          // Reusing the same socket factory allows sockets to be
          // reused, supporting persistent connections.
          if( null == sslSocketFactory) {
              SSLContext sc = SSLContext.getInstance("SSL");
              sc.init(null, ALL_TRUSTING_TRUST_MANAGER, new java.security.SecureRandom());
              sslSocketFactory = sc.getSocketFactory();
          }
  
          connection.setSSLSocketFactory(sslSocketFactory);
  
          // Since we may be using a cert with a different name, we need to ignore
          // the hostname as well.
          connection.setHostnameVerifier(ALL_TRUSTING_HOSTNAME_VERIFIER);
      }
  
      private static final TrustManager[] ALL_TRUSTING_TRUST_MANAGER = new TrustManager[] {
          new X509TrustManager() {
              public X509Certificate[] getAcceptedIssuers() {
                  return null;
              }
              public void checkClientTrusted(X509Certificate[] certs, String authType) {}
              public void checkServerTrusted(X509Certificate[] certs, String authType) {}
          }
      };
  
      private static final HostnameVerifier ALL_TRUSTING_HOSTNAME_VERIFIER  = new HostnameVerifier() {
          public boolean verify(String hostname, SSLSession session) {
              return true;
          }
      };
  }
RESTAssured: REST API testing
ºFULL JOURNEY == Simulate full (REST) API in expected orderº
└ Pre-Setup:
  ˂dependency˃
      ˂groupId˃io.rest-assured˂/groupId˃
      ˂artifactId˃scala-support˂/artifactId˃
      ˂version˃3.0.6˂/version˃
      ˂scope˃test˂/scope˃
  ˂/dependency˃
  ˂dependency˃
      ˂groupId˃io.rest-assured˂/groupId˃
      ˂artifactId˃json-schema-validator˂/artifactId˃
      ˂version˃3.0.6˂/version˃
      ˂scope˃test˂/scope˃
  ˂/dependency˃

└ Ussage Example:
  package com.mycompany.myproject.mymodule;
  
  import static junit.framework.TestCase.assertTrue;
  import static org.hamcrest.Matchers.*;
  
  import static io.restassured.RestAssured.given;
  
  import io.restassured.RestAssured;
  import io.restassured.config.HttpClientConfig;
  import io.restassured.path.json.JsonPath;
  import io.restassured.response.Response;
  import io.restassured.specification.RequestSpecification;
  import junit.framework.TestCase;
  import org.apache.http.client.HttpClient;
  import org.apache.http.impl.client.SystemDefaultHttpClient;
  import org.apache.http.params.HttpConnectionParams;
  import org.apache.http.params.HttpParams;
  import org.eclipse.jetty.http.HttpStatus;
  import org.junit.Ignore;
  import org.junit.Test;
  import org.junit.BeforeClass;
  
  import org.hamcrest.BaseMatcher;
  import org.hamcrest.Description;
  
  import java.util.Base64;
  import java.util.Map;
  
  public class FullJourneyTest {
  
      // Custom regex matcher for RestAssured Framework
      public static classBºRegexMatcherºextendsºBaseMatcher˂Object˃º{
          private final String regex;
          public BºRegexMatcherº(String regex){ this.regex = regex; }
         º@Overrideºpublic booleanºmatchesº(Object o){ return ((String)o).matches(regex); }
         º@Overrideºpublic voidºdescribeToº(Description description){
              description.appendText("matches regex=");
          }
          public staticBºRegexMatcherº matches(String regex){ return newBºRegexMatcherº(regex); }
      }
  
       public static classGºBase64MatcherºextendsºBaseMatcher˂Object˃º{
          public Base64Matcher(){}
         º@Overrideºpublic booleanºmatchesº(Object o){
              try {
                  Base64.getDecoder().decode((String)o);
                  return true;
              }catch (Exception e){
                  return false;
              }
          }
  
         º@Overrideºpublic voidºdescribeToº(Description description){
              description.appendText("can be parsed as Base64");
          }
  
          public static Base64Matcher isBase64Encoded(){
              return new Base64Matcher();
          }
      }
      private static final String AUTH_HEADER_VALUE = "Bearer " + ServerConfig.apiKey;
  
      protected static RequestSpecification setupCommonHeaders() {
          return given().header("Authorization", AUTH_HEADER_VALUE)
                        .header("Accept"       , "application/json")
                        .header("content-type" , "application/json;charset=utf-8")
          .log().all();
      }
  
  
      final String
          NAME="COMMUNITY_1", SYMBOL="SY1";
  
      Response response;
    Qº@BeforeClassº
      public static void setup() {
          RestAssured.port     = ServerConfig.serverPort;
          RestAssured.basePath = "/";
          RestAssured.baseURI  = "http://localhost";
  
          HttpClientConfig clientConfig = RestAssured.config().getHttpClientConfig();
          clientConfig = clientConfig.httpClientFactory(new HttpClientConfig.HttpClientFactory() {
              @Override
              public HttpClient createHttpClient() {
                  HttpClient rv =  new SystemDefaultHttpClient();
                  HttpParams httpParams = rv.getParams();
                  //  Wait 5s max for a connection
                  HttpConnectionParams.setConnectionTimeout(httpParams, 5 * 1000);
                  // Default session is 60s
                  HttpConnectionParams.setSoTimeout(httpParams, 60 * 1000);
                  return rv;
              }
          });
          // This is necessary to ensure, that the client is reused.
          clientConfig = clientConfig.reuseHttpClientInstance();
          RestAssured.config = RestAssured.config().httpClient(clientConfig);
      }
  
    Qº@Testº
      public void A010_PutNewCommunityAndNewUserForPendingToMineCommunity() {
          String jsonBody =
              "{ " +
                  " \"name\": \""+NAME+"\", " +
                  " \"symbol\": \"" + SYMBOL + "\","
              "}";
          response = setupCommonHeaders().body(jsonBody).when().ºpost("/Route/To/REST/API/01")º;
          System.out.println(response.body().prettyPrint());
          response.then()
              /* ºget sure JSON serializer do not include extra (maybe sensitive) infOº */
              .body("size()", Oºis(5)                          º)
              .body("id"    , Oºnot(isEmptyString())           º)
              .body("pubkey", Oºnot(isEmptyString())           º)
              .body("pubkey", BºRegexMatcherºOº.matches("^{65}$")º)
              .body("pubkey", OºBase64Matcher.isBase64Encoded()º)
              .body("name"  , OºequalTo(NAME)                  º)
              .body("symbol", OºequalTo(SYMBOL)                º)
              .statusCode(HttpStatus.ACCEPTED_202);
          String BºNEW_ID = response.getBody().jsonPath().get("id")º;
  
          // Next related test to execute synchronously after fetching NEW_ID
          String jsonBody =
              "{ " +
                  B*" \"FK_ID\": \""+NEW_ID+"\", " +*
                  ...
              "}";
  
          response = setupCommonHeaders().body(jsonBody).when().ºpost("/Route/To/REST/API/02")º;
          ...
      }
  }
BDD Serenity Testing
@[https://serenity-bdd.github.io/theserenitybook/latest/index.html]

- Serenity BDD is an open source library that aims to make the idea of living
  documentation a reality.

- write cleaner and more maintainable automated acceptance and 
  regression tests faster. Serenity also uses the test results to 
  produce illustrated, narrative reports that document and describe 
  what your application does and how it works. Serenity tells you not 
  only what tests have been executed, but more importantly, what 
  requirements have been tested.

- One key advantage of using Serenity BDD is that you do not have to invest time
  in building and maintaining your own automation framework.

- Serenity BDD provides strong support for different types of automated acceptance testing, including:
  - Rich built-in support for web testing with Selenium.
  - REST API testing with RestAssured.
  - Highly readable, maintainable and scalable automated testing with the
    Screenplay pattern.

- The aim of Serenity is to make it easy to quickly write well-structured,
  maintainable automated acceptance criteria, using your favourite BDD or
  conventional testing library. You can work with Behaviour-Driven-Development
  tools like Cucumber or JBehave, or simply use JUnit. You can integrate with
  requirements stored in an external source (such as JIRA or any other test cases
  management tool), or just use a simple directory-based approach to organise
  your requirements.
JBehave
- framework for Behaviour-Driven Development (BDD). BDD is an 
  evolution of test-driven development (TDD) and acceptance-test driven 
  design, and is intended to make these practices more accessible and 
  intuitive to newcomers and experts alike. It shifts the vocabulary 
  from being test-based to behaviour-based, and positions itself as a 
  design philosophy.

1 Write story
Scenario: A trader is alerted of status
Given a stock and a threshold of 15.0
When stock is traded at 5.0
Then the alert status should be OFF
When stock is traded at 16.0
Then the alert status should be ON

2 Map to java

3 Configure Stories

4 Run Stories
GraalVM
GraalVM Summary
@[http://www.graalvm.org/]
@[https://technology.amis.nl/2018/11/23/comparing-jvm-performance-zulu-openjdk-openjdk-oracle-jdk-graalvm-ce/]
@[https://www.reddit.com/r/java/comments/acarqq/graalvm_in_2018/]

- Graal: How to Use the New JVM JIT Compiler in Real Life
  @[https://www.infoq.com/presentations/graal-jvm-jit/]

- GraalVM Native Image
@[https://www.graalvm.org/docs/reference-manual/native-image/]
º"native-image"º utility:
 - ahead-of-time compiler to a Bºstandalone executableº.
 - JVM is replaced with necesary  components (memory mngr,
   Thread scheduler) in "Substrate VM" runtime:
   Substrate VM runtime is actually the name for the runtime components
   (like the deoptimizer, garbage collector, thread scheduling etc.).
 - Result has faster startup time and lower runtime memory .
 - It statically analyses which classes and methods are reachable
   and used during application execution and passes all this
   reachable code as the input to the GraalVM compiler for
   ahead-of-time compilation into native-library.
Ex Ussage:
@[https://github.com/web3j/svm/blob/master/generate_native_image.sh]
  # tested with graalvm 19.3.1
  ./gradlew spotlessApply
  ./gradlew build
  ./gradlew shadowJar  // ← create fat JARs, relocate packages for apps/libs
  cd "build/libs" || exit
  native-image \
     -cp svm-1.0-SNAPSHOT-all.jar \
     org.web3j.svm.MainKt \
     --no-fallback \
     --enable-https \
     --enable-http
Quarkus
GraalVM
Framework
@[https://quarkus.io/guides/]
@[https://quarkus.io/guides/kogito-guide]
@[https://quarkus.io/guides/using-vertx.html]
..
@[https://www.infoq.com/news/2019/03/redhat-release-quarkus]

Extracted from "Hibernate with Panache" by Emmanuel Bernard.
""" Quarkus is Supersonic Subatomic Java. extremely fast with low memory footprint""".
@[https://quarkus.io/guides/hibernate-orm-panache-guide]
Hibernate ORM is the de facto JPA implementation and offers you the full
breadth of an Object Relational Mapper. It makes complex mappings possible,
but it does not make simple and common mappings trivial. Hibernate ORM with
Panache focuses on making your entities trivial and fun to write in Quarkus.
Tech Radar
LMAX Disruptor: High Perf Inter-Thread Messaging Library
@[https://lmax-exchange.github.io/disruptor/]

See also:
@[https://www.infoq.com/articles/High-Performance-Java-Inter-Thread-Communications/]

@[https://www.infoq.com/news/2013/05/lmax-zing]
LMAX Exchange Getting Up To 50% Improvement in Latency From Azul's Zing JVM
Interesting points about GC tunning.
Java Value Types proposal
@[https://www.infoq.com/news/2017/11/ValueTypesNov10]
            ┌────────────────────────────┬───────────────────────────────────────
            │ "NOW" (2019─12)            │ "FUTURE"
            │ + primitive types          │ + primitive types
            │ + object references:       │ + object references:
            │ ─ NO low─level mem.control │ + Value types
            │   (deliberately)           │
────────────┼────────────────────────────┼───────────────────────────────────────
PROS:       │ ─ Great simplicity         │ ─ Memory layout efficiency
            │                            │ ─ removes the need for
            │                            │   a full object header
            │                            │   for each item of composite data.
            │                            │ ─ header removal
            │                            │   =→ instance metadata removal
────────────┼────────────────────────────┼───────────────────────────────────────
CONS:       │ performance penalties      │ ─ Higher complexity
            │ ─ indirections in arrays   │ ─ object's identity is lost
            │ ─ cache misses.            │ ─ new bytecodes needs to be introduced
────────────┴────────────────────────────┴───────────────────────────────────────
Tribe: reliable multicast
REF: @[http://tribe.ow2.org/]
- Unlike JGroups, Tribe only targets reliable multicast
 (no probabilistic delivery) and is optimized for cluster
 communications.
JGroups multicast
@[http://www.jgroups.org/]
- toolkit for reliable multicast communication.
- point-to-point FIFO communication channels (basically TCP)
- Targets high performance cluster environments.

- Unlike JGroups, Tribe only targets reliable multicast
  (no probabilistic delivery) and is optimized for
  cluster communications.
Apache MINA:Netty Alt.
Apache MINA vs Netty: https://www.youtube.com/watch?v=A2pWsxPWJuc

Apache MINA is a network application framework which helps users develop high
performance and high scalability network applications easily. It provides an
abstract event-driven asynchronous API over various transports such as TCP/IP
and UDP/IP via Java NIO.

Apache MINA is often called:
- NIO framework library
- client server framework library, or
- a networking socket library

Apache MINA comes with many subprojects :
- Asyncweb : An HTTP server build on top of MINA asynchronous framework
- FtpServer : A FTP server
- SSHd : A Java library supporting the SSH protocol
- Vysper : An XMPP server
OSV.io
- @[http://osv.io/]
  versatile modular unikernel designed to run unmodified Linux
  applications securely on micro-VMs in the cloud. Built from the ground up for
  effortless deployment and management of micro-services and serverless apps,
  with superior performance. (Includes CRaSH shell)
AsyncAPI.org
@[https://www.asyncapi.org/]
- Building the future of event-driven architectures.
- Open source tools to easily build and maintain your event-driven architecture.
- All powered by the AsyncAPI specification, the industry standard for defining
  asynchronous APIs.

Non-Classiffied
Google Guava
JS transpilers
- JSweet.org: Java to Javascript transpiler:

@[http://teavm.org/]
  TeaVM is an ahead-of-time compiler for Java bytecode that emits JavaScript
  and WebAssembly that runs in a browser. Its close relative is the well-known
  GWT. The main difference is that TeaVM does not require source code, only
  compiled class files. Moreover, the source code is not required to be Java,
  so TeaVM successfully compiles Kotlin and Scala.

- @[https://www.infoq.com/news/2019/05/j2cl-java-javascript-transpiler/]
"https://en.wikipedia.org/wiki/Java_virtual_machine#Compilation_to_JavaScript
""Main JVM bytecode to JavaScript compilers are TeaVM,[20] the compiler
contained in Dragome Web SDK,[21] Bck2Brwsr,[22] and j2js-compiler.[23]"""
Crypto.API(JCA)
- See also:
  Bounce Castle FIPS JCA provider
Javalin: Kiss Kotlin/Java web framework
@[https://javalin.io]
- Inspired by Javascript KOA.js framework

- Ex: Declare server and API in the same place
  | import io.javalin.ApiBuilder.*;
  | import io.javalin.Javalin;
  |
  | Javalin app = Javalin.create(config -˃ {
  |     config.defaultContentType = "application/json";
  |     config.addStaticFiles("/public");
  |     config.enableCorsForAllOrigins();
  | }).routes(() -˃ {
  |     path("users", () -˃ {
  |         get(UserController::getAll);
  |         post(UserController::create);
  |         path(":user-id", () -˃ {
  |             get(UserController::getOne);
  |             patch(UserController::update);
  |             delete(UserController::delete);
  |         });
  |         ws("events", userController::webSocketEvents);
  |     });
  | }).start(port);
JNR(JNI/UNIX friendly)
( used by Netty and others...)
-@[https://github.com/jnr/jnr-ffi]
   load native libraries without writing JNI code by hand, or using tools such as SWIG.
-@[https://github.com/jnr/jnr-unixsocket]
   jnr-unixsocket: UNIX domain sockets (AF_UNIX) for Java
-@[https://github.com/jnr/jnr-enxio]
   Java Native Runtime Enhanced X-platform I/O
-@[https://github.com/jnr/jnr-x86asm]
   Pure java x86 and x86_64 assembler
-@[https://github.com/jnr/jnr-a64asm]
  AArch64 assembler for the Java Native Runtime
-@[https://github.com/jnr/jnr-process]
  A ProcessBuilder look-alike based entirely on native POSIX APIs
-...
Modules (1.9+)
JSR 376
- implemented within project Jigsaw.

module:
- named, self-describing collection of code and data.
-  Its code is organized as a set of packages containing types
   (JVM classes and interfaces).
- its data includes resources and other kinds of static information.
Java Erasure
- Type Erasure is a technique employed the Java compiler to support the use of Generics.
@[https://developer.ibm.com/recipes/tutorials/java-language-type-erasure/]
JAAS
@[https://en.wikipedia.org/wiki/Java_Authentication_and_Authorization_Service]
- Sort of Plugable Authentication similar to the UNIX PAM.
Eclipse Microprofile
@[https://dzone.com/articles/microprofile-5-things-you-need-to-know]

- launched at JavaOne 2016 to address the shortcomings in the Enterprise Java microservices space.

- MicroProfile specifies a collection of Java EE APIs and technologies which together
  form a core baseline microservice that aims to deliver application portability across multiple runtimes.

- MicroProfile 1.0 spec includes a subset of the 30+ Java Enterprise specifications:
  - JAX-RS 2.0 for RESTful endpoints
  - CDI 1.1 for extensions and dependency injection
  - JSON-P 1.0 for processing JSON messages.

- MicroProfile 1.2  (September 2017) include:
  - Configuration 1.1
  - Fault Tolerance
  - JWT
  - Metrics
  - Health Check

- MicroProfile 2.0 (Future). It is expected it will align all APIs to Java EE 8.

- vendors runtime support:
  - WebSphere Liberty IBM
  - TomEE from Tomitribe
  - Payara
  - RedHat's WildFly Swarm
  - KumuluzEE.

- Community support:
  - London Java Community
  - SOUJava
  - ...

- key code sample consists of four microservices and a front-end application.
  Vendor            |     JAR |      StartUp
                    | size/Mb | Time in Secs
  WebSphere Liberty |   35    |            7
  WildFly Swarm     |   65    |            6
  Payara            |   33    |            5
  TomEE             |   35    |            3
  KumuluzEE*        |   11    |            2

- CDI-Centric Programming Model
  - Context and Dependency Injection specification
  - Two of its most powerful features are interceptors and observers.
    - Interceptors perform cross-cutting tasks that are orthogonal to business logic
      such as auditing, logging, and security
    - The baked-in event notification model implements the observer
      pattern to provide a powerful and lightweight event notification system
      that can be leveraged system-wide.
Concurrency Classes Video
@[https://www.youtube.com/watch?v=8yD0hHAz3cs&list=PLw8RQJQ8K1ySGcb3ZP66peK4Za0LKf728&index=4]
JavaPoet
@[https://github.com/square/javapoet]
- Library/API for generating .java source files.
- Useful for things like:
  - annotation processing
  - interacting with metadata files (e.g., database schemas, protocol formats).
  - Transpiler (language A → Java Src ).
  Bºkeeping a single source of truth for the metadataº.
Avian Embedded JVM
https://readytalk.github.io/avian/  ("Embedded java")
- lightweight JVM+class library designed to provide a useful subset 
  of Java’s features, suitable for building self-contained 
  applications.

From Mike's blog:
https://blog.plan99.net/kotlin-native-310ffac94af2
""" Avian is a lightweight virtual machine and class library designed 
    to provide a useful subset of Java’s features, suitable for 
    building self-contained applications.
    
     So says the website. They aren’t joking. The example app demos use 
    of the native UI toolkit on Windows, MacOS X or Linux. It’s not a 
    trivial Hello World app at all, yet it’s a standalone 
    self-contained binary that clocks in at only one megabyte. In 
    contrast, "Hello World" in Go generates a binary that is 1.1mb in 
    size, despite doing much less.
    
     Avian can get these tiny sizes because it’s fully focused on doing 
    so: it implements optimisations and features the standard HotSpot JVM 
    lacks, like the use of LZMA compression and ProGuard to strip the 
    standard libraries. Yet it still provides a garbage collector and a 
    JIT compiler. """


R2DBC API
@[https://www.infoq.com/news/2018/10/springone-r2dbc]
  Experimental Reactive Relational Database Connectivity Driver, R2DBC, Announced at SpringOne

  Ex:
  connectionFactory.create()
    .flatMapMany ( conn -˃
       conn.createStatement ( "SELECT value FROM test" )
          .execute()
            .flatMap (result -˃ 
              result.map(( row, metadata -→ row.get("value"))))
Panama
- Non-Java foreign-function and data interfaces, including 
  native function calling from JVM (C, C++), and native data access 
  from JVM or inside JVM heap
Nailgun
- Nailgun is a client, protocol, and server for running Java programs
  from the command line without incurring the JVM startup overhead.

- Programs run in the server (which is implemented in Java), and are
  triggered by the client (written in C), which handles all I/O.

@[https://github.com/facebook/nailgun]
Lint4j
@[http://www.jutils.com/]
- static Java source and byte code analyzer that detects locking and 
threading issues, performance and scalability problems, and checks 
complex contracts such as Java serialization by performing type, data 
flow, and lock graph analysis.
9 Profiling tools
@[https://blog.idrsolutions.com/2014/06/java-performance-tuning-tools/]
- Ref: http://java.jiderhamn.se/2012/02/26/classloader-leaks-v-common-mistakes-and-known-offenders/
  Logging frameworks such as Apache Commons Logging (ACL) – 
  formerly Jakarta Commons Logging (JCL) – log4j and 
  java.util.logging (JUL) will cause classloader leaks under some 
  circumstances.

  Apache Commons Logging will cause trouble if the logging framework 
  is supplied outside of the web application, such as within the 
  Application Server. In such a case, you need to add a bit of cleanup 
  code to the ServletContextListener we’ve talked about:

  org.apache.commons.logging.LogFactory.release(Thread.currentThread().getContextClassLoader());

  or

  org.apache.commons.logging.LogFactory.release(this.getClass().getClassLoader());

  There is an article about this on the Apache Commons Wiki. It is also mentioned in the guide and FAQ.
3 NIO ways to read files 
@[https://howtodoinjava.com/java7/nio/3-ways-to-read-files-using-java-nio/]
- read small file using ByteBuffer and RandomAccessFile
- FileChannel and ByteBuffer to read large files
- Example 3: Reading a file using memory-mapped files in Java
Obevo
@[https://github.com/goldmansachs/obevo]
- database deployment tool that handles enterprise scale schemas and complexity

""" Deploying tables for a new application?
  Or looking to improve the DB Deployment of a years-old system with 
  hundreds (or thousands) of tables, views, stored procedures, and 
  other objects?

  Obevo has your use case covered.

  Supported platforms: DB2, H2, HSQLDB, Microsoft SQL Server, MongoDB, 
  Oracle, PostgreSQL, Redshift (from Amazon), Sybase ASE, Sybase IQ
"""
Tablasco
@[https://github.com/goldmansachs/tablasco]
- JUnit rule for comparing tables and Spark module for comparing large data sets
JHipster
@[https://www.jhipster.tech/]
JHipster is a development platform to generate, develop and deploy 
Spring Boot + Angular / React / Vue Web applications and Spring 
microservices.