├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ └── maven-wrapper.properties ├── .vscode ├── launch.json └── settings.json ├── HELP.md ├── LICENSE ├── README.md ├── docker ├── Dockerfile ├── docker-compose-postgres.yml ├── docker-compose-prometheus.yml └── docker-compose.yml ├── grafana ├── grafana-dashboard.json ├── jvm-micrometer_rev9.json ├── scdf-task-batch.json ├── scdf-tasks.json ├── spring-boot-hikaricp-jdbc_rev5.json ├── spring-boot-statistics_rev2.json └── spring-grafana-dashboard.json ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── example │ │ └── demo │ │ ├── SpringBatchDemoApplication.java │ │ ├── config │ │ └── BatchConfiguration.java │ │ ├── models │ │ ├── FileFooter.java │ │ ├── FileHeader.java │ │ ├── RegTypeOne.java │ │ ├── RegTypeThree.java │ │ ├── RegTypeTwo.java │ │ ├── Register.java │ │ └── Transaction.java │ │ ├── repositories │ │ └── TransactionRepository.java │ │ └── steps │ │ ├── chunklets │ │ ├── TransactionItemProcessor.java │ │ └── TransactionItemWriter.java │ │ ├── mappers │ │ ├── DefaultCompositeLineMapper.java │ │ ├── DefaultFieldSetMapper.java │ │ ├── DefaultRecordSeparationPolicy.java │ │ ├── FileFooterFieldSetMapper.java │ │ ├── FileHeaderFieldSetMapper.java │ │ └── TransactionFieldSetMapper.java │ │ ├── tasklets │ │ └── FileDownloadTasklet.java │ │ └── tokenizers │ │ ├── DefaultTokenizer.java │ │ ├── FileFooterTokenizer.java │ │ ├── FileHeaderTokenizer.java │ │ └── TransactionTokenizer.java └── resources │ ├── application.properties │ ├── application.yml.bkp │ ├── banner.txt │ ├── input │ ├── exemplo-sou-java-10.txt │ ├── exemplo-sou-java-1mi.txt.7z │ └── exemplo-sou-java.txt │ └── logback-spring.xml └── test ├── java └── com │ └── example │ └── demo │ ├── SpringBatchDemoApplicationTests.java │ └── TransactionRepositoryTest.java └── resources ├── application.properties └── logback-spring.xml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/intelij+all,git,java,maven,eclipse,windows 3 | # Edit at https://www.gitignore.io/?templates=intelij+all,git,java,maven,eclipse,windows 4 | 5 | ### Eclipse ### 6 | .metadata 7 | bin/ 8 | tmp/ 9 | *.tmp 10 | *.bak 11 | *.swp 12 | *~.nib 13 | local.properties 14 | .settings/ 15 | .loadpath 16 | .recommenders 17 | 18 | # External tool builders 19 | .externalToolBuilders/ 20 | 21 | # Locally stored "Eclipse launch configurations" 22 | *.launch 23 | 24 | # PyDev specific (Python IDE for Eclipse) 25 | *.pydevproject 26 | 27 | # CDT-specific (C/C++ Development Tooling) 28 | .cproject 29 | 30 | # CDT- autotools 31 | .autotools 32 | 33 | # Java annotation processor (APT) 34 | .factorypath 35 | 36 | # PDT-specific (PHP Development Tools) 37 | .buildpath 38 | 39 | # sbteclipse plugin 40 | .target 41 | 42 | # Tern plugin 43 | .tern-project 44 | 45 | # TeXlipse plugin 46 | .texlipse 47 | 48 | # STS (Spring Tool Suite) 49 | .springBeans 50 | 51 | # Code Recommenders 52 | .recommenders/ 53 | 54 | # Annotation Processing 55 | .apt_generated/ 56 | 57 | # Scala IDE specific (Scala & Java development for Eclipse) 58 | .cache-main 59 | .scala_dependencies 60 | .worksheet 61 | 62 | ### Eclipse Patch ### 63 | # Eclipse Core 64 | .project 65 | 66 | # JDT-specific (Eclipse Java Development Tools) 67 | .classpath 68 | 69 | # Annotation Processing 70 | .apt_generated 71 | 72 | .sts4-cache/ 73 | 74 | ### Git ### 75 | # Created by git for backups. To disable backups in Git: 76 | # $ git config --global mergetool.keepBackup false 77 | *.orig 78 | 79 | # Created by git when using merge tools for conflicts 80 | *.BACKUP.* 81 | *.BASE.* 82 | *.LOCAL.* 83 | *.REMOTE.* 84 | *_BACKUP_*.txt 85 | *_BASE_*.txt 86 | *_LOCAL_*.txt 87 | *_REMOTE_*.txt 88 | 89 | #!! ERROR: intelij+all is undefined. Use list command to see defined gitignore types !!# 90 | 91 | ### Java ### 92 | # Compiled class file 93 | *.class 94 | 95 | # Log file 96 | *.log 97 | 98 | # BlueJ files 99 | *.ctxt 100 | 101 | # Mobile Tools for Java (J2ME) 102 | .mtj.tmp/ 103 | 104 | # Package Files # 105 | *.jar 106 | *.war 107 | *.nar 108 | *.ear 109 | *.zip 110 | *.tar.gz 111 | *.rar 112 | 113 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 114 | hs_err_pid* 115 | 116 | ### Maven ### 117 | target/ 118 | pom.xml.tag 119 | pom.xml.releaseBackup 120 | pom.xml.versionsBackup 121 | pom.xml.next 122 | release.properties 123 | dependency-reduced-pom.xml 124 | buildNumber.properties 125 | .mvn/timing.properties 126 | .mvn/wrapper/maven-wrapper.jar 127 | .flattened-pom.xml 128 | 129 | ### Windows ### 130 | # Windows thumbnail cache files 131 | Thumbs.db 132 | Thumbs.db:encryptable 133 | ehthumbs.db 134 | ehthumbs_vista.db 135 | 136 | # Dump file 137 | *.stackdump 138 | 139 | # Folder config file 140 | [Dd]esktop.ini 141 | 142 | # Recycle Bin used on file shares 143 | $RECYCLE.BIN/ 144 | 145 | # Windows Installer files 146 | *.cab 147 | *.msi 148 | *.msix 149 | *.msm 150 | *.msp 151 | 152 | # Windows shortcuts 153 | *.lnk 154 | 155 | # End of https://www.gitignore.io/api/intelij+all,git,java,maven,eclipse,windows 156 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "java", 9 | "name": "CodeLens (Launch) - Teste", 10 | "request": "launch", 11 | "mainClass": "com.example.demo.Teste", 12 | "projectName": "spring-batch-demo" 13 | }, 14 | { 15 | "type": "java", 16 | "name": "CodeLens (Launch) - teste", 17 | "request": "launch", 18 | "mainClass": "teste", 19 | "projectName": "spring-batch-demo" 20 | }, 21 | { 22 | "type": "java", 23 | "name": "Debug (Attach)", 24 | "request": "attach", 25 | "hostName": "localhost", 26 | "port": "5005" 27 | }, 28 | { 29 | "type": "java", 30 | "name": "Debug (Launch) - Current File", 31 | "request": "launch", 32 | "mainClass": "${file}" 33 | }, 34 | { 35 | "type": "java", 36 | "name": "Debug (Launch)-SpringBatchDemoApplication", 37 | "request": "launch", 38 | "mainClass": "com.example.demo.SpringBatchDemoApplication", 39 | "projectName": "spring-batch-demo" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "automatic" 3 | } -------------------------------------------------------------------------------- /HELP.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ### Reference Documentation 4 | For further reference, please consider the following sections: 5 | 6 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) 7 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.3.0.RC1/maven-plugin/reference/html/) 8 | * [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.3.0.RC1/maven-plugin/reference/html/#build-image) 9 | * [Spring Batch](https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/htmlsingle/#howto-batch-applications) 10 | * [Validation](https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/htmlsingle/#boot-features-validation) 11 | * [Spring Data JPA](https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/htmlsingle/#boot-features-jpa-and-spring-data) 12 | * [Spring Boot DevTools](https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/htmlsingle/#using-boot-devtools) 13 | 14 | ### Guides 15 | The following guides illustrate how to use some features concretely: 16 | 17 | * [Creating a Batch Service](https://spring.io/guides/gs/batch-processing/) 18 | * [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/) 19 | 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Frederico Garcia Costa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Spring Batch example project running on Spring Cloud Data Flow 2 | 3 | [![GitHub license](https://img.shields.io/github/license/fredgcosta/spring-batch-demo)](https://github.com/fredgcosta/spring-batch-demo/blob/master/LICENSE) 4 | 5 | The only thing better than a Maven archetype is a repo you can fork with everything already setup. Skip the documentation and just fork-and-code. 6 | 7 | Delete the sample code, replace with your own and you’re good to go. 8 | 9 | ## Built With 10 | 11 | * [Maven](https://maven.apache.org/) - Dependency Management 12 | * [Spring Boot](https://start.spring.io/) - Spring Boot Initializer 13 | * [OpenJDK](https://adoptopenjdk.net/?variant=openjdk11&jvmVariant=hotspot) - Java™ Platform, Standard Edition Development Kit 14 | * [Spring Boot](https://spring.io/projects/spring-boot) - Framework to ease the bootstrapping and development of new Spring Applications 15 | * [PostgreSQL](https://www.postgresql.org/) - The World's Most Advanced Open Source Relational Database 16 | * [git](https://git-scm.com/) - Free and Open-Source distributed version control system 17 | * [Prometheus](https://prometheus.io/) - Monitoring system and time series database 18 | * [Lombok](https://projectlombok.org/) - Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more. 19 | 20 | ## External Tools Used 21 | 22 | * [Postman](https://www.getpostman.com/) - API Development Environment (Testing Docmentation) 23 | 24 | ## To-Do 25 | 26 | - [x] Logger (Console, Json, ELK) 27 | - [x] RESTful Web Service (API for Job executing) 28 | - [ ] Docker 29 | - [x] Spring Cloud Data Flow 30 | - [ ] NoSQL (Redis) 31 | - [ ] PostgreSQL (Connect to Multiple Schemas) 32 | - [x] Micrometer 33 | - [x] Grafna 34 | 35 | ## Running the application locally 36 | 37 | There are several ways to run a Spring Boot application on your local machine. One way is to execute the `main` method in the `com.example.demo.SpringBatchDemoApplication` class from your IDE. 38 | 39 | - Download the zip or clone the Git repository. 40 | - Unzip the zip file (if you downloaded one) 41 | - Open Command Prompt and Change directory (cd) to folder containing pom.xml 42 | - Open Eclipse 43 | - File -> Import -> Existing Maven Project -> Navigate to the folder where you unzipped the zip 44 | - Select the project 45 | - Choose the Spring Boot Application file (search for @SpringBootApplication) 46 | - Right Click on the file and Run as Java Application 47 | 48 | Alternatively you can use the [Spring Boot Maven plugin](https://docs.spring.io/spring-boot/docs/current/reference/html/build-tool-plugins-maven-plugin.html) like so: 49 | 50 | ```shell 51 | mvn spring-boot:run 52 | ``` 53 | 54 | Debug Mode 55 | ```shell 56 | mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" 57 | ``` 58 | 59 | If you want to run the Spring Cloud Data Flow example, run the following commands: 60 | 61 | ```shell 62 | HOST_MOUNT_PATH=~/.m2/repository/ DOCKER_MOUNT_PATH=/root/.m2/repository STREAM_APPS_URI=https://dataflow.spring.io/Einstein-BUILD-SNAPSHOT-stream-applications-kafka-maven SKIPPER_VERSION=2.4.0.RELEASE DATAFLOW_VERSION=2.5.0.RELEASE docker-compose -f ./docker/docker-compose.yml -f ./docker/docker-compose-postgres.yml -f ./docker/docker-compose-prometheus.yml up 63 | ``` 64 | 65 | And to Shut Down the containers: 66 | 67 | ```shell 68 | HOST_MOUNT_PATH=~/.m2/repository/ DOCKER_MOUNT_PATH=/root/.m2/repository STREAM_APPS_URI=https://dataflow.spring.io/Einstein-BUILD-SNAPSHOT-stream-applications-kafka-maven SKIPPER_VERSION=2.4.0.RELEASE DATAFLOW_VERSION=2.5.0.RELEASE docker-compose -f ./docker/docker-compose.yml -f ./docker/docker-compose-postgres.yml -f ./docker/docker-compose-prometheus.yml down 69 | ``` 70 | 71 | ### Tools 72 | 73 | To monitor and manage your application 74 | 75 | | Tool | URL | Method | 76 | | ------------- | ----------------------------------------- | ------ | 77 | | SCDF Dashboad | `http://localhost:9393/dashboard` | GET | 78 | | Prometheus | `http://localhost:9090/graph` | GET | 79 | | Grafana | `http://localhost:3000` | GET | 80 | | RSocket Proxy | `http://localhost:9096/metrics/connected` | GET | 81 | | pgAdmin4 | `http://localhost:80` | GET | 82 | 83 | ### URLs 84 | 85 | | URL | Method | Remarks | 86 | | --- | ------ | ------- | 87 | | | GET | | 88 | | | GET | | 89 | | | GET | | 90 | | | GET | | 91 | | | GET | | 92 | 93 | ### Person URLs 94 | 95 | | URL | Method | Remarks | 96 | | ------------------------------------ | ------ | ------------------------------------------------------------------------------------ | 97 | | `http://localhost:8080/api/person` | GET | Header `Accept:application/json` or `Accept:application/xml` for content negotiation | 98 | | `http://localhost:8080/api/person/1` | GET | | 99 | 100 | ## Documentation 101 | 102 | - [Postman Collection](https://documenter.getpostman.com/view/2449187/RWTiwzb2) - online, with code auto-generated snippets in cURL, jQuery, Ruby,Python Requests, Node, PHP and Go programming languages 103 | - [Postman Collection](https://github.com/fredgcosta/spring-batch-demo/blob/master/Spring%20Boot%20Template.postman_collection.json) - offline 104 | - [Swagger](http://localhost:8088/swagger-ui.html) - Documentation & Testing 105 | 106 | ## Files and Directories 107 | 108 | The project (a.k.a. project directory) has a particular directory structure. A representative project is shown below: 109 | 110 | ``` 111 | . 112 | ├── Spring Elements 113 | ├── src 114 | │ └── main 115 | │ └── java 116 | │ ├── com.example.demo 117 | │ ├── com.example.demo.config 118 | │ ├── com.example.demo.models 119 | │ ├── com.example.demo.repositories 120 | │ ├── com.example.demo.steps 121 | │ ├── com.example.demo.steps.chunklets 122 | │ ├── com.example.demo.steps.mappers 123 | │ ├── com.example.demo.steps.tasklets 124 | │ └── com.example.demo.steps.tokenizers 125 | ├── src 126 | │ └── main 127 | │ └── resources 128 | ├── input 129 | │ └── exemplo-sou-java.txt 130 | │ ├── application.properties 131 | │ ├── application.yml 132 | │ ├── banner.txt 133 | │ └── logback-spring.xml 134 | ├── src 135 | │ └── test 136 | │ └── java 137 | ├── JRE System Library 138 | ├── Maven Dependencies 139 | ├── target 140 | │ └──spring-batch-demo-0.0.1-SNAPSHOT 141 | ├── mvnw 142 | ├── mvnw.cmd 143 | ├── pom.xml 144 | └── README.md 145 | ``` 146 | 147 | ## packages 148 | 149 | - `models` — to hold our entities; 150 | - `repositories` — to communicate with the database; 151 | - `resources/` - Contains all the static resources, templates and property files. 152 | - `resources/application.properties` - It contains application-wide properties. Spring reads the properties defined in this file to configure your application. You can define server’s default port, server’s context path, database URLs etc, in this file. 153 | 154 | - `test/` - contains unit and integration tests 155 | 156 | - `pom.xml` - contains all the project dependencies 157 | 158 | ## Reporting Issues 159 | 160 | This Project uses GitHub's integrated issue tracking system to record bugs and feature requests. If you want to raise an issue, please follow the recommendations below: 161 | 162 | - Before you log a bug, please https://github.com/fredgcosta/spring-batch-demo/search?type=Issues[search the issue tracker] 163 | to see if someone has already reported the problem. 164 | - If the issue doesn't already exist, https://github.com/fredgcosta/spring-batch-demo/issues/new[create a new issue]. 165 | - Please provide as much information as possible with the issue report. 166 | - If you need to paste code, or include a stack trace use Markdown +++```+++ escapes before and after your text. 167 | 168 | ## Resources 169 | 170 | - [My API Lifecycle Checklist and Scorecard](https://dzone.com/articles/my-api-lifecycle-checklist-and-scorecard) 171 | - [HTTP Status Codes](https://www.restapitutorial.com/httpstatuscodes.html) 172 | - [Bootstrap w3schools](https://www.w3schools.com/bootstrap/) 173 | - [Common application properties](https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html) 174 | 175 | ## License 176 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM springcloud/spring-cloud-dataflow-server:2.5.0.RELEASE 2 | 3 | RUN rm -rf /opt/openjdk && \ 4 | cd /opt && \ 5 | curl https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_linux-x64_bin.tar.gz | tar xz && \ 6 | mv /opt/jdk-11 /opt/openjdk 7 | 8 | ENTRYPOINT ["java" "-jar" "/maven/spring-cloud-dataflow-server.jar"] -------------------------------------------------------------------------------- /docker/docker-compose-postgres.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | # Reconfigures the default docker-compose.yml to replace MySQL by Postgres 4 | # Usage: docker-compose -f ./docker-compose.yml -f ./docker-compose-postgres.yml up 5 | services: 6 | mysql: 7 | entrypoint: ["echo", "MySQL service is disabled"] 8 | 9 | postgres: 10 | image: postgres:12.2-alpine 11 | container_name: dataflow-postgres 12 | restart: always 13 | environment: 14 | POSTGRES_DB: dataflow 15 | POSTGRES_USER: root 16 | POSTGRES_PASSWORD: rootpw 17 | expose: 18 | - 5432 19 | ports: 20 | - 5432:5432 21 | networks: 22 | - scdf-net 23 | 24 | pgadmin4: 25 | image: dpage/pgadmin4:4.21 26 | container_name: dataflow-pgadmin4 27 | restart: always 28 | environment: 29 | PGADMIN_DEFAULT_EMAIL: "admin@example.com" 30 | PGADMIN_DEFAULT_PASSWORD: "admin" 31 | ports: 32 | - "80:80" 33 | depends_on: 34 | - postgres 35 | networks: 36 | - scdf-net 37 | 38 | dataflow-server: 39 | environment: 40 | - SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/dataflow 41 | - SPRING_DATASOURCE_USERNAME=root 42 | - SPRING_DATASOURCE_PASSWORD=rootpw 43 | - SPRING_DATASOURCE_DRIVER_CLASS_NAME=org.postgresql.Driver 44 | entrypoint: "./wait-for-it.sh -t 240 postgres:5432 -- java -jar /maven/spring-cloud-dataflow-server.jar" 45 | 46 | skipper-server: 47 | environment: 48 | - SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/dataflow 49 | - SPRING_DATASOURCE_USERNAME=root 50 | - SPRING_DATASOURCE_PASSWORD=rootpw 51 | - SPRING_DATASOURCE_DRIVER_CLASS_NAME=org.postgresql.Driver 52 | entrypoint: "./wait-for-it.sh -t 240 postgres:5432 -- java -Djava.security.egd=file:/dev/./urandom -jar /maven/spring-cloud-skipper-server.jar" 53 | -------------------------------------------------------------------------------- /docker/docker-compose-prometheus.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | # Extends the default docker-compose.yml with Prometheus/Grafana monitoring configuration 4 | # Usage: docker-compose -f ./docker-compose.yml -f ./docker-compose-prometheus.yml up 5 | services: 6 | dataflow-server: 7 | environment: 8 | - | 9 | SPRING_APPLICATION_JSON= 10 | { 11 | "spring.cloud.dataflow.applicationProperties":{ 12 | "task.management.metrics.export.prometheus":{ 13 | "enabled":true, 14 | "rsocket.enabled":true, 15 | "rsocket.host":"prometheus-rsocket-proxy", 16 | "rsocket.port":7001 17 | }, 18 | "stream.management.metrics.export.prometheus":{ 19 | "enabled":true, 20 | "rsocket.enabled":true, 21 | "rsocket.host":"prometheus-rsocket-proxy", 22 | "rsocket.port":7001 23 | } 24 | }, 25 | "spring.cloud.dataflow.grafana-info.url":"http://localhost:3000" 26 | } 27 | 28 | prometheus-rsocket-proxy: 29 | image: micrometermetrics/prometheus-rsocket-proxy:0.10.6 30 | container_name: prometheus-rsocket-proxy 31 | expose: 32 | - "9096" 33 | - "7001" 34 | - "8081" 35 | ports: 36 | - "9096:9096" 37 | - "7001:7001" 38 | - "8081:8081" 39 | environment: 40 | - server.port=9096 41 | networks: 42 | - scdf-net 43 | 44 | grafana: 45 | image: springcloud/spring-cloud-dataflow-grafana-prometheus:${DATAFLOW_VERSION:?DATAFLOW_VERSION is not set! Use 'export DATAFLOW_VERSION=local-server-image-tag'} 46 | container_name: grafana 47 | ports: 48 | - "3000:3000" 49 | networks: 50 | - scdf-net 51 | 52 | prometheus: 53 | image: springcloud/spring-cloud-dataflow-prometheus-local:${DATAFLOW_VERSION:?DATAFLOW_VERSION is not set! Use 'export DATAFLOW_VERSION=local-server-image-tag'} 54 | container_name: prometheus 55 | ports: 56 | - "9090:9090" 57 | networks: 58 | - scdf-net 59 | -------------------------------------------------------------------------------- /docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | # Configuration environment variables: 4 | # - DATAFLOW_VERSION and SKIPPER_VERSION specify what DataFlow and Skipper image versions to use. 5 | # - STREAM_APPS_URI and TASK_APPS_URI are used to specify what Stream and Task applications to pre-register. 6 | # - HOST_MOUNT_PATH and DOCKER_MOUNT_PATH are used to set the host and docker mount folders. 7 | # If not set HOST_MOUNT_PATH defaults to the local host folder where the docker compose is being started. 8 | # If not set DOCKER_MOUNT_PATH defaults to /root/scdf on dataflow-server and skipper containers. 9 | # Example to mount the local Maven repository: HOST_MOUNT_PATH=~/.m2/repository/ DOCKER_MOUNT_PATH=/root/.m2 docker-compose up 10 | # 11 | # Exposed container ports: 12 | # - 9393:9393 - Data Flow server port (http://localhost:9393/dashboard) 13 | # - 7577:7577 - Skipper server port (http://localhost:7577/api) 14 | # - 20000-20105:20000-20105 - Port range for all deployed stream applications. That means you can reach the 15 | # application's actuator endpoints from your host machine. 16 | services: 17 | mysql: 18 | image: mysql:5.7.25 19 | container_name: dataflow-mysql 20 | environment: 21 | MYSQL_DATABASE: dataflow 22 | MYSQL_USER: root 23 | MYSQL_ROOT_PASSWORD: rootpw 24 | expose: 25 | - 3306 26 | networks: 27 | - scdf-net 28 | 29 | kafka-broker: 30 | image: confluentinc/cp-kafka:5.5.0 31 | container_name: dataflow-kafka 32 | expose: 33 | - "9092" 34 | environment: 35 | - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka-broker:9092 36 | - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 37 | - KAFKA_ADVERTISED_HOST_NAME=kafka-broker 38 | - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 39 | depends_on: 40 | - zookeeper 41 | networks: 42 | - scdf-net 43 | 44 | zookeeper: 45 | image: confluentinc/cp-zookeeper:5.5.0 46 | container_name: dataflow-kafka-zookeeper 47 | expose: 48 | - "2181" 49 | environment: 50 | - ZOOKEEPER_CLIENT_PORT=2181 51 | networks: 52 | - scdf-net 53 | 54 | dataflow-server: 55 | # image: springcloud/spring-cloud-dataflow-server:${DATAFLOW_VERSION:?DATAFLOW_VERSION is not set!} 56 | build: ./ 57 | image: springcloud/spring-cloud-dataflow-server:local 58 | container_name: dataflow-server 59 | ports: 60 | - "9393:9393" 61 | environment: 62 | - spring.cloud.dataflow.applicationProperties.stream.spring.cloud.stream.kafka.binder.brokers=PLAINTEXT://kafka-broker:9092 63 | - spring.cloud.dataflow.applicationProperties.stream.spring.cloud.stream.kafka.streams.binder.brokers=PLAINTEXT://kafka-broker:9092 64 | - spring.cloud.dataflow.applicationProperties.stream.spring.cloud.stream.kafka.binder.zkNodes=zookeeper:2181 65 | - spring.cloud.dataflow.applicationProperties.stream.spring.cloud.stream.kafka.streams.binder.zkNodes=zookeeper:2181 66 | - spring.cloud.skipper.client.serverUri=http://skipper-server:7577/api 67 | - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/dataflow 68 | - SPRING_DATASOURCE_USERNAME=root 69 | - SPRING_DATASOURCE_PASSWORD=rootpw 70 | - SPRING_DATASOURCE_DRIVER_CLASS_NAME=org.mariadb.jdbc.Driver 71 | depends_on: 72 | - kafka-broker 73 | entrypoint: "./wait-for-it.sh mysql:3306 -- java -jar /maven/spring-cloud-dataflow-server.jar" 74 | volumes: 75 | - ${HOST_MOUNT_PATH:-.}:${DOCKER_MOUNT_PATH:-/root/scdf} 76 | networks: 77 | - scdf-net 78 | 79 | app-import: 80 | image: springcloud/openjdk:2.0.1.RELEASE 81 | container_name: dataflow-app-import 82 | depends_on: 83 | - dataflow-server 84 | command: > 85 | /bin/sh -c " 86 | ./wait-for-it.sh -t 180 dataflow-server:9393; 87 | wget -qO- 'http://dataflow-server:9393/apps' --post-data='uri=${STREAM_APPS_URI:-https://dataflow.spring.io/kafka-maven-latest&force=true}'; 88 | echo 'Stream apps imported' 89 | wget -qO- 'http://dataflow-server:9393/apps' --post-data='uri=${TASK_APPS_URI:-https://dataflow.spring.io/task-maven-latest&force=true}'; 90 | echo 'Task apps imported'" 91 | networks: 92 | - scdf-net 93 | 94 | skipper-server: 95 | image: springcloud/spring-cloud-skipper-server:${SKIPPER_VERSION:?SKIPPER_VERSION is not set!} 96 | container_name: skipper 97 | ports: 98 | - "7577:7577" 99 | - "20000-20105:20000-20105" 100 | environment: 101 | - SPRING_CLOUD_SKIPPER_SERVER_PLATFORM_LOCAL_ACCOUNTS_DEFAULT_PORTRANGE_LOW=20000 102 | - SPRING_CLOUD_SKIPPER_SERVER_PLATFORM_LOCAL_ACCOUNTS_DEFAULT_PORTRANGE_HIGH=20100 103 | - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/dataflow 104 | - SPRING_DATASOURCE_USERNAME=root 105 | - SPRING_DATASOURCE_PASSWORD=rootpw 106 | - SPRING_DATASOURCE_DRIVER_CLASS_NAME=org.mariadb.jdbc.Driver 107 | entrypoint: "./wait-for-it.sh mysql:3306 -- java -Djava.security.egd=file:/dev/./urandom -jar /spring-cloud-skipper-server.jar" 108 | volumes: 109 | - ${HOST_MOUNT_PATH:-.}:${DOCKER_MOUNT_PATH:-/root/scdf} 110 | networks: 111 | - scdf-net 112 | 113 | networks: 114 | scdf-net: 115 | name: scdf-net 116 | driver: bridge 117 | ipam: 118 | config: 119 | - subnet: 192.168.145.0/24 120 | -------------------------------------------------------------------------------- /grafana/grafana-dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [ 4 | { 5 | "builtIn": 1, 6 | "datasource": "-- Grafana --", 7 | "enable": true, 8 | "hide": true, 9 | "iconColor": "rgba(0, 211, 255, 1)", 10 | "name": "Annotations & Alerts", 11 | "type": "dashboard" 12 | } 13 | ] 14 | }, 15 | "editable": true, 16 | "gnetId": null, 17 | "graphTooltip": 0, 18 | "id": 26, 19 | "links": [], 20 | "panels": [ 21 | { 22 | "aliasColors": {}, 23 | "bars": false, 24 | "dashLength": 10, 25 | "dashes": false, 26 | "datasource": null, 27 | "fill": 0, 28 | "fillGradient": 0, 29 | "gridPos": { 30 | "h": 8, 31 | "w": 11, 32 | "x": 0, 33 | "y": 0 34 | }, 35 | "hiddenSeries": false, 36 | "id": 10, 37 | "legend": { 38 | "avg": false, 39 | "current": false, 40 | "max": false, 41 | "min": false, 42 | "show": true, 43 | "total": false, 44 | "values": false 45 | }, 46 | "lines": true, 47 | "linewidth": 2, 48 | "nullPointMode": "null", 49 | "options": { 50 | "dataLinks": [] 51 | }, 52 | "percentage": false, 53 | "pointradius": 2, 54 | "points": false, 55 | "renderer": "flot", 56 | "seriesOverrides": [], 57 | "spaceLength": 10, 58 | "stack": false, 59 | "steppedLine": true, 60 | "targets": [ 61 | { 62 | "expr": "prometheus_proxy_unrecognized_rsocket_total", 63 | "legendFormat": "{{kubernetes_pod_name}}", 64 | "refId": "A" 65 | } 66 | ], 67 | "thresholds": [], 68 | "timeFrom": null, 69 | "timeRegions": [], 70 | "timeShift": null, 71 | "title": "Unrecognized RSockets", 72 | "tooltip": { 73 | "shared": true, 74 | "sort": 0, 75 | "value_type": "individual" 76 | }, 77 | "type": "graph", 78 | "xaxis": { 79 | "buckets": null, 80 | "mode": "time", 81 | "name": null, 82 | "show": true, 83 | "values": [] 84 | }, 85 | "yaxes": [ 86 | { 87 | "format": "short", 88 | "label": null, 89 | "logBase": 1, 90 | "max": null, 91 | "min": null, 92 | "show": true 93 | }, 94 | { 95 | "format": "short", 96 | "label": null, 97 | "logBase": 1, 98 | "max": null, 99 | "min": null, 100 | "show": true 101 | } 102 | ], 103 | "yaxis": { 104 | "align": false, 105 | "alignLevel": null 106 | } 107 | }, 108 | { 109 | "aliasColors": {}, 110 | "bars": false, 111 | "dashLength": 10, 112 | "dashes": false, 113 | "datasource": null, 114 | "fill": 7, 115 | "fillGradient": 0, 116 | "gridPos": { 117 | "h": 8, 118 | "w": 12, 119 | "x": 11, 120 | "y": 0 121 | }, 122 | "hiddenSeries": false, 123 | "id": 6, 124 | "interval": "", 125 | "legend": { 126 | "alignAsTable": true, 127 | "avg": false, 128 | "current": true, 129 | "max": true, 130 | "min": false, 131 | "show": true, 132 | "total": false, 133 | "values": true 134 | }, 135 | "lines": true, 136 | "linewidth": 2, 137 | "nullPointMode": "null", 138 | "options": { 139 | "dataLinks": [] 140 | }, 141 | "percentage": false, 142 | "pointradius": 2, 143 | "points": false, 144 | "renderer": "flot", 145 | "seriesOverrides": [ 146 | { 147 | "alias": "complete", 148 | "color": "#73BF69" 149 | }, 150 | { 151 | "alias": "cancel", 152 | "color": "#FADE2A" 153 | }, 154 | { 155 | "alias": "error", 156 | "color": "#F2495C", 157 | "fill": 0, 158 | "lines": false, 159 | "points": true 160 | } 161 | ], 162 | "spaceLength": 10, 163 | "stack": true, 164 | "steppedLine": true, 165 | "targets": [ 166 | { 167 | "expr": "sum(rate(rsocket_request_response_seconds_count{signal_type=\"ON_COMPLETE\"}[1m]))", 168 | "legendFormat": "complete", 169 | "refId": "B" 170 | }, 171 | { 172 | "expr": "sum(rate(rsocket_request_response_seconds_count{signal_type=\"CANCEL\"}[1m]))", 173 | "legendFormat": "cancel", 174 | "refId": "C" 175 | }, 176 | { 177 | "expr": "sum(rate(rsocket_request_response_seconds_count{signal_type=\"ON_ERROR\"}[1m]))", 178 | "legendFormat": "error", 179 | "refId": "A" 180 | } 181 | ], 182 | "thresholds": [], 183 | "timeFrom": null, 184 | "timeRegions": [], 185 | "timeShift": null, 186 | "title": "RSocket Request/Responses", 187 | "tooltip": { 188 | "shared": true, 189 | "sort": 0, 190 | "value_type": "individual" 191 | }, 192 | "type": "graph", 193 | "xaxis": { 194 | "buckets": null, 195 | "mode": "time", 196 | "name": null, 197 | "show": true, 198 | "values": [] 199 | }, 200 | "yaxes": [ 201 | { 202 | "format": "ops", 203 | "label": "requests", 204 | "logBase": 1, 205 | "max": null, 206 | "min": null, 207 | "show": true 208 | }, 209 | { 210 | "format": "short", 211 | "label": null, 212 | "logBase": 1, 213 | "max": null, 214 | "min": null, 215 | "show": true 216 | } 217 | ], 218 | "yaxis": { 219 | "align": false, 220 | "alignLevel": null 221 | } 222 | }, 223 | { 224 | "aliasColors": {}, 225 | "bars": false, 226 | "dashLength": 10, 227 | "dashes": false, 228 | "datasource": null, 229 | "fill": 7, 230 | "fillGradient": 0, 231 | "gridPos": { 232 | "h": 8, 233 | "w": 11, 234 | "x": 0, 235 | "y": 8 236 | }, 237 | "hiddenSeries": false, 238 | "id": 8, 239 | "legend": { 240 | "alignAsTable": true, 241 | "avg": false, 242 | "current": true, 243 | "max": true, 244 | "min": false, 245 | "show": true, 246 | "total": false, 247 | "values": true 248 | }, 249 | "lines": true, 250 | "linewidth": 2, 251 | "nullPointMode": "null", 252 | "options": { 253 | "dataLinks": [] 254 | }, 255 | "percentage": false, 256 | "pointradius": 2, 257 | "points": false, 258 | "renderer": "flot", 259 | "seriesOverrides": [ 260 | { 261 | "alias": "success", 262 | "color": "#73BF69" 263 | }, 264 | { 265 | "alias": "closed", 266 | "color": "#FADE2A" 267 | }, 268 | { 269 | "alias": "error", 270 | "color": "#F2495C", 271 | "fill": 0, 272 | "lines": false, 273 | "points": true 274 | } 275 | ], 276 | "spaceLength": 10, 277 | "stack": true, 278 | "steppedLine": true, 279 | "targets": [ 280 | { 281 | "expr": "sum(rate(prometheus_proxy_scrape_seconds_count{outcome=\"success\"}[1m]))", 282 | "legendFormat": "success", 283 | "refId": "A" 284 | }, 285 | { 286 | "expr": "sum(rate(prometheus_proxy_scrape_seconds_count{outcome=\"closed\"}[1m]))", 287 | "legendFormat": "closed", 288 | "refId": "B" 289 | }, 290 | { 291 | "expr": "sum(rate(prometheus_proxy_scrape_seconds_count{outcome=\"error\"}[1m]))", 292 | "legendFormat": "error", 293 | "refId": "C" 294 | } 295 | ], 296 | "thresholds": [], 297 | "timeFrom": null, 298 | "timeRegions": [], 299 | "timeShift": null, 300 | "title": "Prometheus Scrapes of Individual Processes by Outcome", 301 | "tooltip": { 302 | "shared": true, 303 | "sort": 0, 304 | "value_type": "individual" 305 | }, 306 | "type": "graph", 307 | "xaxis": { 308 | "buckets": null, 309 | "mode": "time", 310 | "name": null, 311 | "show": true, 312 | "values": [] 313 | }, 314 | "yaxes": [ 315 | { 316 | "format": "ops", 317 | "label": "scrapes", 318 | "logBase": 1, 319 | "max": null, 320 | "min": null, 321 | "show": true 322 | }, 323 | { 324 | "format": "short", 325 | "label": null, 326 | "logBase": 1, 327 | "max": null, 328 | "min": null, 329 | "show": true 330 | } 331 | ], 332 | "yaxis": { 333 | "align": false, 334 | "alignLevel": null 335 | } 336 | }, 337 | { 338 | "aliasColors": {}, 339 | "bars": false, 340 | "dashLength": 10, 341 | "dashes": false, 342 | "datasource": null, 343 | "fill": 0, 344 | "fillGradient": 0, 345 | "gridPos": { 346 | "h": 8, 347 | "w": 12, 348 | "x": 11, 349 | "y": 8 350 | }, 351 | "hiddenSeries": false, 352 | "id": 2, 353 | "legend": { 354 | "avg": false, 355 | "current": false, 356 | "max": false, 357 | "min": false, 358 | "show": true, 359 | "total": false, 360 | "values": false 361 | }, 362 | "lines": true, 363 | "linewidth": 2, 364 | "nullPointMode": "null", 365 | "options": { 366 | "dataLinks": [] 367 | }, 368 | "percentage": false, 369 | "pointradius": 2, 370 | "points": false, 371 | "renderer": "flot", 372 | "seriesOverrides": [], 373 | "spaceLength": 10, 374 | "stack": false, 375 | "steppedLine": true, 376 | "targets": [ 377 | { 378 | "expr": "prometheus_proxy_scrape_active_connections", 379 | "legendFormat": "{{kubernetes_pod_name}}", 380 | "refId": "A" 381 | } 382 | ], 383 | "thresholds": [], 384 | "timeFrom": null, 385 | "timeRegions": [], 386 | "timeShift": null, 387 | "title": "Active Connections", 388 | "tooltip": { 389 | "shared": true, 390 | "sort": 0, 391 | "value_type": "individual" 392 | }, 393 | "type": "graph", 394 | "xaxis": { 395 | "buckets": null, 396 | "mode": "time", 397 | "name": null, 398 | "show": true, 399 | "values": [] 400 | }, 401 | "yaxes": [ 402 | { 403 | "format": "short", 404 | "label": "connections", 405 | "logBase": 1, 406 | "max": null, 407 | "min": null, 408 | "show": true 409 | }, 410 | { 411 | "format": "short", 412 | "label": null, 413 | "logBase": 1, 414 | "max": null, 415 | "min": null, 416 | "show": true 417 | } 418 | ], 419 | "yaxis": { 420 | "align": false, 421 | "alignLevel": null 422 | } 423 | }, 424 | { 425 | "aliasColors": {}, 426 | "bars": false, 427 | "dashLength": 10, 428 | "dashes": false, 429 | "datasource": null, 430 | "fill": 0, 431 | "fillGradient": 0, 432 | "gridPos": { 433 | "h": 8, 434 | "w": 11, 435 | "x": 0, 436 | "y": 16 437 | }, 438 | "hiddenSeries": false, 439 | "id": 4, 440 | "legend": { 441 | "alignAsTable": true, 442 | "avg": false, 443 | "current": false, 444 | "max": true, 445 | "min": false, 446 | "rightSide": false, 447 | "show": true, 448 | "total": false, 449 | "values": true 450 | }, 451 | "lines": true, 452 | "linewidth": 2, 453 | "nullPointMode": "null", 454 | "options": { 455 | "dataLinks": [] 456 | }, 457 | "percentage": false, 458 | "pointradius": 2, 459 | "points": false, 460 | "renderer": "flot", 461 | "seriesOverrides": [ 462 | { 463 | "alias": "count", 464 | "fill": 4, 465 | "linewidth": 0, 466 | "yaxis": 2 467 | } 468 | ], 469 | "spaceLength": 10, 470 | "stack": false, 471 | "steppedLine": true, 472 | "targets": [ 473 | { 474 | "expr": "prometheus_proxy_scrape_payload_bytes_max", 475 | "legendFormat": "{{kubernetes_pod_name}}", 476 | "refId": "A" 477 | }, 478 | { 479 | "expr": "sum(rate(prometheus_proxy_scrape_payload_bytes_count[1m]))", 480 | "legendFormat": "count", 481 | "refId": "B" 482 | } 483 | ], 484 | "thresholds": [], 485 | "timeFrom": null, 486 | "timeRegions": [], 487 | "timeShift": null, 488 | "title": "Maximum Scrape Payload", 489 | "tooltip": { 490 | "shared": true, 491 | "sort": 0, 492 | "value_type": "individual" 493 | }, 494 | "type": "graph", 495 | "xaxis": { 496 | "buckets": null, 497 | "mode": "time", 498 | "name": null, 499 | "show": true, 500 | "values": [] 501 | }, 502 | "yaxes": [ 503 | { 504 | "format": "decbytes", 505 | "label": "scrape payload size", 506 | "logBase": 1, 507 | "max": null, 508 | "min": "0", 509 | "show": true 510 | }, 511 | { 512 | "format": "ops", 513 | "label": "scrape throughput", 514 | "logBase": 1, 515 | "max": null, 516 | "min": null, 517 | "show": true 518 | } 519 | ], 520 | "yaxis": { 521 | "align": false, 522 | "alignLevel": null 523 | } 524 | } 525 | ], 526 | "refresh": false, 527 | "schemaVersion": 21, 528 | "style": "dark", 529 | "tags": [], 530 | "templating": { 531 | "list": [] 532 | }, 533 | "time": { 534 | "from": "2020-04-08T22:28:38.562Z", 535 | "to": "2020-04-08T22:31:22.858Z" 536 | }, 537 | "timepicker": { 538 | "refresh_intervals": [ 539 | "5s", 540 | "10s", 541 | "30s", 542 | "1m", 543 | "5m", 544 | "15m", 545 | "30m", 546 | "1h", 547 | "2h", 548 | "1d" 549 | ] 550 | }, 551 | "timezone": "", 552 | "title": "Prometheus Proxy", 553 | "uid": "5sancpjZk", 554 | "version": 21 555 | } 556 | -------------------------------------------------------------------------------- /grafana/scdf-task-batch.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [{ 4 | "builtIn": 1, 5 | "datasource": "-- Grafana --", 6 | "enable": true, 7 | "hide": true, 8 | "iconColor": "rgba(0, 211, 255, 1)", 9 | "name": "Annotations & Alerts", 10 | "type": "dashboard" 11 | }] 12 | }, 13 | "editable": true, 14 | "gnetId": null, 15 | "graphTooltip": 0, 16 | "id": 5, 17 | "iteration": 1566398687952, 18 | "links": [{ 19 | "icon": "external link", 20 | "tags": [], 21 | "type": "dashboards" 22 | }], 23 | "panels": [{ 24 | "cacheTimeout": null, 25 | "colorBackground": false, 26 | "colorValue": false, 27 | "colors": [ 28 | "#299c46", 29 | "rgba(237, 129, 40, 0.89)", 30 | "#d44a3a" 31 | ], 32 | "datasource": "ScdfPrometheus", 33 | "description": "Number of executed tasks in this the time range", 34 | "format": "none", 35 | "gauge": { 36 | "maxValue": 100, 37 | "minValue": 0, 38 | "show": false, 39 | "thresholdLabels": false, 40 | "thresholdMarkers": true 41 | }, 42 | "gridPos": { 43 | "h": 4, 44 | "w": 2, 45 | "x": 0, 46 | "y": 0 47 | }, 48 | "id": 13, 49 | "interval": null, 50 | "links": [], 51 | "mappingType": 1, 52 | "mappingTypes": [{ 53 | "name": "value to text", 54 | "value": 1 55 | }, 56 | { 57 | "name": "range to text", 58 | "value": 2 59 | } 60 | ], 61 | "maxDataPoints": 100, 62 | "nullPointMode": "connected", 63 | "nullText": null, 64 | "options": {}, 65 | "pluginVersion": "6.2.5", 66 | "postfix": "", 67 | "postfixFontSize": "50%", 68 | "prefix": "", 69 | "prefixFontSize": "50%", 70 | "rangeMaps": [{ 71 | "from": "null", 72 | "text": "N/A", 73 | "to": "null" 74 | }], 75 | "sparkline": { 76 | "fillColor": "rgba(31, 118, 189, 0.18)", 77 | "full": true, 78 | "lineColor": "rgb(31, 120, 193)", 79 | "show": true 80 | }, 81 | "tableColumn": "Value", 82 | "targets": [{ 83 | "expr": "count(count by (task_name,task_execution_id) (spring_cloud_task_seconds_count))", 84 | "format": "time_series", 85 | "instant": false, 86 | "interval": "", 87 | "intervalFactor": 1, 88 | "refId": "A" 89 | }], 90 | "thresholds": "", 91 | "timeFrom": null, 92 | "timeShift": null, 93 | "title": "Task Count", 94 | "type": "singlestat", 95 | "valueFontSize": "80%", 96 | "valueMaps": [{ 97 | "op": "=", 98 | "text": "N/A", 99 | "value": "null" 100 | }], 101 | "valueName": "total" 102 | }, 103 | { 104 | "aliasColors": {}, 105 | "bars": false, 106 | "cacheTimeout": null, 107 | "dashLength": 10, 108 | "dashes": false, 109 | "datasource": "ScdfPrometheus", 110 | "description": "Number of executed tasks in this the time range", 111 | "fill": 1, 112 | "fillGradient": 0, 113 | "gridPos": { 114 | "h": 8, 115 | "w": 10, 116 | "x": 2, 117 | "y": 0 118 | }, 119 | "id": 14, 120 | "legend": { 121 | "avg": false, 122 | "current": false, 123 | "max": false, 124 | "min": false, 125 | "show": true, 126 | "total": false, 127 | "values": false 128 | }, 129 | "lines": true, 130 | "linewidth": 1, 131 | "links": [], 132 | "nullPointMode": "null", 133 | "options": { 134 | "dataLinks": [] 135 | }, 136 | "percentage": false, 137 | "pluginVersion": "6.2.5", 138 | "pointradius": 2, 139 | "points": false, 140 | "renderer": "flot", 141 | "seriesOverrides": [], 142 | "spaceLength": 10, 143 | "stack": false, 144 | "steppedLine": true, 145 | "targets": [{ 146 | "expr": "spring_cloud_task_active_seconds_active_count", 147 | "format": "time_series", 148 | "instant": false, 149 | "intervalFactor": 1, 150 | "legendFormat": "{{task_name}}:{{task_execution_id}}", 151 | "refId": "A" 152 | }], 153 | "thresholds": [], 154 | "timeFrom": null, 155 | "timeRegions": [], 156 | "timeShift": null, 157 | "title": "Active Tasks Count", 158 | "tooltip": { 159 | "shared": true, 160 | "sort": 0, 161 | "value_type": "individual" 162 | }, 163 | "type": "graph", 164 | "xaxis": { 165 | "buckets": null, 166 | "mode": "time", 167 | "name": null, 168 | "show": true, 169 | "values": [] 170 | }, 171 | "yaxes": [{ 172 | "format": "short", 173 | "label": null, 174 | "logBase": 1, 175 | "max": "1", 176 | "min": "0", 177 | "show": false 178 | }, 179 | { 180 | "format": "short", 181 | "label": null, 182 | "logBase": 1, 183 | "max": null, 184 | "min": null, 185 | "show": false 186 | } 187 | ], 188 | "yaxis": { 189 | "align": false, 190 | "alignLevel": null 191 | } 192 | }, 193 | { 194 | "aliasColors": {}, 195 | "bars": true, 196 | "dashLength": 10, 197 | "dashes": false, 198 | "datasource": "ScdfPrometheus", 199 | "fill": 1, 200 | "fillGradient": 0, 201 | "gridPos": { 202 | "h": 8, 203 | "w": 12, 204 | "x": 12, 205 | "y": 0 206 | }, 207 | "id": 5, 208 | "legend": { 209 | "avg": false, 210 | "current": false, 211 | "max": false, 212 | "min": false, 213 | "show": true, 214 | "total": false, 215 | "values": false 216 | }, 217 | "lines": false, 218 | "linewidth": 1, 219 | "links": [], 220 | "nullPointMode": "null", 221 | "options": { 222 | "dataLinks": [] 223 | }, 224 | "percentage": false, 225 | "pointradius": 2, 226 | "points": false, 227 | "renderer": "flot", 228 | "seriesOverrides": [], 229 | "spaceLength": 10, 230 | "stack": true, 231 | "steppedLine": false, 232 | "targets": [{ 233 | "expr": "sum(spring_cloud_task_seconds_sum) by (task_name,task_execution_id)", 234 | "format": "time_series", 235 | "intervalFactor": 1, 236 | "legendFormat": "{{task_name}}:{{task_execution_id}}", 237 | "refId": "A" 238 | }], 239 | "thresholds": [], 240 | "timeFrom": null, 241 | "timeRegions": [], 242 | "timeShift": null, 243 | "title": "Task Duration", 244 | "tooltip": { 245 | "shared": true, 246 | "sort": 0, 247 | "value_type": "individual" 248 | }, 249 | "type": "graph", 250 | "xaxis": { 251 | "buckets": null, 252 | "mode": "time", 253 | "name": null, 254 | "show": true, 255 | "values": [] 256 | }, 257 | "yaxes": [{ 258 | "format": "s", 259 | "label": null, 260 | "logBase": 1, 261 | "max": null, 262 | "min": null, 263 | "show": true 264 | }, 265 | { 266 | "format": "short", 267 | "label": null, 268 | "logBase": 1, 269 | "max": null, 270 | "min": null, 271 | "show": false 272 | } 273 | ], 274 | "yaxis": { 275 | "align": false, 276 | "alignLevel": null 277 | } 278 | }, 279 | { 280 | "cacheTimeout": null, 281 | "colorBackground": false, 282 | "colorValue": false, 283 | "colors": [ 284 | "#299c46", 285 | "rgba(237, 129, 40, 0.89)", 286 | "#d44a3a" 287 | ], 288 | "datasource": "ScdfPrometheus", 289 | "description": "Number of executed tasks in this the time range", 290 | "format": "none", 291 | "gauge": { 292 | "maxValue": 100, 293 | "minValue": 0, 294 | "show": false, 295 | "thresholdLabels": false, 296 | "thresholdMarkers": true 297 | }, 298 | "gridPos": { 299 | "h": 4, 300 | "w": 2, 301 | "x": 0, 302 | "y": 4 303 | }, 304 | "id": 16, 305 | "interval": null, 306 | "links": [], 307 | "mappingType": 1, 308 | "mappingTypes": [{ 309 | "name": "value to text", 310 | "value": 1 311 | }, 312 | { 313 | "name": "range to text", 314 | "value": 2 315 | } 316 | ], 317 | "maxDataPoints": 100, 318 | "nullPointMode": "connected", 319 | "nullText": null, 320 | "options": {}, 321 | "pluginVersion": "6.2.5", 322 | "postfix": "", 323 | "postfixFontSize": "50%", 324 | "prefix": "", 325 | "prefixFontSize": "50%", 326 | "rangeMaps": [{ 327 | "from": "null", 328 | "text": "N/A", 329 | "to": "null" 330 | }], 331 | "sparkline": { 332 | "fillColor": "rgba(31, 118, 189, 0.18)", 333 | "full": true, 334 | "lineColor": "rgb(31, 120, 193)", 335 | "show": true 336 | }, 337 | "tableColumn": "Value", 338 | "targets": [{ 339 | "expr": "count(count(spring_batch_job_active_seconds_active_count) by (task_name,task_execution_id,name))", 340 | "format": "time_series", 341 | "instant": false, 342 | "interval": "", 343 | "intervalFactor": 1, 344 | "refId": "A" 345 | }], 346 | "thresholds": "", 347 | "timeFrom": null, 348 | "timeShift": null, 349 | "title": "Job Count", 350 | "type": "singlestat", 351 | "valueFontSize": "80%", 352 | "valueMaps": [{ 353 | "op": "=", 354 | "text": "N/A", 355 | "value": "null" 356 | }], 357 | "valueName": "total" 358 | }, 359 | { 360 | "aliasColors": {}, 361 | "bars": false, 362 | "dashLength": 10, 363 | "dashes": false, 364 | "datasource": "ScdfPrometheus", 365 | "fill": 1, 366 | "fillGradient": 0, 367 | "gridPos": { 368 | "h": 8, 369 | "w": 12, 370 | "x": 0, 371 | "y": 8 372 | }, 373 | "id": 4, 374 | "legend": { 375 | "avg": false, 376 | "current": false, 377 | "max": false, 378 | "min": false, 379 | "show": true, 380 | "total": false, 381 | "values": false 382 | }, 383 | "lines": true, 384 | "linewidth": 1, 385 | "links": [], 386 | "nullPointMode": "null", 387 | "options": { 388 | "dataLinks": [] 389 | }, 390 | "percentage": false, 391 | "pointradius": 2, 392 | "points": false, 393 | "renderer": "flot", 394 | "seriesOverrides": [], 395 | "spaceLength": 10, 396 | "stack": false, 397 | "steppedLine": true, 398 | "targets": [{ 399 | "expr": "sum(spring_cloud_task_active_seconds_duration_sum{task_name=~\"$task_name\",task_execution_id=~\"$task_execution_id\"}) by (task_name, task_execution_id)", 400 | "format": "time_series", 401 | "intervalFactor": 1, 402 | "legendFormat": "{{task_name}}:{{task_execution_id}}", 403 | "refId": "A" 404 | }], 405 | "thresholds": [], 406 | "timeFrom": null, 407 | "timeRegions": [], 408 | "timeShift": null, 409 | "title": "Active Task Duration", 410 | "tooltip": { 411 | "shared": true, 412 | "sort": 0, 413 | "value_type": "individual" 414 | }, 415 | "type": "graph", 416 | "xaxis": { 417 | "buckets": null, 418 | "mode": "time", 419 | "name": null, 420 | "show": true, 421 | "values": [] 422 | }, 423 | "yaxes": [{ 424 | "format": "s", 425 | "label": null, 426 | "logBase": 1, 427 | "max": null, 428 | "min": "0", 429 | "show": true 430 | }, 431 | { 432 | "format": "short", 433 | "label": null, 434 | "logBase": 1, 435 | "max": null, 436 | "min": null, 437 | "show": false 438 | } 439 | ], 440 | "yaxis": { 441 | "align": false, 442 | "alignLevel": null 443 | } 444 | }, 445 | { 446 | "aliasColors": {}, 447 | "bars": false, 448 | "dashLength": 10, 449 | "dashes": false, 450 | "datasource": "ScdfPrometheus", 451 | "fill": 1, 452 | "fillGradient": 0, 453 | "gridPos": { 454 | "h": 8, 455 | "w": 12, 456 | "x": 12, 457 | "y": 8 458 | }, 459 | "id": 8, 460 | "legend": { 461 | "avg": false, 462 | "current": false, 463 | "max": false, 464 | "min": false, 465 | "show": true, 466 | "total": false, 467 | "values": false 468 | }, 469 | "lines": true, 470 | "linewidth": 1, 471 | "links": [], 472 | "nullPointMode": "null", 473 | "options": { 474 | "dataLinks": [] 475 | }, 476 | "percentage": false, 477 | "pointradius": 2, 478 | "points": false, 479 | "renderer": "flot", 480 | "seriesOverrides": [], 481 | "spaceLength": 10, 482 | "stack": false, 483 | "steppedLine": true, 484 | "targets": [{ 485 | "expr": "sum(spring_batch_job_seconds_max{task_name=~\"$task_name\",name=~\"$job_name\"}) by (task_name,task_execution_id,name)", 486 | "format": "time_series", 487 | "intervalFactor": 1, 488 | "legendFormat": "{{task_name}}:{{task_execution_id}}-{{name}}", 489 | "refId": "A" 490 | }], 491 | "thresholds": [], 492 | "timeFrom": null, 493 | "timeRegions": [], 494 | "timeShift": null, 495 | "title": "Job Duration", 496 | "tooltip": { 497 | "shared": true, 498 | "sort": 0, 499 | "value_type": "individual" 500 | }, 501 | "type": "graph", 502 | "xaxis": { 503 | "buckets": null, 504 | "mode": "time", 505 | "name": null, 506 | "show": true, 507 | "values": [] 508 | }, 509 | "yaxes": [{ 510 | "format": "s", 511 | "label": null, 512 | "logBase": 1, 513 | "max": null, 514 | "min": null, 515 | "show": true 516 | }, 517 | { 518 | "format": "short", 519 | "label": null, 520 | "logBase": 1, 521 | "max": null, 522 | "min": null, 523 | "show": false 524 | } 525 | ], 526 | "yaxis": { 527 | "align": false, 528 | "alignLevel": null 529 | } 530 | }, 531 | { 532 | "aliasColors": {}, 533 | "bars": true, 534 | "dashLength": 10, 535 | "dashes": false, 536 | "datasource": "ScdfPrometheus", 537 | "fill": 1, 538 | "fillGradient": 0, 539 | "gridPos": { 540 | "h": 8, 541 | "w": 12, 542 | "x": 0, 543 | "y": 16 544 | }, 545 | "id": 2, 546 | "legend": { 547 | "avg": false, 548 | "current": false, 549 | "max": false, 550 | "min": false, 551 | "show": true, 552 | "total": false, 553 | "values": false 554 | }, 555 | "lines": false, 556 | "linewidth": 1, 557 | "links": [], 558 | "nullPointMode": "null", 559 | "options": { 560 | "dataLinks": [] 561 | }, 562 | "percentage": false, 563 | "pointradius": 2, 564 | "points": false, 565 | "renderer": "flot", 566 | "seriesOverrides": [{}], 567 | "spaceLength": 10, 568 | "stack": false, 569 | "steppedLine": false, 570 | "targets": [{ 571 | "expr": "rate(spring_cloud_task_seconds_count[1m])", 572 | "format": "time_series", 573 | "intervalFactor": 1, 574 | "legendFormat": "", 575 | "refId": "A" 576 | }], 577 | "thresholds": [], 578 | "timeFrom": null, 579 | "timeRegions": [], 580 | "timeShift": null, 581 | "title": "Task Rate", 582 | "tooltip": { 583 | "shared": true, 584 | "sort": 0, 585 | "value_type": "individual" 586 | }, 587 | "type": "graph", 588 | "xaxis": { 589 | "buckets": null, 590 | "mode": "time", 591 | "name": null, 592 | "show": true, 593 | "values": [] 594 | }, 595 | "yaxes": [{ 596 | "format": "opm", 597 | "label": null, 598 | "logBase": 1, 599 | "max": null, 600 | "min": "0", 601 | "show": true 602 | }, 603 | { 604 | "format": "short", 605 | "label": null, 606 | "logBase": 1, 607 | "max": null, 608 | "min": null, 609 | "show": false 610 | } 611 | ], 612 | "yaxis": { 613 | "align": false, 614 | "alignLevel": null 615 | } 616 | }, 617 | { 618 | "aliasColors": {}, 619 | "bars": true, 620 | "dashLength": 10, 621 | "dashes": false, 622 | "datasource": "ScdfPrometheus", 623 | "fill": 1, 624 | "fillGradient": 0, 625 | "gridPos": { 626 | "h": 8, 627 | "w": 12, 628 | "x": 12, 629 | "y": 16 630 | }, 631 | "id": 6, 632 | "legend": { 633 | "avg": false, 634 | "current": false, 635 | "max": false, 636 | "min": false, 637 | "show": true, 638 | "total": false, 639 | "values": false 640 | }, 641 | "lines": false, 642 | "linewidth": 1, 643 | "links": [], 644 | "nullPointMode": "null", 645 | "options": { 646 | "dataLinks": [] 647 | }, 648 | "percentage": false, 649 | "pointradius": 2, 650 | "points": false, 651 | "renderer": "flot", 652 | "seriesOverrides": [{}], 653 | "spaceLength": 10, 654 | "stack": false, 655 | "steppedLine": false, 656 | "targets": [{ 657 | "expr": "rate(spring_cloud_task_active_seconds_active_count{task_name=~\"$task_name\"}[1m]) ", 658 | "format": "time_series", 659 | "intervalFactor": 1, 660 | "legendFormat": "{{task_name}}:{{task_execution_id}}", 661 | "refId": "A" 662 | }], 663 | "thresholds": [], 664 | "timeFrom": null, 665 | "timeRegions": [], 666 | "timeShift": null, 667 | "title": "Active Task Rate", 668 | "tooltip": { 669 | "shared": true, 670 | "sort": 0, 671 | "value_type": "individual" 672 | }, 673 | "type": "graph", 674 | "xaxis": { 675 | "buckets": null, 676 | "mode": "time", 677 | "name": null, 678 | "show": true, 679 | "values": [] 680 | }, 681 | "yaxes": [{ 682 | "format": "opm", 683 | "label": null, 684 | "logBase": 1, 685 | "max": null, 686 | "min": "0", 687 | "show": true 688 | }, 689 | { 690 | "format": "short", 691 | "label": null, 692 | "logBase": 1, 693 | "max": null, 694 | "min": null, 695 | "show": false 696 | } 697 | ], 698 | "yaxis": { 699 | "align": false, 700 | "alignLevel": null 701 | } 702 | }, 703 | { 704 | "aliasColors": {}, 705 | "bars": false, 706 | "dashLength": 10, 707 | "dashes": false, 708 | "datasource": "ScdfPrometheus", 709 | "fill": 1, 710 | "fillGradient": 0, 711 | "gridPos": { 712 | "h": 8, 713 | "w": 12, 714 | "x": 0, 715 | "y": 24 716 | }, 717 | "id": 9, 718 | "legend": { 719 | "avg": false, 720 | "current": false, 721 | "max": false, 722 | "min": false, 723 | "show": true, 724 | "total": false, 725 | "values": false 726 | }, 727 | "lines": true, 728 | "linewidth": 1, 729 | "links": [], 730 | "nullPointMode": "null", 731 | "options": { 732 | "dataLinks": [] 733 | }, 734 | "percentage": false, 735 | "pointradius": 2, 736 | "points": false, 737 | "renderer": "flot", 738 | "seriesOverrides": [], 739 | "spaceLength": 10, 740 | "stack": false, 741 | "steppedLine": true, 742 | "targets": [{ 743 | "expr": "rate(spring_batch_job_seconds_max{task_name=\"$task_name\",name=~\"$job_name\"}[1m])", 744 | "format": "time_series", 745 | "intervalFactor": 1, 746 | "legendFormat": "{{task_name}}-{{name}}", 747 | "refId": "A" 748 | }], 749 | "thresholds": [], 750 | "timeFrom": null, 751 | "timeRegions": [], 752 | "timeShift": null, 753 | "title": "Job Rate", 754 | "tooltip": { 755 | "shared": true, 756 | "sort": 0, 757 | "value_type": "individual" 758 | }, 759 | "type": "graph", 760 | "xaxis": { 761 | "buckets": null, 762 | "mode": "time", 763 | "name": null, 764 | "show": true, 765 | "values": [] 766 | }, 767 | "yaxes": [{ 768 | "format": "ops", 769 | "label": null, 770 | "logBase": 1, 771 | "max": null, 772 | "min": "0", 773 | "show": true 774 | }, 775 | { 776 | "format": "short", 777 | "label": null, 778 | "logBase": 1, 779 | "max": null, 780 | "min": null, 781 | "show": false 782 | } 783 | ], 784 | "yaxis": { 785 | "align": false, 786 | "alignLevel": null 787 | } 788 | } 789 | ], 790 | "refresh": "15s", 791 | "schemaVersion": 19, 792 | "style": "dark", 793 | "tags": [], 794 | "templating": { 795 | "list": [{ 796 | "allValue": null, 797 | "current": { 798 | "text": "task999", 799 | "value": "task999" 800 | }, 801 | "datasource": "ScdfPrometheus", 802 | "definition": "label_values(task_name)", 803 | "hide": 0, 804 | "includeAll": true, 805 | "label": "task", 806 | "multi": false, 807 | "name": "task_name", 808 | "options": [], 809 | "query": "label_values(task_name)", 810 | "refresh": 2, 811 | "regex": "", 812 | "skipUrlSync": false, 813 | "sort": 0, 814 | "tagValuesQuery": "", 815 | "tags": [], 816 | "tagsQuery": "", 817 | "type": "query", 818 | "useTags": false 819 | }, 820 | { 821 | "allValue": null, 822 | "current": { 823 | "text": "All", 824 | "value": "$__all" 825 | }, 826 | "datasource": "ScdfPrometheus", 827 | "definition": "label_values({task_name=\"$task_name\"},task_execution_id)", 828 | "hide": 0, 829 | "includeAll": true, 830 | "label": "task_id", 831 | "multi": true, 832 | "name": "task_execution_id", 833 | "options": [], 834 | "query": "label_values({task_name=\"$task_name\"},task_execution_id)", 835 | "refresh": 2, 836 | "regex": "", 837 | "skipUrlSync": false, 838 | "sort": 0, 839 | "tagValuesQuery": "name", 840 | "tags": [], 841 | "tagsQuery": "spring_batch_job_seconds_max", 842 | "type": "query", 843 | "useTags": false 844 | }, 845 | { 846 | "allValue": null, 847 | "current": { 848 | "text": "All", 849 | "value": "$__all" 850 | }, 851 | "datasource": "ScdfPrometheus", 852 | "definition": "label_values(spring_batch_job_seconds_max{task_name=\"$task_name\"},name)", 853 | "hide": 0, 854 | "includeAll": true, 855 | "label": "job", 856 | "multi": true, 857 | "name": "job_name", 858 | "options": [], 859 | "query": "label_values(spring_batch_job_seconds_max{task_name=\"$task_name\"},name)", 860 | "refresh": 2, 861 | "regex": "", 862 | "skipUrlSync": false, 863 | "sort": 0, 864 | "tagValuesQuery": "name", 865 | "tags": [], 866 | "tagsQuery": "spring_batch_job_seconds_max", 867 | "type": "query", 868 | "useTags": false 869 | } 870 | ] 871 | }, 872 | "time": { 873 | "from": "now-15m", 874 | "to": "now" 875 | }, 876 | "timepicker": { 877 | "refresh_intervals": [ 878 | "5s", 879 | "10s", 880 | "30s", 881 | "1m", 882 | "5m", 883 | "15m", 884 | "30m", 885 | "1h", 886 | "2h", 887 | "1d" 888 | ], 889 | "time_options": [ 890 | "5m", 891 | "15m", 892 | "1h", 893 | "6h", 894 | "12h", 895 | "24h", 896 | "2d", 897 | "7d", 898 | "30d" 899 | ] 900 | }, 901 | "timezone": "", 902 | "title": "Tasks", 903 | "uid": "scdf-tasks", 904 | "version": 4 905 | } -------------------------------------------------------------------------------- /grafana/spring-boot-hikaricp-jdbc_rev5.json: -------------------------------------------------------------------------------- 1 | { 2 | "__inputs": [ 3 | { 4 | "name": "DS_PROMETHEUS", 5 | "label": "Prometheus", 6 | "description": "", 7 | "type": "datasource", 8 | "pluginId": "prometheus", 9 | "pluginName": "Prometheus" 10 | } 11 | ], 12 | "__requires": [ 13 | { 14 | "type": "grafana", 15 | "id": "grafana", 16 | "name": "Grafana", 17 | "version": "6.1.4" 18 | }, 19 | { 20 | "type": "panel", 21 | "id": "graph", 22 | "name": "Graph", 23 | "version": "" 24 | }, 25 | { 26 | "type": "datasource", 27 | "id": "prometheus", 28 | "name": "Prometheus", 29 | "version": "1.0.0" 30 | }, 31 | { 32 | "type": "panel", 33 | "id": "singlestat", 34 | "name": "Singlestat", 35 | "version": "" 36 | } 37 | ], 38 | "annotations": { 39 | "list": [ 40 | { 41 | "builtIn": 1, 42 | "datasource": "-- Grafana --", 43 | "enable": true, 44 | "hide": true, 45 | "iconColor": "rgba(0, 211, 255, 1)", 46 | "name": "Annotations & Alerts", 47 | "type": "dashboard" 48 | }, 49 | { 50 | "datasource": "${DS_PROMETHEUS}", 51 | "enable": true, 52 | "expr": "resets(process_uptime_seconds{application=\"$application\", region=\"$region\", instance=\"$instance\"}[1m]) > 0", 53 | "hide": false, 54 | "iconColor": "rgba(255, 96, 96, 1)", 55 | "limit": 100, 56 | "name": "Restart Detection", 57 | "showIn": 0, 58 | "step": "1m", 59 | "tagKeys": "restart-tag", 60 | "tags": [], 61 | "textFormat": "uptime reset", 62 | "titleFormat": "Restart", 63 | "type": "tags" 64 | } 65 | ] 66 | }, 67 | "description": "HikariCP & JDBC Dashboard (Micrometer.io)", 68 | "editable": true, 69 | "gnetId": 6083, 70 | "graphTooltip": 1, 71 | "id": null, 72 | "iteration": 1556302170069, 73 | "links": [], 74 | "panels": [ 75 | { 76 | "collapsed": false, 77 | "gridPos": { 78 | "h": 1, 79 | "w": 24, 80 | "x": 0, 81 | "y": 0 82 | }, 83 | "id": 4, 84 | "panels": [], 85 | "title": "JDBC Connections", 86 | "type": "row" 87 | }, 88 | { 89 | "cacheTimeout": null, 90 | "colorBackground": false, 91 | "colorValue": false, 92 | "colors": [ 93 | "#299c46", 94 | "rgba(237, 129, 40, 0.89)", 95 | "#d44a3a" 96 | ], 97 | "datasource": "${DS_PROMETHEUS}", 98 | "format": "none", 99 | "gauge": { 100 | "maxValue": 100, 101 | "minValue": 0, 102 | "show": false, 103 | "thresholdLabels": false, 104 | "thresholdMarkers": true 105 | }, 106 | "gridPos": { 107 | "h": 3, 108 | "w": 8, 109 | "x": 0, 110 | "y": 1 111 | }, 112 | "id": 6, 113 | "interval": null, 114 | "links": [], 115 | "mappingType": 1, 116 | "mappingTypes": [ 117 | { 118 | "name": "value to text", 119 | "value": 1 120 | }, 121 | { 122 | "name": "range to text", 123 | "value": 2 124 | } 125 | ], 126 | "maxDataPoints": 100, 127 | "nullPointMode": "connected", 128 | "nullText": null, 129 | "postfix": "", 130 | "postfixFontSize": "50%", 131 | "prefix": "", 132 | "prefixFontSize": "50%", 133 | "rangeMaps": [ 134 | { 135 | "from": "null", 136 | "text": "N/A", 137 | "to": "null" 138 | } 139 | ], 140 | "sparkline": { 141 | "fillColor": "rgba(31, 118, 189, 0.18)", 142 | "full": false, 143 | "lineColor": "rgb(31, 120, 193)", 144 | "show": false 145 | }, 146 | "tableColumn": "", 147 | "targets": [ 148 | { 149 | "expr": "jdbc_connections_min{application=\"$application\", region=~\"$region\", instance=~\"$instance\", name=~\"$jdbc_connection_name\"}", 150 | "format": "time_series", 151 | "intervalFactor": 1, 152 | "refId": "A" 153 | } 154 | ], 155 | "thresholds": "", 156 | "title": "Min", 157 | "type": "singlestat", 158 | "valueFontSize": "80%", 159 | "valueMaps": [ 160 | { 161 | "op": "=", 162 | "text": "N/A", 163 | "value": "null" 164 | } 165 | ], 166 | "valueName": "current" 167 | }, 168 | { 169 | "cacheTimeout": null, 170 | "colorBackground": false, 171 | "colorValue": false, 172 | "colors": [ 173 | "#299c46", 174 | "rgba(237, 129, 40, 0.89)", 175 | "#d44a3a" 176 | ], 177 | "datasource": "${DS_PROMETHEUS}", 178 | "format": "none", 179 | "gauge": { 180 | "maxValue": 100, 181 | "minValue": 0, 182 | "show": false, 183 | "thresholdLabels": false, 184 | "thresholdMarkers": true 185 | }, 186 | "gridPos": { 187 | "h": 3, 188 | "w": 8, 189 | "x": 8, 190 | "y": 1 191 | }, 192 | "id": 7, 193 | "interval": null, 194 | "links": [], 195 | "mappingType": 1, 196 | "mappingTypes": [ 197 | { 198 | "name": "value to text", 199 | "value": 1 200 | }, 201 | { 202 | "name": "range to text", 203 | "value": 2 204 | } 205 | ], 206 | "maxDataPoints": 100, 207 | "nullPointMode": "connected", 208 | "nullText": null, 209 | "postfix": "", 210 | "postfixFontSize": "50%", 211 | "prefix": "", 212 | "prefixFontSize": "50%", 213 | "rangeMaps": [ 214 | { 215 | "from": "null", 216 | "text": "N/A", 217 | "to": "null" 218 | } 219 | ], 220 | "sparkline": { 221 | "fillColor": "#C0D8FF", 222 | "full": false, 223 | "lineColor": "rgb(31, 120, 193)", 224 | "show": true 225 | }, 226 | "tableColumn": "", 227 | "targets": [ 228 | { 229 | "expr": "jdbc_connections_active{application=\"$application\", region=~\"$region\", instance=~\"$instance\", name=~\"$jdbc_connection_name\"}", 230 | "format": "time_series", 231 | "intervalFactor": 1, 232 | "refId": "A" 233 | } 234 | ], 235 | "thresholds": "", 236 | "title": "Active", 237 | "type": "singlestat", 238 | "valueFontSize": "80%", 239 | "valueMaps": [ 240 | { 241 | "op": "=", 242 | "text": "N/A", 243 | "value": "null" 244 | } 245 | ], 246 | "valueName": "current" 247 | }, 248 | { 249 | "cacheTimeout": null, 250 | "colorBackground": false, 251 | "colorValue": false, 252 | "colors": [ 253 | "#299c46", 254 | "rgba(237, 129, 40, 0.89)", 255 | "#d44a3a" 256 | ], 257 | "datasource": "${DS_PROMETHEUS}", 258 | "format": "none", 259 | "gauge": { 260 | "maxValue": 100, 261 | "minValue": 0, 262 | "show": false, 263 | "thresholdLabels": false, 264 | "thresholdMarkers": true 265 | }, 266 | "gridPos": { 267 | "h": 3, 268 | "w": 8, 269 | "x": 16, 270 | "y": 1 271 | }, 272 | "id": 8, 273 | "interval": null, 274 | "links": [], 275 | "mappingType": 1, 276 | "mappingTypes": [ 277 | { 278 | "name": "value to text", 279 | "value": 1 280 | }, 281 | { 282 | "name": "range to text", 283 | "value": 2 284 | } 285 | ], 286 | "maxDataPoints": 100, 287 | "nullPointMode": "connected", 288 | "nullText": null, 289 | "postfix": "", 290 | "postfixFontSize": "50%", 291 | "prefix": "", 292 | "prefixFontSize": "50%", 293 | "rangeMaps": [ 294 | { 295 | "from": "null", 296 | "text": "N/A", 297 | "to": "null" 298 | } 299 | ], 300 | "sparkline": { 301 | "fillColor": "rgba(31, 118, 189, 0.18)", 302 | "full": false, 303 | "lineColor": "rgb(31, 120, 193)", 304 | "show": false 305 | }, 306 | "tableColumn": "", 307 | "targets": [ 308 | { 309 | "expr": "jdbc_connections_max{application=\"$application\", region=~\"$region\", instance=~\"$instance\", name=~\"$jdbc_connection_name\"}", 310 | "format": "time_series", 311 | "intervalFactor": 1, 312 | "refId": "A" 313 | } 314 | ], 315 | "thresholds": "", 316 | "title": "Max", 317 | "type": "singlestat", 318 | "valueFontSize": "80%", 319 | "valueMaps": [ 320 | { 321 | "op": "=", 322 | "text": "N/A", 323 | "value": "null" 324 | } 325 | ], 326 | "valueName": "current" 327 | }, 328 | { 329 | "collapsed": false, 330 | "gridPos": { 331 | "h": 1, 332 | "w": 24, 333 | "x": 0, 334 | "y": 4 335 | }, 336 | "id": 2, 337 | "panels": [], 338 | "title": "Hikari Connections", 339 | "type": "row" 340 | }, 341 | { 342 | "aliasColors": {}, 343 | "bars": false, 344 | "dashLength": 10, 345 | "dashes": false, 346 | "datasource": "${DS_PROMETHEUS}", 347 | "fill": 1, 348 | "gridPos": { 349 | "h": 12, 350 | "w": 21, 351 | "x": 0, 352 | "y": 5 353 | }, 354 | "id": 10, 355 | "legend": { 356 | "alignAsTable": true, 357 | "avg": false, 358 | "current": false, 359 | "max": true, 360 | "min": true, 361 | "show": true, 362 | "total": false, 363 | "values": true 364 | }, 365 | "lines": true, 366 | "linewidth": 1, 367 | "links": [], 368 | "nullPointMode": "null", 369 | "percentage": false, 370 | "pointradius": 5, 371 | "points": false, 372 | "renderer": "flot", 373 | "seriesOverrides": [], 374 | "spaceLength": 10, 375 | "stack": false, 376 | "steppedLine": false, 377 | "targets": [ 378 | { 379 | "expr": "hikaricp_connections_active{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}", 380 | "format": "time_series", 381 | "intervalFactor": 1, 382 | "legendFormat": "Active connections", 383 | "refId": "C" 384 | }, 385 | { 386 | "expr": "hikaricp_connections_idle{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}", 387 | "format": "time_series", 388 | "intervalFactor": 1, 389 | "legendFormat": "Idle connections", 390 | "refId": "A" 391 | }, 392 | { 393 | "expr": "hikaricp_connections_pending{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}", 394 | "format": "time_series", 395 | "intervalFactor": 1, 396 | "legendFormat": "Pending threads", 397 | "refId": "B" 398 | } 399 | ], 400 | "thresholds": [], 401 | "timeFrom": null, 402 | "timeRegions": [], 403 | "timeShift": null, 404 | "title": "Connections", 405 | "tooltip": { 406 | "shared": true, 407 | "sort": 0, 408 | "value_type": "individual" 409 | }, 410 | "type": "graph", 411 | "xaxis": { 412 | "buckets": null, 413 | "mode": "time", 414 | "name": null, 415 | "show": true, 416 | "values": [] 417 | }, 418 | "yaxes": [ 419 | { 420 | "format": "short", 421 | "label": null, 422 | "logBase": 1, 423 | "max": null, 424 | "min": "0", 425 | "show": true 426 | }, 427 | { 428 | "format": "short", 429 | "label": null, 430 | "logBase": 1, 431 | "max": null, 432 | "min": null, 433 | "show": false 434 | } 435 | ], 436 | "yaxis": { 437 | "align": false, 438 | "alignLevel": null 439 | } 440 | }, 441 | { 442 | "cacheTimeout": null, 443 | "colorBackground": false, 444 | "colorValue": false, 445 | "colors": [ 446 | "#299c46", 447 | "rgba(237, 129, 40, 0.89)", 448 | "#d44a3a" 449 | ], 450 | "datasource": "${DS_PROMETHEUS}", 451 | "format": "none", 452 | "gauge": { 453 | "maxValue": 100, 454 | "minValue": 0, 455 | "show": false, 456 | "thresholdLabels": false, 457 | "thresholdMarkers": true 458 | }, 459 | "gridPos": { 460 | "h": 4, 461 | "w": 3, 462 | "x": 21, 463 | "y": 5 464 | }, 465 | "id": 12, 466 | "interval": null, 467 | "links": [], 468 | "mappingType": 1, 469 | "mappingTypes": [ 470 | { 471 | "name": "value to text", 472 | "value": 1 473 | }, 474 | { 475 | "name": "range to text", 476 | "value": 2 477 | } 478 | ], 479 | "maxDataPoints": 100, 480 | "nullPointMode": "connected", 481 | "nullText": null, 482 | "postfix": "", 483 | "postfixFontSize": "50%", 484 | "prefix": "", 485 | "prefixFontSize": "50%", 486 | "rangeMaps": [ 487 | { 488 | "from": "null", 489 | "text": "N/A", 490 | "to": "null" 491 | } 492 | ], 493 | "sparkline": { 494 | "fillColor": "rgba(31, 118, 189, 0.18)", 495 | "full": false, 496 | "lineColor": "rgb(31, 120, 193)", 497 | "show": false 498 | }, 499 | "tableColumn": "", 500 | "targets": [ 501 | { 502 | "expr": "hikaricp_connections_max{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}", 503 | "format": "time_series", 504 | "intervalFactor": 1, 505 | "refId": "A" 506 | } 507 | ], 508 | "thresholds": "", 509 | "title": "Max", 510 | "type": "singlestat", 511 | "valueFontSize": "80%", 512 | "valueMaps": [ 513 | { 514 | "op": "=", 515 | "text": "N/A", 516 | "value": "null" 517 | } 518 | ], 519 | "valueName": "current" 520 | }, 521 | { 522 | "cacheTimeout": null, 523 | "colorBackground": false, 524 | "colorValue": false, 525 | "colors": [ 526 | "#299c46", 527 | "rgba(237, 129, 40, 0.89)", 528 | "#d44a3a" 529 | ], 530 | "datasource": "${DS_PROMETHEUS}", 531 | "format": "none", 532 | "gauge": { 533 | "maxValue": 100, 534 | "minValue": 0, 535 | "show": false, 536 | "thresholdLabels": false, 537 | "thresholdMarkers": true 538 | }, 539 | "gridPos": { 540 | "h": 4, 541 | "w": 3, 542 | "x": 21, 543 | "y": 9 544 | }, 545 | "id": 13, 546 | "interval": null, 547 | "links": [], 548 | "mappingType": 1, 549 | "mappingTypes": [ 550 | { 551 | "name": "value to text", 552 | "value": 1 553 | }, 554 | { 555 | "name": "range to text", 556 | "value": 2 557 | } 558 | ], 559 | "maxDataPoints": 100, 560 | "nullPointMode": "connected", 561 | "nullText": null, 562 | "postfix": "", 563 | "postfixFontSize": "50%", 564 | "prefix": "", 565 | "prefixFontSize": "50%", 566 | "rangeMaps": [ 567 | { 568 | "from": "null", 569 | "text": "N/A", 570 | "to": "null" 571 | } 572 | ], 573 | "sparkline": { 574 | "fillColor": "rgba(31, 118, 189, 0.18)", 575 | "full": false, 576 | "lineColor": "rgb(31, 120, 193)", 577 | "show": false 578 | }, 579 | "tableColumn": "", 580 | "targets": [ 581 | { 582 | "expr": "hikaricp_connections_min{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}", 583 | "format": "time_series", 584 | "intervalFactor": 1, 585 | "refId": "A" 586 | } 587 | ], 588 | "thresholds": "", 589 | "title": "Min", 590 | "type": "singlestat", 591 | "valueFontSize": "80%", 592 | "valueMaps": [ 593 | { 594 | "op": "=", 595 | "text": "N/A", 596 | "value": "null" 597 | } 598 | ], 599 | "valueName": "current" 600 | }, 601 | { 602 | "cacheTimeout": null, 603 | "colorBackground": false, 604 | "colorValue": false, 605 | "colors": [ 606 | "#299c46", 607 | "rgba(237, 129, 40, 0.89)", 608 | "#d44a3a" 609 | ], 610 | "datasource": "${DS_PROMETHEUS}", 611 | "format": "none", 612 | "gauge": { 613 | "maxValue": 100, 614 | "minValue": 0, 615 | "show": false, 616 | "thresholdLabels": false, 617 | "thresholdMarkers": true 618 | }, 619 | "gridPos": { 620 | "h": 4, 621 | "w": 3, 622 | "x": 21, 623 | "y": 13 624 | }, 625 | "id": 17, 626 | "interval": null, 627 | "links": [], 628 | "mappingType": 1, 629 | "mappingTypes": [ 630 | { 631 | "name": "value to text", 632 | "value": 1 633 | }, 634 | { 635 | "name": "range to text", 636 | "value": 2 637 | } 638 | ], 639 | "maxDataPoints": 100, 640 | "nullPointMode": "connected", 641 | "nullText": null, 642 | "postfix": "", 643 | "postfixFontSize": "50%", 644 | "prefix": "", 645 | "prefixFontSize": "50%", 646 | "rangeMaps": [ 647 | { 648 | "from": "null", 649 | "text": "N/A", 650 | "to": "null" 651 | } 652 | ], 653 | "sparkline": { 654 | "fillColor": "rgba(31, 118, 189, 0.18)", 655 | "full": false, 656 | "lineColor": "rgb(31, 120, 193)", 657 | "show": false 658 | }, 659 | "tableColumn": "", 660 | "targets": [ 661 | { 662 | "expr": "hikaricp_connections_timeout_total{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}", 663 | "format": "time_series", 664 | "intervalFactor": 1, 665 | "legendFormat": "", 666 | "refId": "A" 667 | } 668 | ], 669 | "thresholds": "", 670 | "title": "Total Timeout", 671 | "type": "singlestat", 672 | "valueFontSize": "80%", 673 | "valueMaps": [ 674 | { 675 | "op": "=", 676 | "text": "N/A", 677 | "value": "null" 678 | } 679 | ], 680 | "valueName": "current" 681 | }, 682 | { 683 | "aliasColors": {}, 684 | "bars": false, 685 | "dashLength": 10, 686 | "dashes": false, 687 | "datasource": "${DS_PROMETHEUS}", 688 | "fill": 1, 689 | "gridPos": { 690 | "h": 9, 691 | "w": 24, 692 | "x": 0, 693 | "y": 17 694 | }, 695 | "id": 16, 696 | "legend": { 697 | "alignAsTable": true, 698 | "avg": false, 699 | "current": false, 700 | "hideEmpty": false, 701 | "hideZero": false, 702 | "max": true, 703 | "min": true, 704 | "rightSide": false, 705 | "show": true, 706 | "total": false, 707 | "values": true 708 | }, 709 | "lines": true, 710 | "linewidth": 1, 711 | "links": [], 712 | "nullPointMode": "null", 713 | "percentage": false, 714 | "pointradius": 5, 715 | "points": false, 716 | "renderer": "flot", 717 | "seriesOverrides": [], 718 | "spaceLength": 10, 719 | "stack": false, 720 | "steppedLine": false, 721 | "targets": [ 722 | { 723 | "expr": "irate(hikaricp_connections_usage_seconds_sum{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}[5m]) / irate(hikaricp_connections_usage_seconds_count{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}[5m])", 724 | "format": "time_series", 725 | "intervalFactor": 1, 726 | "legendFormat": "Usage time", 727 | "refId": "C" 728 | }, 729 | { 730 | "expr": "irate(hikaricp_connections_creation_seconds_sum{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}[5m]) / irate(hikaricp_connections_creation_seconds_count{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}[5m])", 731 | "format": "time_series", 732 | "intervalFactor": 1, 733 | "legendFormat": "Creation time", 734 | "refId": "A" 735 | }, 736 | { 737 | "expr": "irate(hikaricp_connections_acquire_seconds_sum{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}[5m]) / irate(hikaricp_connections_acquire_seconds_count{application=\"$application\", region=~\"$region\", instance=~\"$instance\", pool=~\"$hikaricp_pool_name\"}[5m])", 738 | "format": "time_series", 739 | "intervalFactor": 1, 740 | "legendFormat": "Acquire time", 741 | "refId": "B" 742 | } 743 | ], 744 | "thresholds": [], 745 | "timeFrom": null, 746 | "timeRegions": [], 747 | "timeShift": null, 748 | "title": "Connections Time", 749 | "tooltip": { 750 | "shared": true, 751 | "sort": 0, 752 | "value_type": "individual" 753 | }, 754 | "type": "graph", 755 | "xaxis": { 756 | "buckets": null, 757 | "mode": "time", 758 | "name": null, 759 | "show": true, 760 | "values": [] 761 | }, 762 | "yaxes": [ 763 | { 764 | "format": "dtdurations", 765 | "label": null, 766 | "logBase": 1, 767 | "max": null, 768 | "min": "0", 769 | "show": true 770 | }, 771 | { 772 | "format": "short", 773 | "label": "", 774 | "logBase": 1, 775 | "max": null, 776 | "min": null, 777 | "show": false 778 | } 779 | ], 780 | "yaxis": { 781 | "align": false, 782 | "alignLevel": null 783 | } 784 | } 785 | ], 786 | "refresh": "5s", 787 | "schemaVersion": 18, 788 | "style": "dark", 789 | "tags": [ 790 | "prometheus", 791 | "hikaricp", 792 | "micrometer", 793 | "spring boot", 794 | "jdbc" 795 | ], 796 | "templating": { 797 | "list": [ 798 | { 799 | "allValue": null, 800 | "current": {}, 801 | "datasource": "${DS_PROMETHEUS}", 802 | "definition": "", 803 | "hide": 0, 804 | "includeAll": false, 805 | "label": "Application", 806 | "multi": false, 807 | "name": "application", 808 | "options": [], 809 | "query": "label_values(application)", 810 | "refresh": 2, 811 | "regex": "", 812 | "skipUrlSync": false, 813 | "sort": 0, 814 | "tagValuesQuery": "", 815 | "tags": [], 816 | "tagsQuery": "", 817 | "type": "query", 818 | "useTags": false 819 | }, 820 | { 821 | "allValue": null, 822 | "current": {}, 823 | "datasource": "${DS_PROMETHEUS}", 824 | "definition": "", 825 | "hide": 0, 826 | "includeAll": true, 827 | "label": "Region", 828 | "multi": false, 829 | "name": "region", 830 | "options": [], 831 | "query": "label_values(jdbc_connections_min{application=\"$application\"}, region)", 832 | "refresh": 1, 833 | "regex": "", 834 | "skipUrlSync": false, 835 | "sort": 1, 836 | "tagValuesQuery": "", 837 | "tags": [], 838 | "tagsQuery": "", 839 | "type": "query", 840 | "useTags": false 841 | }, 842 | { 843 | "allValue": null, 844 | "current": {}, 845 | "datasource": "${DS_PROMETHEUS}", 846 | "definition": "label_values(jdbc_connections_min{application=\"$application\", region=~\"$region\"}, instance)", 847 | "hide": 0, 848 | "includeAll": true, 849 | "label": "Instance", 850 | "multi": false, 851 | "name": "instance", 852 | "options": [], 853 | "query": "label_values(jdbc_connections_min{application=\"$application\", region=~\"$region\"}, instance)", 854 | "refresh": 2, 855 | "regex": "", 856 | "skipUrlSync": false, 857 | "sort": 1, 858 | "tagValuesQuery": "", 859 | "tags": [], 860 | "tagsQuery": "", 861 | "type": "query", 862 | "useTags": false 863 | }, 864 | { 865 | "allValue": null, 866 | "current": {}, 867 | "datasource": "${DS_PROMETHEUS}", 868 | "definition": "label_values(jdbc_connections_min{application=\"$application\", region=~\"$region\", instance=~\"$instance\"}, name)", 869 | "hide": 0, 870 | "includeAll": false, 871 | "label": "JDBC Connection Name", 872 | "multi": false, 873 | "name": "jdbc_connection_name", 874 | "options": [], 875 | "query": "label_values(jdbc_connections_min{application=\"$application\", region=~\"$region\", instance=~\"$instance\"}, name)", 876 | "refresh": 2, 877 | "regex": "", 878 | "skipUrlSync": false, 879 | "sort": 1, 880 | "tagValuesQuery": "", 881 | "tags": [], 882 | "tagsQuery": "", 883 | "type": "query", 884 | "useTags": false 885 | }, 886 | { 887 | "allValue": null, 888 | "current": {}, 889 | "datasource": "${DS_PROMETHEUS}", 890 | "definition": "label_values(hikaricp_connections_min{application=\"$application\", region=~\"$region\", instance=~\"$instance\"}, pool)", 891 | "hide": 0, 892 | "includeAll": false, 893 | "label": "Hikari Pool Name", 894 | "multi": false, 895 | "name": "hikaricp_pool_name", 896 | "options": [], 897 | "query": "label_values(hikaricp_connections_min{application=\"$application\", region=~\"$region\", instance=~\"$instance\"}, pool)", 898 | "refresh": 2, 899 | "regex": "", 900 | "skipUrlSync": false, 901 | "sort": 1, 902 | "tagValuesQuery": "", 903 | "tags": [], 904 | "tagsQuery": "", 905 | "type": "query", 906 | "useTags": false 907 | } 908 | ] 909 | }, 910 | "time": { 911 | "from": "now-30m", 912 | "to": "now" 913 | }, 914 | "timepicker": { 915 | "refresh_intervals": [ 916 | "5s", 917 | "10s", 918 | "30s", 919 | "1m", 920 | "5m", 921 | "15m", 922 | "30m", 923 | "1h", 924 | "2h", 925 | "1d" 926 | ], 927 | "time_options": [ 928 | "5m", 929 | "15m", 930 | "1h", 931 | "6h", 932 | "12h", 933 | "24h", 934 | "2d", 935 | "7d", 936 | "30d" 937 | ] 938 | }, 939 | "timezone": "", 940 | "title": "Spring Boot HikariCP / JDBC", 941 | "uid": "wdV6wx7iz", 942 | "version": 8 943 | } -------------------------------------------------------------------------------- /grafana/spring-grafana-dashboard.json: -------------------------------------------------------------------------------- 1 | { 2 | "annotations": { 3 | "list": [{ 4 | "builtIn": 1, 5 | "datasource": "-- Grafana --", 6 | "enable": true, 7 | "hide": true, 8 | "iconColor": "rgba(0, 211, 255, 1)", 9 | "limit": 100, 10 | "name": "Annotations & Alerts", 11 | "showIn": 0, 12 | "type": "dashboard" 13 | }] 14 | }, 15 | "description": "Dashboard for Spring Batch applications instrumented with Micrometer", 16 | "editable": true, 17 | "gnetId": 4701, 18 | "graphTooltip": 1, 19 | "id": 5, 20 | "links": [], 21 | "panels": [{ 22 | "collapsed": false, 23 | "gridPos": { 24 | "h": 1, 25 | "w": 24, 26 | "x": 0, 27 | "y": 0 28 | }, 29 | "id": 132, 30 | "panels": [], 31 | "repeat": null, 32 | "title": "Spring Batch Metrics", 33 | "type": "row" 34 | }, 35 | { 36 | "aliasColors": {}, 37 | "bars": false, 38 | "dashLength": 10, 39 | "dashes": false, 40 | "datasource": "ScdfPrometheus", 41 | "editable": true, 42 | "error": false, 43 | "fill": 1, 44 | "fillGradient": 0, 45 | "grid": { 46 | "leftLogBase": 1, 47 | "leftMax": null, 48 | "leftMin": null, 49 | "rightLogBase": 1, 50 | "rightMax": null, 51 | "rightMin": null 52 | }, 53 | "gridPos": { 54 | "h": 7, 55 | "w": 8, 56 | "x": 0, 57 | "y": 1 58 | }, 59 | "id": 37, 60 | "legend": { 61 | "alignAsTable": false, 62 | "avg": false, 63 | "current": false, 64 | "hideEmpty": false, 65 | "hideZero": false, 66 | "max": false, 67 | "min": false, 68 | "rightSide": false, 69 | "show": true, 70 | "total": false, 71 | "values": false 72 | }, 73 | "lines": true, 74 | "linewidth": 1, 75 | "links": [], 76 | "nullPointMode": "null", 77 | "options": { 78 | "dataLinks": [] 79 | }, 80 | "paceLength": 10, 81 | "percentage": false, 82 | "pointradius": 5, 83 | "points": false, 84 | "renderer": "flot", 85 | "seriesOverrides": [], 86 | "spaceLength": 10, 87 | "stack": false, 88 | "steppedLine": false, 89 | "targets": [{ 90 | "expr": "spring_batch_job_seconds_max", 91 | "format": "time_series", 92 | "interval": "", 93 | "intervalFactor": 1, 94 | "legendFormat": "{{name}} {{status}}", 95 | "metric": "", 96 | "refId": "A", 97 | "step": 1200 98 | }], 99 | "thresholds": [], 100 | "timeFrom": null, 101 | "timeRegions": [], 102 | "timeShift": null, 103 | "title": "Job duration", 104 | "tooltip": { 105 | "msResolution": false, 106 | "shared": true, 107 | "sort": 0, 108 | "value_type": "cumulative" 109 | }, 110 | "type": "graph", 111 | "x-axis": true, 112 | "xaxis": { 113 | "buckets": null, 114 | "mode": "time", 115 | "name": null, 116 | "show": true, 117 | "values": [] 118 | }, 119 | "y-axis": true, 120 | "y_formats": [ 121 | "short", 122 | "short" 123 | ], 124 | "yaxes": [{ 125 | "format": "s", 126 | "label": "", 127 | "logBase": 1, 128 | "max": null, 129 | "min": 0, 130 | "show": true 131 | }, 132 | { 133 | "format": "short", 134 | "label": "", 135 | "logBase": 1, 136 | "max": null, 137 | "min": null, 138 | "show": true 139 | } 140 | ], 141 | "yaxis": { 142 | "align": false, 143 | "alignLevel": null 144 | } 145 | }, 146 | { 147 | "aliasColors": {}, 148 | "bars": false, 149 | "dashLength": 10, 150 | "dashes": false, 151 | "datasource": "ScdfPrometheus", 152 | "editable": true, 153 | "error": false, 154 | "fill": 1, 155 | "fillGradient": 0, 156 | "grid": { 157 | "leftLogBase": 1, 158 | "leftMax": null, 159 | "leftMin": null, 160 | "rightLogBase": 1, 161 | "rightMax": null, 162 | "rightMin": null 163 | }, 164 | "gridPos": { 165 | "h": 7, 166 | "w": 8, 167 | "x": 8, 168 | "y": 1 169 | }, 170 | "id": 38, 171 | "legend": { 172 | "avg": false, 173 | "current": false, 174 | "max": false, 175 | "min": false, 176 | "show": true, 177 | "total": false, 178 | "values": false 179 | }, 180 | "lines": true, 181 | "linewidth": 1, 182 | "links": [], 183 | "nullPointMode": "null", 184 | "options": { 185 | "dataLinks": [] 186 | }, 187 | "paceLength": 10, 188 | "percentage": false, 189 | "pointradius": 5, 190 | "points": false, 191 | "renderer": "flot", 192 | "seriesOverrides": [], 193 | "spaceLength": 10, 194 | "stack": false, 195 | "steppedLine": false, 196 | "targets": [{ 197 | "expr": "rate(spring_batch_job_seconds_count[1m]) * 60", 198 | "format": "time_series", 199 | "hide": false, 200 | "interval": "", 201 | "intervalFactor": 2, 202 | "legendFormat": "{{name}} {{status}}", 203 | "metric": "", 204 | "refId": "A", 205 | "step": 1200 206 | }], 207 | "thresholds": [], 208 | "timeFrom": null, 209 | "timeRegions": [], 210 | "timeShift": null, 211 | "title": "Job execution rate", 212 | "tooltip": { 213 | "msResolution": false, 214 | "shared": true, 215 | "sort": 0, 216 | "value_type": "cumulative" 217 | }, 218 | "type": "graph", 219 | "x-axis": true, 220 | "xaxis": { 221 | "buckets": null, 222 | "mode": "time", 223 | "name": null, 224 | "show": true, 225 | "values": [] 226 | }, 227 | "y-axis": true, 228 | "y_formats": [ 229 | "ops", 230 | "short" 231 | ], 232 | "yaxes": [{ 233 | "decimals": null, 234 | "format": "opm", 235 | "label": "", 236 | "logBase": 1, 237 | "max": null, 238 | "min": null, 239 | "show": true 240 | }, 241 | { 242 | "format": "short", 243 | "label": null, 244 | "logBase": 1, 245 | "max": null, 246 | "min": null, 247 | "show": true 248 | } 249 | ], 250 | "yaxis": { 251 | "align": false, 252 | "alignLevel": null 253 | } 254 | }, 255 | { 256 | "aliasColors": {}, 257 | "bars": false, 258 | "dashLength": 10, 259 | "dashes": false, 260 | "datasource": "ScdfPrometheus", 261 | "fill": 1, 262 | "fillGradient": 0, 263 | "gridPos": { 264 | "h": 7, 265 | "w": 8, 266 | "x": 16, 267 | "y": 1 268 | }, 269 | "id": 138, 270 | "legend": { 271 | "avg": false, 272 | "current": false, 273 | "max": false, 274 | "min": false, 275 | "show": true, 276 | "total": false, 277 | "values": false 278 | }, 279 | "lines": true, 280 | "linewidth": 1, 281 | "links": [], 282 | "nullPointMode": "null", 283 | "options": { 284 | "dataLinks": [] 285 | }, 286 | "paceLength": 10, 287 | "percentage": false, 288 | "pointradius": 5, 289 | "points": false, 290 | "renderer": "flot", 291 | "seriesOverrides": [], 292 | "spaceLength": 10, 293 | "stack": false, 294 | "steppedLine": false, 295 | "targets": [{ 296 | "expr": "(sum(rate(spring_batch_job_seconds_count{status=\"FAILED\"}[5m])) by (name, status)) / (sum(rate(spring_batch_job_seconds_count[5m])) by (name, status))", 297 | "format": "time_series", 298 | "hide": false, 299 | "instant": false, 300 | "intervalFactor": 1, 301 | "legendFormat": "{{name}} {{status}}", 302 | "refId": "A" 303 | }], 304 | "thresholds": [], 305 | "timeFrom": null, 306 | "timeRegions": [], 307 | "timeShift": null, 308 | "title": "Job failure rate", 309 | "tooltip": { 310 | "shared": true, 311 | "sort": 0, 312 | "value_type": "individual" 313 | }, 314 | "type": "graph", 315 | "xaxis": { 316 | "buckets": null, 317 | "mode": "time", 318 | "name": null, 319 | "show": true, 320 | "values": [] 321 | }, 322 | "yaxes": [{ 323 | "format": "percentunit", 324 | "label": null, 325 | "logBase": 1, 326 | "max": null, 327 | "min": null, 328 | "show": true 329 | }, 330 | { 331 | "format": "short", 332 | "label": null, 333 | "logBase": 1, 334 | "max": null, 335 | "min": null, 336 | "show": true 337 | } 338 | ], 339 | "yaxis": { 340 | "align": false, 341 | "alignLevel": null 342 | } 343 | }, 344 | { 345 | "aliasColors": {}, 346 | "bars": false, 347 | "dashLength": 10, 348 | "dashes": false, 349 | "datasource": "ScdfPrometheus", 350 | "fill": 1, 351 | "fillGradient": 0, 352 | "gridPos": { 353 | "h": 9, 354 | "w": 12, 355 | "x": 0, 356 | "y": 8 357 | }, 358 | "id": 141, 359 | "legend": { 360 | "avg": false, 361 | "current": false, 362 | "max": false, 363 | "min": false, 364 | "show": true, 365 | "total": false, 366 | "values": false 367 | }, 368 | "lines": true, 369 | "linewidth": 1, 370 | "links": [], 371 | "nullPointMode": "null", 372 | "options": { 373 | "dataLinks": [] 374 | }, 375 | "paceLength": 10, 376 | "percentage": false, 377 | "pointradius": 5, 378 | "points": false, 379 | "renderer": "flot", 380 | "seriesOverrides": [{ 381 | "alias": "write success", 382 | "yaxis": 1 383 | }], 384 | "spaceLength": 10, 385 | "stack": false, 386 | "steppedLine": false, 387 | "targets": [{ 388 | "expr": "rate(spring_batch_item_read_seconds_count[1m])", 389 | "format": "time_series", 390 | "interval": "", 391 | "intervalFactor": 1, 392 | "legendFormat": "read {{status}}", 393 | "refId": "B" 394 | }], 395 | "thresholds": [], 396 | "timeFrom": null, 397 | "timeRegions": [], 398 | "timeShift": null, 399 | "title": "Item read throughput", 400 | "tooltip": { 401 | "shared": true, 402 | "sort": 0, 403 | "value_type": "individual" 404 | }, 405 | "type": "graph", 406 | "xaxis": { 407 | "buckets": null, 408 | "mode": "time", 409 | "name": null, 410 | "show": true, 411 | "values": [] 412 | }, 413 | "yaxes": [{ 414 | "format": "ops", 415 | "label": null, 416 | "logBase": 1, 417 | "max": null, 418 | "min": null, 419 | "show": true 420 | }, 421 | { 422 | "format": "ops", 423 | "label": null, 424 | "logBase": 1, 425 | "max": null, 426 | "min": null, 427 | "show": true 428 | } 429 | ], 430 | "yaxis": { 431 | "align": false, 432 | "alignLevel": null 433 | } 434 | }, 435 | { 436 | "aliasColors": {}, 437 | "bars": false, 438 | "dashLength": 10, 439 | "dashes": false, 440 | "datasource": "ScdfPrometheus", 441 | "fill": 1, 442 | "fillGradient": 0, 443 | "gridPos": { 444 | "h": 9, 445 | "w": 12, 446 | "x": 12, 447 | "y": 8 448 | }, 449 | "id": 140, 450 | "legend": { 451 | "avg": false, 452 | "current": false, 453 | "max": false, 454 | "min": false, 455 | "show": true, 456 | "total": false, 457 | "values": false 458 | }, 459 | "lines": true, 460 | "linewidth": 1, 461 | "links": [], 462 | "nullPointMode": "null", 463 | "options": { 464 | "dataLinks": [] 465 | }, 466 | "paceLength": 10, 467 | "percentage": false, 468 | "pointradius": 5, 469 | "points": false, 470 | "renderer": "flot", 471 | "seriesOverrides": [{ 472 | "alias": "write success", 473 | "yaxis": 1 474 | }], 475 | "spaceLength": 10, 476 | "stack": false, 477 | "steppedLine": false, 478 | "targets": [{ 479 | "expr": "rate(spring_batch_chunk_write_seconds_count[1m])", 480 | "format": "time_series", 481 | "interval": "", 482 | "intervalFactor": 1, 483 | "legendFormat": "write {{status}}", 484 | "refId": "B" 485 | }], 486 | "thresholds": [], 487 | "timeFrom": null, 488 | "timeRegions": [], 489 | "timeShift": null, 490 | "title": "Item write throughput", 491 | "tooltip": { 492 | "shared": true, 493 | "sort": 0, 494 | "value_type": "individual" 495 | }, 496 | "type": "graph", 497 | "xaxis": { 498 | "buckets": null, 499 | "mode": "time", 500 | "name": null, 501 | "show": true, 502 | "values": [] 503 | }, 504 | "yaxes": [{ 505 | "format": "ops", 506 | "label": null, 507 | "logBase": 1, 508 | "max": null, 509 | "min": null, 510 | "show": true 511 | }, 512 | { 513 | "format": "ops", 514 | "label": null, 515 | "logBase": 1, 516 | "max": null, 517 | "min": null, 518 | "show": true 519 | } 520 | ], 521 | "yaxis": { 522 | "align": false, 523 | "alignLevel": null 524 | } 525 | } 526 | ], 527 | "refresh": "5s", 528 | "schemaVersion": 19, 529 | "style": "dark", 530 | "tags": [], 531 | "templating": { 532 | "list": [] 533 | }, 534 | "time": { 535 | "from": "now-5m", 536 | "to": "now" 537 | }, 538 | "timepicker": { 539 | "now": true, 540 | "refresh_intervals": [ 541 | "5s", 542 | "10s", 543 | "30s", 544 | "1m", 545 | "5m", 546 | "15m", 547 | "30m", 548 | "1h", 549 | "2h", 550 | "1d" 551 | ], 552 | "time_options": [ 553 | "5m", 554 | "15m", 555 | "1h", 556 | "6h", 557 | "12h", 558 | "24h", 559 | "2d", 560 | "7d", 561 | "30d" 562 | ] 563 | }, 564 | "timezone": "browser", 565 | "title": "Spring Batch Prometheus", 566 | "uid": "qRLUmOCmk", 567 | "version": 2 568 | } -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # https://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | org.springframework.boot 6 | spring-boot-starter-parent 7 | 2.2.6.RELEASE 8 | 9 | 10 | com.example 11 | spring-batch-demo 12 | 0.0.1-SNAPSHOT 13 | spring-batch-demo 14 | Demo project for Spring Boot 15 | 16 | 11 17 | Hoxton.SR4 18 | 2.5.0.RELEASE 19 | 0.9.0 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-batch 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-data-jpa 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-validation 33 | 34 | 35 | 36 | 37 | org.springframework.cloud 38 | spring-cloud-starter-task 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-configuration-processor 44 | true 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-actuator 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-test 54 | test 55 | 56 | 57 | org.junit.vintage 58 | junit-vintage-engine 59 | 60 | 61 | 62 | 63 | org.springframework.batch 64 | spring-batch-test 65 | test 66 | 67 | 68 | 69 | 70 | 71 | io.micrometer.prometheus 72 | prometheus-rsocket-spring 73 | ${prometheus-rsocket-proxy.version} 74 | 75 | 76 | io.micrometer.prometheus 77 | prometheus-rsocket-client 78 | ${prometheus-rsocket-proxy.version} 79 | 80 | 81 | 82 | io.micrometer 83 | micrometer-registry-prometheus 84 | 85 | 86 | io.github.mweirauch 87 | micrometer-jvm-extras 88 | 0.2.0 89 | 90 | 91 | net.logstash.logback 92 | logstash-logback-encoder 93 | 6.3 94 | 95 | 96 | org.projectlombok 97 | lombok 98 | true 99 | 100 | 101 | org.postgresql 102 | postgresql 103 | runtime 104 | 105 | 106 | org.assertj 107 | assertj-core 108 | 3.15.0 109 | test 110 | 111 | 112 | com.h2database 113 | h2 114 | test 115 | 116 | 117 | 118 | 119 | 120 | org.springframework.cloud 121 | spring-cloud-dependencies 122 | ${spring-cloud.version} 123 | pom 124 | import 125 | 126 | 127 | 128 | 129 | 130 | 131 | org.springframework.boot 132 | spring-boot-maven-plugin 133 | 134 | 135 | 136 | 137 | 138 | spring-milestones 139 | Spring Milestones 140 | https://repo.spring.io/milestone 141 | 142 | 143 | 144 | 145 | spring-milestones 146 | Spring Milestones 147 | https://repo.spring.io/milestone 148 | 149 | 150 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/SpringBatchDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringBatchDemoApplication { 8 | 9 | public static void main(String[] args) { 10 | 11 | SpringApplication.run(SpringBatchDemoApplication.class, args); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/config/BatchConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.config; 2 | 3 | import com.example.demo.models.Transaction; 4 | import com.example.demo.repositories.TransactionRepository; 5 | import com.example.demo.steps.chunklets.TransactionItemProcessor; 6 | import com.example.demo.steps.chunklets.TransactionItemWriter; 7 | import com.example.demo.steps.mappers.DefaultCompositeLineMapper; 8 | import com.example.demo.steps.mappers.DefaultRecordSeparationPolicy; 9 | import com.example.demo.steps.tasklets.FileDownloadTasklet; 10 | 11 | import org.springframework.batch.core.Job; 12 | import org.springframework.batch.core.Step; 13 | import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; 14 | import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; 15 | import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; 16 | import org.springframework.batch.core.configuration.annotation.StepScope; 17 | import org.springframework.batch.core.launch.support.RunIdIncrementer; 18 | import org.springframework.batch.item.file.FlatFileItemReader; 19 | import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.beans.factory.annotation.Value; 22 | import org.springframework.cloud.task.configuration.EnableTask; 23 | import org.springframework.context.annotation.Bean; 24 | import org.springframework.context.annotation.Configuration; 25 | import org.springframework.core.io.ClassPathResource; 26 | 27 | import lombok.extern.slf4j.Slf4j; 28 | 29 | @Configuration 30 | @EnableTask 31 | @EnableBatchProcessing 32 | @Slf4j 33 | public class BatchConfiguration { 34 | 35 | private static final int CHUNK_SIZE = 2500; 36 | 37 | @Autowired 38 | public StepBuilderFactory stepBuilderFactory; 39 | 40 | @Bean 41 | @StepScope 42 | public FlatFileItemReader reader( 43 | @Value("#{jobParameters['baseDir'] ?: '/input/'}") final String baseDir, 44 | @Value("#{jobParameters['fileName'] ?: 'exemplo-sou-java-10.txt' }") final String fileName) { 45 | 46 | return new FlatFileItemReaderBuilder() 47 | .name("myFlatFileItemReader") 48 | .resource(new ClassPathResource(baseDir + fileName)) 49 | .lineMapper(new DefaultCompositeLineMapper()) 50 | .recordSeparatorPolicy(new DefaultRecordSeparationPolicy()) 51 | .linesToSkip(1) 52 | .skippedLinesCallback(log::info) 53 | .build(); 54 | } 55 | 56 | @Bean 57 | @StepScope 58 | public TransactionItemProcessor processor() { 59 | return new TransactionItemProcessor(); 60 | } 61 | 62 | @Bean 63 | @StepScope 64 | public TransactionItemWriter writer(@Autowired TransactionRepository transactionRepository) { 65 | return new TransactionItemWriter(transactionRepository); 66 | } 67 | 68 | @Bean 69 | public Step chunkletStep() { 70 | return stepBuilderFactory.get("transactionProcessingStep") 71 | . chunk(CHUNK_SIZE) 72 | .reader(reader(null, null)) 73 | .processor(processor()) 74 | .writer(writer(null)) 75 | .stream(reader(null, null)).build(); 76 | } 77 | 78 | @Bean 79 | public Step taskletStep() { 80 | return stepBuilderFactory.get("fileDownloadingStep").tasklet(new FileDownloadTasklet()).build(); 81 | } 82 | 83 | @Bean 84 | public Job souJavaJob(@Autowired JobBuilderFactory jobBuilderFactory) { 85 | return jobBuilderFactory.get("souJavaJob") 86 | .incrementer(new RunIdIncrementer()) 87 | .start(taskletStep()) 88 | .next(chunkletStep()) 89 | .build(); 90 | } 91 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/models/FileFooter.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.models; 2 | 3 | import javax.persistence.Entity; 4 | 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | 8 | @Entity 9 | @Data 10 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 11 | public class FileFooter extends Register { 12 | public static final String LINE_ID = "9999"; 13 | 14 | private String field01; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/models/FileHeader.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.models; 2 | 3 | import javax.persistence.Entity; 4 | 5 | import lombok.Data; 6 | import lombok.EqualsAndHashCode; 7 | 8 | @Entity 9 | @Data 10 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 11 | public class FileHeader extends Register { 12 | public static final String LINE_ID = "0000"; 13 | 14 | private String field01; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/models/RegTypeOne.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.models; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.FetchType; 5 | import javax.persistence.JoinColumn; 6 | import javax.persistence.MapsId; 7 | import javax.persistence.OneToOne; 8 | 9 | import lombok.Data; 10 | import lombok.EqualsAndHashCode; 11 | import lombok.ToString; 12 | 13 | @Entity 14 | @Data 15 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 16 | public class RegTypeOne extends Register { 17 | 18 | public static final String LINE_ID = "0101"; 19 | 20 | @OneToOne(fetch = FetchType.LAZY) 21 | @JoinColumn(name = "id") 22 | @MapsId 23 | @ToString.Exclude 24 | private Transaction transaction; 25 | 26 | private String field01; 27 | private String field02; 28 | private String field03; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/models/RegTypeThree.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.models; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.FetchType; 5 | import javax.persistence.JoinColumn; 6 | import javax.persistence.MapsId; 7 | import javax.persistence.OneToOne; 8 | 9 | import lombok.Data; 10 | import lombok.EqualsAndHashCode; 11 | import lombok.ToString; 12 | 13 | @Entity 14 | @Data 15 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 16 | public class RegTypeThree extends Register { 17 | 18 | public static final String LINE_ID = "0103"; 19 | 20 | @OneToOne(fetch = FetchType.LAZY) 21 | @JoinColumn(name = "id") 22 | @MapsId 23 | @ToString.Exclude 24 | private Transaction transaction; 25 | 26 | private String field01; 27 | private String field02; 28 | private String field03; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/models/RegTypeTwo.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.models; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.FetchType; 5 | import javax.persistence.JoinColumn; 6 | import javax.persistence.MapsId; 7 | import javax.persistence.OneToOne; 8 | 9 | import lombok.Data; 10 | import lombok.EqualsAndHashCode; 11 | import lombok.ToString; 12 | 13 | @Entity 14 | @Data 15 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 16 | public class RegTypeTwo extends Register { 17 | 18 | public static final String LINE_ID = "0102"; 19 | 20 | @OneToOne(fetch = FetchType.LAZY) 21 | @JoinColumn(name = "id") 22 | @MapsId 23 | @ToString.Exclude 24 | private Transaction transaction; 25 | 26 | private String field01; 27 | private String field02; 28 | private String field03; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/models/Register.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.models; 2 | 3 | import javax.persistence.Id; 4 | import javax.persistence.MappedSuperclass; 5 | 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | 9 | @Data 10 | @MappedSuperclass 11 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 12 | public class Register { 13 | 14 | private String regId; 15 | 16 | @Id 17 | @EqualsAndHashCode.Include 18 | private long id; 19 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/models/Transaction.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.models; 2 | 3 | import javax.persistence.CascadeType; 4 | import javax.persistence.Entity; 5 | import javax.persistence.FetchType; 6 | import javax.persistence.OneToOne; 7 | 8 | import lombok.Data; 9 | import lombok.EqualsAndHashCode; 10 | 11 | @Entity 12 | @Data 13 | @EqualsAndHashCode(onlyExplicitlyIncluded = true) 14 | public class Transaction extends Register { 15 | public static final String LINE_ID = "0100"; 16 | 17 | @OneToOne(mappedBy = "transaction", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false) 18 | private RegTypeOne regTypeOne; 19 | @OneToOne(mappedBy = "transaction", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false) 20 | private RegTypeTwo regTypeTwo; 21 | @OneToOne(mappedBy = "transaction", cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false) 22 | private RegTypeThree regTypeThree; 23 | 24 | private String field01; 25 | private String field02; 26 | private String field03; 27 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/repositories/TransactionRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.repositories; 2 | 3 | import com.example.demo.models.Transaction; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | @Repository 9 | public interface TransactionRepository extends JpaRepository { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/chunklets/TransactionItemProcessor.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.chunklets; 2 | 3 | import com.example.demo.models.Transaction; 4 | 5 | import org.springframework.batch.item.ItemProcessor; 6 | 7 | import lombok.extern.slf4j.Slf4j; 8 | 9 | @Slf4j 10 | public class TransactionItemProcessor implements ItemProcessor { 11 | @Override 12 | public Transaction process(Transaction item) throws Exception { 13 | // TODO Implementar lógica de processamento 14 | log.debug(item.toString()); 15 | item.setField01(item.getField01().toUpperCase()); 16 | item.setField02(item.getField02().toUpperCase()); 17 | item.setField03(item.getField03().toUpperCase()); 18 | 19 | item.getRegTypeOne().setField01(item.getRegTypeOne().getField01().toUpperCase()); 20 | item.getRegTypeOne().setField02(item.getRegTypeOne().getField02().toUpperCase()); 21 | item.getRegTypeOne().setField03(item.getRegTypeOne().getField03().toUpperCase()); 22 | 23 | item.getRegTypeTwo().setField01(item.getRegTypeTwo().getField01().toUpperCase()); 24 | item.getRegTypeTwo().setField02(item.getRegTypeTwo().getField02().toUpperCase()); 25 | item.getRegTypeTwo().setField03(item.getRegTypeTwo().getField03().toUpperCase()); 26 | 27 | item.getRegTypeThree().setField01(item.getRegTypeThree().getField01().toUpperCase()); 28 | item.getRegTypeThree().setField02(item.getRegTypeThree().getField02().toUpperCase()); 29 | item.getRegTypeThree().setField03(item.getRegTypeThree().getField03().toUpperCase()); 30 | 31 | log.debug(item.toString()); 32 | return item; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/chunklets/TransactionItemWriter.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.chunklets; 2 | 3 | import java.util.List; 4 | 5 | import javax.transaction.Transactional; 6 | 7 | import com.example.demo.models.Transaction; 8 | import com.example.demo.repositories.TransactionRepository; 9 | 10 | import org.springframework.batch.item.ItemWriter; 11 | 12 | import lombok.extern.slf4j.Slf4j; 13 | 14 | @Slf4j 15 | public class TransactionItemWriter implements ItemWriter { 16 | private TransactionRepository transactionRepository; 17 | 18 | public TransactionItemWriter(TransactionRepository transactionRepository) { 19 | this.transactionRepository = transactionRepository; 20 | } 21 | 22 | @Override 23 | @Transactional 24 | public void write(List items) throws Exception { 25 | log.info("salvando a lista de transações em lotes de " + items.size()); 26 | transactionRepository.saveAll(items); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/mappers/DefaultCompositeLineMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.mappers; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.example.demo.models.Transaction; 7 | import com.example.demo.steps.tokenizers.DefaultTokenizer; 8 | import com.example.demo.steps.tokenizers.TransactionTokenizer; 9 | 10 | import org.springframework.batch.item.file.mapping.FieldSetMapper; 11 | import org.springframework.batch.item.file.mapping.PatternMatchingCompositeLineMapper; 12 | import org.springframework.batch.item.file.transform.LineTokenizer; 13 | 14 | public class DefaultCompositeLineMapper extends PatternMatchingCompositeLineMapper { 15 | public DefaultCompositeLineMapper() { 16 | Map tokenizers = new HashMap<>(); 17 | tokenizers.put(Transaction.LINE_ID + "*", new TransactionTokenizer()); 18 | //TODO Consertar o tipo Generics 19 | // tokenizers.put(FileHeader.LINE_ID + "*", new FileHeaderTokenizer()); 20 | // tokenizers.put(FileFooter.LINE_ID + "*", new FileFooterTokenizer()); 21 | tokenizers.put("*", new DefaultTokenizer()); 22 | this.setTokenizers(tokenizers); 23 | 24 | Map> fieldSetMappers = new HashMap<>(); 25 | fieldSetMappers.put(Transaction.LINE_ID + "*", new TransactionFieldSetMapper()); 26 | // fieldSetMappers.put(FileHeader.LINE_ID + "*", new FileHeaderFieldSetMapper()); 27 | // fieldSetMappers.put(FileFooter.LINE_ID + "*", new FileFooterFieldSetMapper()); 28 | fieldSetMappers.put("*", new DefaultFieldSetMapper()); 29 | this.setFieldSetMappers(fieldSetMappers); 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/mappers/DefaultFieldSetMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.mappers; 2 | 3 | import com.example.demo.models.Transaction; 4 | 5 | import org.springframework.batch.item.file.mapping.FieldSetMapper; 6 | import org.springframework.batch.item.file.transform.FieldSet; 7 | import org.springframework.validation.BindException; 8 | 9 | public class DefaultFieldSetMapper implements FieldSetMapper { 10 | public static final String REG_ID = "regId"; 11 | 12 | @Override 13 | public Transaction mapFieldSet(FieldSet fieldSet) throws BindException { 14 | Transaction transaction = new Transaction(); 15 | transaction.setRegId(fieldSet.readString(REG_ID)); 16 | return transaction; 17 | } 18 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/mappers/DefaultRecordSeparationPolicy.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.mappers; 2 | 3 | import org.springframework.batch.item.file.separator.RecordSeparatorPolicy; 4 | 5 | public class DefaultRecordSeparationPolicy implements RecordSeparatorPolicy { 6 | private boolean isFirstRead = true; 7 | private String currentRecord = ""; 8 | private String nextRecord = ""; 9 | private boolean isHeader; 10 | 11 | @Override 12 | public boolean isEndOfRecord(String record) { 13 | if (record.startsWith("0000")) { 14 | isHeader = true; 15 | return true; 16 | } else if (record.startsWith("9999")) { 17 | return true; 18 | } else if (record.startsWith("0100")) { 19 | isHeader = false; 20 | if (isFirstRead) { 21 | isFirstRead = false; 22 | return false; 23 | } else { 24 | return true; 25 | } 26 | } else { 27 | isHeader = false; 28 | return false; 29 | } 30 | } 31 | 32 | /** 33 | * Pass the record through. Do nothing. 34 | * 35 | * @see org.springframework.batch.item.file.separator.RecordSeparatorPolicy#postProcess(java.lang.String) 36 | */ 37 | @Override 38 | public String postProcess(String record) { 39 | if (isHeader) { 40 | return record; 41 | } 42 | 43 | nextRecord = currentRecord; 44 | currentRecord = record; 45 | 46 | return nextRecord; 47 | 48 | } 49 | 50 | /** 51 | * Pass the line through. Do nothing. 52 | * 53 | * @see org.springframework.batch.item.file.separator.RecordSeparatorPolicy#preProcess(java.lang.String) 54 | */ 55 | @Override 56 | public String preProcess(String record) { 57 | currentRecord += record; 58 | record = ""; 59 | return record; 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/mappers/FileFooterFieldSetMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.mappers; 2 | 3 | import com.example.demo.models.FileFooter; 4 | 5 | import org.springframework.batch.item.file.mapping.FieldSetMapper; 6 | import org.springframework.batch.item.file.transform.FieldSet; 7 | import org.springframework.validation.BindException; 8 | 9 | public class FileFooterFieldSetMapper implements FieldSetMapper { 10 | public static final String FILE_FOOTER_REG_ID = "fileFooterRegId"; 11 | public static final String FILE_FOOTER_FIELD01 = "fileFooterField01"; 12 | 13 | @Override 14 | public FileFooter mapFieldSet(FieldSet fieldSet) throws BindException { 15 | FileFooter fileFooter = new FileFooter(); 16 | fileFooter.setRegId(fieldSet.readString(FILE_FOOTER_REG_ID)); 17 | fileFooter.setField01(fieldSet.readString(FILE_FOOTER_FIELD01)); 18 | 19 | return fileFooter; 20 | 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/mappers/FileHeaderFieldSetMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.mappers; 2 | 3 | import com.example.demo.models.FileHeader; 4 | 5 | import org.springframework.batch.item.file.mapping.FieldSetMapper; 6 | import org.springframework.batch.item.file.transform.FieldSet; 7 | import org.springframework.validation.BindException; 8 | 9 | public class FileHeaderFieldSetMapper implements FieldSetMapper { 10 | public static final String FILE_HEADER_REG_ID = "fileHeaderRegId"; 11 | public static final String FILE_HEADER_FIELD01 = "fileHeaderField01"; 12 | 13 | @Override 14 | public FileHeader mapFieldSet(FieldSet fieldSet) throws BindException { 15 | FileHeader fileHeader = new FileHeader(); 16 | fileHeader.setRegId(fieldSet.readString(FILE_HEADER_REG_ID)); 17 | fileHeader.setField01(fieldSet.readString(FILE_HEADER_FIELD01)); 18 | 19 | return fileHeader; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/mappers/TransactionFieldSetMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.mappers; 2 | 3 | import com.example.demo.models.RegTypeOne; 4 | import com.example.demo.models.RegTypeThree; 5 | import com.example.demo.models.RegTypeTwo; 6 | import com.example.demo.models.Transaction; 7 | 8 | import org.springframework.batch.item.file.mapping.FieldSetMapper; 9 | import org.springframework.batch.item.file.transform.FieldSet; 10 | import org.springframework.validation.BindException; 11 | 12 | public class TransactionFieldSetMapper implements FieldSetMapper { 13 | public static final String TRANSACTION_REG_ID = "transactionRegId"; 14 | public static final String TRANSACTION_ID = "transactionId"; 15 | public static final String TRANSACTION_FIELD01 = "transactionField01"; 16 | public static final String TRANSACTION_FIELD02 = "transactionField02"; 17 | public static final String TRANSACTION_FIELD03 = "transactionField03"; 18 | public static final String REG_TYPE_ONE_REG_ID = "regTypeOneRegId"; 19 | public static final String REG_TYPE_ONE_FIELD01 = "regTypeOneField01"; 20 | public static final String REG_TYPE_ONE_FIELD02 = "regTypeOneField02"; 21 | public static final String REG_TYPE_ONE_FIELD03 = "regTypeOneField03"; 22 | public static final String REG_TYPE_TWO_REG_ID = "regTypeTwoRegId"; 23 | public static final String REG_TYPE_TWO_FIELD01 = "regTypeTwoField01"; 24 | public static final String REG_TYPE_TWO_FIELD02 = "regTypeTwoField02"; 25 | public static final String REG_TYPE_TWO_FIELD03 = "regTypeTwoField03"; 26 | public static final String REG_TYPE_THREE_REG_ID = "regTypeThreeRegId"; 27 | public static final String REG_TYPE_THREE_FIELD01 = "regTypeThreeField01"; 28 | public static final String REG_TYPE_THREE_FIELD02 = "regTypeThreeField02"; 29 | public static final String REG_TYPE_THREE_FIELD03 = "regTypeThreeField03"; 30 | 31 | // 32 | 33 | @Override 34 | public Transaction mapFieldSet(FieldSet fieldSet) throws BindException { 35 | Transaction transaction = new Transaction(); 36 | Long transactionId = fieldSet.readLong(TRANSACTION_ID); 37 | transaction.setId(transactionId); 38 | transaction.setRegId(fieldSet.readString(TRANSACTION_REG_ID)); 39 | transaction.setField01(fieldSet.readString(TRANSACTION_FIELD01)); 40 | transaction.setField02(fieldSet.readString(TRANSACTION_FIELD02)); 41 | transaction.setField03(fieldSet.readString(TRANSACTION_FIELD03)); 42 | 43 | RegTypeOne regTypeOne = new RegTypeOne(); 44 | regTypeOne.setRegId(fieldSet.readString(REG_TYPE_ONE_REG_ID)); 45 | regTypeOne.setField01(fieldSet.readString(REG_TYPE_ONE_FIELD01)); 46 | regTypeOne.setField02(fieldSet.readString(REG_TYPE_ONE_FIELD02)); 47 | regTypeOne.setField03(fieldSet.readString(REG_TYPE_ONE_FIELD03)); 48 | regTypeOne.setTransaction(transaction); 49 | regTypeOne.setId(transactionId); 50 | 51 | RegTypeTwo regTypeTwo = new RegTypeTwo(); 52 | regTypeTwo.setRegId(fieldSet.readString(REG_TYPE_TWO_REG_ID)); 53 | regTypeTwo.setField01(fieldSet.readString(REG_TYPE_TWO_FIELD01)); 54 | regTypeTwo.setField02(fieldSet.readString(REG_TYPE_TWO_FIELD02)); 55 | regTypeTwo.setField03(fieldSet.readString(REG_TYPE_TWO_FIELD03)); 56 | regTypeTwo.setTransaction(transaction); 57 | regTypeTwo.setId(transactionId); 58 | 59 | RegTypeThree regTypeThree = new RegTypeThree(); 60 | regTypeThree.setRegId(fieldSet.readString(REG_TYPE_THREE_REG_ID)); 61 | regTypeThree.setField01(fieldSet.readString(REG_TYPE_THREE_FIELD01)); 62 | regTypeThree.setField02(fieldSet.readString(REG_TYPE_THREE_FIELD02)); 63 | regTypeThree.setField03(fieldSet.readString(REG_TYPE_THREE_FIELD03)); 64 | regTypeThree.setTransaction(transaction); 65 | regTypeThree.setId(transactionId); 66 | 67 | transaction.setRegTypeOne(regTypeOne); 68 | transaction.setRegTypeTwo(regTypeTwo); 69 | transaction.setRegTypeThree(regTypeThree); 70 | 71 | return transaction; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/tasklets/FileDownloadTasklet.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.tasklets; 2 | 3 | import org.springframework.batch.core.StepContribution; 4 | import org.springframework.batch.core.scope.context.ChunkContext; 5 | import org.springframework.batch.core.step.tasklet.Tasklet; 6 | import org.springframework.batch.repeat.RepeatStatus; 7 | 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | @Slf4j 11 | public class FileDownloadTasklet implements Tasklet { 12 | 13 | @Override 14 | public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { 15 | // TODO Lógica para fazer o download do arquivo 16 | log.info("executando a lógica de download do arquivo"); 17 | return RepeatStatus.FINISHED; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/tokenizers/DefaultTokenizer.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.tokenizers; 2 | 3 | import org.springframework.batch.item.file.transform.FixedLengthTokenizer; 4 | import org.springframework.batch.item.file.transform.Range; 5 | 6 | public class DefaultTokenizer extends FixedLengthTokenizer { 7 | public DefaultTokenizer() { 8 | String[] names = new String[] { 9 | "regId" 10 | }; 11 | 12 | Range[] ranges = new Range[] { 13 | new Range(1, 4) 14 | }; 15 | this.setNames(names); 16 | this.setColumns(ranges); 17 | this.setStrict(false); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/tokenizers/FileFooterTokenizer.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.tokenizers; 2 | 3 | import org.springframework.batch.item.file.transform.FixedLengthTokenizer; 4 | import org.springframework.batch.item.file.transform.Range; 5 | 6 | public class FileFooterTokenizer extends FixedLengthTokenizer { 7 | public FileFooterTokenizer() { 8 | final String[] names = new String[] { 9 | "fileFooterRegId", 10 | "fileFooterField01" 11 | }; 12 | /* 13 | * File template 14 | * ----5----0----5----0----5----0- 15 | * 16 | * 0000este eh o header do arquivo 17 | */ 18 | final Range[] ranges = new Range[] { 19 | new Range(1, 4), //4 20 | new Range(5, 31) 21 | }; 22 | this.setNames(names); 23 | this.setColumns(ranges); 24 | this.setStrict(false); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/tokenizers/FileHeaderTokenizer.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.tokenizers; 2 | 3 | import org.springframework.batch.item.file.transform.FixedLengthTokenizer; 4 | import org.springframework.batch.item.file.transform.Range; 5 | 6 | public class FileHeaderTokenizer extends FixedLengthTokenizer { 7 | public FileHeaderTokenizer() { 8 | final String[] names = new String[] { 9 | "fileHeaderRegId", 10 | "fileHeaderField01" 11 | }; 12 | /* 13 | * File template 14 | * ----5----0----5----0----5----0- 15 | * 16 | * 0000este eh o header do arquivo 17 | */ 18 | final Range[] ranges = new Range[] { 19 | new Range(1, 4), //4 20 | new Range(5, 31) 21 | }; 22 | this.setNames(names); 23 | this.setColumns(ranges); 24 | this.setStrict(false); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/example/demo/steps/tokenizers/TransactionTokenizer.java: -------------------------------------------------------------------------------- 1 | package com.example.demo.steps.tokenizers; 2 | 3 | import org.springframework.batch.item.file.transform.FixedLengthTokenizer; 4 | import org.springframework.batch.item.file.transform.Range; 5 | 6 | public class TransactionTokenizer extends FixedLengthTokenizer { 7 | public TransactionTokenizer() { 8 | final String[] names = new String[] { 9 | "transactionRegId", 10 | "transactionId", 11 | "transactionField01", 12 | "transactionField02", 13 | "transactionField03", 14 | "regTypeOneRegId", 15 | "regTypeOneField01", 16 | "regTypeOneField02", 17 | "regTypeOneField03", 18 | "regTypeTwoRegId", 19 | "regTypeTwoField01", 20 | "regTypeTwoField02", 21 | "regTypeTwoField03", 22 | "regTypeThreeRegId", 23 | "regTypeThreeField01", 24 | "regTypeThreeField02", 25 | "regTypeThreeField03" 26 | }; 27 | /* 28 | * File template 29 | * ----5----0----5----0----5----0----5----0----5----0----5----0----5----0----5----0----5----0----5----0----5----0----5-- 30 | * - 31 | * 32 | * 0100000000000000000001campo03campo04campo050101campo13campo14campo150102campo23campo24campo250103campo33campo34campo35 33 | */ 34 | final Range[] ranges = new Range[] { 35 | new Range(1, 4), //4 36 | new Range(5, 22), //18 37 | new Range(23, 29), //7 38 | new Range(30, 36), //7 39 | new Range(37, 43), //7 40 | new Range(44, 47), //4 41 | new Range(48, 54), //7 42 | new Range(55, 61), //7 43 | new Range(62, 68), //7 44 | new Range(69, 72), //4 45 | new Range(73, 79), //7 46 | new Range(80, 86), //7 47 | new Range(87, 93), //7 48 | new Range(94, 97), //4 49 | new Range(98, 104), //7 50 | new Range(105, 111), //7 51 | new Range(112, 118), //7 52 | 53 | }; 54 | this.setNames(names); 55 | this.setColumns(ranges); 56 | this.setStrict(false); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=souJavaBsb 2 | spring.cloud.task.name=souJavaBsb-task 3 | spring.batch.name=souJavaBsb-Batch 4 | info.app.name=@project.artifactId@ 5 | info.app.description=@project.description@ 6 | info.app.version=@project.version@ 7 | spring.datasource.url=jdbc:postgresql://localhost:5432/dataflow?useSSL=false 8 | spring.datasource.driver-class-name=org.postgresql.Driver 9 | spring.datasource.username=root 10 | spring.datasource.password=rootpw 11 | spring.jpa.show-sql=false 12 | spring.jpa.hibernate.ddl-auto=update 13 | spring.jpa.properties.hibernate.jdbc.batch_size=2500 14 | spring.jpa.properties.hibernate.order_inserts=true 15 | spring.jpa.properties.hibernate.cache.use_query_cache=false 16 | spring.jpa.properties.hibernate.cache.use_second_level_cache=false 17 | spring.jpa.properties.hibernate.cache.use_structured_entries=false 18 | spring.jpa.properties.hibernate.cache.use_minimal_puts=false 19 | spring.jpa.properties.hibernate.format_sql=false 20 | spring.jpa.properties.hibernate.generate_statistics=false 21 | management.metrics.tags.application=${spring.application.name} 22 | management.metrics.tags.instance=local 23 | management.metrics.export.prometheus.enabled=true 24 | management.metrics.export.prometheus.rsocket.enabled=true 25 | management.metrics.export.prometheus.rsocket.host=localhost 26 | management.metrics.export.prometheus.rsocket.port=7001 27 | management.metrics.export.prometheus.rsocket.max-retries=10000 28 | management.metrics.export.prometheus.rsocket.first-backoff=10s 29 | management.metrics.export.prometheus.rsocket.max-backoff=10m 30 | management.endpoints.web.exposure.include=* 31 | logging.level.com.example.demo=ERROR 32 | logging.level.org.springframework.cloud.task=ERROR 33 | logging.level.org.springframework.batch.item.data=ERROR 34 | -------------------------------------------------------------------------------- /src/main/resources/application.yml.bkp: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: souJavaBsb 4 | datasource: 5 | url: jdbc:postgresql://localhost:5432/dataflow?useSSL=false 6 | driver-class-name: org.postgresql.Driver 7 | username: root 8 | password: rootpw 9 | # driver-class-name: org.h2.Driver 10 | # url: jdbc:h2:mem:testdb 11 | # driver-class-name: org.hsqldb.jdbc.JDBCDriver 12 | # url: jdbc:hsqldb:mem:testdb;DB_CLOSE_DELAY=-1 13 | # username: sa 14 | # password: password 15 | jpa: 16 | show-sql: false 17 | hibernate: 18 | ddl-auto: update 19 | properties: 20 | hibernate.jdbc.batch_size: 2500 21 | hibernate.order_inserts: true 22 | hibernate.cache.use_query_cache: false 23 | hibernate.cache.use_second_level_cache: false 24 | hibernate.cache.use_structured_entries: false 25 | hibernate.cache.use_minimal_puts: false 26 | hibernate.format_sql: false 27 | hibernate.generate_statistics: false 28 | h2: 29 | console: 30 | enabled: true 31 | management: 32 | metrics: 33 | tags: 34 | application: ${spring.application.name} 35 | export: 36 | prometheus: 37 | enabled: true 38 | rsocket: 39 | enabled: true 40 | host: localhost #required 41 | port: 7001 42 | endpoints: 43 | web: 44 | exposure: 45 | include: "*" 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | ____ ____ _ __ 2 | / ___| _ __ _ __${AnsiColor.GREEN}(_)${AnsiColor.DEFAULT}_ __ __ _ / ___| | ___ _ _ __| | 3 | \___ \| '_ \| '__| | '_ \ / _` | | | | |/ _ \| | | |/ _` | 4 | ___) | |_) | | | | | | | (_| | | |___| | (_) | |_| | (_| | 5 | |____/| .__/|_| |_|_| |_|\__, | \____|_|\___/ \__,_|\__,_| 6 | ____ |_| _ __|___/ ${AnsiColor.BLUE} __________${AnsiColor.DEFAULT} 7 | | _ \ __ _| |_ __ _ | ___| | _____ __ ${AnsiColor.BLUE} \ \ \ \ \ \${AnsiColor.DEFAULT} 8 | | | | |/ _` | __/ _` | | |_ | |/ _ \ \ /\ / / ${AnsiColor.BLUE} \ \ \ \ \ \${AnsiColor.DEFAULT} 9 | | |_| | (_| | || (_| | | _| | | (_) \ V V / ${AnsiColor.BLUE} / / / / / /${AnsiColor.DEFAULT} 10 | |____/ \__,_|\__\__,_| |_| |_|\___/ \_/\_/ ${AnsiColor.BLUE} /_/_/_/_/_/${AnsiColor.DEFAULT} 11 | 12 | ${application.title} ${AnsiColor.GREEN}${application.formatted-version}${AnsiColor.DEFAULT} 13 | -------------------------------------------------------------------------------- /src/main/resources/input/exemplo-sou-java-10.txt: -------------------------------------------------------------------------------- 1 | 0000este eh o header do arquivo 2 | 0100000000000000000001campo03campo04campo05 3 | 0101campo13campo14campo15 4 | 0102campo23campo24campo25 5 | 0103campo33campo34campo35 6 | 0100000000000000000002campo03campo04campo05 7 | 0101campo13campo14campo15 8 | 0102campo23campo24campo25 9 | 0103campo33campo34campo35 10 | 0100000000000000000003campo03campo04campo05 11 | 0101campo13campo14campo15 12 | 0102campo23campo24campo25 13 | 0103campo33campo34campo35 14 | 0100000000000000000004campo03campo04campo05 15 | 0101campo13campo14campo15 16 | 0102campo23campo24campo25 17 | 0103campo33campo34campo35 18 | 0100000000000000000005campo03campo04campo05 19 | 0101campo13campo14campo15 20 | 0102campo23campo24campo25 21 | 0103campo33campo34campo35 22 | 0100000000000000000006campo03campo04campo05 23 | 0101campo13campo14campo15 24 | 0102campo23campo24campo25 25 | 0103campo33campo34campo35 26 | 0100000000000000000007campo03campo04campo05 27 | 0101campo13campo14campo15 28 | 0102campo23campo24campo25 29 | 0103campo33campo34campo35 30 | 0100000000000000000008campo03campo04campo05 31 | 0101campo13campo14campo15 32 | 0102campo23campo24campo25 33 | 0103campo33campo34campo35 34 | 0100000000000000000009campo03campo04campo05 35 | 0101campo13campo14campo15 36 | 0102campo23campo24campo25 37 | 0103campo33campo34campo35 38 | 0100000000000000000010campo03campo04campo05 39 | 0101campo13campo14campo15 40 | 0102campo23campo24campo25 41 | 0103campo33campo34campo35 42 | 9999este eh o footer do arquivo -------------------------------------------------------------------------------- /src/main/resources/input/exemplo-sou-java-1mi.txt.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fredgcosta/spring-batch-demo/241e7e4801ff89eee6adb5611911b9095f147465/src/main/resources/input/exemplo-sou-java-1mi.txt.7z -------------------------------------------------------------------------------- /src/main/resources/input/exemplo-sou-java.txt: -------------------------------------------------------------------------------- 1 | 0000este eh o header do arquivo 2 | 0100000000000000000001campo01campo02campo03 3 | 0101campo11campo12campo13 4 | 0102campo21campo22campo23 5 | 0103campo31campo32campo33 6 | 0100000000000000000002campo01campo02campo03 7 | 0101campo11campo12campo13 8 | 0102campo21campo22campo23 9 | 0103campo31campo32campo33 10 | 0100000000000000000003campo01campo02campo03 11 | 0101campo11campo12campo13 12 | 0102campo21campo22campo23 13 | 0103campo31campo32campo33 14 | 0100000000000000000004campo01campo02campo03 15 | 0101campo11campo12campo13 16 | 0102campo21campo22campo23 17 | 0103campo31campo32campo33 18 | 0100000000000000000005campo01campo02campo03 19 | 0101campo11campo12campo13 20 | 0102campo21campo22campo23 21 | 0103campo31campo32campo33 22 | 0100000000000000000006campo01campo02campo03 23 | 0101campo11campo12campo13 24 | 0102campo21campo22campo23 25 | 0103campo31campo32campo33 26 | 0100000000000000000007campo01campo02campo03 27 | 0101campo11campo12campo13 28 | 0102campo21campo22campo23 29 | 0103campo31campo32campo33 30 | 0100000000000000000008campo01campo02campo03 31 | 0101campo11campo12campo13 32 | 0102campo21campo22campo23 33 | 0103campo31campo32campo33 34 | 0100000000000000000009campo01campo02campo03 35 | 0101campo11campo12campo13 36 | 0102campo21campo22campo23 37 | 0103campo31campo32campo33 38 | 0100000000000000000010campo01campo02campo03 39 | 0101campo11campo12campo13 40 | 0102campo21campo22campo23 41 | 0103campo31campo32campo33 42 | 0100000000000000000011campo01campo02campo03 43 | 0101campo11campo12campo13 44 | 0102campo21campo22campo23 45 | 0103campo31campo32campo33 46 | 0100000000000000000012campo01campo02campo03 47 | 0101campo11campo12campo13 48 | 0102campo21campo22campo23 49 | 0103campo31campo32campo33 50 | 0100000000000000000013campo01campo02campo03 51 | 0101campo11campo12campo13 52 | 0102campo21campo22campo23 53 | 0103campo31campo32campo33 54 | 0100000000000000000014campo01campo02campo03 55 | 0101campo11campo12campo13 56 | 0102campo21campo22campo23 57 | 0103campo31campo32campo33 58 | 0100000000000000000015campo01campo02campo03 59 | 0101campo11campo12campo13 60 | 0102campo21campo22campo23 61 | 0103campo31campo32campo33 62 | 0100000000000000000016campo01campo02campo03 63 | 0101campo11campo12campo13 64 | 0102campo21campo22campo23 65 | 0103campo31campo32campo33 66 | 0100000000000000000017campo01campo02campo03 67 | 0101campo11campo12campo13 68 | 0102campo21campo22campo23 69 | 0103campo31campo32campo33 70 | 0100000000000000000018campo01campo02campo03 71 | 0101campo11campo12campo13 72 | 0102campo21campo22campo23 73 | 0103campo31campo32campo33 74 | 0100000000000000000019campo01campo02campo03 75 | 0101campo11campo12campo13 76 | 0102campo21campo22campo23 77 | 0103campo31campo32campo33 78 | 0100000000000000000020campo01campo02campo03 79 | 0101campo11campo12campo13 80 | 0102campo21campo22campo23 81 | 0103campo31campo32campo33 82 | 0100000000000000000021campo01campo02campo03 83 | 0101campo11campo12campo13 84 | 0102campo21campo22campo23 85 | 0103campo31campo32campo33 86 | 0100000000000000000022campo01campo02campo03 87 | 0101campo11campo12campo13 88 | 0102campo21campo22campo23 89 | 0103campo31campo32campo33 90 | 0100000000000000000023campo01campo02campo03 91 | 0101campo11campo12campo13 92 | 0102campo21campo22campo23 93 | 0103campo31campo32campo33 94 | 0100000000000000000024campo01campo02campo03 95 | 0101campo11campo12campo13 96 | 0102campo21campo22campo23 97 | 0103campo31campo32campo33 98 | 0100000000000000000025campo01campo02campo03 99 | 0101campo11campo12campo13 100 | 0102campo21campo22campo23 101 | 0103campo31campo32campo33 102 | 0100000000000000000026campo01campo02campo03 103 | 0101campo11campo12campo13 104 | 0102campo21campo22campo23 105 | 0103campo31campo32campo33 106 | 0100000000000000000027campo01campo02campo03 107 | 0101campo11campo12campo13 108 | 0102campo21campo22campo23 109 | 0103campo31campo32campo33 110 | 0100000000000000000028campo01campo02campo03 111 | 0101campo11campo12campo13 112 | 0102campo21campo22campo23 113 | 0103campo31campo32campo33 114 | 0100000000000000000029campo01campo02campo03 115 | 0101campo11campo12campo13 116 | 0102campo21campo22campo23 117 | 0103campo31campo32campo33 118 | 0100000000000000000030campo01campo02campo03 119 | 0101campo11campo12campo13 120 | 0102campo21campo22campo23 121 | 0103campo31campo32campo33 122 | 0100000000000000000031campo01campo02campo03 123 | 0101campo11campo12campo13 124 | 0102campo21campo22campo23 125 | 0103campo31campo32campo33 126 | 0100000000000000000032campo01campo02campo03 127 | 0101campo11campo12campo13 128 | 0102campo21campo22campo23 129 | 0103campo31campo32campo33 130 | 0100000000000000000033campo01campo02campo03 131 | 0101campo11campo12campo13 132 | 0102campo21campo22campo23 133 | 0103campo31campo32campo33 134 | 0100000000000000000034campo01campo02campo03 135 | 0101campo11campo12campo13 136 | 0102campo21campo22campo23 137 | 0103campo31campo32campo33 138 | 0100000000000000000035campo01campo02campo03 139 | 0101campo11campo12campo13 140 | 0102campo21campo22campo23 141 | 0103campo31campo32campo33 142 | 0100000000000000000036campo01campo02campo03 143 | 0101campo11campo12campo13 144 | 0102campo21campo22campo23 145 | 0103campo31campo32campo33 146 | 0100000000000000000037campo01campo02campo03 147 | 0101campo11campo12campo13 148 | 0102campo21campo22campo23 149 | 0103campo31campo32campo33 150 | 0100000000000000000038campo01campo02campo03 151 | 0101campo11campo12campo13 152 | 0102campo21campo22campo23 153 | 0103campo31campo32campo33 154 | 0100000000000000000039campo01campo02campo03 155 | 0101campo11campo12campo13 156 | 0102campo21campo22campo23 157 | 0103campo31campo32campo33 158 | 0100000000000000000040campo01campo02campo03 159 | 0101campo11campo12campo13 160 | 0102campo21campo22campo23 161 | 0103campo31campo32campo33 162 | 0100000000000000000041campo01campo02campo03 163 | 0101campo11campo12campo13 164 | 0102campo21campo22campo23 165 | 0103campo31campo32campo33 166 | 0100000000000000000042campo01campo02campo03 167 | 0101campo11campo12campo13 168 | 0102campo21campo22campo23 169 | 0103campo31campo32campo33 170 | 0100000000000000000043campo01campo02campo03 171 | 0101campo11campo12campo13 172 | 0102campo21campo22campo23 173 | 0103campo31campo32campo33 174 | 0100000000000000000044campo01campo02campo03 175 | 0101campo11campo12campo13 176 | 0102campo21campo22campo23 177 | 0103campo31campo32campo33 178 | 0100000000000000000045campo01campo02campo03 179 | 0101campo11campo12campo13 180 | 0102campo21campo22campo23 181 | 0103campo31campo32campo33 182 | 0100000000000000000046campo01campo02campo03 183 | 0101campo11campo12campo13 184 | 0102campo21campo22campo23 185 | 0103campo31campo32campo33 186 | 0100000000000000000047campo01campo02campo03 187 | 0101campo11campo12campo13 188 | 0102campo21campo22campo23 189 | 0103campo31campo32campo33 190 | 0100000000000000000048campo01campo02campo03 191 | 0101campo11campo12campo13 192 | 0102campo21campo22campo23 193 | 0103campo31campo32campo33 194 | 0100000000000000000049campo01campo02campo03 195 | 0101campo11campo12campo13 196 | 0102campo21campo22campo23 197 | 0103campo31campo32campo33 198 | 0100000000000000000050campo01campo02campo03 199 | 0101campo11campo12campo13 200 | 0102campo21campo22campo23 201 | 0103campo31campo32campo33 202 | 0100000000000000000051campo01campo02campo03 203 | 0101campo11campo12campo13 204 | 0102campo21campo22campo23 205 | 0103campo31campo32campo33 206 | 0100000000000000000052campo01campo02campo03 207 | 0101campo11campo12campo13 208 | 0102campo21campo22campo23 209 | 0103campo31campo32campo33 210 | 0100000000000000000053campo01campo02campo03 211 | 0101campo11campo12campo13 212 | 0102campo21campo22campo23 213 | 0103campo31campo32campo33 214 | 0100000000000000000054campo01campo02campo03 215 | 0101campo11campo12campo13 216 | 0102campo21campo22campo23 217 | 0103campo31campo32campo33 218 | 0100000000000000000055campo01campo02campo03 219 | 0101campo11campo12campo13 220 | 0102campo21campo22campo23 221 | 0103campo31campo32campo33 222 | 0100000000000000000056campo01campo02campo03 223 | 0101campo11campo12campo13 224 | 0102campo21campo22campo23 225 | 0103campo31campo32campo33 226 | 0100000000000000000057campo01campo02campo03 227 | 0101campo11campo12campo13 228 | 0102campo21campo22campo23 229 | 0103campo31campo32campo33 230 | 0100000000000000000058campo01campo02campo03 231 | 0101campo11campo12campo13 232 | 0102campo21campo22campo23 233 | 0103campo31campo32campo33 234 | 0100000000000000000059campo01campo02campo03 235 | 0101campo11campo12campo13 236 | 0102campo21campo22campo23 237 | 0103campo31campo32campo33 238 | 0100000000000000000060campo01campo02campo03 239 | 0101campo11campo12campo13 240 | 0102campo21campo22campo23 241 | 0103campo31campo32campo33 242 | 0100000000000000000061campo01campo02campo03 243 | 0101campo11campo12campo13 244 | 0102campo21campo22campo23 245 | 0103campo31campo32campo33 246 | 0100000000000000000062campo01campo02campo03 247 | 0101campo11campo12campo13 248 | 0102campo21campo22campo23 249 | 0103campo31campo32campo33 250 | 0100000000000000000063campo01campo02campo03 251 | 0101campo11campo12campo13 252 | 0102campo21campo22campo23 253 | 0103campo31campo32campo33 254 | 0100000000000000000064campo01campo02campo03 255 | 0101campo11campo12campo13 256 | 0102campo21campo22campo23 257 | 0103campo31campo32campo33 258 | 0100000000000000000065campo01campo02campo03 259 | 0101campo11campo12campo13 260 | 0102campo21campo22campo23 261 | 0103campo31campo32campo33 262 | 0100000000000000000066campo01campo02campo03 263 | 0101campo11campo12campo13 264 | 0102campo21campo22campo23 265 | 0103campo31campo32campo33 266 | 0100000000000000000067campo01campo02campo03 267 | 0101campo11campo12campo13 268 | 0102campo21campo22campo23 269 | 0103campo31campo32campo33 270 | 0100000000000000000068campo01campo02campo03 271 | 0101campo11campo12campo13 272 | 0102campo21campo22campo23 273 | 0103campo31campo32campo33 274 | 0100000000000000000069campo01campo02campo03 275 | 0101campo11campo12campo13 276 | 0102campo21campo22campo23 277 | 0103campo31campo32campo33 278 | 0100000000000000000070campo01campo02campo03 279 | 0101campo11campo12campo13 280 | 0102campo21campo22campo23 281 | 0103campo31campo32campo33 282 | 0100000000000000000071campo01campo02campo03 283 | 0101campo11campo12campo13 284 | 0102campo21campo22campo23 285 | 0103campo31campo32campo33 286 | 0100000000000000000072campo01campo02campo03 287 | 0101campo11campo12campo13 288 | 0102campo21campo22campo23 289 | 0103campo31campo32campo33 290 | 0100000000000000000073campo01campo02campo03 291 | 0101campo11campo12campo13 292 | 0102campo21campo22campo23 293 | 0103campo31campo32campo33 294 | 0100000000000000000074campo01campo02campo03 295 | 0101campo11campo12campo13 296 | 0102campo21campo22campo23 297 | 0103campo31campo32campo33 298 | 0100000000000000000075campo01campo02campo03 299 | 0101campo11campo12campo13 300 | 0102campo21campo22campo23 301 | 0103campo31campo32campo33 302 | 0100000000000000000076campo01campo02campo03 303 | 0101campo11campo12campo13 304 | 0102campo21campo22campo23 305 | 0103campo31campo32campo33 306 | 0100000000000000000077campo01campo02campo03 307 | 0101campo11campo12campo13 308 | 0102campo21campo22campo23 309 | 0103campo31campo32campo33 310 | 0100000000000000000078campo01campo02campo03 311 | 0101campo11campo12campo13 312 | 0102campo21campo22campo23 313 | 0103campo31campo32campo33 314 | 0100000000000000000079campo01campo02campo03 315 | 0101campo11campo12campo13 316 | 0102campo21campo22campo23 317 | 0103campo31campo32campo33 318 | 0100000000000000000080campo01campo02campo03 319 | 0101campo11campo12campo13 320 | 0102campo21campo22campo23 321 | 0103campo31campo32campo33 322 | 0100000000000000000081campo01campo02campo03 323 | 0101campo11campo12campo13 324 | 0102campo21campo22campo23 325 | 0103campo31campo32campo33 326 | 0100000000000000000082campo01campo02campo03 327 | 0101campo11campo12campo13 328 | 0102campo21campo22campo23 329 | 0103campo31campo32campo33 330 | 0100000000000000000083campo01campo02campo03 331 | 0101campo11campo12campo13 332 | 0102campo21campo22campo23 333 | 0103campo31campo32campo33 334 | 0100000000000000000084campo01campo02campo03 335 | 0101campo11campo12campo13 336 | 0102campo21campo22campo23 337 | 0103campo31campo32campo33 338 | 0100000000000000000085campo01campo02campo03 339 | 0101campo11campo12campo13 340 | 0102campo21campo22campo23 341 | 0103campo31campo32campo33 342 | 0100000000000000000086campo01campo02campo03 343 | 0101campo11campo12campo13 344 | 0102campo21campo22campo23 345 | 0103campo31campo32campo33 346 | 0100000000000000000087campo01campo02campo03 347 | 0101campo11campo12campo13 348 | 0102campo21campo22campo23 349 | 0103campo31campo32campo33 350 | 0100000000000000000088campo01campo02campo03 351 | 0101campo11campo12campo13 352 | 0102campo21campo22campo23 353 | 0103campo31campo32campo33 354 | 0100000000000000000089campo01campo02campo03 355 | 0101campo11campo12campo13 356 | 0102campo21campo22campo23 357 | 0103campo31campo32campo33 358 | 0100000000000000000090campo01campo02campo03 359 | 0101campo11campo12campo13 360 | 0102campo21campo22campo23 361 | 0103campo31campo32campo33 362 | 0100000000000000000091campo01campo02campo03 363 | 0101campo11campo12campo13 364 | 0102campo21campo22campo23 365 | 0103campo31campo32campo33 366 | 0100000000000000000092campo01campo02campo03 367 | 0101campo11campo12campo13 368 | 0102campo21campo22campo23 369 | 0103campo31campo32campo33 370 | 0100000000000000000093campo01campo02campo03 371 | 0101campo11campo12campo13 372 | 0102campo21campo22campo23 373 | 0103campo31campo32campo33 374 | 0100000000000000000094campo01campo02campo03 375 | 0101campo11campo12campo13 376 | 0102campo21campo22campo23 377 | 0103campo31campo32campo33 378 | 0100000000000000000095campo01campo02campo03 379 | 0101campo11campo12campo13 380 | 0102campo21campo22campo23 381 | 0103campo31campo32campo33 382 | 0100000000000000000096campo01campo02campo03 383 | 0101campo11campo12campo13 384 | 0102campo21campo22campo23 385 | 0103campo31campo32campo33 386 | 0100000000000000000097campo01campo02campo03 387 | 0101campo11campo12campo13 388 | 0102campo21campo22campo23 389 | 0103campo31campo32campo33 390 | 0100000000000000000098campo01campo02campo03 391 | 0101campo11campo12campo13 392 | 0102campo21campo22campo23 393 | 0103campo31campo32campo33 394 | 0100000000000000000099campo01campo02campo03 395 | 0101campo11campo12campo13 396 | 0102campo21campo22campo23 397 | 0103campo31campo32campo33 398 | 0100000000000000000100campo01campo02campo03 399 | 0101campo11campo12campo13 400 | 0102campo21campo22campo23 401 | 0103campo31campo32campo33 402 | 9999este eh o footer do arquivo -------------------------------------------------------------------------------- /src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ${spring.application.name} 5 | 6 | 7 | 8 | 131072 9 | sleeping 10 | 11 | 12 | 13 | 14 | app 15 | 16 | 17 | ts 18 | UTC 19 | 20 | 21 | logger 22 | 23 | 24 | level 25 | 26 | 27 | class 28 | method 29 | line 30 | file 31 | 32 | 33 | thread 34 | 35 | 36 | 37 | false 38 | 39 | 40 | 41 | 30 42 | 4096 43 | 20 44 | true 45 | 46 | 47 | 48 | msg 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/test/java/com/example/demo/SpringBatchDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringBatchDemoApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/example/demo/TransactionRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.example.demo; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | import static org.junit.jupiter.api.Assertions.assertNotNull; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.Optional; 10 | 11 | import javax.persistence.EntityManager; 12 | import javax.sql.DataSource; 13 | 14 | import com.example.demo.models.RegTypeOne; 15 | import com.example.demo.models.RegTypeThree; 16 | import com.example.demo.models.RegTypeTwo; 17 | import com.example.demo.models.Transaction; 18 | import com.example.demo.repositories.TransactionRepository; 19 | 20 | import org.junit.jupiter.api.Test; 21 | import org.junit.jupiter.api.extension.ExtendWith; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 24 | import org.springframework.jdbc.core.JdbcTemplate; 25 | import org.springframework.test.context.junit.jupiter.SpringExtension; 26 | 27 | @ExtendWith(SpringExtension.class) 28 | @DataJpaTest 29 | public class TransactionRepositoryTest { 30 | 31 | @Autowired 32 | private DataSource dataSource; 33 | @Autowired 34 | private JdbcTemplate jdbcTemplate; 35 | @Autowired 36 | private EntityManager entityManager; 37 | @Autowired 38 | private TransactionRepository transactionRepository; 39 | 40 | @Test 41 | void injectedComponentsAreNotNull() { 42 | assertThat(dataSource).isNotNull(); 43 | assertThat(jdbcTemplate).isNotNull(); 44 | assertThat(entityManager).isNotNull(); 45 | assertThat(transactionRepository).isNotNull(); 46 | } 47 | 48 | @Test 49 | public void testSaveAllTransactions() { 50 | 51 | List transactions = new ArrayList<>(3); 52 | 53 | Transaction transaction1 = new Transaction(); 54 | transaction1.setRegId("0100"); 55 | transaction1.setField01("field01"); 56 | transaction1.setField02("field02"); 57 | transaction1.setField03("field03"); 58 | transaction1.setId(1L); 59 | 60 | RegTypeOne regTypeOne1 = new RegTypeOne(); 61 | regTypeOne1.setRegId("0101"); 62 | regTypeOne1.setField01("field11"); 63 | regTypeOne1.setField02("field12"); 64 | regTypeOne1.setField03("field13"); 65 | regTypeOne1.setTransaction(transaction1); 66 | regTypeOne1.setId(1L); 67 | transaction1.setRegTypeOne(regTypeOne1); 68 | 69 | RegTypeTwo regTypeTwo1 = new RegTypeTwo(); 70 | regTypeTwo1.setRegId("0102"); 71 | regTypeTwo1.setField01("field21"); 72 | regTypeTwo1.setField02("field22"); 73 | regTypeTwo1.setField03("field23"); 74 | regTypeTwo1.setTransaction(transaction1); 75 | regTypeTwo1.setId(1L); 76 | transaction1.setRegTypeTwo(regTypeTwo1); 77 | 78 | RegTypeThree regTypeThree1 = new RegTypeThree(); 79 | regTypeThree1.setRegId("0103"); 80 | regTypeThree1.setField01("field31"); 81 | regTypeThree1.setField02("field32"); 82 | regTypeThree1.setField03("field33"); 83 | regTypeThree1.setTransaction(transaction1); 84 | regTypeThree1.setId(1L); 85 | transaction1.setRegTypeThree(regTypeThree1); 86 | 87 | Transaction transaction2 = new Transaction(); 88 | transaction2.setRegId("0100"); 89 | transaction2.setField01("field01"); 90 | transaction2.setField02("field02"); 91 | transaction2.setField03("field03"); 92 | transaction2.setId(2L); 93 | 94 | RegTypeOne regTypeOne2 = new RegTypeOne(); 95 | regTypeOne2.setRegId("0101"); 96 | regTypeOne2.setField01("field11"); 97 | regTypeOne2.setField02("field12"); 98 | regTypeOne2.setField03("field13"); 99 | regTypeOne2.setTransaction(transaction2); 100 | regTypeOne2.setId(2L); 101 | transaction2.setRegTypeOne(regTypeOne2); 102 | 103 | RegTypeTwo regTypeTwo2 = new RegTypeTwo(); 104 | regTypeTwo2.setRegId("0102"); 105 | regTypeTwo2.setField01("field21"); 106 | regTypeTwo2.setField02("field22"); 107 | regTypeTwo2.setField03("field23"); 108 | regTypeTwo2.setTransaction(transaction2); 109 | regTypeTwo2.setId(2L); 110 | transaction2.setRegTypeTwo(regTypeTwo2); 111 | 112 | RegTypeThree regTypeThree2 = new RegTypeThree(); 113 | regTypeThree2.setRegId("0103"); 114 | regTypeThree2.setField01("field31"); 115 | regTypeThree2.setField02("field32"); 116 | regTypeThree2.setField03("field33"); 117 | regTypeThree2.setTransaction(transaction2); 118 | regTypeThree2.setId(2L); 119 | transaction2.setRegTypeThree(regTypeThree2); 120 | 121 | Transaction transaction3 = new Transaction(); 122 | transaction3.setRegId("0100"); 123 | transaction3.setField01("field01"); 124 | transaction3.setField02("field02"); 125 | transaction3.setField03("field03"); 126 | transaction3.setId(3L); 127 | 128 | RegTypeOne regTypeOne3 = new RegTypeOne(); 129 | regTypeOne3.setRegId("0101"); 130 | regTypeOne3.setField01("field11"); 131 | regTypeOne3.setField02("field12"); 132 | regTypeOne3.setField03("field13"); 133 | regTypeOne3.setTransaction(transaction3); 134 | regTypeOne3.setId(3L); 135 | transaction3.setRegTypeOne(regTypeOne3); 136 | 137 | RegTypeTwo regTypeTwo3 = new RegTypeTwo(); 138 | regTypeTwo3.setRegId("0102"); 139 | regTypeTwo3.setField01("field21"); 140 | regTypeTwo3.setField02("field22"); 141 | regTypeTwo3.setField03("field23"); 142 | regTypeTwo3.setTransaction(transaction3); 143 | regTypeTwo3.setId(3L); 144 | transaction3.setRegTypeTwo(regTypeTwo3); 145 | 146 | RegTypeThree regTypeThree3 = new RegTypeThree(); 147 | regTypeThree3.setRegId("0103"); 148 | regTypeThree3.setField01("field31"); 149 | regTypeThree3.setField02("field32"); 150 | regTypeThree3.setField03("field33"); 151 | regTypeThree3.setTransaction(transaction3); 152 | regTypeThree3.setId(3L); 153 | transaction3.setRegTypeThree(regTypeThree3); 154 | 155 | transactions.add(transaction1); 156 | transactions.add(transaction2); 157 | transactions.add(transaction3); 158 | 159 | List savedTransactions = transactionRepository.saveAll(transactions); 160 | assertThat(savedTransactions).isEqualTo(transactions); 161 | 162 | } 163 | 164 | @Test 165 | public void testIdempotencyOfSaveAllTransactions() { 166 | 167 | List transactions = new ArrayList<>(3); 168 | 169 | Transaction transaction1 = new Transaction(); 170 | transaction1.setRegId("0100"); 171 | transaction1.setField01("field01"); 172 | transaction1.setField02("field02"); 173 | transaction1.setField03("field03"); 174 | transaction1.setId(1L); 175 | 176 | RegTypeOne regTypeOne1 = new RegTypeOne(); 177 | regTypeOne1.setRegId("0101"); 178 | regTypeOne1.setField01("field11"); 179 | regTypeOne1.setField02("field12"); 180 | regTypeOne1.setField03("field13"); 181 | regTypeOne1.setTransaction(transaction1); 182 | regTypeOne1.setId(1L); 183 | transaction1.setRegTypeOne(regTypeOne1); 184 | 185 | RegTypeTwo regTypeTwo1 = new RegTypeTwo(); 186 | regTypeTwo1.setRegId("0102"); 187 | regTypeTwo1.setField01("field21"); 188 | regTypeTwo1.setField02("field22"); 189 | regTypeTwo1.setField03("field23"); 190 | regTypeTwo1.setTransaction(transaction1); 191 | regTypeTwo1.setId(1L); 192 | transaction1.setRegTypeTwo(regTypeTwo1); 193 | 194 | RegTypeThree regTypeThree1 = new RegTypeThree(); 195 | regTypeThree1.setRegId("0103"); 196 | regTypeThree1.setField01("field31"); 197 | regTypeThree1.setField02("field32"); 198 | regTypeThree1.setField03("field33"); 199 | regTypeThree1.setTransaction(transaction1); 200 | regTypeThree1.setId(1L); 201 | transaction1.setRegTypeThree(regTypeThree1); 202 | 203 | Transaction transaction2 = new Transaction(); 204 | transaction2.setRegId("0100"); 205 | transaction2.setField01("field01"); 206 | transaction2.setField02("field02"); 207 | transaction2.setField03("field03"); 208 | transaction2.setId(1L); 209 | 210 | RegTypeOne regTypeOne2 = new RegTypeOne(); 211 | regTypeOne2.setRegId("0101"); 212 | regTypeOne2.setField01("field11"); 213 | regTypeOne2.setField02("field12"); 214 | regTypeOne2.setField03("field13"); 215 | regTypeOne2.setTransaction(transaction2); 216 | regTypeOne2.setId(1L); 217 | transaction2.setRegTypeOne(regTypeOne2); 218 | 219 | RegTypeTwo regTypeTwo2 = new RegTypeTwo(); 220 | regTypeTwo2.setRegId("0102"); 221 | regTypeTwo2.setField01("field21"); 222 | regTypeTwo2.setField02("field22"); 223 | regTypeTwo2.setField03("field23"); 224 | regTypeTwo2.setTransaction(transaction2); 225 | regTypeTwo2.setId(1L); 226 | transaction2.setRegTypeTwo(regTypeTwo2); 227 | 228 | RegTypeThree regTypeThree2 = new RegTypeThree(); 229 | regTypeThree2.setRegId("0103"); 230 | regTypeThree2.setField01("field31"); 231 | regTypeThree2.setField02("field32"); 232 | regTypeThree2.setField03("field33"); 233 | regTypeThree2.setTransaction(transaction2); 234 | regTypeThree2.setId(1L); 235 | transaction2.setRegTypeThree(regTypeThree2); 236 | 237 | Transaction transaction3 = new Transaction(); 238 | transaction3.setRegId("0100"); 239 | transaction3.setField01("field01"); 240 | transaction3.setField02("field02"); 241 | transaction3.setField03("field03"); 242 | transaction3.setId(1L); 243 | 244 | RegTypeOne regTypeOne3 = new RegTypeOne(); 245 | regTypeOne3.setRegId("0101"); 246 | regTypeOne3.setField01("field11"); 247 | regTypeOne3.setField02("field12"); 248 | regTypeOne3.setField03("field13"); 249 | regTypeOne3.setTransaction(transaction3); 250 | regTypeOne3.setId(1L); 251 | transaction3.setRegTypeOne(regTypeOne3); 252 | 253 | RegTypeTwo regTypeTwo3 = new RegTypeTwo(); 254 | regTypeTwo3.setRegId("0102"); 255 | regTypeTwo3.setField01("field21"); 256 | regTypeTwo3.setField02("field22"); 257 | regTypeTwo3.setField03("field23"); 258 | regTypeTwo3.setTransaction(transaction3); 259 | regTypeTwo3.setId(1L); 260 | transaction3.setRegTypeTwo(regTypeTwo3); 261 | 262 | RegTypeThree regTypeThree3 = new RegTypeThree(); 263 | regTypeThree3.setRegId("0103"); 264 | regTypeThree3.setField01("field31"); 265 | regTypeThree3.setField02("field32"); 266 | regTypeThree3.setField03("field33"); 267 | regTypeThree3.setTransaction(transaction3); 268 | regTypeThree3.setId(1L); 269 | transaction3.setRegTypeThree(regTypeThree3); 270 | 271 | transactions.add(transaction1); 272 | transactions.add(transaction2); 273 | transactions.add(transaction3); 274 | 275 | List savedTransactions = transactionRepository.saveAll(transactions); 276 | assertThat(savedTransactions).isEqualTo(transactions); 277 | } 278 | 279 | @Test 280 | public void testSaveTransaction() { 281 | 282 | Transaction transaction1 = new Transaction(); 283 | transaction1.setRegId("0100"); 284 | transaction1.setField01("field01"); 285 | transaction1.setField02("field02"); 286 | transaction1.setField03("field03"); 287 | transaction1.setId(1L); 288 | 289 | RegTypeOne regTypeOne1 = new RegTypeOne(); 290 | regTypeOne1.setRegId("0101"); 291 | regTypeOne1.setField01("field11"); 292 | regTypeOne1.setField02("field12"); 293 | regTypeOne1.setField03("field13"); 294 | regTypeOne1.setTransaction(transaction1); 295 | regTypeOne1.setId(1L); 296 | transaction1.setRegTypeOne(regTypeOne1); 297 | 298 | RegTypeTwo regTypeTwo1 = new RegTypeTwo(); 299 | regTypeTwo1.setRegId("0102"); 300 | regTypeTwo1.setField01("field21"); 301 | regTypeTwo1.setField02("field22"); 302 | regTypeTwo1.setField03("field23"); 303 | regTypeTwo1.setTransaction(transaction1); 304 | regTypeTwo1.setId(1L); 305 | transaction1.setRegTypeTwo(regTypeTwo1); 306 | 307 | RegTypeThree regTypeThree1 = new RegTypeThree(); 308 | regTypeThree1.setRegId("0103"); 309 | regTypeThree1.setField01("field31"); 310 | regTypeThree1.setField02("field32"); 311 | regTypeThree1.setField03("field33"); 312 | regTypeThree1.setTransaction(transaction1); 313 | regTypeThree1.setId(1L); 314 | transaction1.setRegTypeThree(regTypeThree1); 315 | 316 | transactionRepository.save(transaction1); 317 | Optional transaction2 = transactionRepository.findById(Long.valueOf(1L)); 318 | assertNotNull(transaction2); 319 | assertEquals(transaction2.get().getField01(), transaction1.getField01()); 320 | assertEquals(transaction2.get().getField02(), transaction1.getField02()); 321 | } 322 | 323 | @Test 324 | public void testDeleteTransaction() { 325 | 326 | Transaction transaction1 = new Transaction(); 327 | transaction1.setRegId("0100"); 328 | transaction1.setField01("field01"); 329 | transaction1.setField02("field02"); 330 | transaction1.setField03("field03"); 331 | transaction1.setId(1L); 332 | 333 | RegTypeOne regTypeOne1 = new RegTypeOne(); 334 | regTypeOne1.setRegId("0101"); 335 | regTypeOne1.setField01("field11"); 336 | regTypeOne1.setField02("field12"); 337 | regTypeOne1.setField03("field13"); 338 | regTypeOne1.setTransaction(transaction1); 339 | regTypeOne1.setId(1L); 340 | transaction1.setRegTypeOne(regTypeOne1); 341 | 342 | RegTypeTwo regTypeTwo1 = new RegTypeTwo(); 343 | regTypeTwo1.setRegId("0102"); 344 | regTypeTwo1.setField01("field21"); 345 | regTypeTwo1.setField02("field22"); 346 | regTypeTwo1.setField03("field23"); 347 | regTypeTwo1.setTransaction(transaction1); 348 | regTypeTwo1.setId(1L); 349 | transaction1.setRegTypeTwo(regTypeTwo1); 350 | 351 | RegTypeThree regTypeThree1 = new RegTypeThree(); 352 | regTypeThree1.setRegId("0103"); 353 | regTypeThree1.setField01("field31"); 354 | regTypeThree1.setField02("field32"); 355 | regTypeThree1.setField03("field33"); 356 | regTypeThree1.setTransaction(transaction1); 357 | regTypeThree1.setId(1L); 358 | transaction1.setRegTypeThree(regTypeThree1); 359 | 360 | transactionRepository.save(transaction1); 361 | transactionRepository.delete(transaction1); 362 | Optional transaction2 = transactionRepository.findById(Long.valueOf(1L)); 363 | assertThat(transaction2).isEmpty(); 364 | } 365 | 366 | @Test 367 | public void findAllEmployees() { 368 | 369 | List transactions = new ArrayList<>(3); 370 | 371 | Transaction transaction1 = new Transaction(); 372 | transaction1.setRegId("0100"); 373 | transaction1.setField01("field01"); 374 | transaction1.setField02("field02"); 375 | transaction1.setField03("field03"); 376 | transaction1.setId(1L); 377 | 378 | RegTypeOne regTypeOne1 = new RegTypeOne(); 379 | regTypeOne1.setRegId("0101"); 380 | regTypeOne1.setField01("field11"); 381 | regTypeOne1.setField02("field12"); 382 | regTypeOne1.setField03("field13"); 383 | regTypeOne1.setTransaction(transaction1); 384 | regTypeOne1.setId(1L); 385 | transaction1.setRegTypeOne(regTypeOne1); 386 | 387 | RegTypeTwo regTypeTwo1 = new RegTypeTwo(); 388 | regTypeTwo1.setRegId("0102"); 389 | regTypeTwo1.setField01("field21"); 390 | regTypeTwo1.setField02("field22"); 391 | regTypeTwo1.setField03("field23"); 392 | regTypeTwo1.setTransaction(transaction1); 393 | regTypeTwo1.setId(1L); 394 | transaction1.setRegTypeTwo(regTypeTwo1); 395 | 396 | RegTypeThree regTypeThree1 = new RegTypeThree(); 397 | regTypeThree1.setRegId("0103"); 398 | regTypeThree1.setField01("field31"); 399 | regTypeThree1.setField02("field32"); 400 | regTypeThree1.setField03("field33"); 401 | regTypeThree1.setTransaction(transaction1); 402 | regTypeThree1.setId(1L); 403 | transaction1.setRegTypeThree(regTypeThree1); 404 | 405 | Transaction transaction2 = new Transaction(); 406 | transaction2.setRegId("0100"); 407 | transaction2.setField01("field01"); 408 | transaction2.setField02("field02"); 409 | transaction2.setField03("field03"); 410 | transaction2.setId(2L); 411 | 412 | RegTypeOne regTypeOne2 = new RegTypeOne(); 413 | regTypeOne2.setRegId("0101"); 414 | regTypeOne2.setField01("field11"); 415 | regTypeOne2.setField02("field12"); 416 | regTypeOne2.setField03("field13"); 417 | regTypeOne2.setTransaction(transaction2); 418 | regTypeOne2.setId(2L); 419 | transaction2.setRegTypeOne(regTypeOne2); 420 | 421 | RegTypeTwo regTypeTwo2 = new RegTypeTwo(); 422 | regTypeTwo2.setRegId("0102"); 423 | regTypeTwo2.setField01("field21"); 424 | regTypeTwo2.setField02("field22"); 425 | regTypeTwo2.setField03("field23"); 426 | regTypeTwo2.setTransaction(transaction2); 427 | regTypeTwo2.setId(2L); 428 | transaction2.setRegTypeTwo(regTypeTwo2); 429 | 430 | RegTypeThree regTypeThree2 = new RegTypeThree(); 431 | regTypeThree2.setRegId("0103"); 432 | regTypeThree2.setField01("field31"); 433 | regTypeThree2.setField02("field32"); 434 | regTypeThree2.setField03("field33"); 435 | regTypeThree2.setTransaction(transaction2); 436 | regTypeThree2.setId(2L); 437 | transaction2.setRegTypeThree(regTypeThree2); 438 | 439 | Transaction transaction3 = new Transaction(); 440 | transaction3.setRegId("0100"); 441 | transaction3.setField01("field01"); 442 | transaction3.setField02("field02"); 443 | transaction3.setField03("field03"); 444 | transaction3.setId(3L); 445 | 446 | RegTypeOne regTypeOne3 = new RegTypeOne(); 447 | regTypeOne3.setRegId("0101"); 448 | regTypeOne3.setField01("field11"); 449 | regTypeOne3.setField02("field12"); 450 | regTypeOne3.setField03("field13"); 451 | regTypeOne3.setTransaction(transaction3); 452 | regTypeOne3.setId(3L); 453 | transaction3.setRegTypeOne(regTypeOne3); 454 | 455 | RegTypeTwo regTypeTwo3 = new RegTypeTwo(); 456 | regTypeTwo3.setRegId("0102"); 457 | regTypeTwo3.setField01("field21"); 458 | regTypeTwo3.setField02("field22"); 459 | regTypeTwo3.setField03("field23"); 460 | regTypeTwo3.setTransaction(transaction3); 461 | regTypeTwo3.setId(3L); 462 | transaction3.setRegTypeTwo(regTypeTwo3); 463 | 464 | RegTypeThree regTypeThree3 = new RegTypeThree(); 465 | regTypeThree3.setRegId("0103"); 466 | regTypeThree3.setField01("field31"); 467 | regTypeThree3.setField02("field32"); 468 | regTypeThree3.setField03("field33"); 469 | regTypeThree3.setTransaction(transaction3); 470 | regTypeThree3.setId(3L); 471 | transaction3.setRegTypeThree(regTypeThree3); 472 | 473 | transactions.add(transaction1); 474 | transactions.add(transaction2); 475 | transactions.add(transaction3); 476 | 477 | transactionRepository.saveAll(transactions); 478 | assertNotNull(transactionRepository.findAll()); 479 | } 480 | 481 | @Test 482 | public void deleteByTransactionIdTest() { 483 | Transaction transaction1 = new Transaction(); 484 | transaction1.setRegId("0100"); 485 | transaction1.setField01("field01"); 486 | transaction1.setField02("field02"); 487 | transaction1.setField03("field03"); 488 | transaction1.setId(1L); 489 | 490 | RegTypeOne regTypeOne1 = new RegTypeOne(); 491 | regTypeOne1.setRegId("0101"); 492 | regTypeOne1.setField01("field11"); 493 | regTypeOne1.setField02("field12"); 494 | regTypeOne1.setField03("field13"); 495 | regTypeOne1.setTransaction(transaction1); 496 | regTypeOne1.setId(1L); 497 | transaction1.setRegTypeOne(regTypeOne1); 498 | 499 | RegTypeTwo regTypeTwo1 = new RegTypeTwo(); 500 | regTypeTwo1.setRegId("0102"); 501 | regTypeTwo1.setField01("field21"); 502 | regTypeTwo1.setField02("field22"); 503 | regTypeTwo1.setField03("field23"); 504 | regTypeTwo1.setTransaction(transaction1); 505 | regTypeTwo1.setId(1L); 506 | transaction1.setRegTypeTwo(regTypeTwo1); 507 | 508 | RegTypeThree regTypeThree1 = new RegTypeThree(); 509 | regTypeThree1.setRegId("0103"); 510 | regTypeThree1.setField01("field31"); 511 | regTypeThree1.setField02("field32"); 512 | regTypeThree1.setField03("field33"); 513 | regTypeThree1.setTransaction(transaction1); 514 | regTypeThree1.setId(1L); 515 | transaction1.setRegTypeThree(regTypeThree1); 516 | 517 | Transaction transaction2 = transactionRepository.save(transaction1); 518 | transactionRepository.deleteById(transaction2.getId()); 519 | 520 | assertThat(transactionRepository.count()).isEqualTo(Long.valueOf(0L)); 521 | } 522 | } 523 | -------------------------------------------------------------------------------- /src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=souJavaBsb 2 | spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 3 | spring.datasource.driver-class-name=org.h2.Driver 4 | spring.datasource.username=sa 5 | spring.datasource.password=password 6 | spring.jpa.show-sql=false 7 | spring.jpahibernate.ddl-auto=update 8 | spring.jpa.properties.hibernate.jdbc.batch_size=10 9 | spring.jpa.properties.hibernate.order_inserts=true 10 | spring.jpa.properties.hibernate.cache.use_query_cache=false 11 | spring.jpa.properties.hibernate.cache.use_second_level_cache=false 12 | spring.jpa.properties.hibernate.cache.use_structured_entries=false 13 | spring.jpa.properties.hibernate.cache.use_minimal_puts=false 14 | spring.jpa.properties.hibernate.format_sql=false 15 | spring.jpa.properties.hibernate.generate_statistics=false 16 | spring.h2.console.enabled=true 17 | management.metrics.export.prometheus.enabled=false 18 | management.metrics.export.prometheus.rsocket.enabled=false 19 | -------------------------------------------------------------------------------- /src/test/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ${spring.application.name} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | --------------------------------------------------------------------------------