This isn't a talk about microservices, NO-SQL, Container solutions or hip new frameworks. This talk will show some of the standard Java APIs that are part of Java since version 5, 6, 7 or 8. All this features are very helpful to create maintainable and future-proof applications, regardless of whether JavaEE, Spring, JavaFX or any other framework is used. The talk will give an overview of some important standard concepts and APIs of Java like annotations, SPI or how to handle null values. Based on an overview of this topics and some samples the talk will answer questions like:
- How can I create my own annotations?
- How can I create a plugin structure without using frameworks like OSGI?
- What's the best way to handle NullPointerExceptions?
2. by
⢠Lead of JUG Dortmund
⢠JSR EG member
⢠Java Developer @ Canoo Engineering AG
⢠JavaOne Rockstar, Java Champion
⢠I ⤠Star Wars
www.guigarage.com@hendrikEbbers
Hendrik Ebbers
8. you should knowJava byAPIs
How to handle null
⢠All of us have seen more than enough
NullPointerExceptions
⢠Java contains some APIs to tame the
beast
9. you should knowJava byAPIs
How to handle null
⢠Before we try to avoid NPEs we should
have a look how to handle null the
right way
⢠Java has null for a reason. Just use it.
10. you should knowJava byAPIs
How to handle null
public long getPeriode(final Date start, final Date end) {
return end.getTime() - start.getTime();
}
⢠This method is a typically bad
example for NPEs / null values and
how to deal with them
⢠Do you have an idea why? ?
11. you should knowJava byAPIs
How to handle null
public long getPeriode(final Date start, final Date end) {
return end.getTime() - start.getTime();
}
Exception in thread "main" java.lang.NullPointerException
at com.guigarage.sample.Example.getPeriode(Example.java:11)
which date is null?
12. you should knowJava byAPIs
How to handle null
public Locale(String language, String country, String variant) {â¨
if (language== null || country == null || variant == null) {â¨
throw new NullPointerException();â¨
}â¨
. . .â¨
}
JDK code . . .
13. you should knowJava byAPIs
How to handle null/**
* . . .
* @throws NullPointerException if start or end is null
*/
public long getPeriode(final Date start, final Date end) {
if(start == null) {
throw new NullPointerException("start must not be null");
}
if(end == null) {
throw new NullPointerException("end must not be null");
}
return end.getTime() - start.getTime();
}
14. you should knowJava byAPIs
How to handle null
/**
* . . .
* @throws NullPointerException if start or end is null
*/
public long getPeriode(final Date start, final Date end) {
Objects.requireNonNull(start, "start must not be null");
Objects.requireNonNull(end, "end must not be null");
return end.getTime() - start.getTime();
}
15. you should knowJava byAPIs
How to handle null
⢠You should use it in constructors, too
public class Periode {
private final Date start;
private final Date end;
public Periode(final Date start, final Date end) {
start = Objects.requireNonNull(start, "start must not be null");
end = Objects.requireNonNull(end, "end must not be null");
}
}
16. you should knowJava byAPIs
How to handle null
⢠Make your own util methods
public class MyUtils {
public static <T> T requireNonNull(final T value, final String name) {
return Objects.requireNonNull(value, name + " must not be null");
}
}
17. you should knowJava byAPIs
How to handle null
⢠Sometime you don't want to throw a
NPE
⢠In that case the use of default values is
an option
18. you should knowJava byAPIs
How to handle null
public boolean containsA(final String input) {
String currentInput = input;
if(currentInput == null) {
currentInput = "";
}
return currentInput.contains("A");
}
19. you should knowJava byAPIs
How to handle null
⢠Sometime you don't want to throw a NPE
⢠In that case the use of default values is
an option
⢠Java 8 provides the Optional class to
simplify this
20. you should knowJava byAPIs
How to handle null
public boolean containsA(final String input) {
return Optional.ofNullable(input).orElse("").contains("A");
}
create a new
Optional that wraps
a value
returns the internal value
or the given value if the
internal value is null
21. you should knowJava byAPIs
How to handle null
⢠You can use Optional internally in your
method logic
⢠You can use Optional as a return value
of a method
⢠You should not use Optional as a param
22. you should knowJava byAPIs
How to handle null
public Optional<Entity> findByName(final String name) {
Objects.requireNonNull(name, "name must not be null");
String query = "Select entity where name = " + name;
return Optional.ofNullable(database.executeQuery(query));
}
⢠This methods can be used as a starting
point for a fluent API
findByName("Java").ifPresent(entity -> table.add(entity));
23. you should knowJava byAPIs
How to handle null
⢠Another example that provides the id of
an selected element
maybe nothing is
selected
list shows "Movie"
objects that provide
title and id
24. you should knowJava byAPIs
How to handle null
final Integer selectedId = Optional.ofNullable(list.getSelected())
.map(i -> i.getId())
.orElse(null);
⢠Another example that provides the id of
an selected element
25. you should knowJava byAPIs
How to handle null
⢠Since autoboxing is a cool feature in
general it sucks if you run in NPEs
⢠Using Optional can help you to avoid
this exceptions
26. you should knowJava byAPIs
⢠Let's have a look at a bean -> entity
converterâ¨
â¨
â¨
â¨
What could possibly go wrong
How to handle null
public class MyBean {
public Integer getCount();
}
public class MyEntity {
public void setCount(int c);
}
?
27. you should knowJava byAPIs
public class MyBean {
public Integer getCount();
}
How to handle null
hint : this could return null
public class MyEntity {
public void setCount(int c);
}
28. you should knowJava byAPIs
public MyEntity convert(final MyBean bean) {
Objects.requireNonNull(bean, "bean must not be null");
MyEntity entity = new MyEntity();
entity.setCount(bean.getCount());
return entity;
}
How to handle null
might throw a NPE since we can't
pass null as value for a primitive
29. you should knowJava byAPIs
public MyEntity convert(final MyBean bean) {
Objects.requireNonNull(bean, "bean must not be null");
MyEntity entity = new MyEntity();
entity.setCount(Optional.ofNullable(bean.getCount()).orElse(0));
return entity;
}
How to handle null
default value
31. you should knowJava byAPIs
Service Provider Interface
⢠Based on Interfaces it's quite easy to
define a general service and several
implementations in Java
32. you should knowJava byAPIs
Service Provider Interface
public interface MathOperation {
String getSign();
double calc(double valA, double valB);
}
33. you should knowJava byAPIs
Service Provider Interface
⢠We can provide several
implementations of math operations
⢠AddOperation
⢠SubstractOperation
34. you should knowJava byAPIs
Service Provider Interface
public class Multiply implements MathOperation {
public String getSign() { return "*";}
double calc(double valA, double valB){
return valA * valB;
}
}
35. you should knowJava byAPIs
Service Provider Interface
⢠Instances of the implementations can
be accessed by using the general
interface
⢠All instances can simply be stored in a
collection
36. you should knowJava byAPIs
Service Provider Interface
List<MathOperation> operations = new ArrayList<>();
operations.add(new MultipyOperation());
operations.add(new AddOperation());
operations.add(new DivideOperation());
operations.add(new SubstractOperation());
operations.forEach(o -> {
System.out.println("Supported Operation: " + o.getSign());
});
37. you should knowJava byAPIs
Service Provider Interface
⢠With Java 8 default methods we can
even define default logic for some
parts of the service
⢠Use defaults only if it really makes
sense!
38. you should knowJava byAPIs
Service Provider Interface
public interface MathOperation {
String getSign();
double calc(double valA, double valB);
default String getHelp() {
return "No help text for sign" + getSign();
}
}
39. you should knowJava byAPIs
Service Provider Interface
⢠Let's think about a bigger application
⢠Often based on several modules /
jars
⢠Several jars contains several service
implementations
40. you should knowJava byAPIs
Service Provider Interface
Application
Basic Math
Module
Math Def
Module
Special Math
Module
contains the interface
41. you should knowJava byAPIs
Service Provider Interface
Application
Basic Math
Module
Math Def
Module
Special Math
Module
contains the interface
contains implementations
contains implementations
42. you should knowJava byAPIs
Service Provider Interface
Application
Basic Math
Module
Math Def
Module
Special Math
Module
contains the interface
contains implementations
contains implementations
use implementations
43. you should knowJava byAPIs
Service Provider Interface
Application
Basic Math
Module
Math Def
Module
Special Math
Module
depends on
depends on
depends ondepends on
44. you should knowJava byAPIs
Service Provider Interface
Application
Basic Math
Module
Math Def
Module
Special Math
Module
One Million Dollar
Question
45. you should knowJava byAPIs
Service Provider Interface
⢠Where should we define the following
method?
public List<MathOperation> getAllImplInClasspath();
?
46. you should knowJava byAPIs
Service Provider Interface
⢠We can't define it in the "Math Def
Module" since this module has no
dependency to any implementation
⢠Method would returnâ¨
an empty list
47. you should knowJava byAPIs
Service Provider Interface
⢠We can't define it in the "Basic Math" or
the "Special Math" since this modules
don't know all implementations.
⢠Method would notâ¨
return all â¨
implementations
48. you should knowJava byAPIs
Service Provider Interface
⢠Only the "Application" module knows all
implementations since it's the only
module that depends on all other
modules
49. you should knowJava byAPIs
Service Provider Interface
Basic Math
Module
Math Def
Module
Special Math
Module
Algebra Math
Module
Geometry
Math Module
⢠Let's add some complexity
50. you should knowJava byAPIs
Service Provider Interface
Customer A
Application
Basic Math
Module
Math Def
Module
Special Math
Module
Algebra Math
Module
Geometry
Math Module
Customer B
Application
Customer C
Application
51. you should knowJava byAPIs
Service Provider Interface
⢠We don't want to implement theâ¨
â¨
for each application
⢠We need something new that loads all
implementations dynamically
public List<MathOperation> getAllImplInClasspath();
52. you should knowJava byAPIs
Service Provider Interface
⢠Service Provider Interface (SPI)
provides a simple API to solve this issue
⢠Could be used to create a minimal but
powerful Plug In API
53. you should knowJava byAPIs
Service Provider Interface
⢠Start by creating an interface
public interface MathOperation {
String getSign();
double calc(double valA, double valB);
}
we already have it
54. you should knowJava byAPIs
Service Provider Interface
⢠Each module that provides
implementations of the interface most
provide a service file
⢠File must be located under META-INF/
services/
55. you should knowJava byAPIs
Service Provider Interface
⢠Name of the file must be equals to the
interface name
META-INF/services/com.canoo.math.MathOperation
file name
56. you should knowJava byAPIs
Service Provider Interface
⢠File simply contains names of all
implementations
com.canoo.basic.AddOperationâ¨
com.canoo.basic.MinusOperation
define one
implementation per line
57. you should knowJava byAPIs
Service Provider Interface
⢠The Service Provider Interface (SPI) will
automatically find all implementations
at runtime
⢠Instances of the classes will
automatically be created
⢠Default constructor is needed
58. you should knowJava byAPIs
Service Provider Interface
⢠You can simply iterate over all
implementations
Iterator<MathOperation> iterator = ServiceLoader.load(MathOperation.class).iterator();
â¨
while (iterator.hasNext()) {â¨
MathOperation operation = iterator.next();â¨
}
59. you should knowJava byAPIs
Service Provider Interface
⢠At the end we can implement theâ¨
â¨
method simple in the "Math Def Module"
⢠The service provider â¨
will automatically findâ¨
all implementations
public List<MathOperation> getAllImplInClasspath();
61. you should knowJava byAPIs
Annotations
⢠Let's start with a quiz :)
⢠How many Java annotations are used
in the code?
?
62. you should knowJava byAPIs
Annotations/**â¨
* A helper classâ¨
* @see Class#getModifiers()â¨
*â¨
* @author Hendrik Ebbers
* @deprecatedâ¨
*/
@Deprectaded
public class Helper {
@Important
private Logger logger = new Logger();
/**â¨
* Return {@code true} if the integer argument includes the {@code private} modifier, {@code false} otherwise.â¨
*â¨
* @param mod a set of modifiersâ¨
* @return {@code true} if {@code mod} includes the {@code private} modifier; {@code false} otherwise.â¨
*/
@Static(false)â¨
public static boolean isPrivate(@Param int mod) {â¨
return (mod & 0x00000002) != 0;â¨
}
}
63. you should knowJava byAPIs
/**â¨
* A helper classâ¨
* @see Class#getModifiers()â¨
*â¨
* @author Hendrik Ebbers
* @deprecatedâ¨
*/
@Deprectaded
public class Helper {
@Important
private Logger logger = new Logger();
/**â¨
* Return {@code true} if the integer argument includes the {@code private} modifier, {@code false} otherwise.â¨
*â¨
* @param mod a set of modifiersâ¨
* @return {@code true} if {@code mod} includes the {@code private} modifier; {@code false} otherwise.â¨
*/
@Static(false)â¨
public static boolean isPrivate(@Param int mod) {â¨
return (mod & 0x00000002) != 0;â¨
}
}
Annotations
64. you should knowJava byAPIs
/**â¨
* A helper classâ¨
* @see Class#getModifiers()â¨
*â¨
* @author Hendrik Ebbers
* @deprecatedâ¨
*/
@Deprectaded
public class Helper {
@Important
private Logger logger = new Logger();
/**â¨
* Return {@code true} if the integer argument includes the {@code private} modifier, {@code false} otherwise.â¨
*â¨
* @param mod a set of modifiersâ¨
* @return {@code true} if {@code mod} includes the {@code private} modifier; {@code false} otherwise.â¨
*/
@Static(false)â¨
public static boolean isPrivate(@Param int mod) {â¨
return (mod & 0x00000002) != 0;â¨
}
}
Annotations
@Deprectated
annotation is defined
in the JRE
65. you should knowJava byAPIs
/**â¨
* A helper classâ¨
* @see Class#getModifiers()â¨
*â¨
* @author Hendrik Ebbers
* @deprecatedâ¨
*/
@Deprectaded
public class Helper {
@Important
private Logger logger = new Logger();
/**â¨
* Return {@code true} if the integer argument includes the {@code private} modifier, {@code false} otherwise.â¨
*â¨
* @param mod a set of modifiersâ¨
* @return {@code true} if {@code mod} includes the {@code private} modifier; {@code false} otherwise.â¨
*/
@Static(false)â¨
public static boolean isPrivate(@Param int mod) {â¨
return (mod & 0x00000002) != 0;â¨
}
}
Annotations
the @Important annotation is not defined in
the JRE but it's easy to create your own
custom annotations (like @Autowired in
Spring)
66. you should knowJava byAPIs
/**â¨
* A helper classâ¨
* @see Class#getModifiers()â¨
*â¨
* @author Hendrik Ebbers
* @deprecatedâ¨
*/
@Deprectaded
public class Helper {
@Important
private Logger logger = new Logger();
/**â¨
* Return {@code true} if the integer argument includes the {@code private} modifier, {@code false} otherwise.â¨
*â¨
* @param mod a set of modifiersâ¨
* @return {@code true} if {@code mod} includes the {@code private} modifier; {@code false} otherwise.â¨
*/
@Static(false)â¨
public static boolean isPrivate(@Param int mod) {â¨
return (mod & 0x00000002) != 0;â¨
}
}
Annotations
the @Static annotation is configured
by a boolean parameter
67. you should knowJava byAPIs
/**â¨
* A helper classâ¨
* @see Class#getModifiers()â¨
*â¨
* @author Hendrik Ebbers
* @deprecatedâ¨
*/
@Deprectaded
public class Helper {
@Important
private Logger logger = new Logger();
/**â¨
* Return {@code true} if the integer argument includes the {@code private} modifier, {@code false} otherwise.â¨
*â¨
* @param mod a set of modifiersâ¨
* @return {@code true} if {@code mod} includes the {@code private} modifier; {@code false} otherwise.â¨
*/
@Static(false)â¨
public static boolean isPrivate(@Param int mod) {â¨
return (mod & 0x00000002) != 0;â¨
}
}
Annotations
the @Param annotation is another
custom annotation that is used to
annotate a method param
68. you should knowJava byAPIs
Annotations
⢠Annotations can be used to add metadata to
the code
⢠Annotations can be added to different points
of the code
⢠Annotation can be parametrable
⢠Custom annotations can be defined
70. you should knowJava byAPIs
Annotations
public @interface MyAnnotation {
}
access modifier name
annotation keyword
71. you should knowJava byAPIs
Annotations
@Documented
@Retention(RUNTIME)
@Target(METHOD)
public @interface MyAnnotation {
}
72. you should knowJava byAPIs
Annotations
@Documented
@Retention(RUNTIME)
@Target(METHOD)
public @interface MyAnnotation {
}
?
73. you should knowJava byAPIs
Annotations
@Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Documented {
}
74. you should knowJava byAPIs
Annotations
⢠If an annotation is annotated with
@Documented the usage of the
annotation will be shown in JavaDoc
⢠The usage of @Documented has no
effect at runtime
75. you should knowJava byAPIs
Annotations
⢠The @Target annotation defines where
an annotation can be used.
⢠The enum ElementType defines all
supported types
76. you should knowJava byAPIs
Annotations
⢠TYPE
⢠FIELD
⢠METHOD
⢠PARAMETER
⢠CONSTRUCTOR
⢠LOCAL_VARIABLE
⢠ANNOTATION_TYPE
⢠PACKAGE
⢠TYPE_PARAMETER
⢠TYPE_USE[ ]
77. you should knowJava byAPIs
Annotations
@Target(METHOD)
public @interface MyAnnotation {
}
@MyAnnotation
public void sqrt(int value) {
return 1;
}
78. you should knowJava byAPIs
Annotations
@Target(METHOD)
public @interface MyAnnotation {
}
public void sqrt(@MyAnnotation int value) {
return 1;
}
79. you should knowJava byAPIs
Annotations
@Target(PARAMETER)
public @interface MyAnnotation {
}
public void sqrt(@MyAnnotation int value) {
return 1;
}
80. you should knowJava byAPIs
Annotations
@Target({PARAMETER, METHOD})
public @interface MyAnnotation {
}
@MyAnnotation
public void sqrt(@MyAnnotation int value) {
return 1;
}
81. you should knowJava byAPIs
Annotations
⢠The @Retention annotation defines
how long an annotation will be
retained.
⢠The enum RetentionPolicy defines all
supported types
82. you should knowJava byAPIs
Annotations
SOURCE CLASS RUNTIME
remove annotation at
compiletime
remove annotation at
runtime
do not remove
annotation
83. you should knowJava byAPIs
Annotations
SOURCE CLASS RUNTIME
general meta
information like
@Override
for example the
annotations of findbugs
All annotations that
are used at runtime
84. you should knowJava byAPIs
Annotations
⢠There are several ways how
annotations can be used
⢠Annotations like @Deprecated define
useful information for the developer
(IDE support) and compiler
85. you should knowJava byAPIs
Annotations
⢠Projects like Lombok use annotations
for annotation processing at compile
time
⢠Annotations like @Inject are used to
modify objects at runtime
86. you should knowJava byAPIs
Annotations
⢠All annotations that have a @Retention
policy that is defined as RUNTIME can
be accessed by using reflection.
⢠In general this is one of the tricks that
make DI or Spring work
87. you should knowJava byAPIs
Annotations
⢠How can I check for annotations in my
code at runtime
?
88. you should knowJava byAPIs
Annotations
Class cls = MyCustomClass.class;â¨
boolean val = cls.isAnnotationPresent(MyAnnotation.class);
⢠Reflections ;)
89. you should knowJava byAPIs
Annotations
⢠Annotations can contain parameters
public @interface Column {
String name();
}
@Column(name="Description")
private String desc;
90. you should knowJava byAPIs
Annotations
⢠If an Annotations only needs one
param it should be named as "value"
⢠By doing so the name must not be
specified when using the annotation
91. you should knowJava byAPIs
Annotations
public @interface Column {
String value();
}
@Column("Name")
private String name;
92. you should knowJava byAPIs
Annotations
⢠Annotations can define a default value
for a parameters
public @interface Column {
String name() default "";
}
@Column
private String name;
93. you should knowJava byAPIs
Annotations
⢠Additional topics:
⢠@Inherited
⢠Lists of annotations
⢠Meta annotations
⢠Annotation Processor