Recently I needed to generate a new id during migration of some data of a Golang application. Another application, written in Java, contained links to the first application’s data. So somehow I needed to update those links to point to that new id. I decided to use a “namespace name based UUID”, which is version 3 and 5 of the UUID spec. They generate a reproducable id based on given data. Since the UUID class of Java only supports v3, that was the way to go.

So first I generated the UUID in Go, that was straight forward using the github.com/satori/go.uuid package. someOldData1 + someOldData2 is a logical unique key of the data, which is available in both applications:

1
2
3
4
5
6
7
8
9
10
11
12

import (
...
"github.com/satori/go.uuid"
...
)

...

newId := uuid.NewV3(uuid.NamespaceURL, someOldData1 + someOldData2).String()

...

Next was to do the same in Java using the UUID class… but wow, that was more work than I expected:

  • Java’s UUID class has no constants for the predefined namespaces (like uuid.NamespaceURL above)
  • The nameUUIDFromBytes(byte[] name) method does not even take 2 parameters (namespace + name), but only one byte array.

It was hard to find any documentation on how to actually use this method, but finally I found out:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

import javax.xml.bind.DatatypeConverter;
import java.nio.charset.Charset;
import java.util.UUID;
...

private String calculateId(String someOldData1, String someOldData2) {

// this is the predefined UUID of the "URL" namespace, with removed dashes
String urlnamespace = "6ba7b8119dad11d180b400c04fd430c8";

String name = someOldData1 + someOldData2;

// now get the bytes of namespace and name
byte[] nsbytes = DatatypeConverter.parseHexBinary(urlnamespace);
byte[] namebytes = name.getBytes(Charset.forName("UTF-8"));

// concat both byte arrays
byte[] allBytes = new byte[nsbytes.length + namebytes.length];
System.arraycopy(nsbytes, 0, allBytes, 0, nsbytes.length);
System.arraycopy(namebytes, 0, allBytes, nsbytes.length, namebytes.length);

// that's what we need as parameter...
UUID uuid = UUID.nameUUIDFromBytes(allBytes);

return uuid.toString();
}

...

Happy coding :)

Comments

2017-01-29