About nobukimi@gmail.com

I’ve been working on Java developer for 15+ years. Hope this website shares my experiences for developing and maintaining business web apps.

AWS – API Gateway to create data in DynamoDB through Lambda function in Java

By Nobukimi Sasaki (2023-04-24) Continued from API Gateway + Lambda + DynamoDB (Configuration)

Dependency for AWS Lambda

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-core</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-lambda-java-events</artifactId>
            <version>2.0.2</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-dynamodb</artifactId>
            <version>1.11.271</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.14.1</version>
        </dependency>

The main class receive the request:APIGatewayProxyRequestEvent::getHttpMethod.

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBScanExpression;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;

public class LambdaHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    @Override
    public APIGatewayProxyResponseEvent handleRequest ( APIGatewayProxyRequestEvent apiGatewayRequest, Context context ) {

        EmployeeService employeeService = new EmployeeService();

        switch (apiGatewayRequest.getHttpMethod()) {

            case "POST":
                return employeeService.saveEmployee( apiGatewayRequest, context );

            case "GET":
                if (apiGatewayRequest.getPathParameters() != null) {
                    return employeeService.getEmployeeById( apiGatewayRequest, context );
                }
                return employeeService.getEmployees( apiGatewayRequest, context );
            case "DELETE":
                if (apiGatewayRequest.getPathParameters() != null) {
                    return employeeService.deleteEmployeeById( apiGatewayRequest, context );
                }
            default:
                throw new Error( "Unsupported Methods:::" + apiGatewayRequest.getHttpMethod() );

        }
    }
}

The 1st parameter, APIGatewayProxyRequestEvent contains:
This getHttpMethod returns String httpMethod that is “GET”, “POST”, “PUT”,,,,

The 2nd parameter, Context contains:

The response class “APIGatewayProxyResponseEvent” contains:

Saving data:

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBScanExpression;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.app.easy2excel.entity.Employee;

import java.util.List;
import java.util.Map;

public class EmployeeService {

    private DynamoDBMapper dynamoDBMapper;
    private static String jsonBody = null;

    public APIGatewayProxyResponseEvent saveEmployee ( APIGatewayProxyRequestEvent apiGatewayRequest, Context context ) {
        initDynamoDB();
        Employee employee = Utility.convertStringToObj( apiGatewayRequest.getBody(), context );
        dynamoDBMapper.save( employee );
        jsonBody = Utility.convertObjToString( employee, context );
        context.getLogger().log( "data saved successfully to dynamodb:::" + jsonBody );
        return createAPIResponse( jsonBody, 201, Utility.createHeaders() );
    }
....

Within the createAPIResponse, it returns the APIGatewayProxyResponseEvent:

    private APIGatewayProxyResponseEvent createAPIResponse ( String body, int statusCode, Map<String, String> headers ) {
        APIGatewayProxyResponseEvent responseEvent = new APIGatewayProxyResponseEvent();
        responseEvent.setBody( body );
        responseEvent.setHeaders( headers );
        responseEvent.setStatusCode( statusCode );
        return responseEvent;
    }

The entity model:

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;

@DynamoDBTable(tableName = "employee")
public class Employee {

    @DynamoDBHashKey(attributeName = "empId")
    private String empId;

    @DynamoDBAttribute(attributeName = "name")
    private String name;

