Avoid Publishing SNAPSHOTs to Nexus

3. July, 2018

Once in a while I’m running into people who deploy SNAPSHOT versions of Maven dependencies to a company-wide Nexus server with a job on a CI server. This is usually a very bad idea, especially when using branches.

Scenario: Two developers, John and Mary, each working in their own branch. They push their branches, CI builds them and they end up on Nexus.

Problem: Nexus doesn’t know or care about branches. Whichever job finishes last wins.

Often, this is not a problem. Now let’s add another project B. B depends on A.

As long as B depends on a release of A, everything is fine.

Now, John needs to make some changes in A. So he updates the dependency in B to A-x.y.z-SNAPSHOT. Everything is still fine, since Mary still uses the latest release of A.

Then Mary also creates a feature branch in her clone of A. That still doesn’t break anything because Maven caches SNAPSHOTs for a day.

The next morning, John makes a change to B and builds it.

This build might break when Mary’s CI job finished last!

The problem here, which can go unnoticed for years, is that Maven silently downloaded Mary’s version of A onto John’s computer and used that to compile. John will see the source code from his branch of A but the binaries will be something else.

Eventually, one of them will make a small changes which affects the others project. They will see MethodNotFoundException or get strange compile errors while the source code (which isn’t affected by this) will look perfectly fine or unit tests will break in odd ways.

That is the main reason why you shouldn’t deploy SNAPSHOT branches to a shared Maven repository: It creates a small chance for subtle bugs which will take a long time to find since your mental model (“I see the source, this is what I get”) will be wrong.

You can get away with publishing the master branch to Nexus (i.e. only a single branch with SNAPSHOTs will ever be published to Nexus).

Note: If your CI server shares local Maven repositories between projects, your builds can fail on the CI server for the same reason. Configure your CI server for per-project local repositories and wipe them before the build to avoid such issues for sure.


Binding one Instance to Two Interfaces in Guice

15. June, 2018

Sometimes, you need to bind one instance to two interfaces in Guice, for example:

interface Foo { ... }

interface Bar extends Foo { ... }

class FooBarImpl implements Bar { ... }

Let’s imaging FooBarImpl is a stateful bean which is saved in a session scope:

bind(Bar.class)
    .to(FooBarImpl.class)
    .in(Session.class);

This works when someone injects Bar but injecting Foo fails. There are two solutions for this: Bind Foo to Bar or use a provider method to transform the type.

Solution 1: Binding Interfaces

bind(Foo.class)
    .to(Bar.class);

This will use the mapping for Bar to satisfy requests for Foo.

Solution 2: Provider Method

Provider methods are a nice way to build complex objects from bound instances. In our case, we can map the types like so:

@Provides
@Session
public Foo fooProvider(Bar impl) {
    return impl;
}

Note: These approaches will put two keys into your scope but they will point to the same instance.


I’m Not a Robot (Rant)

31. December, 2017

Google’s “I’m not a robot” CAPTCHA is freaking me out.

I often spend minutes clicking stupid images only to be presented with more fucking images. It feels like it takes half an hour or more to just get the stupid thing to get out of the way so I can do whatever I came to do.

My main complaints:

  1. Is the frame of a street sign part of a street sign?
  2. Why do I get another page of images when I complete a task? Is the thing playing Sisyphus with me?
  3. Why does the thing suddenly change the game? First, I have to select pieces and click “Continue” and suddenly, it replaces pieces as I click and the button at the bottom behaves differently.
  4. Why can’t the thing remember me? Google and his friends know that it’s me! That’s their fucking business model! They make billions by tracking our movements on the web.
  5. The Google site boasts “Low friction, effortless interaction for your users.” There is no “File complaint” or support link anywhere. If it’s broken, guess who doesn’t care because they never hear about it? It’s one of these “it’s perfect – no one ever complained” situations.
  6. It puts me in an unbearable helpless situation where everything becomes a problem.

Just seeing the box turns me off by now. I’m starting to avoid web sites that use this. Patreon is about the last one where I force myself to endure the pain so I can help people. The support guys were nice and supportive, but there is little that they can do.


Stop on specific NullPointerException in Eclipse

20. December, 2017

TL;DR: Find the line where the exception occurs and then add a conditional breakpoint which checks the local variables for values that would trigger the exception.

In Eclipse, you can stop on any exception by using the menu Run -> “Add Java Exception Breakpoint…“.

That’s great but it doesn’t help when you want to stop on a certain exception on a certain line. It’s a big problem with code that uses exceptions for control flow – you could have thousands of those exceptions before you get to the one which you care about.

In my case, I had a NullPointerException in java.util.concurrent.ConcurrentHashMap:

    public V get(Object key) {
        Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
        int h = spread(key.hashCode()); <-------- key is null
        ...

I tried to add a conditional breakpoint here with the condition key == null but Eclipse complained that it couldn’t compile the expression (probably missing debug information).

The method was called from Jetty’s ClassInheritanceHandler, so I added a conditional breakpoint there.

That’s another reason to copy method results into local variables before using them.


Code Formatting by Example

15. December, 2017

People are starting to use Machine Learning to write better code.

One example is code formatting. Instead of painstakingly writing a parser and then rules which are to be applied to each node of the Abstract Syntax Tree (AST), the guys from Codebuff are using the “learn by example approach”. Just feed Codebuff with a couple of examples and it will learn to apply those implied rules to source code.

If you find something that looks bad, you don’t have to dig through dozens of pages of code formatter options or code formatter config files, just add more examples.

If you’re using Xtext, you can use the tool to write code formatters for you DSL: “Machine Learning Formatting with Xtext


Climate Change Visible

7. December, 2017

In the early days of by blog, almost 10 years ago, I posted “Why You Should Bother About 2°“. In the mean time, I’ve found another graphic that helps to understand that something is more broken than usual. Leisurely scroll down for a nice reminder of our history and how long things take to change.

xkcd: Earth Temperature Timeline

xkcd: Earth Temperature Timeline


Why Apple Sucks

10. November, 2017

People often ask my why I hate Apple products. My answer: “I’m not compatible.”

I was always looking for a good example what I mean. In my hands, Apple products crash, show weird behavior or important features are utterly broken.

Case in point: Apple has released an “everyone can write an App” course on iTunes. Here is what I did:

  1. I clicked the link
  2. itunes.apple.com opened in my web browser
  3. A few seconds, nothing happened
  4. Then I got a message box: “Do you want to open this link in iTunes?”
  5. Uhh… yes?
  6. iTunes opened. Showing my music library. Where is the product that you were supposed to open? Thanks for wasting 10 seconds of my life.
  7. Clicked the link again.
  8. Clicked “yes” again
  9. Now iTunes shows a page with “Swift Playgrounds”. Probably what I wanted to see, I’m not sure anymore.
  10. I click on the product.
  11. iTunes opens a web page in my browser. WTF???? What’s the point of having iTunes when it can’t even download something!?
  12. The web page says “Please install iTunes.”
  13. I give up.

That’s one example in which Apple products waste my time. It’s almost always like that.

Apple, I hate you.