Upgrading to Java 9

Upgrading to Java 9

Ever since Java 9 was released last fall, I have been wanting to upgrade our software at work to the new platform. I am not interested in the new module stuff, mostly I just want the convenience methods like List.of(), and the platform improvements. I think G1 by default looks good, the new representation for strings to save memory looks like a huge win, and all the performance numbers that I have seen show it to be a big win. Unfortunately this is not as straight forward as one should hope.

Step 1 – Spring Support

Even though Spring 5.0 was released back in December I think which fully supports Java 9, Spring Boot 2.0 is not yet released. I believe it is in RC2 now and about to be released in the next week or so, but at this point we are less than a month away from Java 10, before we will have proper Spring Boot support in Java 9. All of our microservices are currently running on Spring Boot 1.5.10 except for one. It is still running on the 1.3.x version of Spring boot, which brings us to our second Spring issue to resolve. Some contractors that originally started that service did a hack to lazy load @Formula s in hibernate. While this worked in Hibernate 4.x in Hibernate 5 the hack no longer worked so we can’t even update this service until we refactor those entities and move that data into views. That is still a work in progress. The other microservices could be moved to 2.0 when it comes out, but I think their is a consensus that we don’t want to move to 2.0 until we have all our services to a place where we could do that.

Step 2 – Gradle

We are currently running gradle 3.5.1. Going to Java 9 is going to require Gradle 4.2 (which is also a requirement for the Spring Boot 2.0 Gradle plugin). Normally this is no big deal upgrade the file edit the wrapper portion to the new version run ./gradlew wrapper and check in the new gradle wrapper. But in this case we still have a developer running on IntelliJ 2016.1 and another on 2016.2. They would have to upgrade to at least 2017.2 in order for the new gradle to work with their IDE. So we will need to convince the whole team to update their IDE if they haven’t already ideally at that point to 2018.1.

Step 3 – FlywayDB

We are currently using Flyway DB 4.2.0. This didn’t work with Java 9 when I was testing it, so we need to go to 5.0.x. Additionally Spring Boot 2.0 requires Flyway 5.0.x. Ideally we want to upgrade this ahead of Spring to minimize risk. Bring the new flyway into production and then once we are satisfied that it doesn’t break anything upgrade Spring Boot.

Step 4 – Docker Containers

Once we have all that software in place we then will have to update our docker containers to pull in the new JVM. It sounds like in Java 9 Linux, OpenJDK ships with an empty certificate store. So that means finding a Oracle or Azul docker container as our base. We then have to verify that New Relic works with Java 9 so we have our container monitoring. After doing all that we can update our base VM to be Java 9.

Step 5 – Update Jenkins

We will need to add a new VM to Jenkins so that as different builds switch to the new Java 9 container we also switch to compiling them with the Java 9 VM (though with the Java 8 flags still at this point).

Will the pain never end…

Finally after doing everything listed above we could change our compiler flags to 9 and start using the features. It is still a painful road to walk to get us there. At this point it feels like by the time we finish the work that needs to be done (as obviously we need to be shipping features and bug fixes, while we lay the foundation for this on the side) Java 11 will be out and we will be moving to that.

Even though Java 9 support is so close to being out in Spring Boot I still feel like I am at least 6 months away from getting to use any of it. This feels much more painful than when I moved an App from Java 7 -> 8. At that point I think it was just a matter of coordinating a JBoss container upgrade from 6.0.1 to 6.4. After we got that into production we updated the VM to Java 8 (still with everything compiling on 7). Then we upgraded our Jenkins machine to have Java 8 for the compiler, and finally we updated our maven pom to use source and target of 8. I wonder if anyone Spring shops will even make it to 9 or if everyone is holding out for 11 at this point (also to get the LTS release). While I really like the sound of the 6 month release cadence actually getting the dependencies in place and lined up to do an upgrade will probably mean most enterprises just end up going from LTS release to LTS release and I would guess that Java 9 and 10 see very little use running production code and mostly will just be things for developers to play with on their machines.


IntelliJ Idea Bug in 2016.1.2

I hit a bug in Idea 2016.1.2 that I wanted to share in case anyone else is hitting the same issue. I was trying to stand up a new Spring Boot project last week and when I what try to launch the app through the IDE the embedded tomcat server would throw an exception.