    @DynamoDBAttribute(attributeName = "email")
    private String email;
....

How to deploy the code:
Go to intellij terminal, as command line >mvn clean install

The jar file is created under target:

After specifying the built jar file, then upload.
Lambda > Functions > RestApiLambda (your function name) … There is a “Upload From” button:

Scroll down and under Runtime settings > Edit

Edit the header info as:

1. Package path
2. Class name
3. Method name
Then Save! Now the API is ready to run

In Postman, the POST request went succesfully:


Go to dashboard DynamoDB > Tables

1. Tables
2. Check
3. Click the table name
4. Explore the items
5. You will see the data created

AWS – API Gateway + Lambda + DynamoDB (Configuration)

By Nobukimi Sasaki (2023-04-24)

Create Dynamo DB

In AWS management console, pick Dynamo DB. In this example, the table name is “employee”. Give the primary key name “empId” in String.

Create Lambda Function:

In AWS management console, pick Lambda, then “Create function”. In this example, “RestApiLambda”.
The Runtime, “Java 11”, the table name is “employee”. Give the primary key name “empId” in String.

Providing a role:

Go to “IMA” console, choose “Lambda”, set the permission to “AmazonDynamoDBFullAccess”, “AWSLambdaBasicExecutionRole”.
Give the role name. In this example, “crudAPIRole”. After creating the role, check “use existing role”, and “Create function”.

Create API Gateway:

In AWS management console, pick “API Gateway”. Choose protocol “REST” and “New API”. In this example, API name is “EmployeeAPI”.

Specify the “Resources” for the API:

Under “API:EmployeeAPI”, click “Resource” then set the name “employee” it make the path …/employee as URL.
Check Enable API Gateway CORS.


1. Click the name of the resource (“employee” in this example)
2. Create Method
3. Select “POST” depends in the type.
4. Check this
5. Lambda Function
6. Use Lambda Proxy Integration
7. Type the name of function you have created (“RestApiLambda” in this example)
8. Save


1. Action
2. Deploy API
3. New Stage
4. dev (environment)
5. Deploy


After deployed, this is the URL for the API.

Microservices with Kafka

By Nobukimi Sasaki (2023-04-23)

Introduction:
This is my study note composed of three services (Spring Boot) with a message broker (kafka).
There services are independent to each other and communicating asynchronously.

Entire project structure:
There are four Spring Boots project under one folder

Service A: order-service
Whenever receiving the HTTP request, the order-service create a event and publish the event to the message broker (Kafka).

Service B (stock-service) & C (email-service)
Just consume the message from the message broker (Kafka) and Service B & C don’t know about Service A (order-service). They are all independent to each other.

Spring Boot for DTO object (base-domains)
The DTO classes for the message that being referred from Service A, B, and C.

Service A – order-service detail:

1. OrderController::placeOrder receives the request from HTTP client
2. OrderController::placeOrder::sendMessage calls Kakfa Producer
3. OrderProducer::sendMessage calls KafkaTemplate::send

spring.kafka.producer.bootstrap-servers: localhost:9092
spring.kafka.producer.key-serializer: org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
spring.kafka.topic.name=order_topics

At Service A, this property configures a Kafka Server (line 1), and topic name (line 4)

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka</artifactId>
		</dependency>
		<dependency>
			<groupId>net.javaguides</groupId>
			<artifactId>base-domains</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka-test</artifactId>
			<scope>test</scope>
		</dependency>

At Service A, B, and C, the dependency is Kakfa and DTO project (base-domains)

import net.javaguides.basedomains.dto.Order;
import net.javaguides.basedomains.dto.OrderEvent;
import net.javaguides.orderservice.kafka.OrderProducer;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
@RequestMapping("/api/v1")
public class OrderController {

    private OrderProducer orderProducer;

    public OrderController(OrderProducer orderProducer) {
        this.orderProducer = orderProducer;
    }

    // Rest End Point API for testing
    @PostMapping("/orders")
    public String placeOrder(@RequestBody Order order){

        order.setOrderId(UUID.randomUUID().toString());

        OrderEvent orderEvent = new OrderEvent();
        orderEvent.setStatus("PENDING");
        orderEvent.setMessage("order status is in pending state");
        orderEvent.setOrder(order);

        orderProducer.sendMessage(orderEvent);

        return "Order placed successfully ...";
    }
}

At Service A, OrderController::placeOrder receives the request from HTTP client, and sendMessage calls Kakfa Producer

import net.javaguides.basedomains.dto.OrderEvent;

import org.apache.kafka.clients.admin.NewTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

@Service
public class OrderProducer {

    private static final Logger LOGGER = LoggerFactory.getLogger(OrderProducer.class);

    private NewTopic topic;

    private KafkaTemplate<String, OrderEvent> kafkaTemplate;

    // Parameter constructor in this class
    public OrderProducer(NewTopic topic, KafkaTemplate<String, OrderEvent> kafkaTemplate) {
        this.topic = topic;
        this.kafkaTemplate = kafkaTemplate;
    }

