<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5721461121197482632</id><updated>2026-03-26T04:31:18.757-07:00</updated><category term="java"/><category term="java8"/><category term="mac osx"/><category term="tapestry5"/><category term="vim"/><category term="spring"/><category term="ruby"/><category term="linux"/><category term="tomcat"/><category term="archlinux"/><category term="blogger"/><category term="design pattern"/><category term="phpbb"/><category term="rabbitmq"/><category term="rack"/><category term="rails"/><category term="restTemplate"/><category term="apache"/><category term="function interface"/><category term="functional interface"/><category term="google"/><category term="javascript"/><category term="jdk"/><category term="kafka"/><category term="lambda"/><category term="mongodb"/><category term="notational velocity"/><category term="pacman"/><category term="redmine"/><category term="rtorrent"/><category term="strategy pattern"/><category term="thread"/><category term="ubuntu"/><category term="vsftpd"/><category term="Activity broadcast"/><category term="Asynchronous"/><category term="BiFunction"/><category term="Concurrent"/><category term="JAAS"/><category term="JNI"/><category term="Mockito"/><category term="Observable"/><category term="Observer"/><category term="Optional"/><category term="Parallel"/><category term="Project Lombok"/><category term="Quartz"/><category term="SASL"/><category term="UnaryOperator"/><category term="amazon s3"/><category term="ant"/><category term="apple"/><category term="applet"/><category term="ate memory"/><category term="books"/><category term="bytecode"/><category term="certificate"/><category term="chrome"/><category term="classloader"/><category term="cli"/><category term="comparable"/><category term="comparator"/><category term="cron expression"/><category term="curl"/><category term="daemon"/><category term="data class"/><category term="default methods"/><category term="dictionary"/><category term="duration"/><category term="eaccelerator"/><category term="equals"/><category term="event-bus"/><category term="ffmpeg"/><category term="framework"/><category term="functional"/><category term="gist-embed"/><category term="github"/><category term="guava"/><category term="hashCode"/><category term="hibernate"/><category term="high-throughput"/><category term="html5"/><category term="http"/><category term="httpclient"/><category term="https"/><category term="httpstat"/><category term="import"/><category term="intellij idea"/><category term="interface"/><category term="io"/><category term="iphone"/><category term="jar"/><category term="java functional interface"/><category term="java swing"/><category term="java7"/><category term="java_home"/><category term="jdbc"/><category term="jmx"/><category term="jmxterm"/><category term="jquery"/><category term="jvm"/><category term="kerberos"/><category term="kuo"/><category term="lambda expression"/><category term="libraries"/><category term="linkedin"/><category term="log4j"/><category term="logback"/><category term="low memory"/><category term="macbook pro"/><category term="map"/><category term="maven"/><category term="meta-programming"/><category term="method reference"/><category term="mod_jk"/><category term="mod_pagespeed"/><category term="mp3"/><category term="network"/><category term="notify"/><category term="notifyall"/><category term="openjdk"/><category term="ordering"/><category term="outlook"/><category term="partition"/><category term="passenger"/><category term="period"/><category term="php"/><category term="predicate"/><category term="radio"/><category term="retry design"/><category term="retry pattern"/><category term="scale"/><category term="settings"/><category term="sift"/><category term="simplenote"/><category term="sorting"/><category term="ssl"/><category term="stock"/><category term="supplier"/><category term="test case"/><category term="threadlocal"/><category term="threadsafe"/><category term="timeout"/><category term="tldr"/><category term="topic"/><category term="tr"/><category term="unctional interface"/><category term="unix"/><category term="visualization"/><category term="volatile"/><category term="wait"/><category term="yahoo input"/><title type='text'>Chrispad</title><subtitle type='html'>軟體開發是一條很長修練之路持續思考與改善~</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.chrispad.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default?start-index=26&amp;max-results=25'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>133</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-4463842547558305566</id><published>2020-05-27T01:05:00.010-07:00</published><updated>2020-05-27T23:53:05.311-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="duration"/><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><category scheme="http://www.blogger.com/atom/ns#" term="period"/><title type='text'>Duration vs Period in Java 8</title><content type='html'>&lt;p&gt;Both classes can be used to represent an amount of time or also measure the difference two dates.&lt;br/&gt;
How to use both in different situations?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;date-based value (Period): check whether days of period is over setting.&lt;/p&gt;
&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;LocalDate localDate = java.time.LocalDate.parse(matcher.group(1), DATE_TIME_FORMATTER);
long days = Period.between(localDate, java.time.LocalDate.now()).getDays();&lt;br/&gt;
return (days &amp;gt;= 5);
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;time-based value (Duration): check an interval of time in  seconds or nanoseconds.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;    Duration.between(startTime, LocalTime.now()).getSeconds();
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_0&quot;&gt;Ref&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/javase/tutorial/datetime/iso/period.html&quot;&gt;Java Period and Duration&lt;/a&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/4463842547558305566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2020/05/duration-vs-period-in-java-8.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/4463842547558305566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/4463842547558305566'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2020/05/duration-vs-period-in-java-8.html' title='Duration vs Period in Java 8'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-3250518451831427223</id><published>2020-05-25T00:37:00.001-07:00</published><updated>2020-05-25T01:02:00.873-07:00</updated><title type='text'>Redpill</title><content type='html'>&lt;p&gt;Redpill is a my side project which is used to visualize financial statement analysis is the process of analyzing a company&amp;#39;s financial statements for decision-making purpose. For me use it to UNDERSTAND the overall health of an organization as well as to evaluate financial performance and business values.&lt;br/&gt;
&lt;img src=&quot;https://i.loli.net/2020/05/25/sk6qJMcRAmyuO7z.jpg&quot; alt=&quot;&quot; style=&quot;width:400px;&quot;/&gt;&lt;/p&gt;

&lt;p&gt;Here are some technologies that can help build it as below.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;JDK 11- Module, JavaFx, HttpClient...&lt;/li&gt;
&lt;li&gt;Apache Spark - an unified analytics engine for big data processing, with built-in modules for streaming, SQL, machine learning and graph processing.&lt;/li&gt;
&lt;li&gt;Integration of Sprint Boot and JavaFx&lt;/li&gt;
&lt;li&gt;Spring-based development.&lt;/li&gt;
&lt;li&gt;Based on Hexagonal architecture, Ports and adapters architecture, is an architectural pattern used in software design. It aims at creating loosely coupled application components that can be easily connected to different software environments.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now it&amp;#39;s still a drat version will be updated by new ideas.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/3250518451831427223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2020/05/redpill.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/3250518451831427223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/3250518451831427223'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2020/05/redpill.html' title='Redpill'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-2872921185616978730</id><published>2020-01-05T22:20:00.004-08:00</published><updated>2020-01-06T02:18:09.697-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="high-throughput"/><category scheme="http://www.blogger.com/atom/ns#" term="kafka"/><category scheme="http://www.blogger.com/atom/ns#" term="partition"/><category scheme="http://www.blogger.com/atom/ns#" term="scale"/><category scheme="http://www.blogger.com/atom/ns#" term="topic"/><title type='text'>Kafka Topic Partitions</title><content type='html'>&lt;p&gt;In kafka, A topic is a category/feed name for messages are stored and pushed. Further, Kafka breaks topic logs up into partitions, interesting part here. &lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://kafka.apache.org/documentation/#intro_topics&quot;&gt;From the kafka documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Each partition is an ordered, immutable sequence of records that is continually appended to—a structured commit log. The records in the partitions are each assigned a sequential id number called the offset that uniquely identifies each record within the partition.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i.loli.net/2020/01/06/1oHc456unEPYSDO.jpg&quot; alt=&quot;&quot;/&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;The partitions in the log serve several purposes. First, they allow the log to scale beyond a size that will fit on a single server. Each individual partition must fit on the servers that host it, but a topic may have many partitions so it can handle an arbitrary amount of data. Second they act as the unit of parallelism—more on that in a bit.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To significantly increase the throughput and performance of handling messages, the multiple partitions be consumed by multiple PODs(instances) should be considered into. Here&amp;#39;s using simple kafka commands to simulate this case.&lt;/p&gt;

&lt;h3 id=&quot;toc_0&quot;&gt;Alter the topic to use two partitions&lt;/h3&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kafka-topics --alter --zookeeper localhost:2181 --topic alarm --partitions 2
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_1&quot;&gt;Count partitions in alarm Topic&lt;/h3&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kafka-topics --describe --zookeeper localhost:2181 --topic alarm
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_2&quot;&gt;Count current message summary&lt;/h3&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kafka-run-class kafka.tools.GetOffsetShell --broker-list localhost:9092 --topic alarm
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_3&quot;&gt;Sending the messages by different keys&lt;/h3&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kafka-console-producer --broker-list localhost:9092 --topic snmp-trap-alarm  --property &amp;quot;parse.key=true&amp;quot; --property &amp;quot;key.separator=:&amp;quot;
&amp;gt;k1:message1
&amp;gt;k2:message2
&amp;gt;k3:message3
&amp;gt;...
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_4&quot;&gt;Consumers can assign the specific partition num 0, 1... to handle messages&lt;/h3&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kafka-console-consumer --bootstrap-server localhost:9092 --from-beginning --topic alarm --property print.key=true --partition 0

kafka-console-consumer --bootstrap-server localhost:9092 --from-beginning --topic alarm --property print.key=true --partition 1
&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/2872921185616978730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2020/01/kafka-topic-partitions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/2872921185616978730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/2872921185616978730'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2020/01/kafka-topic-partitions.html' title='Kafka Topic Partitions'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-4328847769602052103</id><published>2019-12-20T18:18:00.004-08:00</published><updated>2019-12-24T18:57:48.422-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="JAAS"/><category scheme="http://www.blogger.com/atom/ns#" term="kafka"/><category scheme="http://www.blogger.com/atom/ns#" term="kerberos"/><category scheme="http://www.blogger.com/atom/ns#" term="SASL"/><title type='text'>Configuring Authentication with Kerberos in Kafka</title><content type='html'>&lt;p&gt;One day R&amp;amp;D team asked by configuring authentication with kerberos to simulate our customer environment and QA be based on this to verify the incoming messages. As we known, Kerberos security for Kafka is optional feature, normal case we don&amp;#39;t need to use it in Intranet network or zone.&lt;/p&gt;

