Upgrade to Java 8
04 May 2015
We are spoiled. One year after Java 8 came out, we can already use it at work. In my field (business applications) and in my country (Belgium), we are now certainly ahead of most large corporate organizations. Maybe we got lucky. I heard the IT department made bitter experiences for waiting too long before upgrading end-of-life products and softwares. Probably why they were readily amenable to a move to Java 8. The expected benefits from Java 8 were high, so I pushed for it without a second of hesitation.
Our path to Java 8
We took the following path from Java 6 to Java 8 :
- Groundwork and preparation : migrate the Java 6 Maven project to Java 8
- Scramble a talk on the relevant new features in Java 7 and 8 for your teammates, with the emphasis on lambda expressions
- Prepare a lambda hacking lab with exercises for 2 hours
- A few weeks later, follow-up with a wrap-up presentation, share code and discuss the Java 8 experience
My now former colleague Pierre Verhaeghe branched the code base and started to move to Java 8. They were minor issues and inconveniences, but no showstoppers.
Tools and libs to upgrade :
- Moving from Tomcat 6 to Tomcat 8
- cxf codegen 2.7.0 -> 3.0.3
- javassist upgrade to 3.17.1-GA
- DB2 (yes...) JDBC driver had to be upgraded to db2jcc4
- p6Spy updgrade
- slf4j scope set to 'provided' and deploy it in Tomcat 8
- Upgrading to Eclipse Luna, although this step was not mandatory
- Make sure you have a comparator for
- Some Guava code needed to be fixed
@PowerMockIgnore("org.slf4j.*")to 3 failing TestNG unit tests
- Using Strict Math for some operations (`pow), because the non-strict version allows deviation between platforms, hence our phonetic algorithm failed.
- Latest servlet version forbids duplicate attributes in JSP. They were several of them. Expect runtime failures if you have no E2E test coverage. IntelliJ issues a red error at least.
Prepare the team
We started with a talk on the relevant new features in Java 7 and 8, with the emphasis on lambda expressions. Take your time, don't rush things at this stage. It can be daunting for some of your colleagues, specially if they've had no prior exposure to functional languages.
A theorical presentation can only take you so far. I had the chance to join a vJug one year before, where Brian Goetz gave a talk on lambda. This was followed by a world-wide lab. I found this was good idea to redo it in the office. I added some exercises of my own to cover additional practical cases.
It's all on GitHub. Pierre added code illustrations of many Java 7 features.
6 weeks after the lab, it was time for us to share code snippets and discuss what Java 8 brought us. I took the chance to talk about traits (more on that in another post, maybe).
Learning curve and productivity
If you're considering moving to Java 8, one of the things should not worry about is the team productivity and learning curve.
We were a bit concerned at first, knowing that some of our colleagues had no prior exposure to functional languages. If you have experience in Python, Scala, Prolog, Groovy, ... it will be a walk in the park. If not, it will still be very pleasant. We were actually impressed by our colleagues adaptability. They picked up the new idioms in a snap, challenging us with though questions, and catching small mistakes in the presentation :-)
Code completion is far behind what you get with IntelliJ. Eclipse Luna seems to struggle at the slightest hindrance. This being said, I'm under the impression that Eclipse struggles on many occasions. The cross you bear is often the cross the management chooses for you.
There were questions on lambda expression performance. It is difficult to put figures on the table. After some research, I came to the following conclusion : "I wouldn't worry about it".
A bit unsettling I admit.
We had performance issues in the application before Java 8, and we still have them afterwards, no more, no less. We typically filter out records in the DAO layer, and we work on small memory collections. Typically 5 to 100 items. For a modern CPU, this is negligible.
Capturing expressions are slower, but even then, on tiny collections, I don't think it's going to make a difference. If you use lambda expression idiomatically, for small, pure functions, you won't need to capture anything and it should perform well.
My conclusion stands provided that you don't need micro-optimized code, and that you remain considered. YMMV.
In any case, measure, don't guess is the cornerstone of profiling and performance testing. Often I've been puzzled by the gap between the suspect and the actual offender. Again, I'd be very surprised if lambda expressions, as we use them, would cause any issue.
Most of Google Guava functional expressions are not needed anymore in our code. We simply kept them as is, removing them when the opportunity arises.
One of the great promises of Java 8 is
java.time.*. Indeed, it's nice. We use
java.util.Date to represent days - in our business, we need days a lot - plus utility classes. As expected, we're not magically going to replace of
java.time.LocalDate. Replacing dates on legacy code is no small undertaking. So we're mostly stuck with dumb old dates.
Pros and Cons
To sum it up :
- Code readability
- Functional expressions elegantly capture functional analysis
- Less code -> less bugs
- Debugging lambda expressions suck, big time. One more reason to stick to simple functional expressions.
- Converting a list of
Xto a list of
Ywas more easily achieved with Goolge Guava, but in practice, that should not happen a lot if you use generics correctly.
Overall, it's a huge win, it pays off in no time, and everybody in the team was glad we did the move.