    public void sendMessage(OrderEvent event){
        LOGGER.info(String.format("Order event => %s", event.toString()));

        // create Message
        Message<OrderEvent> message = MessageBuilder
                .withPayload(event)
                .setHeader(KafkaHeaders.TOPIC, topic.name())
                .build();
        kafkaTemplate.send(message);
    }
}

At Service A, OrderProducer::sendMessage calls KafkaTemplate::send

Service B (stock-service) and C (email-service) Service detail:

Service B (stock-service) and C (email-service) has kafka consumer to receive the message.

server.port=8081
spring.kafka.consumer.bootstrap-servers: localhost:9092
spring.kafka.consumer.group-id: stock
spring.kafka.consumer.auto-offset-reset: earliest
spring.kafka.consumer.key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
spring.kafka.consumer.properties.spring.json.trusted.packages=*
spring.kafka.topic.name=order_topics

At Service B (stock-service), Line 1 – the port is 8081, and group id is “stock”

server.port=8082
spring.kafka.consumer.bootstrap-servers: localhost:9092
spring.kafka.consumer.group-id: email
spring.kafka.consumer.auto-offset-reset: earliest
spring.kafka.consumer.key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
spring.kafka.consumer.properties.spring.json.trusted.packages=*
spring.kafka.topic.name=order_topics

At Service C (email-service), Line 1 – the port is 8082, and group id is “email”
Both Service B & C, Line 2 – register the kafka server port 9092, and line 8, the topic name of “order_topics”

import net.javaguides.basedomains.dto.OrderEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Service;

@Service
public class OrderConsumer {

    private static final Logger LOGGER = LoggerFactory.getLogger(OrderConsumer.class);

    @KafkaListener(
            topics = "${spring.kafka.topic.name}"
            ,groupId = "${spring.kafka.consumer.group-id}"
    )
    public void consume(OrderEvent event){
        LOGGER.info(String.format("Order event received in stock service => %s", event.toString()));

        // business logic
    }
}

Both Service B & C have this consumer class.

DTO object (base-domains) Details:

This DTO classes are referenced from Service A, B, and C


Example of RESTFul client

QR code decoding by zxing

package com.ns.utils;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;

public class QRCodeZxingUtil {

	public static Map<String, String> scanQRCode(String dir, String fileName, String textKey) {
		Map<String, String> mp = new HashMap<String, String>();
		// Hints for scanning
		Vector<BarcodeFormat> decodeFormat = new Vector<BarcodeFormat>();
		decodeFormat.add(BarcodeFormat.QR_CODE);

		Hashtable<DecodeHintType, Object> hintMap = new Hashtable<DecodeHintType, Object>();
		hintMap.put(DecodeHintType.TRY_HARDER, true);
		hintMap.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormat);

		MultiFormatReader qrcodeReader = new MultiFormatReader();
		qrcodeReader.setHints(hintMap);
		// We try for several images of the PDF page at several DPI settings,
		// starting at the lowest setting, this might help for speed...
		int[] dpiSettings = { 96, 150, 200, 250, 300, 350 };
		for (int i = 0; i < dpiSettings.length; i++) {
			try {
				// Try lowest DPI first.
				BufferedImage pageImage = getPageImage(dir, fileName, dpiSettings[i]);
				if (pageImage != null) {
					LuminanceSource source = new BufferedImageLuminanceSource(pageImage);
					BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
					// By using decodeWithState, we keep the Hints that we set earlier.
					Result result = qrcodeReader.decodeWithState(bitmap);
					String text = result.getText();
					// System.out.println(" Sucess at DPI -> " + dpiSettings[i]);
					pageImage.flush();

					if (text != null && text.length() > 0) {
						mp.put(textKey, text);
						mp.put("DPI", Integer.toString(dpiSettings[i]));
					}
				}
				if (mp.containsKey(textKey)) {
					return mp;
				}
			} catch (IOException e) {
				System.out.print(" IOException at DPI -> " + dpiSettings[i]);
			} catch (NotFoundException e) {
				System.out.print(" NotFoundException at DPI -> " + dpiSettings[i]);
			}
		}
		return null;
	}

