Java Doesn’t Suck – You’re Just Using it Wrong

Check out the Russian translation provided by Everycloudtech.

I’ve been building enterprise Java web apps since servlets were created. In that time the Java ecosystem has changed a lot but sadly many enterprise Java developers are stuck in some very painful and inefficient ways of doing things. In my travels I continue to see Java The Sucky Parts – but it doesn’t have to be that way. It is time for enterprises to move past the sucky ways they are using the Java platform. Here is a list of the suckiest parts of Java that I see most often and some recommendations for how to move past them.

10 Page Wikis to Setup Dev Environments Suck

Setting up a new development environment should be no more than 3 steps:

  1. Install the JDK
  2. Clone / checkout the SCM repo
  3. Run the build / start the app

Seriously. It can and should be that easy. Modern build tools like Gradle and sbt have launchers that you can drop right into your root source tree so that new developers can just run ./gradlew or./activator (for sbt). The build should have everything needed to get the app up and running – including the server. The easiest way to do this is to go containerless with things like Play Framework and Drop Wizard but if you are stuck in a container then consider things like Webapp Runner. One of the many problems with the container approach is the very high probability of running into the it works on my machine syndrome because environments easily differ when a critical dependency exists outside of the realm of the build and SCM. How many wikis keep the server.xml changes up-to-date? Wiki-based configuration is a great way to cause pain.

What about service dependencies like databases and external web services – don’t developers need to set those things up and configure them? Not if your build can do it for them. Smart build systems should be able to provision the required services either locally or on the cloud. Docker has emerged as a great way to manage local environments that are a replica of the production system.

If your app needs a relational database then use an in-memory db like hsql or cloud services like Heroku Postgres, RDS, Redis Labs, etc. However one risk with most in-memory databases is that they differ from what is used in production. JPA / Hibernate try to hide this but sometimes bugs crop up due to subtle differences. So it is best to mimic the production services for developers even down to the version of the database. Java-based databases like Neo4J work the same in-memory and out-of-process minimizing risk while also making it easy to setup new development environments. External web services should either have a sandbox host that can be used by developers or the web services should be mocked.

Incongruent Deployment Environments Suck

To minimize risk when promoting builds from dev to staging to production, the only thing that should change between each environment is configuration. A deployable artifact should not change as it moves between environments. Continuous Integration systems should run the same build and tests that developers run. Have the CI system do automatic deployment to a testing or staging environment. A proper release pipeline makes it easy to promote a deployable artifact from staging to production.

I used to maintain a Java web app where the deployment process went like this:

  1. Build a WAR file
  2. SCP the WAR file to a server
  3. SSH to the server
  4. Extract the WAR file
  5. Edit the web.xml file so it contains new database connection info
  6. Restart the server

That setup isn’t the worst I’ve seen but it is was always risky. It would have been much better to utilize environment variables so the only thing that changed between environments was those variables. Environment variables can be automatically read by the app so that the artifact stays the exact same. In this setup reproducing an environment is super easy – just set the env vars.

Servers That Take More Than 30 Seconds to Start Suck

For developer productivity and so that scaling up can happen instantly, servers should startup quickly. If your server takes more than 30 seconds to start then break the app into smaller pieces, adopting a Microservices architecture. Going containerless or having a one-app-per-container rule can really help reduce startup time. If your container takes a long time to start you should ask yourself: What are all those container services there for? Can the services be broken out into separate apps? Can they be removed or turned off?

If you need some ammunition to prove to your management that your startup times are killing your team’s productivity then use the stopwatch on your phone to count the total minutes per day wasted by waiting for the app to start. Bonus points if you calculate out how much wasted money that translates to for yourself, your team, and your org. Double bonus points if you show a chart that defeats the “we spent a lot of money on this app server” sunk cost argument.

Manually Managed Dependencies Suck

It sucks if any of your library dependencies aren’t managed by a build tool. Manually copying Jar files into the WEB-INF/lib is horribly error prone. It makes it hard to correlate files to versions. Transitive dependencies are addressed by ClassNotFound errors. Dependencies are brittle. Knowing the libraries’ licenses is hard. Getting your IDE to pull the sources and JavaDocs for the libraries is tough.

So first… Use a build tool. It doesn’t matter if you choose Ant + Ivy, Maven, Gradle, or sbt. Just pick one and use it to automatically pull your dependencies from Maven Central or your own Artifactory / Nexus server. With WebJars you can even manage your JavaScript and CSS library dependencies. Then get fancy by automatically denying SCM check-ins that include Jar files.

Unversioned & Unpublished Libraries Suck

Enterprises usually have many libraries and services shared across apps and teams. To help make teams more productive and to enable managed dependencies these libraries should be versioned and published to internal artifact servers like Nexus and Artifactory. SNAPSHOT releases should be avoided since they break the guarantee of a reproducible build. Instead consider versioning based on your SCM information. For instance, the sbt-git plugin defaults the build version to the git hash or if there is a git tag for the current position then the tag is used instead. This makes published releases immutable so that library consumers know exactly the correlation between the version they are using and the point-in-time in the code.

Long Development / Validation Cycles Really Suck

Billions of dollars a year are probably wasted with developers just waiting to see / test their changes. Modern web frameworks like Play Framework and tools like JRebel can significantly reduce the time to see changes. If every change requires a rebuild of a WAR file or a restart of a container then you are wasting ridiculous amounts of money. Likewise, running tests should happen continuously. Testing a code change (via reloading the browser or running a test) should not take more time than an incremental compile. Web frameworks that display helpful compile and runtime errors in the browser post-refresh are also very helpful to reduce long manual testing cycles.

