Hacker News new | comments | ask | show | jobs | submit login
Java Pain (tbray.org)
176 points by robin_reala on June 20, 2014 | hide | past | web | favorite | 144 comments

I'm seeing a lot of comments here along the lines of "this is just a problem Java newbies would have and this Tim Bray guy, whoever he is, doesn't want to take the time to learn the tools."

Well. True, to a degree, I suppose, but whoever this Tim Bray guy is adds some pretty important context. He co-authored the XML spec and was director of web technologies at Sun. You know, the people who made Java and promoted it as a web technology. Going out on a limb here, but it doesn't seem to me that the man is a Java newbie.

The point of Bray's rant, I'd suggest, is that these tools largely haven't gotten any easier since 2004. It frequently seems to be controversial in these parts to assert that it's worthwhile to make developer tools easy to use ("what you're complaining about is obviously easily addressed by whipping together something with bash, awk and sed and therefore isn't a pain point at all, you whiner"), which has always vaguely irritated me. A toolchain which requires you to wrangle it into place for every project is a toolchain which could benefit from usability improvements.

Agreed - and both Sun and Oracle have no cultural tradition of taking toolchain usability seriously. Installing updates is a complete trainwreck for almost every product they've ever released and that's one of the most basic tasks for a software vendor.

Fundamentally, I think the problem is arrogance – companies like Oracle or Sun historically assumed that their products are so important that it's someone's full-time job to deal with the rough edges, they've invested in training or reading massive doc dumps, etc. – familiar to anyone who's heard tales of mainframe operators with run books of canned solutions for each problem. Those HN commentators have the same blindspot.

In addition to usually being flat-out wrong, as the more common user is someone who just needs to do what should be a simple task which is blocking their actual real job, this ignores how profligately that mindset wastes other peoples' time and how it sets a dangerous long-term precedent where alternatives look attractive because everyone simply assumes e.g. Java, Solaris, Oracle's database etc. is hard to use and expensive.

  Installing updates is a complete trainwreck for almost
  every product they've ever released and that's one of the
  most basic tasks for a software vendor."
Then you haven't used Solaris 11, because in general, installing updates for the OS (and Java and many other things) is as simple as: pkg update

Also, your generalisations about 'no cultural tradition of taking toolchain usability seriously' are simply not true, I can show you plenty of tools where clearly whoever was working on them did care about usability.

With that said, I'm sure you're just venting and didn't mean what you said "literally"...

We have a joke around here that if you get a job at Oracle out of college the first project they put you on is the Oracle Universal Installer. The thing has never worked. If you want to entertain yourself for a couple of weeks, try installing the latest version of the Oracle Database on the latest version of Oracle Linux. Oh, and try doing something "advanced" like using a non-default block size for the database. There is a little check box for that, but it doesn't work. You'll end up hand-editing a lot of Perl and Korn shell scripts and essentially running (and re-running) the whole install by hand. It's ridiculous. Once you get it running the software is amazing. Obviously they are capable of writing an installer. They just don't care.

You're right, I have never used Solaris 11. I stopped at Solaris 10 because the TCO was too hard to justify versus Linux – the then-new updates bricking a whole shipment of servers was the final straw for us.

I've used both Sun and Oracle products since the mid-90s. The only one which I can recall seeming to respect my time was DTrace and maybe ZFS. Oracle is by far worse (updates shipped as a flat ZIP file with text instructions where to install them?) but both really left the impression that they assumed my time was cheaper than them hiring a packaging engineer.

My point was that you generalised your experience with one product to all things ever produced by either company. Generalisations are usually wrong.

You claimed none of their products ever showed any care about usability. Yet, at last check, they all had fairly extensive documentation, accessibility work done to them, and clearly do many things that consider the user experience.

Like I said, you're clearly venting. Consider being more constructive in your comments, or at least focusing on something specific instead of just ranting.

> My point was that you generalised your experience with one product to all things ever produced by either company. Generalisations are usually wrong.

Then it's a good thing I didn't do that. I've used a number of products from both company, ranging in price from free to suites which come with 6 figure annual support contracts.

> You claimed none of their products ever showed any care about usability. Yet, at last check, they all had fairly extensive documentation, accessibility work done to them, and clearly do many things that consider the user experience.

Allow me to quote what I actually said:

> both Sun and Oracle have no cultural tradition of taking toolchain usability seriously

That's not saying that they don't do things like, say, accessibility as required to get government contracts. What I was talking about is that all of the products seemed to assume that their product was so compelling that we would be willing to invest considerable resources doing the kind of support which other vendors do as part of their job.

At multiple employers, having spent 6-8 figures on Oracle database or enterprise business applications, we used to get things like critical security updates delivered as a ZIP file with instructions for where to copy files and what permissions to set them. Sure, it's not that hard to roll a pkg, rpm, etc. but why should every customer need to do that?

One of Oracle's big enterprise apps broke when IE8 was released because the latest version still shipped a 5+ year-old JavaScript library which performed some illegal DOM operations which were now validated even in IE7 compatibility mode. When I called support, they arrogantly told me that they don't test Microsoft's software for them and would test after it was released (which was weeks in the past at this point). About a week later, a manager called me asking for a copy of the patch which I had mentioned developing so they could distribute it to other customers who had the same problem.

During the year I spent supporting that mess, our half-million-year contract didn't once get a support engineer who fixed a problem, or could even troubleshoot it without my hand-holding them through reading the error messages and eventually entering a ticket. At every point the answer was to install the latest version or reinstall what we already had, which was a long manual process with tons of hand redundant configuration in many places (many daemons on many servers). Having documentation telling you to open an XML file here and add certain blocks of text with values matching this plist over there is extensive but is not usable.