&lt;h2 id=&quot;toc_0&quot;&gt;What&amp;#39;s Kerberos&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Kerberos is a network authentication protocol. It is designed to provide strong authentication for client/server applications by using secret-key cryptography&lt;/strong&gt;. A free implementation of this protocol is available from the Massachusetts Institute of Technology. Kerberos is available in many commercial products as well. [&lt;a href=&quot;https://web.mit.edu/kerberos/#what_is&quot;&gt;ref&lt;/a&gt;]&lt;/p&gt;

&lt;h2 id=&quot;toc_1&quot;&gt;Prerequisite&lt;/h2&gt;

&lt;p&gt;Kerberos, Kafka and Zookeeper are installed on same host with using same domain. First time don&amp;#39;t consider to setup in different hosts with different domain.&lt;br/&gt;
A Kerberos realm is the domain over which a Kerberos authentication server has the authority to authenticate a user, host or service. &lt;br/&gt;
All hosts must be reachable using hostnames; It is a Kerberos requirement that all your hosts can be resolved with their FQDNs.&lt;/p&gt;

&lt;h2 id=&quot;toc_2&quot;&gt;Configure&lt;/h2&gt;

&lt;h3 id=&quot;toc_3&quot;&gt;Step 1: Prepare keytab for kafka/client/zookeeper&lt;/h3&gt;

&lt;p&gt;Using two commands to create principal and export the keytab as file.&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo /usr/sbin/kadmin.local -q &amp;#39;addprinc -randkey {principal}/{hostname}@{REALM}&amp;#39;
sudo /usr/sbin/kadmin.local -q &amp;quot;ktadd -k /tmp/keytabs/{keytabname}.keytab kafka/{hostname}@{REALM}&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Kafka&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo /usr/sbin/kadmin.local -q &amp;#39;addprinc -randkey kafka/mydomain.com@SUPER_HERO&amp;#39;
sudo /usr/sbin/kadmin.local -q &amp;quot;ktadd -k /tmp/keytabs/kafka.keytab kafka/mydomain.com@SUPER_HERO&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;zookeeper&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo /usr/sbin/kadmin.local -q &amp;#39;addprinc -randkey zookeeper/mydomain.com@SUPER_HERO&amp;#39;
sudo /usr/sbin/kadmin.local -q &amp;quot;ktadd -k /tmp/keytabs/zookeeper.keytab zookeeper/mydomain.com@SUPER_HERO&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;kafka client&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo /usr/sbin/kadmin.local -q &amp;#39;addprinc -randkey kafka_client/mydomain.com@SUPER_HERO&amp;#39;
sudo /usr/sbin/kadmin.local -q &amp;quot;ktadd -k /tmp/keytabs/kafka_client.keytab kafka_client/mydomain.com@SUPER_HERO&amp;quot;

&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_4&quot;&gt;Step 2: Kafka and Zookeeper Operation First&lt;/h3&gt;

&lt;p&gt;Configure server.properties for kafka &lt;br/&gt;
vim server.properties&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;...
#Binding SASL_PLAINTEXT protocol in 9094 port
listeners=PLAINTEXT://localhost:9092,SASL_PLAINTEXT://mydomain.com:9094 
advertised.listeners=PLAINTEXT://localhost:9092,SASL_PLAINTEXT://mydomain.com:9094
listener.security.protocol.map=PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL

## inner comuncation with SASL_PLAINTEXT
security.protocol=SASL_PLAINTEXT
sasl.mechanism=GSSAPI
sasl.mechanism.inter.broker.protocol=GSSAPI
sasl.kerberos.service.name=kafka
...
zookeeper.connect=mydomain.com:2181
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Prepare JDK&amp;#39;s Kerberos Requirements (/usr/local/etc/kafka/security/krb5.conf)&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;[libdefaults]
default_realm = SUPER_HERO
forwardable = true
kdc_timeout = 3000
ns_lookup_kdc = false
dns_lookup_realm = false
[realms]
SUPER_HERO = {
  kdc = mydomain.com
  admin_server = mydomain.com
}
[domain_realm]
.mydomain.com = SUPER_HERO
mydomain.com = SUPER_HERO

&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_5&quot;&gt;Step 2.1: Startup Zookeeper&lt;/h3&gt;

&lt;p&gt;Prepare Zookeeper&amp;#39;s Jaas file (/usr/local/etc/kafka/security/zookeeper_jaas.conf)&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Server {
  com.sun.security.auth.module.Krb5LoginModule required 
  debug=true
  useKeyTab=true
  keyTab=&amp;quot;/usr/local/etc/kafka/security/zookeeper.keytab&amp;quot; &amp;lt;--your zookeper keytab path
  storeKey=true
  useTicketCache=false
  principal=&amp;quot;zookeeper/mydomain.com@SUPER_HERO&amp;quot;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Export KAFKA_HEAP_OPTS for zookeeper process. MUST ENABLE  sun.security.krb5.debug MODE, otherwise it&amp;#39;s super hard to find the cause.&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;export KAFKA_HEAP_OPTS=&amp;quot;-Djava.security.krb5.conf=/usr/local/etc/kafka/security/krb5.conf -Djava.security.auth.login.config=/usr/local/etc/kafka/security/zookeeper_jaas.conf  -Dsun.security.krb5.debug=true&amp;quot;

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;start zookeeper process&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;zookeeper-server-start /usr/local/etc/kafka/zookeeper.properties

&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_6&quot;&gt;Step 2.2: Startup Kafka&lt;/h3&gt;

&lt;p&gt;Prepare Kafka&amp;#39;s Jaas file (/usr/local/etc/kafka/security/kafka_server_jaas.conf)&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;KafkaServer {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    storeKey=true
    debug=true
    serviceName=&amp;quot;kafka&amp;quot;
    keyTab=&amp;quot;/usr/local/etc/kafka/security/kafka.keytab&amp;quot;
    principal=&amp;quot;kafka/mydomain.com@SUPER_HERO&amp;quot;;
};

