Generating and Reading QR Codes for Products in Java

QR codes are essential for product identification, inventory tracking, and customer engagement. This comprehensive guide covers generating, reading, and managing QR codes for products in Java applications.

Architecture Overview

Product Data → QR Code Generator → QR Code Image
→ Encoded URL/Data → Product Information
QR Code Image → QR Code Reader → Decoded Data → Product Lookup

Dependencies Setup

Maven Dependencies

<properties>
<zxing.version>3.5.1</zxing.version>
<barcode4j.version>2.1</barcode4j.version>
<boofcv.version>0.41</boofcv.version>
</properties>
<dependencies>
<!-- ZXing Core Library -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>${zxing.version}</version>
</dependency>
<!-- ZXing JavaSE Extension for GUI -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>${zxing.version}</version>
</dependency>
<!-- Alternative: BoofCV for advanced QR processing -->
<dependency>
<groupId>org.boofcv</groupId>
<artifactId>boofcv-core</artifactId>
<version>${boofcv.version}</version>
</dependency>
<!-- Image processing -->
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-core</artifactId>
<version>3.9.4</version>
</dependency>
</dependencies>

Configuration Properties

# QR Code Configuration
qr.code.width=300
qr.code.height=300
qr.code.format=png
qr.code.charset=UTF-8
# Product QR Content Template
qr.product.url.template=https://yourdomain.com/products/{productId}
qr.product.data.template=PRODUCT:{productId}:{sku}
# Storage Paths
qr.storage.path=/var/www/qrcodes/
qr.backup.path=/backup/qrcodes/

Core QR Code Service

1. Product QR Code Generator

