SlideShare a Scribd company logo
1 of 108
Hamlet D'Arcy – Canoo Engineering AG @HamletDRC http://hamletdarcy.blogspot.com Java Boilerplate Busters
Agenda ,[object Object]
Builders / Fluent APIs
Function Objects /  Proxies / Interceptors
Java 7
Lombok / Groovy
About Me
Boilerplate – noun Code you shouldn't be writing yourself
Agenda ,[object Object]
Builders / Fluent APIs
Function Objects /  Proxies / Interceptors
Java 7
Lombok / Groovy
import static  org.apache.commons.lang.StringUtils.*;
import static  org.apache.commons.lang.StringUtils.*; assert   isAlpha ( "abcde" ); assert   isNumeric ( "12345" ); assert   isAlphanumeric ( "12345abc" );
import static  org.apache.commons.lang.StringUtils.*; assert   isBlank ( "" ); assert   isBlank ( null );
import static  org.apache.commons.lang.StringUtils.*; assert   isAllLowerCase ( "abcdef" ); assert   isAllUpperCase ( "ABCDEF" );
import static  org.apache.commons.lang.StringUtils.*; assert   "abc"  ==  defaultString ( "abc" ); assert   ""  ==  defaultString ( "" ); assert   ""  ==  defaultString ( null );
import static  org.apache.commons.lang.StringUtils.*; assert   "abc" .equals( left ( "abcdef" ,  3 )); assert   "def" .equals( right ( "abcdef" ,  3 )); assert   null  ==  right ( null ,  3 );
import static  org.apache.commons.lang.StringUtils.*; Object[] array =  new  Object[]{ 1 ,  2 ,  3 }; assert   "1, 2, 3" .equals( join (array,  ", " )); List list = Arrays. asList ( 1 ,  2 ,  3 ); assert   "1, 2, 3" .equals( join (list,  ", " ));
import  org.apache.commons.lang.StringEscapeUtils;
import  org.apache.commons.lang.StringEscapeUtils; String xmlText =  " amp;quot; Hello amp;quot;   &  amp;quot; GoodBye amp;quot; " ; String escapedXml =  ""Hello" & " +  ""GoodBye"" ; assert  escapedXml.equals( StringEscapeUtils. escapeXml (xmlText) ); assert  xmlText.equals( StringEscapeUtils. unescapeXml (escapedXml) );
import  org.apache.commons.lang.StringEscapeUtils; String htmlText =  &quot;<body>text</body>&quot; ; String escapedHtml =  &quot;&lt;body&gt;&quot;  + &quot;text&lt;/body&gt;&quot; ; assert  escapedHtml.equals( StringEscapeUtils. escapeHtml (htmlText) ); assert  htmlText.equals( StringEscapeUtils. unescapeHtml (escapedHtml) );
import  org.apache.commons.lang.StringEscapeUtils; String csvText =  &quot;red, beans, and rice&quot; ; String escapedCsv =  &quot; amp;quot; red, beans, and rice amp;quot; &quot; ; assert  escapedCsv.equals( StringEscapeUtils. escapeCsv (csvText) ); assert  csvText.equals( StringEscapeUtils. unescapeCsv (escapedCsv) );
import static  org.apache.commons.lang.ArrayUtils.*;
import static  org.apache.commons.lang.ArrayUtils.*; int [] evens =  new   int []{ 2 ,  4 ,  6 }; int [] odds =  new   int []{ 1 ,  3 ,  5 }; assert   contains (evens,  2 ); assert   contains (odds,  3 );
import static  org.apache.commons.lang.ArrayUtils.*; int [] evens =  new   int []{ 2 ,  4 ,  6 }; int [] odds =  new   int []{ 1 ,  3 ,  5 }; assert  Arrays. equals (   new   int []{ 2 ,  4 ,  6 ,  8 },    add (evens,  8 ) ); assert  Arrays. equals ( new   int []{ 2 ,  4 ,  6 ,  1 ,  3 ,  5 },  addAll (evens, odds) );
import static  org.apache.commons.lang.ArrayUtils.*; int [] evens =  new   int []{ 2 ,  4 ,  6 }; int [] odds =  new   int []{ 1 ,  3 ,  5 }; assert  Arrays. equals (   new   int []{ 2 ,  6 },    remove (evens,  1 ) ); assert  Arrays. equals (   new   int []{ 1 ,  3 },    remove (odds,  2 ) );
import static  org.apache.commons.lang.BooleanUtils.*;
import static  org.apache.commons.lang.BooleanUtils.*; assert   toBoolean ( &quot;true&quot; ); assert   toBoolean ( &quot;TRUE&quot; ); assert   toBoolean ( &quot;tRUe&quot; ); assert   toBoolean ( &quot;on&quot; ); assert   toBoolean ( &quot;ON&quot; ); assert   toBoolean ( &quot;yes&quot; ); assert   toBoolean ( &quot;YES&quot; );
import  org.apache.commons.lang.builder.ToStringBuilder;
import  org.apache.commons.lang.builder.ToStringBuilder; public   class  Person { String  name ; Date  timestamp  =  new  Date(); @Override public  String toString() { return   new  ToStringBuilder( this ) .append( &quot;name&quot; ,  name ) .append( &quot;timestamp&quot; ,  timestamp ) .toString(); } }
import  org.apache.commons.lang.builder.EqualsBuilder;
import  org.apache.commons.lang.builder.EqualsBuilder; public   class  Person { String  name ; Date  timestamp  =  new  Date(); @Override public   boolean  equals(Object obj) { if  (obj ==  null ) {  return   false ; } if  (obj ==  this ) {  return   true ; } if  (obj.getClass() != getClass()) {  return   false ; } Person rhs = (Person) obj; return   new  EqualsBuilder() .append( name , rhs. name ) .append( timestamp , rhs. timestamp ) .isEquals(); } }
import  org.apache.commons.lang.builder.HashCodeBuilder;
import  org.apache.commons.lang.builder.HashCodeBuilder; public   class  Person { String  name ; Date  timestamp  =  new  Date(); @Override public   int  hashCode() { return   new  HashCodeBuilder() .append( name ) .append( timestamp ) .toHashCode(); } }
import  org.apache.commons.lang.builder. CompareToBuilder ;
import  org.apache.commons.lang.builder. CompareToBuilder ; public   class  Person  implements  Comparable<Person> { String  name ; Date  timestamp  =  new  Date(); public   int  compareTo(Person other) { return   new  CompareToBuilder() .append( this . name , other. name ) .toComparison(); } }
Apache Commons Lang ,[object Object]
No Generics
Many functions obsoleted by JDK 5 ,[object Object],[object Object]
Not backwards compatible with 2.6
new  HashMap<T, Set<U>>
import  com.google.common.collect.Multimap;
import  com.google.common.collect.Multimap; Multimap<String, String> multiMap =  HashMultimap. create (); multiMap.put( &quot;Canoo&quot; ,  &quot;Hamlet&quot; ); multiMap.put( &quot;Canoo&quot; ,  &quot;Dierk&quot; ); multiMap.put( &quot;Canoo&quot; ,  &quot;Andres&quot; ); multiMap.put( &quot;EngineYard&quot; ,  &quot;Charles&quot; ); multiMap.put( &quot;EngineYard&quot; ,  &quot;Thomas&quot; ); multiMap.put( &quot;EngineYard&quot; ,  &quot;Nick&quot; );
import  com.google.common.collect.Multimap; assert  multiMap.containsKey( &quot;Canoo&quot; ); assert  multiMap.containsKey( &quot;EngineYard&quot; ); assert  multiMap.containsValue( &quot;Hamlet&quot; ); assert  multiMap.containsValue( &quot;Charles&quot; );
import  com.google.common.collect.Multimap; Collection<String> canooies = multiMap.get( &quot;Canoo&quot; ); Collection<String> c = Lists. newArrayList ( &quot;Dierk&quot; , &quot;Andres&quot; ,  &quot;Hamlet&quot; ); assert  canooies.containsAll(c);
import  com.google.common.collect.BiMap;
import  com.google.common.collect.BiMap; BiMap<String, String> biMap = HashBiMap. create (); biMap.put( &quot;Switzerland&quot; ,  &quot;die Schweiz&quot; ); biMap.put( &quot;Poland&quot; ,  &quot;Polska&quot; ); biMap.put( &quot;Austria&quot; ,  &quot;Österreich&quot; ); assert   &quot;Polska&quot;  == biMap.get( &quot;Poland&quot; ); assert   &quot;Switzerland&quot;  == biMap.inverse() .get( &quot;die Schweiz&quot; );
new  HashMap<T, Map<U, V>>
import  com.google.common.collect.Table;
import  com.google.common.collect.Table; Table<Integer, Integer, String> table =  HashBasedTable. create (); table.put( 1 ,  1 ,  &quot;Hamlet&quot; ); table.put( 1 ,  2 ,  &quot;Dierk&quot; ); table.put( 2 ,  1 ,  &quot;Andres&quot; ); table.put( 2 ,  2 ,  &quot;Matthius&quot; );
import  com.google.common.collect.Table; assert  table.contains( 1 ,  1 ); assert  table.containsRow( 1 ); assert  table.containsColumn( 2 ); assert  !table.contains( 3 ,  1 ); assert  !table.containsRow( 3 ); assert  !table.containsColumn( 3 ); assert   &quot;Hamlet&quot;  == table.get( 1 ,  1 ); assert  table.containsValue( &quot;Hamlet&quot; );
import  com.google.common.base.Joiner;
import  com.google.common.base.Joiner; Set<Integer> set = Sets. newHashSet ( 1 ,  2 ,  3 ); assert   &quot;1, 2, 3&quot; .equals(Joiner. on ( &quot;, &quot; ).join(set));
import  com.google.common.base.Splitter;
import  com.google.common.base.Splitter; String string =  &quot;1, 2, , 3&quot; ; Iterable<String> i = Splitter. on ( &quot;,&quot; ) .omitEmptyStrings() .trimResults() .split(string);
import static  com.google.common.collect.Iterables.*; import static  com.google.common.collect.Lists.*; Iterable<Integer> setAsInts =  transform (i, new  Function<String, Integer>() { @Override public  Integer apply(String input) { return  Integer. valueOf (input); } }); assert   newArrayList ( 1 ,  2 ,  3 ) .containsAll( newArrayList (setAsInts));
import static  com.google.common.base.Strings.*;
import static  com.google.common.base.Strings.*; assert   emptyToNull ( &quot;&quot; ) ==  null ; assert   &quot;&quot; .equals( nullToEmpty ( null )); assert   isNullOrEmpty ( &quot;&quot; ); assert   &quot;abcabcabc&quot; .equals( repeat ( &quot;abc&quot; ,  3 ));
import static  com.google.common.base.Preconditions.*;
import static  com.google.common.base.Preconditions.*; int  userID =  1 ; String userName =  &quot;some name&quot; ; checkArgument (userID >  0 ,  &quot;userid is negative: %s&quot; , userID); checkNotNull (userName,  &quot;user %s missing name&quot; , userID); checkState (userName.length() >  0 ,  &quot;user %s missing name&quot; , userID);
import static  com.google.common.base.Objects.*;
import static  com.google.common.base.Objects.*; class  Person { String  name ; Date  timestamp  =  new  Date(); @Override public  String toString() { return   toStringHelper ( this ) .add( &quot;name&quot; ,  name ) .add( &quot;timestamp&quot; ,  timestamp ).toString(); } }
import static  com.google.common.base.Equivalences.*;
import static  com.google.common.base.Equivalences.*; class  Person  implements  Comparable<Person> { String  name ; Date  timestamp  =  new  Date(); @Override public   boolean  equals(Object obj) { if  (obj ==  null ) {  return   false ; } if  (obj ==  this ) {  return   true ; } if  (obj.getClass() != getClass()) { return   false ; } Person rhs = (Person) obj; return   equals ().equivalent( name , rhs. name ) && equals ().equivalent( timestamp , rhs. timestamp ); } @Override public   int  hashCode() { return   hashCode ( name ,  timestamp ); } }
import static  com.google.common.collect.ComparisonChain.*;
import static  com.google.common.collect.ComparisonChain.*; class  Person  implements  Comparable<Person> { String  name ; Date  timestamp  =  new  Date(); public   int  compareTo(Person other) { return   start () .compare( name , other. name ) .compare( timestamp , other. timestamp ) .result(); } }
import  com.google.common.base.Throwables;
import  com.google.common.base.Throwables; Exception ex =  new  Exception(); Throwables. propagateIfPossible (ex); Throwables. propagate (ex); // throws Exception Throwables. throwCause (ex,  false );
import  com.google.common.base.Function;
import  com.google.common.base.Function; Person alice =  new  Person( &quot;Alice&quot; ); Person bob =  new  Person( &quot;Bob&quot; ); Person carol =  new  Person( &quot;Carol&quot; ); List<Person> people =  newArrayList (alice, bob, carol);
import  com.google.common.base.Function; Function<Person, String> getName =  new  Function<Person, String>() { public  String apply(Person p) { return  p.getName(); } }; assert   &quot;Alice&quot;  == getName.apply(alice); Collection<String> names = Collections2 . transform (people, getName); assert  names.containsAll( newArrayList ( &quot;Alice&quot; ,  &quot;Bob&quot; ,  &quot;Carol&quot; ) );
import  com.google.common.base.Predicate;
import  com.google.common.base.Predicate; Predicate<Person> predicate =  new  Predicate<Person>() { public   boolean  apply(Person input) { return  input.getName().contains( &quot;o&quot; ); } }; Iterable<Person> filteredList = Iterables . filter ( people, predicate); assert  Iterables. contains (filteredList, bob); assert  Iterables. contains (filteredList, carol); assert  !Iterables. contains (filteredList, alice);
Google Guava ,[object Object]
Well-Designed
Consistent?
Active
Agenda ,[object Object]
Builders / Fluent APIs
Function Objects /  Proxies / Interceptors
Java 7
Lombok / Groovy
“Traditional API” Order order =  new  Order(); order.setItemName( &quot;lattes&quot; ); order.setQuantity( 2 ); order.pay(Currency. getInstance ( &quot;USD&quot; ));
“Modern API” new  FluentOrder() .withItem( &quot;lattes&quot; ) .withQuantity( 2 ) .pay(Currency. getInstance ( &quot;USD&quot; ));
“Modern API” class  FluentOrder { private  String  item ; private   int   quantity ; public  FluentOrder withItem(String item) { this . item  = item; return   this ; }   public  FluentOrder withQuantity( int  quantity) { this . quantity  = quantity; return   this ; }   boolean  pay(Currency currency) {   // pay order return   true ; } }
class  OrderBuilder { QuantityHolder withItem(String item) { return   new  QuantityHolder(item); } } class  QuantityHolder { private   final  String  item ; private  QuantityHolder(String item) { this . item  = item; } OrderFiller withQuantity( int  quantity) { return   new  OrderFiller( item , quantity);  } } class  OrderFiller { private   final  String  item ; private   final   int   quantity ; private  OrderFiller(String item,  int  quantity) { this . item  = item;  this . quantity  = quantity; } boolean  pay(Currency currency) { /* pay order... */   return   true ; } }
... another type-safe version new  Order( OrderBuilder. newInstance () .initItemName( &quot;latte&quot; ) .initQuantity( 10 ) .withCurrency(Currency. getInstance ( &quot;CHF&quot; )) ).pay(); // forgetting required args is a compile error new  Order( OrderBuilder.newInstance() .initItemName( &quot;latte&quot; ) .withCurrency(Currency.getInstance( &quot;CHF&quot; ) ));
public   class  OrderBuilder<NAME, QUANTITY> { // required fields private  String  itemName ; private   int   quantity ; private  Currency  currency ;  // optional field public   static  OrderBuilder<NOK, NOK> newInstance() { return   new  OrderBuilder<>(); } public  OrderBuilder(String itemName,  int  quantity, Currency currency) { this . itemName  = itemName; this . quantity  = quantity; this . currency  = currency; } public  OrderBuilder<OK, QUANTITY> initItemName(String itemName) { this . itemName  = itemName; return   new  OrderBuilder<>(name,  quantity ,  currency ); } public  OrderBuilder<NAME, OK> initQuantity( int  quantity) { this . quantity  = quantity; return   new  OrderBuilder<>( itemName , quantity,  currency ); } public  OrderBuilder<NAME, QUANTITY> withCurrency(Currency currency) { this . currency  = currency; return   this ; } ...  // getters & default ctor omitted }
... and it's just plain old Groovy new  Order( itemName:  'lattes' , quantity: 2 ).pay(Currency.getInstance( 'USD' )) new  Order().with { itemName =  'lattes' quantity = 2 pay(Currency. getInstance ( 'USD' )) }
Builders & Fluent API + More expressive + Type-safer + Easier to use - Harder to write - Harder to learn? - Some reformatting tools choke
Agenda ,[object Object]
Builders / Fluent APIs
Function Objects /  Proxies / Interceptors
Java 7
Lombok / Groovy
public   class  ResourceProvider {   private   final  ReadWriteLock  lock  =  new  ReentrantReadWriteLock(); private   final  Map<String, String>  data  =  new  ConcurrentHashMap();   public  String getResource(String key)  throws  Exception { lock .readLock().lock(); try  { return   data .get(key); }  finally  { lock .readLock().unlock(); } } public   void  refresh()  throws  Exception { lock .writeLock().lock(); try  { // reload settings... }  finally  { lock .writeLock().unlock(); } } } “Traditional API”
public   class  ResourceController { private   final  ReadWriteLock  lock  =  new  ReentrantReadWriteLock(); public  <T> T withReadLock(Callable<T> block)  throws  Exception { lock .readLock().lock(); try  { return  block.call(); }  finally  { lock .readLock().unlock(); } } public  <T> T withWriteLock(Callable<T> block)  throws  Exception { lock .writeLock().lock(); try  { return  block.call(); }  finally  { lock .writeLock().unlock(); } } } “Modern API” con't
public   class  ResourceProvider { private   final  ResourceController  controller  =  new  ResourceController(); private   final  Map<String, String>  data  =  new  ConcurrentHashMap(); public  String getResource( final  String key)  throws  Exception { return   controller .withReadLock( new  Callable<String>() { public  String call()  throws  Exception { return   data .get( key ); } }); } public   void  refresh()  throws  Exception { controller .withWriteLock( new  Callable<Void>() { public  Void call()  throws  Exception { // reload settings return   null ; } }); } } “Modern API” -- Function Objects
class  ResourceProvider { private   final   controller  =  new  ResourceController() private   final   data  = [:]  as  ConcurrentHashMap String getResource(String key) { controller .withReadLock({  data .get( key )  }  as  Callable) } void  refresh() { controller .withWriteLock( {  /* reload settings */ }  as  Callable)  } } “Modern API” -- Groovy Function Objects
public   class  DefaultResourceProvider  implements  ResourceProvider { private   final  Map<String, String>  data  =  new  ConcurrentHashMap(); @WithReadLock public  String getResource(String key) { return   data .get(key); } @WithWriteLock public   void  refresh() { System. out .println( &quot;Reloading the settings...&quot; ); } } “Modern API” -- Proxy Class
public   class  ResourceController  implements  InvocationHandler { private   final  Object  target ; private   final  ReadWriteLock  lock  =  new  ReentrantReadWriteLock(); ResourceController(Object target) {  this . target  = target; } public  Object invoke (Object proxy, Method method, Object[] args) { try  { Method targetMethod =  target .getClass().getMethod( method.getName(), method.getParameterTypes()); if  (targetMethod.isAnnotationPresent( WithReadLock . class )) { lock .readLock().lock(); try  { return  targetMethod.invoke( target , args); }  finally  { lock .readLock().unlock(); } }  else   if  (targetMethod.isAnnotationPresent( WithWriteLock . class )){ lock .writeLock().lock(); try  { return  targetMethod.invoke( target , args); }  finally  { lock .writeLock().unlock(); } }  else  { return  targetMethod.invoke( target , args); } }  catch  (Exception ex) { throw   new  RuntimeException(ex); } } }
“Modern API” -- Proxy Class con't InvocationHandler handler =  new  ResourceController( new  DefaultResourceProvider() ); ResourceProvider p = (ResourceProvider) Proxy. newProxyInstance ( DefaultResourceProvider. class .getClassLoader(), new  Class[]{ResourceProvider. class }, hand ler); p.refresh(); p.getResource( &quot;property&quot; );
“Modern API” -- Proxy Class con't class  ResourceProvider { private   final  Map  data  =  new  ConcurrentHashMap(); @WithReadLock String getResource(String key) { return  (String) data .get(key); } @WithWriteLock void  refresh() { // Reload settings... } }
public   class  WithLockInterceptor  {   // This is shared!!! private   final  ReadWriteLock  lock  =  new  ReentrantReadWriteLock(); @AroundInvoke public  Object enforceLock(InvocationContext context)  throws  Exception{ try  { Method targetMethod = context.getMethod(); if  (targetMethod.isAnnotationPresent( WithReadLock . class )) { lock .readLock().lock(); try  { return  context.proceed(); }  finally  { lock .readLock().unlock(); } }  else   if  (targetMethod.isAnnotationPresent( WithWriteLock . class )){ lock .writeLock().lock(); try  { //reload the resources into memory return  context.proceed(); }  finally  { lock .writeLock().unlock(); } }    return  context.proceed(); }  catch  (Exception ex) { throw   new  RuntimeException(ex); } } }
Function Objects  + Safe + Boilerplate is compiler enforced + Easily replaces finally & catch blocks  + Easier in Java 8 and Groovy - Verbose - Different
Proxies & Interceptors + Declarative  + Expressive + Easily replaces finally & catch blocks  + Many implementation options - Proxy requires interface - Proxy hard to instantiate - Unproxied class may not be “valid”

More Related Content

What's hot

Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
Rubyc Slides
 

What's hot (20)

What's in Kotlin for us - Alexandre Greschon, MyHeritage
What's in Kotlin for us - Alexandre Greschon, MyHeritageWhat's in Kotlin for us - Alexandre Greschon, MyHeritage
What's in Kotlin for us - Alexandre Greschon, MyHeritage
 
using python module: doctest
using python module: doctestusing python module: doctest
using python module: doctest
 
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09
Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09
 
50 new things we can do with Java 8
50 new things we can do with Java 850 new things we can do with Java 8
50 new things we can do with Java 8
 
JFokus 50 new things with java 8
JFokus 50 new things with java 8JFokus 50 new things with java 8
JFokus 50 new things with java 8
 
Java SE 8 for Java EE developers
Java SE 8 for Java EE developersJava SE 8 for Java EE developers
Java SE 8 for Java EE developers
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
 
The Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsThe Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 Seasons
 
Functional aspects of java 8
Functional aspects of java 8Functional aspects of java 8
Functional aspects of java 8
 
Rxjs marble-testing
Rxjs marble-testingRxjs marble-testing
Rxjs marble-testing
 
Free your lambdas
Free your lambdasFree your lambdas
Free your lambdas
 
Rxjs vienna
Rxjs viennaRxjs vienna
Rxjs vienna
 
Next Level Testing Revisited
Next Level Testing RevisitedNext Level Testing Revisited
Next Level Testing Revisited
 
The redux saga begins
The redux saga beginsThe redux saga begins
The redux saga begins
 
Return Oriented Programming (ROP chaining)
Return Oriented Programming (ROP chaining)Return Oriented Programming (ROP chaining)
Return Oriented Programming (ROP chaining)
 
Using Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side EffectsUsing Redux-Saga for Handling Side Effects
Using Redux-Saga for Handling Side Effects
 
Specs Presentation
Specs PresentationSpecs Presentation
Specs Presentation
 
Testing your javascript code with jasmine
Testing your javascript code with jasmineTesting your javascript code with jasmine
Testing your javascript code with jasmine
 
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, GettLean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
Lean way write asynchronous code with Kotlin’s coroutines - Ronen Sabag, Gett
 
Knowledge is Power: Getting out of trouble by understanding Git - Steve Smith...
Knowledge is Power: Getting out of trouble by understanding Git - Steve Smith...Knowledge is Power: Getting out of trouble by understanding Git - Steve Smith...
Knowledge is Power: Getting out of trouble by understanding Git - Steve Smith...
 

Similar to Java Boilerplate Busters

Javascript Unit Testing
Javascript Unit TestingJavascript Unit Testing
Javascript Unit Testing
Paul Klipp
 
Unit8
Unit8Unit8
Unit8
md751
 
Build Lightweight Web Module
Build Lightweight Web ModuleBuild Lightweight Web Module
Build Lightweight Web Module
Morgan Cheng
 
Embedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for JavaEmbedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for Java
Jevgeni Kabanov
 

Similar to Java Boilerplate Busters (20)

Google guava
Google guavaGoogle guava
Google guava
 
Google collections api an introduction
Google collections api   an introductionGoogle collections api   an introduction
Google collections api an introduction
 
Scala 2 + 2 > 4
Scala 2 + 2 > 4Scala 2 + 2 > 4
Scala 2 + 2 > 4
 
Spring Capitulo 05
Spring Capitulo 05Spring Capitulo 05
Spring Capitulo 05
 
Testing Javascript with Jasmine
Testing Javascript with JasmineTesting Javascript with Jasmine
Testing Javascript with Jasmine
 
Javascript Unit Testing
Javascript Unit TestingJavascript Unit Testing
Javascript Unit Testing
 
My java file
My java fileMy java file
My java file
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Unit8
Unit8Unit8
Unit8
 
Groovy
GroovyGroovy
Groovy
 
Build Lightweight Web Module
Build Lightweight Web ModuleBuild Lightweight Web Module
Build Lightweight Web Module
 
Effective Java - Still Effective After All These Years
Effective Java - Still Effective After All These YearsEffective Java - Still Effective After All These Years
Effective Java - Still Effective After All These Years
 
Prototype js
Prototype jsPrototype js
Prototype js
 
Python - Getting to the Essence - Points.com - Dave Park
Python - Getting to the Essence - Points.com - Dave ParkPython - Getting to the Essence - Points.com - Dave Park
Python - Getting to the Essence - Points.com - Dave Park
 
Exploiting Php With Php
Exploiting Php With PhpExploiting Php With Php
Exploiting Php With Php
 
Linq intro
Linq introLinq intro
Linq intro
 
Javascript Primer
Javascript PrimerJavascript Primer
Javascript Primer
 
Embedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for JavaEmbedded Typesafe Domain Specific Languages for Java
Embedded Typesafe Domain Specific Languages for Java
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
 
JQuery Presentation
JQuery PresentationJQuery Presentation
JQuery Presentation
 

More from HamletDRC (8)

Static Analysis and AST Transformations
Static Analysis and AST TransformationsStatic Analysis and AST Transformations
Static Analysis and AST Transformations
 
Static Analysis in IDEA
Static Analysis in IDEAStatic Analysis in IDEA
Static Analysis in IDEA
 
AST Transformations at JFokus
AST Transformations at JFokusAST Transformations at JFokus
AST Transformations at JFokus
 
10 Years of Groovy
10 Years of Groovy10 Years of Groovy
10 Years of Groovy
 
New Ideas for Old Code - Greach
New Ideas for Old Code - GreachNew Ideas for Old Code - Greach
New Ideas for Old Code - Greach
 
Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)Groovy Ast Transformations (greach)
Groovy Ast Transformations (greach)
 
AST Transformations
AST TransformationsAST Transformations
AST Transformations
 
Ast transformations
Ast transformationsAst transformations
Ast transformations
 

Recently uploaded

Breaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdfBreaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
UK Journal
 
Structuring Teams and Portfolios for Success
Structuring Teams and Portfolios for SuccessStructuring Teams and Portfolios for Success
Structuring Teams and Portfolios for Success
UXDXConf
 

Recently uploaded (20)

Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
Event-Driven Architecture Masterclass: Engineering a Robust, High-performance...
 
Working together SRE & Platform Engineering
Working together SRE & Platform EngineeringWorking together SRE & Platform Engineering
Working together SRE & Platform Engineering
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
 
Extensible Python: Robustness through Addition - PyCon 2024
Extensible Python: Robustness through Addition - PyCon 2024Extensible Python: Robustness through Addition - PyCon 2024
Extensible Python: Robustness through Addition - PyCon 2024
 
Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby Standard library at RubyKaigi 2024
 
Your enemies use GenAI too - staying ahead of fraud with Neo4j
Your enemies use GenAI too - staying ahead of fraud with Neo4jYour enemies use GenAI too - staying ahead of fraud with Neo4j
Your enemies use GenAI too - staying ahead of fraud with Neo4j
 
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdfBreaking Down the Flutterwave Scandal What You Need to Know.pdf
Breaking Down the Flutterwave Scandal What You Need to Know.pdf
 
Structuring Teams and Portfolios for Success
Structuring Teams and Portfolios for SuccessStructuring Teams and Portfolios for Success
Structuring Teams and Portfolios for Success
 
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdfSimplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
Simplified FDO Manufacturing Flow with TPMs _ Liam at Infineon.pdf
 
Event-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream ProcessingEvent-Driven Architecture Masterclass: Challenges in Stream Processing
Event-Driven Architecture Masterclass: Challenges in Stream Processing
 
Overview of Hyperledger Foundation
Overview of Hyperledger FoundationOverview of Hyperledger Foundation
Overview of Hyperledger Foundation
 
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
 
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
Human Expert Website Manual WCAG 2.0 2.1 2.2 Audit - Digital Accessibility Au...
 
WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024WebRTC and SIP not just audio and video @ OpenSIPS 2024
WebRTC and SIP not just audio and video @ OpenSIPS 2024
 
ERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage IntacctERP Contender Series: Acumatica vs. Sage Intacct
ERP Contender Series: Acumatica vs. Sage Intacct
 
Collecting & Temporal Analysis of Behavioral Web Data - Tales From The Inside
Collecting & Temporal Analysis of Behavioral Web Data - Tales From The InsideCollecting & Temporal Analysis of Behavioral Web Data - Tales From The Inside
Collecting & Temporal Analysis of Behavioral Web Data - Tales From The Inside
 
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfIntroduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
 
1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT
1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT
1111 ChatGPT Prompts PDF Free Download - Prompts for ChatGPT
 
Design Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptxDesign Guidelines for Passkeys 2024.pptx
Design Guidelines for Passkeys 2024.pptx
 
Introduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptxIntroduction to FIDO Authentication and Passkeys.pptx
Introduction to FIDO Authentication and Passkeys.pptx
 

Java Boilerplate Busters

  • 1. Hamlet D'Arcy – Canoo Engineering AG @HamletDRC http://hamletdarcy.blogspot.com Java Boilerplate Busters
  • 2.
  • 4. Function Objects / Proxies / Interceptors
  • 8. Boilerplate – noun Code you shouldn't be writing yourself
  • 9.
  • 11. Function Objects / Proxies / Interceptors
  • 14. import static org.apache.commons.lang.StringUtils.*;
  • 15. import static org.apache.commons.lang.StringUtils.*; assert isAlpha ( &quot;abcde&quot; ); assert isNumeric ( &quot;12345&quot; ); assert isAlphanumeric ( &quot;12345abc&quot; );
  • 16. import static org.apache.commons.lang.StringUtils.*; assert isBlank ( &quot;&quot; ); assert isBlank ( null );
  • 17. import static org.apache.commons.lang.StringUtils.*; assert isAllLowerCase ( &quot;abcdef&quot; ); assert isAllUpperCase ( &quot;ABCDEF&quot; );
  • 18. import static org.apache.commons.lang.StringUtils.*; assert &quot;abc&quot; == defaultString ( &quot;abc&quot; ); assert &quot;&quot; == defaultString ( &quot;&quot; ); assert &quot;&quot; == defaultString ( null );
  • 19. import static org.apache.commons.lang.StringUtils.*; assert &quot;abc&quot; .equals( left ( &quot;abcdef&quot; , 3 )); assert &quot;def&quot; .equals( right ( &quot;abcdef&quot; , 3 )); assert null == right ( null , 3 );
  • 20. import static org.apache.commons.lang.StringUtils.*; Object[] array = new Object[]{ 1 , 2 , 3 }; assert &quot;1, 2, 3&quot; .equals( join (array, &quot;, &quot; )); List list = Arrays. asList ( 1 , 2 , 3 ); assert &quot;1, 2, 3&quot; .equals( join (list, &quot;, &quot; ));
  • 22. import org.apache.commons.lang.StringEscapeUtils; String xmlText = &quot; amp;quot; Hello amp;quot; & amp;quot; GoodBye amp;quot; &quot; ; String escapedXml = &quot;&quot;Hello&quot; &amp; &quot; + &quot;&quot;GoodBye&quot;&quot; ; assert escapedXml.equals( StringEscapeUtils. escapeXml (xmlText) ); assert xmlText.equals( StringEscapeUtils. unescapeXml (escapedXml) );
  • 23. import org.apache.commons.lang.StringEscapeUtils; String htmlText = &quot;<body>text</body>&quot; ; String escapedHtml = &quot;&lt;body&gt;&quot; + &quot;text&lt;/body&gt;&quot; ; assert escapedHtml.equals( StringEscapeUtils. escapeHtml (htmlText) ); assert htmlText.equals( StringEscapeUtils. unescapeHtml (escapedHtml) );
  • 24. import org.apache.commons.lang.StringEscapeUtils; String csvText = &quot;red, beans, and rice&quot; ; String escapedCsv = &quot; amp;quot; red, beans, and rice amp;quot; &quot; ; assert escapedCsv.equals( StringEscapeUtils. escapeCsv (csvText) ); assert csvText.equals( StringEscapeUtils. unescapeCsv (escapedCsv) );
  • 25. import static org.apache.commons.lang.ArrayUtils.*;
  • 26. import static org.apache.commons.lang.ArrayUtils.*; int [] evens = new int []{ 2 , 4 , 6 }; int [] odds = new int []{ 1 , 3 , 5 }; assert contains (evens, 2 ); assert contains (odds, 3 );
  • 27. import static org.apache.commons.lang.ArrayUtils.*; int [] evens = new int []{ 2 , 4 , 6 }; int [] odds = new int []{ 1 , 3 , 5 }; assert Arrays. equals ( new int []{ 2 , 4 , 6 , 8 }, add (evens, 8 ) ); assert Arrays. equals ( new int []{ 2 , 4 , 6 , 1 , 3 , 5 }, addAll (evens, odds) );
  • 28. import static org.apache.commons.lang.ArrayUtils.*; int [] evens = new int []{ 2 , 4 , 6 }; int [] odds = new int []{ 1 , 3 , 5 }; assert Arrays. equals ( new int []{ 2 , 6 }, remove (evens, 1 ) ); assert Arrays. equals ( new int []{ 1 , 3 }, remove (odds, 2 ) );
  • 29. import static org.apache.commons.lang.BooleanUtils.*;
  • 30. import static org.apache.commons.lang.BooleanUtils.*; assert toBoolean ( &quot;true&quot; ); assert toBoolean ( &quot;TRUE&quot; ); assert toBoolean ( &quot;tRUe&quot; ); assert toBoolean ( &quot;on&quot; ); assert toBoolean ( &quot;ON&quot; ); assert toBoolean ( &quot;yes&quot; ); assert toBoolean ( &quot;YES&quot; );
  • 32. import org.apache.commons.lang.builder.ToStringBuilder; public class Person { String name ; Date timestamp = new Date(); @Override public String toString() { return new ToStringBuilder( this ) .append( &quot;name&quot; , name ) .append( &quot;timestamp&quot; , timestamp ) .toString(); } }
  • 34. import org.apache.commons.lang.builder.EqualsBuilder; public class Person { String name ; Date timestamp = new Date(); @Override public boolean equals(Object obj) { if (obj == null ) { return false ; } if (obj == this ) { return true ; } if (obj.getClass() != getClass()) { return false ; } Person rhs = (Person) obj; return new EqualsBuilder() .append( name , rhs. name ) .append( timestamp , rhs. timestamp ) .isEquals(); } }
  • 36. import org.apache.commons.lang.builder.HashCodeBuilder; public class Person { String name ; Date timestamp = new Date(); @Override public int hashCode() { return new HashCodeBuilder() .append( name ) .append( timestamp ) .toHashCode(); } }
  • 38. import org.apache.commons.lang.builder. CompareToBuilder ; public class Person implements Comparable<Person> { String name ; Date timestamp = new Date(); public int compareTo(Person other) { return new CompareToBuilder() .append( this . name , other. name ) .toComparison(); } }
  • 39.
  • 41.
  • 43. new HashMap<T, Set<U>>
  • 45. import com.google.common.collect.Multimap; Multimap<String, String> multiMap = HashMultimap. create (); multiMap.put( &quot;Canoo&quot; , &quot;Hamlet&quot; ); multiMap.put( &quot;Canoo&quot; , &quot;Dierk&quot; ); multiMap.put( &quot;Canoo&quot; , &quot;Andres&quot; ); multiMap.put( &quot;EngineYard&quot; , &quot;Charles&quot; ); multiMap.put( &quot;EngineYard&quot; , &quot;Thomas&quot; ); multiMap.put( &quot;EngineYard&quot; , &quot;Nick&quot; );
  • 46. import com.google.common.collect.Multimap; assert multiMap.containsKey( &quot;Canoo&quot; ); assert multiMap.containsKey( &quot;EngineYard&quot; ); assert multiMap.containsValue( &quot;Hamlet&quot; ); assert multiMap.containsValue( &quot;Charles&quot; );
  • 47. import com.google.common.collect.Multimap; Collection<String> canooies = multiMap.get( &quot;Canoo&quot; ); Collection<String> c = Lists. newArrayList ( &quot;Dierk&quot; , &quot;Andres&quot; , &quot;Hamlet&quot; ); assert canooies.containsAll(c);
  • 49. import com.google.common.collect.BiMap; BiMap<String, String> biMap = HashBiMap. create (); biMap.put( &quot;Switzerland&quot; , &quot;die Schweiz&quot; ); biMap.put( &quot;Poland&quot; , &quot;Polska&quot; ); biMap.put( &quot;Austria&quot; , &quot;Österreich&quot; ); assert &quot;Polska&quot; == biMap.get( &quot;Poland&quot; ); assert &quot;Switzerland&quot; == biMap.inverse() .get( &quot;die Schweiz&quot; );
  • 50. new HashMap<T, Map<U, V>>
  • 52. import com.google.common.collect.Table; Table<Integer, Integer, String> table = HashBasedTable. create (); table.put( 1 , 1 , &quot;Hamlet&quot; ); table.put( 1 , 2 , &quot;Dierk&quot; ); table.put( 2 , 1 , &quot;Andres&quot; ); table.put( 2 , 2 , &quot;Matthius&quot; );
  • 53. import com.google.common.collect.Table; assert table.contains( 1 , 1 ); assert table.containsRow( 1 ); assert table.containsColumn( 2 ); assert !table.contains( 3 , 1 ); assert !table.containsRow( 3 ); assert !table.containsColumn( 3 ); assert &quot;Hamlet&quot; == table.get( 1 , 1 ); assert table.containsValue( &quot;Hamlet&quot; );
  • 55. import com.google.common.base.Joiner; Set<Integer> set = Sets. newHashSet ( 1 , 2 , 3 ); assert &quot;1, 2, 3&quot; .equals(Joiner. on ( &quot;, &quot; ).join(set));
  • 57. import com.google.common.base.Splitter; String string = &quot;1, 2, , 3&quot; ; Iterable<String> i = Splitter. on ( &quot;,&quot; ) .omitEmptyStrings() .trimResults() .split(string);
  • 58. import static com.google.common.collect.Iterables.*; import static com.google.common.collect.Lists.*; Iterable<Integer> setAsInts = transform (i, new Function<String, Integer>() { @Override public Integer apply(String input) { return Integer. valueOf (input); } }); assert newArrayList ( 1 , 2 , 3 ) .containsAll( newArrayList (setAsInts));
  • 59. import static com.google.common.base.Strings.*;
  • 60. import static com.google.common.base.Strings.*; assert emptyToNull ( &quot;&quot; ) == null ; assert &quot;&quot; .equals( nullToEmpty ( null )); assert isNullOrEmpty ( &quot;&quot; ); assert &quot;abcabcabc&quot; .equals( repeat ( &quot;abc&quot; , 3 ));
  • 61. import static com.google.common.base.Preconditions.*;
  • 62. import static com.google.common.base.Preconditions.*; int userID = 1 ; String userName = &quot;some name&quot; ; checkArgument (userID > 0 , &quot;userid is negative: %s&quot; , userID); checkNotNull (userName, &quot;user %s missing name&quot; , userID); checkState (userName.length() > 0 , &quot;user %s missing name&quot; , userID);
  • 63. import static com.google.common.base.Objects.*;
  • 64. import static com.google.common.base.Objects.*; class Person { String name ; Date timestamp = new Date(); @Override public String toString() { return toStringHelper ( this ) .add( &quot;name&quot; , name ) .add( &quot;timestamp&quot; , timestamp ).toString(); } }
  • 65. import static com.google.common.base.Equivalences.*;
  • 66. import static com.google.common.base.Equivalences.*; class Person implements Comparable<Person> { String name ; Date timestamp = new Date(); @Override public boolean equals(Object obj) { if (obj == null ) { return false ; } if (obj == this ) { return true ; } if (obj.getClass() != getClass()) { return false ; } Person rhs = (Person) obj; return equals ().equivalent( name , rhs. name ) && equals ().equivalent( timestamp , rhs. timestamp ); } @Override public int hashCode() { return hashCode ( name , timestamp ); } }
  • 67. import static com.google.common.collect.ComparisonChain.*;
  • 68. import static com.google.common.collect.ComparisonChain.*; class Person implements Comparable<Person> { String name ; Date timestamp = new Date(); public int compareTo(Person other) { return start () .compare( name , other. name ) .compare( timestamp , other. timestamp ) .result(); } }
  • 70. import com.google.common.base.Throwables; Exception ex = new Exception(); Throwables. propagateIfPossible (ex); Throwables. propagate (ex); // throws Exception Throwables. throwCause (ex, false );
  • 72. import com.google.common.base.Function; Person alice = new Person( &quot;Alice&quot; ); Person bob = new Person( &quot;Bob&quot; ); Person carol = new Person( &quot;Carol&quot; ); List<Person> people = newArrayList (alice, bob, carol);
  • 73. import com.google.common.base.Function; Function<Person, String> getName = new Function<Person, String>() { public String apply(Person p) { return p.getName(); } }; assert &quot;Alice&quot; == getName.apply(alice); Collection<String> names = Collections2 . transform (people, getName); assert names.containsAll( newArrayList ( &quot;Alice&quot; , &quot;Bob&quot; , &quot;Carol&quot; ) );
  • 75. import com.google.common.base.Predicate; Predicate<Person> predicate = new Predicate<Person>() { public boolean apply(Person input) { return input.getName().contains( &quot;o&quot; ); } }; Iterable<Person> filteredList = Iterables . filter ( people, predicate); assert Iterables. contains (filteredList, bob); assert Iterables. contains (filteredList, carol); assert !Iterables. contains (filteredList, alice);
  • 76.
  • 80.
  • 82. Function Objects / Proxies / Interceptors
  • 85. “Traditional API” Order order = new Order(); order.setItemName( &quot;lattes&quot; ); order.setQuantity( 2 ); order.pay(Currency. getInstance ( &quot;USD&quot; ));
  • 86. “Modern API” new FluentOrder() .withItem( &quot;lattes&quot; ) .withQuantity( 2 ) .pay(Currency. getInstance ( &quot;USD&quot; ));
  • 87. “Modern API” class FluentOrder { private String item ; private int quantity ; public FluentOrder withItem(String item) { this . item = item; return this ; } public FluentOrder withQuantity( int quantity) { this . quantity = quantity; return this ; } boolean pay(Currency currency) { // pay order return true ; } }
  • 88. class OrderBuilder { QuantityHolder withItem(String item) { return new QuantityHolder(item); } } class QuantityHolder { private final String item ; private QuantityHolder(String item) { this . item = item; } OrderFiller withQuantity( int quantity) { return new OrderFiller( item , quantity); } } class OrderFiller { private final String item ; private final int quantity ; private OrderFiller(String item, int quantity) { this . item = item; this . quantity = quantity; } boolean pay(Currency currency) { /* pay order... */ return true ; } }
  • 89. ... another type-safe version new Order( OrderBuilder. newInstance () .initItemName( &quot;latte&quot; ) .initQuantity( 10 ) .withCurrency(Currency. getInstance ( &quot;CHF&quot; )) ).pay(); // forgetting required args is a compile error new Order( OrderBuilder.newInstance() .initItemName( &quot;latte&quot; ) .withCurrency(Currency.getInstance( &quot;CHF&quot; ) ));
  • 90. public class OrderBuilder<NAME, QUANTITY> { // required fields private String itemName ; private int quantity ; private Currency currency ; // optional field public static OrderBuilder<NOK, NOK> newInstance() { return new OrderBuilder<>(); } public OrderBuilder(String itemName, int quantity, Currency currency) { this . itemName = itemName; this . quantity = quantity; this . currency = currency; } public OrderBuilder<OK, QUANTITY> initItemName(String itemName) { this . itemName = itemName; return new OrderBuilder<>(name, quantity , currency ); } public OrderBuilder<NAME, OK> initQuantity( int quantity) { this . quantity = quantity; return new OrderBuilder<>( itemName , quantity, currency ); } public OrderBuilder<NAME, QUANTITY> withCurrency(Currency currency) { this . currency = currency; return this ; } ... // getters & default ctor omitted }
  • 91. ... and it's just plain old Groovy new Order( itemName: 'lattes' , quantity: 2 ).pay(Currency.getInstance( 'USD' )) new Order().with { itemName = 'lattes' quantity = 2 pay(Currency. getInstance ( 'USD' )) }
  • 92. Builders & Fluent API + More expressive + Type-safer + Easier to use - Harder to write - Harder to learn? - Some reformatting tools choke
  • 93.
  • 95. Function Objects / Proxies / Interceptors
  • 98. public class ResourceProvider { private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Map<String, String> data = new ConcurrentHashMap(); public String getResource(String key) throws Exception { lock .readLock().lock(); try { return data .get(key); } finally { lock .readLock().unlock(); } } public void refresh() throws Exception { lock .writeLock().lock(); try { // reload settings... } finally { lock .writeLock().unlock(); } } } “Traditional API”
  • 99. public class ResourceController { private final ReadWriteLock lock = new ReentrantReadWriteLock(); public <T> T withReadLock(Callable<T> block) throws Exception { lock .readLock().lock(); try { return block.call(); } finally { lock .readLock().unlock(); } } public <T> T withWriteLock(Callable<T> block) throws Exception { lock .writeLock().lock(); try { return block.call(); } finally { lock .writeLock().unlock(); } } } “Modern API” con't
  • 100. public class ResourceProvider { private final ResourceController controller = new ResourceController(); private final Map<String, String> data = new ConcurrentHashMap(); public String getResource( final String key) throws Exception { return controller .withReadLock( new Callable<String>() { public String call() throws Exception { return data .get( key ); } }); } public void refresh() throws Exception { controller .withWriteLock( new Callable<Void>() { public Void call() throws Exception { // reload settings return null ; } }); } } “Modern API” -- Function Objects
  • 101. class ResourceProvider { private final controller = new ResourceController() private final data = [:] as ConcurrentHashMap String getResource(String key) { controller .withReadLock({ data .get( key ) } as Callable) } void refresh() { controller .withWriteLock( { /* reload settings */ } as Callable) } } “Modern API” -- Groovy Function Objects
  • 102. public class DefaultResourceProvider implements ResourceProvider { private final Map<String, String> data = new ConcurrentHashMap(); @WithReadLock public String getResource(String key) { return data .get(key); } @WithWriteLock public void refresh() { System. out .println( &quot;Reloading the settings...&quot; ); } } “Modern API” -- Proxy Class
  • 103. public class ResourceController implements InvocationHandler { private final Object target ; private final ReadWriteLock lock = new ReentrantReadWriteLock(); ResourceController(Object target) { this . target = target; } public Object invoke (Object proxy, Method method, Object[] args) { try { Method targetMethod = target .getClass().getMethod( method.getName(), method.getParameterTypes()); if (targetMethod.isAnnotationPresent( WithReadLock . class )) { lock .readLock().lock(); try { return targetMethod.invoke( target , args); } finally { lock .readLock().unlock(); } } else if (targetMethod.isAnnotationPresent( WithWriteLock . class )){ lock .writeLock().lock(); try { return targetMethod.invoke( target , args); } finally { lock .writeLock().unlock(); } } else { return targetMethod.invoke( target , args); } } catch (Exception ex) { throw new RuntimeException(ex); } } }
  • 104. “Modern API” -- Proxy Class con't InvocationHandler handler = new ResourceController( new DefaultResourceProvider() ); ResourceProvider p = (ResourceProvider) Proxy. newProxyInstance ( DefaultResourceProvider. class .getClassLoader(), new Class[]{ResourceProvider. class }, hand ler); p.refresh(); p.getResource( &quot;property&quot; );
  • 105. “Modern API” -- Proxy Class con't class ResourceProvider { private final Map data = new ConcurrentHashMap(); @WithReadLock String getResource(String key) { return (String) data .get(key); } @WithWriteLock void refresh() { // Reload settings... } }
  • 106. public class WithLockInterceptor { // This is shared!!! private final ReadWriteLock lock = new ReentrantReadWriteLock(); @AroundInvoke public Object enforceLock(InvocationContext context) throws Exception{ try { Method targetMethod = context.getMethod(); if (targetMethod.isAnnotationPresent( WithReadLock . class )) { lock .readLock().lock(); try { return context.proceed(); } finally { lock .readLock().unlock(); } } else if (targetMethod.isAnnotationPresent( WithWriteLock . class )){ lock .writeLock().lock(); try { //reload the resources into memory return context.proceed(); } finally { lock .writeLock().unlock(); } } return context.proceed(); } catch (Exception ex) { throw new RuntimeException(ex); } } }
  • 107. Function Objects + Safe + Boilerplate is compiler enforced + Easily replaces finally & catch blocks + Easier in Java 8 and Groovy - Verbose - Different
  • 108. Proxies & Interceptors + Declarative + Expressive + Easily replaces finally & catch blocks + Many implementation options - Proxy requires interface - Proxy hard to instantiate - Unproxied class may not be “valid”
  • 109.
  • 111. Function Objects / Proxies / Interceptors
  • 112. Java 7
  • 114. “Traditional Error Handling” try { doSomething(); } catch (UnsupportedOperationException e) { handleError(e); } catch (IllegalStateException e) { handleError(e); } catch (IllegalArgumentException e) { handleError(e); }
  • 115. “Modern Error Handling” try { doSomething(); } catch (UnsupportedOperationException | IllegalStateException | IllegalArgumentException e) { handleError(e); }
  • 116. “Traditional Resource Management” FileReader reader = new FileReader(path); try { return reader.read(); } finally { reader.close(); }
  • 117. “Modern Resource Management” try (FileReader reader = new FileReader(path)) { return reader.read(); }
  • 118. “Modern Resource Management” class MyResource implements AutoCloseable { String getResource() { return &quot;some resource&quot; ; } @Override public void close() throws Exception { // closing } } try (MyResource resource = new MyResource()) { return resource.getResource(); }
  • 119. Strings in Switch class Calculator { Number apply( int left, String operator, int right) { switch (operator) { case &quot;plus&quot; : return left + right; case &quot;minus&quot; : return left - right; case &quot;times&quot; : return left * right; case &quot;divided by&quot; : return left / right; default : throw new Exception(operator); } } } Calculator calculator = new Calculator(); assert calculator.apply( 1 , &quot;plus&quot; , 2 ).equals( 3 ); assert calculator.apply( 5 , &quot;times&quot; , 2 ).equals( 10 ); assert calculator.apply( 5 , &quot;minus&quot; , 2 ).equals( 3 );
  • 120. Regex in Groovy Switch Number apply( int left, String operator, int right) { switch (operator) { c ase ~/ (i)plus/ : return left + right case ~/ (i)minus/ : return left - right case ~/ (i)times/ : return left * right case ~/ (i)divided by/ : return left / right default : throw new Exception(operator) } } assert apply( 1 , &quot;plus&quot; , 2 ) == 3 assert apply( 5 , &quot;TIMES&quot; , 2 ) == 10 assert apply( 5 , &quot;MiNuS&quot; , 2 ) == 3
  • 121. Less Generic Cruft Map<Integer, String> map = new HashMap<>();
  • 122. Java 7 Features + Soon to be widely used + Terser code - No Lambdas - Not widely used
  • 123.
  • 125. Function Objects / Proxies / Interceptors
  • 126. Java 7
  • 128. “Traditional Java Bean” public class Person { private String fName ; private String lName ; public String getFirstName() { return fName ; } public void setFirstName(String f) { this . fName = f; } public String getLastName() { return lName ; } public void setLastName(String l) { this . lName = l; } @Override public boolean equals(Object o) { ... } @Override public int hashCode() { ... } }
  • 129. “Modern Java Bean” -- Lombok @EqualsAndHashCode public class Person { @Setter @Getter private String firstName ; @Setter @Getter private String lastName ; }
  • 130. “Modern Java Bean” -- Lombok @Data public class Person { private String firstName ; private String lastName ; }
  • 131.
  • 132. Lombok + Generates boilerplate into Class file + Java-only, IDE support + delombok option - IDEA Plugin is poor - Hinders some Eclipse features - Not all features are loved by all
  • 133. “Modern Java Bean” -- Groovy @EqualsAndHashCode public class Person { String firstName String lastName }
  • 134.
  • 135.
  • 136. Groovy + Generates boilerplate into Class file + Great Java interop & IDE support + Gateway to many other features - Requires a new language ? Performs worse than Java ? Hinders some IDE features
  • 137.
  • 139. Function Objects / Proxies / Interceptors
  • 140. Java 7
  • 142.

Editor's Notes

  1. // Propagates throwable as-is if it is an instance of RuntimeException or Error, or else as a last resort, wraps it in a RuntimeException then propagates. Throwables.propagate(ex); // Propagates throwable exactly as-is, if and only if it is an instance of RuntimeException or Error. Throwables.propagateIfPossible(ex); // Rethrows the cause exception of a given throwable, discarding the original throwable. if the cause is null, then throws the ex Throwables.throwCause(ex, false);