Client {
  com.sun.security.auth.module.Krb5LoginModule required
  debug=true
  useKeyTab=true
  storeKey=true
  keyTab=&amp;quot;/usr/local/etc/kafka/security/kafka.keytab&amp;quot;
  principal=&amp;quot;kafka/mydomain.com@SUPER_HERO&amp;quot;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Export KAFKA_HEAP_OPTS for zookeeper process. MUST ENABLE  sun.security.krb5.debug MODE, otherwise it&amp;#39;s super hard to find the cause.&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;export KAFKA_HEAP_OPTS=&amp;quot;-Djava.security.krb5.conf=/usr/local/etc/kafka/security/krb5.conf -Djava.security.auth.login.config=/usr/local/etc/kafka/security/kafka_server_jaas.conf -Dsun.security.krb5.debug=true&amp;quot;

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;start kafka process&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kafka-server-start /usr/local/etc/kafka/server.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;EVERYTHING IS FINE, THE KAFKA LOG LOOK LIKE as &lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;Added key: 16version: 2
Added key: 23version: 2
Added key: 18version: 2
Using builtin default etypes for default_tkt_enctypes
default etypes for default_tkt_enctypes: 18 17 16 23.
&amp;gt;&amp;gt;&amp;gt; EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
&amp;gt;&amp;gt;&amp;gt; KrbAsReq creating message
&amp;gt;&amp;gt;&amp;gt; KrbKdcReq send: kdc=mydomain.com UDP:88, timeout=3000, number of retries =3, #bytes=281
&amp;gt;&amp;gt;&amp;gt; KDCCommunication: kdc=mydomain.com UDP:88, timeout=3000,Attempt =1, #bytes=281
&amp;gt;&amp;gt;&amp;gt; KrbKdcReq send: #bytes read=815
&amp;gt;&amp;gt;&amp;gt; KdcAccessibility: remove mydomain.com
Looking for keys for: kafka/mydomain.com@SUPER_HERO
Found unsupported keytype (1) for kafka/mydomain.com@SUPER_HERO
Added key: 16version: 2
Added key: 23version: 2
Added key: 18version: 2
&amp;gt;&amp;gt;&amp;gt; EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType
&amp;gt;&amp;gt;&amp;gt; KrbAsRep cons in KrbAsReq.getReply kafka/mydomain.com
principal is kafka/mydomain.com@SUPER_HERO
Will use keytab
Commit Succeeded

[2019-12-21 12:13:43,633] INFO Successfully logged in. (org.apache.kafka.common.security.authenticator.AbstractLogin)
[2019-12-21 12:13:43,634] INFO [Principal=kafka/mydomain.com@SUPER_HERO]: TGT refresh thread started. (org.apache.kafka.common.security.kerberos.KerberosLogin)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_7&quot;&gt;Step 2.3: Kafka Client&lt;/h3&gt;

&lt;p&gt;Prepare client.properties which tell client to use SASL_PLAINTEXT.&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;security.protocol=SASL_PLAINTEXT
sasl.kerberos.service.name=kafka
sasl.mechanism=GSSAPI
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Prepare Client&amp;#39;s Jaas file (/Users/chliu/temp/qa_kafka/jaas.conf)&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;KafkaClient {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    storeKey=true
    debug=true
    keyTab=&amp;quot;/usr/local/etc/kafka/security/kafka-client.keytab&amp;quot;
    principal=&amp;quot;kafka-client/mydomain.com@SUPER_HERO&amp;quot;;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;export KAFKA_OPTS=&amp;quot;-Djava.security.auth.login.config=/Users/chliu/temp/qa_kafka/jaas.conf -Djava.security.krb5.conf=/usr/local/etc/kafka/security/krb5.conf -Dsun.security.krb5.debug=true&amp;quot;

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sending message into test topic.&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;kafka-console-producer  --broker-list mydomain.com:9094 --topic test --producer.config client.properties

&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/4328847769602052103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/12/configuring-authentication-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/4328847769602052103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/4328847769602052103'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/12/configuring-authentication-with.html' title='Configuring Authentication with Kerberos in Kafka'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-1465001802572945243</id><published>2019-10-29T02:26:00.005-07:00</published><updated>2019-10-29T05:07:02.014-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="jmx"/><category scheme="http://www.blogger.com/atom/ns#" term="jmxterm"/><category scheme="http://www.blogger.com/atom/ns#" term="logback"/><title type='text'>Change log level at runtime for logback</title><content type='html'>&lt;p&gt;For Ops issues cares a lot about logging to store in elasticsearch, which is impacted to the performance. In past We tried to reduce logging as default and change to debug level, but sometimes devs also need to go to troubleshooting incidents in production. Here is change log level way which doesn&amp;#39;t need to rebuild project based on logback jmx feature.&lt;/p&gt;

&lt;h2 id=&quot;toc_0&quot;&gt;Enable JMX in logback configuration&lt;/h2&gt;

&lt;p&gt;jmxConfigurator need to be added in logback.&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-&amp;lt;configuration&amp;gt;&quot;&gt;  &amp;lt;jmxConfigurator /&amp;gt;
  
  &amp;lt;appender name=&amp;quot;console&amp;quot; class=&amp;quot;ch.qos.logback.core.ConsoleAppender&amp;quot;&amp;gt;
    &amp;lt;layout class=&amp;quot;ch.qos.logback.classic.PatternLayout&amp;quot;&amp;gt;
      &amp;lt;Pattern&amp;gt;%date [%thread] %-5level %logger{25} - %msg%n&amp;lt;/Pattern&amp;gt;
    &amp;lt;/layout&amp;gt;
  &amp;lt;/appender&amp;gt;

  &amp;lt;root level=&amp;quot;debug&amp;quot;&amp;gt;
    &amp;lt;appender-ref ref=&amp;quot;console&amp;quot; /&amp;gt;
  &amp;lt;/root&amp;gt;  
&amp;lt;/configuration&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The logback with jmx can be verified by jconsole.&lt;br/&gt;
&lt;img src=&quot;https://i.loli.net/2019/10/29/YeNDt12d3bOqZKE.jpg&quot; alt=&quot;&quot; style=&quot;width:506px;&quot;/&gt;&lt;/p&gt;

&lt;h2 id=&quot;toc_1&quot;&gt;Use jmxterm command line based interactive to access&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Download executable jar &lt;br/&gt;
wget &lt;a href=&quot;https://github.com/jiaqi/jmxterm/releases/download/v1.0.0/jmxterm-1.0.0-uber.jar&quot;&gt;https://github.com/jiaqi/jmxterm/releases/download/v1.0.0/jmxterm-1.0.0-uber.jar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Entry jmx client console&lt;br/&gt;
java -jar jmxterm-1.0.0-uber.jar&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Welcome to JMX terminal. Type &amp;quot;help&amp;quot; for available commands.
$&amp;gt;open 2767  &amp;lt;--process id
#Connection to 2767 is opened
$&amp;gt;domains
#following domains are available
JMImplementation
ch.qos.logback.classic
com.sun.management
java.lang
java.nio
java.util.logging
kafka
kafka.consumer
kafka.producer
$&amp;gt;domain ch.qos.logback.classic
#domain is set to ch.qos.logback.classic
$&amp;gt;bean ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator
#bean is set to ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator
$&amp;gt;run setLoggerLevel com.abc.cde.consumer.MessageRequestConsumer DEBUG  
#calling operation setLoggerLevel of mbean ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator with params [com.abc.cde.consumer.MessageRequestConsumer, DEBUG]
#operation returns:
null
$&amp;gt;close
#disconnected
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;jmxterm has been supported silent mode, so we can easily implement a shell script for some special handling as below example.&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;#!/bin/bash
file=jmxterm-1.0.0-uber.jar
if [ ! -f &amp;quot;$file&amp;quot; ]; then
    wget https://github.com/jiaqi/jmxterm/releases/download/v1.0.0/jmxterm-1.0.0-uber.jar
fi
processId=`jps -lvm | grep Bootstrap | awk &amp;#39;{print $1}&amp;#39;`
echo &amp;quot;Java App processId; $processId ; fm logging level to ;$1&amp;quot;
cat &amp;lt;&amp;lt;EOF &amp;gt; jmxcommands
open $processId
bean ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator
run setLoggerLevel com.abc.cdef.Parser $1
close
EOF
java -jar &amp;quot;$file&amp;quot; -n &amp;lt; jmxcommands

&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_2&quot;&gt;References&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.cyclopsgroup.org/jmxterm&quot;&gt;JMXTERM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/tutorial/jmx/&quot;&gt;JMX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://logback.qos.ch/manual/jmxConfig.html&quot;&gt;logback JMX configurator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/1465001802572945243/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/10/change-log-level-at-runtime-for-logback.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/1465001802572945243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/1465001802572945243'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/10/change-log-level-at-runtime-for-logback.html' title='Change log level at runtime for logback'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-7457986452171826636</id><published>2019-08-21T23:55:00.000-07:00</published><updated>2019-08-22T00:03:41.995-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="data class"/><category scheme="http://www.blogger.com/atom/ns#" term="Project Lombok"/><title type='text'>[Ref] Data Classes Considered Harmful</title><content type='html'>&lt;p&gt;In reality, there ain&amp;#39;t no such thing as a free lunch, when you used data class as Project Lombok.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://paluch.biz/blog/180-data-classes-considered-harmful.html&quot;&gt;Data Classes Considered Harmful&lt;/a&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/7457986452171826636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/08/ref-data-classes-considered-harmful.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/7457986452171826636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/7457986452171826636'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/08/ref-data-classes-considered-harmful.html' title='[Ref] Data Classes Considered Harmful'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-787267027910924730</id><published>2019-06-03T02:23:00.004-07:00</published><updated>2019-06-22T17:30:48.240-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ate memory"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="low memory"/><title type='text'>Linux ate ram as disk cache</title><content type='html'>&lt;p&gt;One day QA asked why memory was really low in QA linux server. Really not sure, this question is interesting for me, as known, our java applications always configured memory limitation, shouldn&amp;#39;t happen low memory issue. &lt;/p&gt;

&lt;p&gt;From result of &amp;quot;free -m&amp;quot; command executed and checked, If you just naively look at &amp;quot;used&amp;quot; and &amp;quot;free&amp;quot;, you&amp;#39;ll think your ram is 98/99% full.&lt;/p&gt;

&lt;p&gt;Googling that situation, &lt;a href=&quot;https://www.linuxatemyram.com/&quot;&gt;linuxatemyram&lt;/a&gt;, what&amp;#39;s going on? &lt;br/&gt;
Linux is borrowing unused memory for disk caching. This makes it looks like you are low on memory, but everything is fine. Try to use unused memory as disk caching makes the system much faster and more responsive.&lt;/p&gt;

&lt;p&gt;If you deeply read &lt;a href=&quot;https://www.linuxatemyram.com/&quot;&gt;&amp;quot;linux ate ram&amp;quot;&lt;/a&gt;, don&amp;#39;t panic, your ram is fine. ^^!&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/787267027910924730/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/06/linux-ate-ram.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/787267027910924730'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/787267027910924730'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/06/linux-ate-ram.html' title='Linux ate ram as disk cache'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-5319852192531068442</id><published>2019-05-22T19:39:00.005-07:00</published><updated>2019-05-27T00:28:42.515-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cli"/><category scheme="http://www.blogger.com/atom/ns#" term="curl"/><category scheme="http://www.blogger.com/atom/ns#" term="http"/><category scheme="http://www.blogger.com/atom/ns#" term="httpstat"/><category scheme="http://www.blogger.com/atom/ns#" term="visualization"/><title type='text'>httpstat - curl statisticsmade simple</title><content type='html'>&lt;p&gt;Sometimes need to measure RESTful Api to clarify network and server processing capabilities in customer side. httpstat tool that visualizes curl statistics in a way of beauty and clarity.&lt;/p&gt;

&lt;h2 id=&quot;toc_0&quot;&gt;macOS install&lt;/h2&gt;

&lt;p&gt;brew install httpstat&lt;/p&gt;

&lt;h2 id=&quot;toc_1&quot;&gt;curl statistics&lt;/h2&gt;

&lt;p&gt;httpstat www.google.com &lt;/p&gt;

￼&lt;div class=&quot;separator&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoaOaHiuj4GUFHRoLJYkOOtjcsM_KILapJlVsd_60hEgs1dWb8vlJogRCRQ5oQ_pxLu7VGU9oHClt4E_LkxFXjfmoLt3B2EZhPvnsM8a8uY-5ynRWO9ghbYi4W00FKdi_UiQ9ph9nmGKDh/s1600/httpstat.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;
&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoaOaHiuj4GUFHRoLJYkOOtjcsM_KILapJlVsd_60hEgs1dWb8vlJogRCRQ5oQ_pxLu7VGU9oHClt4E_LkxFXjfmoLt3B2EZhPvnsM8a8uY-5ynRWO9ghbYi4W00FKdi_UiQ9ph9nmGKDh/s320/httpstat.png&quot; width=&quot;320&quot; height=&quot;152&quot; data-original-width=&quot;1122&quot; data-original-height=&quot;534&quot; /&gt;
&lt;/a&gt;
&lt;/div&gt;

&lt;h2 id=&quot;toc_2&quot;&gt;httpstat site&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/reorx/httpstat&quot;&gt;https://github.com/reorx/httpstat&lt;/a&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/5319852192531068442/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/05/httpstat-curl-statisticsmade-simple.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/5319852192531068442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/5319852192531068442'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/05/httpstat-curl-statisticsmade-simple.html' title='httpstat - curl statisticsmade simple'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoaOaHiuj4GUFHRoLJYkOOtjcsM_KILapJlVsd_60hEgs1dWb8vlJogRCRQ5oQ_pxLu7VGU9oHClt4E_LkxFXjfmoLt3B2EZhPvnsM8a8uY-5ynRWO9ghbYi4W00FKdi_UiQ9ph9nmGKDh/s72-c/httpstat.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-6631391768223501508</id><published>2019-04-19T00:39:00.000-07:00</published><updated>2019-04-19T01:05:13.859-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="restTemplate"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><title type='text'>Disable encoding URL Using RestTemplate in Spring</title><content type='html'>&lt;p&gt;The RestTemplate is smart to convert the URL with specific characters to URL encoded. But sometimes, we need to disable URL encoding in order to some specific characters are available on server side as its business requirement. &lt;br/&gt;
It&amp;#39;s a legacy web service and bad design, but customer don&amp;#39;t want to  change for some reasons. &lt;/p&gt;

&lt;h2 id=&quot;toc_0&quot;&gt;Disable Encoding URL&lt;/h2&gt;

&lt;p&gt;Set encoding encoding mode when initialing rest template.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;DefaultUriBuilderFactory defaultUriBuilderFactory = new DefaultUriBuilderFactory();
defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);
      
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(defaultUriBuilderFactory);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Using other encoding mode to satisfy different integration strategies.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;TEMPLATE_AND_VALUES, VALUES_ONLY, URI_COMPONENT, NONE
&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/6631391768223501508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/04/disable-encoding-url-using-resttemplate.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/6631391768223501508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/6631391768223501508'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/04/disable-encoding-url-using-resttemplate.html' title='Disable encoding URL Using RestTemplate in Spring'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-230962720900867240</id><published>2019-04-10T20:19:00.000-07:00</published><updated>2019-04-11T08:43:12.081-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="httpclient"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><category scheme="http://www.blogger.com/atom/ns#" term="timeout"/><title type='text'>3 Type of Timeouts in Http client</title><content type='html'>&lt;p&gt;There are three type of timeouts in Http Client which could be considered to be adjusted when encountering unreliable destination endpoint.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ConnectionTimeout &lt;br/&gt;
Set the timeout in milliseconds used when requesting a connection from the connection manager.&lt;/li&gt;
&lt;li&gt;ConnectionRequestTimeout&lt;br/&gt;
Determines the timeout in milliseconds until a connection is established. A timeout value of zero is interpreted as an infinite timeout.&lt;/li&gt;
&lt;li&gt;SocketTimeout&lt;br/&gt;
Determines the socket timeout (SO_TIMEOUT) in milliseconds, which is the timeout for waiting for data or, put differently, a maximum period inactivity between two consecutive data packets).&lt;/li&gt;
&lt;/ol&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/230962720900867240/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/04/3-type-of-timeouts-in-http-client.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/230962720900867240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/230962720900867240'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/04/3-type-of-timeouts-in-http-client.html' title='3 Type of Timeouts in Http client'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-3631464646717981954</id><published>2019-02-19T22:53:00.000-08:00</published><updated>2019-02-19T23:57:29.427-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="certificate"/><category scheme="http://www.blogger.com/atom/ns#" term="import"/><category scheme="http://www.blogger.com/atom/ns#" term="restTemplate"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><category scheme="http://www.blogger.com/atom/ns#" term="ssl"/><title type='text'> Import a SSL certificate into a JVM</title><content type='html'>&lt;p&gt;Sometimes, it&amp;#39;s inevitable that HTTPs is only provided, or you are unable to change third part code to ignore certificate verification. &lt;/p&gt;