package com.yourapp.qrcode;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@Service
public class ProductQRCodeService {
@Value("${qr.code.width:300}")
private int qrWidth;
@Value("${qr.code.height:300}")
private int qrHeight;
@Value("${qr.storage.path:/tmp/qrcodes}")
private String storagePath;
private final QRCodeWriter qrCodeWriter;
public ProductQRCodeService() {
this.qrCodeWriter = new QRCodeWriter();
}
/**
* Generate QR code for product with basic information
*/
public byte[] generateProductQRCode(String productId, String productName, String sku) 
throws WriterException, IOException {
String qrContent = buildProductQRContent(productId, productName, sku);
return generateQRCodeImage(qrContent, qrWidth, qrHeight);
}
/**
* Generate QR code with product URL
*/
public byte[] generateProductQRCodeWithURL(String productId, String baseUrl) 
throws WriterException, IOException {
String url = baseUrl + "/products/" + productId;
return generateQRCodeImage(url, qrWidth, qrHeight);
}
/**
* Generate QR code with custom product data
*/
public byte[] generateProductQRCode(ProductQRData productData) 
throws WriterException, IOException {
String qrContent = buildCustomProductContent(productData);
return generateQRCodeImage(qrContent, qrWidth, qrHeight);
}
/**
* Generate QR code with logo (branded QR code)
*/
public byte[] generateBrandedQRCode(String productId, String productName, 
byte[] logoBytes) throws WriterException, IOException {
String qrContent = buildProductQRContent(productId, productName, null);
// Generate base QR code
BufferedImage qrImage = generateQRCodeBufferedImage(qrContent, qrWidth, qrHeight);
// Add logo
return addLogoToQRCode(qrImage, logoBytes);
}
/**
* Generate and save QR code to file system
*/
public String generateAndSaveQRCode(ProductQRData productData, String filename) 
throws IOException, WriterException {
byte[] qrCode = generateProductQRCode(productData);
Path directory = Paths.get(storagePath);
// Create directory if not exists
if (!Files.exists(directory)) {
Files.createDirectories(directory);
}
Path filePath = directory.resolve(filename + ".png");
Files.write(filePath, qrCode);
return filePath.toString();
}
/**
* Generate QR code as Base64 string for web display
*/
public String generateQRCodeBase64(String productId, String productName, String sku) {
try {
byte[] qrCode = generateProductQRCode(productId, productName, sku);
String base64 = Base64.getEncoder().encodeToString(qrCode);
return "data:image/png;base64," + base64;
} catch (Exception e) {
throw new RuntimeException("Failed to generate QR code", e);
}
}
private byte[] generateQRCodeImage(String text, int width, int height) 
throws WriterException, IOException {
BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height);
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
MatrixToImageWriter.writeToStream(bitMatrix, "PNG", outputStream);
return outputStream.toByteArray();
}
}
private BufferedImage generateQRCodeBufferedImage(String text, int width, int height) 
throws WriterException {
BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height);
return MatrixToImageWriter.toBufferedImage(bitMatrix);
}
private byte[] addLogoToQRCode(BufferedImage qrImage, byte[] logoBytes) throws IOException {
// Read logo image
BufferedImage logoImage = ImageIO.read(new java.io.ByteArrayInputStream(logoBytes));
// Calculate logo dimensions (20% of QR code size)
int logoWidth = qrImage.getWidth() / 5;
int logoHeight = qrImage.getHeight() / 5;
// Resize logo
BufferedImage resizedLogo = new BufferedImage(logoWidth, logoHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = resizedLogo.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(logoImage, 0, 0, logoWidth, logoHeight, null);
g.dispose();
// Calculate position to center logo
int x = (qrImage.getWidth() - logoWidth) / 2;
int y = (qrImage.getHeight() - logoHeight) / 2;
// Combine QR code and logo
Graphics2D combined = qrImage.createGraphics();
combined.drawImage(resizedLogo, x, y, null);
combined.dispose();
// Convert to byte array
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
ImageIO.write(qrImage, "PNG", outputStream);
return outputStream.toByteArray();
}
}
private String buildProductQRContent(String productId, String productName, String sku) {
Map<String, String> data = new HashMap<>();
data.put("productId", productId);
data.put("productName", productName != null ? productName : "");
data.put("sku", sku != null ? sku : "");
data.put("timestamp", String.valueOf(System.currentTimeMillis()));
return "PRODUCT:" + productId + 
"|NAME:" + (productName != null ? productName.replace("|", "") : "") +
"|SKU:" + (sku != null ? sku : "") +
"|TS:" + System.currentTimeMillis();
}
private String buildCustomProductContent(ProductQRData productData) {
StringBuilder sb = new StringBuilder();
sb.append("PRODUCT_DATA:");
sb.append("ID:").append(productData.getProductId()).append("|");
sb.append("SKU:").append(productData.getSku()).append("|");
sb.append("NAME:").append(productData.getProductName().replace("|", "")).append("|");
sb.append("CATEGORY:").append(productData.getCategory()).append("|");
sb.append("PRICE:").append(productData.getPrice()).append("|");
sb.append("BATCH:").append(productData.getBatchNumber()).append("|");
sb.append("EXPIRY:").append(productData.getExpiryDate()).append("|");
sb.append("TS:").append(System.currentTimeMillis());
return sb.toString();
}
}

2. Product QR Data Model

package com.yourapp.qrcode;
import java.time.LocalDate;
public class ProductQRData {
private String productId;
private String sku;
private String productName;
private String category;
private double price;
private String batchNumber;
private LocalDate expiryDate;
private String manufacturer;
private String weight;
private String dimensions;
// Constructors
public ProductQRData() {}
public ProductQRData(String productId, String sku, String productName) {
this.productId = productId;
this.sku = sku;
this.productName = productName;
}
// Getters and Setters
public String getProductId() { return productId; }
public void setProductId(String productId) { this.productId = productId; }
public String getSku() { return sku; }
public void setSku(String sku) { this.sku = sku; }
public String getProductName() { return productName; }
public void setProductName(String productName) { this.productName = productName; }
public String getCategory() { return category; }
public void setCategory(String category) { this.category = category; }
public double getPrice() { return price; }
public void setPrice(double price) { this.price = price; }
public String getBatchNumber() { return batchNumber; }
public void setBatchNumber(String batchNumber) { this.batchNumber = batchNumber; }
public LocalDate getExpiryDate() { return expiryDate; }
public void setExpiryDate(LocalDate expiryDate) { this.expiryDate = expiryDate; }
public String getManufacturer() { return manufacturer; }
public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; }
public String getWeight() { return weight; }
public void setWeight(String weight) { this.weight = weight; }
public String getDimensions() { return dimensions; }
public void setDimensions(String dimensions) { this.dimensions = dimensions; }
@Override
public String toString() {
return "ProductQRData{" +
"productId='" + productId + '\'' +
", sku='" + sku + '\'' +
", productName='" + productName + '\'' +
", category='" + category + '\'' +
", price=" + price +
", batchNumber='" + batchNumber + '\'' +
", expiryDate=" + expiryDate +
'}';
}
}