Sun wasn't as bad but they weren't well organized. Brand new V40z servers arrive with Solaris 10. The updater rendered them unbootable. Support says to try the install again, which produces the same result. Calling our sales guy says this is a known problem and they can have a systems engineer help walk us through patching a bunch of stuff by hand so the updater won't break it – great, they're supporting us but … who's paying us for the hours spent on something which would literally take 5 minutes for their QA team to reproduce? If we had thousands of them and a strong case for Solaris we might have been able to justify the time investment but it took 20 minutes to have the systems in production running Debian Linux and we spent less time on OS support over the life of hardware than trying to get a core feature to work once.

Your clarifications are helpful, but your initial post certainly didn't imply such nuance. Regardless, I appreciate you taking the time to better explain your position.

With that said, I still disagree with your conclusion that Sun and Oracle has no "cultural tradition of taking toolchain usability seriously". Again, I strongly disagree and believe that does not apply to all products or projects.

Perhaps it doesn't apply to the degree that you want, but you are claiming that it doesn't exist at all, and I can assure you that was / is not the case based on people I know that have worked on many of those projects.

  At multiple employers, having spent 6-8 figures on Oracle
  database or enterprise business applications, we used to
  get things like critical security updates delivered as a
  ZIP file with instructions for where to copy files and
  what permissions to set them. Sure, it's not that hard to
  roll a pkg, rpm, etc. but why should every customer need
  to do that?
I completely agree that there should be a better update system; Sun was already working towards a better one which was first introduced in Solaris 11: The Image Packaging System. It was a new packaging system intended to simplify software updates for all of Sun's Solaris customers. The Glassfish team also chose to leverage for their product, distributing updates for Glassfish on Solaris, Windows, Linux and even Mac OS X via IPS.

  Sun wasn't ... it took 20 minutes to have the systems in
  production running Debian Linux and we spent less time on
  OS support over the life of hardware than trying to get a
  core feature to work once.
I sympathise, but again, this is why a completely new packaging and installation system was introduced in Solaris 11; to avoid problems like that. It helps ensure administrators have easy access to updates and always performs OS updates in a way that can be easily reverted if there's a problem.

If that's even mildly interesting to you, there's a website where both the FOSS source code for the new packaging system and the reasoning behind it is available:


The "Background Reading" section on that page has several helpful links that talk about the reasoning and philosophy behind it.

Solaris 11+ has a great update story compared to pretty much any UNIX-like system out there today. To update to the next release of the operating system, it's generally as simple as:

  pkg update
Now behind that simple command lies an entire set of processes that happen each time it is executed:

1) newest "package catalog" is retrieved from the configured package repositories (local and/or remote)

2) determines which packages are installed, and what all of the newer versions of those packages are

3) parses dependencies of all packages involved to establish the transitive closure of the dependency graph

4) transforms dependencies into a set of boolean statements that can be evaluated by minisat, the boolean satisfiability solver that's used

5) takes the solution (if one is available) provided by the solver and then maps that to the equivalent set of packages

6) retrieves package manifests for all packages that will be upgraded, added, or modified

7) determines differences between installed version and target version ensuring that only files that have changed between package versions are retrieved and only files that need to be updated, installed, or removed are modified

8) organises differences based on the order they need to be executed as a single set ignoring package boundaries, performing reference counting and conflict checking

9) retrieves only the files that will be upgraded or installed as part of the operation

10) determines if the operation can be safely performed on the live system, if it cannot, it will create a snapshot of the root filesystem and clone it, otherwise, it will take a snapshot of the filesystem as a precaution before execution

11) executes planned operation, executes commands that prepare new boot environment for use, etc.

12) if operation succeeds, new boot environment (if applicable) is activated

Or put more simply, when you execute 'pkg update' on Solaris 11+, generally only a copy of the system is updated. So if the update fails, you can just pick an older boot environment from the GRUB2 menu and be right back to a working system in moments.

The other big difference from all of this, as an example, is that the package system is capable of upgrading from any older version of Solaris to any newer version of Solaris.

There are no patch readmes or zip files; administrators just update from one version to the next -- the system figures out the rest. It even knows when upgrades require a firmware update.

Are you saying that every JDK install should come with Solaris? Or that operating systems should be built specifically to suppport java installation?

> Or that operating systems should be built specifically to suppport java installation?

Not even "specifically"; these updating woes rarely exist on platforms where you have a proper package manager (be it APT or YUM or Zypper or Pacman or Homebrew or whatever). Software devs shouldn't have to worry about writing updaters, since updating should be handled by the OS.

Exactly, Solaris 11 has a "proper" package manager: Network-based repositories, SAT-solver-based dependency management, signed packages, boot environments, etc.

In this case, every jdk install is available from the Solaris network package repository. Just like many Linux distros.

Linux distributions have the same problem so I don't understand the downvotes.

Last time I used Solaris they didn't have proper package names. Everything was VNDRacnm where the first part was the vendor second part acronym was a minified piece of some bit of information that would have been useful if it wasn't minified.

As I said, then you haven't used Solaris 11.

For example, the vim package name is 'editor/vim'. A similar naming scheme is used for almost every package.

I'm surprised he thinks the core platform should offer that, the JDK is large enough as it is thank you. Any number of countless application generators and libs make it easy. Even a quick glance at maven central would've answered his question.

In other words, Java wont search the internet for you.

I'd argue Maven is a giant kludge in the very spirit being argued about. If the underlying platform was better Maven would go away, but the existence of it prevents useful discussions about how to improve the underlying platform with "why aren't you using maven?" "because it sucks the life out of my soul" etc.