&lt;p&gt;How to import a certificate into a JVM? Here are some steps.&lt;/p&gt;

&lt;h2 id=&quot;toc_0&quot;&gt;Step1. Fetch the certificate&lt;/h2&gt;

&lt;pre class=&quot;line-numbers pretty-print&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;openssl s_client -connect youtube.com:443 &amp;lt; /dev/null | sed -ne &amp;#39;/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p&amp;#39; &amp;gt; youtube.crt
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_1&quot;&gt;Step2. Import the certificate&lt;/h2&gt;

&lt;pre class=&quot;line-numbers pretty-print&quot;&gt;&lt;code class=&quot;language-text pretty-print&quot;&gt;keytool -import -alias youtube.com -keystore /Users/chliu/.sdkman/candidates/java/current/jre/lib/security/cacerts -file youtube.crt
Enter keystore password:&amp;lt;changeit&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;pre class=&quot;line-numbers pretty-print&quot;&gt;&lt;code class=&quot;language-text pretty-print&quot;&gt;Owner: CN=*.google.com, O=Google LLC, L=Mountain View, ST=California, C=US
Issuer: CN=Google Internet Authority G3, O=Google Trust Services, C=US
Serial number: 3b6e50a1d2080062
Valid from: Tue Jan 29 22:58:00 CST 2019 until: Tue Apr 23 22:58:00 CST 2019
Certificate fingerprints:
     MD5:  19:0D:FC:58:69:85:29:59:C4:42:71:05:21:EA:B4:2E
     SHA1: E4:A8:7B:F5:3E:9A:17:4A:E2:9F:26:8F:81:23:78:E3:15:08:85:99
     SHA256: F7:EE:A9:17:44:FD:5D:E8:09:73:4D:97:85:E4:7E:AE:FA:73:6D:6F:31:36:55:0B:07:1B:15:68:D8:81:A3:C8
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3

Extensions:

#1: ObjectId: 1.3.6.1.5.5.7.1.1 Criticality=false
AuthorityInfoAccess [
  [
   accessMethod: caIssuers
   accessLocation: URIName: http://pki.goog/gsr2/GTSGIAG3.crt
,
   accessMethod: ocsp
   accessLocation: URIName: http://ocsp.pki.goog/GTSGIAG3
]
]

#2: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 77 C2 B8 50 9A 67 76 76   B1 2D C2 86 D0 83 A0 7E  w..P.gvv.-......
0010: A6 7E BA 4B                                        ...K
]
]

#3: ObjectId: 2.5.29.19 Criticality=true
BasicConstraints:[
  CA:false
  PathLen: undefined
]

#4: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
  [DistributionPoint:
     [URIName: http://crl.pki.goog/GTSGIAG3.crl]
]]

#5: ObjectId: 2.5.29.32 Criticality=false
CertificatePolicies [
  [CertificatePolicyId: [1.3.6.1.4.1.11129.2.5.3]
[]  ]
  [CertificatePolicyId: [2.23.140.1.2.2]
[]  ]
]

#6: ObjectId: 2.5.29.37 Criticality=false
ExtendedKeyUsages [
  serverAuth
]

#7: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
  DNSName: *.google.com
  DNSName: *.android.com
  DNSName: *.appengine.google.com
  DNSName: *.cloud.google.com
  DNSName: *.g.co
  DNSName: *.gcp.gvt2.com
  DNSName: *.ggpht.cn
  DNSName: *.google-analytics.com
  DNSName: *.google.ca
  DNSName: *.google.cl
  DNSName: *.google.co.in
  DNSName: *.google.co.jp
  DNSName: *.google.co.uk
  DNSName: *.google.com.ar
  DNSName: *.google.com.au
  DNSName: *.google.com.br
  DNSName: *.google.com.co
  DNSName: *.google.com.mx
  DNSName: *.google.com.tr
  DNSName: *.google.com.vn
  DNSName: *.google.de
  DNSName: *.google.es
  DNSName: *.google.fr
  DNSName: *.google.hu
  DNSName: *.google.it
  DNSName: *.google.nl
  DNSName: *.google.pl
  DNSName: *.google.pt
  DNSName: *.googleadapis.com
  DNSName: *.googleapis.cn
  DNSName: *.googlecommerce.com
  DNSName: *.googlevideo.com
  DNSName: *.gstatic.cn
  DNSName: *.gstatic.com
  DNSName: *.gstaticcnapps.cn
  DNSName: *.gvt1.com
  DNSName: *.gvt2.com
  DNSName: *.metric.gstatic.com
  DNSName: *.urchin.com
  DNSName: *.url.google.com
  DNSName: *.youtube-nocookie.com
  DNSName: *.youtube.com
  DNSName: *.youtubeeducation.com
  DNSName: *.youtubekids.com
  DNSName: *.yt.be
  DNSName: *.ytimg.com
  DNSName: android.clients.google.com
  DNSName: android.com
  DNSName: developer.android.google.cn
  DNSName: developers.android.google.cn
  DNSName: g.co
  DNSName: ggpht.cn
  DNSName: goo.gl
  DNSName: google-analytics.com
  DNSName: google.com
  DNSName: googlecommerce.com
  DNSName: source.android.google.cn
  DNSName: urchin.com
  DNSName: www.goo.gl
  DNSName: youtu.be
  DNSName: youtube.com
  DNSName: youtubeeducation.com
  DNSName: youtubekids.com
  DNSName: yt.be
]

#8: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: BB F4 15 80 EC F0 4E F6   58 5A B1 49 4C 82 12 48  ......N.XZ.IL..H
0010: F9 FB 7E 3B                                        ...;
]
]

&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_2&quot;&gt;Step3. Check certificate in keystore&lt;/h2&gt;

&lt;pre class=&quot;line-numbers pretty-print&quot;&gt;&lt;code class=&quot;language-text pretty-print&quot;&gt;keytool -list -v -keystore $JAVA_HOME/jre/lib/security/cacerts
keytool -list -v -keystore $JAVA_HOME/jre/lib/security/cacerts | grep youtube
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_3&quot;&gt;Step4. Specify trust store AND PASSWRD&lt;/h2&gt;

&lt;pre class=&quot;line-numbers pretty-print&quot;&gt;&lt;code class=&quot;language-text pretty-print&quot;&gt;-Djavax.net.ssl.trustStore=$JAVA_HOME/jre/lib/security/cacerts 
-Djavax.net.ssl.trustStorePassword=changeit 
-Djavax.net.debug=all
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If there are some issue that hostname in certificate didn&amp;#39;t matched, the steps below can help to confirm the issue.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the Server’s FQDN and make sure this match with the URL configured on the Certificate.&lt;/li&gt;
&lt;li&gt;Wildcard certificate cannot support subdomain. The subdomain also need to create a certificate.
&lt;a href=&quot;&quot;&gt;How to Fix SSL Common Name Mismatch Error&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/3631464646717981954/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/02/import-ssl-certificate-into-jvm.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/3631464646717981954'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/3631464646717981954'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/02/import-ssl-certificate-into-jvm.html' title=' Import a SSL certificate into a JVM'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-1068864465237804726</id><published>2019-02-14T22:08:00.000-08:00</published><updated>2019-02-17T05:45:25.749-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="https"/><category scheme="http://www.blogger.com/atom/ns#" term="restTemplate"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><title type='text'>Ignore Certificate Verification Using RestTemplate</title><content type='html'>&lt;p&gt;For some reasons, we don&amp;#39;t want to verify certificate verification when data transfer has to happen over HTTPS. &lt;/p&gt;

