Skip to main content

If you don't have an IBM ID and password, register here.

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. This profile includes the first name, last name, and display name you identified when you registered with developerWorks. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

 

Reading between the lines

Using Java to read bar codes and maintain an inventory database

Michael Abernethy, Software Engineer, IBM, Software Group
Michael Abernethy works as a Java Consultant for IBM based in Austin, TX.
Kulvir Bhogal (kbhogal@us.ibm.com), Software Engineer, IBM, Software Group
Kulvir Singh Bhogal
Kulvir Singh Bhogal works as an IBM consultant, devising and implementing Java-centric solutions at customer sites across the nation. You can contact Kulvir at kbhogal@us.ibm.com.

Summary:  This article takes a new look at UPC symbols and bar codes, and describes how you can use Java to read information from a UPC bar code. The authors explain how to expedite and organize your enterprise operations that revolve around an IBM DB2 database. The sample application described in the article includes downloadable code.

Date:  01 Jul 2002
Level:  Intermediate

Comments:  

Introduction

Look around you. What do you see? If you are a software programmer surrounded by other programmers, what you see can't be too pretty. We aren't referring to your cubicle neighbors, though; we are referring to bar codes. Bar codes have become ubiquitous, as our fast-paced economy has readily adopted the facilities offered by them. From tracking courier packages to issuing library books, bar codes are everywhere.

In this article we take a closer at these zebra-like creatures with their black and white lines, and show you how to use Java to expedite and organize enterprise operations that revolve around an IBM DB2 database.

To follow along with the article, you can download the jmart.jar code file, and also download barcode.zip, the required comm port files.


A look between the lines

There are many different types of bar codes. In this article, we focus on only one species -- UPC bar codes. If you were wondering, UPC stands for Universal Product Code. These codes were originally created to expedite operations in grocery store checkout lines and to track inventory. Because of their success, the idea spread like wildfire to other retail products.

UPCs for merchandise are actually issued by a company called the Uniform Code Council (UCC). In essence, you can think of the UCC as the agency that makes sure two different products do not have the same UPC code. Manufacturers have to apply to the UCC, and pay an annual fee, for permission to enter their system. In return, the UCC issues the manufacturer a manufacturer identification number.

UPC symbols usually have two parts:

  • A machine-readable bar code
  • A human-readable 12 digit UPC number

The first six digits of a UPC number are the manufacturer identification number. The next five digits are the item number. The manufacturer is in charge of making sure that no two of their products get the same item number. Every item the manufacturer sells needs to have a different item number. If there are different sizes of packaging or repackaging of items involved, then these instances also need their own unique item number.

So far, we have accounted for only 11 of the 12 digits of a UPC number. The last digit is a check digit. Without delving too deep into the science of bar codes, let us just leave it that the final digit ensures that UPC symbols scanned are scanned accurately. At this point, you might want to stop and scrutinize every UPC code you can get a hold of. Note that some of the UPC codes you see might not have 12 digits; the shorter ones are called zero-suppressed bar codes. The code accompanying this article won't address the shorter bar codes, per se, but you should be able to easily adapt our code to make things work for the abbreviated UPC codes.


Project overview

Now let's move on to our project. The only information housed in the UPC code is the manufacturer number and item number. Information about price and quantity on hand is not stored in the UPC symbol, which makes sense. Doing so would not be smart because the setup wouldn't be able to adapt to price changes and changes in inventory. So how do things work? When the scanner at a checkout line scans a UPC code, the cash register sends the scanned UPC code information to a point of sale (POS) computer. The POS computer then returns preprogrammed information about the scanned item, which can include price, quantity on hand, and other requested information.

The goal of our BarCodeScanner project is to emulate the setup described in the previous paragraph. Our code will work with data coming from a scanner that can be hooked up to your serial port. Using this data, you will be able to perform the operations that a stock boy would do at your local grocery store. We call our friendly neighborhood grocery store J*Mart. An IBM DB2 database will act as the back end, storing information about each item. Without further ado, let's begin.


The back end

We will be using a DB2 database as our back end, and will call it our point-of-sale (or POS) database. Go ahead and create your database by hitting the DB2 command line and issuing the following statement:

CREATE DB POSDB

Next, you'll need a table to house the data. The table below shows what you might need in your database:

Property nameExample valueDatabase column nameColumn type
Item Number12345ITEMNUMBERInteger
Manufacturer Identification Number123456MANUFACTURERNUMBERInteger
Product NameDoritosNAMEVarchar(40)
Manufacturer NameFrito-LayMANUFACTURERNAMEVarchar(40)
Quantity23QUANTITYInteger
Price1.67PRICEDecimal(5,2)

Issue the following statement to create the table:

Create Table posTable (Itemnumber Integer NOT NULL, ManufacturerNumber Integer NOT NULL, name varchar(40) NOT NULL, manufacturerName varchar(40) NOT NULL, quantity Integer NOT NULL, Price decimal(5,2) NOT NULL)

Notice that all of these database columns require that a new record have no null values.

The front end will be able to interact with the database in a number of different ways:

  • A new product can be entered into the database
  • An existing product can have its quantity updated
  • A product can be removed from the POS database entirely
  • Information can be obtained about existing products in the database

To accomplish the tasks, our Java program uses Java Database Connectivity (JDBC) to interact with the IBM DB2 database. At this point, it would be helpful for you to review the code in com.jmart.dbaccess (download the JAR file, if you haven't already done so). In particular, the class Database is a helper class that facilitates your connection to the DB2 database. The DatabaseAccess class is where we have the functions delInventory, qryInventory, and updInventory. The code is documented, so you should be able to figure out what is going on without too much heartache.

The methods have an incoming parameter type of InventoryData. The InventoryData class, part of the com.jmart.data package, is used throughout the project as a temporary housing facility to carry data back and forth. In Java programmer terminology, the InventoryData class can be thought of as a JavaBean component. The class acts as a communications conduit. Throughout our code, we take full advantage of the fact that objects in Java are passed by reference.

Required comm port files

To get the BarCodeScanner running, download the barcode.zip file and install the zipped files correctly.

comm.jar - contains the classes needed to run BarCodeScanner and other applications using serial ports or parallel ports. Make sure your classpath points at this JAR file when running the application.

javax.comm properties - place this file in your jre's lib directory.

win32comm.dll - place this file in your Windows directory (c:\Windows for example)

To make this program run on other OSs, search for your required dll file.


Scanning overview

Believe it or not, bar code scanning has been fairly standardized. Nowadays you can buy a handheld scanner that hooks up to the COM port of your PC. The scanner sends signals to the COM port that can be picked up by programs that are taught to listen to the incoming stream. The listening facility is rather primitive in the world of Java; but this very primitiveness makes our lives easier. An incoming scan is written as a byte array to the serial port, and it is up to the programmer to turn this into useful information.

The implementation of BarCodeScanner in itself is not very difficult. We know we're going to get the information and we know it's our job to turn it into a useful string we can parse for information. The javax.comm package provides the framework we need for collecting this information from the serial ports or parallel ports. (See Resources for more information on the javax.comm package.)

The javax.comm package is very basic in its handling of the ports and how information is retrieved from them. This is the 21st century and OO has come a long way since the old days of 1998. So, to make the bar code scanner behave like other established Java design models, we created an event/listener model for the bar code that fires a BarCodeEvent when each bar code is scanned. In this sense you can treat and code the bar code scanner much as you would a button press or a mouse click. Now, on with the code...

BarCodeScanner

The constructor for the BarCodeScanner class is responsible for creating the ports and setting all the parameters that the barcode scanner will work on. For the most part, these settings can be changed depending on the bar code scanner being used. Check your bar code scanner settings and adjust your code accordingly, or (preferably) remove them from the code and place them in a properties file.

CommPortIdentifier commPort = CommPortIdentifier.getPortIdentifier("COM1");
serialPort = (SerialPort)commPort.open("Barcode Scanner",3000);
inputStream = new BufferedReader (new InputStreamReader
  (new BufferedInputStream(serialPort.getInputStream())));
serialPort.setInputBufferSize(200);
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
serialPort.setSerialPortParams(BAUD_RATE, SerialPort.DATABITS_8, 
  SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

Now that the serial port is open and listening, we have to be ready to receive and interpret the barcodes read. The javax.comm provides its own event/listener interface for the port, the serialEvent() method, which notifies the class that there has been data posted to the buffer. It is now up to us to deal with this code.

We use the input stream to convert the byte array into a String. However, we have found the following issues while working with different barcode scanners and bar codes.

  • When dealing with a large bar code of more than about 100 characters, there are two serialEvents fired: the first with the buffer only partially filled, and the second with the buffer completely filled. The easiest way around this problem is to just disregard the event when the data in the buffer is not complete, and wait until it is complete to pass it to the listeners.
    	if (inputStream.available() < length)
    	    return;

  • Some bar code scanners will insert a carriage return at the end of each String read and/or a newline character. To correct this and keep our code usable for all bar codes, we create a buffer larger than the length of the bar code and only use the characters we're interested in when creating the String. In essence, this will ignore the extraneous characters some bar codes have at the end.
    	barCodeString = new String(buffer, 0, length);

Finally, as a bar code is read and converted, we have to notify all the listeners of the new String. But it takes time to cycle through all the barCodeScanned() methods of the listeners, particularly if they are querying the database (as it does in this case). In the Java Abstract Window Toolkit (AWT) model, clicking the button twice will not fire two ActionEvents if actionPerformed() has not been completed for the first event. This is unacceptable for a bar code scanner, because we can't afford to miss bar codes if they are read rapidly. Therefore, we have to spawn a new thread for every barcode read, and let this thread call and wait on the AWT thread, ensuring no bar codes are missed when "machine gunning" occurs.

Creating a new thread for every bar code read has a negative side -- the familiar threading issues rear their ugly heads: locks, monitors, race conditions, and all those things you tried to ignore at 2 a.m. in your college OS class the night before a program was due. But we digress... Although our demo application does not deal with these issues because the user will not be "machine gunning" the bar codes, in an application such as a checkout line, they can be solved by using thread-safe queues and synchronized blocks.


GUI

Although not the focus of the application, the simple GUI lets you see how an application can use the bar code scanner. It was set up using the Model-View-Controller (MVC) design. The main method to start the J*Mart application also resides in the InventoryView class.

Model

The InventoryData acts as the model in this application. It is a simple JavaBean that contains all the data we will need to pass from the View to the database.

View

InventoryView displays all the necessary information to run this application, and deals with certain scenarios:

  • A bar code is read that does not exist in the database. The application will then let the user input a name, price, and quantity to insert into the database.
    Bar code does not exist in database
    Does not exist in database
  • A bar code is read that does exist in the DB. It will display this information and then let the user add a certain number of inventory, delete a certain number of inventory, or delete the entire item from the DB.
    Bar code does exist in database
    Does exist in database

In these scenarios, the application lets a user completely control the inventory in the DB starting with an empty table.

Controller

The InventoryController acts as a gateway to the DatabaseAccess class, handles the BarCodeScanner, and passes the information to the InventoryView to display.


Conclusion

The goal of this small application is to show how you can develop an effective framework for working with bar codes, and retrieving the information from the database using what's provided in the bar code as a search key. Although this application is tailored for use in UPC symbols, with a few changes in the property settings the code for BarCodeScanner is completely reusable for any bar code setup and every bar code scanner on the market.



Downloads

NameSizeDownload method
i-barcode.zipHTTP
i-jmart.jarHTTP

Information about download methods


Resources

About the authors

Michael Abernethy works as a Java Consultant for IBM based in Austin, TX.

Kulvir Singh Bhogal

Kulvir Singh Bhogal works as an IBM consultant, devising and implementing Java-centric solutions at customer sites across the nation. You can contact Kulvir at kbhogal@us.ibm.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in

If you don't have an IBM ID and password, register here.


Forgot your IBM ID?


Forgot your password?
Change your password


By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. This profile includes the first name, last name, and display name you identified when you registered with developerWorks. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)


By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Sample IT projects
ArticleID=10207
ArticleTitle=Reading between the lines
publish-date=07012002
author1-email=mabernet@us.ibm.com
author1-email-cc=
author2-email=kbhogal@us.ibm.com
author2-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).