QR Code Reader Service

1. Product QR Code Reader

package com.yourapp.qrcode;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.multi.qrcode.QRCodeMultiReader;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Service
public class ProductQRCodeReader {
private final Map<DecodeHintType, Object> decodeHints;
public ProductQRCodeReader() {
decodeHints = new EnumMap<>(DecodeHintType.class);
decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
decodeHints.put(DecodeHintType.POSSIBLE_FORMATS, Collections.singletonList(BarcodeFormat.QR_CODE));
// Support multiple QR codes in one image
decodeHints.put(DecodeHintType.ALSO_INVERTED, Boolean.TRUE);
}
/**
* Read QR code from byte array
*/
public ProductQRData readProductQRCode(byte[] imageData) throws IOException, NotFoundException {
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(imageData)) {
BufferedImage image = ImageIO.read(inputStream);
return readProductQRCode(image);
}
}
/**
* Read QR code from BufferedImage
*/
public ProductQRData readProductQRCode(BufferedImage image) throws NotFoundException {
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result;
try {
// Try with multi-reader first for multiple QR codes
QRCodeMultiReader multiReader = new QRCodeMultiReader();
Result[] results = multiReader.decodeMultiple(bitmap, decodeHints);
result = results[0]; // Take first result for now
} catch (NotFoundException e) {
// Fall back to single QR code reader
QRCodeReader reader = new QRCodeReader();
result = reader.decode(bitmap, decodeHints);
}
return parseProductQRContent(result.getText());
}
/**
* Read QR code from file path
*/
public ProductQRData readProductQRCode(String filePath) throws IOException, NotFoundException {
BufferedImage image = ImageIO.read(new java.io.File(filePath));
return readProductQRCode(image);
}
/**
* Read QR code from URL
*/
public ProductQRData readProductQRCodeFromURL(String imageUrl) throws IOException, NotFoundException {
try (InputStream inputStream = new URL(imageUrl).openStream()) {
BufferedImage image = ImageIO.read(inputStream);
return readProductQRCode(image);
}
}
/**
* Read multiple QR codes from single image
*/
public List<ProductQRData> readMultipleProductQRCodes(byte[] imageData) 
throws IOException, NotFoundException {
List<ProductQRData> products = new ArrayList<>();
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(imageData)) {
BufferedImage image = ImageIO.read(inputStream);
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
QRCodeMultiReader multiReader = new QRCodeMultiReader();
Result[] results = multiReader.decodeMultiple(bitmap, decodeHints);
for (Result result : results) {
try {
ProductQRData productData = parseProductQRContent(result.getText());
products.add(productData);
} catch (Exception e) {
// Log error but continue processing other QR codes
System.err.println("Failed to parse QR content: " + result.getText());
}
}
}
return products;
}
/**
* Parse product data from QR code content
*/
private ProductQRData parseProductQRContent(String qrContent) {
ProductQRData productData = new ProductQRData();
// Handle different QR content formats
if (qrContent.startsWith("PRODUCT_DATA:")) {
parseCustomFormat(qrContent, productData);
} else if (qrContent.startsWith("PRODUCT:")) {
parseSimpleFormat(qrContent, productData);
} else if (qrContent.contains("/products/")) {
parseURLFormat(qrContent, productData);
} else {
// Try to extract product ID using patterns
extractUsingPatterns(qrContent, productData);
}
return productData;
}
private void parseCustomFormat(String qrContent, ProductQRData productData) {
// Format: PRODUCT_DATA:ID:123|SKU:ABC123|NAME:Product Name|...
String dataPart = qrContent.substring("PRODUCT_DATA:".length());
String[] pairs = dataPart.split("\\|");
for (String pair : pairs) {
String[] keyValue = pair.split(":", 2);
if (keyValue.length == 2) {
String key = keyValue[0];
String value = keyValue[1];
switch (key) {
case "ID":
productData.setProductId(value);
break;
case "SKU":
productData.setSku(value);
break;
case "NAME":
productData.setProductName(value);
break;
case "CATEGORY":
productData.setCategory(value);
break;
case "PRICE":
try {
productData.setPrice(Double.parseDouble(value));
} catch (NumberFormatException e) {
// Ignore parsing errors
}
break;
case "BATCH":
productData.setBatchNumber(value);
break;
case "EXPIRY":
try {
productData.setExpiryDate(java.time.LocalDate.parse(value));
} catch (Exception e) {
// Ignore parsing errors
}
break;
}
}
}
}
private void parseSimpleFormat(String qrContent, ProductQRData productData) {
// Format: PRODUCT:123|NAME:Product Name|SKU:ABC123|TS:123456789
String dataPart = qrContent.substring("PRODUCT:".length());
String[] pairs = dataPart.split("\\|");
for (String pair : pairs) {
String[] keyValue = pair.split(":", 2);
if (keyValue.length == 2) {
String key = keyValue[0];
String value = keyValue[1];
switch (key) {
case "NAME":
productData.setProductName(value);
break;
case "SKU":
productData.setSku(value);
break;
default:
// Assume first part is product ID
if (productData.getProductId() == null) {
productData.setProductId(keyValue[0]);
}
break;
}
}
}
}
private void parseURLFormat(String qrContent, ProductQRData productData) {
// Extract product ID from URL like https://domain.com/products/123
Pattern pattern = Pattern.compile("/products/([^/?]+)");
Matcher matcher = pattern.matcher(qrContent);
if (matcher.find()) {
productData.setProductId(matcher.group(1));
}
productData.setProductName("Product from URL");
}
private void extractUsingPatterns(String qrContent, ProductQRData productData) {
// Try to extract product ID using common patterns
Pattern productIdPattern = Pattern.compile("([A-Z0-9]{3,}-[A-Z0-9]{3,})");
Matcher matcher = productIdPattern.matcher(qrContent);
if (matcher.find()) {
productData.setProductId(matcher.group(1));
} else {
productData.setProductId(qrContent.substring(0, Math.min(20, qrContent.length())));
}
productData.setProductName("Unknown Product");
}
}