The other classic example is the increasingly popular multi-cursor editing editors, which should be a giant red flag over the lack of expression in the programming language. What happens is they make it almost tolerable, and the incentives to improve are thus diminished greatly, to the point the problem will be ignored by most.

But Maven is that toolchain. Invoking "java -cp ..." directly and complaining that it's complex is like turning off X11 and then complaining that it's harder to know which programs are available. A modern Java developer doesn't even need to know that the underlying interpreter happens to be called "java"; you can just work in Maven all the time and the conventions are sensible, the project infrastructure gets out of your way and you can get on with writing your code.

  > Maven is that toolchain. 
The idea that I need to use an external build tool because my language provided build tools are inadequate is the argument. It should not be as hard to use Java as it was 10 years ago by virtue of it's own improvement. It was a sharp edge then, and remains unnecessarily sharp today.

I'd fear any language provided build tool would risk becoming, like the python standard library, the place where modules go to die. I think what we've seen in recent years (particularly with the example of node.js) is that it's best for a language core to remain as small as possible, offloading most functionality into external libraries which can have their own release cycles and development philosophies, and even be replaced if need be. With maven we even have a nice layering of this: maven's core is small and most of the functionality is in modules, which can be updated or replaced without having to rewrite everything.

If we bundled maven or maven-like functionality into the Java core it would slow down the release schedule and destroy the productively competitive build tool ecosystem we have at the moment. What is it you think we'd gain?

>'d fear any language provided build tool would risk becoming, like the python standard library, the place where modules go to die....

I used to think this, but Go changed my mind. Like Go or not, its an excellent example of awesome tooling.