org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh( ~[spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh( ~[spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh( [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.createAndRefreshContext( [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at com.chooseenergy.auth.AuthApplication.main( [classes/:na]Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory( ~[spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer( ~[spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh( ~[spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
... 8 common frames omitted

The weird thing was if I ran the maven spring-boot:run plugin the app ran perfectly. I did all sorts of things with no luck to work around it. I starting worrying about it, thinking if I can’t find a solution to this, it is going to be hard to sell using Spring Boot for our Microservices in my new role as we can’t even properly debug them. Finally after no luck I opened a bug against Idea over here. As is often the case, just the simple act of reporting the bug gets me thinking about possibilities and I solved the issue before I heard back from JetBrains. It turns out that the provided scope is broken in Idea and by default the spring-boot-starter-tomcat is marked scope provided in the generated maven pom file from the Spring Boot Initializer. As soon as I removed the provided scope Idea got happy. Jetbrains later updated the ticket as a duplicate of a bug with provided scope not working. So if you see that stack trace in Idea try removing the provided scope to work around it.


The Jetbrains fiasco

This is sort of old news now, but I haven’t had a chance to weigh in yet so I figured I would type my thoughts up anyway. On September 3rd Jetbrains announced a new licensing model. As you can imagine people immediately went crazy on twitter and 15 years of developer goodwill went up in smoke. What is the issue with the new model, the biggest problem with it is that they are moving from a perpetual model where you own that version of the IDE to a rental model ala Adobe where if you stop paying your tools stop working. Even more infuriating they came out like this was doing a favor for their developers and making it cheaper. In reality it only really makes it cheaper if you are say a consulting shop that is often switching between say pycharm, webstorm and idea. Then you can save some money over the cost of 3 perpetual licenses. For pretty much everyone else it is much worse.

As soon as they saw all of this blowing up they quickly came up with another response. In the comments of the 2 articles they argued that they were giving a lower price to the current customers with a perpetual license. That isn’t exactly true. If I am a customer that as soon as my license expires I renew it can be true for a year at least as they are only guaranteeing that license price for the first year. So assuming they kept the new lower price it would be an $89 a year update to IDEA instead of $99 the current price. But for new customers the renewal is $119 for a promotional price before January and then it goes to $149 a year which is much more expensive than the current model ($199 for a personal license and $99 for an upgrade).

Another way this fails vs the current model is if I buy a license and then say an upgrade for a few years and then I am short on money I can continue to use my old version without updates as long as I want. In the new model as soon as I stop paying the software is gone. So it really does feel like owning a license to that version of the software vs renting the software.

We switched to Idea at work a little over a year ago. In that time I fell in love with that product. It really is the best IDE I have ever used. I was such a fan that when they had the save 20% sale for the 20 years of Java I decided to buy a personal license to mess around with at home. In my home use case I don’t use the tool a ton. A couple of times a month I will use it to play around with an idea I have or to experiment with some idea or technology that I may use in the future at work. But given that I make no money with it at home and it is just something to toy with I have the option when it expires to not renew for a few years and just use the tool as I do now. Unfortunately with the new licensing model Jetbrains takes that away from me. If I don’t keep paying for it monthly I don’t get to use it. I can’t justify a monthly bill for what is effectively something I just play around with when I am bored. If there is no perpetual model going forward I will use the license I have now until it doesn’t work for me anymore (probably when Java 9 comes out next year) and then I will go back to Netbeans.

Thinking about it at a professional level, at this point I was ready to advocate for the environment in any company I was working for. I truly believe their tools are better. But at the same time I don’t want to see a business I am working for held hostage by their tools. It feels like a cross between dealing with Adobe (for their monthly subscriptions) and Oracle who would allegedly threaten businesses with a license audit if one believes what they read on the internet. So on the one hand I am tempted to say we should immediately upgrade our licenses at work before the switch so we can kick the can down the road for another year before we have to make a decision on it. And on the other hand that sort of feels like rewarding them for the betrayal to the developers when they get all those license fees for everyone trying to keep their perpetual license a bit longer. Will I recommend that we stay on it if our only choice is subscription? Given what I have seen so often with corporate budgets being frozen for a period of time I would have a hard time recommending a tool that may stop working for us because we are in a spending freeze.

So I am not sure what to do, what I can say is if they don’t have a perpetual model they have probably lost me as a customer forever.