Showing posts with label lombok. Show all posts
Showing posts with label lombok. Show all posts

Monday, 11 May 2015

Immutable Objects with Lombok - workshop

An immutable object is an object whose state cannot be modified after it is created.


Why Immutable Objects are important?


Because you have no total control : objects can be passed anywhere and can arrive from anywhere  in the code. If they are mutable, then any object can modify their state. Different threads can access the same model object and modify/read its state creating many problems difficult to handle.

What is an Immutable object?


Final private fields,  No Setters & Unmodifiable collections

An example ?



What does Lombok?


Project Lombok aims to reduce boilerplate codes by replacing them with a simple set of annotations.

How to install Lombok?


see here : https://projectlombok.org/download.html


Workshop :

Create a model object called Home with the following fields :   

String address;
The street name of your home

int age;
How old were you when you enter this house


int fromYear;
Which year you start living there
int toYear;
Which year you left


Create a toString() method to print the details.




Create a class called MyHomes that prints the list of Homes you lived in.   

This class should create as many homes you lived in and print the details for each one of them. 


Now make the class immutable

Now try to clean the Home class code with Lombok!!

Hints / Immutability support :-

val
@AllArgsConstructor
@Builder
@Value
@FieldDefaults



 
 How can we change a value? 

Add an immutable boolean field to indicate if the address has been verified.

Default should be false.

Add a method to MyHomes to verify a List of Homes


 Now try to use the @Wither annotation from Lombok!!




End of the workshop











Stretch content


































































Friday, 26 July 2013

Lombok’s Sneaky Throws

I finally found a real life scenario where I want to use “Sneaky Throws” Lombok’s feature. According to the documentation:

@SneakyThrows

To boldly throw checked exceptions where no one has thrown them before!

Overview

@SneakyThrows can be used to sneakily throw checked exceptions without actually declaring this in your method’s throws clause. This somewhat contentious ability should be used carefully, of course. The code generated by lombok will not ignore, wrap, replace, or otherwise modify the thrown checked exception; it simply fakes out the compiler. On the JVM (class file) level, all exceptions, checked or not, can be thrown regardless of the throws clause of your methods, which is why this works.
More info about this feature. here: http://projectlombok.org/features/SneakyThrows.html
The scenario is the following:
We have a helper class that retrieves a field using reflection and in turn uses the Apache Commons’ PropertyUtils class. 
The latter throws 4 checked exceptions we don’t want to propagate to the final user. 
In other words, if some of these exceptions are thrown, we want everything to explode (especially, because we use this helper only for unit tests). So, the options were:
  1. Wrap everything around a big try{} catch (Exception) block and throw a RuntimeException such as IllegalArgumentException.
    • Con: Sonar would complain that we are catching the generic class “Exception”.
  2. Throw all exceptions.
    • Con: ugly. User will have to explicitly catch all these exceptions. Not really an option.
  3. Use Lombok’s “Sneaky Throws” feature. This would throw all of the above mentioned exceptions but without forcing users to explicitly catch them. This is the approach:
@SneakyThrows(value = { SecurityException.class, NoSuchFieldException.class, IllegalArgumentException.class, IllegalAccessException.class })
public static <T> void setPrivateStaticFinalField(Class<T> targetClass, T targetObject, String fieldName, Object newValue) {
    Field logField = ReflectionUtils.findField(targetClass, fieldName);
    logField.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(logField, logField.getModifiers() & ~Modifier.FINAL);
    ReflectionUtils.setField(logField, targetObject, newValue);
}