Go run/build/install/vet/test make my life to much easier than it used to be in Java/C/++ world (and C# tool because I'm not enslaved to VS for my teams tooling).

> I used to think this, but Go changed my mind. Like Go or not, its an excellent example of awesome tooling.

It's awesome tooling now. Most of the Python standard library was awesome when it was written. My concern is that it will stagnate as time goes on.

Let me quote from a C++ post: "We already "fixed" C++ largely by writing sane libraries, by having great compilers and IDEs, detecting issues with linters and so on."

This is how old languages work. You want a nice language? Switch! People get Scala working on Android, I hear.

> these tools largely haven't gotten any easier since 2004

That's not really true. I was doing professional Java development in 2004. Nowadays we have things like Dropwizard and Play.

It sounds like Bray was intentionally trying to use just the Oracle-provided tools and libraries. If he wanted to do that he'd been better off with Play. That's a single distribution designed for exactly his use case: simple OOTB text editor scripting, no compilation, no deployment, lots of stuff built in, just go.

While I have to put up the big blinking disclaimer that I'm not a Java programmer so take this with a box of salt, I'm not sure that really invalidates his point -- out of the box it's (apparently) far harder to build at least certain kinds of applications in Java that seem pretty trivial in other languages. I don't doubt your word that if he'd started with Play it would have been much easier to write that command line app that fetches a document with HTTPS, but downloading a third-party, self-described "high-velocity web framework" probably shouldn't be a recommended way to solve this problem.

It's not harder in Java.. if you use Play, which offers everything OOTB. How is that not a recommendable solution?

If you refuse to download Play out of some misguided principle that everything must be OOTB by the core language provider, then (a) that's arbitrary and (b) you're misunderstanding the design principle of low-level languages like Java and C++ that have enabled them to stick around for so long. They don't bake in (as many) opinions. Play does, which makes it easier OOTB. So does Dropwizard. Take your pick, they're all "Java". That's the beauty of it.. it can address a very wide range of needs from "I just want to get something done" to "I want to control every detail very close to the metal".

>True, to a degree, I suppose, but whoever this Tim Bray guy is adds some pretty important context. He co-authored the XML spec and was director of web technologies at Sun. You know, the people who made Java and promoted it as a web technology.

I'm partly joking, but I'd be hiding in shame if I had inflicted either of those things upon the world (that is the XML spec, and Java's web technologies, especially JSF and J2EE).

Now, it could just be me, I never found Tim Bray's posts interesting, and this is a case in point. The same blog post could have come from any random guy trying to run a Java app on the commandline. It might be a valid complaint for the status of java packages, but it's not insightful at all.

I have to agree: XML and J2EE are the fucking devil. I say this as someone who LIKES Java.

The confusing series of shell scripts most Java services (Cassandra, Kafka, Elasticearch) come wrapped in are a constant annoyance. Not only do they rarely if ever follow common shell command idioms, but trying to configure production services turns into tracing environment variables through a series of shell scripts sprinkled across my system.

It's nothing wrong with Java the language, but the platform just seems to make common UNIX best practices hard.

Edit: Just remembered Kafka is Scala, not Java, but I think it just supports my asssertion that the Java/JVM ecosystem just makes common best practices hard.

I was about to say "omg yes" -- as someone who writes piles of java code, this is a constant pain. However, look at the other tools: I run python out of a virtualenv. I use rvm to run multiple rubys, and that shit breaks all the time for me. (Or rather, I use it infrequently enough that I never learn it well enough; I use it for the first time again every 2-3 months).

That said, java is a special bit of shit. Those shell scripts are really complex. Most java shops have had problems with classpaths exceeding the 32k limit in shells! And java is yet another language where the morons who run it refuse to sand off some of the really sharp edges most likely because their heads are in their asses. To give two really simple examples:

1 - why the fuck can't I import a directory full of jars? eg

   --classpath ./lib/jars/*
or better yet, recursively descend

   --classpath ./lib/jars/**
For personal projects I often use ant just to manage the classpath.

2 - a nullsafe repeated dereference operator, like groovy. If I'm pulling out a.b.c.d out of a nested object, in real code, I have to say if

   String address = null;
   if (a != null)
     if (a.b != null)
       if(a.b.c != null)
          if(a.b.c.d != null)
            address = a.b.c.d.address;
   return address;
   // vs groovy
   String address = a?.b?.c?.d?.address;
this is the sort of minor irritant that you have to deal with all day long with deep class hierarchies, and there's some really low hanging fruit to instantly make my life better. sigh.

And for java, the combination of ant, maven, ivy, etc, are a special set of hell.

Re: classpath. You mean like this[1]?

[1] http://docs.oracle.com/javase/6/docs/technotes/tools/windows...

eh, you're quite right; it's the recursive I really need. oops. fta:

   Subdirectories are not searched recursively.
our solution has typically been to unjar all the libs and turn everything into a single giant jar, though this often leads to 100+M jars.

Yeah I use uberjars sometimes too. Java deployment in general is awkward/subpar. Some of the newer tech like dropwizard has helped with this, but it's still far from ideal.

Take a look at capsule[1] (I'm the author).

[1]: https://github.com/puniverse/capsule

This is what I was going to bring up. Also: hello again ;).

    1 - why can't I import a directory full of jars? eg
       --classpath ./lib/jars/*
    or better yet, recursively descend
       --classpath ./lib/jars/**
I usually do this as (in zsh):

   -cp "$(print -l ./lib/jars/**/*.jar | tr '\n' :)"

> why the fuck can't I import a directory full of jars?

Use the -Djava.ext.dirs command line flag to do it.

> like Groovy [...] String address = a?.b?.c?.d?.address

The Groovy backers have been talking for years every now and then about making ?. ripple though the . after it, so using a?.b.c.d.address would have the same effect as a?.b?.c?.d?.address , but nothing ever gets done. Better look for a language solution being actively maintained for its original purpose, instead of its backers going off on tangents looking to entangle itself in every pie.

Ad 2: Things evolve. If you stopped somwhere in the mid 90, you won't notice. But in Java 8 you can do null checking easily using Optional. Your example would be: String address = a.map(A::b).map(B::c).map(C::d).orElse("UNKNOWN");

I find that quite wordy, but thank you

"I use rvm to run multiple rubys, and that shit breaks all the time for me."

You are doing it wrong then.

There are several problems with RVM (and a lot of extra "magic" it does compared to say rbenv). Those have been discussed in the community for years.

So, besides the use of a BS idiom "you're doing it wrong", the parent comment doesn't add much value to the discussion.

Java just has a slow to adapt ecosystem, and that slowness seeps into everything Java touches. The fact that it's 2014 and there is no Java Repl highlights this.

Java is FINALLY adding Lambda functions (a lackluster implementation at that), but guess what? There already exist billions of lines of code written in "noun based" Java.

Our shop has a client that refuses to upgrade from Java 5. There's no chance in hell this project sees a Lambda.

Not just lambda functions, but functions period.

Java through 1.7 does not even have functions, the closest thing you can get is to write a class and give it a static method (which of course is not a closure).

AFAIK in Java 1.8 you still cannot define or call functions outside of a class. So it's still "noun based."

I find that as incredible as a FPL not containing an implementation of OOP

> trying to configure production services turns into tracing environment variables through a series of shell scripts sprinkled across my system

Yes, exactly.

      cat /proc/28014/environ | tr \\000 \\n
Is a way to show what you end up with, but I have yet to discover a good way to figure out how the environ was set there in the first place, having to fall back to strace'ing the full process tree from the startup script to figure out everything being launched and reading its source :(

One thing which I noticed during the Stripe CTF, where Node, Scala, and Go were all first time languages for me, was that the baseline experience of getting a dev environment assuming you have a Linux box is, in 2014, really freaking awesome. I was doing Java in 2004, and think it would probably take me half an hour going from zero to "minimum viable Java dev environment." I was hello worlding after maybe three console commands in Go/Node/etc.

This is partly a technology problem, partially a philosophy problem (Java does not have a scripting language heritage which counsels e.g. having a REPL or really obvious options for program invocation), and partly a marketing problem. I rather doubt that anyone at Oracle has the job "Make people's first experience with Java suck less." Web devs thankfully have standardized on "batteries included; max five minutes to install" for new platforms in the last few years (Rails strikes me as the conspicuous first example, and ironically is harder to install now than it used to be).

It still often takes me 30+ minutes to set up the environment for a new language, but that's mostly spent doing some reading on how to set it up "right" vs. just executing an apt-get.

Most of which comes down to the fact that official documentation for first-time users is somewhere on the spectrum of nonexistent to crappy. Many languages have pretty good tools for managing virtual environments and dependencies and such these days, but odds are that a new user won't find out about them for quite some time unless they know to go looking.

Play targets this exact pain point in Java. The "I want to script stuff easily in a text editor not an IDE and by invoking from the command line and/or by loading a web page without a compilation and deployment step" case.

Here's the manual page for calling an HTTPS service [1]. You just call WS.url("https://example.com").get(). And if it's a self-signed certificate then it's more or less one line in a config file to add it. That's about as easy as it gets short of deliberately making HTTPS insecure.

My experience: I very quickly evolved beyond this case and prefer the robustness of standard Java with the convenience of a bundle like Dropwizard [2]. Dropwizard packages up and glues together various best-of-breed libraries for building services. That was the real pain point for me, not so much having to use an IDE.

[1] http://www.playframework.com/documentation/2.3.x/WSQuickStar...

[2] http://dropwizard.io

Yup, he's right. Most of these problems have been solved with tools, not by the JDK. If I have arbitrary Java that I want to execute quickly I write a unit test, not a test program for precisely this reason.

I guess it doesn't slow me down, because I know the unit test 'trick', in the same way as I know how to get Light Table to execute arbitrary s-expressions to get around Clojures load times has meant that I'm far less obsessed with Clojures slow startup.

Its a problem, sure, but I don't think Java is broken, its just never had the CLI in mind.

If I have arbitrary Java that I want to execute quickly I write a unit test, not a test program for precisely this reason.

Exactly. JUnit is your "command line" (and your REPL) for Java.

There are many Java pains, both little and big. Most of them are more related to the JVM than the language.

It's why I still don't use Clojure significantly (or even ClojureScript), even though I really like the language. Things just break or simply never work and it appears random. Other environments I use get a lot less wrong (although node is pretty bad too).

That is true. Coming from Ruby world, you find that Java and the Clojure world have a lot of rough edges. But Clojure makes things as easy as possible. For example, reading from a file or a URL is still (slurp "https://"). It works fine on a stock OSX, Java 8 sdk and the latest clojure. Don't let such minor inconveniences discourage you from exploring Clojure/ClojureScript. The language is fascinating. I feel that learning and practicing clojure has made me a better developer.

Actually, Clojure improves the "Java experience" by quite a bit. As an example, leiningen as a build tool is quite usable, and it doesn't take much work to get a working (yes, also from the command line) application.

As for the JVM "just breaking", I can't agree with that. The JVM is an impressive piece of engineering and I'm very glad I can make use of it in Clojure, rather than deal with half-baked attempts at building yet another VM (reference counting, anyone?).

Interestingly, Leiningen is very much usable as a Maven replacement even for pure Java projects. I've tried it, it works fine. Just specify :java-source-paths in project.clj, and you get all the goodies like lein uberjar for free.

What's wrong with node? npm is a very polished package manager, and I'm frankly surprised how infrequently libraries with native bindings fail to build.

For as great as npm is it also has plenty of issues. `npm clear cache` is so common that I don't know why it even bothers with a cache.

I have always had the feeling that JVM is very stable, but I don't have much Java experience. Is that a wrong assumption?

Stable != Convenient to develop with.

Right, of course. Been working a lot with the Swift compiler so I was in some state of mind where I associated interpreter/compiler pain with faults and crashes :)

