├── .gitignore
├── README.md
├── create-multiple-sheet-excel-file-from-database
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── README.md
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── hardik
│ │ │ │ └── bharta
│ │ │ │ ├── CreateMultipleSheetExcelFileFromDatabaseApplication.java
│ │ │ │ ├── bootstrap
│ │ │ │ └── DataPopulationOnBootstrap.java
│ │ │ │ ├── configuration
│ │ │ │ ├── OpenApiConfiguration.java
│ │ │ │ └── properties
│ │ │ │ │ └── OpenApiConfigurationProperties.java
│ │ │ │ ├── constant
│ │ │ │ └── ApiConstant.java
│ │ │ │ ├── controller
│ │ │ │ ├── ExcelController.java
│ │ │ │ └── SuperHeroController.java
│ │ │ │ ├── dto
│ │ │ │ └── SuperHeroCreationRequestDto.java
│ │ │ │ ├── entity
│ │ │ │ ├── MasterComic.java
│ │ │ │ └── SuperHero.java
│ │ │ │ ├── excel
│ │ │ │ ├── service
│ │ │ │ │ └── ExcelService.java
│ │ │ │ └── utility
│ │ │ │ │ └── ExcelCellUtils.java
│ │ │ │ ├── exception
│ │ │ │ ├── DuplicateSuperHeroNameException.java
│ │ │ │ └── handler
│ │ │ │ │ ├── DuplicateSuperHeroNameExceptionHandler.java
│ │ │ │ │ └── ValidationFailureExceptionHandler.java
│ │ │ │ ├── repository
│ │ │ │ ├── MasterComicRepository.java
│ │ │ │ └── SuperHeroRepository.java
│ │ │ │ └── service
│ │ │ │ └── SuperHeroService.java
│ │ └── resources
│ │ │ └── application.properties
│ └── test
│ │ └── java
│ │ └── com
│ │ └── hardik
│ │ └── bharta
│ │ └── CreateMultipleSheetExcelFileFromDatabaseApplicationTests.java
└── system.properties
├── create-single-excel-from-database
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── README.md
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── hardik
│ │ │ └── killercroc
│ │ │ ├── CreateSingleExcelFromDatabaseApplication.java
│ │ │ ├── bootstrap
│ │ │ └── EmployeeDataPopulationOnBootstrap.java
│ │ │ ├── configuration
│ │ │ ├── OpenApiConfiguration.java
│ │ │ └── properties
│ │ │ │ └── OpenApiConfigurationProperties.java
│ │ │ ├── constant
│ │ │ └── ApiConstant.java
│ │ │ ├── controller
│ │ │ ├── EmployeeController.java
│ │ │ └── ExcelController.java
│ │ │ ├── dto
│ │ │ └── EmployeeCreationRequestDto.java
│ │ │ ├── entity
│ │ │ └── Employee.java
│ │ │ ├── excel
│ │ │ └── service
│ │ │ │ └── ExcelService.java
│ │ │ ├── exception
│ │ │ └── handler
│ │ │ │ └── ValidationFailureExceptionHandler.java
│ │ │ ├── repository
│ │ │ └── EmployeeRepository.java
│ │ │ ├── service
│ │ │ └── EmployeeService.java
│ │ │ └── utility
│ │ │ └── ExcelCellUtils.java
│ │ └── resources
│ │ └── application.properties
└── system.properties
├── read-excel-to-database
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── README.md
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── hardik
│ │ │ │ └── kofta
│ │ │ │ ├── ReadExcelToDatabaseApplication.java
│ │ │ │ ├── annotation
│ │ │ │ ├── IsXlsx.java
│ │ │ │ └── aspect
│ │ │ │ │ └── CheckExcelFormatXlsxAspect.java
│ │ │ │ ├── bean
│ │ │ │ └── OtpCacheBean.java
│ │ │ │ ├── configuration
│ │ │ │ ├── OpenApiConfiguration.java
│ │ │ │ └── properties
│ │ │ │ │ ├── ExcelCacheConfigurationProperties.java
│ │ │ │ │ └── OpenApiConfigurationProperties.java
│ │ │ │ ├── constant
│ │ │ │ ├── ApiPath.java
│ │ │ │ └── ApiSummary.java
│ │ │ │ ├── controller
│ │ │ │ ├── EmployeeController.java
│ │ │ │ └── ExcelController.java
│ │ │ │ ├── entity
│ │ │ │ └── Employee.java
│ │ │ │ ├── excel
│ │ │ │ └── service
│ │ │ │ │ └── ExcelService.java
│ │ │ │ ├── exception
│ │ │ │ ├── FileNotSameThatWasValidatedException.java
│ │ │ │ ├── InvalidCodeException.java
│ │ │ │ ├── InvalidExcelFileExtensionException.java
│ │ │ │ ├── InvalidTemplateFormatException.java
│ │ │ │ └── handler
│ │ │ │ │ ├── FileNotSameThatWasValidatedExceptionHandler.java
│ │ │ │ │ ├── InvalidCodeExceptionHandler.java
│ │ │ │ │ ├── InvalidExcelFileExtensionExceptionHandler.java
│ │ │ │ │ └── InvalidTemplateFormatExceptionHandler.java
│ │ │ │ ├── repository
│ │ │ │ └── EmployeeRepository.java
│ │ │ │ └── service
│ │ │ │ └── EmployeeService.java
│ │ └── resources
│ │ │ ├── application.properties
│ │ │ └── template.xlsx
│ └── test
│ │ └── java
│ │ └── com
│ │ └── hardik
│ │ └── kofta
│ │ └── ReadExcelToDatabaseApplicationTests.java
└── system.properties
├── validate-excel-for-error-list-response
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── README.md
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── hardik
│ │ │ │ └── pyaaru
│ │ │ │ ├── ValidateExcelForErrorListResponseApplication.java
│ │ │ │ ├── annotation
│ │ │ │ ├── IsXlsx.java
│ │ │ │ └── aspect
│ │ │ │ │ └── CheckExcelFormatXlsxAspect.java
│ │ │ │ ├── bootstrap
│ │ │ │ └── EmployeeDataPopulationOnBootstrap.java
│ │ │ │ ├── configuration
│ │ │ │ ├── OpenApiConfiguration.java
│ │ │ │ └── properties
│ │ │ │ │ └── OpenApiConfigurationProperties.java
│ │ │ │ ├── controller
│ │ │ │ ├── EmployeeController.java
│ │ │ │ └── ExcelController.java
│ │ │ │ ├── entity
│ │ │ │ └── Employee.java
│ │ │ │ ├── exception
│ │ │ │ ├── InvalidExcelFileExtensionException.java
│ │ │ │ ├── InvalidTemplateFormatException.java
│ │ │ │ └── handler
│ │ │ │ │ ├── InvalidExcelFileExtensionExceptionHandler.java
│ │ │ │ │ └── InvalidTemplateFormatExceptionHandler.java
│ │ │ │ ├── repository
│ │ │ │ └── EmployeeRepository.java
│ │ │ │ └── service
│ │ │ │ └── ExcelService.java
│ │ └── resources
│ │ │ └── application.properties
│ └── test
│ │ └── java
│ │ └── com
│ │ └── hardik
│ │ └── pyaaru
│ │ └── ValidateExcelForErrorListResponseApplicationTests.java
└── system.properties
└── validate-excel-for-error-response-modify-same-file
├── .gitignore
├── .mvn
└── wrapper
│ ├── MavenWrapperDownloader.java
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── README.md
├── mvnw
├── mvnw.cmd
├── pom.xml
├── src
├── main
│ ├── java
│ │ └── com
│ │ │ └── hardik
│ │ │ └── durian
│ │ │ ├── ValidateExcelForErrorResponseModifySameFileApplication.java
│ │ │ ├── annotation
│ │ │ ├── IsXlsx.java
│ │ │ └── aspect
│ │ │ │ └── CheckExcelFormatXlsxAspect.java
│ │ │ ├── bootstrap
│ │ │ └── EmployeeDataPopulationOnBootstrap.java
│ │ │ ├── configuration
│ │ │ ├── OpenApiConfiguration.java
│ │ │ └── properties
│ │ │ │ └── OpenApiConfigurationProperties.java
│ │ │ ├── controller
│ │ │ ├── EmployeeController.java
│ │ │ └── ExcelController.java
│ │ │ ├── dto
│ │ │ └── ErrorMessageDto.java
│ │ │ ├── entity
│ │ │ └── Employee.java
│ │ │ ├── exception
│ │ │ ├── InvalidExcelFileExtensionException.java
│ │ │ ├── InvalidTemplateFormatException.java
│ │ │ └── handler
│ │ │ │ ├── InvalidExcelFileExtensionExceptionHandler.java
│ │ │ │ └── InvalidTemplateFormatExceptionHandler.java
│ │ │ ├── repository
│ │ │ └── EmployeeRepository.java
│ │ │ └── service
│ │ │ └── ExcelService.java
│ └── resources
│ │ └── application.properties
└── test
│ └── java
│ └── com
│ └── hardik
│ └── durian
│ └── ValidateExcelForErrorResponseModifySameFileApplicationTests.java
└── system.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | .metadata
2 | bin/
3 | tmp/
4 | *.tmp
5 | *.bak
6 | *.swp
7 | *~.nib
8 | local.properties
9 | .settings/
10 | .loadpath
11 | .recommenders
12 |
13 | # External tool builders
14 | .externalToolBuilders/
15 |
16 | # Locally stored "Eclipse launch configurations"
17 | *.launch
18 |
19 | # Java annotation processor (APT)
20 | .factorypath
21 |
22 | # sbteclipse plugin
23 | .target
24 |
25 | # Tern plugin
26 | .tern-project
27 |
28 | # STS (Spring Tool Suite)
29 | .springBeans
30 |
31 | # Code Recommenders
32 | .recommenders/
33 |
34 | # Annotation Processing
35 | .apt_generated/
36 | .apt_generated_test/
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Reference POC projects to work with excel files using Apache POI library and Java Spring-boot
2 | ##### All Proof of concepts are deployed to heroku with their links and sample videos included in their respective README.md file
3 |
4 | ### Proof of concepts included in this repo (Summary)
5 | * **Create excel file with single sheet from database records**
6 | * Insert 300 dummy employees records in H2 DB on startup using @PostConstruct
7 | * endpoint exposed to download created excel sheet from the inserted records at runtime
8 | * **Create excel file with multiple sheet from database records**
9 | * insert super_heroes from different comics in DB at startup (Marvel, Detective Comics)
10 | * endpoint exposed to download multiple sheet excel file created at runtime
11 | * each sheet contains records of super_heroes from one comic
12 | * one sheet for all superheroes from marvel comics, one for DC and so on.
13 | * **Validate data inside excel sheet for errors and return errors as List.of(String)**
14 | * endpoint exposed for user to download excel template (required columns)
15 | * user fills in data (rows) to downloaded template
16 | * exception is thrown is file extension or format(column names and order) is different
17 | * the errors include leaving cells blank, duplicate email-id, wrong email-id, invalid number type etc
18 | * each row is validated for errors, if errors exists a list is returned detailing out the error messages along with it's cell position
19 | * **Validate data inside excel sheet for errors and detail out errors in given excel file itself and return the same**
20 | * same as above (first 4)
21 | * each cell of each row is validated for errors and if a cell is found to have any error it is colored in RED
22 | * a new sheet in the same excel file is created detailing out the error messages (type) and the cell position (row, column)
23 | * the above modified file is returned (downloaded automatically to users screen) if errors exists
24 | * **Read data from excel sheet to database**
25 | * endpoint exposing to download required excel sheet template (required columns)
26 | * sheet is validated for errors, if no errors are found a unique 6 digit code and the hex of the validated file is generated, the code is returned as response
27 | * the code is stored in a cache as key with the validated file's hex being it's value
28 | * user hits /employee/bulk-upload API with given code and validated file (error thrown if code is invalid or file other than the validated one is provided)
29 | * each row is read from the given sheet and corresponding records are created in the database
30 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007-present the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.6";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hardikSinghBehl/spring-boot-apache-POI/aabf92885ba7f9cc543772b2b1c6f7429ed31cf0/create-multiple-sheet-excel-file-from-database/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/README.md:
--------------------------------------------------------------------------------
1 | # Creating Multiple Sheet Excel File from Existing Database Records
2 |
3 | ###### POC to demonstrate Generating Excel file (.xlsx) with multiple sheet with data coming from a database using Apache-POI library.
4 |
5 |
6 | RUNNING APPLICATION (Swagger-ui)
7 |
8 |
9 | ## Tech Stack
10 |
11 | * Java 15
12 | * Spring Boot
13 | * Apache POI
14 | * H2 Database
15 | * Open-API (Swagger-ui)
16 |
17 | ## Application Flow
18 |
19 | There are two entites
20 | * SuperHeroe
21 | * MasterComic
22 |
23 | Superheroes have one to many relationship with masterComic
24 | * Batman belongs to detective comics
25 | * Superman belongs to detective comics
26 | * Detecive comic has List.of(Batman, Superman)
27 |
28 | Data is populated into the H2 DB on application startup using @PostConstruct
29 | * DataPopulationOnBootstrap.class
30 |
31 | Excel file is generated and downloaded with
32 | * Sheet containing records of Superheroes from detective comics
33 | * Sheet containing records of Superheroes from marvel comics
34 | * Sheet containing records of Superheroes from other comics
35 |
36 | ## Local Setup
37 |
38 | * Install Java 15
39 | * Install Maven
40 |
41 | Recommended way is to use [sdkman](https://sdkman.io/) for installing both maven and java
42 |
43 | Run the below commands in the core
44 |
45 | ```
46 | mvn clean install
47 | ```
48 |
49 | ```
50 | mvn spring-boot:run
51 |
52 | ```
53 |
54 | server port is configured to 8089 and base path to /bharta which can be changed in application.properties file
55 |
56 | Go to the below url to view swagger-ui (API docs)
57 |
58 | ```
59 | http://localhost:8089/bharta/swagger-ui.html
60 | ```
61 |
62 | https://user-images.githubusercontent.com/69693621/121804452-15d4de00-cc64-11eb-9ddd-4f6215c1ed8f.mp4
63 |
64 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
124 |
125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
162 | if ERRORLEVEL 1 goto error
163 | goto end
164 |
165 | :error
166 | set ERROR_CODE=1
167 |
168 | :end
169 | @endlocal & set ERROR_CODE=%ERROR_CODE%
170 |
171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
175 | :skipRcPost
176 |
177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
179 |
180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
181 |
182 | exit /B %ERROR_CODE%
183 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.boot
8 | spring-boot-starter-parent
9 | 2.5.0
10 |
11 |
12 | com.hardik
13 | create-multiple-sheet-excel-file-from-database
14 | 0.0.1-SNAPSHOT
15 | create-multiple-sheet-excel-file-from-database
16 | POC to generate multiple sheet excel file using apache-POI with data coming from a database
17 |
18 | 15
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-data-jpa
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-validation
32 |
33 |
34 | org.json
35 | json
36 | 20210307
37 |
38 |
39 | org.apache.poi
40 | poi
41 | 5.0.0
42 |
43 |
44 | org.apache.poi
45 | poi-ooxml
46 | 5.0.0
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-devtools
51 | runtime
52 | true
53 |
54 |
55 | com.h2database
56 | h2
57 | runtime
58 |
59 |
60 | org.projectlombok
61 | lombok
62 | true
63 |
64 |
65 | org.springdoc
66 | springdoc-openapi-ui
67 | 1.5.8
68 |
69 |
70 | org.springframework.boot
71 | spring-boot-starter-test
72 | test
73 |
74 |
75 | org.springframework.boot
76 | spring-boot-configuration-processor
77 | true
78 |
79 |
80 |
81 |
82 |
83 |
84 | org.springframework.boot
85 | spring-boot-maven-plugin
86 |
87 |
88 |
89 | org.projectlombok
90 | lombok
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/CreateMultipleSheetExcelFileFromDatabaseApplication.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class CreateMultipleSheetExcelFileFromDatabaseApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(CreateMultipleSheetExcelFileFromDatabaseApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/bootstrap/DataPopulationOnBootstrap.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.bootstrap;
2 |
3 | import java.util.List;
4 |
5 | import javax.annotation.PostConstruct;
6 |
7 | import org.springframework.stereotype.Component;
8 |
9 | import com.hardik.bharta.entity.MasterComic;
10 | import com.hardik.bharta.entity.SuperHero;
11 | import com.hardik.bharta.repository.MasterComicRepository;
12 | import com.hardik.bharta.repository.SuperHeroRepository;
13 |
14 | import lombok.AllArgsConstructor;
15 | import net.bytebuddy.utility.RandomString;
16 |
17 | @Component
18 | @AllArgsConstructor
19 | public class DataPopulationOnBootstrap {
20 |
21 | private final MasterComicRepository masterComicRepository;
22 | private final SuperHeroRepository superHeroRepository;
23 |
24 | @PostConstruct
25 | void populatingMasterComicData() {
26 | final var comicNameList = List.of("Detective Comics", "Marvel Comics", "Other");
27 |
28 | comicNameList.forEach(comicName -> {
29 | final var comic = new MasterComic();
30 | comic.setName(comicName);
31 | masterComicRepository.save(comic);
32 | });
33 | }
34 |
35 | @PostConstruct
36 | void populatingRealSuperHeroData() {
37 | final var superHeroDataList = List.of(List.of("BATMAN", "Bruce Wayne", 1),
38 | List.of("WONDER WOMAN", "Diana Prince", 1), List.of("SUPERMAN", "Clark Kent", 1),
39 | List.of("FLASH", "Barry Allen", 1), List.of("AQUAMAN", "Arthur Curry", 1),
40 | List.of("GREEN ARROW", "Oliver Queen", 1), List.of("MARTIAN MANHUNTER", "John Jones", 1),
41 | List.of("SPIDER MAN", "Peter Parker", 2), List.of("IRON MAN", "Tony Stark", 2),
42 | List.of("HULK", "Bruce Banner", 2), List.of("THOR", "Donald Blake", 2),
43 | List.of("CAPTAIN AMERICA", "Steve Rogers", 2), List.of("BLACK WIDOW", "Natasha Romanoff", 2));
44 |
45 | superHeroDataList.forEach(superHeroData -> {
46 | final var superHero = new SuperHero();
47 | superHero.setName(((String) superHeroData.get(0)));
48 | superHero.setAlterEgo(((String) superHeroData.get(1)));
49 | superHero.setMasterComicId(((Integer) superHeroData.get(2)));
50 | superHeroRepository.save(superHero);
51 | });
52 | }
53 |
54 | @PostConstruct
55 | void populatingRandomSuperHeroData() {
56 | for (int count = 0; count <= 30; count++) {
57 | final var superHero = new SuperHero();
58 | superHero.setAlterEgo(RandomString.make(5));
59 | superHero.setName(RandomString.make(4) + RandomString.make(7));
60 | superHero.setMasterComicId(3);
61 | superHeroRepository.save(superHero);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/configuration/OpenApiConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.configuration;
2 |
3 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 |
7 | import com.hardik.bharta.configuration.properties.OpenApiConfigurationProperties;
8 |
9 | import io.swagger.v3.oas.models.OpenAPI;
10 | import io.swagger.v3.oas.models.info.Contact;
11 | import io.swagger.v3.oas.models.info.Info;
12 | import lombok.AllArgsConstructor;
13 |
14 | @Configuration
15 | @EnableConfigurationProperties(OpenApiConfigurationProperties.class)
16 | @AllArgsConstructor
17 | public class OpenApiConfiguration {
18 |
19 | private final OpenApiConfigurationProperties openApiConfigurationProperties;
20 |
21 | @Bean
22 | public OpenAPI customOpenAPI() {
23 | final var properties = openApiConfigurationProperties.getSwagger();
24 | final var contact = properties.getContact();
25 | final var info = new Info().title(properties.getTitle()).version(properties.getApiVersion())
26 | .description(properties.getDescription())
27 | .contact(new Contact().email(contact.getEmail()).name(contact.getName()).url(contact.getUrl()));
28 |
29 | return new OpenAPI().info(info);
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/configuration/properties/OpenApiConfigurationProperties.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.configuration.properties;
2 |
3 | import org.springframework.boot.context.properties.ConfigurationProperties;
4 |
5 | import lombok.Data;
6 |
7 | @Data
8 | @ConfigurationProperties(prefix = "com.hardik.bharta")
9 | public class OpenApiConfigurationProperties {
10 |
11 | private Swagger swagger = new Swagger();
12 |
13 | @Data
14 | public class Swagger {
15 | private String title;
16 | private String description;
17 | private String apiVersion;
18 |
19 | private Contact contact = new Contact();
20 |
21 | @Data
22 | public class Contact {
23 | private String email;
24 | private String name;
25 | private String url;
26 | }
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/constant/ApiConstant.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.constant;
2 |
3 | public class ApiConstant {
4 |
5 | public static final String EXCEL_CONTROLLER_BASE_PATH = "/excel";
6 | public static final String SUPERHERO_CONTROLLER_BASE_PATH = "/super-hero";
7 |
8 | public static final String GENERATE = "/generate";
9 | public static final String GENERATE_EXCEL_SUMMARY = "Creates excel file with distinct sheet for each comic's superheroes";
10 | public static final String CREATE_HERO_SUMMARY = "Creates super-hero record in system";
11 | public static final String GET_HERO_LIST_SUMMARY = "Returns list of superheroes stored in system";
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/controller/ExcelController.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.controller;
2 |
3 | import java.io.IOException;
4 |
5 | import org.springframework.core.io.InputStreamResource;
6 | import org.springframework.http.HttpStatus;
7 | import org.springframework.http.ResponseEntity;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.ResponseStatus;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import com.hardik.bharta.constant.ApiConstant;
14 | import com.hardik.bharta.excel.service.ExcelService;
15 |
16 | import io.swagger.v3.oas.annotations.Operation;
17 | import lombok.AllArgsConstructor;
18 |
19 | @RestController
20 | @RequestMapping(value = ApiConstant.EXCEL_CONTROLLER_BASE_PATH)
21 | @AllArgsConstructor
22 | public class ExcelController {
23 |
24 | private final ExcelService excelService;
25 |
26 | @GetMapping(value = ApiConstant.GENERATE)
27 | @ResponseStatus(value = HttpStatus.OK)
28 | @Operation(summary = ApiConstant.GENERATE_EXCEL_SUMMARY)
29 | public ResponseEntity generateAndDownloadExcelFile() throws IOException {
30 | return excelService.generate();
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/controller/SuperHeroController.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.controller;
2 |
3 | import java.util.List;
4 |
5 | import javax.validation.Valid;
6 |
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.http.MediaType;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.GetMapping;
11 | import org.springframework.web.bind.annotation.PostMapping;
12 | import org.springframework.web.bind.annotation.RequestBody;
13 | import org.springframework.web.bind.annotation.RequestMapping;
14 | import org.springframework.web.bind.annotation.ResponseStatus;
15 | import org.springframework.web.bind.annotation.RestController;
16 |
17 | import com.hardik.bharta.constant.ApiConstant;
18 | import com.hardik.bharta.dto.SuperHeroCreationRequestDto;
19 | import com.hardik.bharta.entity.SuperHero;
20 | import com.hardik.bharta.service.SuperHeroService;
21 |
22 | import io.swagger.v3.oas.annotations.Operation;
23 | import lombok.AllArgsConstructor;
24 |
25 | @RestController
26 | @RequestMapping(value = ApiConstant.SUPERHERO_CONTROLLER_BASE_PATH)
27 | @AllArgsConstructor
28 | public class SuperHeroController {
29 |
30 | private final SuperHeroService superHeroService;
31 |
32 | @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
33 | @ResponseStatus(value = HttpStatus.OK)
34 | @Operation(summary = ApiConstant.GET_HERO_LIST_SUMMARY)
35 | public ResponseEntity> superHeroRetreivalHandler() {
36 | return superHeroService.retreiveAll();
37 | }
38 |
39 | @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
40 | @ResponseStatus(value = HttpStatus.OK)
41 | @Operation(summary = ApiConstant.CREATE_HERO_SUMMARY)
42 | public ResponseEntity> superHeroCreationHandler(
43 | @Valid @RequestBody(required = true) final SuperHeroCreationRequestDto superHeroCreationRequest) {
44 | return superHeroService.create(superHeroCreationRequest);
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/dto/SuperHeroCreationRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.dto;
2 |
3 | import javax.validation.constraints.DecimalMax;
4 | import javax.validation.constraints.DecimalMin;
5 | import javax.validation.constraints.NotBlank;
6 | import javax.validation.constraints.NotNull;
7 |
8 | import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
9 |
10 | import io.swagger.v3.oas.annotations.media.Schema;
11 | import lombok.Builder;
12 | import lombok.Getter;
13 |
14 | @Getter
15 | @Builder
16 | @JacksonStdImpl
17 | public class SuperHeroCreationRequestDto {
18 |
19 | @Schema(description = "Superhero name", required = true, example = "SomethingMan")
20 | @NotBlank(message = "superhero name must not be empty")
21 | private final String name;
22 |
23 | @Schema(description = "Superhero alter-ego name", required = true, example = "Ordinary Anything Name")
24 | @NotBlank(message = "superhero alter-ego name must not be empty")
25 | private final String alterEgoName;
26 |
27 | @Schema(description = "1 for Detective Comics, 2 for Marvel Comics", required = true, example = "2")
28 | @NotNull(message = "comic-id must not be null")
29 | @DecimalMin(value = "1", message = "comic-id value must be either 1 ,2 or 3")
30 | @DecimalMax(value = "3", message = "comic-id value must be either 1 ,2 or 3")
31 | private final Integer comicId;
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/entity/MasterComic.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.entity;
2 |
3 | import java.io.Serializable;
4 | import java.util.List;
5 |
6 | import javax.persistence.Column;
7 | import javax.persistence.Entity;
8 | import javax.persistence.FetchType;
9 | import javax.persistence.GeneratedValue;
10 | import javax.persistence.GenerationType;
11 | import javax.persistence.Id;
12 | import javax.persistence.OneToMany;
13 | import javax.persistence.Table;
14 |
15 | import com.fasterxml.jackson.annotation.JsonIgnore;
16 |
17 | import io.swagger.v3.oas.annotations.Hidden;
18 | import lombok.Data;
19 | import lombok.EqualsAndHashCode.Exclude;
20 |
21 | @Data
22 | @Entity
23 | @Table(name = "master_comics")
24 | public class MasterComic implements Serializable {
25 |
26 | private static final long serialVersionUID = -3197702603107771751L;
27 |
28 | @Id
29 | @GeneratedValue(strategy = GenerationType.IDENTITY)
30 | @Column(name = "id", nullable = false, unique = true, updatable = false)
31 | private Integer id;
32 |
33 | @Column(name = "name", nullable = false, unique = true, length = 50)
34 | private String name;
35 |
36 | @Hidden
37 | @Exclude
38 | @JsonIgnore
39 | @OneToMany(mappedBy = "masterComic", fetch = FetchType.LAZY)
40 | private List superHeros;
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/entity/SuperHero.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.entity;
2 |
3 | import java.io.Serializable;
4 | import java.time.LocalDateTime;
5 | import java.util.UUID;
6 |
7 | import javax.persistence.Column;
8 | import javax.persistence.Entity;
9 | import javax.persistence.FetchType;
10 | import javax.persistence.GeneratedValue;
11 | import javax.persistence.GenerationType;
12 | import javax.persistence.Id;
13 | import javax.persistence.JoinColumn;
14 | import javax.persistence.ManyToOne;
15 | import javax.persistence.PrePersist;
16 | import javax.persistence.PreUpdate;
17 | import javax.persistence.Table;
18 |
19 | import io.swagger.v3.oas.annotations.Hidden;
20 | import lombok.Data;
21 | import lombok.EqualsAndHashCode.Exclude;
22 |
23 | @Data
24 | @Entity
25 | @Table(name = "super_hero")
26 | public class SuperHero implements Serializable {
27 |
28 | private static final long serialVersionUID = -3420777030541125428L;
29 |
30 | @Id
31 | @GeneratedValue(strategy = GenerationType.AUTO)
32 | @Column(name = "id", nullable = false, unique = true, updatable = false)
33 | private UUID id;
34 |
35 | @Column(name = "name", nullable = false, unique = true)
36 | private String name;
37 |
38 | @Column(name = "alter_ego", nullable = false)
39 | private String alterEgo;
40 |
41 | @Column(name = "comic_id", nullable = false)
42 | private Integer masterComicId;
43 |
44 | @Hidden
45 | @Exclude
46 | @ManyToOne(optional = false, fetch = FetchType.EAGER)
47 | @JoinColumn(name = "comic_id", nullable = false, insertable = false, updatable = false)
48 | private MasterComic masterComic;
49 |
50 | @Column(name = "created_at", nullable = false)
51 | private LocalDateTime createdAt;
52 |
53 | @Column(name = "updated_at", nullable = false, updatable = false)
54 | private LocalDateTime updatedAt;
55 |
56 | @PrePersist
57 | void onCreate() {
58 | this.id = UUID.randomUUID();
59 | this.createdAt = LocalDateTime.now();
60 | this.updatedAt = LocalDateTime.now();
61 | }
62 |
63 | @PreUpdate
64 | void onUpdate() {
65 | this.updatedAt = LocalDateTime.now();
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/excel/service/ExcelService.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.excel.service;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.IOException;
6 | import java.util.List;
7 |
8 | import org.apache.poi.xssf.usermodel.XSSFRow;
9 | import org.apache.poi.xssf.usermodel.XSSFSheet;
10 | import org.apache.poi.xssf.usermodel.XSSFWorkbook;
11 | import org.springframework.core.io.InputStreamResource;
12 | import org.springframework.http.HttpHeaders;
13 | import org.springframework.http.HttpStatus;
14 | import org.springframework.http.MediaType;
15 | import org.springframework.http.ResponseEntity;
16 | import org.springframework.stereotype.Service;
17 |
18 | import com.hardik.bharta.entity.SuperHero;
19 | import com.hardik.bharta.excel.utility.ExcelCellUtils;
20 | import com.hardik.bharta.repository.MasterComicRepository;
21 |
22 | import lombok.AllArgsConstructor;
23 |
24 | @Service
25 | @AllArgsConstructor
26 | public class ExcelService {
27 |
28 | private final MasterComicRepository masterComicRepository;
29 | private final List workSheetNames = List.of("Detective Comics", "Marvel Comics", "Other");
30 | private final List columnNames = List.of("ID", "Name", "Alter Ego", "Comic", "Created-At");
31 | private final XSSFWorkbook workBook = new XSSFWorkbook();
32 |
33 | public ResponseEntity generate() throws IOException {
34 |
35 | workSheetNames.forEach(workSheetName -> {
36 | final var workSheet = workBook.createSheet(workSheetName);
37 | final var initialRow = workSheet.createRow(0);
38 | writeInitialRow(initialRow);
39 | writeSuperHeroDataInSheet(workSheet, masterComicRepository.findByName(workSheetName).get().getSuperHeros());
40 | autoSizeColumns(workSheet);
41 | });
42 |
43 | final var outputStream = new ByteArrayOutputStream();
44 | workBook.write(outputStream);
45 |
46 | workBook.close();
47 | return ResponseEntity.status(HttpStatus.OK)
48 | .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=Superheroes.xlsx")
49 | .contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
50 | .body(new InputStreamResource(new ByteArrayInputStream(outputStream.toByteArray())));
51 | }
52 |
53 | private void writeInitialRow(final XSSFRow initialRow) {
54 | // To make heading row's font bold
55 | final var style = workBook.createCellStyle();
56 | final var font = workBook.createFont();
57 | font.setBold(true);
58 | style.setFont(font);
59 |
60 | // Writing heading cell names in inital-row
61 | for (int column = 0; column < columnNames.size(); column++) {
62 | final var cell = initialRow.createCell(column);
63 | cell.setCellStyle(style);
64 | cell.setCellValue(columnNames.get(column));
65 | }
66 | }
67 |
68 | private void autoSizeColumns(final XSSFSheet workSheet) {
69 | for (int column = 0; column < columnNames.size(); column++) {
70 | workSheet.autoSizeColumn(column);
71 | }
72 | }
73 |
74 | private void writeSuperHeroDataInSheet(final XSSFSheet workSheet, final List superHeroes) {
75 | for (int row = 0; row < superHeroes.size(); row++) {
76 |
77 | // making a new row representing the current employee
78 | final var currentRow = workSheet.createRow(row + 1);
79 |
80 | // populating current employees data in columns
81 | for (int column = 0; column < columnNames.size(); column++) {
82 | final var currentCell = currentRow.createCell(column);
83 | final var currentSuperHero = superHeroes.get(row);
84 | currentCell.setCellValue(ExcelCellUtils.getValue(column, currentSuperHero));
85 | }
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/excel/utility/ExcelCellUtils.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.excel.utility;
2 |
3 | import com.hardik.bharta.entity.SuperHero;
4 |
5 | public class ExcelCellUtils {
6 |
7 | public static String getValue(final int columnIndex, final SuperHero superHero) {
8 | switch (columnIndex) {
9 | case 0: {
10 | return superHero.getId().toString();
11 | }
12 | case 1: {
13 | return superHero.getName();
14 | }
15 | case 2: {
16 | return superHero.getAlterEgo();
17 | }
18 | case 3: {
19 | return superHero.getMasterComic().getName();
20 | }
21 | case 4: {
22 | return superHero.getCreatedAt().toString();
23 | }
24 | default:
25 | throw new IllegalArgumentException("Unexpected value: " + columnIndex);
26 | }
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/exception/DuplicateSuperHeroNameException.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.exception;
2 |
3 | public class DuplicateSuperHeroNameException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = -1835179058201713965L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/exception/handler/DuplicateSuperHeroNameExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 |
5 | import org.json.JSONObject;
6 | import org.springframework.core.Ordered;
7 | import org.springframework.core.annotation.Order;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.ControllerAdvice;
11 | import org.springframework.web.bind.annotation.ExceptionHandler;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 | import org.springframework.web.bind.annotation.ResponseStatus;
14 |
15 | import com.hardik.bharta.exception.DuplicateSuperHeroNameException;
16 |
17 | @Order(Ordered.HIGHEST_PRECEDENCE)
18 | @ControllerAdvice
19 | public class DuplicateSuperHeroNameExceptionHandler {
20 |
21 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
22 | @ResponseBody
23 | @ExceptionHandler(DuplicateSuperHeroNameException.class)
24 | public ResponseEntity> duplicateSuperHeroNameViolation(DuplicateSuperHeroNameException ex) {
25 |
26 | final var response = new JSONObject();
27 | response.put("status", "Failure");
28 | response.put("message", "Super Hero with specified name already exists in the system");
29 | response.put("timestamp", LocalDateTime.now().toString());
30 | return ResponseEntity.badRequest().body(response.toString());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/exception/handler/ValidationFailureExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 | import java.util.List;
5 |
6 | import org.json.JSONObject;
7 | import org.springframework.core.Ordered;
8 | import org.springframework.core.annotation.Order;
9 | import org.springframework.http.HttpStatus;
10 | import org.springframework.http.ResponseEntity;
11 | import org.springframework.validation.BindingResult;
12 | import org.springframework.validation.FieldError;
13 | import org.springframework.web.bind.MethodArgumentNotValidException;
14 | import org.springframework.web.bind.annotation.ControllerAdvice;
15 | import org.springframework.web.bind.annotation.ExceptionHandler;
16 | import org.springframework.web.bind.annotation.ResponseBody;
17 | import org.springframework.web.bind.annotation.ResponseStatus;
18 |
19 | @Order(Ordered.HIGHEST_PRECEDENCE)
20 | @ControllerAdvice
21 | public class ValidationFailureExceptionHandler {
22 |
23 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
24 | @ResponseBody
25 | @ExceptionHandler(MethodArgumentNotValidException.class)
26 | public ResponseEntity> methodArgumentNotValidException(MethodArgumentNotValidException ex) {
27 | BindingResult result = ex.getBindingResult();
28 | List fieldErrors = result.getFieldErrors();
29 | String errorMessage = fieldErrors.get(0).getDefaultMessage();
30 |
31 | final var response = new JSONObject();
32 | response.put("status", "Failure");
33 | response.put("message", errorMessage);
34 | response.put("timestamp", LocalDateTime.now().toString());
35 | return ResponseEntity.badRequest().body(response.toString());
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/repository/MasterComicRepository.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.repository;
2 |
3 | import java.util.Optional;
4 |
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import com.hardik.bharta.entity.MasterComic;
9 |
10 | @Repository
11 | public interface MasterComicRepository extends JpaRepository {
12 |
13 | Optional findByName(String name);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/repository/SuperHeroRepository.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.repository;
2 |
3 | import java.util.UUID;
4 |
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import com.hardik.bharta.entity.SuperHero;
9 |
10 | @Repository
11 | public interface SuperHeroRepository extends JpaRepository {
12 |
13 | boolean existsByName(String name);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/java/com/hardik/bharta/service/SuperHeroService.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta.service;
2 |
3 | import java.util.List;
4 |
5 | import org.json.JSONObject;
6 | import org.springframework.http.ResponseEntity;
7 | import org.springframework.stereotype.Service;
8 |
9 | import com.hardik.bharta.dto.SuperHeroCreationRequestDto;
10 | import com.hardik.bharta.entity.SuperHero;
11 | import com.hardik.bharta.exception.DuplicateSuperHeroNameException;
12 | import com.hardik.bharta.repository.SuperHeroRepository;
13 |
14 | import lombok.AllArgsConstructor;
15 |
16 | @Service
17 | @AllArgsConstructor
18 | public class SuperHeroService {
19 |
20 | private final SuperHeroRepository superHeroRepository;
21 |
22 | public ResponseEntity> retreiveAll() {
23 | return ResponseEntity.ok(superHeroRepository.findAll());
24 | }
25 |
26 | public ResponseEntity> create(final SuperHeroCreationRequestDto superHeroCreationRequest) {
27 |
28 | if (existsByName(superHeroCreationRequest.getName()))
29 | throw new DuplicateSuperHeroNameException();
30 |
31 | final var superHero = new SuperHero();
32 | superHero.setName(superHeroCreationRequest.getName());
33 | superHero.setAlterEgo(superHeroCreationRequest.getAlterEgoName());
34 | superHero.setMasterComicId(superHeroCreationRequest.getComicId());
35 | superHeroRepository.save(superHero);
36 |
37 | return ResponseEntity.ok(new JSONObject().put("message", "Super hero created successfully").toString());
38 | }
39 |
40 | public boolean existsByName(final String name) {
41 | return superHeroRepository.existsByName(name);
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #PORT-PATH
2 | server.port=8089
3 | server.servlet.context-path=/bharta
4 |
5 | #Datasource
6 | spring.datasource.url=jdbc:h2:mem:bharta
7 | spring.datasource.driverClassName=org.h2.Driver
8 | spring.datasource.username=bharta
9 | spring.datasource.password=bharta
10 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
11 | spring.jpa.show-sql=true
12 |
13 | #OPEN-API
14 | com.hardik.bharta.swagger.title=Bharta
15 | com.hardik.bharta.swagger.description=POC to generate multiple sheet excel file from database records using apache-POI library
16 | com.hardik.bharta.swagger.api-version=1.0.0
17 | com.hardik.bharta.swagger.contact.name=Hardik Singh Behl
18 | com.hardik.bharta.swagger.contact.email=hardik.behl7444@gmail.com
19 | com.hardik.bharta.swagger.contact.url=https://www.linkedin.com/in/hardikSinghBehl
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/src/test/java/com/hardik/bharta/CreateMultipleSheetExcelFileFromDatabaseApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.hardik.bharta;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class CreateMultipleSheetExcelFileFromDatabaseApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/create-multiple-sheet-excel-file-from-database/system.properties:
--------------------------------------------------------------------------------
1 | java.runtime.version=15
--------------------------------------------------------------------------------
/create-single-excel-from-database/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007-present the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.6";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hardikSinghBehl/spring-boot-apache-POI/aabf92885ba7f9cc543772b2b1c6f7429ed31cf0/create-single-excel-from-database/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/create-single-excel-from-database/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/README.md:
--------------------------------------------------------------------------------
1 | # Creating Single Excel Sheet from Existing Database Records
2 |
3 | ###### POC to demonstrate Generating Excel file (.xlsx) with single sheet with data coming from a database using Apache-POI library.
4 |
5 |
6 | CLICK HERE TO VIEW API DOCS (Deployed Swagger-UI)
7 |
8 |
9 | ## Tech Stack
10 |
11 | * Java 15
12 | * Spring Boot
13 | * Apache POI
14 | * H2 Database
15 | * Open-API (Swagger-ui)
16 |
17 | ## Flow
18 |
19 | * 300 employees are saved into the database on startup with dummy values **(com.hardik.killercroc.bootstrap.EmployeeDataPopulationOnBootstrap.java)**
20 | * Controller endpoint is provided to create additional employees in the system
21 | * Controller endpoint to generate excel file representing all employees in the system
22 |
23 | ## Local Setup
24 |
25 | * Install Java 15
26 | * Install Maven
27 |
28 | Recommended way is to use [sdkman](https://sdkman.io/) for installing both maven and java
29 |
30 | Run the below commands in the core
31 |
32 | ```
33 | mvn clean install
34 | ```
35 |
36 | ```
37 | mvn spring-boot:run
38 |
39 | ```
40 |
41 | server port is configured to 8089 which can be changed in application.properties file
42 |
43 | Go to the below url to view swagger-ui (API docs)
44 |
45 | ```
46 | http://localhost:8089/swagger-ui.html
47 | ```
--------------------------------------------------------------------------------
/create-single-excel-from-database/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
124 |
125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
162 | if ERRORLEVEL 1 goto error
163 | goto end
164 |
165 | :error
166 | set ERROR_CODE=1
167 |
168 | :end
169 | @endlocal & set ERROR_CODE=%ERROR_CODE%
170 |
171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
175 | :skipRcPost
176 |
177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
179 |
180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
181 |
182 | exit /B %ERROR_CODE%
183 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.boot
8 | spring-boot-starter-parent
9 | 2.5.0
10 |
11 |
12 | com.hardik
13 | create-excel-from-database
14 | 0.0.1-SNAPSHOT
15 | create-single-excel-from-database
16 | POC to generate single excel sheet using apache-POI with data coming from a database
17 |
18 | 15
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-data-jpa
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-validation
32 |
33 |
34 | org.json
35 | json
36 | 20210307
37 |
38 |
39 | org.apache.poi
40 | poi
41 | 5.0.0
42 |
43 |
44 | org.apache.poi
45 | poi-ooxml
46 | 5.0.0
47 |
48 |
49 | org.springframework.boot
50 | spring-boot-devtools
51 | runtime
52 | true
53 |
54 |
55 | org.springdoc
56 | springdoc-openapi-ui
57 | 1.5.8
58 |
59 |
60 | com.h2database
61 | h2
62 | runtime
63 |
64 |
65 | org.projectlombok
66 | lombok
67 | true
68 |
69 |
70 | org.springframework.boot
71 | spring-boot-starter-test
72 | test
73 |
74 |
75 | org.springframework.boot
76 | spring-boot-configuration-processor
77 | true
78 |
79 |
80 |
81 |
82 |
83 |
84 | org.springframework.boot
85 | spring-boot-maven-plugin
86 |
87 |
88 |
89 | org.projectlombok
90 | lombok
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/CreateSingleExcelFromDatabaseApplication.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class CreateSingleExcelFromDatabaseApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(CreateSingleExcelFromDatabaseApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/bootstrap/EmployeeDataPopulationOnBootstrap.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.bootstrap;
2 |
3 | import java.time.LocalDate;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.Random;
7 |
8 | import javax.annotation.PostConstruct;
9 |
10 | import org.springframework.stereotype.Component;
11 |
12 | import com.hardik.killercroc.entity.Employee;
13 | import com.hardik.killercroc.repository.EmployeeRepository;
14 |
15 | import lombok.AllArgsConstructor;
16 | import net.bytebuddy.utility.RandomString;
17 |
18 | @Component
19 | @AllArgsConstructor
20 | public class EmployeeDataPopulationOnBootstrap {
21 |
22 | private final EmployeeRepository employeeRepository;
23 |
24 | @PostConstruct
25 | void populatingEmployeeDataInsideInMemoryDatabaseOnStartup() {
26 | final var employeeList = new ArrayList();
27 | final var random = new Random();
28 | final var jobTitleList = List.of("Backend Developer", "Frontend Developer", "Database Admin", "Designer",
29 | "Human Resource Manager", "Project manager", "Android Developer", "Web Developer", "System Engineer");
30 |
31 | for (int i = 1; i < 300; i++) {
32 | final var employee = new Employee();
33 | employee.setActive(random.nextInt(2) == 0 ? true : false);
34 | employee.setDateOfBirth(LocalDate.of(random.ints(1, 1950, 2001).sum(), random.ints(1, 1, 13).sum(),
35 | random.ints(1, 1, 26).sum()));
36 | employee.setFirstName(RandomString.make(7));
37 | employee.setLastName(RandomString.make(7));
38 | employee.setMiddleName(random.nextInt(2) == 0 ? RandomString.make(10) : null);
39 | employee.setEmailId(employee.getFirstName() + "." + employee.getLastName() + "@thelattice.in");
40 | employee.setJoiningDate(LocalDate.of(random.ints(1, 1989, 2021).sum(), random.ints(1, 1, 13).sum(),
41 | random.ints(1, 1, 26).sum()));
42 | employee.setJobTitle(jobTitleList.stream().skip(random.nextInt(jobTitleList.size())).findFirst().get());
43 | employeeList.add(employee);
44 | }
45 |
46 | employeeRepository.saveAll(employeeList);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/configuration/OpenApiConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.configuration;
2 |
3 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 |
7 | import com.hardik.killercroc.configuration.properties.OpenApiConfigurationProperties;
8 |
9 | import io.swagger.v3.oas.models.OpenAPI;
10 | import io.swagger.v3.oas.models.info.Contact;
11 | import io.swagger.v3.oas.models.info.Info;
12 | import lombok.AllArgsConstructor;
13 |
14 | @Configuration
15 | @EnableConfigurationProperties(OpenApiConfigurationProperties.class)
16 | @AllArgsConstructor
17 | public class OpenApiConfiguration {
18 |
19 | private final OpenApiConfigurationProperties openApiConfigurationProperties;
20 |
21 | @Bean
22 | public OpenAPI customOpenAPI() {
23 | final var properties = openApiConfigurationProperties.getProperties();
24 | final var contact = properties.getContact();
25 | final var info = new Info().title(properties.getTitle()).version(properties.getApiVersion())
26 | .description(properties.getDescription())
27 | .contact(new Contact().email(contact.getEmail()).name(contact.getName()).url(contact.getUrl()));
28 |
29 | return new OpenAPI().info(info);
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/configuration/properties/OpenApiConfigurationProperties.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.configuration.properties;
2 |
3 | import org.springframework.boot.context.properties.ConfigurationProperties;
4 |
5 | import lombok.Data;
6 |
7 | @Data
8 | @ConfigurationProperties(prefix = "com.hardik.killercroc.swagger")
9 | public class OpenApiConfigurationProperties {
10 |
11 | private Properties properties = new Properties();
12 |
13 | @Data
14 | public class Properties {
15 | private String title;
16 | private String description;
17 | private String apiVersion;
18 |
19 | private Contact contact = new Contact();
20 |
21 | @Data
22 | public class Contact {
23 | private String email;
24 | private String name;
25 | private String url;
26 | }
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/constant/ApiConstant.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.constant;
2 |
3 | public class ApiConstant {
4 |
5 | public static final String EXCEL_CONTROLLER_BASE_PATH = "/excel";
6 | public static final String EMPLOYEE_CONTROLLER_BASE_PATH = "/employee";
7 |
8 | public static final String CREATE_EMPLOYEE_SUMMARY = "Creates a new employee record in the system";
9 | public static final String GENERATE_EXCEL_SUMMARY = "generates excel sheet of all employee records in system";
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/controller/EmployeeController.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.controller;
2 |
3 | import javax.validation.Valid;
4 |
5 | import org.springframework.http.HttpStatus;
6 | import org.springframework.http.ResponseEntity;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 | import org.springframework.web.bind.annotation.RequestBody;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.ResponseStatus;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import com.hardik.killercroc.constant.ApiConstant;
14 | import com.hardik.killercroc.dto.EmployeeCreationRequestDto;
15 | import com.hardik.killercroc.service.EmployeeService;
16 |
17 | import io.swagger.v3.oas.annotations.Operation;
18 | import lombok.AllArgsConstructor;
19 |
20 | @RestController
21 | @AllArgsConstructor
22 | @RequestMapping(value = ApiConstant.EMPLOYEE_CONTROLLER_BASE_PATH)
23 | public class EmployeeController {
24 |
25 | private final EmployeeService employeeService;
26 |
27 | @PostMapping
28 | @ResponseStatus(value = HttpStatus.OK)
29 | @Operation(summary = ApiConstant.CREATE_EMPLOYEE_SUMMARY)
30 | public ResponseEntity> employeeCreationhandler(
31 | @Valid @RequestBody(required = true) final EmployeeCreationRequestDto employeeCreationRequestDto) {
32 | return employeeService.createEmployee(employeeCreationRequestDto);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/controller/ExcelController.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.controller;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.http.HttpServletResponse;
6 |
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.ResponseStatus;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import com.hardik.killercroc.constant.ApiConstant;
14 | import com.hardik.killercroc.excel.service.ExcelService;
15 |
16 | import io.swagger.v3.oas.annotations.Operation;
17 | import lombok.AllArgsConstructor;
18 |
19 | @RestController
20 | @AllArgsConstructor
21 | @RequestMapping(value = ApiConstant.EXCEL_CONTROLLER_BASE_PATH)
22 | public class ExcelController {
23 |
24 | private final ExcelService excelService;
25 |
26 | @GetMapping
27 | @ResponseStatus(value = HttpStatus.OK)
28 | @Operation(summary = ApiConstant.GENERATE_EXCEL_SUMMARY)
29 | public void employeeExcelGenerationHandler(final HttpServletResponse httpServletResponse) throws IOException {
30 | excelService.generate(httpServletResponse);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/dto/EmployeeCreationRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.dto;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javax.validation.constraints.Email;
6 | import javax.validation.constraints.NotBlank;
7 | import javax.validation.constraints.Past;
8 | import javax.validation.constraints.Size;
9 |
10 | import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
11 |
12 | import io.swagger.v3.oas.annotations.media.Schema;
13 | import lombok.Builder;
14 | import lombok.Getter;
15 |
16 | @Getter
17 | @Builder
18 | @JacksonStdImpl
19 | public class EmployeeCreationRequestDto {
20 |
21 | @Schema(description = "email-id of employee", required = true, example = "hardik.behl7444@gmail.com")
22 | @NotBlank(message = "Email-id must not be empty")
23 | @Email(message = "Email-id must be of a valid format")
24 | @Size(max = 50, message = "email-id must not exceed 50 characters")
25 | private final String emailId;
26 |
27 | @Schema(description = "first-name of employee", required = true, example = "Hardik")
28 | @NotBlank(message = "First-name must not be empty")
29 | @Size(max = 50, message = "first-name must not exceed 50 characters")
30 | private final String firstName;
31 |
32 | @Schema(description = "middle-name of employee", required = false, example = "Singh")
33 | @Size(max = 50, message = "middle-name must not exceed 50 characters")
34 | private final String middleName;
35 |
36 | @Schema(description = "last-name of employee", required = true, example = "Behl")
37 | @NotBlank(message = "Last-name must not be empty")
38 | @Size(max = 50, message = "last-name must not exceed 50 characters")
39 | private final String lastName;
40 |
41 | @Schema(description = "date-of-birth of employee", required = true, example = "1990-12-25")
42 | @NotBlank(message = "Date-of-birth must not be empty")
43 | @Past(message = "date-of-birth must be in the past")
44 | private final LocalDate dateOfBirth;
45 |
46 | @Schema(description = "joining-date of employee", required = true, example = "2021-05-14")
47 | @NotBlank(message = "joining-date must not be empty")
48 | private final LocalDate joiningDate;
49 |
50 | @Schema(description = "job-title of employee", required = true, example = "Backend Developer")
51 | @NotBlank(message = "Job-title must not be empty")
52 | private final String jobTitle;
53 |
54 | @Schema(description = "boolean flag to represent if employee is still working", required = true, example = "true")
55 | @NotBlank(message = "Active field must not be empty")
56 | private final boolean active;
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/entity/Employee.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.entity;
2 |
3 | import java.io.Serializable;
4 | import java.time.LocalDate;
5 | import java.util.UUID;
6 |
7 | import javax.persistence.Column;
8 | import javax.persistence.Entity;
9 | import javax.persistence.GeneratedValue;
10 | import javax.persistence.GenerationType;
11 | import javax.persistence.Id;
12 | import javax.persistence.PrePersist;
13 | import javax.persistence.Table;
14 |
15 | import lombok.Data;
16 |
17 | @Data
18 | @Entity
19 | @Table(name = "employees")
20 | public class Employee implements Serializable {
21 |
22 | private static final long serialVersionUID = -9050953080264878033L;
23 |
24 | @Id
25 | @GeneratedValue(strategy = GenerationType.AUTO)
26 | @Column(name = "id", nullable = false, unique = true, updatable = false)
27 | private UUID id;
28 |
29 | @Column(name = "emailId", nullable = false, unique = true, length = 50)
30 | private String emailId;
31 |
32 | @Column(name = "first_name", nullable = false, length = 50)
33 | private String firstName;
34 |
35 | @Column(name = "middle_name", nullable = true, length = 50)
36 | private String middleName;
37 |
38 | @Column(name = "last_name", nullable = false, length = 50)
39 | private String lastName;
40 |
41 | @Column(name = "date_of_birth", nullable = true)
42 | private LocalDate dateOfBirth;
43 |
44 | @Column(name = "joining_date", nullable = false)
45 | private LocalDate joiningDate;
46 |
47 | @Column(name = "job_title", nullable = false)
48 | private String jobTitle;
49 |
50 | @Column(name = "is_active", nullable = false)
51 | private boolean active;
52 |
53 | @PrePersist
54 | void onCreate() {
55 | this.id = UUID.randomUUID();
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/excel/service/ExcelService.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.excel.service;
2 |
3 | import java.io.BufferedOutputStream;
4 | import java.io.IOException;
5 | import java.util.List;
6 |
7 | import javax.servlet.http.HttpServletResponse;
8 |
9 | import org.apache.poi.xssf.usermodel.XSSFWorkbook;
10 | import org.springframework.http.HttpHeaders;
11 | import org.springframework.stereotype.Service;
12 |
13 | import com.hardik.killercroc.service.EmployeeService;
14 | import com.hardik.killercroc.utility.ExcelCellUtils;
15 |
16 | import lombok.AllArgsConstructor;
17 |
18 | @Service
19 | @AllArgsConstructor
20 | public class ExcelService {
21 |
22 | private final EmployeeService employeeService;
23 | private final List columnNameList = List.of("id", "email-id", "date-of-birth", "first-name", "middle-name",
24 | "last-name", "job-title", "joining-date", "is-active");
25 |
26 | public void generate(final HttpServletResponse response) throws IOException {
27 | response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=employee-record.xlsx");
28 | final var outputStream = new BufferedOutputStream(response.getOutputStream());
29 | final var employees = employeeService.getAllEmployees();
30 | final var workBook = new XSSFWorkbook();
31 | final var workSheet = workBook.createSheet("Employee Records");
32 | final var initialRow = workSheet.createRow(0);
33 |
34 | // To make heading row's font bold
35 | final var style = workBook.createCellStyle();
36 | final var font = workBook.createFont();
37 | font.setBold(true);
38 | style.setFont(font);
39 |
40 | // Writing heading cell names in inital-row
41 | for (int column = 0; column < columnNameList.size(); column++) {
42 | final var cell = initialRow.createCell(column);
43 | cell.setCellStyle(style);
44 | cell.setCellValue(columnNameList.get(column));
45 | }
46 |
47 | // Iterating over each employee
48 | for (int row = 0; row < employees.size(); row++) {
49 |
50 | // making a new row representing the current employee
51 | final var currentRow = workSheet.createRow(row + 1);
52 |
53 | // populating current employees data in columns
54 | for (int column = 0; column < columnNameList.size(); column++) {
55 | final var currentCell = currentRow.createCell(column);
56 | final var currentEmployee = employees.get(row);
57 | currentCell.setCellValue(ExcelCellUtils.getValue(column, currentEmployee));
58 | }
59 |
60 | }
61 |
62 | // auto sizing each column in worksheet
63 | for (int column = 0; column < columnNameList.size(); column++) {
64 | workSheet.autoSizeColumn(column);
65 | }
66 |
67 | workBook.write(outputStream);
68 | workBook.close();
69 | outputStream.close();
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/exception/handler/ValidationFailureExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 | import java.util.List;
5 |
6 | import org.json.JSONObject;
7 | import org.springframework.core.Ordered;
8 | import org.springframework.core.annotation.Order;
9 | import org.springframework.http.HttpStatus;
10 | import org.springframework.http.ResponseEntity;
11 | import org.springframework.validation.BindingResult;
12 | import org.springframework.validation.FieldError;
13 | import org.springframework.web.bind.MethodArgumentNotValidException;
14 | import org.springframework.web.bind.annotation.ControllerAdvice;
15 | import org.springframework.web.bind.annotation.ExceptionHandler;
16 | import org.springframework.web.bind.annotation.ResponseBody;
17 | import org.springframework.web.bind.annotation.ResponseStatus;
18 |
19 | @Order(Ordered.HIGHEST_PRECEDENCE)
20 | @ControllerAdvice
21 | public class ValidationFailureExceptionHandler {
22 |
23 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
24 | @ResponseBody
25 | @ExceptionHandler(MethodArgumentNotValidException.class)
26 | public ResponseEntity> methodArgumentNotValidException(MethodArgumentNotValidException ex) {
27 | BindingResult result = ex.getBindingResult();
28 | List fieldErrors = result.getFieldErrors();
29 | String errorMessage = fieldErrors.get(0).getDefaultMessage();
30 |
31 | final var response = new JSONObject();
32 | response.put("status", "Failure");
33 | response.put("message", errorMessage);
34 | response.put("timestamp", LocalDateTime.now().toString());
35 | return ResponseEntity.badRequest().body(response.toString());
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/repository/EmployeeRepository.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.repository;
2 |
3 | import java.util.UUID;
4 |
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import com.hardik.killercroc.entity.Employee;
9 |
10 | @Repository
11 | public interface EmployeeRepository extends JpaRepository {
12 |
13 | Boolean existsByEmailId(String emailId);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/service/EmployeeService.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.service;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.http.ResponseEntity;
6 | import org.springframework.stereotype.Service;
7 |
8 | import com.hardik.killercroc.dto.EmployeeCreationRequestDto;
9 | import com.hardik.killercroc.entity.Employee;
10 | import com.hardik.killercroc.repository.EmployeeRepository;
11 |
12 | import lombok.AllArgsConstructor;
13 |
14 | @Service
15 | @AllArgsConstructor
16 | public class EmployeeService {
17 |
18 | private final EmployeeRepository employeeRepository;
19 |
20 | public ResponseEntity> createEmployee(final EmployeeCreationRequestDto employeeCreationRequestDto) {
21 |
22 | if (employeeRepository.existsByEmailId(employeeCreationRequestDto.getEmailId()))
23 | return ResponseEntity.badRequest().body("Duplicate Email-id provided");
24 |
25 | final var employee = new Employee();
26 | employee.setActive(employeeCreationRequestDto.isActive());
27 | employee.setDateOfBirth(employeeCreationRequestDto.getDateOfBirth());
28 | employee.setEmailId(employeeCreationRequestDto.getEmailId());
29 | employee.setFirstName(employeeCreationRequestDto.getFirstName());
30 | employee.setJobTitle(employeeCreationRequestDto.getJobTitle());
31 | employee.setJoiningDate(employeeCreationRequestDto.getJoiningDate());
32 | employee.setLastName(employeeCreationRequestDto.getLastName());
33 | employee.setMiddleName(employeeCreationRequestDto.getMiddleName());
34 |
35 | employeeRepository.save(employee);
36 | return ResponseEntity.ok("Employee Saved Successfully");
37 | }
38 |
39 | public List getAllEmployees() {
40 | return employeeRepository.findAll();
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/java/com/hardik/killercroc/utility/ExcelCellUtils.java:
--------------------------------------------------------------------------------
1 | package com.hardik.killercroc.utility;
2 |
3 | import com.hardik.killercroc.entity.Employee;
4 |
5 | public class ExcelCellUtils {
6 |
7 | public static String getValue(final int columnIndex, final Employee employee) {
8 | switch (columnIndex) {
9 | case 0: {
10 | return employee.getId().toString();
11 | }
12 | case 1: {
13 | return employee.getEmailId();
14 | }
15 | case 2: {
16 | return employee.getDateOfBirth().toString();
17 | }
18 | case 3: {
19 | return employee.getFirstName();
20 | }
21 | case 4: {
22 | return employee.getMiddleName();
23 | }
24 | case 5: {
25 | return employee.getLastName();
26 | }
27 | case 6: {
28 | return employee.getJobTitle();
29 | }
30 | case 7: {
31 | return employee.getJoiningDate().toString();
32 | }
33 | case 8: {
34 | return employee.isActive() ? "true" : "false";
35 | }
36 | default:
37 | throw new IllegalArgumentException("Unexpected value: " + columnIndex);
38 | }
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/create-single-excel-from-database/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #PORT-PATH
2 | server.port=8089
3 | server.servlet.context-path=/killercroc
4 |
5 | #Datasource
6 | spring.datasource.url=jdbc:h2:mem:killercroc
7 | spring.datasource.driverClassName=org.h2.Driver
8 | spring.datasource.username=killercroc
9 | spring.datasource.password=killercroc
10 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
11 | spring.jpa.show-sql=true
12 |
13 | #OPEN-API
14 | com.hardik.killercroc.swagger.properties.title=Killercroc
15 | com.hardik.killercroc.swagger.properties.description=POC to generate single excel sheet from database records using apache-POI library
16 | com.hardik.killercroc.swagger.properties.api-version=1.0.0
17 | com.hardik.killercroc.swagger.properties.contact.name=Hardik Singh Behl
18 | com.hardik.killercroc.swagger.properties.contact.email=hardik.behl7444@gmail.com
19 | com.hardik.killercroc.swagger.properties.contact.url=https://www.linkedin.com/in/hardikSinghBehl
--------------------------------------------------------------------------------
/create-single-excel-from-database/system.properties:
--------------------------------------------------------------------------------
1 | java.runtime.version=15
--------------------------------------------------------------------------------
/read-excel-to-database/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/read-excel-to-database/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007-present the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.6";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/read-excel-to-database/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hardikSinghBehl/spring-boot-apache-POI/aabf92885ba7f9cc543772b2b1c6f7429ed31cf0/read-excel-to-database/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/read-excel-to-database/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/read-excel-to-database/README.md:
--------------------------------------------------------------------------------
1 | # Reading Validated Data From Excel Sheet And Storing In DB
2 |
3 | ###### POC to demonstrate reading data from excel file and storing records in database using apache POT library
4 |
5 |
6 | RUNNING APPLICATION (Swagger-ui)
7 |
8 |
9 | ## Application Flow
10 |
11 | * GET /excel/template API is hit to download excel template
12 | * POST /excel API is hit to validate data inside excel following above downloaded template
13 | * Unique 6 digit code is provided when the excel is validated and is stored in a cache as a key, the value of the key is the hash of the validated excel file
14 | * POST /employee/bulk-upload API is is hit with the provided code and the validated excel file
15 | * exception is thrown if code is invalid
16 | * exception is thrown if file other than the validated one is given (comparing file hashes with stored hash corresponding to given code in cache)
17 | * if code and excel files are valid, employee records are inserted into the database
18 |
19 | ## Tech Stack
20 |
21 | * Java 15
22 | * Spring Boot
23 | * Apache POI
24 | * H2 Database
25 | * Open-API (Swagger-ui)
26 |
27 | ## Local Setup
28 |
29 | * Install Java 15
30 | * Install Maven
31 |
32 | Recommended way is to use [sdkman](https://sdkman.io/) for installing both maven and java
33 |
34 | Run the below commands in the core
35 |
36 | ```
37 | mvn clean install
38 | ```
39 |
40 | ```
41 | mvn spring-boot:run
42 |
43 | ```
44 |
45 | server port is configured to 8089 and base path to /kofta which can be changed in application.properties file
46 |
47 | Go to the below url to view swagger-ui (API docs)
48 |
49 | ```
50 | http://localhost:8089/kofta/swagger-ui.html
51 | ```
52 |
53 |
54 | https://user-images.githubusercontent.com/69693621/121804360-96dfa580-cc63-11eb-8c5b-ae14d15d2871.mp4
55 |
56 |
--------------------------------------------------------------------------------
/read-excel-to-database/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
124 |
125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
162 | if ERRORLEVEL 1 goto error
163 | goto end
164 |
165 | :error
166 | set ERROR_CODE=1
167 |
168 | :end
169 | @endlocal & set ERROR_CODE=%ERROR_CODE%
170 |
171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
175 | :skipRcPost
176 |
177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
179 |
180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
181 |
182 | exit /B %ERROR_CODE%
183 |
--------------------------------------------------------------------------------
/read-excel-to-database/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.boot
8 | spring-boot-starter-parent
9 | 2.5.0
10 |
11 |
12 | com.hardik
13 | read-excel-to-database
14 | 0.0.1-SNAPSHOT
15 | read-excel-to-database
16 | POC to read excel sheet using apache-POI and storing data in SQL Database
17 |
18 | 15
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-data-jpa
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-validation
32 |
33 |
34 | com.google.code.gson
35 | gson
36 |
37 |
38 | commons-validator
39 | commons-validator
40 | 1.4.1
41 |
42 |
43 | org.json
44 | json
45 | 20210307
46 |
47 |
48 | org.apache.poi
49 | poi
50 | 5.0.0
51 |
52 |
53 | org.apache.poi
54 | poi-ooxml
55 | 5.0.0
56 |
57 |
58 | org.springdoc
59 | springdoc-openapi-ui
60 | 1.5.8
61 |
62 |
63 | com.google.guava
64 | guava
65 | 19.0
66 |
67 |
68 | org.springframework.boot
69 | spring-boot-devtools
70 | runtime
71 | true
72 |
73 |
74 | com.h2database
75 | h2
76 | runtime
77 |
78 |
79 | org.projectlombok
80 | lombok
81 | true
82 |
83 |
84 | org.springframework.boot
85 | spring-boot-starter-test
86 | test
87 |
88 |
89 | org.springframework.boot
90 | spring-boot-configuration-processor
91 | true
92 |
93 |
94 |
95 |
96 |
97 |
98 | org.springframework.boot
99 | spring-boot-maven-plugin
100 |
101 |
102 |
103 | org.projectlombok
104 | lombok
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/ReadExcelToDatabaseApplication.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ReadExcelToDatabaseApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ReadExcelToDatabaseApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/annotation/IsXlsx.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.annotation;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | @Target(ElementType.METHOD)
10 | @Retention(RetentionPolicy.RUNTIME)
11 | @Documented
12 | public @interface IsXlsx {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/annotation/aspect/CheckExcelFormatXlsxAspect.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.annotation.aspect;
2 |
3 | import java.util.concurrent.atomic.AtomicInteger;
4 |
5 | import org.aspectj.lang.JoinPoint;
6 | import org.aspectj.lang.annotation.Aspect;
7 | import org.aspectj.lang.annotation.Before;
8 | import org.aspectj.lang.reflect.CodeSignature;
9 | import org.springframework.stereotype.Component;
10 | import org.springframework.web.multipart.MultipartFile;
11 |
12 | import com.hardik.kofta.annotation.IsXlsx;
13 | import com.hardik.kofta.exception.InvalidExcelFileExtensionException;
14 |
15 | import lombok.RequiredArgsConstructor;
16 | import lombok.extern.slf4j.Slf4j;
17 |
18 | @Component
19 | @RequiredArgsConstructor
20 | @Aspect
21 | @Slf4j
22 | public class CheckExcelFormatXlsxAspect {
23 |
24 | private Integer headerArgumentPosition;
25 |
26 | @Before("execution(* *.*(..)) && @annotation(isXlsx)")
27 | public void checkIfExcelFileFormatIsValid(JoinPoint joinPoint, IsXlsx isXlsx) {
28 | log.info("Running Is Active Check On Method {}() in {}.class", joinPoint.getSignature().getName(),
29 | joinPoint.getSignature().getDeclaringType().getSimpleName());
30 |
31 | CodeSignature codeSignature = (CodeSignature) joinPoint.getSignature();
32 | AtomicInteger count = new AtomicInteger(0);
33 |
34 | for (int i = 0; i < codeSignature.getParameterNames().length; i++) {
35 | if (codeSignature.getParameterNames()[i].equalsIgnoreCase("file")) {
36 | headerArgumentPosition = count.get();
37 | break;
38 | } else
39 | count.incrementAndGet();
40 | }
41 |
42 | final var file = (MultipartFile) joinPoint.getArgs()[headerArgumentPosition];
43 |
44 | if (!file.getOriginalFilename().endsWith(".xlsx"))
45 | throw new InvalidExcelFileExtensionException();
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/bean/OtpCacheBean.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.bean;
2 |
3 | import java.util.concurrent.TimeUnit;
4 |
5 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 |
9 | import com.google.common.cache.CacheBuilder;
10 | import com.google.common.cache.CacheLoader;
11 | import com.google.common.cache.LoadingCache;
12 | import com.hardik.kofta.configuration.properties.ExcelCacheConfigurationProperties;
13 |
14 | import lombok.AllArgsConstructor;
15 |
16 | @Configuration
17 | @AllArgsConstructor
18 | @EnableConfigurationProperties(ExcelCacheConfigurationProperties.class)
19 | public class OtpCacheBean {
20 |
21 | private final ExcelCacheConfigurationProperties excelCacheConfigurationProperties;
22 |
23 | @Bean
24 | public LoadingCache loadingCache() {
25 | final var expirationMinutes = excelCacheConfigurationProperties.getCode().getExpirationMinutes();
26 | return CacheBuilder.newBuilder().expireAfterWrite(expirationMinutes, TimeUnit.MINUTES)
27 | .build(new CacheLoader<>() {
28 | public String load(Integer key) {
29 | return "";
30 | }
31 | });
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/configuration/OpenApiConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.configuration;
2 |
3 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 |
7 | import com.hardik.kofta.configuration.properties.OpenApiConfigurationProperties;
8 |
9 | import io.swagger.v3.oas.models.OpenAPI;
10 | import io.swagger.v3.oas.models.info.Contact;
11 | import io.swagger.v3.oas.models.info.Info;
12 | import lombok.AllArgsConstructor;
13 |
14 | @Configuration
15 | @EnableConfigurationProperties(OpenApiConfigurationProperties.class)
16 | @AllArgsConstructor
17 | public class OpenApiConfiguration {
18 |
19 | private final OpenApiConfigurationProperties openApiConfigurationProperties;
20 |
21 | @Bean
22 | public OpenAPI customOpenAPI() {
23 | final var properties = openApiConfigurationProperties.getProperties();
24 | final var contact = properties.getContact();
25 | final var info = new Info().title(properties.getTitle()).version(properties.getApiVersion())
26 | .description(properties.getDescription())
27 | .contact(new Contact().email(contact.getEmail()).name(contact.getName()).url(contact.getUrl()));
28 |
29 | return new OpenAPI().info(info);
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/configuration/properties/ExcelCacheConfigurationProperties.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.configuration.properties;
2 |
3 | import org.springframework.boot.context.properties.ConfigurationProperties;
4 |
5 | import lombok.Data;
6 |
7 | @Data
8 | @ConfigurationProperties(prefix = "com.hardik.kofta")
9 | public class ExcelCacheConfigurationProperties {
10 |
11 | private Code code = new Code();
12 |
13 | @Data
14 | public class Code {
15 | private Integer expirationMinutes;
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/configuration/properties/OpenApiConfigurationProperties.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.configuration.properties;
2 |
3 | import org.springframework.boot.context.properties.ConfigurationProperties;
4 |
5 | import lombok.Data;
6 |
7 | @Data
8 | @ConfigurationProperties(prefix = "com.hardik.kofta.swagger")
9 | public class OpenApiConfigurationProperties {
10 |
11 | private Properties properties = new Properties();
12 |
13 | @Data
14 | public class Properties {
15 | private String title;
16 | private String description;
17 | private String apiVersion;
18 |
19 | private Contact contact = new Contact();
20 |
21 | @Data
22 | public class Contact {
23 | private String email;
24 | private String name;
25 | private String url;
26 | }
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/constant/ApiPath.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.constant;
2 |
3 | public class ApiPath {
4 |
5 | public static final String EMPLOYEE_BASE_PATH = "/employee";
6 | public static final String ALL = "/all";
7 | public static final String BULK_UPLOAD = "/bulk-upload";
8 | public static final String EXCEL_BASE_PATH = "/excel";
9 | public static final String EXCEL_TEMPLATE = "/template";
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/constant/ApiSummary.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.constant;
2 |
3 | public class ApiSummary {
4 |
5 | public static final String EXCEL_TEMPLATE_DOWNLOAD = "Download excel file template";
6 | public static final String EXCEL_VALIDATE = "Validates Data in Excel File";
7 | public static final String EMPLOYEE_LIST = "Returns list of employees records in the system";
8 | public static final String BULK_UPLOAD = "bulk upload employee data in database";
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/controller/EmployeeController.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.controller;
2 |
3 | import java.io.IOException;
4 | import java.security.NoSuchAlgorithmException;
5 | import java.util.List;
6 | import java.util.concurrent.ExecutionException;
7 |
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.MediaType;
10 | import org.springframework.http.ResponseEntity;
11 | import org.springframework.web.bind.annotation.GetMapping;
12 | import org.springframework.web.bind.annotation.PostMapping;
13 | import org.springframework.web.bind.annotation.RequestMapping;
14 | import org.springframework.web.bind.annotation.RequestParam;
15 | import org.springframework.web.bind.annotation.ResponseStatus;
16 | import org.springframework.web.bind.annotation.RestController;
17 | import org.springframework.web.multipart.MultipartFile;
18 |
19 | import com.hardik.kofta.annotation.IsXlsx;
20 | import com.hardik.kofta.constant.ApiPath;
21 | import com.hardik.kofta.constant.ApiSummary;
22 | import com.hardik.kofta.entity.Employee;
23 | import com.hardik.kofta.service.EmployeeService;
24 |
25 | import io.swagger.v3.oas.annotations.Operation;
26 | import io.swagger.v3.oas.annotations.Parameter;
27 | import lombok.AllArgsConstructor;
28 |
29 | @RestController
30 | @RequestMapping(value = ApiPath.EMPLOYEE_BASE_PATH)
31 | @AllArgsConstructor
32 | public class EmployeeController {
33 |
34 | private final EmployeeService employeeService;
35 |
36 | @GetMapping(value = ApiPath.ALL, produces = MediaType.APPLICATION_JSON_VALUE)
37 | @ResponseStatus(value = HttpStatus.OK)
38 | @Operation(summary = ApiSummary.EMPLOYEE_LIST)
39 | public ResponseEntity> getEmployees() {
40 | return employeeService.retreiveEmployees();
41 | }
42 |
43 | @IsXlsx
44 | @PostMapping(value = ApiPath.BULK_UPLOAD, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
45 | @ResponseStatus(value = HttpStatus.OK)
46 | @Operation(summary = ApiSummary.BULK_UPLOAD)
47 | public ResponseEntity> bulkUploadEmployeeDataHandler(
48 | @Parameter @RequestParam(name = "code", required = true) final Integer code,
49 | @Parameter @RequestParam(name = "file", required = true) final MultipartFile file)
50 | throws NumberFormatException, ExecutionException, NoSuchAlgorithmException, IOException {
51 | return employeeService.bulkUpload(code, file);
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/controller/ExcelController.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.controller;
2 |
3 | import java.io.IOException;
4 | import java.security.NoSuchAlgorithmException;
5 |
6 | import org.springframework.core.io.InputStreamResource;
7 | import org.springframework.http.HttpHeaders;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.MediaType;
10 | import org.springframework.http.ResponseEntity;
11 | import org.springframework.web.bind.annotation.GetMapping;
12 | import org.springframework.web.bind.annotation.PostMapping;
13 | import org.springframework.web.bind.annotation.RequestMapping;
14 | import org.springframework.web.bind.annotation.RequestParam;
15 | import org.springframework.web.bind.annotation.ResponseStatus;
16 | import org.springframework.web.bind.annotation.RestController;
17 | import org.springframework.web.multipart.MultipartFile;
18 |
19 | import com.hardik.kofta.annotation.IsXlsx;
20 | import com.hardik.kofta.constant.ApiPath;
21 | import com.hardik.kofta.constant.ApiSummary;
22 | import com.hardik.kofta.excel.service.ExcelService;
23 |
24 | import io.swagger.v3.oas.annotations.Operation;
25 | import io.swagger.v3.oas.annotations.Parameter;
26 | import lombok.AllArgsConstructor;
27 |
28 | @RestController
29 | @AllArgsConstructor
30 | @RequestMapping(value = ApiPath.EXCEL_BASE_PATH)
31 | public class ExcelController {
32 |
33 | private final ExcelService excelService;
34 |
35 | @GetMapping(value = ApiPath.EXCEL_TEMPLATE)
36 | @ResponseStatus(value = HttpStatus.OK)
37 | @Operation(summary = ApiSummary.EXCEL_TEMPLATE_DOWNLOAD)
38 | public ResponseEntity excelTemplateFileDownloadHandler() throws IOException {
39 | final var template = Thread.currentThread().getContextClassLoader().getResourceAsStream("template.xlsx");
40 | return ResponseEntity.status(HttpStatus.OK)
41 | .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=template.xlsx")
42 | .contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
43 | .body(new InputStreamResource(template));
44 | }
45 |
46 | @IsXlsx
47 | @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
48 | @ResponseStatus(value = HttpStatus.OK)
49 | @Operation(summary = ApiSummary.EXCEL_VALIDATE)
50 | public ResponseEntity> validateExcelFileHandler(
51 | @Parameter @RequestParam(name = "file", required = true) final MultipartFile file)
52 | throws IOException, NoSuchAlgorithmException {
53 | return excelService.validateData(file);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/entity/Employee.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.entity;
2 |
3 | import java.io.Serializable;
4 | import java.time.LocalDateTime;
5 | import java.util.UUID;
6 |
7 | import javax.persistence.Column;
8 | import javax.persistence.Entity;
9 | import javax.persistence.GeneratedValue;
10 | import javax.persistence.GenerationType;
11 | import javax.persistence.Id;
12 | import javax.persistence.PrePersist;
13 | import javax.persistence.Table;
14 |
15 | import lombok.Data;
16 |
17 | @Data
18 | @Entity
19 | @Table(name = "employees")
20 | public class Employee implements Serializable {
21 |
22 | private static final long serialVersionUID = 291742406510888152L;
23 |
24 | @Id
25 | @GeneratedValue(strategy = GenerationType.AUTO)
26 | @Column(name = "id", nullable = false, unique = true)
27 | private UUID id;
28 |
29 | @Column(name = "email_id", nullable = false, unique = true)
30 | private String emailId;
31 |
32 | @Column(name = "full_name", nullable = false)
33 | private String fullName;
34 |
35 | @Column(name = "salary_per_month", nullable = false)
36 | private Double salaryPerMonth;
37 |
38 | @Column(name = "created_at", nullable = false)
39 | private LocalDateTime createdAt;
40 |
41 | @PrePersist
42 | void onCreate() {
43 | this.id = UUID.randomUUID();
44 | this.createdAt = LocalDateTime.now();
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/excel/service/ExcelService.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.excel.service;
2 |
3 | import java.io.IOException;
4 | import java.security.MessageDigest;
5 | import java.security.NoSuchAlgorithmException;
6 | import java.time.LocalDateTime;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 | import java.util.Random;
10 |
11 | import javax.xml.bind.DatatypeConverter;
12 |
13 | import org.apache.commons.lang3.math.NumberUtils;
14 | import org.apache.commons.validator.EmailValidator;
15 | import org.apache.poi.ss.usermodel.DataFormatter;
16 | import org.apache.poi.xssf.usermodel.XSSFRow;
17 | import org.apache.poi.xssf.usermodel.XSSFWorkbook;
18 | import org.json.JSONObject;
19 | import org.springframework.http.HttpStatus;
20 | import org.springframework.http.ResponseEntity;
21 | import org.springframework.stereotype.Service;
22 | import org.springframework.web.multipart.MultipartFile;
23 |
24 | import com.google.common.cache.LoadingCache;
25 | import com.google.gson.Gson;
26 | import com.hardik.kofta.entity.Employee;
27 | import com.hardik.kofta.exception.InvalidTemplateFormatException;
28 | import com.hardik.kofta.repository.EmployeeRepository;
29 |
30 | import lombok.RequiredArgsConstructor;
31 |
32 | @Service
33 | @RequiredArgsConstructor
34 | public class ExcelService {
35 |
36 | private final List columnNames = List.of("Email-id", "Full-Name", "Salary");
37 | private final DataFormatter dataFormatter = new DataFormatter();
38 | private final EmployeeRepository employeeRepository;
39 | private final LoadingCache loadingCache;
40 |
41 | public ResponseEntity> validateData(final MultipartFile file) throws IOException, NoSuchAlgorithmException {
42 | final var workBook = new XSSFWorkbook(file.getInputStream());
43 | final var workSheet = workBook.getSheetAt(0);
44 | final var initialRow = workSheet.getRow(0);
45 | final var numberOfRowsInWorkSheet = workSheet.getLastRowNum();
46 | checkForValidFormat(workBook, initialRow);
47 | final var errorMessages = new ArrayList();
48 |
49 | for (int row = 0; row < numberOfRowsInWorkSheet; row++) {
50 | final var currentRow = workSheet.getRow(row + 1);
51 |
52 | for (int cell = 0; cell < currentRow.getLastCellNum(); cell++) {
53 | var currentCell = currentRow.getCell(cell);
54 | if (currentCell != null) {
55 | if (cell == 0)
56 | validateCellForEmail(dataFormatter.formatCellValue(currentCell), errorMessages, row + 1,
57 | cell + 1);
58 | if (cell == 1)
59 | validateCellForName(dataFormatter.formatCellValue(currentCell), errorMessages, row + 1,
60 | cell + 1);
61 | if (cell == 2)
62 | validateCellForSalary(dataFormatter.formatCellValue(currentCell), errorMessages, row + 1,
63 | cell + 1);
64 | } else
65 | errorMessages.add("No Value Present At Row " + row + 1 + " Cell " + cell + 1);
66 | }
67 |
68 | }
69 |
70 | workBook.close();
71 | if (errorMessages.size() == 0) {
72 | final var response = new JSONObject();
73 | final var fileMessageDigest = MessageDigest.getInstance("MD5");
74 | fileMessageDigest.update(file.getBytes());
75 | final var fileHash = DatatypeConverter.printHexBinary(fileMessageDigest.digest()).toUpperCase();
76 | final var code = new Random().ints(1, 100000, 999999).sum();
77 | loadingCache.put(code, fileHash);
78 | response.put("Code", code);
79 | response.put("message", "No Errors found, use this code and submitted file to bulk upload");
80 | response.put("timestamp", LocalDateTime.now().toString());
81 | return ResponseEntity.ok(response.toString());
82 | }
83 | return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new Gson().toJson(errorMessages));
84 | }
85 |
86 | private void validateCellForEmail(final String cellValue, final ArrayList errorMessages, Integer rowIndex,
87 | Integer cellIndex) {
88 |
89 | if (!EmailValidator.getInstance().isValid(cellValue))
90 | errorMessages.add("Email Id Not Valid At Row " + rowIndex + " Cell " + cellIndex);
91 |
92 | if (employeeRepository.existsByEmailId(cellValue))
93 | errorMessages.add("Email Id " + cellValue + " Already Exists In The System At Row " + rowIndex + " Cell "
94 | + cellIndex);
95 |
96 | }
97 |
98 | private void validateCellForName(final String cellValue, final ArrayList errorMessages, Integer rowIndex,
99 | Integer cellIndex) {
100 |
101 | if (cellValue.matches(".*\\d.*"))
102 | errorMessages.add("Invalid Name Entered At Row " + rowIndex + " Cell " + cellIndex);
103 | }
104 |
105 | private void validateCellForSalary(final String cellValue, final ArrayList errorMessages, Integer rowIndex,
106 | Integer cellIndex) {
107 |
108 | if (!NumberUtils.isParsable(cellValue))
109 | errorMessages.add("Invalid Salary Amount Entered At Row " + rowIndex + " Cell " + cellIndex);
110 |
111 | }
112 |
113 | private void checkForValidFormat(final XSSFWorkbook workBook, final XSSFRow initialRow) throws IOException {
114 | if (initialRow.getLastCellNum() != columnNames.size())
115 | throw new InvalidTemplateFormatException();
116 |
117 | for (int cell = 0; cell < initialRow.getLastCellNum(); cell++) {
118 | final var currentCell = initialRow.getCell(cell);
119 | if (!dataFormatter.formatCellValue(currentCell).equals(columnNames.get(cell))) {
120 | workBook.close();
121 | throw new InvalidTemplateFormatException();
122 | }
123 | }
124 | }
125 |
126 | public List extractData(final MultipartFile file) throws IOException {
127 | final var workBook = new XSSFWorkbook(file.getInputStream());
128 | final var workSheet = workBook.getSheetAt(0);
129 | final var numberOfRowsInWorkSheet = workSheet.getLastRowNum();
130 | final var employees = new ArrayList();
131 |
132 | for (int row = 0; row < numberOfRowsInWorkSheet; row++) {
133 | final var currentRow = workSheet.getRow(row + 1);
134 | final var employee = new Employee();
135 | employee.setEmailId(dataFormatter.formatCellValue(currentRow.getCell(0)));
136 | employee.setFullName(dataFormatter.formatCellValue(currentRow.getCell(1)));
137 | employee.setSalaryPerMonth(Double.valueOf(dataFormatter.formatCellValue(currentRow.getCell(2))));
138 | employees.add(employee);
139 | }
140 | workBook.close();
141 | return employees;
142 | }
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/exception/FileNotSameThatWasValidatedException.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.exception;
2 |
3 | public class FileNotSameThatWasValidatedException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = -5079419685058011167L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/exception/InvalidCodeException.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.exception;
2 |
3 | public class InvalidCodeException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = -2452916753149902478L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/exception/InvalidExcelFileExtensionException.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.exception;
2 |
3 | public class InvalidExcelFileExtensionException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = 5749059778362432774L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/exception/InvalidTemplateFormatException.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.exception;
2 |
3 | public class InvalidTemplateFormatException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = -2728139256516753823L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/exception/handler/FileNotSameThatWasValidatedExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 |
5 | import org.json.JSONObject;
6 | import org.springframework.core.Ordered;
7 | import org.springframework.core.annotation.Order;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.ControllerAdvice;
11 | import org.springframework.web.bind.annotation.ExceptionHandler;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 | import org.springframework.web.bind.annotation.ResponseStatus;
14 |
15 | import com.hardik.kofta.exception.FileNotSameThatWasValidatedException;
16 |
17 | @Order(Ordered.HIGHEST_PRECEDENCE)
18 | @ControllerAdvice
19 | public class FileNotSameThatWasValidatedExceptionHandler {
20 |
21 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
22 | @ResponseBody
23 | @ExceptionHandler(FileNotSameThatWasValidatedException.class)
24 | public ResponseEntity> fileNotSameThatWasValidatedExceptionHandler(FileNotSameThatWasValidatedException ex) {
25 |
26 | final var response = new JSONObject();
27 | response.put("status", "Failure");
28 | response.put("message", "File not the same that was validated");
29 | response.put("timestamp", LocalDateTime.now().toString());
30 | return ResponseEntity.badRequest().body(response.toString());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/exception/handler/InvalidCodeExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 |
5 | import org.json.JSONObject;
6 | import org.springframework.core.Ordered;
7 | import org.springframework.core.annotation.Order;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.ControllerAdvice;
11 | import org.springframework.web.bind.annotation.ExceptionHandler;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 | import org.springframework.web.bind.annotation.ResponseStatus;
14 |
15 | import com.hardik.kofta.exception.InvalidCodeException;
16 |
17 | @Order(Ordered.HIGHEST_PRECEDENCE)
18 | @ControllerAdvice
19 | public class InvalidCodeExceptionHandler {
20 |
21 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
22 | @ResponseBody
23 | @ExceptionHandler(InvalidCodeException.class)
24 | public ResponseEntity> invalidCodeExceptionHandler(InvalidCodeException ex) {
25 |
26 | final var response = new JSONObject();
27 | response.put("status", "Failure");
28 | response.put("message", "Invalid code");
29 | response.put("timestamp", LocalDateTime.now().toString());
30 | return ResponseEntity.badRequest().body(response.toString());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/exception/handler/InvalidExcelFileExtensionExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 |
5 | import org.json.JSONObject;
6 | import org.springframework.core.Ordered;
7 | import org.springframework.core.annotation.Order;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.ControllerAdvice;
11 | import org.springframework.web.bind.annotation.ExceptionHandler;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 | import org.springframework.web.bind.annotation.ResponseStatus;
14 |
15 | import com.hardik.kofta.exception.InvalidExcelFileExtensionException;
16 |
17 | @Order(Ordered.HIGHEST_PRECEDENCE)
18 | @ControllerAdvice
19 | public class InvalidExcelFileExtensionExceptionHandler {
20 |
21 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
22 | @ResponseBody
23 | @ExceptionHandler(InvalidExcelFileExtensionException.class)
24 | public ResponseEntity> duplicateSuperHeroNameViolation(InvalidExcelFileExtensionException ex) {
25 |
26 | final var response = new JSONObject();
27 | response.put("status", "Failure");
28 | response.put("message", "File must have .xlsx extension");
29 | response.put("timestamp", LocalDateTime.now().toString());
30 | return ResponseEntity.badRequest().body(response.toString());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/exception/handler/InvalidTemplateFormatExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 |
5 | import org.json.JSONObject;
6 | import org.springframework.core.Ordered;
7 | import org.springframework.core.annotation.Order;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.ControllerAdvice;
11 | import org.springframework.web.bind.annotation.ExceptionHandler;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 | import org.springframework.web.bind.annotation.ResponseStatus;
14 |
15 | import com.hardik.kofta.exception.InvalidTemplateFormatException;
16 |
17 | @Order(Ordered.HIGHEST_PRECEDENCE)
18 | @ControllerAdvice
19 | public class InvalidTemplateFormatExceptionHandler {
20 |
21 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
22 | @ResponseBody
23 | @ExceptionHandler(InvalidTemplateFormatException.class)
24 | public ResponseEntity> duplicateSuperHeroNameViolation(InvalidTemplateFormatException ex) {
25 |
26 | final var response = new JSONObject();
27 | response.put("status", "Failure");
28 | response.put("message", "Excel File Does Not Conform To Given Template");
29 | response.put("timestamp", LocalDateTime.now().toString());
30 | return ResponseEntity.badRequest().body(response.toString());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/repository/EmployeeRepository.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.repository;
2 |
3 | import java.util.UUID;
4 |
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import com.hardik.kofta.entity.Employee;
9 |
10 | @Repository
11 | public interface EmployeeRepository extends JpaRepository {
12 |
13 | boolean existsByEmailId(String emailId);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/java/com/hardik/kofta/service/EmployeeService.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta.service;
2 |
3 | import java.io.IOException;
4 | import java.security.MessageDigest;
5 | import java.security.NoSuchAlgorithmException;
6 | import java.time.LocalDateTime;
7 | import java.util.List;
8 | import java.util.concurrent.ExecutionException;
9 |
10 | import javax.xml.bind.DatatypeConverter;
11 |
12 | import org.json.JSONObject;
13 | import org.springframework.http.ResponseEntity;
14 | import org.springframework.stereotype.Service;
15 | import org.springframework.web.multipart.MultipartFile;
16 |
17 | import com.google.common.cache.LoadingCache;
18 | import com.hardik.kofta.entity.Employee;
19 | import com.hardik.kofta.excel.service.ExcelService;
20 | import com.hardik.kofta.exception.FileNotSameThatWasValidatedException;
21 | import com.hardik.kofta.exception.InvalidCodeException;
22 | import com.hardik.kofta.repository.EmployeeRepository;
23 |
24 | import lombok.AllArgsConstructor;
25 |
26 | @Service
27 | @AllArgsConstructor
28 | public class EmployeeService {
29 |
30 | private final EmployeeRepository employeeRepository;
31 | private final ExcelService excelService;
32 | private final LoadingCache loadingCache;
33 |
34 | public ResponseEntity> bulkUpload(final Integer code, final MultipartFile file)
35 | throws NumberFormatException, ExecutionException, NoSuchAlgorithmException, IOException {
36 | final var retreivedCode = loadingCache.get(code);
37 | final var response = new JSONObject();
38 | if (retreivedCode == null)
39 | throw new InvalidCodeException();
40 |
41 | final var fileMessageDigest = MessageDigest.getInstance("MD5");
42 | fileMessageDigest.update(file.getBytes());
43 | final var fileHash = DatatypeConverter.printHexBinary(fileMessageDigest.digest()).toUpperCase();
44 |
45 | if (!retreivedCode.equals(fileHash))
46 | throw new FileNotSameThatWasValidatedException();
47 |
48 | final var data = excelService.extractData(file);
49 | employeeRepository.saveAll(data);
50 |
51 | response.put("message", data.size() + " Employees data successfully saved to database");
52 | response.put("timestamp", LocalDateTime.now().toString());
53 | return ResponseEntity.ok(response.toString());
54 | }
55 |
56 | public ResponseEntity> retreiveEmployees() {
57 | return ResponseEntity.ok(employeeRepository.findAll());
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #PORT-PATH
2 | server.port=8089
3 | server.servlet.context-path=/kofta
4 |
5 | #Datasource
6 | spring.datasource.url=jdbc:h2:mem:kofta
7 | spring.datasource.driverClassName=org.h2.Driver
8 | spring.datasource.username=kofta
9 | spring.datasource.password=kofta
10 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
11 | spring.jpa.show-sql=true
12 |
13 | #OPEN-API
14 | com.hardik.kofta.swagger.properties.title=Kofta
15 | com.hardik.kofta.swagger.properties.description=POC to read excel sheet data and store it to database after validation using apache-POI library
16 | com.hardik.kofta.swagger.properties.api-version=1.0.0
17 | com.hardik.kofta.swagger.properties.contact.name=Hardik Singh Behl
18 | com.hardik.kofta.swagger.properties.contact.email=hardik.behl7444@gmail.com
19 | com.hardik.kofta.swagger.properties.contact.url=https://www.linkedin.com/in/hardikSinghBehl
20 |
21 | #CACHE
22 | com.hardik.kofta.code.expiration-minutes=5
--------------------------------------------------------------------------------
/read-excel-to-database/src/main/resources/template.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hardikSinghBehl/spring-boot-apache-POI/aabf92885ba7f9cc543772b2b1c6f7429ed31cf0/read-excel-to-database/src/main/resources/template.xlsx
--------------------------------------------------------------------------------
/read-excel-to-database/src/test/java/com/hardik/kofta/ReadExcelToDatabaseApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.hardik.kofta;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ReadExcelToDatabaseApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/read-excel-to-database/system.properties:
--------------------------------------------------------------------------------
1 | java.runtime.version=15
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007-present the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.6";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hardikSinghBehl/spring-boot-apache-POI/aabf92885ba7f9cc543772b2b1c6f7429ed31cf0/validate-excel-for-error-list-response/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/README.md:
--------------------------------------------------------------------------------
1 | # Validate Excel Sheet Data For Errors And Send ErrorMessages as List
2 |
3 | ###### POC to demonstrate Validating Excel file (.xlsx) data for error and in case of errors returning List of String detailin g out the error type with cell and row position.
4 |
5 |
6 | RUNNING APPLICATION (Swagger-ui)
7 |
8 |
9 | ## Tech Stack
10 |
11 | * Java 15
12 | * Spring Boot
13 | * Apache POI
14 | * H2 Database
15 | * Open-API (Swagger-ui)
16 |
17 | ## Application Flow
18 |
19 | * User Downloads The Excel File Template from the API path /excel/template
20 | * User fills in the value conforming to the downloaded format
21 | * POST request to path /excel is made to validate the file
22 | * Incase of errors, a List of String(s) is returned detailing out the error type with the row and cell index value
23 |
24 | The following checks are made
25 | * values are not left blank
26 | * email-id is of a valid type
27 | * email-id does not already exist in the database (data populated in DB in bootstrap class)
28 | * a valid numric value is entered in the salary column
29 | * a valid name is entered in the fullname column
30 |
31 |
32 | ## Local Setup
33 |
34 | * Install Java 15
35 | * Install Maven
36 |
37 | Recommended way is to use [sdkman](https://sdkman.io/) for installing both maven and java
38 |
39 | Run the below commands in the core
40 |
41 | ```
42 | mvn clean install
43 | ```
44 |
45 | ```
46 | mvn spring-boot:run
47 |
48 | ```
49 |
50 | server port is configured to 8070 and base path to /pyaaru which can be changed in application.properties file
51 |
52 | Go to the below url to view swagger-ui (API docs)
53 |
54 | ```
55 | http://localhost:8070/pyaaru/swagger-ui.html
56 | ```
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
124 |
125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
162 | if ERRORLEVEL 1 goto error
163 | goto end
164 |
165 | :error
166 | set ERROR_CODE=1
167 |
168 | :end
169 | @endlocal & set ERROR_CODE=%ERROR_CODE%
170 |
171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
175 | :skipRcPost
176 |
177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
179 |
180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
181 |
182 | exit /B %ERROR_CODE%
183 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.boot
8 | spring-boot-starter-parent
9 | 2.5.0
10 |
11 |
12 | com.hardik
13 | validate-excel-for-error-list-response
14 | 0.0.1-SNAPSHOT
15 | validate-excel-for-error-list-response
16 | POC to validate data inside input excel sheet and return list<String > errorMessages
17 |
18 | 15
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-data-jpa
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-validation
32 |
33 |
34 | com.google.code.gson
35 | gson
36 |
37 |
38 | commons-validator
39 | commons-validator
40 | 1.4.1
41 |
42 |
43 | org.json
44 | json
45 | 20210307
46 |
47 |
48 | org.apache.poi
49 | poi
50 | 5.0.0
51 |
52 |
53 | org.apache.poi
54 | poi-ooxml
55 | 5.0.0
56 |
57 |
58 | org.springdoc
59 | springdoc-openapi-ui
60 | 1.5.8
61 |
62 |
63 | org.springframework.boot
64 | spring-boot-devtools
65 | runtime
66 | true
67 |
68 |
69 | com.h2database
70 | h2
71 | runtime
72 |
73 |
74 | org.projectlombok
75 | lombok
76 | true
77 |
78 |
79 | org.springframework.boot
80 | spring-boot-starter-test
81 | test
82 |
83 |
84 | org.springframework.boot
85 | spring-boot-configuration-processor
86 | true
87 |
88 |
89 |
90 |
91 |
92 |
93 | org.springframework.boot
94 | spring-boot-maven-plugin
95 |
96 |
97 |
98 | org.projectlombok
99 | lombok
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/ValidateExcelForErrorListResponseApplication.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ValidateExcelForErrorListResponseApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ValidateExcelForErrorListResponseApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/annotation/IsXlsx.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.annotation;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | @Target(ElementType.METHOD)
10 | @Retention(RetentionPolicy.RUNTIME)
11 | @Documented
12 | public @interface IsXlsx {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/annotation/aspect/CheckExcelFormatXlsxAspect.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.annotation.aspect;
2 |
3 | import java.util.concurrent.atomic.AtomicInteger;
4 |
5 | import org.aspectj.lang.JoinPoint;
6 | import org.aspectj.lang.annotation.Aspect;
7 | import org.aspectj.lang.annotation.Before;
8 | import org.aspectj.lang.reflect.CodeSignature;
9 | import org.springframework.stereotype.Component;
10 | import org.springframework.web.multipart.MultipartFile;
11 |
12 | import com.hardik.pyaaru.annotation.IsXlsx;
13 | import com.hardik.pyaaru.exception.InvalidExcelFileExtensionException;
14 |
15 | import lombok.RequiredArgsConstructor;
16 | import lombok.extern.slf4j.Slf4j;
17 |
18 | @Component
19 | @RequiredArgsConstructor
20 | @Aspect
21 | @Slf4j
22 | public class CheckExcelFormatXlsxAspect {
23 |
24 | private Integer headerArgumentPosition;
25 |
26 | @Before("execution(* *.*(..)) && @annotation(isXlsx)")
27 | public void checkIfExcelFileFormatIsValid(JoinPoint joinPoint, IsXlsx isXlsx) {
28 | log.info("Running Is Active Check On Method {}() in {}.class", joinPoint.getSignature().getName(),
29 | joinPoint.getSignature().getDeclaringType().getSimpleName());
30 |
31 | CodeSignature codeSignature = (CodeSignature) joinPoint.getSignature();
32 | AtomicInteger count = new AtomicInteger(0);
33 |
34 | for (int i = 0; i < codeSignature.getParameterNames().length; i++) {
35 | if (codeSignature.getParameterNames()[i].equalsIgnoreCase("file")) {
36 | headerArgumentPosition = count.get();
37 | break;
38 | } else
39 | count.incrementAndGet();
40 | }
41 |
42 | final var file = (MultipartFile) joinPoint.getArgs()[headerArgumentPosition];
43 |
44 | if (!file.getOriginalFilename().endsWith(".xlsx"))
45 | throw new InvalidExcelFileExtensionException();
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/bootstrap/EmployeeDataPopulationOnBootstrap.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.bootstrap;
2 |
3 | import java.util.List;
4 | import java.util.Random;
5 |
6 | import javax.annotation.PostConstruct;
7 |
8 | import org.springframework.stereotype.Component;
9 |
10 | import com.hardik.pyaaru.entity.Employee;
11 | import com.hardik.pyaaru.repository.EmployeeRepository;
12 |
13 | import lombok.RequiredArgsConstructor;
14 | import net.bytebuddy.utility.RandomString;
15 |
16 | @Component
17 | @RequiredArgsConstructor
18 | public class EmployeeDataPopulationOnBootstrap {
19 |
20 | private final EmployeeRepository employeeRepository;
21 | private final List emailIds = List.of("hardik.behl7444@gmail.com", "hardikbehl5@gmail.com",
22 | "dummy@gmail.com");
23 |
24 | @PostConstruct
25 | void populateEmployeeData() {
26 | emailIds.forEach(emailId -> {
27 | final var employee = new Employee();
28 | employee.setEmailId(emailId);
29 | employee.setFullName(RandomString.make(4) + " " + RandomString.make(7));
30 | employee.setSalaryPerMonth(new Random().doubles(2, 1500.89, 78000.543).sum());
31 | employeeRepository.save(employee);
32 | });
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/configuration/OpenApiConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.configuration;
2 |
3 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 |
7 | import com.hardik.pyaaru.configuration.properties.OpenApiConfigurationProperties;
8 |
9 | import io.swagger.v3.oas.models.OpenAPI;
10 | import io.swagger.v3.oas.models.info.Contact;
11 | import io.swagger.v3.oas.models.info.Info;
12 | import lombok.AllArgsConstructor;
13 |
14 | @Configuration
15 | @EnableConfigurationProperties(OpenApiConfigurationProperties.class)
16 | @AllArgsConstructor
17 | public class OpenApiConfiguration {
18 |
19 | private final OpenApiConfigurationProperties openApiConfigurationProperties;
20 |
21 | @Bean
22 | public OpenAPI customOpenAPI() {
23 | final var properties = openApiConfigurationProperties.getSwagger();
24 | final var contact = properties.getContact();
25 | final var info = new Info().title(properties.getTitle()).version(properties.getApiVersion())
26 | .description(properties.getDescription())
27 | .contact(new Contact().email(contact.getEmail()).name(contact.getName()).url(contact.getUrl()));
28 |
29 | return new OpenAPI().info(info);
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/configuration/properties/OpenApiConfigurationProperties.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.configuration.properties;
2 |
3 | import org.springframework.boot.context.properties.ConfigurationProperties;
4 |
5 | import lombok.Data;
6 |
7 | @Data
8 | @ConfigurationProperties(prefix = "com.hardik.pyaaru")
9 | public class OpenApiConfigurationProperties {
10 |
11 | private Swagger swagger = new Swagger();
12 |
13 | @Data
14 | public class Swagger {
15 | private String title;
16 | private String description;
17 | private String apiVersion;
18 |
19 | private Contact contact = new Contact();
20 |
21 | @Data
22 | public class Contact {
23 | private String email;
24 | private String name;
25 | private String url;
26 | }
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/controller/EmployeeController.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.controller;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.http.HttpStatus;
6 | import org.springframework.http.MediaType;
7 | import org.springframework.http.ResponseEntity;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.ResponseStatus;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import com.hardik.pyaaru.entity.Employee;
14 | import com.hardik.pyaaru.repository.EmployeeRepository;
15 |
16 | import io.swagger.v3.oas.annotations.Operation;
17 | import lombok.AllArgsConstructor;
18 |
19 | @RestController
20 | @AllArgsConstructor
21 | @RequestMapping(value = "/employees")
22 | public class EmployeeController {
23 |
24 | private final EmployeeRepository employeeRepository;
25 |
26 | @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
27 | @ResponseStatus(value = HttpStatus.OK)
28 | @Operation(summary = "Returns List of Employees in system")
29 | public ResponseEntity> retreiveEmployees() {
30 | return ResponseEntity.ok(employeeRepository.findAll());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/controller/ExcelController.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.controller;
2 |
3 | import java.io.IOException;
4 |
5 | import org.springframework.core.io.InputStreamResource;
6 | import org.springframework.http.HttpHeaders;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.http.MediaType;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.GetMapping;
11 | import org.springframework.web.bind.annotation.PostMapping;
12 | import org.springframework.web.bind.annotation.RequestMapping;
13 | import org.springframework.web.bind.annotation.RequestParam;
14 | import org.springframework.web.bind.annotation.ResponseStatus;
15 | import org.springframework.web.bind.annotation.RestController;
16 | import org.springframework.web.multipart.MultipartFile;
17 |
18 | import com.hardik.pyaaru.annotation.IsXlsx;
19 | import com.hardik.pyaaru.service.ExcelService;
20 |
21 | import io.swagger.v3.oas.annotations.Operation;
22 | import io.swagger.v3.oas.annotations.Parameter;
23 | import lombok.AllArgsConstructor;
24 |
25 | @RestController
26 | @AllArgsConstructor
27 | @RequestMapping(value = "/excel")
28 | public class ExcelController {
29 |
30 | private final ExcelService excelService;
31 |
32 | @GetMapping(value = "/template")
33 | @ResponseStatus(value = HttpStatus.OK)
34 | @Operation(summary = "Download excel file template")
35 | public ResponseEntity excelTemplateFileDownloadHandler() throws IOException {
36 | return ResponseEntity.status(HttpStatus.OK)
37 | .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=template.xlsx")
38 | .contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
39 | .body(new InputStreamResource(excelService.getTemplate()));
40 | }
41 |
42 | @IsXlsx
43 | @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
44 | @ResponseStatus(value = HttpStatus.OK)
45 | @Operation(summary = "Validates Data in Excel File")
46 | public ResponseEntity> validateExcelFileHandler(
47 | @Parameter @RequestParam(name = "file", required = true) final MultipartFile file) throws IOException {
48 | return excelService.validateData(file);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/entity/Employee.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.entity;
2 |
3 | import java.io.Serializable;
4 | import java.time.LocalDateTime;
5 | import java.util.UUID;
6 |
7 | import javax.persistence.Column;
8 | import javax.persistence.Entity;
9 | import javax.persistence.GeneratedValue;
10 | import javax.persistence.GenerationType;
11 | import javax.persistence.Id;
12 | import javax.persistence.PrePersist;
13 | import javax.persistence.Table;
14 |
15 | import lombok.Data;
16 |
17 | @Data
18 | @Entity
19 | @Table(name = "employees")
20 | public class Employee implements Serializable {
21 |
22 | private static final long serialVersionUID = 291742406510888152L;
23 |
24 | @Id
25 | @GeneratedValue(strategy = GenerationType.AUTO)
26 | @Column(name = "id", nullable = false, unique = true)
27 | private UUID id;
28 |
29 | @Column(name = "email_id", nullable = false, unique = true)
30 | private String emailId;
31 |
32 | @Column(name = "full_name", nullable = false)
33 | private String fullName;
34 |
35 | @Column(name = "salary_per_month", nullable = false)
36 | private Double salaryPerMonth;
37 |
38 | @Column(name = "created_at", nullable = false)
39 | private LocalDateTime createdAt;
40 |
41 | @PrePersist
42 | void onCreate() {
43 | this.id = UUID.randomUUID();
44 | this.createdAt = LocalDateTime.now();
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/exception/InvalidExcelFileExtensionException.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.exception;
2 |
3 | public class InvalidExcelFileExtensionException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = 5749059778362432774L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/exception/InvalidTemplateFormatException.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.exception;
2 |
3 | public class InvalidTemplateFormatException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = -2728139256516753823L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/exception/handler/InvalidExcelFileExtensionExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 |
5 | import org.json.JSONObject;
6 | import org.springframework.core.Ordered;
7 | import org.springframework.core.annotation.Order;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.ControllerAdvice;
11 | import org.springframework.web.bind.annotation.ExceptionHandler;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 | import org.springframework.web.bind.annotation.ResponseStatus;
14 |
15 | import com.hardik.pyaaru.exception.InvalidExcelFileExtensionException;
16 |
17 | @Order(Ordered.HIGHEST_PRECEDENCE)
18 | @ControllerAdvice
19 | public class InvalidExcelFileExtensionExceptionHandler {
20 |
21 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
22 | @ResponseBody
23 | @ExceptionHandler(InvalidExcelFileExtensionException.class)
24 | public ResponseEntity> duplicateSuperHeroNameViolation(InvalidExcelFileExtensionException ex) {
25 |
26 | final var response = new JSONObject();
27 | response.put("status", "Failure");
28 | response.put("message", "File must have .xlsx extension");
29 | response.put("timestamp", LocalDateTime.now().toString());
30 | return ResponseEntity.badRequest().body(response.toString());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/exception/handler/InvalidTemplateFormatExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 |
5 | import org.json.JSONObject;
6 | import org.springframework.core.Ordered;
7 | import org.springframework.core.annotation.Order;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.ControllerAdvice;
11 | import org.springframework.web.bind.annotation.ExceptionHandler;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 | import org.springframework.web.bind.annotation.ResponseStatus;
14 |
15 | import com.hardik.pyaaru.exception.InvalidTemplateFormatException;
16 |
17 | @Order(Ordered.HIGHEST_PRECEDENCE)
18 | @ControllerAdvice
19 | public class InvalidTemplateFormatExceptionHandler {
20 |
21 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
22 | @ResponseBody
23 | @ExceptionHandler(InvalidTemplateFormatException.class)
24 | public ResponseEntity> duplicateSuperHeroNameViolation(InvalidTemplateFormatException ex) {
25 |
26 | final var response = new JSONObject();
27 | response.put("status", "Failure");
28 | response.put("message", "Excel File Does Not Conform To Given Template");
29 | response.put("timestamp", LocalDateTime.now().toString());
30 | return ResponseEntity.badRequest().body(response.toString());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/repository/EmployeeRepository.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.repository;
2 |
3 | import java.util.UUID;
4 |
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import com.hardik.pyaaru.entity.Employee;
9 |
10 | @Repository
11 | public interface EmployeeRepository extends JpaRepository {
12 |
13 | boolean existsByEmailId(String cellValue);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/java/com/hardik/pyaaru/service/ExcelService.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru.service;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.IOException;
6 | import java.time.LocalDateTime;
7 | import java.util.ArrayList;
8 | import java.util.List;
9 | import java.util.concurrent.atomic.AtomicInteger;
10 |
11 | import org.apache.commons.lang3.math.NumberUtils;
12 | import org.apache.commons.validator.EmailValidator;
13 | import org.apache.poi.ss.usermodel.DataFormatter;
14 | import org.apache.poi.xssf.usermodel.XSSFCell;
15 | import org.apache.poi.xssf.usermodel.XSSFRow;
16 | import org.apache.poi.xssf.usermodel.XSSFSheet;
17 | import org.apache.poi.xssf.usermodel.XSSFWorkbook;
18 | import org.json.JSONObject;
19 | import org.springframework.http.HttpStatus;
20 | import org.springframework.http.ResponseEntity;
21 | import org.springframework.stereotype.Service;
22 | import org.springframework.web.multipart.MultipartFile;
23 |
24 | import com.google.gson.Gson;
25 | import com.hardik.pyaaru.exception.InvalidTemplateFormatException;
26 | import com.hardik.pyaaru.repository.EmployeeRepository;
27 |
28 | import lombok.RequiredArgsConstructor;
29 |
30 | @Service
31 | @RequiredArgsConstructor
32 | public class ExcelService {
33 |
34 | private final List columnNames = List.of("Email-id", "Full-Name", "Salary");
35 | private final DataFormatter dataFormatter = new DataFormatter();
36 | private final EmployeeRepository employeeRepository;
37 |
38 | public ByteArrayInputStream getTemplate() throws IOException {
39 | final var workBook = new XSSFWorkbook();
40 | final var workSheet = workBook.createSheet("Employee Data Registery Template");
41 | final var initialRow = workSheet.createRow(0);
42 | final var count = new AtomicInteger(0);
43 |
44 | columnNames.forEach(columnName -> {
45 | final var cell = initialRow.createCell(count.getAndIncrement());
46 | styleBold(workBook, cell);
47 | cell.setCellValue(columnName);
48 | });
49 |
50 | autoSizeColumns(workSheet);
51 |
52 | final var outputStream = new ByteArrayOutputStream();
53 | workBook.write(outputStream);
54 |
55 | workBook.close();
56 | return new ByteArrayInputStream(outputStream.toByteArray());
57 | }
58 |
59 | private void styleBold(final XSSFWorkbook workBook, final XSSFCell cell) {
60 | final var style = workBook.createCellStyle();
61 | final var font = workBook.createFont();
62 | font.setBold(true);
63 | style.setFont(font);
64 |
65 | for (int column = 0; column < columnNames.size(); column++) {
66 | cell.setCellStyle(style);
67 | }
68 | }
69 |
70 | private void autoSizeColumns(final XSSFSheet workSheet) {
71 | for (int column = 0; column < columnNames.size(); column++) {
72 | workSheet.autoSizeColumn(column);
73 | }
74 | }
75 |
76 | public ResponseEntity> validateData(final MultipartFile file) throws IOException {
77 | final var workBook = new XSSFWorkbook(file.getInputStream());
78 | final var workSheet = workBook.getSheetAt(0);
79 | final var initialRow = workSheet.getRow(0);
80 | final var numberOfRowsInWorkSheet = workSheet.getLastRowNum();
81 | checkForValidFormat(workBook, initialRow);
82 | final var errorMessages = new ArrayList();
83 |
84 | for (int row = 0; row < numberOfRowsInWorkSheet; row++) {
85 | final var currentRow = workSheet.getRow(row + 1);
86 |
87 | for (int cell = 0; cell < currentRow.getLastCellNum(); cell++) {
88 | var currentCell = currentRow.getCell(cell);
89 | if (currentCell != null) {
90 | if (cell == 0)
91 | validateCellForEmail(dataFormatter.formatCellValue(currentCell), errorMessages, row + 1,
92 | cell + 1);
93 | if (cell == 1)
94 | validateCellForName(dataFormatter.formatCellValue(currentCell), errorMessages, row + 1,
95 | cell + 1);
96 | if (cell == 2)
97 | validateCellForSalary(dataFormatter.formatCellValue(currentCell), errorMessages, row + 1,
98 | cell + 1);
99 | } else
100 | errorMessages.add("No Value Present At Row " + row + 1 + " Cell " + cell + 1);
101 | }
102 |
103 | }
104 |
105 | workBook.close();
106 | if (errorMessages.size() == 0) {
107 | final var response = new JSONObject();
108 | response.put("message", "No Errors Found");
109 | response.put("timestamp", LocalDateTime.now().toString());
110 | return ResponseEntity.ok(response.toString());
111 | }
112 | return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new Gson().toJson(errorMessages));
113 | }
114 |
115 | private void validateCellForEmail(final String cellValue, final ArrayList errorMessages, Integer rowIndex,
116 | Integer cellIndex) {
117 |
118 | if (!EmailValidator.getInstance().isValid(cellValue))
119 | errorMessages.add("Email Id Not Valid At Row " + rowIndex + " Cell " + cellIndex);
120 |
121 | if (employeeRepository.existsByEmailId(cellValue))
122 | errorMessages.add("Email Id " + cellValue + " Already Exists In The System At Row " + rowIndex + " Cell "
123 | + cellIndex);
124 |
125 | }
126 |
127 | private void validateCellForName(final String cellValue, final ArrayList errorMessages, Integer rowIndex,
128 | Integer cellIndex) {
129 |
130 | if (cellValue.matches(".*\\d.*"))
131 | errorMessages.add("Invalid Name Entered At Row " + rowIndex + " Cell " + cellIndex);
132 | }
133 |
134 | private void validateCellForSalary(final String cellValue, final ArrayList errorMessages, Integer rowIndex,
135 | Integer cellIndex) {
136 |
137 | if (!NumberUtils.isParsable(cellValue))
138 | errorMessages.add("Invalid Salary Amount Entered At Row " + rowIndex + " Cell " + cellIndex);
139 |
140 | }
141 |
142 | private void checkForValidFormat(final XSSFWorkbook workBook, final XSSFRow initialRow) throws IOException {
143 | if (initialRow.getLastCellNum() != columnNames.size())
144 | throw new InvalidTemplateFormatException();
145 |
146 | for (int cell = 0; cell < initialRow.getLastCellNum(); cell++) {
147 | final var currentCell = initialRow.getCell(cell);
148 | if (!dataFormatter.formatCellValue(currentCell).equals(columnNames.get(cell))) {
149 | workBook.close();
150 | throw new InvalidTemplateFormatException();
151 | }
152 | }
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #PORT-PATH
2 | server.port=8070
3 | server.servlet.context-path=/pyaaru
4 |
5 | #Datasource
6 | spring.datasource.url=jdbc:h2:mem:pyaaru
7 | spring.datasource.driverClassName=org.h2.Driver
8 | spring.datasource.username=pyaaru
9 | spring.datasource.password=pyaaru
10 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
11 | spring.jpa.show-sql=true
12 |
13 | #OPEN-API
14 | com.hardik.pyaaru.swagger.title=Pyaaru
15 | com.hardik.pyaaru.swagger.description=POC to validate data inside input excel sheet and return list errorMessages
16 | com.hardik.pyaaru.swagger.api-version=1.0.0
17 | com.hardik.pyaaru.swagger.contact.name=Hardik Singh Behl
18 | com.hardik.pyaaru.swagger.contact.email=hardik.behl7444@gmail.com
19 | com.hardik.pyaaru.swagger.contact.url=https://www.linkedin.com/in/hardikSinghBehl
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/src/test/java/com/hardik/pyaaru/ValidateExcelForErrorListResponseApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.hardik.pyaaru;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ValidateExcelForErrorListResponseApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/validate-excel-for-error-list-response/system.properties:
--------------------------------------------------------------------------------
1 | java.runtime.version=15
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007-present the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.6";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hardikSinghBehl/spring-boot-apache-POI/aabf92885ba7f9cc543772b2b1c6f7429ed31cf0/validate-excel-for-error-response-modify-same-file/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Validate Given Excel Sheet Data And Change Color of Cells With Error And Detail Out Error In Seperate Sheet
3 |
4 | ###### POC to validate data inside input excel sheet, modify the existing sheet to detail out the error and send it back as response to the user
5 |
6 |
7 | RUNNING APPLICATION (Swagger-ui)
8 |
9 |
10 | ## Tech Stack
11 |
12 | * Java 15
13 | * Spring Boot
14 | * Apache POI
15 | * H2 Database
16 | * Open-API (Swagger-ui)
17 |
18 | ## Application Flow
19 |
20 | * User Downloads The Excel File Template from the API path /excel/template
21 | * User fills in the value conforming to the downloaded format
22 | * POST request to path /excel is made to validate the file
23 | * Incase of no errors, success message is returned
24 | * Incase of Errors, the cell containing invalid values are colored for the user and a seperate sheet is created in the same excel file detailing out the error messages and their position
25 |
26 | The following checks are made
27 | * values are not left blank
28 | * email-id is of a valid type
29 | * email-id does not already exist in the database (data populated in DB in bootstrap class)
30 | * a valid numric value is entered in the salary column
31 | * a valid name is entered in the fullname column
32 |
33 | ## Local Setup
34 |
35 | * Install Java 15
36 | * Install Maven
37 |
38 | Recommended way is to use [sdkman](https://sdkman.io/) for installing both maven and java
39 |
40 | Run the below commands in the core
41 |
42 | ```
43 | mvn clean install
44 | ```
45 |
46 | ```
47 | mvn spring-boot:run
48 |
49 | ```
50 |
51 | server port is configured to 8070 and base path to /durian which can be changed in application.properties file
52 |
53 | Go to the below url to view swagger-ui (API docs)
54 |
55 | ```
56 | http://localhost:8070/durian/swagger-ui.html
57 | ```
58 |
59 | https://user-images.githubusercontent.com/69693621/121804019-cc838f00-cc61-11eb-89bc-0ddce7bcb4f7.mp4
60 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.5.0
9 |
10 |
11 | com.hardik
12 | validate-excel-for-error-response-modify-same-file
13 | 0.0.1-SNAPSHOT
14 | validate-excel-for-error-response-modify-same-file
15 | POC to validate data inside input excel sheet and return error messages in the same excel file
16 |
17 | 15
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-data-jpa
23 |
24 |
25 | org.springframework.boot
26 | spring-boot-starter-web
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-validation
31 |
32 |
33 | com.google.code.gson
34 | gson
35 |
36 |
37 | commons-validator
38 | commons-validator
39 | 1.4.1
40 |
41 |
42 | org.json
43 | json
44 | 20210307
45 |
46 |
47 | org.apache.poi
48 | poi
49 | 5.0.0
50 |
51 |
52 | org.apache.poi
53 | poi-ooxml
54 | 5.0.0
55 |
56 |
57 | org.springdoc
58 | springdoc-openapi-ui
59 | 1.5.8
60 |
61 |
62 | org.springframework.boot
63 | spring-boot-devtools
64 | runtime
65 | true
66 |
67 |
68 | com.h2database
69 | h2
70 | runtime
71 |
72 |
73 | org.projectlombok
74 | lombok
75 | true
76 |
77 |
78 | org.springframework.boot
79 | spring-boot-starter-test
80 | test
81 |
82 |
83 | org.springframework.boot
84 | spring-boot-configuration-processor
85 | true
86 |
87 |
88 |
89 |
90 |
91 |
92 | org.springframework.boot
93 | spring-boot-maven-plugin
94 |
95 |
96 |
97 | org.projectlombok
98 | lombok
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/ValidateExcelForErrorResponseModifySameFileApplication.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class ValidateExcelForErrorResponseModifySameFileApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(ValidateExcelForErrorResponseModifySameFileApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/annotation/IsXlsx.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.annotation;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | @Target(ElementType.METHOD)
10 | @Retention(RetentionPolicy.RUNTIME)
11 | @Documented
12 | public @interface IsXlsx {
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/annotation/aspect/CheckExcelFormatXlsxAspect.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.annotation.aspect;
2 |
3 | import java.util.concurrent.atomic.AtomicInteger;
4 |
5 | import org.aspectj.lang.JoinPoint;
6 | import org.aspectj.lang.annotation.Aspect;
7 | import org.aspectj.lang.annotation.Before;
8 | import org.aspectj.lang.reflect.CodeSignature;
9 | import org.springframework.stereotype.Component;
10 | import org.springframework.web.multipart.MultipartFile;
11 |
12 | import com.hardik.durian.annotation.IsXlsx;
13 | import com.hardik.durian.exception.InvalidExcelFileExtensionException;
14 |
15 | import lombok.RequiredArgsConstructor;
16 | import lombok.extern.slf4j.Slf4j;
17 |
18 | @Component
19 | @RequiredArgsConstructor
20 | @Aspect
21 | @Slf4j
22 | public class CheckExcelFormatXlsxAspect {
23 |
24 | private Integer headerArgumentPosition;
25 |
26 | @Before("execution(* *.*(..)) && @annotation(isXlsx)")
27 | public void checkIfExcelFileFormatIsValid(JoinPoint joinPoint, IsXlsx isXlsx) {
28 | log.info("Running Is Active Check On Method {}() in {}.class", joinPoint.getSignature().getName(),
29 | joinPoint.getSignature().getDeclaringType().getSimpleName());
30 |
31 | CodeSignature codeSignature = (CodeSignature) joinPoint.getSignature();
32 | AtomicInteger count = new AtomicInteger(0);
33 |
34 | for (int i = 0; i < codeSignature.getParameterNames().length; i++) {
35 | if (codeSignature.getParameterNames()[i].equalsIgnoreCase("file")) {
36 | headerArgumentPosition = count.get();
37 | break;
38 | } else
39 | count.incrementAndGet();
40 | }
41 |
42 | final var file = (MultipartFile) joinPoint.getArgs()[headerArgumentPosition];
43 |
44 | if (!file.getOriginalFilename().endsWith(".xlsx"))
45 | throw new InvalidExcelFileExtensionException();
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/bootstrap/EmployeeDataPopulationOnBootstrap.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.bootstrap;
2 |
3 | import java.util.List;
4 | import java.util.Random;
5 |
6 | import javax.annotation.PostConstruct;
7 |
8 | import org.springframework.stereotype.Component;
9 |
10 | import com.hardik.durian.entity.Employee;
11 | import com.hardik.durian.repository.EmployeeRepository;
12 |
13 | import lombok.RequiredArgsConstructor;
14 | import net.bytebuddy.utility.RandomString;
15 |
16 | @Component
17 | @RequiredArgsConstructor
18 | public class EmployeeDataPopulationOnBootstrap {
19 |
20 | private final EmployeeRepository employeeRepository;
21 | private final List emailIds = List.of("hardik.behl7444@gmail.com", "hardikbehl5@gmail.com",
22 | "dummy@gmail.com");
23 |
24 | @PostConstruct
25 | void populateEmployeeData() {
26 | emailIds.forEach(emailId -> {
27 | final var employee = new Employee();
28 | employee.setEmailId(emailId);
29 | employee.setFullName(RandomString.make(4) + " " + RandomString.make(7));
30 | employee.setSalaryPerMonth(new Random().doubles(2, 1500.89, 78000.543).sum());
31 | employeeRepository.save(employee);
32 | });
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/configuration/OpenApiConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.configuration;
2 |
3 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 |
7 | import com.hardik.durian.configuration.properties.OpenApiConfigurationProperties;
8 |
9 | import io.swagger.v3.oas.models.OpenAPI;
10 | import io.swagger.v3.oas.models.info.Contact;
11 | import io.swagger.v3.oas.models.info.Info;
12 | import lombok.AllArgsConstructor;
13 |
14 | @Configuration
15 | @EnableConfigurationProperties(OpenApiConfigurationProperties.class)
16 | @AllArgsConstructor
17 | public class OpenApiConfiguration {
18 |
19 | private final OpenApiConfigurationProperties openApiConfigurationProperties;
20 |
21 | @Bean
22 | public OpenAPI customOpenAPI() {
23 | final var properties = openApiConfigurationProperties.getSwagger();
24 | final var contact = properties.getContact();
25 | final var info = new Info().title(properties.getTitle()).version(properties.getApiVersion())
26 | .description(properties.getDescription())
27 | .contact(new Contact().email(contact.getEmail()).name(contact.getName()).url(contact.getUrl()));
28 |
29 | return new OpenAPI().info(info);
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/configuration/properties/OpenApiConfigurationProperties.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.configuration.properties;
2 |
3 | import org.springframework.boot.context.properties.ConfigurationProperties;
4 |
5 | import lombok.Data;
6 |
7 | @Data
8 | @ConfigurationProperties(prefix = "com.hardik.durian")
9 | public class OpenApiConfigurationProperties {
10 |
11 | private Swagger swagger = new Swagger();
12 |
13 | @Data
14 | public class Swagger {
15 | private String title;
16 | private String description;
17 | private String apiVersion;
18 |
19 | private Contact contact = new Contact();
20 |
21 | @Data
22 | public class Contact {
23 | private String email;
24 | private String name;
25 | private String url;
26 | }
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/controller/EmployeeController.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.controller;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.http.HttpStatus;
6 | import org.springframework.http.MediaType;
7 | import org.springframework.http.ResponseEntity;
8 | import org.springframework.web.bind.annotation.GetMapping;
9 | import org.springframework.web.bind.annotation.RequestMapping;
10 | import org.springframework.web.bind.annotation.ResponseStatus;
11 | import org.springframework.web.bind.annotation.RestController;
12 |
13 | import com.hardik.durian.entity.Employee;
14 | import com.hardik.durian.repository.EmployeeRepository;
15 |
16 | import io.swagger.v3.oas.annotations.Operation;
17 | import lombok.AllArgsConstructor;
18 |
19 | @RestController
20 | @AllArgsConstructor
21 | @RequestMapping(value = "/employees")
22 | public class EmployeeController {
23 |
24 | private final EmployeeRepository employeeRepository;
25 |
26 | @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
27 | @ResponseStatus(value = HttpStatus.OK)
28 | @Operation(summary = "Returns List of Employees in system")
29 | public ResponseEntity> retreiveEmployees() {
30 | return ResponseEntity.ok(employeeRepository.findAll());
31 | }
32 | }
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/controller/ExcelController.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.controller;
2 |
3 | import java.io.IOException;
4 |
5 | import org.springframework.core.io.InputStreamResource;
6 | import org.springframework.http.HttpHeaders;
7 | import org.springframework.http.HttpStatus;
8 | import org.springframework.http.MediaType;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.GetMapping;
11 | import org.springframework.web.bind.annotation.PostMapping;
12 | import org.springframework.web.bind.annotation.RequestMapping;
13 | import org.springframework.web.bind.annotation.RequestParam;
14 | import org.springframework.web.bind.annotation.ResponseStatus;
15 | import org.springframework.web.bind.annotation.RestController;
16 | import org.springframework.web.multipart.MultipartFile;
17 |
18 | import com.hardik.durian.annotation.IsXlsx;
19 | import com.hardik.durian.service.ExcelService;
20 |
21 | import io.swagger.v3.oas.annotations.Operation;
22 | import io.swagger.v3.oas.annotations.Parameter;
23 | import lombok.AllArgsConstructor;
24 |
25 | @RestController
26 | @AllArgsConstructor
27 | @RequestMapping(value = "/excel")
28 | public class ExcelController {
29 |
30 | private final ExcelService excelService;
31 |
32 | @GetMapping(value = "/template")
33 | @ResponseStatus(value = HttpStatus.OK)
34 | @Operation(summary = "Download excel file template")
35 | public ResponseEntity excelTemplateFileDownloadHandler() throws IOException {
36 | return ResponseEntity.status(HttpStatus.OK)
37 | .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=template.xlsx")
38 | .contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
39 | .body(new InputStreamResource(excelService.getTemplate()));
40 | }
41 |
42 | @IsXlsx
43 | @PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
44 | @ResponseStatus(value = HttpStatus.OK)
45 | @Operation(summary = "Validates Data in Excel File")
46 | public ResponseEntity> validateExcelFileHandler(
47 | @Parameter @RequestParam(name = "file", required = true) final MultipartFile file) throws IOException {
48 | return excelService.validateData(file);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/dto/ErrorMessageDto.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.dto;
2 |
3 | import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
4 |
5 | import lombok.Builder;
6 | import lombok.Getter;
7 |
8 | @Getter
9 | @Builder
10 | @JacksonStdImpl
11 | public class ErrorMessageDto {
12 |
13 | private final Integer row;
14 | private final Integer cell;
15 | private final String message;
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/entity/Employee.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.entity;
2 |
3 | import java.io.Serializable;
4 | import java.time.LocalDateTime;
5 | import java.util.UUID;
6 |
7 | import javax.persistence.Column;
8 | import javax.persistence.Entity;
9 | import javax.persistence.GeneratedValue;
10 | import javax.persistence.GenerationType;
11 | import javax.persistence.Id;
12 | import javax.persistence.PrePersist;
13 | import javax.persistence.Table;
14 |
15 | import lombok.Data;
16 |
17 | @Data
18 | @Entity
19 | @Table(name = "employees")
20 | public class Employee implements Serializable {
21 |
22 | private static final long serialVersionUID = 291742406510888152L;
23 |
24 | @Id
25 | @GeneratedValue(strategy = GenerationType.AUTO)
26 | @Column(name = "id", nullable = false, unique = true)
27 | private UUID id;
28 |
29 | @Column(name = "email_id", nullable = false, unique = true)
30 | private String emailId;
31 |
32 | @Column(name = "full_name", nullable = false)
33 | private String fullName;
34 |
35 | @Column(name = "salary_per_month", nullable = false)
36 | private Double salaryPerMonth;
37 |
38 | @Column(name = "created_at", nullable = false)
39 | private LocalDateTime createdAt;
40 |
41 | @PrePersist
42 | void onCreate() {
43 | this.id = UUID.randomUUID();
44 | this.createdAt = LocalDateTime.now();
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/exception/InvalidExcelFileExtensionException.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.exception;
2 |
3 | public class InvalidExcelFileExtensionException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = 5749059778362432774L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/exception/InvalidTemplateFormatException.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.exception;
2 |
3 | public class InvalidTemplateFormatException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = -2728139256516753823L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/exception/handler/InvalidExcelFileExtensionExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 |
5 | import org.json.JSONObject;
6 | import org.springframework.core.Ordered;
7 | import org.springframework.core.annotation.Order;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.ControllerAdvice;
11 | import org.springframework.web.bind.annotation.ExceptionHandler;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 | import org.springframework.web.bind.annotation.ResponseStatus;
14 |
15 | import com.hardik.durian.exception.InvalidExcelFileExtensionException;
16 |
17 | @Order(Ordered.HIGHEST_PRECEDENCE)
18 | @ControllerAdvice
19 | public class InvalidExcelFileExtensionExceptionHandler {
20 |
21 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
22 | @ResponseBody
23 | @ExceptionHandler(InvalidExcelFileExtensionException.class)
24 | public ResponseEntity> duplicateSuperHeroNameViolation(InvalidExcelFileExtensionException ex) {
25 |
26 | final var response = new JSONObject();
27 | response.put("status", "Failure");
28 | response.put("message", "File must have .xlsx extension");
29 | response.put("timestamp", LocalDateTime.now().toString());
30 | return ResponseEntity.badRequest().body(response.toString());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/exception/handler/InvalidTemplateFormatExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.exception.handler;
2 |
3 | import java.time.LocalDateTime;
4 |
5 | import org.json.JSONObject;
6 | import org.springframework.core.Ordered;
7 | import org.springframework.core.annotation.Order;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.ResponseEntity;
10 | import org.springframework.web.bind.annotation.ControllerAdvice;
11 | import org.springframework.web.bind.annotation.ExceptionHandler;
12 | import org.springframework.web.bind.annotation.ResponseBody;
13 | import org.springframework.web.bind.annotation.ResponseStatus;
14 |
15 | import com.hardik.durian.exception.InvalidTemplateFormatException;
16 |
17 | @Order(Ordered.HIGHEST_PRECEDENCE)
18 | @ControllerAdvice
19 | public class InvalidTemplateFormatExceptionHandler {
20 |
21 | @ResponseStatus(value = HttpStatus.BAD_REQUEST)
22 | @ResponseBody
23 | @ExceptionHandler(InvalidTemplateFormatException.class)
24 | public ResponseEntity> duplicateSuperHeroNameViolation(InvalidTemplateFormatException ex) {
25 |
26 | final var response = new JSONObject();
27 | response.put("status", "Failure");
28 | response.put("message", "Excel File Does Not Conform To Given Template");
29 | response.put("timestamp", LocalDateTime.now().toString());
30 | return ResponseEntity.badRequest().body(response.toString());
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/java/com/hardik/durian/repository/EmployeeRepository.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian.repository;
2 |
3 | import java.util.UUID;
4 |
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import com.hardik.durian.entity.Employee;
9 |
10 | @Repository
11 | public interface EmployeeRepository extends JpaRepository {
12 |
13 | boolean existsByEmailId(String cellValue);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #PORT-PATH
2 | server.port=8070
3 | server.servlet.context-path=/durian
4 |
5 | #Datasource
6 | spring.datasource.url=jdbc:h2:mem:durian
7 | spring.datasource.driverClassName=org.h2.Driver
8 | spring.datasource.username=durian
9 | spring.datasource.password=durian
10 | spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
11 | spring.jpa.show-sql=true
12 |
13 | #OPEN-API
14 | com.hardik.durian.swagger.title=Durian
15 | com.hardik.durian.swagger.description=POC to validate data inside input excel sheet, modify the existing sheet to detail out the error and send it back as response to the user
16 | com.hardik.durian.swagger.api-version=1.0.0
17 | com.hardik.durian.swagger.contact.name=Hardik Singh Behl
18 | com.hardik.durian.swagger.contact.email=hardik.behl7444@gmail.com
19 | com.hardik.durian.swagger.contact.url=https://www.linkedin.com/in/hardikSinghBehl
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/src/test/java/com/hardik/durian/ValidateExcelForErrorResponseModifySameFileApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.hardik.durian;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ValidateExcelForErrorResponseModifySameFileApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/validate-excel-for-error-response-modify-same-file/system.properties:
--------------------------------------------------------------------------------
1 | java.runtime.version=15
--------------------------------------------------------------------------------