Home > Blog > Java Application Modernization: Useful Recommendations For Java 8

Java Application Modernization: Useful Recommendations For Java 8

08 May 2017

A legacy application is any business application that is based on older system architecture and yet continues to support core business functions of an organization. These systems are often monolithic (meaning they have little or no reusable code “snippets”). The systems are also difficult to understand and modify. Thus, organizations often resort to Application Modernization or Re-engineering for reducing IT costs and increasing agility.


A well-planned application modernization project has significant business benefits. In fact, Gartner has advised IT
Leaders and CIOs to place IT modernization at the core of their objectives. The Java platform has been around for a long time and has evolved with times. Newer versions are released frequently. Many enterprises have acquired a portfolio of Java applications over the years that run their business-critical processes. They need to modernize and bring these applications up to speed so that they can remain competitive and deliver optimum performance.


Make The Most Of Java 8 With These Helpful Tips

Java App Modernization

Stay ahead of the competiton by optimizing performance and agility of your legacy application. Talk to our experts now!

Of course, migrating to a modern release of Java such as Java SE 8 is a momentous task. Java 8 is a revolutionary release with a huge upgrade to the model and a coordinated evolution of JVM, Java language and libraries. However, there are some best practice measures with Java 8 code that are useful in general whether you are considering migration or building a new. Here are a few of them:


Optional is quite underappreciated as a feature. It has the capability to remove quite a lot of the NullPointerExceptions that are the bane of Java developers. Optional is specifically important at the boundaries of code (for APIs you might be using or exposing) as it allows you and the calling code to reason what to expect.


However, optional should be used with careful thought and design as it can impact many classes. Optional should only be used for return types and not parameters, neither fields. Luckily, IntelliJ IDEA allows you to inspect if you are following the recommendations for optional use.


private Optional<T> convertedValue;
public final Object encode(final Optional<T> value) {
return encode(value = null);


IntelliJ IDEA’s recommendations will prevent Optional leaking all over your code, so remember you should deal with Optional where you found it and move swiftly on.


final Optional<Key> key = mapper.getConverters().decode(keyClass, dbObject, mappedField);
if (key.isPresent() ) {
proxiedMap.put(key.get(), value);

Don’t simply call(get)
Simply calling get() without verifying isPresent() first will possibly lead to a null pointer eventually. Once again IntelliJ IDEA has an inspection to caution you.


final Optional<Key> key = mapper.getConverters().decode(keyClass, dbObject, mappedField);
proxiedMap.put(key.get(), value);


Fret not, there is an elegant way.
The isPresent() combined with get() solves the problem. But there are more sophisticated solutions. For example, you can use orElse to give an alternative value in case it’s null.


final Optional<Key> key = mapper.getConverters().decode(keyClass, dbObject, mappedField);
if (key.isPresent()) {
proxiedMap.put(key.get(), value);
else {
proxiedMap.put(createNewKey(), value);


final Optional<Key> key = mapper.getConverters().decode(keyClass, dbObject, mappedField);
proxiedMap.put(key.orElse(createNewKey()), value);


Optionally, you can use orElseGet to instruct which method to call in case of the value being null. While it appears the same as the above example, the supplier method will be called only if required, so if it is an expensive method, it would be preferable to use lambda.


final Optional<Key> key = mapper.getConverters().decode(keyClass, dbObject, mappedField);
proxiedMap.put(key.orElseGet(() -> createNewKey()), value);


Using Lambda Expressions
Lambda expressions are one of the key strengths of Java 8. Even if you may not be using Java 8 yet, you might have a fair idea of what they entail. There are still some ground rules to be established for using lambda expressions.


Keep it concise
Seasoned Java professionals might be adept at handling longer lambda expressions, but for the general majority, it is easier to keep lambda expressions to a small number of lines. You may also prefer to limit them to just a single line.


These may even collapse down into method references. Method references may seem a bit alien at first, but it’s worth persevering with them as they can actually aid readability in some cases.


.until(() -> foundTenItems());


In short, avoid blocks of code in lambda’s body. But please don’t use the one-line lambda rule as a dogma.


Avoid specifying parameter types
A compiler is generally able to resolve the type of lambda parameters with the help of type inference. Adding a type to parameters is thus optional and can be avoided.


Do this:

(a, b) -> a.toLowerCase() + b.toLowerCase();
rather than this:


(String a, String b) -> a.toLowerCase() + b.toLowerCase();


Use Method References
Frequently, lambda expressions just call methods which are already implemented elsewhere. In this scenario, it is helpful to use: method references.


So, the lambda expression:

a -> a.toLowerCase();
can be replaced by:




This is not always shorter, but it makes the code more readable.

In conclusion
As you can see Java 8 has some stellar features and by adopting best programming practices and tips you can enhance your application development and avoid some common pitfalls. If you are looking at Java application development services to modernize some of your applications, please get in touch.

Get a Free Consultation

Consult our experts to get the best Java based enterprise solutions.