	private static BufferedImage getPageImage(String dir, String fileName, int dpi) throws IOException {
		BufferedImage image = null;
		Path docPath = Paths.get(dir.concat(fileName));
		PDDocument pdfDoc = PDDocument.load(docPath.toFile());
		try {
			PDFRenderer renderer = new PDFRenderer(pdfDoc);
			image = renderer.renderImageWithDPI(0, dpi, ImageType.BINARY); // entire page info
		} finally {
			pdfDoc.close();
		}		
		return image;
	}
}

QR code decoding by pdmodel

package com.ns.utils;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDResources;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObject;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectImage;

import com.ns.service.QRCodeDecoder;

public class QRCodePdModelUtil {

	@SuppressWarnings("unchecked")
	public static Map<String, String> scanQRCode(String dir, String fileName, String textKey) {

		Map<String, String> map = new HashMap<String, String>();

		List<PDPage> pages = null;
		BufferedImage qrCodeImg = null;
		String qrCode = null;
		PDDocument pdfDoc = null;

		try {
			Path docPath = Paths.get(dir.concat(fileName));
			pdfDoc = PDDocument.load(docPath.toFile());
			QRCodeDecoder decoder = new QRCodeDecoder();

			pages = pdfDoc.getDocumentCatalog().getAllPages();
			int dpi = 0;
			int dpiEffective = 0;
			int dpiLow = 0;

			for (PDPage page : pages) {
				try {
					if (null == qrCode) {
						qrCodeImg = page.convertToImage(BufferedImage.TYPE_BYTE_GRAY, 100);
						qrCode = decoder.getCompressedQRCode(qrCodeImg);
					}
					if (null == qrCode) {
						dpi = detectPageDPI(page);
						dpiEffective = dpi;
						dpiLow = dpi - 5;
						for (; dpiLow < dpiEffective; dpiEffective--) {
							qrCodeImg = page.convertToImage(BufferedImage.TYPE_BYTE_GRAY, dpiEffective);
							qrCode = decoder.getCode(qrCodeImg);
							if (null != qrCode) {
								break;
							}
						}
					}
					if (null == qrCode) {
						qrCodeImg = page.convertToImage(BufferedImage.TYPE_BYTE_GRAY, 400);
						qrCode = decoder.getCompressedQRCode(qrCodeImg);
					}
					System.out.println("Code:::" + qrCode);
					if (null != qrCode) {
						map.put("DPI", Integer.toString(dpi));
						map.put(textKey, qrCode);
						return map;
					}
				} catch (Exception e) {
					System.out.println(e.getMessage());

				} finally {
					qrCodeImg = null;
					qrCode = null;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != pdfDoc) {
				try {
					pdfDoc.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			pages = null;
		}
		return null;
	}

	private static int detectPageDPI(PDPage page) {
		PDResources res = page.getResources();
		Collection<PDXObject> xObjects = res.getXObjects().values();
		int imgHeight = 0;
		for (PDXObject xObject : xObjects) {
			if (xObject instanceof PDXObjectImage) {
				imgHeight = ((PDXObjectImage) xObject).getHeight();
			}
		}

		float pageHeight = page.getMediaBox().getHeight() / 72;
		int dpi = (int) (imgHeight / pageHeight);
		if (200 > dpi) {
			dpi = 200;
		}
		if (300 < dpi) {
			dpi = 300;
		}
		return dpi;
	}

}

package com.ns.service;

import java.awt.RenderingHints;
import java.awt.RenderingHints.Key;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.awt.image.RasterFormatException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
import com.google.zxing.LuminanceSource;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;

@Service
public class QRCodeDecoder {

	public String getCode(BufferedImage image) {
		String code = null;
		try {
			// vertical bottom scan
			BufferedImage procImage = image.getSubimage(0, image.getHeight() / 2, image.getWidth(), image.getHeight() / 2 - 20);
			code = decode(procImage);

		} catch (RasterFormatException e) {
			// continue
		}
		return code;
	}

	public String getCompressedQRCode(BufferedImage image) {
		String code = null;
		try {
			// vertical bottom scan
			BufferedImage procImage = image.getSubimage(150, image.getHeight() / 2, image.getWidth() - 150, image.getHeight() / 2 - 200);
			code = decode(procImage);
		} catch (RasterFormatException e) {
			// continue
		}
		return code;
	}

	public String decode(BufferedImage image) {
		RenderingHints hints = getRenderingHints();
		float[] kernelData = null;
		BufferedImageOp op = null;
		BufferedImage procImage = null;
		LuminanceSource source = null;
		BinaryBitmap bitmap = null;
		QRCodeReader reader = new QRCodeReader();
		Result result = null;
		String code = null;

		for (int denom = 10; denom <= 50; denom += 10) {
			try {
				procImage = image;
				float factor = (1.0f / ((float) denom));
				kernelData = getKernelData(factor);
				op = new ConvolveOp(new Kernel(4, 4, kernelData), ConvolveOp.EDGE_NO_OP, hints);
				source = new BufferedImageLuminanceSource(op.filter(procImage, null));
				bitmap = new BinaryBitmap(new HybridBinarizer(source));
				result = reader.decode(bitmap);
				code = result.getText();
				break;
			} catch (NotFoundException e) {
				// continue
			} catch (ChecksumException e) {
				// continue
			} catch (FormatException e) {
				// continue
			} finally {
				hints = null;
				kernelData = null;
				op = null;
				source = null;
				bitmap = null;
				procImage = null;
				result = null;
			}
		}
		return code;
	}

	protected RenderingHints getRenderingHints() {
		Map<Key, Object> map = new HashMap<Key, Object>();
		map.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		map.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
		map.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		RenderingHints hints = new RenderingHints(map);
		return hints;
	}

	protected float[] getKernelData(float data) {
		return new float[] { data, data, data, data, data, data, data, data, data, data, data, data, data, data, data, data };
	}
}

Reading QR code within PDF file

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Hashtable;
import java.util.Vector;

import javax.activation.DataSource;
import javax.mail.util.ByteArrayDataSource;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;

	private String scanQRCode() {

		// Hints for scanning
		Vector<BarcodeFormat> decodeFormat = new Vector<BarcodeFormat>();
		decodeFormat.add(BarcodeFormat.QR_CODE);

		Hashtable<DecodeHintType, Object> hintMap = new Hashtable<DecodeHintType, Object>();
		hintMap.put(DecodeHintType.TRY_HARDER, true);
		hintMap.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormat);

		MultiFormatReader qrcodeReader = new MultiFormatReader();
		qrcodeReader.setHints(hintMap);

		try {
			// Try lowest DPI first.
			// BufferedImage pageImage = getPageImage(pageIndex, dpiSettings[i]);
			BufferedImage pageImage = getPageImage();
			LuminanceSource source = new BufferedImageLuminanceSource(pageImage);
			BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
			// By using decodeWithState, we keep the Hints that we set earlier.
			Result result = qrcodeReader.decodeWithState(bitmap);
			String text = result.getText();
			return text;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (NotFoundException e) {
			e.printStackTrace();
		}
		// This should never happen, ever...
		return null;
	}

	private BufferedImage getPageImage() throws IOException {		
		Path docPath = Paths.get("C:\\NS2\\test_files\\java3.pdf");		
		PDDocument pdfDoc = PDDocument.load(docPath.toFile());
		PDFRenderer renderer = new PDFRenderer(pdfDoc);
		// renderImageWithDPI(page number, image size, format)
		BufferedImage image = renderer.renderImageWithDPI(0, 150, ImageType.BINARY); // entire page info
		pdfDoc.close();
		return image;
	}

Spring REST GET with HttpServletRequest

REST client:


import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import com.ns.model.UdsTransactionRequest;
import com.ns.model.UfsReferenceNumber;
import com.ns.model.notification.UfsPipeline;
import com.ns.service.ServiceResponse;

	@SuppressWarnings("unchecked")
	private void testGet2() {

		RestTemplate restTemplate = new RestTemplate();

		Long txId = 123456789L;
		String[] array = {"6B","EL","SO","RN","KK"};

		String url = "http://localhost:8080/transaction/references/pipeline/{txId}/?types={types}";

		ServiceResponse<UfsReferenceNumber> response = restTemplate.getForObject(url, ServiceResponse.class, txId, StringUtils.join(array, ","));

		List<UfsReferenceNumber> results = response.getData();
		if (results != null && !results.isEmpty()) {
			for (UfsReferenceNumber a : results) {
				System.out.println("---------------- ID: " + a.getId().getRefNum());
			}
		}
		System.out.println("---------------- END testGet2------------------");
	}

This gives the URL:

http://localhost:8080/transaction/references/pipeline/123456789/?types=6B,EL,SO,RN,KK

The “request.getParameter(“types”);” gets the values from URL “types=6B,EL,SO,RN,KK”.

REST endpoint:

@RequestMapping(value = "/references/pipeline/{txId}/", method = RequestMethod.GET)
public ServiceResponse<UfsReferenceNumber> getReferences(@PathVariable String txId, HttpServletRequest request) {
	ServiceResponse<UfsReferenceNumber> response = new ServiceResponse<>();
	String typesCsv = request.getParameter("types");
	List<String> types = null;
	List<UfsReferenceNumber> references = null;
	if (null != typesCsv && 0 != typesCsv.length()) {
		types = Arrays.asList(typesCsv.split(","));
	}
	try {
		references = repo.getTxnReferenceNumbers(new Long(txId), types);
		if (null != references && !references.isEmpty()) {
			response.setData(references);
		}
	} catch (Exception e) {
	}
	return response;
}

Mongo DB query examples

Greater than:

db.getCollection('StorageContent').find({ $and:[
    {"shardKey" : "7507501"},
    {"cd": {$gte: ISODate("2017-07-02T00:00:00.731Z")}}
]})

Less than:

db.getCollection('NotificationProfile').find({ $and:[
    {createdBy: "hban"}, 
    {deliveryType: "F"}, 
    { 
    "createdDate": {
        $lte: ISODate("2018-11-30")
    }}
]})

Between:

db.getCollection('LogEntry').find({ $and:[
    {
    "time": {
        $gte: ISODate("2017-11-10")
    }}, 
    { 
    "time": {
        $lte: ISODate("2017-11-17")
    }}
]})

Oerder By date:

db.getCollection('notifyEmailSent').find({ $and:[
    {
    "created": {
        $gte: ISODate("2018-12-01 16:00:00:000Z")
    }}
]}).sort({"created": -1})

Exist:

db.getCollection('NotificationProfile').find({ $and:[
    {
        "terminal":{$exists:true}
    },
    {
        "company": '100'
    }
]})

Group By:

db.getCollection('DocumentAudit').aggregate([  
   {  
      "$match":{  
         "tp":"STR",
         "stp":"SSC",
      }
   },
   {  
      "$group":{  
         _id:{  
            "grp":"$grp",
            "com":"$com",
            "tp":"$tp",
            "stp":"$stp"
         },
         count:{  
            $sum:1
         }
      }
   },
   {  
      "$sort":{  
         "_id.grp":1
      }
   },
   {  
      "$sort":{  
         "_id.com":1
      }
   },
   {  
      "$sort":{  
         "_id.tp":1
      }
   },
   {  
      "$project":{  
         "count":1,
         "group":"$_id.grp",
         "company":"$_id.com",
         "type":"$_id.tp",
         "subType":"$_id.stp"
      }
   },
   {  
      "$limit":2000
   }
])

Spring REST PUT form data

Postman image:

REST client:

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

	@SuppressWarnings("unchecked")
	private void testPost() {

		String url = "http://localhost:8080/uds-transaction-1.3.0/pipeline/list/";
		RestTemplate restTemplate = new RestTemplate();

		List<Long> list = new ArrayList<Long>();
		list.add(new Long(30284039614L));
		list.add(new Long(30262601669L));
		list.add(new Long(30262662522L));

		UdsTransactionRequest req = new UdsTransactionRequest();
		req.setTrxIdsLong(list);

		HttpEntity<UdsTransactionRequest> request = new HttpEntity<>(req);

		ServiceResponse<UfsPipeline> response = restTemplate.postForObject(url, request, ServiceResponse.class);

		List<UfsPipeline> results = response.getData();
		if (results != null && !results.isEmpty()) {
			for (UfsPipeline a : results) {
				System.out.println("---------------- txNo: " + a.getTxNo());
			}
		}
	}

Endpoint:

	@RequestMapping(value = "/pipeline/list/", produces = "application/json", method = RequestMethod.POST)
	public ServiceResponse<UfsPipeline> getOfficeDocumentEndPoint(@RequestBody UdsTransactionRequest req) {
		ServiceResponse<UfsPipeline> response = new ServiceResponse<>();
		try {
			List<UfsPipeline> list = pipelineRepo.getPipelinesByKeys(req.getTrxIdsLong());
			response.setData(list);
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
			response.addError(e);
		}
		return response;
	}

Support class:

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.ns.model.DataCacheMeta;
import com.ns.model.notification.UfsPipeline;

@JsonInclude(Include.NON_NULL)
public class ServiceResponse<T extends ResponseData> implements Serializable {

	public static final String OK = "ok";
	public static final String ERROR = "error";

	private static final long serialVersionUID = 4579157541957745675L;
	private List<ResponseError> errors;
	private List<T> data;
	private String status = OK;

	public void addError(Exception e) {
		if (null == errors) {
			errors = new ArrayList<>();
		}
		ResponseError error = new ResponseError(null, ResponseError.ERROR, e.getMessage());
		errors.add(error);
		setStatus(ServiceResponse.ERROR);
	}

	public void addData(T dataElement) {
		if (null == data) {
			data = new ArrayList<>();
		}
		data.add(dataElement);
	}

	@JsonSubTypes({@JsonSubTypes.Type(value = ResponseError.class, name = "error")})
	public List<ResponseError> getErrors() {
		return errors;
	}

	public void setErrors(List<ResponseError> errors) {
		this.errors = errors;
	}

	@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
	@JsonSubTypes({ @JsonSubTypes.Type(value = DataCacheMeta.class, name = "DataCacheMeta"),
			@JsonSubTypes.Type(value = UfsPipeline.class, name = "UfsPipeline")
	})
	public List<T> getData() {
		return data;
	}

	public void setData(List<T> data) {
		this.data = data;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}
}

Scan QR code in PDF

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.imageio.ImageIO;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ns.support.QrPdf;

public class My20190205QrCodeTest {

	private static String path = "C:\\NS2\\test_files\\520044839973-ARV.pdf";//

	public static void main(String[] args) {

		My20190205QrCodeTest a = new My20190205QrCodeTest();
		try {
			a.testPdf();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("---------------- END ------------------");
	}

	private void testPdf() {
		try {
			String line = scanQRCode(1);
			System.out.println("---------------- test7 result:::" + line);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	private String scanQRCode(int pageIndex) {

		// Hints for scanning
		Vector<BarcodeFormat> decodeFormat = new Vector<BarcodeFormat>();
		decodeFormat.add(BarcodeFormat.QR_CODE);

		Hashtable<DecodeHintType, Object> hintMap = new Hashtable<DecodeHintType, Object>();
		hintMap.put(DecodeHintType.TRY_HARDER, true);
		hintMap.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormat);

		MultiFormatReader qrcodeReader = new MultiFormatReader();
		qrcodeReader.setHints(hintMap);

		try {
			// Try lowest DPI first.
			BufferedImage pageImage = getPageImage();
			LuminanceSource source = new BufferedImageLuminanceSource(pageImage);
			BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
			// By using decodeWithState, we keep the Hints that we set earlier.
			Result result = qrcodeReader.decodeWithState(bitmap);
			String text = result.getText();
			// System.out.println(" -- text:::" + text);
			return text;
		} catch (IOException e) {
			e.printStackTrace();
		} catch (NotFoundException e) {
			e.printStackTrace();

		}
		// This should never happen, ever...
		return null;
	}

	private BufferedImage getPageImage() throws IOException {
		Path docPath = Paths.get(path);
		PDDocument pdfDoc = PDDocument.load(docPath.toFile());
		PDFRenderer renderer = new PDFRenderer(pdfDoc);
		// renderImageWithDPI(page number, image size, format)
		BufferedImage image = renderer.renderImageWithDPI(0, 150, ImageType.BINARY); // entire page info
		// BufferedImage image = renderer.renderImage(0);
		pdfDoc.close();
		return image;
	}
}