Lagom and Immutability


What is Lagom?
Lagom is not in disguise anymore. Everyone who’s following on micro-service architecture knows about Lagom framework. Lagom is an open source framework built with the shifting from monoliths to micro-services-driven application architecture in mind. It abstracts the complexity of building, running and monitoring micro-services driven applications.
The Lagom framework includes Java and Scala APIs to simplify development of microservices. Lagom helps us to build micro-services as reactive systems so that the micro-services are resilient, elastic and scalable from within.

One important concept to follow when using Lagom is immutability. In Lagom, immutable objects are required in several places, such as:

  • Service request and response types
  • Persistent entity commands, events, and states
  • Publish and subscribe messages

What is Immutability?
Immutability is considered as one of the key concept of functional programming. Most of the functional languages like Scala, uses immutable object by default. An immutable object is one whose state cannot and will not change after it’s initial creation. I highly recommend spending some time with a functional language like Scala to really understand and appreciate the power immutable Objects.

Benefits of Immutable Objects :-

  • Immutable objects are thread-safe so you will not have any synchronization issues.
  • The internal state of your program will be consistent even if you have exceptions.
  • Code based on immutable objects is clearer and likelier to be correct. Bugs involving unexpected changes simply can’t occur.
  • References to immutable objects can be cached as they are not going to change.
  • It potentially simplifies the implementation of the class.
  • Immutability makes it easier to parallelize your program as there are no conflicts among objects.

Interestingly, almost all of the new features in Java 8 (Date and Time, Optionals and Streams) have been implemented in an immutable fashion. We can get the benefits of immutable Objects in Java for user defined classes, in the following way:

  • Mark class as final
  • Mark all the fields and private and final
  • Use parameterized constructors and do not use any setter methods.
  • Do not change the state of the objects in any method of the class.

But instead of doing this manually, Lagom recommends to use third-party tools to achieve immutability.
So for achieving immutability Lagom prefers the following:-
For user-defined classes:  Lombok
For Collections: PCollections.

Lombok: It provides various annotations to be used for making our class immutable, with less lines of code and achieve immutability in a cleaner way.
Maven dependency for Lombok:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.18</version>
</dependency>

Here’s an example of creating a user-defined class with lombok:

@Immutable
@JsonDeserialize
@Value
@Builder
@AllArgsConstructor(onConstructor = @__(@JsonCreator))
public class Data {
    @NotNull
    String value1;
    @NotNull
    String value2;
}

See the beauty of Lombok, there are more lines of annotations than the code for class. Let’s see what these annotations indicates:

@Immutable is from the javax.annotation.concurrent package. The class to which this annotation is applied is immutable. And immutable objects are inherently thread-safe.
@JsonDeserialize is a Jackson annotation from  that indicates that the annotated class should be used for deserialized JSON data.
@Value is the immutable variant of @Data; all fields are made private and final by default, and setters are not generated. It generates getter methods for them, generates standard equals(), hashCode(), and toString() methods, and generates a constructor taking all fields as arguments.
@Builder generates a builder class and method for constructing an object through the builder pattern. In this example, this generates a method called builder() which returns a new DataBuilder, and that class provides methods such as value1() and value2()to set these values, and a build() method to construct a Data object.
@AllArgsConstructor generates a constructor with 1 parameter for each field in your class. This constructor replaces the constructor that would’ve been generated by the @Value annotation. The reason we use this constructor is in order to decorate that constructor with the @JsonCreator annotation. This annotation is another Jackson annotation that indicates how to construct new instances of this class using JSON data.
@NonNull is another Lombok feature that results in null checks in generated constructors and setters for that field. This annotation throws a NullPointerException, if the value of the field is null.

If an immutable object contains a collection, that collection must be immutable too.
One possible fix would be to make a defensive copy of the List in the constructor and use Collections.unmodifiableList in the getter. The danger of Java’s implementation is that because there is no interface specifically for immutable collections, those unmodifiable collections still have the mutable methods add/put and remove which will throw an UnsupportedOperationException if called. On the other hand, Scala created separate scala.collection and scala.collection.mutable interfaces for mutable and immutable collections to avoid this problem.
Google’s popular Java Library Guava created separate public ImmutableSet, ImmutableMap, and ImmutableList classes.
The Guava collections are certainly better for this purpose than plain java.util collections. However, the Guava collections are cumbersome and inefficient for some common operations (for example, making a slightly modified copy of an existing collection).
Therefore, Lagom recommend PCollections, which is a collection library that is designed from the ground up for immutability and efficiency.

PCollections: PCollections serves as a persistent and immutable analogue of the Java Collections Framework. This includes efficient, thread-safe, generic, immutable, and persistent stacks, maps, vectors, sets, and bags, compatible with their Java Collections counterparts. Here, the word “persistent” means that even when you construct a modified copy of a collection, the original “persists”.
Both Guava and Java’s Collections utility class provide immutable collections but they are not persistent, that is they do not provide efficient producers, so they are not nearly as useful.
Example:

import org.pcollections.PSet;
PSet<String> set = HashTreePSet.empty();
    set = set.plus("something");
    System.out.println(set);
    System.out.println(set.plus("something else"));
    System.out.println(set);

So this was an attempt to showcase the recommended way of achieving immutability while using Lagom framework to build reactive micro-services. Hope this attempt would be helpful to you. For more doubts and examples regarding Lagom, feel free to go through our blogs, because we at Knoldus believe in gaining knowledge and growing our skills together.

References:
https://www.lagomframework.com/documentation/
https://projectlombok.org/
https://pcollections.org/


knoldus-advt-sticker


Advertisements

About anmolmehta

Technology Enthusiast
This entry was posted in Architecture, Java, knoldus, Microservices, Scala and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s