What pains come from the JVM? From my viewpoint the JVM is the best thing to come from the Java ecosystem.

Quite a lot of languages let's you do https, but just give you illusion of security. Not really validating it, which is trivial to spoof with certificate signed by "your own authority".

"The Most Dangerous Code in the World: Validating SSL Certificates in Non-Browser Software" https://www.cs.utexas.edu/~shmat/shmat_ccs12.pdf

Wow, does this imply that the Heartbleed bug might end up being even more damaging that previously thought? This paper shows that even if you've already revoked your old certs, many pieces of widely used software don't even bother validating them.

This has nothing to do with heartbleed. This means you can just generate certs on your own machine that a lot of software will simply accept.

Given Suns history with EJB 2.0, I would humbly submit that "ease of use", work out-of-the box etc should not be the default expectations with Java.

Having said that (snarky response) having worked with Java from 1.1, I think the language is moving in the right direction. The latest release (8) adds a ton of syntactic sugar and there is a real impetus towards easier more dev friendly features.

Plus Java needs a non-backwards compatible version soon. I suggest Java X be that where it gets rid of a lot of the cruft that has built up.

(Go Duke!)

Amen for breaking backwards compatibility. Needs to happen soon so the CRUFT can be cut out of JEE.

I see the appeal but... Python's long, slow march to widespread adoption of 3.x, and Perl 6's much less successful experience, both suggest there would be a lot of danger in that.

Yep; I'd rather just have Perl5 on Parrot than have to relearn Perl.

Not to mention that the O'Reilly book for Perl6+Parrot doesn't have a parrot, or even a camel. Deal-breaker right there ;)

Java is Enterprisey. Enterprises survive and operate only because they by freak accident at some point began earning way too much money. They employ lots of people who have no incentive to save work. We are paid for our work. Effects of the work are secondary to almost everybody in corporate world. Why trouble yourself with figuring out code if you can get paid all the same for tinkering with claspaths and poms for few days.

Java is a decent language but its developers have way too much tolerance for pointless hoopjumping.

As a java dev myself, I'd just like to say that I agree. If I want all of those extra features, I will just move to scala though.

The command line is a bit quirky, but I think like anything else in java, we typically solve it with libraries like args4j. It's not the best situation, and there's lots of ways to do things.

That being said, whether you consider this stockholm syndrome or not, I'm used to the quirkiness and it doesn't really affect my day to day. Could I be as productive had java had better features/support? yes. Is it that much of a non starter? I think it's just like any situation, use what makes sense for the job.

I know Java well, though I'm not primarily a developer. As a DevOps guy, there are a few places where I'd love to be able to write a quick program in Java to take advantage of one API or another, or to ensure compatibility with the app I'm trying to manage or what have you, but between the boilerplate, the classpath, the compilation step, and the awkward command line, it's almost never worth it, and I write it in Ruby or Bash instead.

The complaint about overstrict PKI libraries is spot on as well. Dealing with Java's PKI infrastructure for https URLs, etc, in a systems level setting where, you know what, sometimes the CN on the cert ain't gonna match the internal name, is a huge pain. Other languages are actually pretty bad about this too, and so too often I resort to calling out to curl -k because it'll just shut up and do what needs to be done.

It's clear that this is all because Java is built around the assumption that you're creating a big program and you're going to use an IDE and you're willing to deal with multiple steps before you have something that'll run on the server. That's fine and dandy. If the Java community wants Java to be more useful for smaller tasks, then Tim's complaints here are dead on target. But if not, I long ago gave up trying to use Java in this way, and I think Tim should do the same.

I'm not sure why Java is taking a bullet on this.