&lt;p&gt;How to disable verification using restTemplate in Spring?  &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Custom trustStrategy that trusts all certs&lt;/li&gt;
&lt;li&gt;Implement hostname verification which trusts all host&lt;/li&gt;
&lt;/ol&gt;


&lt;script src=&quot;https://gist.github.com/chliu/daa3b94a5061f86f8d9fc3c5ddba0301.js&quot;&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/1068864465237804726/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/02/disable-certificate-verification-using.html#comment-form' title='21 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/1068864465237804726'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/1068864465237804726'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/02/disable-certificate-verification-using.html' title='Ignore Certificate Verification Using RestTemplate'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>21</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-8156094932715580704</id><published>2019-01-17T23:22:00.001-08:00</published><updated>2019-01-17T23:36:32.171-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="settings"/><title type='text'> Show Java Settings as Default</title><content type='html'>&lt;p&gt;Java -XshowSettings can show possible category arguments in JVM env.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;-XshowSettings:category
Shows settings and continues. Possible category arguments for this option include the following:

all
Shows all categories of settings. This is the default value.

locale
Shows settings related to locale.

properties
Shows settings related to system properties.

vm
Shows the settings of the JVM.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;java -XshowSettings:all -version&lt;/p&gt;

&lt;p&gt;when executed above command, the usage information for running the Java launcher will also be displayed. It can make maintainer a bit less convenient to see those details.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;
VM settings:
    Max. Heap Size (Estimated): 3.56G
    Ergonomics Machine Class: server
    Using VM: Java HotSpot(TM) 64-Bit Server VM

Property settings:
    awt.toolkit = sun.lwawt.macosx.LWCToolkit
    file.encoding = UTF-8
    file.encoding.pkg = sun.io
    file.separator = /
    ftp.nonProxyHosts = local|*.local|169.254/16|*.169.254/16
    gopherProxySet = false
    http.nonProxyHosts = local|*.local|169.254/16|*.169.254/16
    java.awt.graphicsenv = sun.awt.CGraphicsEnvironment
    java.awt.printerjob = sun.lwawt.macosx.CPrinterJob
    java.class.path = .
    java.class.version = 52.0
    java.endorsed.dirs = /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/endorsed
    java.ext.dirs = /Users/chliu/Library/Java/Extensions
        /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/ext
        /Library/Java/Extensions
        /Network/Library/Java/Extensions
        /System/Library/Java/Extensions
        /usr/lib/java
    java.home = /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre
    java.io.tmpdir = /var/folders/zd/5kbv_wbd6cqbpfrf8w95sfnr0000gn/T/
    java.library.path = /Users/chliu/Library/Java/Extensions
        /Library/Java/Extensions
        /Network/Library/Java/Extensions
        /System/Library/Java/Extensions
        /usr/lib/java
        .
    java.runtime.name = Java(TM) SE Runtime Environment
    java.runtime.version = 1.8.0_111-b14
    java.specification.name = Java Platform API Specification
    java.specification.vendor = Oracle Corporation
    java.specification.version = 1.8
    java.vendor = Oracle Corporation
    java.vendor.url = http://java.oracle.com/
    java.vendor.url.bug = http://bugreport.sun.com/bugreport/
    java.version = 1.8.0_111
    java.vm.info = mixed mode
    java.vm.name = Java HotSpot(TM) 64-Bit Server VM
    java.vm.specification.name = Java Virtual Machine Specification
    java.vm.specification.vendor = Oracle Corporation
    java.vm.specification.version = 1.8
    java.vm.vendor = Oracle Corporation
    java.vm.version = 25.111-b14
    line.separator = \n
    os.arch = x86_64
    os.name = Mac OS X
    os.version = 10.14.2
    path.separator = :
    socksNonProxyHosts = local|*.local|169.254/16|*.169.254/16
    sun.arch.data.model = 64
    sun.boot.class.path = /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/resources.jar
        /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/rt.jar
        /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/sunrsasign.jar
        /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jsse.jar
        /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jce.jar
        /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/charsets.jar
        /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/jfr.jar
        /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/classes
    sun.boot.library.path = /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib
    sun.cpu.endian = little
    sun.cpu.isalist =
    sun.io.unicode.encoding = UnicodeBig
    sun.java.launcher = SUN_STANDARD
    sun.jnu.encoding = UTF-8
    sun.management.compiler = HotSpot 64-Bit Tiered Compilers
    sun.os.patch.level = unknown
    user.country = US
    user.country.format = TW
    user.dir = /Users/chliu/temp/aa/WEB-INF/lib
    user.home = /Users/chliu
    user.language = en
    user.name = chliu
    user.timezone =

Locale settings:
    default locale = English
    default display locale = English (United States)
    default format locale = English (Taiwan)
    available locales = , ar, ar_AE, ar_BH, ar_DZ, ar_EG, ar_IQ, ar_JO,
        ar_KW, ar_LB, ar_LY, ar_MA, ar_OM, ar_QA, ar_SA, ar_SD,
        ar_SY, ar_TN, ar_YE, be, be_BY, bg, bg_BG, ca,
        ca_ES, cs, cs_CZ, da, da_DK, de, de_AT, de_CH,
        de_DE, de_GR, de_LU, el, el_CY, el_GR, en, en_AU,
        en_CA, en_GB, en_IE, en_IN, en_MT, en_NZ, en_PH, en_SG,
        en_US, en_ZA, es, es_AR, es_BO, es_CL, es_CO, es_CR,
        es_CU, es_DO, es_EC, es_ES, es_GT, es_HN, es_MX, es_NI,
        es_PA, es_PE, es_PR, es_PY, es_SV, es_US, es_UY, es_VE,
        et, et_EE, fi, fi_FI, fr, fr_BE, fr_CA, fr_CH,
        fr_FR, fr_LU, ga, ga_IE, hi, hi_IN, hr, hr_HR,
        hu, hu_HU, in, in_ID, is, is_IS, it, it_CH,
        it_IT, iw, iw_IL, ja, ja_JP, ja_JP_JP_#u-ca-japanese, ko, ko_KR,
        lt, lt_LT, lv, lv_LV, mk, mk_MK, ms, ms_MY,
        mt, mt_MT, nl, nl_BE, nl_NL, no, no_NO, no_NO_NY,
        pl, pl_PL, pt, pt_BR, pt_PT, ro, ro_RO, ru,
        ru_RU, sk, sk_SK, sl, sl_SI, sq, sq_AL, sr,
        sr_BA, sr_BA_#Latn, sr_CS, sr_ME, sr_ME_#Latn, sr_RS, sr_RS_#Latn, sr__#Latn,
        sv, sv_SE, th, th_TH, th_TH_TH_#u-nu-thai, tr, tr_TR, uk,
        uk_UA, vi, vi_VN, zh, zh_CN, zh_HK, zh_SG, zh_TW

java version &amp;quot;1.8.0_111&amp;quot;
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/8156094932715580704/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/01/show-java-settings-as-default.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/8156094932715580704'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/8156094932715580704'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/01/show-java-settings-as-default.html' title=' Show Java Settings as Default'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-3899204319396482188</id><published>2019-01-13T01:03:00.003-08:00</published><updated>2019-01-13T03:21:09.912-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><category scheme="http://www.blogger.com/atom/ns#" term="lambda"/><category scheme="http://www.blogger.com/atom/ns#" term="method reference"/><title type='text'>[Java8] Method References</title><content type='html'>&lt;p&gt;Method references are the special form of Lambda expression. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, this way is often clearer to refer to existing method by name. They are more compact and easy-to-ready to express something.&lt;/p&gt;

&lt;p&gt;Basically, this is just shorthand syntax for a Lambda Expression but this version is more concise &amp;amp; readable. &lt;/p&gt;

&lt;h2 id=&quot;toc_0&quot;&gt;Types of Method reference&lt;/h2&gt;

&lt;p&gt;There are four types of method reference.&lt;/p&gt;

