In our Web application project, we are using the Redis to manage the session. To support it, we are serializing any object which will be stored in the session.
For example, we use DTO's to hold the bean data which is used to display on the screen. Even if the DTO having any other object inside (Composition) we also have to serialize it otherwise, we get NotSerializableException
.
I had a problem when I was creating an anonymous inner class to implement the Comparator
like below:
Collections.sort(people, new Comparator<Person>() {
public int compare(Person p1, Person p2) {
return p1.getLastName().compareTo(p2.getLastName());
}
});
The above code threw the NotSerializableException
and I resolved it by creating a class that implements the Comparator
as well as Serializable
interface. The problem was, it was thrown inside the JSP
page which was using this DTO. I had to do a lot of debugging to find the actual problem.
But now, I'm wondering to change the above code to use Lambda expression like below:
Collections.sort(people, (p1, p2) -> p1.getLastName().compareTo(p2.getLastName()));
However, I fear the same exception might occur. Does the Lambda expression create objects internally?
We can serialize a lambda expression if its target type and its captured arguments have serialized. However, like inner classes, the serialization of lambda expressions is strongly discouraged. As the lambda function is not serialized by default we simply have to cast our lambda to java. io.
Serializable interface. Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.
Explanation. Both of the above options are correct. Q 5 - Which of the following is correct about Java 8 lambda expression? A - Lambda expressions are used primarily to define inline implementation of a functional interface.
Lambda Expressions were added in Java 8. A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.
You can create a serializable lambda expression via
Collections.sort(people, (Comparator<Person>&Serializable)
(p1, p2) -> p1.getLastName().compareTo(p2.getLastName()));
but it should be noted, that creating a Comparator
via
(p1, p2) -> p1.getLastName().compareTo(p2.getLastName())
bears a discouraged redundancy. You are calling getLastName()
twice and have to care to invoke it on the right parameter variable in either case. It is more straight-forward to use
Comparator.comparing(Person::getLastName)
instead. You can also make this comparator serializable, though that implies loosing much of the conciseness:
Collections.sort(people,
Comparator.comparing((Function<Person,String>&Serializable)Person::getLastName));
This is also more robust. The serialized form of a lambda expression contains a reference to the implementation method, which is in the first variant a synthetic method with a compiler generated name that might change when you use another lambda expression within the defining method. In contrast, Person::getLastName
points the the named method getLastName
as implementation method (at least with javac
).
But generally, serializable lambda expressions might contain surprising compiler dependencies and should be used with care.
Since they are meant to describe behavior rather than data, there is no point in long-term storage of them anyway. For transferring them between JVMs with the same code base, they are sufficient.
Yes it does create an Object. The second parameter is of type Comparator, so that's what will be created implicitly.
See this: Does a lambda expression create an object on the heap every time it's executed?
On a side note, you'd benefit in allowing your application to run locally. To start an embedded Redis server, you may take a look at my personal project on github: https://github.com/alexbt/sample-spring-boot-data-redis-embedded.
It's using the following dependencies:
<dependency>
<groupId>com.github.kstyrc</groupId>
<artifactId>embedded-redis</artifactId>
<version>0.6</version>
</dependency>
and mostly these 3 lines to handle it:
new RedisServer(redisPort);
redisServer.start();
redisServer.stop();
You could even do that in a side project, just to stop/start Redis on a specific port. It would be even better if you integrate it inside the application trigger with a specific a Spring Profile, but that will be more work in the short term.
The library's website: https://github.com/kstyrc/embedded-redis:
Running RedisServer is as simple as:
RedisServer redisServer = new RedisServer(6379); redisServer.start(); // do some work redisServer.stop();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With