GS1 DataMatrix codes in Java

TLDR; GS1 Datamatrix codes can be tricky. Use OkapiBarcode for easy handling.

Anyone who has had to deal with GS1 barcodes has most likely made an acquaintance with this document, or perhaps even this one if working more specifically with DataMatrix. If you found your way here then you most likely already know what DataMatrix codes look like, and you should also know that they consist of one to several fields, where a field essentially is a key value pair; the key consisting of 2-4 digits (called Application Identifier, or AI for short), and the value being a fixed or dynamic number of digits, depending on the Application Identifier.

Furthermore, you’ve likely also figured out that in order for the scanner/receiving system to know where fields of dynamic length end, the GS1 standards organisation has decided that a special character known as FNC1 (Function 1 Symbol Character) should be used. This is a non-printable character which should be replaced by the ASCII control character <GS> (Group Separator, ASCII character 29) when encoded; except of course in the first position, when it should be [d2, which in turn is encoded differently depending on the system. All in all, it’s really rather confusing, so let’s see how some ready-made solutions can help us.

Firstly, there are two primary ways of generating barcodes:

  1. Using barcode fonts
  2. Creating a bitmap

The benefit of barcode fonts is that they scale without a problem, so you can generate a barcode for anything from a stamp to a poster without any changes. The drawback, depending on how price sensitive you are, is that (to my knowledge) there are no free options, and they generally cost in the order of hundreds or thousands of US dollars. Libraries will generally also be of varying quality, but as long as you have the funds then this generally tends to be a good option. Search the web a bit and you’ll find several alternatives.

However, assuming that you’re not printing building-sized banners, then option number 2 should basically be able to cover most use cases. Let us therefore have a closer look at what’s available (this post is limited to looking at Javabased options). All options are licensed under the Apache 2 license (meaning you can use it freely; even commercially).

  • Barcode4J
  • ZXing
  • OkapiBarcode

If we start with Barcode4J then we quickly notice that its last release was version 2.0.1 in December of 2010. So let’s just go ahead and remove that from our list without further ado.

This leaves us with two potential candidates. ZXing certainly has the bigger community, but as it turns out, does not actually support GS1 encoding due to irregularities with the <GS> character mentioned above (or at least it didn’t at the time of writing).

Okapi Barcode on the other hand is built more as a standalone java application rather than a library, but is able to handle everything flawlessly – hooray! The only thing you need to keep in mind is that the Application Identifiers need to be enclosed in square brackets, for example like this: [21]12345678987654[3901]00000000590 (just in case you’re curious, AI 21 represents a serial number, and AI 3901 means “Amount payable – single monetary area”, i.e. the price of the product, where the 1 represents the number of decimals). This ensures that the <GS> character is properly encoded by Okapi.

The following code illustrates an example where we generate a DataMatrix and return it as a Base64 encoded String, including returning an image containing the text “Invalid Barcode” in case the input was incorrectly formatted:

Needless to say, the same method can be used to generate non-GS1-DataMatrix codes by simply setting the DataType to UTF8

and then throwing whatever URL or text at it that you feel like (I haven’t actually tested this myself, but I’m presuming it should work).

And as a bonus, here’s the code for generating an Interleaved 2 of 5 barcode as well:

All in all, a potentially complicated issue becomes surprisingly easy with the right tools. No need to read through the various GS1 specification documents. Good luck!

This Post Has 8 Comments

  1. Thanks for summarizing your findings for other’s benefit. I was looking for a GS1Parser, which would accept a string of characters and extract the Application identifiers and their values out of it. If you have come across a solution for this, please let me know.

    1. Hi Sandhya,

      Glad it could be of some use. I haven’t used any GS1 parser myself since I was only converting non-GS1 to GS1 before making a barcode out it. I was never on the receiving end that had to decode it. However, maybe this could be of help? https://github.com/PeterBrockfeld/BarcodeParser

  2. Hi,

    thank you for you notes.
    i’ve got a question regarding the ratio. i’m not understanding the management of square.
    the force square means that avoiding this i can create a rectangular data matrix that use a different data path or just that the image is in reality squared and without that it would be stretched in a different ratio?

    1. Hi Maruizio,

      Glad the post was to some help. I’m uncertain what you mean by “different data path”, could you explain a bit more?

      To be honest though, my knowledge regarding this stretches only as far as what I experienced while developing this. What I saw then is that there is a certain breakpoint (related to the amount of data) at which the library would rather output a rectangle than a square, and by setting forceSquare(true) I was able to make it output squares for a bigger amount of data, but still only up to a certain point. Not setting it to true – at least as far as I experienced it – simply pushes that boundary a bit, so that you might get rectangles with a smaller amount of data than otherwise. The exact details of the algorithm in the library that decides on square or rectangle are unknown to me, I’m afraid.

  3. Hi Karl,
    Thanks for the wonderful post. This definitely helps a lot of people.
    I tried the example and I am able to create the 2D Barcode but it is not scan able.

    Just wanted to know what should I change in this piece of code so that it is scan able?

    1. Hi Roy,

      Thank you for the comment. Hard to say what you might need to change without knowing more about the actual setup you’re using, including the kind of scanner. Straight off the bat I would guess that maybe your scanner is expecting data encoded in a particular way that doesn’t correspond with what’s being outputted by the code above? Feel free to send me an email if you want to get into more detail, and I’ll see what I can do (no promises).

  4. Hi Karl,

    Thank you so much for the post! I was struggling to find any documentation on OkapiBarcode and your code snippet was immensely helpful – especially the formatting of the AI in the content string (the fact that you use brackets). I was wondering about your comment re: “Okapi Barcode on the other hand is built more as a standalone java application rather than a library” – I see that your example is a standalone application, however, I had no issues using it within the context of a web application as a Maven dependency. Is there any issues you’re aware of that I could run into (eg thread safety issues, etc)?

    1. Hi Staci,

      Thank you for your comment. I’m glad the blog post was of use!

      The simple answer is that no, I don’t know of/think you will have any issues that you might run into as a result of running it in the context of a web application. The main difference as far as I’m concerned is that the standalone java application includes a UI and related code that bloats your own application unless you’ve extracted only the necessary bits, but thread safety and general functionality should not be a problem.

Leave a Reply

Close Menu