The default in other languages is often to not do any certificate validation.

That seems like the worse approach since no-one can tell their code is insecure. Maybe fine for a scripting tool, but I wouldn't want that on my production boxes.

I'm not sure why every language needs to be useful as a scripting tool. If there are things that help the common case and also scripting (eg classpaths being a pain), there's obviously an argument for "why the fuck hasn't this been fixed yet", but in other cases there are either fundamental tradeoffs or resource constraints.

> I'm not sure why every language needs to be useful as a scripting tool.

"Easy things should be easy, and hard things should be possible." -- Larry Wall

One of the reasons why I switched from Java to Perl. I didn't feel that easy things were easy in Java, and I don't run into enough hard problems on a daily basis to justify the verbosity and masochism involved.

On one hand, I'm happy you found something more productive.

On the other, I've spent a good chunk of time just reading other people's code, and I've come to appreciate really straight forward verbose code.

So I am a bit biased against the Perl I've seen, since it is generally not written with ease of understanding as a priority.

That's unfortunate. I try to keep my code (no matter what language, Perl included) as readable and tidy as possible for the sake of those reading the code in the future (myself included). While creatively stringing an incomprehensible stream of punctuation marks into a usable program is fun, I'm with you in agreeing that such coding styles should be avoided in anything that's not a one-off mental exercise.

That said, too much verbosity can introduce the same problem of unreadability by making important things harder to identify. There's an important balance between verbosity and terseness that should always be considered.

HTTP should be secure. A programmer should have to go out of their way if they want something designed to be secure to act in some other way.

No. HTTPS should be secure out of the box. If you want to break HTTPS then you should have to do work.

Without the code and error message, this is just a rant from some (famous) guy who can't/won't figure out his tools.

  First of al­l, it took me for­ev­er to fig­ure out the ja­va
  command-line in­can­ta­tions to tell it that it need­ed my
  project’s class files and the json.org li­brary (which I’d
  al­ready down­load­ed so I could com­pile the suck­er). Yeah,
  I used to know that stuff ten years ago, but there re­al­ly
  shouldn’t be any com­plex­i­ty here.
"in­can­ta­tions"? It's not wizardry.

Referring to things like unusual command line options as "incantations" has been reasonably common across the history of computer usage at least from the 1970s or so, if not earlier.

See: http://www.catb.org/jargon/html/I/incantation.html

  Especially used of tricks that are so poorly documented
  that they must be learned from a wizard.

what's so unusual about -cp (or "-classpath")

If you're familiar with most unix tools, you'd expect that to be --classpath.

If you need more than one addition, do you use a colon separated list (Unix), semicolon (Windows), or repeat it once per option? Does it expand ~ or do you need to

None of this is that hard but if you don't use this all the time it's easy for everyone's soup of almost-but-not-quite similar conventions to blur together and you waste time figuring it out.

In the Java world you have the added problem that the JVM has a legacy convention which doesn't follow any platform standard and the problem that many projects use different conventions so you probably also have a different set of rules for JVM options and the actual program options.

That's unixese for -c -p, for one. -C <classpath> or --classpath=<classpath> would be more typical.

Especially since the guy writing this literally wrote the XML spec. You'd think he's be good at deciphering "incantations".

I'm no fan of Java, but in this case I have to say I don't have much sympathy for Bray. Yes, running Java from the command line is a huge pain, especially if you haven't done it in ten years. Yes, it should be possible. But it can't be intuitive to everybody because people have conflicting ideas of what the intuitive thing would be. Yes, you will have to run "java -help" to figure it out, or package everything in a .jar file.

Every programming environment needs to know where to find it's libraries but it's not exactly rocket science - CLASSPATH, GEM_PATH, LOAD_PATH, GO_PATH etc. Just takes a few minutes to figure it out each time.

I was going to say: "first things first: learning your tools is the 1st step" but I see it's been told already.

This is just a rant and personally I can't sympathize with. How that is a newsworthy is another issue, though.

Seems like 2 issues:

1. Launching Java Programs can suck

2. Java defaults to secure on https requests.

First, on #2, yeah, really cant do anything here. If they didnt do this way, it would be reported as another vulnerability in the JVM that they would have to patch.

On #1, this is actually an old problem that I had worked on this years ago and i even published the solution in javanet (remember that?). If there is any interest in this, i can revive the project since its been dead for nearly 10 years. (http://web.archive.org/web/20070724060104/https://launcher.d...)

Basically I had a custom classloader read the lib dir that worked similarly to tomcat's classloader. Dump any jars/wars/etc in there that you want. All you had to do was tell me where the main class was (because a lot of jars have testing Main built into it and i wouldnt know which one you wanted to run).

How is the classpath problem different from manually specifying the -L and -I compiling that little c program exactly?

-L and -I are specified at compile time, so if you distribute/deploy a binary the runtime doesn't have to care (except in the case of dynamic linking - eek!)

$CLASSPATH is purely runtime, so it's all the fun of dynamic linking, all the time. Monolithic shaded JARs can solve this problem but introduce some of their own.

So someone has already gone to the effort of specifying them. In that case the analogous java situation is downloading a packaged jar and running java -jar mything.jar

Executable jar anyone? It's not that hard. Generating a standalone executable (a jar plus a bundled JRE) is not as simple as it should be, but it's certainly doable.

Everyone knows in theory that an actual command line is being run, and somewhere a main() method has kicked it all off, but the Java world is really dominated by enterprise tooling concerns, many levels of abstraction away from such things. Since people in the community don't spend much time thinking about it, it doesn't get the attention and polish it needs.

$CLASSPATH pain is one of the first things a new Java developer encounters — maybe the last, in many cases.

The only reason it's not quite as bad in .NET is that it can usually reference at least the framework in a well-known location.

