Java Argument Files, Affiliations, And Lego

CodeFX Weekly #14 — 14th of April 2017

Hi everyone,

while working on that Java 9 migration (in case you wonder why it takes so long, it’s ~1'200 kLOC in ~400 Maven projects and I only work ~6 hours per week on it) I encountered an older Java feature that I only knew existed because I saw a Java 9 related change speed by in some post or mail: argument files.

I send this newsletter out every Friday. Yes, as an actual email. Subscribe!


Java Argument Files

What do you think happens when you execute the command javac @somefile? Here's what javac -help says (or on Java 9, thanks to the commitment to GNU-style command line options, the much saner javac --help):

@<filename> Read options and filenames from file

From the official documentation:

To shorten or simplify the javac command, you can specify one or more files that contain arguments to the javac command (except -J options). This enables you to create javac commands of any length on any operating system.
An argument file can include javac options and source file names in any combination. The arguments within a file can be separated by spaces or new line characters. If a file name contains embedded spaces, then put the whole file name in double quotation marks.

That’s actually pretty nice. One good use case is that you can collect compiler options in a specific file that you can separately commit to version control. I didn’t know about that until very recently because I never compile anything but demo projects by hand and I assume I’m not the only one.

On Java 9

Argument files get particularly interesting when you think about Java 9. The first thing to note is that on Java 9 java also accepts argument files. This might have a profound impact...

With the module system in play, it is likely that many projects need quite a few command line escapes like --add-modules, --add-reads, and --add-exports. This is true during compilation as well as at run time, where a few --add-opens might join the crowd. How do you want to keep them organized? I think argument files might be a good way to do that.

You might have one file with all the flags you need for compilation and another one with all the flags for running the application, maybe a third for running tests (or are those the same as at “regular” run time?). It looks like you could even use the same file for all cases because apparently javac accepts --add-opens as well. (I'm not sure why, given that --add-opens is targeted at reflection, a purely run-time concept. Interestingly enough javac --help does not list it either, so this might be a fluke.)

Even better, when you have a large number of subprojects that constitute an application, you can automatically merge subproject-specific files into a larger one required to successfully run the entire thing. Extending a launch script to reference an argument file and than maintain the latter separately sounds much cleaner than mucking about in a script every time you update or shed a troubling dependency requiring an escape hatch.

With Maven

I hope I got you really excited because the more you are… the more you will be able to share my disappointment that this doesn’t work with Maven.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<!-- NOPE! -->
<arg>@somefile</arg>
</compilerArgs>
</configuration>
</plugin>

To apply command line arguments, Maven needs to start the compiler as a separate process (called forking). But since any build tool is wont to create very long command lines they are at risk of bursting all limits of the underlying terminal or command prompt. The solution for that is… right, putting all those flags into a single argument file and calling javac with that. (I assume this is the reason why the compiler even has that feature and why java didn't up to now.) Here comes the kicker (quoting from the official docs again):

Use of the at sign (@) to recursively interpret files is not supported.

Argh. So if you do what I did above, Maven (or to be more precise the Plexus Compiler’s class JavacCompiler) puts the arguments it needs into a temporary argument file, including my @somefile, which javac then refuses to expand. Dead end.

I created a feature request for Plexus, let’s see what comes from it.


J9MS Standing Discount

In case you didn’t buy a copy of The Java 9 Module System during the first week, you can now get it with a standing discount of 37% with the code fccparlog any time you want.

I am still working on the feedback for the first five chapters, which included the wish for a tech comparison. If you want to know how the module system compares to build tools, OSGi, and Microservices, then watch this space. The free first chapter should include it soon.

Oh, did I mention that you can get the first chapter for free? I guess I didn’t, so let me do that now: The first chapter is free.


Affiliate Programs

I’m really not a friend of Amazon, or rather that part of the company that sends out physical products as it looks like they are routinely underpaying and even mistreating their employees. (Amazon headquarters doesn’t seem to be a relaxing place to work either but those employees are more empowered and can find other employers — unlike the warehousers, whose position on the job market is much worse.) That sucks! As a consequence I have been boycotting Amazon for years, buying there only very rarely (maybe once a year).

Then, a few weeks back, a reader told me that my glowing recommendation of A Deepness In The Sky caused him to buy that book and whether I ever considered earning money with affiliate links. I haven’t and judging by the size of my readership I could expect maybe a buck or two from each recommendation. Still, I am always up for experiments, so the idea wouldn’t quite leave me…

Which brought me back to Amazon, the biggest “international” (I’ll explain the scare quotes in a minute) market and one with a proper affiliate program to boot. I finished the Zones of Thought series and am in the middle of another book I wanted to write about, so I decided to try that affiliation thingy. This is where things get all fucked up …

But before I go there, I want to point out that I plan to remedy my moral qualms by giving half the affiliate income to the German union representing Amazon’s warehousers (if that’s possible) or some international labor organization. Amazon is a cool thing, they “just” need to be forced to pay more.

Amazon Affiliation Fuck-up

Did you ever follow a link to amazon.com only to find out that you can’t or don’t want to buy there so you navigate to your national variant and shop “locally”? What do you think happens if a poor sob wanted you to make him rich by affiliation and the original link included an ID that would give them a few percent of the money you spent? Surely Amazon tracks that, right? Pfft, you fool!

No, obviously the sob needs a separate associate account for each national shop (each creating a distinct ID) and when advertising a product needs to build links for each shop and make you click the right one. (There are actually services for the latter but I’m not yet sure I trust them.)

What? How THE FUCK is this up to par in the modern world? Can’t there be — I don’t know — a single entity, handing out unique IDs carrying the information from shop to shop via cookies or something? I’m surely suffering from Dunning-Kruger here but it can’t be that hard, can it?!

Eh, so I did that this morning, spending a few hours filling everything in. You would think that because you have to provide the exact same info over and over, there would be a way to just do it once. Nope. Well, a little bit, once you created an affiliate account in one EU country you can one-click-create ones on the other shops — not the payment information, though, because… oh fuck off, you can’t make this shit up! Seriously folks, you better buy whatever I recommend!

Kobo

To offer you an alternative to Amazon and also give you a way to buy non-Kindle ebooks I decided to look for another store. (Also, because it is obviously so much fun!) Not knowing where to start I just went with Kobo because I’ve used it for a while with one of their e-readers and am generally happy.

First screw-up: Password must be 8 to 12 characters (yes, upper bound!) with two letters and two digits. Other than that this seems to be a little more sane. You create a general account with Rakuten Linkshare (Rakuten is the company behind Kobo), which offers affiliation with all kinds of merchandisers and services, and then apply to individual merchants. They review the application and once they approve you can start selling.


SciFi

All of this filling and affiliating and associating and shit soured my mood, so I don’t feel like writing about the cool things I’m currently reading. I’ll push that to next week.


Lego

Is it weird to look forward to sorting Lego pieces? Because I was already practically giddy just thinking about that when still putting together the bucketwheel excavator. I mean, there are roughly 3'900 pieces — you don’t want to go through all of them to look for that one cogwheel, right? A system was needed! Oh, the joy.

Here it is:

Nice, eh? (Quick nerd test: If you nod, you’re one.)

In the mean time I started building the alternative model:

Not quite there yet…


Project Of The Week

A while back I wrote an article about how to correctly implement equals and the other day a commenter asked about how to properly test an implementation. I never used it myself but recommended checking out EqualsVerifier, which, if it does what it claims, should be pretty awesome.

Have you ever written an equals method, along with five screens of unit tests to test it? Or worse: not bothered to test it at all, because “the IDE generates it anyway”?
EqualsVerifier helps you. Testing equals can be as simple as:
@Test
public void equalsContract() {
EqualsVerifier.forClass(Foo.class).verify();
}
And EqualsVerifier even gives you 100% coverage on equals and hashCode methods.

Shots

Last but not least I want to recommend a cool easter-ish story Kevlin Henney (yes, the software dude) wrote a few years back, Milk Teeth and Chocolate Eggs. An excerpt:

A figure steps out from the shadows. Tailcoat, shirt, cravat and breeches cover fur. A worn leather satchel is slung over one shoulder. His yellow eyes are narrowed. His ears are tall, upright and alert. His face is crossed by a fresh scratch, his buck teeth stained by blood. Cat blood.
“It has been a long time, Easter Bunny.” He would dislike that name.
“Tooth Fairy.” She is used to it. “I was in the garden doing my rounds. I sensed a presence indoors…. It has been a long time.”
“Not long enough. You should have remained outside.”
His whiskers twitch. He looks her up and down. “Nice wand.”

Even burn-in-hell atheists like myself should enjoy that one.

so long … Nicolai


PS: Don’t forget to subscribe or recommend! :)