Advanced QR Code Features

1. Batch QR Code Generator

@Service
public class BatchQRCodeService {
private final ProductQRCodeService qrCodeService;
public BatchQRCodeService(ProductQRCodeService qrCodeService) {
this.qrCodeService = qrCodeService;
}
/**
* Generate QR codes for multiple products in batch
*/
public Map<String, String> generateBatchQRCodes(List<ProductQRData> products) {
Map<String, String> results = new HashMap<>();
for (ProductQRData product : products) {
try {
String filename = "product_" + product.getProductId() + "_" + System.currentTimeMillis();
String filePath = qrCodeService.generateAndSaveQRCode(product, filename);
results.put(product.getProductId(), filePath);
} catch (Exception e) {
results.put(product.getProductId(), "ERROR: " + e.getMessage());
}
}
return results;
}
/**
* Generate QR codes with different sizes
*/
public Map<String, byte[]> generateQRCodesWithSizes(ProductQRData product, List<Integer> sizes) {
Map<String, byte[]> qrCodes = new HashMap<>();
for (Integer size : sizes) {
try {
String content = buildProductQRContent(product);
byte[] qrCode = generateCustomSizeQRCode(content, size, size);
qrCodes.put(size + "x" + size, qrCode);
} catch (Exception e) {
System.err.println("Failed to generate QR code size " + size + ": " + e.getMessage());
}
}
return qrCodes;
}
private byte[] generateCustomSizeQRCode(String content, int width, int height) 
throws WriterException, IOException {
QRCodeWriter writer = new QRCodeWriter();
BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height);
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
MatrixToImageWriter.writeToStream(bitMatrix, "PNG", outputStream);
return outputStream.toByteArray();
}
}
private String buildProductQRContent(ProductQRData product) {
return "PRODUCT_DATA:ID:" + product.getProductId() +
"|NAME:" + product.getProductName() +
"|SKU:" + product.getSku() +
"|TS:" + System.currentTimeMillis();
}
}