But generally, whatever you call the problem that $CLASSPATH is designed to solve (assembly binding, reference resolution), it's an unsolved problem.

That's a feature, not a bug. It's part and parcel of dynamic linking and dependency management. You certainly can generate a monolithic executable jar file if you want.

not sure what .Net issues you're referring to, but they sound sort of obscure

In java to be able to crawl a https url you have to do the following - http://www.coderanch.com/t/134619/Security/JDK-trust-Certifi... Its easier in other languages but its not that hard in java. Just export certificate via IE and save to disk and from the jre/lib/security folder and issue one command keytool -import -alias mycert -keystore cacerts -file d:\mycert.cer. (default password is changeit) Done.

Why must you do that? And why you don't have to do that for environments of modern llanguags?

tl;dr: Other environments are insecure out of the box, and require applications specifically opt-in to security. Java requires you opt-out of the security.

HTTPS is built on top of PKI, which involves a list of trusted root authorities who verify that the certificate for blahblah.com is actually for blahblah.com. A self-signed certificate won't have that, and any application that doesn't validate that the certificate is signed by a trusted authority and not expired, etc. has no security.

If an application doesn't validate it's certificate, anybody sitting between you and the HTTPS server can step in between you and your traffic, give you a phony certificate, and then proxy all your "secure" traffic to the HTTPS server. And, of course, "sitting between you and the HTTPS server" means not only the NSA with their low-latency network specifically built to conduct these types of attacks, it also means the guy in the corner at Starbucks too (because WiFi is a radio).

Java only actually started checking if certificates were valid very recently (IIRC it was J7, r51). Prior to that, Java was just as lax as every other toolkit---probably specifically to address complaints like Bray's: "testing HTTPS is tough".

I never understood how trustworthy is cert that you could buy for 100$. What that certificate proves? That whoever signed the stuff had a 100$ at some point?

Besides ... why can't java just pull the certs out of the system (like you did manually) or ship with them like every browser does (I presume).

They typically ask that you perform some step of the transaction using an e-mail address tied to the domain, so it's not quite that terrible. The 700USD EV certs actually require corporate registration paperwork, tax IDs, etc. and are far closer to a credit check in terms of depth.