&lt;h3 id=&quot;toc_1&quot;&gt;Reference to a static method&lt;/h3&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;  @Test
   public void testReferenceStaticMethod()
   {
      Function&amp;lt;String, String&amp;gt; upperFunc = StringUtils::toUpperCase;
      Assert.assertEquals(&amp;quot;HI JAVA&amp;quot;, upperFunc.apply(&amp;quot;hi Java&amp;quot;));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_2&quot;&gt;Reference to an instance method of a particular object&lt;/h3&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;    @Test
   public void testInstanceMethod()
   {
      String text = &amp;quot;hi java&amp;quot;;
      Supplier&amp;lt;Integer&amp;gt; getLength = text::length;
      Assert.assertEquals(Integer.valueOf(7), getLength.get());
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_3&quot;&gt;Reference to an instance method of a particular type&lt;/h3&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;    @Test
   public void testInstanceMethodByType()
   {
      Function&amp;lt;String, String&amp;gt; upperFunc = String::toLowerCase;
      Assert.assertEquals(&amp;quot;hi java&amp;quot;, upperFunc.apply(&amp;quot;hi Java&amp;quot;));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;toc_4&quot;&gt;Reference to a constructor&lt;/h3&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;    @Test
    public void testCallConstructor()
   {
      Function&amp;lt;Integer, Integer&amp;gt; f = Integer::new;
      Assert.assertEquals(new Integer(99), f.apply(99));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_5&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;In conclusion, if possible, we should try to use method references can make our code cleaner, more readable &amp;amp; promote code reusability, but they have some restrictions on some cases.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/3899204319396482188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/01/java8-method-references.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/3899204319396482188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/3899204319396482188'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/01/java8-method-references.html' title='[Java8] Method References'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-1471197564416435136</id><published>2019-01-07T00:48:00.000-08:00</published><updated>2019-01-10T22:28:44.376-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bytecode"/><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><category scheme="http://www.blogger.com/atom/ns#" term="jvm"/><category scheme="http://www.blogger.com/atom/ns#" term="lambda"/><title type='text'>[Java8] the compiled bytecode of lambda </title><content type='html'>&lt;p&gt;What&amp;#39;s byecode of lambda be generated in Java is interesting for me. From below simple code, we can execute javap to get the compiled asm code which will be performed by JVM.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-public&quot;&gt;{
   private Function&amp;lt;String, Integer&amp;gt; f = s -&amp;gt; Integer.parseInt(s);
   public String test()
   {
      Function&amp;lt;String, String&amp;gt; c = (a) -&amp;gt; a.toUpperCase();
      Supplier&amp;lt;Date&amp;gt; s = () -&amp;gt; new Date();
      return c.apply(&amp;quot;java&amp;quot;) + s.get() + f.apply(&amp;quot;99&amp;quot;);
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;javap -c -p LambdaBytecode.class&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;public class org.javasafari.lambda.LambdaBytecode {
  private java.util.function.Function&amp;lt;java.lang.String, java.lang.Integer&amp;gt; f;

  public org.javasafari.lambda.LambdaBytecode();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object.&amp;quot;&amp;lt;init&amp;gt;&amp;quot;:()V
       4: aload_0
       5: invokedynamic #2,  0              // InvokeDynamic #0:apply:()Ljava/util/function/Function;
      10: putfield      #3                  // Field f:Ljava/util/function/Function;
      13: return

  public java.lang.String test();
    Code:
       0: invokedynamic #4,  0              // InvokeDynamic #1:apply:()Ljava/util/function/Function;
       5: astore_1
       6: invokedynamic #5,  0              // InvokeDynamic #2:get:()Ljava/util/function/Supplier;
      11: astore_2
      12: new           #6                  // class java/lang/StringBuilder
      15: dup
      16: invokespecial #7                  // Method java/lang/StringBuilder.&amp;quot;&amp;lt;init&amp;gt;&amp;quot;:()V
      19: aload_1
      20: ldc           #8                  // String java
      22: invokeinterface #9,  2            // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
      27: checkcast     #10                 // class java/lang/String
      30: invokevirtual #11                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      33: aload_2
      34: invokeinterface #12,  1           // InterfaceMethod java/util/function/Supplier.get:()Ljava/lang/Object;
      39: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      42: aload_0
      43: getfield      #3                  // Field f:Ljava/util/function/Function;
      46: ldc           #14                 // String 99
      48: invokeinterface #9,  2            // InterfaceMethod java/util/function/Function.apply:(Ljava/lang/Object;)Ljava/lang/Object;
      53: invokevirtual #13                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      56: invokevirtual #15                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      59: areturn

  private static java.util.Date lambda$test$2();
    Code:
       0: new           #16                 // class java/util/Date
       3: dup
       4: invokespecial #17                 // Method java/util/Date.&amp;quot;&amp;lt;init&amp;gt;&amp;quot;:()V
       7: areturn

  private static java.lang.String lambda$test$1(java.lang.String);
    Code:
       0: aload_0
       1: invokevirtual #18                 // Method java/lang/String.toUpperCase:()Ljava/lang/String;
       4: areturn

  private static java.lang.Integer lambda$new$0(java.lang.String);
    Code:
       0: aload_0
       1: invokestatic  #19                 // Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
       4: invokestatic  #20                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       7: areturn
}

&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_0&quot;&gt;Lambdas and invokedynamic&lt;/h2&gt;

&lt;p&gt;The translation of a lambda expression to be bytecode will be performed in below steps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate an invokedynamic call site (lambda factory), which when invoked returns an instance of the Functional Interface defined. &lt;/li&gt;
&lt;li&gt;Create a static method which included the lambda expression will be invoked through the invokedynamic instruction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to know how invokedynamic works, &amp;quot;&lt;a href=&quot;https://www.infoq.com/presentations/invokedynamic&quot;&gt;Using Invoke Dynamic to Teach the JVM a New Language&lt;/a&gt;&amp;quot; is good for us.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/1471197564416435136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2019/01/java8-compiled-bytecode-of-lambda.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/1471197564416435136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/1471197564416435136'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2019/01/java8-compiled-bytecode-of-lambda.html' title='[Java8] the compiled bytecode of lambda '/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-4505352643576137931</id><published>2018-12-27T02:01:00.001-08:00</published><updated>2018-12-28T06:34:20.901-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><category scheme="http://www.blogger.com/atom/ns#" term="lambda expression"/><title type='text'>[Java8] Lambda Expression</title><content type='html'>&lt;p&gt;From Wikipedia, the free encyclopedia&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In computer programming, &lt;strong&gt;an anonymous function (function literal, lambda abstraction, or lambda expression) is a function definition that is not bound to an identifier.&lt;/strong&gt; &lt;strong&gt;Anonymous functions are often arguments being passed to higher-order functions, or used for constructing the result of a higher-order function that needs to return a function&lt;/strong&gt;.[1] If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function. Anonymous functions are ubiquitous in functional programming languages and other languages with first-class functions, where they fulfill the same role for the function type as literals do for other data types.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What&amp;#39;s a lambda expression in Java world?&lt;br/&gt;
&lt;strong&gt;A lambda expression is an unnamed block of code with a list of formal parameters and a body, or named an anonymous function.&lt;/strong&gt;&lt;br/&gt;
It can be easily imagined with 3 parts: arguments list, arrow token and body. Let&amp;#39;s see more examples.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;() -&amp;gt; {}                // No parameters; result is void
() -&amp;gt; 42                // No parameters, expression body
() -&amp;gt; null              // No parameters, expression body
() -&amp;gt; { return 42; }    // No parameters, block body with return
() -&amp;gt; { System.gc(); }  // No parameters, void block body
() -&amp;gt; {                 // Complex block body with returns
  if (true) return 12;
  else {
    int result = 15;
    for (int i = 1; i &amp;lt; 10; i++)
      result *= i;
    return result;
} }
(int x) -&amp;gt; x+1              // Single declared-type parameter
(int x) -&amp;gt; { return x+1; }  // Single declared-type parameter
(x) -&amp;gt; x+1
x -&amp;gt; x+1
(String s) -&amp;gt; s.length()
(Thread t) -&amp;gt; { t.start(); }  // Single declared-type parameter
s -&amp;gt; s.length()               // Single inferred-type parameter
t -&amp;gt; { t.start(); }           // Single inferred-type parameter

(int x, int y) -&amp;gt; x+y  // Multiple declared-type parameters
(x, y) -&amp;gt; x+y          // Multiple inferred-type parameters
(x, int y) -&amp;gt; x+y    // Illegal: can&amp;#39;t mix inferred and declared types
(x, final y) -&amp;gt; x+y  // Illegal: no modifiers with inferred types

&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Basically, we should use inferred-type parameters and simple statement as body while writing code. &lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/4505352643576137931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2018/12/java8-lambda-expression.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/4505352643576137931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/4505352643576137931'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2018/12/java8-lambda-expression.html' title='[Java8] Lambda Expression'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-5758410157563169404</id><published>2018-12-22T07:22:00.000-08:00</published><updated>2018-12-22T18:52:08.849-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="default methods"/><category scheme="http://www.blogger.com/atom/ns#" term="interface"/><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><category scheme="http://www.blogger.com/atom/ns#" term="map"/><title type='text'>[Java8] Map with Mew Default Methods</title><content type='html'>&lt;p&gt;Java 8 introduced the new default methods to Map interface which stores lazied-computed value and doesn&amp;#39;t break map contract. We can be based on below to write clean code.&lt;/p&gt;

&lt;h2 id=&quot;toc_0&quot;&gt;getOrDefault&lt;/h2&gt;

&lt;p&gt;Returns the value to which the specified key is mapped, or defaultValue if this map contains no mapping for the key.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testGetOfDefault()
   {
      Map&amp;lt;String, Integer&amp;gt; studentGrades = new HashMap&amp;lt;&amp;gt;();
      Assert.assertThat(studentGrades.getOrDefault(&amp;quot;Chris&amp;quot;, 0), equalTo(new Integer(0)));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_1&quot;&gt;forEach&lt;/h2&gt;

&lt;p&gt;Performs the give action for each entry in this map util all entries have been processed or the action throws an exception.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testForEach()
   {
      Map&amp;lt;String, Integer&amp;gt; collector = new HashMap()
      { { put(&amp;quot;A&amp;quot;, 99); put(&amp;quot;B&amp;quot;, 80); put(&amp;quot;C&amp;quot;, 70); } };
      collector.forEach((key, value) -&amp;gt; System.out.println(String.format(&amp;quot;%s =&amp;gt; %s&amp;quot;, key, value)));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_2&quot;&gt;replaceAll&lt;/h2&gt;

&lt;p&gt;Replaces each entry&amp;#39;s value with the result of invoking the given function on that entry util all entries have been processed or the function throws an exception.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testReplaceAll()
   {
      Map&amp;lt;String, Integer&amp;gt; collector = new HashMap()
      { { put(&amp;quot;A&amp;quot;, 99); put(&amp;quot;B&amp;quot;, 82); put(&amp;quot;C&amp;quot;, 71); } };
      collector.replaceAll((key, value) -&amp;gt; value &amp;lt; 90 ? value + 10 : value);
      assertThat(collector, hasEntry(&amp;quot;A&amp;quot;, 99));
      assertThat(collector, hasEntry(&amp;quot;B&amp;quot;, 92));
      assertThat(collector, hasEntry(&amp;quot;C&amp;quot;, 81));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_3&quot;&gt;putIfAbsent&lt;/h2&gt;

&lt;p&gt;If the specified key is not already associated with a value is mapped to null associates if with the given value and return null, else returns the current value.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testPutIfAbsent()
   {
      Map&amp;lt;String, Integer&amp;gt; counters = new HashMap()
      {{ put(&amp;quot;c0&amp;quot;, 0); }};

      counters.putIfAbsent(&amp;quot;c0&amp;quot;, 99);
      counters.putIfAbsent(&amp;quot;c1&amp;quot;, 99);
      
      assertEquals(Integer.valueOf(0), counters.get(&amp;quot;c0&amp;quot;));
      assertEquals(Integer.valueOf(99), counters.get(&amp;quot;c1&amp;quot;));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_4&quot;&gt;computeIfAbsent&lt;/h2&gt;

&lt;p&gt;If the specified key is not already associated with a value, attempts too compute its value using the given function and enters it into this map unless null.&lt;/p&gt;

&lt;pre class=&quot;line-numbers&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testComputeIfAbsent()
   {
      Map&amp;lt;String, List&amp;lt;Integer&amp;gt;&amp;gt; counters = new HashMap&amp;lt;&amp;gt;();
      counters.computeIfAbsent(&amp;quot;key&amp;quot;, k -&amp;gt; new ArrayList&amp;lt;&amp;gt;()).addAll(Arrays.asList(1, 3, 5));
      Assert.assertThat(counters.get(&amp;quot;key&amp;quot;), hasItems(1, 3, 5));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_5&quot;&gt;computeIfPresent&lt;/h2&gt;

&lt;p&gt;If the value for the specified key is present and not-null, attempts to compute a new mapping given the key and its current mapped value.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testComputeIfPresent()
   {
      Map&amp;lt;String, Integer&amp;gt; map = new HashMap()
      {{
         put(&amp;quot;key&amp;quot;, 2);
      }};
      map.computeIfPresent(&amp;quot;key&amp;quot;, (k, v) -&amp;gt; v / 2);
      assertThat(map.get(&amp;quot;key&amp;quot;), equalTo(1));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;toc_6&quot;&gt;merge&lt;/h2&gt;

&lt;p&gt;If the value for the specified key is present and non-null, attempts to compute a new mapping give the key and its current mapped value.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testMergeValue()
   {
      Map&amp;lt;String, String&amp;gt; holder = new HashMap();
      holder.put(&amp;quot;chris&amp;quot;, &amp;quot;^^~&amp;quot;);
      holder.merge(&amp;quot;chris&amp;quot;, &amp;quot;Java&amp;quot;, (v1, v2) -&amp;gt; v1.concat(v2));
      Assert.assertThat(holder.get(&amp;quot;chris&amp;quot;), is(&amp;quot;^^~Java&amp;quot;));
   }
   
&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/5758410157563169404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2018/12/java8-map-with-mew-default-methods.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/5758410157563169404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/5758410157563169404'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2018/12/java8-map-with-mew-default-methods.html' title='[Java8] Map with Mew Default Methods'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-8523124722342991552</id><published>2018-12-14T18:13:00.000-08:00</published><updated>2018-12-14T19:30:35.933-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><category scheme="http://www.blogger.com/atom/ns#" term="Optional"/><title type='text'>[Java8] Optional</title><content type='html'>&lt;p&gt;Java 8 SE introduces a new class called Optional&lt;T&gt; that is inspired from Haskell and Scala. It&amp;#39;s a class that encapsulates an option value. We can view Optional as a single value that either contains a value or not.&lt;/p&gt;

&lt;p&gt;From Java definition&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are some test cases.&lt;/p&gt;

&lt;p&gt;Creates the non-null and null value optional.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;  @Test
   public void testCreate_NonNull_null_Optionals()
   {
      Optional&amp;lt;String&amp;gt; country = Optional.of(&amp;quot;Taiwan&amp;quot;);
      Assertions.assertTrue(country.isPresent());
      Assertions.assertEquals(&amp;quot;Taiwan&amp;quot;, country.get());

      Assertions.assertEquals(false, Optional.ofNullable(null).isPresent());
      Assertions.assertEquals(&amp;quot;defaultValue&amp;quot;, Optional.ofNullable(null).orElse(&amp;quot;defaultValue&amp;quot;));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Return value if present, otherwise return other.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;   @Test
   public void testGetElseOption()
   {
      Optional&amp;lt;Date&amp;gt; current = Optional.ofNullable(null);
      Assertions.assertNotNull(current.orElse(new Date()));
   }
   
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Return the value if present, otherwise invoke other and return  the result of that invocation.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;   @Test
   public void testOrElseGet()
   {
      Date dateNow = null;
Assertions.assertNotNull(Optional.ofNullable(dateNow).orElseGet(Date::new));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Return  the contained value, if present, otherwise throw an exception to be created by the provided supplier.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;   @Test
   public void testOrElseThrow()
   {
      Date dateNow = null;
      Assertions.assertThrows(IllegalArgumentException.class, 
         () -&amp;gt; Optional.ofNullable(dateNow).orElseThrow(IllegalArgumentException::new));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If a value is present, and the value matches the given predicate, return a describing the value, otherwise return an empty.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;   @Test
   public void testFilter()
   {
      Optional&amp;lt;String&amp;gt; taipeiCity = Optional.of(&amp;quot;Taipei&amp;quot;).filter((v) -&amp;gt; v.contains(&amp;quot;No.1 City&amp;quot;));
      Assertions.assertEquals(Optional.empty(), taipeiCity);

      Optional&amp;lt;String&amp;gt; county = Optional.of(&amp;quot;Taiwan&amp;quot;).filter(v -&amp;gt; v.contains(&amp;quot;Taiwan&amp;quot;));
      Assertions.assertEquals(&amp;quot;Taiwan&amp;quot;, county.get());
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If a value is present, apply the provided {@code Optional}-bearing mapping function to it, return that result, otherwise return an empty {@code Optional}&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;   @Test
   public void testFlatMap()
   {
      Optional&amp;lt;Integer&amp;gt; numOp = Optional.of(&amp;quot;111&amp;quot;).flatMap(v -&amp;gt; Optional.of(Integer.valueOf(v)));
      Assertions.assertEquals(Integer.valueOf(111), numOp.get());
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In Java8 Optional is often be misused, optionals are not as easy as they seem. &lt;a href=&quot;https://dzone.com/articles/using-optional-correctly-is-not-optional&quot;&gt;This tutorial&lt;/a&gt; will help us to avoid doing stupid code.&lt;/p&gt;


&lt;a href=&quot;https://dzone.com/articles/using-optional-correctly-is-not-optional&quot;&gt;26 Reasons Why Using Optional Correctly Is Not Optional&lt;/a&gt;

</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/8523124722342991552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2018/12/java8-optional.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/8523124722342991552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/8523124722342991552'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2018/12/java8-optional.html' title='[Java8] Optional'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-6124007503110857475</id><published>2018-12-12T19:12:00.000-08:00</published><updated>2018-12-12T20:03:43.620-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="BiFunction"/><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><category scheme="http://www.blogger.com/atom/ns#" term="unctional interface"/><title type='text'>[Java8] BiFunction Functional Interface</title><content type='html'>&lt;p&gt;From Wikipedia about Arity, &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In logic, mathematics, and computer science, the arity /ˈærɪti/ (About this soundlisten) of a function or operation is the number of arguments or operands that the function takes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A binary function takes two arguments.&lt;br/&gt;
Example: {f(x,y)=2xy}&lt;/p&gt;

&lt;p&gt;From Java definition&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Represents a function that accepts two arguments and produces a result. This is the two arity  specialization of Function.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;here are some test cases to understand deeply biFunction.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testFindEvenNumbers()
   {

      //given
      BiFunction&amp;lt;List&amp;lt;Integer&amp;gt;, Predicate&amp;lt;Integer&amp;gt;, List&amp;lt;Integer&amp;gt;&amp;gt; evenFinder = (list, even) -&amp;gt; {
         return list.stream().filter(even).collect(Collectors.toList());
      };

      //when
      List&amp;lt;Integer&amp;gt; evenNumList = evenFinder.apply(
         Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8),
         (num) -&amp;gt; num % 2 == 0
      );

      //verify
      MatcherAssert.assertThat(evenNumList, hasItems(2, 4, 6, 8));
   }
&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/6124007503110857475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2018/12/java8-bifunction-functional-interface.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/6124007503110857475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/6124007503110857475'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2018/12/java8-bifunction-functional-interface.html' title='[Java8] BiFunction Functional Interface'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-1749034059074316719</id><published>2018-12-11T17:33:00.000-08:00</published><updated>2018-12-11T17:49:50.353-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java functional interface"/><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><category scheme="http://www.blogger.com/atom/ns#" term="UnaryOperator"/><title type='text'>[Java8] UnaryOperator Functional Interface</title><content type='html'>&lt;p&gt;Unary operators need only one operand to &lt;strong&gt;perform the task or operation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From Java definition&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Represents an operation on &lt;strong&gt;single operand that produces a result of the same type as its operand&lt;/strong&gt;. This is a specialization of Function for the case where the operand the result are of the same type.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are some test cases.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;   @Test
   public void testUnaryOperator()
   {
      //when
      UnaryOperator&amp;lt;Integer&amp;gt; increment = (n) -&amp;gt; ++n;
      //verify
      Assertions.assertEquals(Integer.valueOf(2), increment.apply(1));

   }
&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/1749034059074316719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2018/12/java8-unaryoperator-functional-interface.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/1749034059074316719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/1749034059074316719'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2018/12/java8-unaryoperator-functional-interface.html' title='[Java8] UnaryOperator Functional Interface'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-5382448127800888362</id><published>2018-12-10T18:48:00.000-08:00</published><updated>2018-12-10T19:02:18.412-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="functional interface"/><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><category scheme="http://www.blogger.com/atom/ns#" term="predicate"/><title type='text'>[Java8] Predicate Functional Interface</title><content type='html'>&lt;p&gt;Definition of Predicate&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a : something that is affirmed or denied of the subject in a proposition in logic&lt;/li&gt;
&lt;li&gt;b : a term designating a property or relation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From java definition&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Represents a predicate (boolean-valued function) of one argument.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are some test cases.&lt;br/&gt;
Evaluates this predicate on the given argument.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testPredicateTest()
   {
      //given
      Predicate&amp;lt;Integer&amp;gt; isEven = (num) -&amp;gt; num % 2 == 0;
      //verify
      Assertions.assertTrue(isEven.test(4));
      Assertions.assertTrue(isEven.test(0));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A composed predicate that represents a short-circuiting logical AND of this predicate and another.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testPredicateTestAnd()
   {
      //given
      Predicate&amp;lt;Integer&amp;gt; isEven = (num) -&amp;gt; num % 2 == 0;
      Predicate&amp;lt;Integer&amp;gt; isEvenAndGreater100 = isEven.and((num) -&amp;gt; num &amp;gt; 100);
      //verify
      Assertions.assertTrue(isEvenAndGreater100.test(102));
      Assertions.assertFalse(isEvenAndGreater100.test(101));
      Assertions.assertFalse(isEvenAndGreater100.test(3));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A composed predicate that represents a short-circuiting logical OR of this predicate and another.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testPredicateTestOr()
   {
      //given
      Predicate&amp;lt;Integer&amp;gt; isEven = (num) -&amp;gt; num % 2 == 0;
      Predicate&amp;lt;Integer&amp;gt; isEvenOrGreater100 = isEven.or((num) -&amp;gt; num &amp;gt; 100);
      //verify
      Assertions.assertTrue(isEvenOrGreater100.test(102));
      Assertions.assertTrue(isEvenOrGreater100.test(101));
      Assertions.assertFalse(isEvenOrGreater100.test(3));

   }
   
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A predicate that tests if two arguments are equal according to {@link Objects#equals(Object, Object)}.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testPredicateIsEqual()
   {
      Assertions.assertTrue(Predicate.isEqual(20).test(20));
   }
&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/5382448127800888362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2018/12/java8-predicate-functional-interface.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/5382448127800888362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/5382448127800888362'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2018/12/java8-predicate-functional-interface.html' title='[Java8] Predicate Functional Interface'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-175825215772488399</id><published>2018-12-09T18:56:00.001-08:00</published><updated>2018-12-09T23:47:09.963-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="function interface"/><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><category scheme="http://www.blogger.com/atom/ns#" term="supplier"/><category scheme="http://www.blogger.com/atom/ns#" term="test case"/><title type='text'>[Java8] Supplier Functional Interface</title><content type='html'>&lt;p&gt;From wikipedia &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manufacturer, uses tools and labour to make things for sale
&lt;ul&gt;
&lt;li&gt;Processor (manufacturing), converts a product from one form to another&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Wholesaler, sells goods or merchandise to retailers&lt;/li&gt;
&lt;li&gt;Merchant, a professional dealing with trade&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From java definition &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Represents a supplier of results. &lt;strong&gt;There is no requirement that a new or distinct result be returned&lt;/strong&gt; each time the supplier is invoked.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are some test cases.&lt;br/&gt;
Gets a result.&lt;/p&gt;

&lt;pre class=&quot;line-numbers prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;   @Test
   public void testGetCurrentDate()
   {
      //when
      Supplier&amp;lt;LocalDateTime&amp;gt; dateTimeSupplier = () -&amp;gt; LocalDateTime.now();

      //verify
      Assertions.assertNotNull(dateTimeSupplier.get());
   }
&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/175825215772488399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2018/12/java8-supplier-functional-interface.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/175825215772488399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/175825215772488399'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2018/12/java8-supplier-functional-interface.html' title='[Java8] Supplier Functional Interface'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-961972444410234892</id><published>2018-12-07T22:04:00.000-08:00</published><updated>2018-12-07T22:46:19.517-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="function interface"/><category scheme="http://www.blogger.com/atom/ns#" term="functional"/><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><title type='text'>[Java8] Function interface</title><content type='html'>&lt;p&gt;Function interface has an abstract method &amp;quot;apply&amp;quot; which take argument of type T and must returns a result of type R.&lt;/p&gt;

&lt;p&gt;Java definition&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Represents a function that &lt;strong&gt;accepts one argument and produces a result.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;public interface Function&amp;lt;T, R&amp;gt; {
    R apply(T t);
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here are some test cases.&lt;br/&gt;
Applies this function to the given argument.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;    @Test
   public void testFuncApply()
   {
      Function&amp;lt;Integer, Integer&amp;gt; sqrt = (num) -&amp;gt; num * num;
      Assertions.assertEquals(Integer.valueOf(100), sqrt.apply(10));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A composed function that first applies the function to its input, and then applies this to the result.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt; @Test
   public void testFuncCompose()
   {
      //given
      Function&amp;lt;Integer, Integer&amp;gt; sqrt = (num) -&amp;gt; num * num;
      Function&amp;lt;String, Integer&amp;gt; input = sqrt.compose(((s) -&amp;gt; Integer.parseInt(s)));
      //when
      Integer result = input.apply(&amp;quot;9&amp;quot;);
      //verify
      Assertions.assertEquals(Integer.valueOf(81), result);
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A composed function that first applies this function to its input and the applies the function to the result.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testFuncAndThen()
   {
      //given
      Function&amp;lt;Integer, Integer&amp;gt; sqrt = (num) -&amp;gt; num * num;
      Function&amp;lt;Integer, Integer&amp;gt; times = sqrt.andThen((num) -&amp;gt; num * num);
      Function&amp;lt;String, Integer&amp;gt; input = times.compose(((s) -&amp;gt; Integer.parseInt(s)));

      //when
      Integer result = input.apply(&amp;quot;10&amp;quot;);

      //verify
      Assertions.assertEquals(Integer.valueOf(10000), result);
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A function that always returns its input argument.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;   @Test
   public void testIdentity()
   {
      //given
      Map&amp;lt;String, String&amp;gt; result =
         Arrays.asList(&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;)
            .stream()
            .collect(Collectors.toMap(Function.identity(), str -&amp;gt; str));
      //verify
      Assertions.assertTrue(result.size() == 3);
      Assertions.assertEquals(result.get(&amp;quot;a&amp;quot;), &amp;quot;a&amp;quot;);
      Assertions.assertEquals(result.get(&amp;quot;b&amp;quot;), &amp;quot;b&amp;quot;);
      Assertions.assertEquals(result.get(&amp;quot;c&amp;quot;), &amp;quot;c&amp;quot;);
   }
&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/961972444410234892/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2018/12/java8-function-interface.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/961972444410234892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/961972444410234892'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2018/12/java8-function-interface.html' title='[Java8] Function interface'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-8335007227467005363</id><published>2018-12-07T18:04:00.001-08:00</published><updated>2018-12-07T18:48:20.823-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="functional interface"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="java8"/><title type='text'>[Java8] Consumer Functional Interface</title><content type='html'>&lt;p&gt;From wikipedia&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A consumer is a person or organization that use economic services or commodities.&lt;/p&gt;

&lt;p&gt;The consumer is the one who pays something to consume goods and services produced. As such, consumers play a vital role in the economic system of a nation. Without consumer demand, producers would lack one of the key motivations to produce: to sell to consumers. The consumer also forms part of the chain of distribution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From Java definition&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Represent an operation that &lt;strong&gt;accepts a single input argument and returns no result&lt;/strong&gt;. Unlike most other functional interfaces, &lt;strong&gt;is expected to operate via side-effects.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Its main functional name is &amp;quot;accept&amp;quot;, but why not call &amp;quot;consume&amp;quot; method. Does it mean consumer only accepts the input argument to consume? &lt;/p&gt;

&lt;p&gt;Here are some test cases.&lt;br/&gt;
Performs this operation on the given argument.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;  @Test
   public void testConsumerAccept()
   {
      //given
      List&amp;lt;String&amp;gt; names = new ArrayList();
      Consumer&amp;lt;String&amp;gt; addStudent = (name) -&amp;gt; names.add(name);
      //when
      addStudent.accept(&amp;quot;chris&amp;quot;);
      //verify
      Assertions.assertEquals(&amp;quot;chris&amp;quot;, names.get(0));
   }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A composed consumer that performs, in sequence, this operation followed by the code after operation&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-@test&quot;&gt;   public void testConsumerAcceptAndThenPrint()
   {
      //given
      List&amp;lt;String&amp;gt; names = new ArrayList();
      Consumer&amp;lt;String&amp;gt; addStudent = (name) -&amp;gt; names.add(name);
      Consumer&amp;lt;String&amp;gt; printStudentAfterAdding = addStudent.andThen(name -&amp;gt; System.out.println(&amp;quot;added &amp;quot; + name));
      //when
      printStudentAfterAdding.accept(&amp;quot;chris&amp;quot;);
      //verify
      Assertions.assertEquals(&amp;quot;chris&amp;quot;, names.get(0));
   }
&lt;/code&gt;&lt;/pre&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/8335007227467005363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2018/12/back-to-java8-consumer-functional.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/8335007227467005363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/8335007227467005363'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2018/12/back-to-java8-consumer-functional.html' title='[Java8] Consumer Functional Interface'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5721461121197482632.post-6969124750989257255</id><published>2018-11-16T18:13:00.001-08:00</published><updated>2018-11-16T19:44:27.291-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="retry design"/><category scheme="http://www.blogger.com/atom/ns#" term="retry pattern"/><title type='text'>Retry Design</title><content type='html'>&lt;p&gt;Sometimes, Network is inherently unreliable. Connections will occasionally time out or be dropped. For some reasons, we still want to try to establish a connection to a remote endpoint which went down. &lt;/p&gt;

&lt;p&gt;There is straightforward answer which wrote down below code to resolve it.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot; &gt;&lt;code class=&quot;language-java&quot;&gt;      try
      {
          this.conn = connect();
      }
      catch (Exception e)
      {
         for (int i = 0; i &amp;lt; maxAttempts; i++)
         {
            try { Thread.sleep(1000); } catch (InterruptedException e) {};
            this.conn = connect();
         }
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But the solution is difficult to maintain and a lack of flexibility. If we are using java8, this may change below to more be useful.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;public static &amp;lt;T&amp;gt; Object retry(Supplier&amp;lt;T&amp;gt; function, int retryCount) throws Exception
   {
      while (0 &amp;lt; retryCount)
      {
         try
         {
            return function.get();
         }
         catch (Exception e)
         {
            if ((retryCount--) == 0)
               throw e;
         }
      }
      return null;
   }
   
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Based on above two solutions, we still try to add extra code into connection logic and the unnecessary design. I think there&amp;#39;s much better to use if you are using spring or AOP concept.&lt;/p&gt;

&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code class=&quot;language-java&quot;&gt; @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 500))
 public void establishConnection() {
    this.connection = newConnection();
 } 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Code is simply and easy to use.&lt;/p&gt;

&lt;h3 id=&quot;toc_0&quot;&gt;Reference&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/spring-projects/spring-retry&quot;&gt;spring-retry &lt;/a&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://www.chrispad.com/feeds/6969124750989257255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.chrispad.com/2018/11/retry-design.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/6969124750989257255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5721461121197482632/posts/default/6969124750989257255'/><link rel='alternate' type='text/html' href='http://www.chrispad.com/2018/11/retry-design.html' title='Retry Design'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>