2. QR Code Validation Service

@Service
public class QRCodeValidationService {
private final ProductQRCodeReader qrCodeReader;
public QRCodeValidationService(ProductQRCodeReader qrCodeReader) {
this.qrCodeReader = qrCodeReader;
}
/**
* Validate QR code content and structure
*/
public ValidationResult validateProductQRCode(byte[] qrCodeImage) {
ValidationResult result = new ValidationResult();
try {
ProductQRData productData = qrCodeReader.readProductQRCode(qrCodeImage);
result.setValid(true);
result.setProductData(productData);
// Validate required fields
if (productData.getProductId() == null || productData.getProductId().trim().isEmpty()) {
result.setValid(false);
result.addError("Product ID is required");
}
if (productData.getProductName() == null || productData.getProductName().trim().isEmpty()) {
result.addWarning("Product name is missing");
}
// Validate product ID format
if (!isValidProductId(productData.getProductId())) {
result.addWarning("Product ID format may be invalid");
}
} catch (Exception e) {
result.setValid(false);
result.addError("Failed to read QR code: " + e.getMessage());
}
return result;
}
/**
* Verify QR code matches expected product
*/
public boolean verifyQRCodeContent(byte[] qrCodeImage, String expectedProductId) {
try {
ProductQRData productData = qrCodeReader.readProductQRCode(qrCodeImage);
return expectedProductId.equals(productData.getProductId());
} catch (Exception e) {
return false;
}
}
private boolean isValidProductId(String productId) {
// Basic validation - adjust based on your product ID format
return productId != null && 
productId.length() >= 3 && 
productId.length() <= 50 &&
productId.matches("[A-Za-z0-9-_]+");
}
public static class ValidationResult {
private boolean valid;
private ProductQRData productData;
private List<String> errors = new ArrayList<>();
private List<String> warnings = new ArrayList<>();
// Getters and setters
public boolean isValid() { return valid; }
public void setValid(boolean valid) { this.valid = valid; }
public ProductQRData getProductData() { return productData; }
public void setProductData(ProductQRData productData) { this.productData = productData; }
public List<String> getErrors() { return errors; }
public void addError(String error) { this.errors.add(error); }
public List<String> getWarnings() { return warnings; }
public void addWarning(String warning) { this.warnings.add(warning); }
}
}

REST API Controllers

1. QR Code Generation API