When I work on Play apps I am continuously rebuilding the source on file save, re-running the tests, and reloading the web page – all automatically. If your dev tools & frameworks can’t support this kind of workflow then it is time to modernize. I’ve used a lot of Java frameworks over the years and Play Framework definitely has the most mature and rapid change cycle support. But if you can’t switch to Play, consider JRebel with a continuous testing plugin for Maven or Gradle.

Monolithic Releases Suck

Unless you work for NASA there is no reason to have release cycles longer than two weeks. It is likely that the reason you have such long release cycles is because a manager somewhere is trying to reduce risk. That manager probably used to do waterfall and then switched to Agile but never changed the actually delivery model to one that is also more Agile. So you have your short sprints but the code doesn’t reach production for months because it would be too risky to release more often. The truth is that Continuous Delivery (CD) actually lowers the cumulative risk of releases. No matter how often you release, things will sometimes break. But with small and more frequent releases fixing that breakage is much easier. When a monolithic release goes south, there goes your weekend, week, or sometimes month. Besides… Releasing feels good. Why not do it all the time?

Moving to Continuous Delivery has a lot of parts and can take years to fully embrace (unless like all startups today, you started with CD). Here are some of the most crucial elements to CD that you can implement one-at-a-time:

  • Friction-less App Provisioning & Deployment: Every developer should be able to instantly provision & deploy a new app.
  • Microservices: Logically group services/apps into independent deployables. This makes it easy for teams to move forward at their own pace.
  • Rollbacks: Make rolling back to a previous version of the app as simple as flipping a switch. There is an obvious deployment side to this but there is also some policy that usually needs to go into place around schema changes.
  • Decoupled Schema & Code Changes: When schema changes and code changes depend on each other rollbacks are really hard. Decoupling the two isolates risk and makes it possible to go back to a previous version of an app without having to also figure out what schema changes need to be made at the same time.
  • Immutable Deployments: Knowing the correlation between what is deployed and an exact point-in-time in your SCM is essential to troubleshooting problems. If you ssh into a server and change something on a deployed system you significantly reduce your ability to reproduce and understand the problem.
  • Zero Intervention Deployments: The environment you are deploying to should own the app’s config. If you have to edit files or perform other manual steps post-deployment then your process is brittle. Deployment should be no more than copying a tested artifact to a server and starting it’s process.
  • Automate Deployment: Provisioning virtual servers, adding & removing servers behind load balancers, auto-starting server processes, and restarting dead processes should be automated.
  • Disposable Servers: Don’t let the Chaos Monkey cause chaos. Servers die. Prepare for it by having a stateless architecture and ephemeral disks. Put persistent state in external, persistent data stores.
  • Central Logging Service: Don’t use the local disk for logs because it prevents disposability and makes it really hard to search across multiple servers.
  • Monitor & Notify: Setup automated health checks, performance monitoring, and log monitoring. Know before your users when something goes wrong.

There are a ton of details to these that I won’t go into here. If you’d like to see me expand on any of these in a future blog, let me know in the comments.

Sticky Sessions and Server State Suck

Sticky sessions and server state are usually one of the best ways to kill your performance and resilience. Session state (in the traditional Servlet sense) makes it really hard to do Continuous Delivery and scale horizontally. If you want a session cache use a real cache system – something that was designed to deal with multi-node use and failure. e.g. Memcache, ehcache, etc. In-memory caches are fast but hard to invalidate in multi-node environments and are not durable across restarts – they have their place, like calculated / derived properties where invalidation and recalculation are easy.

Web apps should move state to the edges. UI-related state should live on the client (e.g. cookies, local storage, and in-memory) and in external data stores (e.g. SQL/NoSQL databases, Memcache stores, and distributed cache clusters). Keep those REST services 100% stateless or else the state monster will literally eat you in your sleep.

Useless Blocking Sucks

In traditional web apps a request comes in, fetches some data from a database, creates a webpage, and then returns it. In this model it was ok to give that full roundtrip a single thread that remained blocked for the entire duration of the request. In the modern world requests often stay open beyond the life of a single database call because either it is a push connection or because it is composing multiple back-end services together. This new world requires a different model for how the threads / blocking is managed. The modern model for dealing with this is called async & non-blocking or Reactive.

Most of the traditional Java networking libraries (Servlets, JDBC, Apache HTTP, etc) are blocking. So even if a connection is idle (like when a database connection is waiting for the query to return), a thread is still allocated. The blocking model limits parallelism, horizontal scalability, and the number of concurrent push connections. The Reactive model only uses threads when they are actively doing something. Ideally your application is Reactive all the way down to the underlying network events. When a request comes in it gets a thread, then if that request needs to get data from another system the thread handling the request can be returned to the pool while waiting for the data. Once the data has arrived a thread can be reallocated to the request so the response can be returned to the requestor.

Java has a great foundation for Reactive with Java NIO. But unfortunately most of the traditional Java web frameworks, database drivers, and HTTP clients do not use it. Luckily a whole new landscape of Reactive libraries and frameworks is emerging that is built on NIO and Netty (a great NIO library). For example, Play Framework is a fully Reactive web framework which many people use with Reactive database libraries like Reactive Mongo.

To be Reactive means that you also need to have a construct for being asynchronous. The traditional way to do this in Java is with anonymous inner classes, like:

public static F.Promise<Result> index() {
    F.Promise<WS.Response> jw = WS.url("").get();
    return F.Function<WS.Response, Result>() {
        public Result apply(WS.Response response) throws Throwable {
            return ok(response.getBody());

Java 8 provides a much more concise syntax for asynchronous operations with Lambdas. The same Reactive request handler above with Java 8 & Lambdas is:

public static F.Promise<Result> foo() {
    F.Promise<WS.Response> jw = WS.url("").get();
    return -> ok(response.getBody()));

If your app does things in parallel and/or handles push connections then you really should be going Reactive. Check out my Building Reactive Apps presentation if you want to dive in deeper on this.

The Java Language Kinda Sucks

The Java Language has a lot of great aspects but due to its massive adoption and desire from its enterprise users for very gradual change, the language is showing its age. Luckily there are a ton of other options that run on the JVM. Here is a quick rundown of the most interesting options and my opinions on some positives and negatives:

  • Scala
    • Great
      • Likely the most widely adopted alternative language on the JVM
      • Fits well with Reactive and Big Data needs
      • Mature ecosystem for libraries, frameworks, support, etc
    • Good
      • Java interoperability is great but often not useful since the Java libraries aren’t built for Reactive and Scala idioms
      • Modern programming concepts with very powerful & flexible language
    • Bad
      • Language flexibility leads to significantly different ways of writing Scala sacrificing universal readability
      • Huge learning curve due to large number of features
  • Groovy
    • Great
      • Large ecosystem for libraries, frameworks, support, etc
      • Simple language with a few very useful features
    • Good
      • Interoperability with Java works and feels pretty natural
    • Bad
      • I prefer good type inference (like Scala) over Groovy’s dynamic and optional static typing
  • Clojure
    • Great
      • The elegance of a Lisp on the JVM
      • Mature ecosystem for libraries, frameworks, support, etc
    • Good
      • JavaScript target seems good but isn’t core
    • Bad
      • The lack of some OO constructs makes managing a large code base challenging
      • Dynamic typing
  • Kotlin
    • Great
      • Interoperability with Java seems natural
      • JavaScript target is first class
    • Good
      • IDE and build tooling seems decent but immature
      • Modern language features that aren’t overwhelming
    • Bad
      • Uncertain where it will be in 5 years – will it catch on and gain critical mass?

Starting with a new / greenfield project can be an easy time to try a new language but most enterprises don’t often do that. For existing projects there some frameworks and build tools that support mixing existing Java with alternative JVM languages better than others. Play Framework / sbt is the one I’ve used for this but I’m sure there are also others that do this well. At the very least, writing just your new tests in an alternative JVM language can be a great place to start experimenting.

Java 8’s Lambdas are a nice upgrade to the Java language. Lambdas do help reduce boilerplate and fit well with the Reactive model. But there is still a lot of other areas where the language is lacking. Now that I know Scala there are a few things I couldn’t live without that are still absent from Java: Type Inference, Pattern Matching, Case Classes, String Interpolation, and Immutability. It is also very nice to have Option and concurrency constructs baked into the core and library ecosystem.

Reality Check

If you are in a typical enterprise then maybe you are lucky and already doing most of this. As shocking as it may seem for some of us, this is really rare. Most of you are probably reading this and feeling sad because moving the enterprise monolith towards a lot of this stuff is really hard. As physics tells us, it is much harder to move large things than small things. But don’t lose heart! I’ve seen a number of stodgy enterprises slowly creep out of Java the Sucky Parts. Walmart Canada recently switched to Play Framework! My recommendation is to pick one of these sucky things and make it your goal to fix it over the next year. Often this requires buy-in from management which can be tough. Here is my suggestion… Spend a couple evenings or weekends working on implementing one of these items. Then show your manager what you did in your own time (that will convey how much you care) and then let them take the credit for the amazing new thing they thought of. Works every time. And if it doesn’t then there are tons of well paying startups who are already doing all of this stuff.

One last thing… Go read The Twelve-Factor App – it was the inspiration for a lot of this content.

  • alexanderjamesking

    An interesting article with some very good points, although a bit too pro Play for my liking.

    Play Framework is a mess, the documentation is inconsistent or just missing for some versions and it’s overly complicated for what it actually does, I would not recommend using it from Java or Scala.

    A few additions to the Bad bullet points for Scala…

    – Breaking changes across versions

    – Tooling (IDE plugins are a million miles away from compared with those for Java)

    – Compilation – it’s slow, very slow

    – Syntax – too complicated and inconsistent

    – Static typing (especially when rendering HTML and building frontend apps)

    – SBT – possibly the worst build tool I’ve ever used

    For REST APIs or backend services I think Clojure/Java/JaxRs/DropWizard/Scala/Play are a good fit but I think they should be avoided when rendering HTML and building frontend apps.

    • Thanks for the feedback!

    • Jay Wren

      Don’t forget Scala Collections:

      • As a bad thing or a good thing, in your opinion? I’d actually put them in the Good column. There are a bunch of convenience functions that reduce boilerplate.

        • Jay Wren

          On the surface, they are great. Then you get into the details and things get nasty. See the video where the types in the docs are actually lying to you.

          • The collections definitely have issues. But I’ve personally never encountered these. Probably because of my novice-level uses. People like Paul are more likely to run into these things because he is smart enough to get into some of the dark corners.

          • martin odersky

            Hi James, nice article! I just wanted to give 2 cents on collections. I have so far had 250’000 people enrolled in my online courses, with all sorts of backgrounds, from beginner to expert. For these courses people have hit lots of problems, with SBT, with variance, with typos on the slides, the list goes on. We have a good record of the problems on the forums, and it takes on average two people full time to deal with them all. But not a single person was confused by the collections. Collection operations just did what people thought they should do and that was it.

          • alexanderjamesking

            The collections are a work of art, mainly thanks to Phil Bagwell’s paper on persistent data structures, and Rich Hickey’s implementation of them in Clojure.

            Even if the implementation of them in Scala is messy in places due to the complicated nature of types, they are still superb, it’s a shame there seems to be no plans to bring them into Java anytime soon.

      • IF you don’t understand the concept of functional paradigm please don’t criticize without having solid arguments.

        • Jay Wren

          That is a lot of assumption on your part. I am not criticizing the concept of functional paradigm. Please watch the video and respond to direct points, there are plenty of solid arguments there.

    • tmarthal

      If you think that any other java web framework is not a mess, then feel free to write up a blog post about it. Truth is, they all are. Play gets so many things right that it is easy to point out its minuscule flaws.

    • I’d add that these days – unless you have the problems that Twitter does at their current scale – rendering HTML on the server is just silly. Java is crackingly good at writing robust, efficient, stateless RESTful services that talk to data stores and integrate to readily accessible pre-written libraries. Let it focus on its strengths and let the clients be written in static (i.e.: easily cacheable) HTML with Knockout or Angular or whatever to power them. You need to do that for your mobile apps anyway, so you’re getting the HTML backend for free that way.

    • Nader Hadji Ghanbari

      It’s always a tradeoff. Nothing is perfect in this world (especially IT world!), but according to my (and probably many others’) experience Scala + Play is a very nice combination.

      – How can you fix the mistakes you’ve committed earlier without breaking backward compatibility? That’s probably why many languages suffer from flaws in their initial design/syntax/etc. In the case of Scala, at least for me, it hasn’t been a huge deal.

      – Your point about tooling in Scala world is true, especially compared to Java. But still compared to a lot of other languages out there, it’s a lot better. This is not a problem of the language per se, but the community. Maybe it needs contribution from community members to improve stuff.

      – Compilation is slower than Java because compiler is a lot smarter. So again this is a tradeoff but with keeping your modules at a reasonable size and exploiting incremental compiling this won’t be an issue (at least we haven’t faced any inconveniences yet by using sbt + Play + Scala combination).

      Anyway it’s not all benefits so if you value compile time over type inference, implicit arguments, and being able to model your types precisely with variance (and a multitude of other features), then probably Java is better than Scala.

    • ddsfan2

      Can’t say that I agree about the syntax or complaints about Scala’s static types, compared to Java of all things?

      Plus, I haven’t seen a Java build tool that was any less awful than sbt (why do none of these tools learn anything from make, or rake, I have no idea…)

      If you’re comparing against Haskell, ML, or Clojure, I can understand.

    • Steven Dobay

      “Breaking changes across versions”

      That was at the very beginning. I haven’t experienced it in the last 4 years.

      “‘Tooling (IDE plugins are a million miles away from compared with those for Java)”

      At my work I use eclipse with java ee and I think Intellij with the Scala plugin is a more far productive alternative.

      “Compilation – it’s slow, very slow”

      Choose one: you can code 1 hour longer or compile 30 seconds longer…

      “Syntax – too complicated and inconsistent”

      If you would understand (or you do) PLT or the problems created by the existence of various DSLs you would say this for java or almost any other language. Scala is a General Programming Language targeting almost every domain.

      “Static typing (especially when rendering HTML and building frontend apps)”

      Is this a bad thing?

      “SBT – possibly the worst build tool I’ve ever used”

      Still far faster than maven with larger projects but without the boilerplate.

      “For REST APIs or backend services I think
      Clojure/Java/JaxRs/DropWizard/Scala/Play are a good fit but I think they
      should be avoided when rendering HTML and building frontend apps.”

      Frontend apps are mostly created with primitive technologies(doesn’t require skills, beginners eat it), these languages aren’t invented for child’s play. But I think going with ScalaFX or Scala.js is easier than with the alternatives.

  • I think you should starting to figuring out why Walmart Canada switch to Play.
    There are a lot of inoperative and bureaucratic work dealing with all those java ee issues, you can’t lie to us and for yourself that time is money. When I’m taking much more time just setting things up otherwise than effectively coding there is something wrong.
    And not, we are not talking about experience here we are talking about inefficiency at core frameworks, IDE’s like Eclipse freezing a lot and several outdated design patterns.
    The world of java is moving and won’t be some support of closures in Java 8 will help changing this reality.
    Best regards.

    • You seem to know what you’re talking about, but your points would be better made if you dropped the aggressive tone and joined the conversation as a peer instead of a critic.

  • Play framework is not servlet based, so don’t try to put it in the same field as others. You can’t just deploy it on a weblogic, it won’t happen.

    • Michael_Sw

      There’s a plugin that lets you deploy it as a traditional .war. I’ve run a Play 2.1 application on Tomcat 7. I don’t know what the performance impact is, I was writing an app with a maximum concurrent user count of three. :)

  • An0nym0usC0ward

    Don’t even think about servlets, use a plain http server implementation to expose your service (a la node), and have a service registry available enterprise-wide (as a service, of course). Your app will always be a tiny service, start up fast, and all it will need in the environment will be a way to discover the service registry (one that’s not enterprisey, that is – or that part alone will be bigger than your entire service).

    Play is IMO a no-go – as is any other framework that mixes UI and server-side development. This mixing creates (or at least favors) coupling that should not be there. Instead, develop small services true to the Unix philosophy (do one thing only and do it well), and put UIs which are pure web clients on top of them (things which are just JS, HTML and CSS and can be loaded from a plain httpd server – caring again just about an entry point into the service registry).

    Added benefit for ops: all they have to do is add a wrapper setting the entry point to the service registry into the environment, maybe some ports to be used by the app, in order to deploy your app. The app can then go ahead and register itself as a service provider with the service registry, ask the service registry about services it needs to call etc. No complex setup that ops needs to perform, no ten pages deployment instructions, no huge monolithic application, no failures so complex that nobody can figure out the stack trace.

    The only thing that remains open is scaling and load balancing – but even this can be implemented as a service plus local agents on each of your machines – and voila, you have your own private cloud, without a need for complexity brought about by all the JEE APIs, no need for an additional, complex and often immature middleware stack. (Of course, there is a cost – such an infrastructure buys you ease of maintenance, reliability and scalability at the cost of increased network, CPU and memory usage – but given HW cost nowadays, I’d say that’s a bargain I’m happy to accept any time. Besides, cutting down on JEE APIs usage, you are likely to save so much computational overhead that the additional HW cost won’t be that high.)

    If done that way, you won’t even be aware that Java sucks in some regards – especially if you use 8.

    • Thanks for the feedback. Just one clarification… Play can be used solely as a back-end API server or as a front-end server or both. You don’t have to mix UI and services if you don’t want.

      • An0nym0usC0ward

        That’s why I said “or at least favors” such mixing.

  • TatuSaloranta

    Good stuff. One thing I’d append to “bad” list of Scala is lack of backwards compatibility — all new versions so far have caused major problems; well past time where language and its runtime would be expected to care about compatibility. And while it’s been promised to work going forward, that remains to be seen.

    • Jamie Allen

      Hi, Jamie from Typesafe. Could you share some of the backwards compatibility troubles you had upgrading from 2.10 to 2.11? Thanks!

  • Will Fleming

    Thanks for writing the post!

    One thing i’ll add is that if you want to work on a JVM language other than Java at a big stodgy enterprise there are options

    The above are all Clojure jobs – but there are plenty of Scala opportunities at big companies as well.

  • MGZ TV

    Good article. I left Java applets because IT was tired of dealing with slow servers. I then went .Net with C# and low and behold most of .NET and C# is now open source! Was thinking of trying Java again in case I need to live in a mixed world. Any ideas where I can catch up?

  • Luke deGruchy

    You mentioned Scala, Groovy, Clojure and Kotlin, but not Ceylon? I think Ceylon is at worst equivalent in stature to Kotlin as an alternative JVM language and it’s certainly been around longer:

    • I think Ceylon could be a good option but I don’t have any experience with it so I didn’t include it.

      • Luke deGruchy

        I recommend spending about 30 minutes or so reading the tour on the site
        I posted, and if not then the quick introduction. You won’t regret

  • Noah Yetter

    Mostly I agree with all of this, so two thumbs up.

    I do think there’s a reasonable case for sticky sessions though: simple cache locality. If a user is interacting with my app, and they’re pegged to one server amongst many, then whatever caching I do in that particular JVM is going to be more effective for that user. If I let them statelessly wander from server to server, I’m going to have to repeat the work of loading their user profile, and whatever Things they happen to be looking at or interacting with, on each server. You may suggest using a distributed cache like memcached, Terracotta, or Coherence as a solution, but that’s where the “simple” comes in. Those things work, but they’re hideously complex and they make reasoning about your application’s behavior very difficult. And ultimately they may not be much faster than just hitting the database again, since you still incur wire time. (This is in the context of a monolith, which is still a valid architecture for many apps. Microservices change this calculus pretty substantially.)

    • Although cycles and storage are both getting cheaper-enough that you may be better off going purely stateless, saving the development time, and throwing some of that extra money into more Redis servers or app servers or whatever. Developers are expensive, and keeping the software boringly simple almost always pays off at real-world scale for most companies.

  • Jonas Hutzenlaub

    nice write up. What do you mean by saying “Decoupled Schema & Code Changes”. Would you please give an example?

    • I remember Netflix talking about how they do this to support CD but I can’t find a reference. Basically there should be a minimum of 3 steps to do a schema change.
      1) Make the schema change
      2) Validate nothing brakes
      3) Make the code change that uses the new schema

      But sometimes the process has to be more steps if a pre-schema-change, code change is necessary to be able to do the schema change.

      Ultimately decoupling the two enables both to be more easily rolled back, especially if the schema change takes some amount of time to actually apply.

      Or alternately go schema-less with NoSQL. :)

  • Edgar Espina

    Great Article! and here is another alternative to Play & Dropwizard:

    Jooby follows all principles exposed here in this post :)

  • Even Java isn’t too bad for long-lived enterprise projects. I’ve very, very rarely come across truly terrible Java code, even when its written by relatively new developers many years ago. Intentionally or not, its one of the very few languages designed more for maintenance than for initial development (which is actually good since that’s where most software lives for most of its life).

    Even an only somewhat modern Jetty/Jersey/JAXB/Redis system can be developed so that you’re spending 95% of your time writing actual business logic, writing user- or developer-facing docs, etc. Getting that 95% up to 98% isn’t nearly as important as going from 25% to 95% was.

    Lambda syntax certainly does help to reduce remaining boilerplate, but most of the other issues aren’t nearly as big of a deal.

  • ‘Prototype in a scripting language. Throw away results and rewrite in Java for a long-lived app.’

    I think that summarizes my current thoughts on Java. I love the platform, but hate how long it takes me to produce something simple. Now, if I want to build something complex, it’s ideal because there’s not much of a loss in productivity from all the boilerplate.

    •, a good ol’ trusty prototyping environment. I am still using it for prototyping; working great in Textmate, Sublimetext and so on – with very minor editor specific tweaks. This is also one of the supported Scripting engines in my open source framework, for quickly wiring up webapp Controllers. I wish beanshell was still maintained.

      • You are nuts. Bean Shell is OK for performing some arbitrary stuff, but not for quickly prototyping a REST endpoint (unless I’ve missed something somewhere!).

    • c_world_poster

      Look at Spring Boot or Dropwizard. Even without those, it is not that tough to create something simple with Java.

      • Oh believe me, I’m familiar with both frameworks (I wrote a library that integrated Spring with Dropwizard before Spring Boot came around: More importantly, I’ve used Java for a very long time.

        The fact of the matter is, it’s still faster to prototype in other languages. Don’t get me wrong, I love the JVM and it’s ecosystem. It’s simply a chore to get things going.

        • c_world_poster

          Please share because whatever you are using must be magical to be faster than what I am currently doing with Spring Boot. ;) I don’t see how opening STS, click new project, select what you want and start coding is a chore. It is simply simple.

          FYI, i have used Java for a long time too :). I’ve also used C# and VB and … etc etc.

          With Java and Spring Boot I can easily get something started that can go from a prototype to something I won’t throw away. FYI, that includes using a JavaScript UI. Guess which one is a pain to use and which one is a Joy? ;)

          • Oh common on! This is comment bait! Listen, I understand the Enterprise Software Engineering’s belief that Java development is not terribly inefficient and that the rest of the world are a bunch of whiners (because in a sense, I think people overly complain about Java). But the fact is, it is much easier and faster to write an equivalent service in Node.js, Ruby or Python. You can use a existing skeleton/bootstrap and text editor to get started (no need for something bulky like STS).

            Just look at compilation times alone (oh wait, JavaScript doesn’t need to compile). Also, server starts are pretty damn fast in Node.js. Having written some serious applications in Dropwizard (with Spring as my IOC container), complex applications can take anywhere from 5-30s to start. Not a big deal until you add in the fact that this is usually done in association with a compilation (adding more time to the process).

            Now, I don’t mean to pick on Java entirely. Node.js doesn’t have anywhere near the debugging support I get when running a Java service inside STS or Intellij. So, perhaps in a complex application Java may be better suited for the task.

            Let’s be real, I’m not alone in this. To pretend like I’m crazy highlights how the Java community has not been honest with itself about problems relating to tooling and frameworks. Dropwizard and Spring Boot were developed out of a desire to depart from the original app-server paradigm in favor of lighter-weight frameworks. But these frameworks are still not as light weight as Express or Sinatra, etc.

          • c_world_poster

            It is not comment bait. I am saying – look at the video link. How much faster do yo want it?

            Lets just agree what is faster for you is not faster for me. Using a text editor slows many people down, including me. I don’t have much experience with Python or Ruby so i can’t say much about them. But using JS slows me waaay down even though it does not need recompiling (which is part of the issue).

            Without Spring Boot would Java be slow to prototype? I’ll go ahead and say yes – maybe to start but it ignores the bigger picture and after a certain point no. But that might just be me.

            “To pretend like I’m crazy highlights how the Java community has not been honest with itself about problems relating to tooling and frameworks.”

            You mean like how the other communities are not honest when they discuss productivity?.

            “You can use a existing skeleton/bootstrap and text editor to get started (no need for something bulky like STS).” If you want you can use a text editor with java – you will need maven or gradle. It still is pretty quick.

            If you count Groovy as a scripting language then i think we might be closer to agreement. :)

          • Well, to each their own. I don’t intend to convince anyone to move away from a platform they like. I do think there are languages where development can be done faster than Spring Boot. My original point though, was that one will typically develop a prototype on those platforms and eventually migrate to something like Spring Boot. We Java Developers often forget that many developers shy away from Enterprise complexity in favor of simpler (less capable) platforms. But in the end, most successful services get rewritten in C#, Java or C++.

  • I totally agree with the opening remarks about setting up a Java environment for development in the easiest way possible. That’s what motivates me to research and try friendlier avenues. Here’s one of my open source attempts:; shameless plug, I am the creator of Micro.

  • javawerks

    This is a Typesafe Play marketing article. Fair enough. Yet take it with a grain of salt.;)

    • I’m sorry you took it that way. That wasn’t my intention and I don’t even work at Typesafe anymore. The reason for the couple of Play references was because Play is one of the primary drivers of my transition from traditional Java to more modern practices. Dropwizard and a number of other frameworks also helped.

      • javawerks

        Interesting. Perhaps, that explains the semi-incoherent post, which was all over the map yet somehow pro-Play.

        Play is a niche framework. If it lost weight and played nice within a standard SBT project, it might gain more acceptance among engineers who need a lot of flexibility.

        Otherwise, lightweight, embeddable frameworks like Scalatra are much more attractive and practical to engineers in the real world. The same could be said of Jetty going back 15+ years. Funny how some things never change.

        Spray, which is being slowly but surely replaced by Akka.Http will eventually become a competitor to Scalatra and the like, but only if it drops the insanely verbose Spray configuration and it’s truly configurable and embeddable.

        Naturally, this is just my opinion based on decades of experience. I trust free expression is ok with you.;)

        All the best with your new venture. Just don’t put all your eggs in the Play basket, because you will lose. History guarantees it.;)

  • Excellent article! We teach many of these concepts in a practical way at

    • javawerks


  • Michal

    Nice article although I have few points:
    Servlets are blocking? AFAIK the asynchronous support has been there since version 3.0 and web containers like Tomcat support it with its non-blocking connector. Having Spring ‘s DeferredResult capabilities makes it easily usable in Spring based applications.

    I’ve started playing with play & scala after almost 10y in Java land and I must say for me it was an eye-opening experience. For the bad parts I’d vote for:
    – Tooling – having been used to Java tools, this feels like stone-age (manually adding imports, huh?, a need for documentation as content assist doesn’t help much). Idea 14 is the way but still..
    – Play feels so heavy. More than 200 jars in classpath for simple app by default? Where’s the micro in that.
    – Slow compilation, learning curve..
    – Maybe it’s just me but I always had troubles running template projects from activator UI

    • Thanks for the feedback.

      Servlets do now have the ability to be async but many servlet-based web frameworks haven’t exposed this. And Tomcat has had some bugs around this stuff. So yes, it is there but very few people use it for a variety of reasons.

      Scala Tooling with IntelliJ IDEA has been great for me.

      I just created a plain Play 2.3.7 app and ran `activator stage` and `ls -al target/universal/stage/lib/|wc -l` which says that for production there are 53 jars.

      • Michal Kascak

        Thanks for checking this.
        I ran activator stage and I have 122 jars in the lib folder. Play 2.3.5 with only dependencies to slick, postgres jdbc and silhouette. But I can see all the selenium and specs2 jars there so there’s probably something wrong. My sbt knowledge is limited to be able to tell.

        • My build.sbt contains:

          libraryDependencies ++= Seq(
          "" %% "play-slick" % "0.8.1",
          "org.postgresql" % "postgresql" % "9.3-1102-jdbc41"

          With Play 2.3.7 I am only getting 51 jars in the lib dir. You definitely shouldn’t be getting the dev and test dependencies in prod.

          • Michal Kascak

            I see. I found out that for me “com.mohiva” %% “play-silhouette” % “2.0-SNAPSHOT” is the culprit which drags a world of dependencies to the target.

  • GabrielKast

    It’s not java that sucks.
    It’s java projects

  • Steve Snodgrass

    Great post James. Really enjoyed it.

  • Gray Fox

    If you have the time to post all this,
    You are not working hard enough ..
    Or you just do not have any real problems to worry about ..
    That’s cool .. Just cut it out with the “java sucks” headlines ..
    They catch the attention and waste the time of people who work on
    massive, reliable and profitable Java systems ..

  • Tim Boudreau

    Servers that take more than 30 seconds to start suck? Nah. Servers that take more than 2 seconds to start suck. Try Netty, and avoid anything that thinks classpath scanning is a good idea.

  • Infiyaz Khalid

    Nice article but I’m finding it a little hard to digest the final theme of your write-up.

    So are you suggesting that Java sucks after all, and that Scala is the best way to go but Play is the easy way out?

    • I have used Play with Java & Scala to help make some of these things better. But I’m not saying that you should. It depends on many factors. There are many tools, frameworks, etc that you can use to address these sucky things. My whole point is that in the Java ecosystem there are many ways to fix these sucky parts.

  • Rob Hafernik

    Remember Joe Sondow’s pithy quote (on server-side architecture): “State is a bug.”

  • John E.

    I’ve been doing full-stack development with Node.js for the past four years and loving it. Currently I’m doing front-end development on top of an Enterprise Java back-end and it’s been fun to observe the differences between Node.js and Java.

    • Marius Kotsbak

      Have a look at Scala.JS: Then you have almost full Scala support for the client too.

  • Nice PoV piece, James

  • This was a good read. I think it’s important to point out something in the comments, though. From personal experience, Play! is great for building web /apps/. That is to say that there will be some use of the MVC paradigm. On the other hand, it is often overkill for simple RESTful services (Jersey + Jetty will do fine here).

    Likewise, I recommend users stay away from Play!’s Java framework and stick to Scala. It’s cleaner and *seems* better documented. Likewise, if you like Scala (like me! :)), the Jersey and Jetty stuff can also be easily done in a nearly identical fashion to the way it is done in Java.

  • Regarding Java (the language), there are so many features that are lacking that other languages, for example C#.

    No properties, no safe navigation (” ?. “), no delegates, no events.

    Streams (a la LINQ) are a nice addition though.

    To me it seems the JVM team is moving much better than the language team.

  • These are all things that companies should be doing, but it seems to me that any language could do this. All things being equal, doesn’t that still put Java behind?

    FWIW, I’m primarily a Java developer.

    • Yeah, these points could be generalized beyond Java but they are most prevalent in the Java ecosystem.

  • Chaz B.

    I can’t tell if this is supposed to be satire or not. :-/

    1) Why are there half a dozen ways to do the same thing and all of them incompatible with each other, and then how is this not sucky?

    2) Why would I put whether or not a DB is Java embeddable as a relevant characteristic of choosing one? That’s the least interesting part of one outside of fringe use cases.

    3) Many of the Great, Good, Bad points are just weird. Ignoring for a moment that “Reactive” is the 2nd dumbest branding of a thing that’s existed for decades. Why is Scala better for “Big Data” needs? Because Spark exists?

    4) Are these even the sucky parts of Java? I’m pretty sure the sucky part of Java is the specification spaghetti full of dozens of abstract class and interface meatballs that are necessary to DRY stitch together behaviors, even trivial ones, because nothing composes neatly without layer on top of layer of ever more abstract abstraction.

  • oregon111

    it takes me months to configure my machine — after that, sometimes programming is OK

    java sucks — and now we have to reinvent the wheel with new “tools”

    why not just do it in php – or .net?

  • ddsfan2

    I think the FRP libraries for Scala are absolutely dreadful, especially compared to Haskell’s offerings, but it’s not as if Java has anything to offer over it.

    I get that Martin Odersky was one of Paul Hudak’s graduate students (so I doubt that he had much to do with the “Reactive” manifesto), so it makes it even harder for me to understand why the Scala community picks solely event-driven temporally discrete actors that require manual notifications for the dataflow and claims those are a good example of “reactive”, when the whole point is to model state with continuous functions over time, where changes automatically propagate.

  • orubel

    Well come on… Scala in general just makes Java worse. Just use Groovy; it’s like Java’s prettier cousin that you actually WANT to fuck.

  • I’ve been trying to learn Scala coming from Java but the learning curve is pretty damned steep… I’m still (slowly) working through the Functional Programming Principles in Scala course on Coursera but Scala ( and functional programming ) is quite different… I guess I fell into the false belief that “Scala is like Java” … assert false.

    Further, SBT is really not working well for me and I’ve been struggling to build simple Scala projects with Maven / Gradle. I’ve heard how Scala will make help me become more productive than Java but it’s not been an easy start… :-/ my 2 cents.

    • You definitely can write Scala like Java but that doesn’t really embrace the power of FP.

      I’ve had my own uphill battle learning Scala. The surface area of it is huge. Atomic Scala definitely helped a lot.

      In the past I was frustrated with sbt but now it is working quite well for me due to improvements and better docs.

      • Interesting you mentioned AtomicScala… I was just watching a preso from Bruce Eckel about the book… I’ll check it out… Thanks James…

  • Paul Hanel

    Yes java sucks. I’m not a programmer. I just click on a link and I get a java script error whatever that means I don’t need to know. I only know that I have to reboot and pray. Yes java sucks.

    • Yura Nakonechnyy

      Paul, Java and Javascript are totally different languages that just happen to have similar names. So your experience proves that Javascript sucks which is totally true and has nothing to do with Java itself.

  • Dusty

    I wouldn’t use Java for web programming, I personally don’t care about web programming. Java as a desktop programming language is powerful, assuming you actually care about that. Yes it is verbose so what? So is C/C++ you don’t hear complaints coming from boilerplate coders. Also maybe most people just haven’t touched Java 8 yet but you can compile to jit and machine language using LLVM and GCJ.

  • Markus Engelhardt

    Interesting article, thanks for that.
    I am a Senior .NET Developer and I have to get going with JEE at present, and I have to admit that I am really deeply shocked, how complicated project setups with Java are.
    It really keeps me from actually getting started with practicing real code writing and that really is a turn off.
    Of course I understand the reasons behind this, but when you’re used to ‘simple’ .NET project setups, Java, its frameworks, its containers, servers, etc etc. can really drive you nuts.

  • Luffy


    I have one question to ask here. I’m a “Java” Developer from last couple of years. I always wonder how to deal with heap memory issue. As all of java developers know that to run a single java application you need big amount of heap memory in which a php developer can run more than 5 projects. I wonder how to deal with it. If we use REST web service in our website than can we prevent or decrease memory loss?

    • You should just split those projects onto separate servers. Maybe Heroku can make that easy…

      • Luffy

        Hi James, Thanks for replying. I just checked Heroku and yes It’s great powerful and easy too but my question that if use REST web service in our project to display content on front end does it cause less memory usage or not..

        • I think it could go either way. But usually REST services are stateless which helps reduce memory usage since often most memory usage in a traditional Java web app is for session state.

  • Play Framework… I hope you’re kidding. That thing is an awful crime against the dev community.

    • Yura Nakonechnyy

      Totally agree with you – they took initially wrong path of not following common rules of Java, that’s why it’s slowly dying now

  • Anthony Hildoer

    One of the measures of “suck” is how easy it is to to “use [a language] wrong”. Every language has ways to use it wrong. The issues then is that many would argue that the ratio of ways to use Java wrong to ways to use Java correctly is much higher than many other mainstream languages. I have been writing and selling software for nearly 20 years, and some languages which have fewer opportunities to use wrong are Scala, Go, JavaScript, Perl and PHP. I am not claiming these other languages are without fault, but on key issues of performance (runtime and space complexity), it is difficult not to use them correctly. I have trained countless entry level developers on all these languages, including Java, and the success rate for “using a language correctly” is orders of magnitude higher for the languages I mentioned above relative to Java, on enterprise, Internet scale applications.

    Even by your own assessment, your article here is several paragraphs long, with lots of details. That is what you think is required to use Java correctly, and your a proponent. The “use Scala/Go/JavaScript/Perl/PHP right” documentation I would write would be < 2 paragraphs for each language. That is based on the training of all those entry and jr level devs.

    Another point is if you look at the biggest Java shops in the world, they apparently all do it wrong as all their products suck down memory, CPU and take relatively forever to start. Some examples that come to mind are Intellij IDEA (which I love despite the Java issues), everything Atlassian makes, ElasticSearch, Cassandra, Crashplan, etc.

    I can't remember the last time I had to dig around for solutions to memory consumption and garbage collection issues for any commercially purchased, non-Java application. By contrast, I have to tweak the JVM for every single Java application I run on my workstation or servers, with the only exception being Minecraft.

    The terrible thing is that from a syntax point of view, Java is my favorite language. It just so happens that the JVM is the worst code execution experience I have ever seen, and I am even considering qBasic (MS DOS 6.22), Cobol and Pascal. No, I take that back. Ruby on Rails is the worst code execution experience I have had. JVM is a close second.

  • Pingback: Comparing Application Deployment: 2005 vs. 2015 – James Ward()

  • Maximilian Schmidt

    Great article!