Java Biz App Developer

Aside

This website is my personal memo, and study history.


From what I have seen so far, these are very important things to develop and/or maintain Biz Apps:

  • To be familiar with a Data model can be the most important thing. For Biz Apps, data is (almost) everything. You always need to look at them whenever you got a question from end users.
  • For technical side, SQL skill is extremely important, perhaps even more important than J2EE; As a system get bigger, more data (and tables) you will have to deal with.
  • It is also important to be familiar with Business Flow. Without knowing the business flow, you cannot define a business logic.

In this website, the most examples are based on my experiences. I use a very simple example of Return application process (You purchase something, but want the product to be returned).

In general, a Return transaction is defined as RMA (Return Merchandise Authorization). One transaction (RMA) can have more than one items to return. Each RMA has a type and a reason for returning item(s).

For example, let’s say a transaction #1 (say RMA#1) that has Item A (Camera) and B (Lens). If you order a wrong model by mistake, in this case, the return type is “order by mistake“ and reason is “wrong item“. Therefore, the transaction attributes of RMA#1 are: Item A, with type “order by mistake“ and reason of “wrong item“.

I hope you enjoy reading it. (Go To Index)

Table of Contents

Aside

Spring MVC
index-icon-mvc1
Spring MVC Config
Submitting a Form
Multiple Row Form Submit
Radio Button and Check Box
Screen Transition (With More than one Controllers)
Select Box Stays Selected

DI (Dependency Injection) and AOP (Aspect Oriented Programming)
index-icon-mvc-aop1
Overview (Dependency Injection)
Dependency Injection: Setter Injection
Dependency Injection: Field Injection
AOP/Aspect-J Overview and Config
Before Advise
After Advise
Around Advise

JPA Hibernate with Spring MVC
hiv-db-bean-img2
Spring + Hibernate Config
Generic DAO
Generic DAO with Custom Method
Generic DAO without Custom Method
HQL and Native SQL in Hibernate
One to Many – Composite Primary Key
Many to Many
Applying Many to Many

Ajax/jQuery with Spring MVC
hdr-sq-img-ajax2
HTML Table Creation
Radio Button Events
Updating an MVC Partial View
Dynamically Creating a Select Box
To Leverage On-Change Dropdown
Auto Complete

Mongo DB, Web Service, Design Pattern, Data Structure, and Bonus
hdr-sq-img-webservice-img2
Mongo DB + Spring MVC
Mongo Repository
Web Service
Optimizing SQL
Static Factory Pattern
Hash Set vs Array List
How To Work on GitHub

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;
	}
}