@RestController
@RequestMapping("/api/qrcode")
public class QRCodeController {
private final ProductQRCodeService qrCodeService;
private final BatchQRCodeService batchQRCodeService;
public QRCodeController(ProductQRCodeService qrCodeService, 
BatchQRCodeService batchQRCodeService) {
this.qrCodeService = qrCodeService;
this.batchQRCodeService = batchQRCodeService;
}
@PostMapping("/product/generate")
public ResponseEntity<QRCodeResponse> generateProductQRCode(@RequestBody ProductQRRequest request) {
try {
byte[] qrCode = qrCodeService.generateProductQRCode(
request.getProductId(), 
request.getProductName(), 
request.getSku()
);
String base64QRCode = Base64.getEncoder().encodeToString(qrCode);
QRCodeResponse response = new QRCodeResponse();
response.setSuccess(true);
response.setQrCodeBase64(base64QRCode);
response.setProductId(request.getProductId());
response.setMessage("QR code generated successfully");
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new QRCodeResponse(false, "Failed to generate QR code: " + e.getMessage()));
}
}
@PostMapping("/product/generate-branded")
public ResponseEntity<QRCodeResponse> generateBrandedQRCode(@ModelAttribute BrandedQRRequest request) {
try {
byte[] qrCode = qrCodeService.generateBrandedQRCode(
request.getProductId(),
request.getProductName(),
request.getLogoFile().getBytes()
);
String base64QRCode = Base64.getEncoder().encodeToString(qrCode);
return ResponseEntity.ok(new QRCodeResponse(true, base64QRCode, request.getProductId()));
} catch (Exception e) {
return ResponseEntity.badRequest()
.body(new QRCodeResponse(false, "Failed to generate branded QR code"));
}
}
@PostMapping("/batch/generate")
public ResponseEntity<BatchQRCodeResponse> generateBatchQRCodes(@RequestBody List<ProductQRData> products) {
try {
Map<String, String> results = batchQRCodeService.generateBatchQRCodes(products);
BatchQRCodeResponse response = new BatchQRCodeResponse();
response.setSuccess(true);
response.setGeneratedQRCodes(results);
response.setTotalProcessed(products.size());
response.setSuccessfulCount((int) results.values().stream()
.filter(v -> !v.startsWith("ERROR"))
.count());
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new BatchQRCodeResponse(false, "Batch generation failed"));
}
}
// Request and Response classes
public static class ProductQRRequest {
private String productId;
private String productName;
private String sku;
private String baseUrl;
// Getters and setters
public String getProductId() { return productId; }
public void setProductId(String productId) { this.productId = productId; }
public String getProductName() { return productName; }
public void setProductName(String productName) { this.productName = productName; }
public String getSku() { return sku; }
public void setSku(String sku) { this.sku = sku; }
public String getBaseUrl() { return baseUrl; }
public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; }
}
public static class QRCodeResponse {
private boolean success;
private String qrCodeBase64;
private String productId;
private String message;
// Constructors
public QRCodeResponse() {}
public QRCodeResponse(boolean success, String message) {
this.success = success;
this.message = message;
}
public QRCodeResponse(boolean success, String qrCodeBase64, String productId) {
this.success = success;
this.qrCodeBase64 = qrCodeBase64;
this.productId = productId;
this.message = "Success";
}
// Getters and setters
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public String getQrCodeBase64() { return qrCodeBase64; }
public void setQrCodeBase64(String qrCodeBase64) { this.qrCodeBase64 = qrCodeBase64; }
public String getProductId() { return productId; }
public void setProductId(String productId) { this.productId = productId; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
public static class BatchQRCodeResponse {
private boolean success;
private Map<String, String> generatedQRCodes;
private int totalProcessed;
private int successfulCount;
private String message;
// Constructors and getters/setters
public BatchQRCodeResponse() {}
public BatchQRCodeResponse(boolean success, String message) {
this.success = success;
this.message = message;
}
// Getters and setters
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public Map<String, String> getGeneratedQRCodes() { return generatedQRCodes; }
public void setGeneratedQRCodes(Map<String, String> generatedQRCodes) { this.generatedQRCodes = generatedQRCodes; }
public int getTotalProcessed() { return totalProcessed; }
public void setTotalProcessed(int totalProcessed) { this.totalProcessed = totalProcessed; }
public int getSuccessfulCount() { return successfulCount; }
public void setSuccessfulCount(int successfulCount) { this.successfulCount = successfulCount; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
}

2. QR Code Reading API

@RestController
@RequestMapping("/api/qrcode")
public class QRCodeReaderController {
private final ProductQRCodeReader qrCodeReader;
private final QRCodeValidationService validationService;
public QRCodeReaderController(ProductQRCodeReader qrCodeReader,
QRCodeValidationService validationService) {
this.qrCodeReader = qrCodeReader;
this.validationService = validationService;
}
@PostMapping("/read")
public ResponseEntity<ReadQRCodeResponse> readQRCode(@RequestBody ReadQRCodeRequest request) {
try {
byte[] imageData = Base64.getDecoder().decode(request.getImageBase64());
ProductQRData productData = qrCodeReader.readProductQRCode(imageData);
ReadQRCodeResponse response = new ReadQRCodeResponse();
response.setSuccess(true);
response.setProductData(productData);
response.setMessage("QR code read successfully");
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.badRequest()
.body(new ReadQRCodeResponse(false, "Failed to read QR code: " + e.getMessage()));
}
}
@PostMapping("/validate")
public ResponseEntity<ValidationResponse> validateQRCode(@RequestBody ReadQRCodeRequest request) {
try {
byte[] imageData = Base64.getDecoder().decode(request.getImageBase64());
QRCodeValidationService.ValidationResult result = validationService.validateProductQRCode(imageData);
ValidationResponse response = new ValidationResponse();
response.setValid(result.isValid());
response.setProductData(result.getProductData());
response.setErrors(result.getErrors());
response.setWarnings(result.getWarnings());
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.badRequest()
.body(new ValidationResponse(false, "Validation failed: " + e.getMessage()));
}
}
@PostMapping("/read-multiple")
public ResponseEntity<MultipleQRCodeResponse> readMultipleQRCodes(@RequestBody ReadQRCodeRequest request) {
try {
byte[] imageData = Base64.getDecoder().decode(request.getImageBase64());
List<ProductQRData> products = qrCodeReader.readMultipleProductQRCodes(imageData);
MultipleQRCodeResponse response = new MultipleQRCodeResponse();
response.setSuccess(true);
response.setProducts(products);
response.setCount(products.size());
return ResponseEntity.ok(response);
} catch (Exception e) {
return ResponseEntity.badRequest()
.body(new MultipleQRCodeResponse(false, "Failed to read multiple QR codes"));
}
}
// Request and Response classes
public static class ReadQRCodeRequest {
private String imageBase64;
public String getImageBase64() { return imageBase64; }
public void setImageBase64(String imageBase64) { this.imageBase64 = imageBase64; }
}
public static class ReadQRCodeResponse {
private boolean success;
private ProductQRData productData;
private String message;
// Constructors and getters/setters
public ReadQRCodeResponse() {}
public ReadQRCodeResponse(boolean success, String message) {
this.success = success;
this.message = message;
}
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public ProductQRData getProductData() { return productData; }
public void setProductData(ProductQRData productData) { this.productData = productData; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
public static class ValidationResponse {
private boolean valid;
private ProductQRData productData;
private List<String> errors = new ArrayList<>();
private List<String> warnings = new ArrayList<>();
private String message;
// Constructors and getters/setters
public ValidationResponse() {}
public ValidationResponse(boolean valid, String message) {
this.valid = valid;
this.message = message;
}
public boolean isValid() { return valid; }
public void setValid(boolean valid) { this.valid = valid; }
public ProductQRData getProductData() { return productData; }
public void setProductData(ProductQRData productData) { this.productData = productData; }
public List<String> getErrors() { return errors; }
public void setErrors(List<String> errors) { this.errors = errors; }
public List<String> getWarnings() { return warnings; }
public void setWarnings(List<String> warnings) { this.warnings = warnings; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
public static class MultipleQRCodeResponse {
private boolean success;
private List<ProductQRData> products;
private int count;
private String message;
// Constructors and getters/setters
public MultipleQRCodeResponse() {}
public MultipleQRCodeResponse(boolean success, String message) {
this.success = success;
this.message = message;
}
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public List<ProductQRData> getProducts() { return products; }
public void setProducts(List<ProductQRData> products) { this.products = products; }
public int getCount() { return count; }
public void setCount(int count) { this.count = count; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
}

Best Practices

  1. Error Correction: Use appropriate error correction levels for different environments
  2. Size Optimization: Balance between QR code size and data capacity
  3. Content Structure: Use consistent data formats for reliable parsing
  4. Security: Validate QR code content to prevent malicious data
  5. Performance: Implement caching for frequently generated QR codes
  6. Storage: Organize generated QR codes with proper naming conventions
  7. Testing: Test QR codes with different scanners and lighting conditions

This comprehensive QR code solution provides everything needed for product identification, inventory management, and customer engagement through QR codes in Java applications.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper