├── .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 --------------------------------------------------------------------------------