I agree that Java should use the certs the system provides, and that is a PITA to wrestle with keytool, but I also know that the self-signed cert that apache is using is not trusted by your PC either (so you've got work to do regardless).

Use a programmer testing framework (e.g. JUnit) even if this is an integration test, even if you're going to "ignore" it later. If you feel the need to create a main() method just to test your code, IMHO, it is a type of code smell and I think this should belong with your programmer tests.

C, CPP, Objective-C, and Swift are all broken too then...

Java runs as compiled bytecode, not interpreted script. Try "mvn exec:java". If you're not using Maven, you're likely making this ridiculously harder than it needs to be. (And yes, Maven sucks too, but it's also pretty good).

I do think a KeyBase Java client is a good idea though! Can't wait to see the results.

Java supports Runnable JARs. This bundles all dependencies into the JAR so you can just run:

  java -jar foobar.jar
And if it's a webapp, you can use something like Jersey so that the JAR itself if a webserver (launched from main function). And with Jersey+Grizzly you can make webapps that have zero XML config, btw.

Java's SSL handling is definitely annoying, though. But I think it's better than how other languages do it which is to simply bypass cert validation.

Also, I don't think it's fair to lump anything Android-related into complaints about Java. Google yoinked the Java syntax and the name and then added their own stack underneath.

My main pain point with Java is dependency management and builds. I don't like any of the systems out there. After years of Ant, Ivy, and Maven, I've just resigned myself to using Eclipse and downloading JARs manually, storing them with the code. It's ugly but not as ugly as Maven.

For those who can accept ant+ivy, I feel this is a stab in the right direction for console apps: https://github.com/djeikyb/simple-console-app

The script target creates a runnable shell script that has the jar and all dependencies embedded. The last step might be using packr[0] to also embed the java runtime.

[0]: https://github.com/libgdx/packr

Except you can't bundle "all dependencies" in when one of them is a JAR itself, can you? Unless you faff about with something like OneJAR (which is a work of genius but honestly, why is this even necessary?)

Are we seriously talking about this article? There's nothing here.

This is why I wrote this open source package


you can create a new project with from a maven archetype that has log4j and Spring set up for you. A centipede application contains a bunch of little command line applications that are defined simply by writing classes that implement CommandLineApplication; Spring automatically finds all of these and makes them available.

Centipede also defines a per-user configuration mechanism that means you have no excuse to hardwire database passwords into your version control.

Tim's rant is misplaced. The reason he can't connect to https://keybase.io using Java 7 is because Keybase have (mis)configured their server so it doesn't offer any cipher suites Java 7 could use.


You can see this in the SSL Labs simulator, in the bottom part of the report. Clicking "Java 7" will show the cipher suites available by default.

tl;dr: Missing certificate in keystore. It'd be helpful to know the details; it's hardly an issue limited to Java (although it's harder to bypass certificate checking than in, say, curl)

Yep, it happens in node. There you fix it with:


I'm confused about the HTTPS complaint. Is he trying to do something special? I'm pretty sure a simple HttpURLConnection object can read HTTPS links same as HTTP links.

I feel like I'm missing something.

This is what I hear: "I am java newb and it doesn't work!" . Its true that other languages are simpler but he is missing the point why in java you have explicitly set classpath. Java allows not only for having multiple versions of libraries on the system with no installation whatsoever, but allows running components requiring those different versions of same lib in the same process (OSGi).

> This is what I hear: "I am java newb and it doesn't work!"

You might want to check your hearing, because this is Tim Bray.

JavaScript with Node.js has those same features, but you can just type "node mycode.js".

So many people commenting here don't seem to have read the article. His comment is that Java can't connect to an SSL encrypted URL out of the box. He is saying that because it can't do this it can't be used for a basic command line app. He isn't complaining that it is hard to write a command line app in Java.

He is trying to load this URL: https://keybase.io/_/api/1.0/user/autocomplete.json?q=someth...

This URL is not self signed and loads fine as a valid cert in a browser. In the Java application it throws an exception about a bad handshake. I believe this is because Java 7 and 8 ship with less trusted certificate authorities than browsers do.

I forked his project and made it easy to run via the command line without Android if anyone wants to try it out: https://github.com/teacurran/KeybaseLib

Just clone the repo and execute "./run.sh something"

´./gradlew run´

Good luck trying to compile a C project without autotools/make either.

It's not that hard. I believe in you.

  gcc test.c -o test

That's not much of a C project. If that's the standard, then Java is a breeze:

javac Test.java

Easy to run, too:

java Test

javac Test.java

is equally easy and unrealistic.

You know there are tools other than `autotools` right? I use qmake and CMake all the time. it is mostly - "qmake && make" for me. Yes, you will have to learn CMake - but I don't think that is any different than learning ant/maven/gradle.

There is a lot of truth in what Tim says.

The Java + Clojure + JRuby ecosystem has been very good to me. That said, I have been spending more time writing Haskell code that anything else this year and being away frmm the JVM, and being able to build compact executables is a breath of fresh air, especially since I am looking at Haskell now more as a strongly typed and perhaps better Lisp.

> Dear Java: I can run Ru­by and Python and Go and JavaScript and C code from the com­mand line on my Mac. If I can’t run you, that means you’re bro­ken.

These were the types of problems dynamic JVM language Groovy was created back in 2003 to solve. If only Groovy had stuck to its knitting when the new management, er, took over from its creator a few years later, it would still be a solution. Unfortunately, Groovy diversified into providing CompileStatic tags to compete with Java, DSL syntax to compete with Maven, a MOP to compete with Rails, and AST annotation hooks to compete with Lisp. It's now become obsolete for its original purpose of JVM scripting, missing the Java 8 boat despite several years advance warning, as well as being at best 2nd fiddle but usually 9th fiddle at the stuff it tried diversifying into.

Also points for readers;

if you use intellij or another good ide it'll package it up for you with a execute script

(gradle's application/java plugin also do this)

manual classpath supplying is not advised

He's getting hamstrung by Java's intolerance of self-signed certs.

Which overriding is a bit of black magic.

IMHO, the best way to distribute java programs is create a single jar and the append that jar to this shell script:

    exec java $JAVA_OPTS -jar "$0" "$@"

really-executable-jars codifies this as a Maven plugin:


and then it doesnt run on windows...so much for run everywhere...

the best way to distribute a package is to create a proper package for each plateform and encapsulate any java "gimmick".

Right, you don't need the script as long as it's an executable jar, it will run fine with:

  java -jar Product.jar
If there are any native libraries then they need to be built into the jar, you could do one jar or one for each platform.

Windows? Really? I think there is an SNL skit in there somewhere for people still deploying server software on Windows.

Very true, I was thinking about this recently. Note there's no technical impediment to making the right tools, so if you're tempted, have a blast :) (Otherwise maybe I will)

you're kidding me, right?

rhodey@rhodey$ mvn package

rhodey@rhodey$ java -jar <package-name>.jar <command line options>

I don't think you read the article. You don't address his certificate issues. Your solution also requires writing a pom.xml which is non-trivial.

::head desk::

A pom.xml at least has a schema and tons of copy/paste examples. Every language sucks in it's own way.

Maven can generate one for you:

  mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Which is not trivial I suppose, but it is pretty easy to do.

to be fair this wouldn't work unless you have assembly/shade plugin configured.

If you're using eclipse or android studio there's just a single button that compiles and sends your app to the plugged in device, and uses your IDEs debugger, and a logcat window for the system log. There's also an emulator which you could use instead, which comes with the sdk.

So to run a smoke test using a language that's already installed on the computer Tim Bray is using, instead of just typing something easy into a terminal, he needs to download an entirely new application, set that up with his project (which isn't exactly a walk in the park), plug in his device, and then run it?

He wants to run a smoke test on a library he's writing. He doesn't want to run a full-blown application just to test his library, or to have to plug in a device to test his library. He wants to open up a terminal, type "java test KeybaseLib" (or something like that) and have it just work.

By far, the most uninteresting post of the day on HN. Some random guy ranting on trivial stuff.

He's not really random, at least I remembered his name. He may have invested enough into the XML, and since Java is pretty strongly into XML, perhaps also the Java world to feel justified venting about it.


"Dear Java: I can run Ru­by and Python and Go and JavaScript and C code from the com­mand line on my Mac." - to be fair most of those languages are scripting languages.

In my opinion, the difference between "scripting" languages and other languages hasn't been relevant for about a decade.

In my mind, the difference is clear: scripting language == has REPL == lets you treat it as a calculator, and (in practice) has a one-line, one-statement "hello, world".

So, I don't think go is a scripting language. It requires you to write a function and then call it before it will output anything.

So, forth, JavaScript, lisp, lua, perl, python, ruby do qualify as scripting languages in my book.

I think the issue is now more one of language philosophy than language implementation now.

In my mind languages tend to have an optimal code size where they work well, and what works at <1000 lines often does poorly at even 10k lines.

Scripting languages are those that the code gets thrown away when the application gets rewritten in C, C++, Java, C#, ... in order to perform properly.

They're programming languages that people use to solve programming problems, just as Java is.

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact