├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md ├── dco.yml └── workflows │ ├── ci-snapshot.yml │ ├── pr-build.yml │ ├── release.yml │ └── verify-staged-artifacts.yml ├── .gitignore ├── .mvn ├── jvm.config └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── LICENSE ├── README.adoc ├── mvnw ├── mvnw.cmd ├── pom.xml ├── spring-cloud-stream-binder-kinesis-docs ├── pom.xml └── src │ └── main │ ├── asciidoc │ ├── Guardfile │ ├── building.adoc │ ├── contributing.adoc │ ├── images │ │ └── kinesis-binder.png │ ├── index-docinfo.xml │ ├── index.adoc │ └── overview.adoc │ ├── docbook │ ├── css │ │ ├── highlight.css │ │ ├── manual-multipage.css │ │ ├── manual-singlepage.css │ │ └── manual.css │ ├── images │ │ ├── background.png │ │ ├── caution.png │ │ ├── important.png │ │ ├── logo.png │ │ ├── note.png │ │ ├── tip.png │ │ └── warning.png │ └── xsl │ │ ├── common.xsl │ │ ├── epub.xsl │ │ ├── html-multipage.xsl │ │ ├── html-singlepage.xsl │ │ ├── html.xsl │ │ ├── pdf.xsl │ │ ├── xslthl-config.xml │ │ └── xslthl │ │ ├── asciidoc-hl.xml │ │ ├── bourne-hl.xml │ │ ├── c-hl.xml │ │ ├── cpp-hl.xml │ │ ├── csharp-hl.xml │ │ ├── css-hl.xml │ │ ├── html-hl.xml │ │ ├── ini-hl.xml │ │ ├── java-hl.xml │ │ ├── javascript-hl.xml │ │ ├── json-hl.xml │ │ ├── perl-hl.xml │ │ ├── php-hl.xml │ │ ├── properties-hl.xml │ │ ├── python-hl.xml │ │ ├── ruby-hl.xml │ │ ├── sql2003-hl.xml │ │ └── yaml-hl.xml │ ├── javadoc │ └── spring-javadoc.css │ └── xslt │ └── dependencyVersions.xsl └── spring-cloud-stream-binder-kinesis ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── springframework │ │ └── cloud │ │ └── stream │ │ └── binder │ │ └── kinesis │ │ ├── KinesisBinderHealthIndicator.java │ │ ├── KinesisMessageChannelBinder.java │ │ ├── LegacyEmbeddedHeadersSupportBytesMessageMapper.java │ │ ├── config │ │ ├── ExtendedBindingHandlerMappingsProviderConfiguration.java │ │ ├── KinesisBinderConfiguration.java │ │ └── KinesisProperties.java │ │ ├── properties │ │ ├── KinesisBinderConfigurationProperties.java │ │ ├── KinesisBindingProperties.java │ │ ├── KinesisConsumerProperties.java │ │ ├── KinesisExtendedBindingProperties.java │ │ └── KinesisProducerProperties.java │ │ └── provisioning │ │ ├── KinesisConsumerDestination.java │ │ ├── KinesisProducerDestination.java │ │ └── KinesisStreamProvisioner.java └── resources │ └── META-INF │ ├── spring.binders │ └── spring │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports └── test ├── java └── org │ └── springframework │ └── cloud │ └── stream │ └── binder │ └── kinesis │ ├── KinesisBinderFunctionalTests.java │ ├── KinesisBinderTests.java │ ├── KinesisTestBinder.java │ ├── LocalstackContainerTest.java │ ├── observation │ └── KinesisBinderObservationTests.java │ └── provisioning │ └── KinesisStreamProvisionerTests.java └── resources └── logback-test.xml /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'type: bug, status: waiting-for-triage' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **In what version(s) of Spring Cloud Stream Binder for AWS Kinesis are you seeing this issue?** 11 | 12 | For example: 13 | 14 | 3.0.0 15 | 16 | Between 3.0.0 and 4.0.0 17 | 18 | **Describe the bug** 19 | 20 | A clear and concise description of what the bug is. 21 | 22 | **To Reproduce** 23 | 24 | Steps to reproduce the behavior. 25 | 26 | **Expected behavior** 27 | 28 | A clear and concise description of what you expected to happen. 29 | 30 | **Sample** 31 | 32 | A link to a GitHub repository with a [minimal, reproducible sample](https://stackoverflow.com/help/minimal-reproducible-example). 33 | 34 | Reports that include a sample will take priority over reports that do not. 35 | At times, we may require a sample, so it is good to try and include a sample up front. 36 | -------------------------------------------------------------------------------- /.github/dco.yml: -------------------------------------------------------------------------------- 1 | require: 2 | members: false 3 | -------------------------------------------------------------------------------- /.github/workflows/ci-snapshot.yml: -------------------------------------------------------------------------------- 1 | name: CI SNAPSHOT 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | - '*.x' 9 | 10 | jobs: 11 | build_snapshot: 12 | uses: spring-io/spring-github-workflows/.github/workflows/spring-artifactory-maven-snapshot.yml@v5 13 | with: 14 | mavenArgs: -U 15 | secrets: 16 | ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} 17 | ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} -------------------------------------------------------------------------------- /.github/workflows/pr-build.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request Build 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | uses: spring-io/spring-github-workflows/.github/workflows/spring-maven-pull-request-build.yml@v5 11 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | run-name: Release current version for branch ${{ github.ref_name }} 7 | 8 | jobs: 9 | release: 10 | permissions: 11 | actions: write 12 | contents: write 13 | issues: write 14 | 15 | uses: spring-io/spring-github-workflows/.github/workflows/spring-artifactory-maven-release.yml@v5 16 | secrets: 17 | GH_ACTIONS_REPO_TOKEN: ${{ secrets.GH_ACTIONS_REPO_TOKEN }} 18 | JF_ARTIFACTORY_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }} 19 | ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }} 20 | ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }} 21 | SPRING_RELEASE_CHAT_WEBHOOK_URL: ${{ secrets.SPRING_RELEASE_GCHAT_WEBHOOK_URL }} 22 | OSSRH_S01_TOKEN_USERNAME: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }} 23 | OSSRH_S01_TOKEN_PASSWORD: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }} 24 | OSSRH_STAGING_PROFILE_NAME: ${{ secrets.OSSRH_STAGING_PROFILE_NAME }} 25 | GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} 26 | GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} -------------------------------------------------------------------------------- /.github/workflows/verify-staged-artifacts.yml: -------------------------------------------------------------------------------- 1 | name: Verify Staged Artifacts 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | releaseVersion: 7 | description: 'Release version like 3.0.0-M1, 3.1.0-RC1, 3.2.0 etc.' 8 | required: true 9 | type: string 10 | 11 | jobs: 12 | verify-staged-with-jfrog: 13 | runs-on: ubuntu-latest 14 | steps: 15 | 16 | - uses: jfrog/setup-jfrog-cli@v4 17 | env: 18 | JF_ENV_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }} 19 | 20 | - name: Download Artifact from Staging Repo 21 | run: | 22 | fileToDownload=org/springframework/cloud/spring-cloud-stream-binder-kinesis/${{ inputs.releaseVersion }}/spring-cloud-stream-binder-kinesis-${{ inputs.releaseVersion }}.jar 23 | jfrog rt download libs-staging-local/$fileToDownload 24 | if [ ! -f $fileToDownload ] 25 | then 26 | echo "::error title=No staged artifact::No spring-cloud-stream-binder-kinesis-${{ inputs.releaseVersion }}.jar in staging repository" 27 | exit 1 28 | fi -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | apps/ 2 | /application.yml 3 | /application.properties 4 | asciidoctor.css 5 | *~ 6 | .#* 7 | *# 8 | target/ 9 | build/ 10 | bin/ 11 | _site/ 12 | .classpath 13 | .project 14 | .settings 15 | .springBeans 16 | .DS_Store 17 | *.sw* 18 | *.iml 19 | *.ipr 20 | *.iws 21 | .idea/ 22 | .factorypath 23 | spring-xd-samples/*/xd 24 | dump.rdb 25 | coverage-error.log 26 | .apt_generated 27 | aws.credentials.properties 28 | /spring-cloud-stream-binder-kinesis/nbproject/ 29 | nb-configuration.xml 30 | -------------------------------------------------------------------------------- /.mvn/jvm.config: -------------------------------------------------------------------------------- 1 | -Xmx1024m -XX:CICompilerCount=1 -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis/1ac3c9fb93d262363faaa63ef11c8336c814b93c/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | https://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | https://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Spring Cloud Stream Binder for AWS Kinesis 2 | 3 | This repository contains the code for the Spring Cloud Stream Binder implementation for AWS Kinesis. 4 | 5 | See https://github.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis/blob/main/spring-cloud-stream-binder-kinesis-docs/src/main/asciidoc/overview.adoc[AWS Kinesis Binder Reference Manual] for more information. 6 | 7 | == Developer Certificate of Origin 8 | 9 | All commits must include a __Signed-off-by__ trailer at the end of each commit message to indicate that the contributor agrees to the Developer Certificate of Origin. 10 | For additional details, please refer to the blog post https://spring.io/blog/2025/01/06/hello-dco-goodbye-cla-simplifying-contributions-to-spring[Hello DCO, Goodbye CLA: Simplifying Contributions to Spring]. 11 | -------------------------------------------------------------------------------- /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 | # http://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 | # Maven2 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 | # 58 | # Look for the Apple JDKs first to preserve the existing behaviour, and then look 59 | # for the new JDKs provided by Oracle. 60 | # 61 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then 62 | # 63 | # Apple JDKs 64 | # 65 | export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home 66 | fi 67 | 68 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then 69 | # 70 | # Apple JDKs 71 | # 72 | export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 73 | fi 74 | 75 | if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then 76 | # 77 | # Oracle JDKs 78 | # 79 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home 80 | fi 81 | 82 | if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then 83 | # 84 | # Apple JDKs 85 | # 86 | export JAVA_HOME=`/usr/libexec/java_home` 87 | fi 88 | ;; 89 | esac 90 | 91 | if [ -z "$JAVA_HOME" ] ; then 92 | if [ -r /etc/gentoo-release ] ; then 93 | JAVA_HOME=`java-config --jre-home` 94 | fi 95 | fi 96 | 97 | if [ -z "$M2_HOME" ] ; then 98 | ## resolve links - $0 may be a link to maven's home 99 | PRG="$0" 100 | 101 | # need this for relative symlinks 102 | while [ -h "$PRG" ] ; do 103 | ls=`ls -ld "$PRG"` 104 | link=`expr "$ls" : '.*-> \(.*\)$'` 105 | if expr "$link" : '/.*' > /dev/null; then 106 | PRG="$link" 107 | else 108 | PRG="`dirname "$PRG"`/$link" 109 | fi 110 | done 111 | 112 | saveddir=`pwd` 113 | 114 | M2_HOME=`dirname "$PRG"`/.. 115 | 116 | # make it fully qualified 117 | M2_HOME=`cd "$M2_HOME" && pwd` 118 | 119 | cd "$saveddir" 120 | # echo Using m2 at $M2_HOME 121 | fi 122 | 123 | # For Cygwin, ensure paths are in UNIX format before anything is touched 124 | if $cygwin ; then 125 | [ -n "$M2_HOME" ] && 126 | M2_HOME=`cygpath --unix "$M2_HOME"` 127 | [ -n "$JAVA_HOME" ] && 128 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 129 | [ -n "$CLASSPATH" ] && 130 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 131 | fi 132 | 133 | # For Migwn, ensure paths are in UNIX format before anything is touched 134 | if $mingw ; then 135 | [ -n "$M2_HOME" ] && 136 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 137 | [ -n "$JAVA_HOME" ] && 138 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 139 | # TODO classpath? 140 | fi 141 | 142 | if [ -z "$JAVA_HOME" ]; then 143 | javaExecutable="`which javac`" 144 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 145 | # readlink(1) is not available as standard on Solaris 10. 146 | readLink=`which readlink` 147 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 148 | if $darwin ; then 149 | javaHome="`dirname \"$javaExecutable\"`" 150 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 151 | else 152 | javaExecutable="`readlink -f \"$javaExecutable\"`" 153 | fi 154 | javaHome="`dirname \"$javaExecutable\"`" 155 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 156 | JAVA_HOME="$javaHome" 157 | export JAVA_HOME 158 | fi 159 | fi 160 | fi 161 | 162 | if [ -z "$JAVACMD" ] ; then 163 | if [ -n "$JAVA_HOME" ] ; then 164 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 165 | # IBM's JDK on AIX uses strange locations for the executables 166 | JAVACMD="$JAVA_HOME/jre/sh/java" 167 | else 168 | JAVACMD="$JAVA_HOME/bin/java" 169 | fi 170 | else 171 | JAVACMD="`which java`" 172 | fi 173 | fi 174 | 175 | if [ ! -x "$JAVACMD" ] ; then 176 | echo "Error: JAVA_HOME is not defined correctly." >&2 177 | echo " We cannot execute $JAVACMD" >&2 178 | exit 1 179 | fi 180 | 181 | if [ -z "$JAVA_HOME" ] ; then 182 | echo "Warning: JAVA_HOME environment variable is not set." 183 | fi 184 | 185 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 186 | 187 | # For Cygwin, switch paths to Windows format before running java 188 | if $cygwin; then 189 | [ -n "$M2_HOME" ] && 190 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 191 | [ -n "$JAVA_HOME" ] && 192 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 193 | [ -n "$CLASSPATH" ] && 194 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 195 | fi 196 | 197 | # traverses directory structure from process work directory to filesystem root 198 | # first directory with .mvn subdirectory is considered project base directory 199 | find_maven_basedir() { 200 | local basedir=$(pwd) 201 | local wdir=$(pwd) 202 | while [ "$wdir" != '/' ] ; do 203 | if [ -d "$wdir"/.mvn ] ; then 204 | basedir=$wdir 205 | break 206 | fi 207 | wdir=$(cd "$wdir/.."; pwd) 208 | done 209 | echo "${basedir}" 210 | } 211 | 212 | # concatenates all lines of a file 213 | concat_lines() { 214 | if [ -f "$1" ]; then 215 | echo "$(tr -s '\n' ' ' < "$1")" 216 | fi 217 | } 218 | 219 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)} 220 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 221 | 222 | # Provide a "standardized" way to retrieve the CLI args that will 223 | # work with both Windows and non-Windows executions. 224 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 225 | export MAVEN_CMD_LINE_ARGS 226 | 227 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 228 | 229 | echo "Running version check" 230 | VERSION=$( sed '\!//' -e 's!.*$!!' ) 231 | echo "The found version is [${VERSION}]" 232 | 233 | if echo $VERSION | egrep -q 'M|RC'; then 234 | echo Activating \"milestone\" profile for version=\"$VERSION\" 235 | echo $MAVEN_ARGS | grep -q milestone || MAVEN_ARGS="$MAVEN_ARGS -Pmilestone" 236 | else 237 | echo Deactivating \"milestone\" profile for version=\"$VERSION\" 238 | echo $MAVEN_ARGS | grep -q milestone && MAVEN_ARGS=$(echo $MAVEN_ARGS | sed -e 's/-Pmilestone//') 239 | fi 240 | 241 | exec "$JAVACMD" \ 242 | $MAVEN_OPTS \ 243 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 244 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 245 | ${WRAPPER_LAUNCHER} ${MAVEN_ARGS} "$@" 246 | -------------------------------------------------------------------------------- /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 http://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 Maven2 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 key stroke 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 enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | org.springframework.cloud 8 | spring-cloud-build 9 | 4.0.6 10 | 11 | 12 | 13 | spring-cloud-stream-binder-kinesis-parent 14 | 4.0.5-SNAPSHOT 15 | pom 16 | 17 | 18 | 17 19 | 4.0.5 20 | 3.0.5 21 | 3.0.9 22 | 2.5.8 23 | 0.15.12 24 | 1.21.1 25 | 26 | 27 | 28 | spring-cloud-stream-binder-kinesis 29 | spring-cloud-stream-binder-kinesis-docs 30 | 31 | 32 | 33 | 34 | 35 | org.testcontainers 36 | testcontainers-bom 37 | ${testcontainers.version} 38 | pom 39 | import 40 | 41 | 42 | 43 | io.awspring.cloud 44 | spring-cloud-aws-dependencies 45 | ${spring-cloud-aws.version} 46 | pom 47 | import 48 | 49 | 50 | 51 | org.springframework.cloud 52 | spring-cloud-stream-dependencies 53 | ${spring-cloud-stream.version} 54 | pom 55 | import 56 | 57 | 58 | 59 | org.springframework.cloud 60 | spring-cloud-stream-binder-kinesis 61 | ${project.version} 62 | 63 | 64 | software.amazon.kinesis 65 | amazon-kinesis-client 66 | 67 | 68 | 69 | 70 | 71 | org.springframework.integration 72 | spring-integration-aws 73 | ${spring-integration-aws.version} 74 | 75 | 76 | software.amazon.kinesis 77 | amazon-kinesis-client 78 | ${amazon-kinesis-client.version} 79 | 80 | 81 | com.amazonaws 82 | amazon-kinesis-producer 83 | ${amazon-kinesis-producer.version} 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-javadoc-plugin 94 | 95 | true 96 | 97 | 98 | 99 | 100 | 101 | 102 | org.apache.maven.plugins 103 | maven-compiler-plugin 104 | 105 | 106 | org.apache.maven.plugins 107 | maven-checkstyle-plugin 108 | 109 | 110 | 111 | 112 | 113 | 114 | org.apache.maven.plugins 115 | maven-checkstyle-plugin 116 | 117 | 118 | 119 | 120 | 121 | 126 | 127 | spring-snapshots 128 | Spring Snapshots 129 | https://repo.spring.io/snapshot 130 | 131 | 132 | spring-milestones 133 | Spring Milestones 134 | https://repo.spring.io/milestone 135 | 136 | 137 | 138 | 139 | spring-snapshots 140 | Spring Snapshots 141 | https://repo.spring.io/snapshot 142 | 143 | 144 | spring-milestones 145 | Spring Milestones 146 | https://repo.spring.io/milestone 147 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/asciidoc/Guardfile: -------------------------------------------------------------------------------- 1 | require 'asciidoctor' 2 | require 'erb' 3 | 4 | guard 'shell' do 5 | watch(/.*\.adoc$/) {|m| 6 | Asciidoctor.render_file('index.adoc', \ 7 | :in_place => true, \ 8 | :safe => Asciidoctor::SafeMode::UNSAFE, \ 9 | :attributes=> { \ 10 | 'source-highlighter' => 'prettify', \ 11 | 'icons' => 'font', \ 12 | 'linkcss'=> 'true', \ 13 | 'copycss' => 'true', \ 14 | 'doctype' => 'book'}) 15 | } 16 | end 17 | 18 | guard 'livereload' do 19 | watch(%r{^.+\.(css|js|html)$}) 20 | end 21 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/asciidoc/building.adoc: -------------------------------------------------------------------------------- 1 | [[building]] 2 | == Building 3 | 4 | :jdkversion: 1.7 5 | 6 | === Basic Compile and Test 7 | 8 | To build the source you will need to install JDK {jdkversion}. 9 | 10 | The build uses the Maven wrapper, so you don't have to install a specific version of Maven. 11 | To enable the tests, you should have Docker running before building. 12 | 13 | The main build command is 14 | 15 | ---- 16 | $ ./mvnw clean install 17 | ---- 18 | 19 | You can also add `-DskipTests` if you like, to avoid running the tests. 20 | 21 | NOTE: You can also install Maven (>=3.5.0) yourself and run the `mvn` command in place of `./mvnw` in the examples below. 22 | If you do that you also might need to add `-P spring` if your local Maven settings do not contain repository declarations for spring pre-release artifacts. 23 | 24 | NOTE: Be aware that you might need to increase the amount of memory available to Maven by setting a `MAVEN_OPTS` environment variable with a value like `-Xmx512m -XX:MaxPermSize=128m`. 25 | We try to cover this in the `.mvn` configuration, so if you find you have to do it to make a build succeed, please raise a ticket to get the settings added to source control. 26 | 27 | 28 | The projects that require middleware generally include a `docker-compose.yml`, so consider using https://docs.docker.com/compose[Docker Compose] to run the middleware servers in Docker containers. 29 | 30 | === Documentation 31 | 32 | There is a "full" profile that will generate documentation. 33 | 34 | === Working with the code 35 | If you don't have an IDE preference we would recommend that you use https://www.springsource.com/developer/sts[Spring Tools Suite] or https://eclipse.org[Eclipse] when working with the code. 36 | We use the https://eclipse.org/m2e/[m2eclipe] eclipse plugin for maven support. 37 | Other IDEs and tools should also work without issue. 38 | 39 | ==== Importing into eclipse with m2eclipse 40 | We recommend the https://eclipse.org/m2e/[m2eclipe] eclipse plugin when working with eclipse. 41 | If you don't already have m2eclipse installed it is available from the "eclipse marketplace". 42 | 43 | Unfortunately m2e does not yet support Maven 3.3, so once the projects are imported into Eclipse you will also need to tell m2eclipse to use the `.settings.xml` file for the projects. 44 | If you do not do this you may see many different errors related to the POMs in the projects. 45 | Open your Eclipse preferences, expand the Maven preferences, and select User Settings. 46 | In the User Settings field click Browse and navigate to the Spring Cloud project you imported selecting the `.settings.xml` file in that project. 47 | Click Apply and then OK to save the preference changes. 48 | 49 | NOTE: Alternatively you can copy the repository settings from https://github.com/spring-cloud/spring-cloud-build/blob/main/.settings.xml[`.settings.xml`] into your own `~/.m2/settings.xml`. 50 | 51 | ==== Importing into eclipse without m2eclipse 52 | If you prefer not to use m2eclipse you can generate eclipse project metadata using the following command: 53 | 54 | [indent=0] 55 | ---- 56 | $ ./mvnw eclipse:eclipse 57 | ---- 58 | 59 | The generated eclipse projects can be imported by selecting `import existing projects` from the `file` menu. 60 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/asciidoc/contributing.adoc: -------------------------------------------------------------------------------- 1 | [[contributing]] 2 | == Contributing 3 | 4 | Spring Cloud is released under the non-restrictive Apache 2.0 license, and follows a very standard GitHub development process, using GitHub tracker for issues and merging pull requests into main. 5 | If you want to contribute even something trivial please do not hesitate, but follow the guidelines below. 6 | 7 | === Sign the Contributor License Agreement 8 | 9 | Before we accept a non-trivial patch or pull request we will need you to sign the https://support.springsource.com/spring_committer_signup[contributor's agreement]. 10 | Signing the contributor's agreement does not grant anyone commit rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. 11 | Active contributors might be asked to join the core team, and given the ability to merge pull requests. 12 | 13 | === Code Conventions and Housekeeping 14 | 15 | None of these is essential for a pull request, but they will all help. 16 | They can also be added after the original pull request but before a merge. 17 | 18 | * Use the Spring Framework code format conventions. If you use Eclipse you can import formatter settings using the `eclipse-code-formatter.xml` file from the https://github.com/spring-cloud/build/tree/main/eclipse-coding-conventions.xml[Spring Cloud Build] project. 19 | If using IntelliJ, you can use the https://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter Plugin] to import the same file. 20 | * Make sure all new `.java` files to have a simple Javadoc class comment with at least an `@author` tag identifying you, and preferably at least a paragraph on what the class is for. 21 | * Add the ASF license header comment to all new `.java` files (copy from existing files in the project) 22 | * Add yourself as an `@author` to the .java files that you modify substantially (more than cosmetic changes). 23 | * Add some Javadocs and, if you change the namespace, some XSD doc elements. 24 | * A few unit tests would help a lot as well -- someone has to do it. 25 | * If no-one else is using your branch, please rebase it against the current main (or other target branch in the main project). 26 | * When writing a commit message please follow https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions], if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit message (where XXXX is the issue number). 27 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/asciidoc/images/kinesis-binder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis/1ac3c9fb93d262363faaa63ef11c8336c814b93c/spring-cloud-stream-binder-kinesis-docs/src/main/asciidoc/images/kinesis-binder.png -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/asciidoc/index-docinfo.xml: -------------------------------------------------------------------------------- 1 | Spring Cloud Stream Kinesis Binder 2 | {spring-cloud-stream-binder-kinesis-version} 3 | 4 | 2017-2021 5 | VMWare, Inc. 6 | 7 | 8 | 9 | Copies of this document may be made for your own use and for distribution to 10 | others, provided that you do not charge any fee for such copies and further 11 | provided that each copy contains this Copyright Notice, whether distributed in 12 | print or electronically. 13 | 14 | 15 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/asciidoc/index.adoc: -------------------------------------------------------------------------------- 1 | [[spring-cloud-stream-binder-kinesis-reference]] 2 | = Spring Cloud Stream AWS Kinesis Binder Reference Guide 3 | Artem Bilan 4 | :doctype: book 5 | :toc: 6 | :toclevels: 4 7 | :source-highlighter: prettify 8 | :numbered: 9 | :icons: font 10 | :hide-uri-scheme: 11 | :spring-cloud-stream-binder-kinesis-repo: snapshot 12 | :github-tag: main 13 | :spring-cloud-stream-binder-kinesis-docs-version: current 14 | :spring-cloud-stream-binder-kinesis-docs: https://docs.spring.io/spring-cloud-stream-binder-kinesis/docs/{spring-cloud-stream-binder-kinesis-docs-version}/reference 15 | :spring-cloud-stream-binder-kinesis-docs-current: https://docs.spring.io/spring-cloud-stream-binder-kinesis/docs/current-SNAPSHOT/reference/html/ 16 | :github-repo: spring-cloud/spring-cloud-stream-binder-aws-kinesis 17 | :github-raw: https://raw.github.com/{github-repo}/{github-tag} 18 | :github-code: https://github.com/{github-repo}/tree/{github-tag} 19 | :github-wiki: https://github.com/{github-repo}/wiki 20 | :github-main-code: https://github.com/{github-repo}/tree/main 21 | :sc-ext: java 22 | // ====================================================================================== 23 | 24 | = Reference Guide 25 | include::overview.adoc[] 26 | 27 | 28 | = Appendices 29 | [appendix] 30 | include::building.adoc[] 31 | [appendix] 32 | include::contributing.adoc[] 33 | 34 | // ====================================================================================== 35 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/css/highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | code highlight CSS resemblign the Eclipse IDE default color schema 3 | @author Costin Leau 4 | */ 5 | 6 | .hl-keyword { 7 | color: #7F0055; 8 | font-weight: bold; 9 | } 10 | 11 | .hl-comment { 12 | color: #3F5F5F; 13 | font-style: italic; 14 | } 15 | 16 | .hl-multiline-comment { 17 | color: #3F5FBF; 18 | font-style: italic; 19 | } 20 | 21 | .hl-tag { 22 | color: #3F7F7F; 23 | } 24 | 25 | .hl-attribute { 26 | color: #7F007F; 27 | } 28 | 29 | .hl-value { 30 | color: #2A00FF; 31 | } 32 | 33 | .hl-string { 34 | color: #2A00FF; 35 | } -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/css/manual-multipage.css: -------------------------------------------------------------------------------- 1 | @IMPORT url("manual.css"); 2 | 3 | body.firstpage { 4 | background: url("../images/background.png") no-repeat center top; 5 | } 6 | 7 | div.part h1 { 8 | border-top: none; 9 | } 10 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/css/manual-singlepage.css: -------------------------------------------------------------------------------- 1 | @IMPORT url("manual.css"); 2 | 3 | body { 4 | background: url("../images/background.png") no-repeat center top; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/css/manual.css: -------------------------------------------------------------------------------- 1 | @IMPORT url("highlight.css"); 2 | 3 | html { 4 | padding: 0pt; 5 | margin: 0pt; 6 | } 7 | 8 | body { 9 | color: #333333; 10 | margin: 15px 30px; 11 | font-family: Helvetica, Arial, Freesans, Clean, Sans-serif; 12 | line-height: 1.6; 13 | -webkit-font-smoothing: antialiased; 14 | } 15 | 16 | code { 17 | font-size: 16px; 18 | font-family: Consolas, "Liberation Mono", Courier, monospace; 19 | } 20 | 21 | :not(a)>code { 22 | color: #6D180B; 23 | } 24 | 25 | :not(pre)>code { 26 | background-color: #F2F2F2; 27 | border: 1px solid #CCCCCC; 28 | border-radius: 4px; 29 | padding: 1px 3px 0; 30 | text-shadow: none; 31 | white-space: nowrap; 32 | } 33 | 34 | body>*:first-child { 35 | margin-top: 0 !important; 36 | } 37 | 38 | div { 39 | margin: 0pt; 40 | } 41 | 42 | hr { 43 | border: 1px solid #CCCCCC; 44 | background: #CCCCCC; 45 | } 46 | 47 | h1,h2,h3,h4,h5,h6 { 48 | color: #000000; 49 | cursor: text; 50 | font-weight: bold; 51 | margin: 30px 0 10px; 52 | padding: 0; 53 | } 54 | 55 | h1,h2,h3 { 56 | margin: 40px 0 10px; 57 | } 58 | 59 | h1 { 60 | margin: 70px 0 30px; 61 | padding-top: 20px; 62 | } 63 | 64 | div.part h1 { 65 | border-top: 1px dotted #CCCCCC; 66 | } 67 | 68 | h1,h1 code { 69 | font-size: 32px; 70 | } 71 | 72 | h2,h2 code { 73 | font-size: 24px; 74 | } 75 | 76 | h3,h3 code { 77 | font-size: 20px; 78 | } 79 | 80 | h4,h1 code,h5,h5 code,h6,h6 code { 81 | font-size: 18px; 82 | } 83 | 84 | div.book,div.chapter,div.appendix,div.part,div.preface { 85 | min-width: 300px; 86 | max-width: 1200px; 87 | margin: 0 auto; 88 | } 89 | 90 | p.releaseinfo { 91 | font-weight: bold; 92 | margin-bottom: 40px; 93 | margin-top: 40px; 94 | } 95 | 96 | div.authorgroup { 97 | line-height: 1; 98 | } 99 | 100 | p.copyright { 101 | line-height: 1; 102 | margin-bottom: -5px; 103 | } 104 | 105 | .legalnotice p { 106 | font-style: italic; 107 | font-size: 14px; 108 | line-height: 1; 109 | } 110 | 111 | div.titlepage+p,div.titlepage+p { 112 | margin-top: 0; 113 | } 114 | 115 | pre { 116 | line-height: 1.0; 117 | color: black; 118 | } 119 | 120 | a { 121 | color: #4183C4; 122 | text-decoration: none; 123 | } 124 | 125 | p { 126 | margin: 15px 0; 127 | text-align: left; 128 | } 129 | 130 | ul,ol { 131 | padding-left: 30px; 132 | } 133 | 134 | li p { 135 | margin: 0; 136 | } 137 | 138 | div.table { 139 | margin: 1em; 140 | padding: 0.5em; 141 | text-align: center; 142 | } 143 | 144 | div.table table,div.informaltable table { 145 | display: table; 146 | width: 100%; 147 | } 148 | 149 | div.table td { 150 | padding-left: 7px; 151 | padding-right: 7px; 152 | } 153 | 154 | .sidebar { 155 | line-height: 1.4; 156 | padding: 0 20px; 157 | background-color: #F8F8F8; 158 | border: 1px solid #CCCCCC; 159 | border-radius: 3px 3px 3px 3px; 160 | } 161 | 162 | .sidebar p.title { 163 | color: #6D180B; 164 | } 165 | 166 | pre.programlisting,pre.screen { 167 | font-size: 15px; 168 | padding: 6px 10px; 169 | background-color: #F8F8F8; 170 | border: 1px solid #CCCCCC; 171 | border-radius: 3px 3px 3px 3px; 172 | clear: both; 173 | overflow: auto; 174 | line-height: 1.4; 175 | font-family: Consolas, "Liberation Mono", Courier, monospace; 176 | } 177 | 178 | table { 179 | border-collapse: collapse; 180 | border-spacing: 0; 181 | border: 1px solid #DDDDDD !important; 182 | border-radius: 4px !important; 183 | border-collapse: separate !important; 184 | line-height: 1.6; 185 | } 186 | 187 | table thead { 188 | background: #F5F5F5; 189 | } 190 | 191 | table tr { 192 | border: none; 193 | border-bottom: none; 194 | } 195 | 196 | table th { 197 | font-weight: bold; 198 | } 199 | 200 | table th,table td { 201 | border: none !important; 202 | padding: 6px 13px; 203 | } 204 | 205 | table tr:nth-child(2n) { 206 | background-color: #F8F8F8; 207 | } 208 | 209 | td p { 210 | margin: 0 0 15px 0; 211 | } 212 | 213 | div.table-contents td p { 214 | margin: 0; 215 | } 216 | 217 | div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist * 218 | { 219 | border: none !important; 220 | background: none !important; 221 | margin: 0; 222 | } 223 | 224 | div.important p,div.note p,div.tip p,div.warning p { 225 | color: #6F6F6F; 226 | line-height: 1.6; 227 | } 228 | 229 | div.important code,div.note code,div.tip code,div.warning code { 230 | background-color: #F2F2F2 !important; 231 | border: 1px solid #CCCCCC !important; 232 | border-radius: 4px !important; 233 | padding: 1px 3px 0 !important; 234 | text-shadow: none !important; 235 | white-space: nowrap !important; 236 | } 237 | 238 | .note th,.tip th,.warning th { 239 | display: none; 240 | } 241 | 242 | .note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td 243 | { 244 | border-right: 1px solid #CCCCCC !important; 245 | padding-top: 10px; 246 | } 247 | 248 | div.calloutlist p,div.calloutlist td { 249 | padding: 0; 250 | margin: 0; 251 | } 252 | 253 | div.calloutlist>table>tbody>tr>td:first-child { 254 | padding-left: 10px; 255 | width: 30px !important; 256 | } 257 | 258 | div.important,div.note,div.tip,div.warning { 259 | margin-left: 0px !important; 260 | margin-right: 20px !important; 261 | margin-top: 20px; 262 | margin-bottom: 20px; 263 | padding-top: 10px; 264 | padding-bottom: 10px; 265 | } 266 | 267 | div.toc { 268 | line-height: 1.2; 269 | } 270 | 271 | dl,dt { 272 | margin-top: 1px; 273 | margin-bottom: 0; 274 | } 275 | 276 | div.toc>dl>dt { 277 | font-size: 32px; 278 | font-weight: bold; 279 | margin: 30px 0 10px 0; 280 | display: block; 281 | } 282 | 283 | div.toc>dl>dd>dl>dt { 284 | font-size: 24px; 285 | font-weight: bold; 286 | margin: 20px 0 10px 0; 287 | display: block; 288 | } 289 | 290 | div.toc>dl>dd>dl>dd>dl>dt { 291 | font-weight: bold; 292 | font-size: 20px; 293 | margin: 10px 0 0 0; 294 | } 295 | 296 | tbody.footnotes * { 297 | border: none !important; 298 | } 299 | 300 | div.footnote p { 301 | margin: 0; 302 | line-height: 1; 303 | } 304 | 305 | div.footnote p sup { 306 | margin-right: 6px; 307 | vertical-align: middle; 308 | } 309 | 310 | div.navheader { 311 | border-bottom: 1px solid #CCCCCC; 312 | } 313 | 314 | div.navfooter { 315 | border-top: 1px solid #CCCCCC; 316 | } 317 | 318 | .title { 319 | margin-left: -1em; 320 | padding-left: 1em; 321 | } 322 | 323 | .title>a { 324 | position: absolute; 325 | visibility: hidden; 326 | display: block; 327 | font-size: 0.85em; 328 | margin-top: 0.05em; 329 | margin-left: -1em; 330 | vertical-align: text-top; 331 | color: black; 332 | } 333 | 334 | .title>a:before { 335 | content: "\00A7"; 336 | } 337 | 338 | .title:hover>a,.title>a:hover,.title:hover>a:hover { 339 | visibility: visible; 340 | } 341 | 342 | .title:focus>a,.title>a:focus,.title:focus>a:focus { 343 | outline: 0; 344 | } 345 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis/1ac3c9fb93d262363faaa63ef11c8336c814b93c/spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/background.png -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/caution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis/1ac3c9fb93d262363faaa63ef11c8336c814b93c/spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/caution.png -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/important.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis/1ac3c9fb93d262363faaa63ef11c8336c814b93c/spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/important.png -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis/1ac3c9fb93d262363faaa63ef11c8336c814b93c/spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/logo.png -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis/1ac3c9fb93d262363faaa63ef11c8336c814b93c/spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/note.png -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/tip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis/1ac3c9fb93d262363faaa63ef11c8336c814b93c/spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/tip.png -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-cloud/spring-cloud-stream-binder-aws-kinesis/1ac3c9fb93d262363faaa63ef11c8336c814b93c/spring-cloud-stream-binder-kinesis-docs/src/main/docbook/images/warning.png -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/common.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 27 | 28 | 29 | 1 30 | 0 31 | 1 32 | 33 | 34 | 35 | images/ 36 | .png 37 | 38 | 39 | book toc,title 40 | 3 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/epub.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/html-multipage.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | css/manual-multipage.css 29 | 30 | '5' 31 | '1' 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | firstpage 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/html-singlepage.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | css/manual-singlepage.css 29 | 30 | 31 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/html.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 27 | 28 | 29 | 30 | 31 | 32 | 1 33 | 34 | 35 | 1 36 | 37 | 38 | 39 | 120 40 | images/callouts/ 41 | .png 42 | 43 | 44 | text/css 45 | 46 | text-align: left 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | , 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 |
114 |

Authors

115 | 116 |
117 |
118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | # 135 | 136 | 137 | 138 | 139 | 140 | 141 |
142 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/asciidoc-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | //// 10 | //// 11 | 12 | 13 | // 14 | 15 | 16 | 17 | ^(={1,6} .+)$ 18 | 19 | MULTILINE 20 | 21 | 22 | ^(\.[^\.\s].+)$ 23 | 24 | MULTILINE 25 | 26 | 27 | ^(:!?\w.*?:) 28 | 29 | MULTILINE 30 | 31 | 32 | ^(-|\*{1,5}|\d*\.{1,5})(?= .+$) 33 | 34 | MULTILINE 35 | 36 | 37 | ^(\[.+\])$ 38 | 39 | MULTILINE 40 | 41 | 42 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/bourne-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | # 29 | 30 | << 31 | ' 32 | " 33 | - 34 | 35 | 36 | 37 | 38 | " 39 | \ 40 | 41 | 42 | ' 43 | \ 44 | 45 | 46 | 47 | 0x 48 | 49 | 50 | 51 | . 52 | 53 | 54 | 55 | 56 | 57 | if 58 | then 59 | else 60 | elif 61 | fi 62 | case 63 | esac 64 | for 65 | while 66 | until 67 | do 68 | done 69 | 70 | exec 71 | shift 72 | exit 73 | times 74 | break 75 | export 76 | trap 77 | continue 78 | readonly 79 | wait 80 | eval 81 | return 82 | 83 | cd 84 | echo 85 | hash 86 | pwd 87 | read 88 | set 89 | test 90 | type 91 | ulimit 92 | umask 93 | unset 94 | 95 | 96 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/c-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 29 | 30 | 31 | /** 32 | */ 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | /* 41 | */ 42 | 43 | // 44 | 45 | 46 | # 47 | \ 48 | 49 | 50 | 51 | 52 | " 53 | \ 54 | 55 | 56 | ' 57 | \ 58 | 59 | 60 | 0x 61 | ul 62 | lu 63 | u 64 | l 65 | 66 | 67 | 68 | . 69 | 70 | e 71 | ul 72 | lu 73 | u 74 | f 75 | l 76 | 77 | 78 | 79 | auto 80 | _Bool 81 | break 82 | case 83 | char 84 | _Complex 85 | const 86 | continue 87 | default 88 | do 89 | double 90 | else 91 | enum 92 | extern 93 | float 94 | for 95 | goto 96 | if 97 | _Imaginary 98 | inline 99 | int 100 | long 101 | register 102 | restrict 103 | return 104 | short 105 | signed 106 | sizeof 107 | static 108 | struct 109 | switch 110 | typedef 111 | union 112 | unsigned 113 | void 114 | volatile 115 | while 116 | 117 | 118 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/cpp-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | /** 34 | */ 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | /* 43 | */ 44 | 45 | // 46 | 47 | 48 | # 49 | \ 50 | 51 | 52 | 53 | 54 | " 55 | \ 56 | 57 | 58 | ' 59 | \ 60 | 61 | 62 | 0x 63 | ul 64 | lu 65 | u 66 | l 67 | 68 | 69 | 70 | . 71 | 72 | e 73 | ul 74 | lu 75 | u 76 | f 77 | l 78 | 79 | 80 | 81 | 82 | auto 83 | _Bool 84 | break 85 | case 86 | char 87 | _Complex 88 | const 89 | continue 90 | default 91 | do 92 | double 93 | else 94 | enum 95 | extern 96 | float 97 | for 98 | goto 99 | if 100 | _Imaginary 101 | inline 102 | int 103 | long 104 | register 105 | restrict 106 | return 107 | short 108 | signed 109 | sizeof 110 | static 111 | struct 112 | switch 113 | typedef 114 | union 115 | unsigned 116 | void 117 | volatile 118 | while 119 | 120 | asm 121 | dynamic_cast 122 | namespace 123 | reinterpret_cast 124 | try 125 | bool 126 | explicit 127 | new 128 | static_cast 129 | typeid 130 | catch 131 | false 132 | operator 133 | template 134 | typename 135 | class 136 | friend 137 | private 138 | this 139 | using 140 | const_cast 141 | inline 142 | public 143 | throw 144 | virtual 145 | delete 146 | mutable 147 | protected 148 | true 149 | wchar_t 150 | 151 | 152 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/csharp-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | /** 34 | */ 35 | 36 | 37 | 38 | /// 39 | 40 | 41 | 42 | /* 43 | */ 44 | 45 | // 46 | 47 | 48 | [ 49 | ] 50 | ( 51 | ) 52 | 53 | 54 | 55 | # 56 | \ 57 | 58 | 59 | 60 | 61 | 62 | @" 63 | " 64 | \ 65 | 66 | 67 | 68 | " 69 | \ 70 | 71 | 72 | ' 73 | \ 74 | 75 | 76 | 0x 77 | ul 78 | lu 79 | u 80 | l 81 | 82 | 83 | 84 | . 85 | 86 | e 87 | ul 88 | lu 89 | u 90 | f 91 | d 92 | m 93 | l 94 | 95 | 96 | 97 | abstract 98 | as 99 | base 100 | bool 101 | break 102 | byte 103 | case 104 | catch 105 | char 106 | checked 107 | class 108 | const 109 | continue 110 | decimal 111 | default 112 | delegate 113 | do 114 | double 115 | else 116 | enum 117 | event 118 | explicit 119 | extern 120 | false 121 | finally 122 | fixed 123 | float 124 | for 125 | foreach 126 | goto 127 | if 128 | implicit 129 | in 130 | int 131 | interface 132 | internal 133 | is 134 | lock 135 | long 136 | namespace 137 | new 138 | null 139 | object 140 | operator 141 | out 142 | override 143 | params 144 | private 145 | protected 146 | public 147 | readonly 148 | ref 149 | return 150 | sbyte 151 | sealed 152 | short 153 | sizeof 154 | stackalloc 155 | static 156 | string 157 | struct 158 | switch 159 | this 160 | throw 161 | true 162 | try 163 | typeof 164 | uint 165 | ulong 166 | unchecked 167 | unsafe 168 | ushort 169 | using 170 | virtual 171 | void 172 | volatile 173 | while 174 | 175 | 176 | 177 | add 178 | alias 179 | from 180 | get 181 | global 182 | group 183 | into 184 | join 185 | orderby 186 | partial 187 | remove 188 | select 189 | set 190 | value 191 | where 192 | yield 193 | 194 | 195 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/css-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 32 | 33 | 34 | /* 35 | */ 36 | 37 | 38 | " 39 | \ 40 | 41 | 42 | 43 | ' 44 | \ 45 | 46 | 47 | 48 | . 49 | 50 | 51 | 52 | @charset 53 | @import 54 | @media 55 | @page 56 | 57 | 58 | 59 | - 60 | azimuth 61 | background-attachment 62 | background-color 63 | background-image 64 | background-position 65 | background-repeat 66 | background 67 | border-collapse 68 | border-color 69 | border-spacing 70 | border-style 71 | border-top 72 | border-right 73 | border-bottom 74 | border-left 75 | border-top-color 76 | border-right-color 77 | border-bottom-color 78 | border-left-color 79 | border-top-style 80 | border-right-style 81 | border-bottom-style 82 | border-left-style 83 | border-top-width 84 | border-right-width 85 | border-bottom-width 86 | border-left-width 87 | border-width 88 | border 89 | bottom 90 | caption-side 91 | clear 92 | clip 93 | color 94 | content 95 | counter-increment 96 | counter-reset 97 | cue-after 98 | cue-before 99 | cue 100 | cursor 101 | direction 102 | display 103 | elevation 104 | empty-cells 105 | float 106 | font-family 107 | font-size 108 | font-style 109 | font-variant 110 | font-weight 111 | font 112 | height 113 | left 114 | letter-spacing 115 | line-height 116 | list-style-image 117 | list-style-position 118 | list-style-type 119 | list-style 120 | margin-right 121 | margin-left 122 | margin-top 123 | margin-bottom 124 | margin 125 | max-height 126 | max-width 127 | min-height 128 | min-width 129 | orphans 130 | outline-color 131 | outline-style 132 | outline-width 133 | outline 134 | overflow 135 | padding-top 136 | padding-right 137 | padding-bottom 138 | padding-left 139 | padding 140 | page-break-after 141 | page-break-before 142 | page-break-inside 143 | pause-after 144 | pause-before 145 | pause 146 | pitch-range 147 | pitch 148 | play-during 149 | position 150 | quotes 151 | richness 152 | right 153 | speak-header 154 | speak-numeral 155 | speak-punctuation 156 | speak 157 | speech-rate 158 | stress 159 | table-layout 160 | text-align 161 | text-decoration 162 | text-indent 163 | text-transform 164 | top 165 | unicode-bidi 166 | vertical-align 167 | visibility 168 | voice-family 169 | volume 170 | white-space 171 | widows 172 | width 173 | word-spacing 174 | z-index 175 | 176 | 177 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/html-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | a 17 | abbr 18 | address 19 | area 20 | article 21 | aside 22 | audio 23 | b 24 | base 25 | bdi 26 | blockquote 27 | body 28 | br 29 | button 30 | caption 31 | canvas 32 | cite 33 | code 34 | command 35 | col 36 | colgroup 37 | dd 38 | del 39 | dialog 40 | div 41 | dl 42 | dt 43 | em 44 | embed 45 | fieldset 46 | figcaption 47 | figure 48 | font 49 | form 50 | footer 51 | h1 52 | h2 53 | h3 54 | h4 55 | h5 56 | h6 57 | head 58 | header 59 | hr 60 | html 61 | i 62 | iframe 63 | img 64 | input 65 | ins 66 | kbd 67 | label 68 | legend 69 | li 70 | link 71 | map 72 | mark 73 | menu 74 | menu 75 | meta 76 | nav 77 | noscript 78 | object 79 | ol 80 | optgroup 81 | option 82 | p 83 | param 84 | pre 85 | q 86 | samp 87 | script 88 | section 89 | select 90 | small 91 | source 92 | span 93 | strong 94 | style 95 | sub 96 | summary 97 | sup 98 | table 99 | tbody 100 | td 101 | textarea 102 | tfoot 103 | th 104 | thead 105 | time 106 | title 107 | tr 108 | track 109 | u 110 | ul 111 | var 112 | video 113 | wbr 114 | xmp 115 | 116 | 117 | 118 | 119 | xsl: 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/ini-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | ; 33 | 34 | 35 | ^(\[.+\]\s*)$ 36 | 37 | MULTILINE 38 | 39 | 40 | 41 | ^(.+)(?==) 42 | 43 | MULTILINE 44 | 45 | 46 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/java-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | /** 34 | */ 35 | 36 | 37 | 38 | /* 39 | */ 40 | 41 | // 42 | 43 | " 44 | \ 45 | 46 | 47 | ' 48 | \ 49 | 50 | 51 | @ 52 | ( 53 | ) 54 | 55 | 56 | 0x 57 | 58 | 59 | 60 | . 61 | e 62 | f 63 | d 64 | l 65 | 66 | 67 | 68 | abstract 69 | boolean 70 | break 71 | byte 72 | case 73 | catch 74 | char 75 | class 76 | const 77 | continue 78 | default 79 | do 80 | double 81 | else 82 | extends 83 | final 84 | finally 85 | float 86 | for 87 | goto 88 | if 89 | implements 90 | import 91 | instanceof 92 | int 93 | interface 94 | long 95 | native 96 | new 97 | package 98 | private 99 | protected 100 | public 101 | return 102 | short 103 | static 104 | strictfp 105 | super 106 | switch 107 | synchronized 108 | this 109 | throw 110 | throws 111 | transient 112 | try 113 | void 114 | volatile 115 | while 116 | 117 | 118 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/javascript-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | /* 34 | */ 35 | 36 | // 37 | 38 | " 39 | \ 40 | 41 | 42 | ' 43 | \ 44 | 45 | 46 | 0x 47 | 48 | 49 | 50 | . 51 | e 52 | 53 | 54 | 55 | break 56 | case 57 | catch 58 | continue 59 | default 60 | delete 61 | do 62 | else 63 | finally 64 | for 65 | function 66 | if 67 | in 68 | instanceof 69 | new 70 | return 71 | switch 72 | this 73 | throw 74 | try 75 | typeof 76 | var 77 | void 78 | while 79 | with 80 | 81 | abstract 82 | boolean 83 | byte 84 | char 85 | class 86 | const 87 | debugger 88 | double 89 | enum 90 | export 91 | extends 92 | final 93 | float 94 | goto 95 | implements 96 | import 97 | int 98 | interface 99 | long 100 | native 101 | package 102 | private 103 | protected 104 | public 105 | short 106 | static 107 | super 108 | synchronized 109 | throws 110 | transient 111 | volatile 112 | 113 | 114 | prototype 115 | 116 | Array 117 | Boolean 118 | Date 119 | Error 120 | EvalError 121 | Function 122 | Math 123 | Number 124 | Object 125 | RangeError 126 | ReferenceError 127 | RegExp 128 | String 129 | SyntaxError 130 | TypeError 131 | URIError 132 | 133 | decodeURI 134 | decodeURIComponent 135 | encodeURI 136 | encodeURIComponent 137 | eval 138 | isFinite 139 | isNaN 140 | parseFloat 141 | parseInt 142 | 143 | Infinity 144 | NaN 145 | undefined 146 | 147 | 148 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/json-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4 | 5 | " 6 | \ 7 | 8 | 9 | ' 10 | \ 11 | 12 | 13 | @ 14 | ( 15 | ) 16 | 17 | 18 | . 19 | e 20 | f 21 | d 22 | l 23 | 24 | 25 | 26 | true 27 | false 28 | 29 | 30 | { 31 | } 32 | , 33 | [ 34 | ] 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/perl-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | # 33 | 34 | << 35 | ' 36 | " 37 | 38 | 39 | 40 | " 41 | \ 42 | 43 | 44 | ' 45 | \ 46 | 47 | 48 | 49 | 0x 50 | 51 | 52 | 53 | . 54 | 55 | 56 | 57 | 58 | if 59 | unless 60 | while 61 | until 62 | foreach 63 | else 64 | elsif 65 | for 66 | when 67 | default 68 | given 69 | 70 | caller 71 | continue 72 | die 73 | do 74 | dump 75 | eval 76 | exit 77 | goto 78 | last 79 | next 80 | redo 81 | return 82 | sub 83 | wantarray 84 | 85 | caller 86 | import 87 | local 88 | my 89 | package 90 | use 91 | 92 | do 93 | import 94 | no 95 | package 96 | require 97 | use 98 | 99 | bless 100 | dbmclose 101 | dbmopen 102 | package 103 | ref 104 | tie 105 | tied 106 | untie 107 | use 108 | 109 | and 110 | or 111 | not 112 | eq 113 | ne 114 | lt 115 | gt 116 | le 117 | ge 118 | cmp 119 | 120 | 121 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/php-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | /** 34 | */ 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | /* 43 | */ 44 | 45 | // 46 | # 47 | 48 | " 49 | \ 50 | 51 | 52 | 53 | ' 54 | \ 55 | 56 | 57 | 58 | <<< 59 | 60 | 61 | 0x 62 | 63 | 64 | 65 | . 66 | e 67 | 68 | 69 | 70 | and 71 | or 72 | xor 73 | __FILE__ 74 | exception 75 | __LINE__ 76 | array 77 | as 78 | break 79 | case 80 | class 81 | const 82 | continue 83 | declare 84 | default 85 | die 86 | do 87 | echo 88 | else 89 | elseif 90 | empty 91 | enddeclare 92 | endfor 93 | endforeach 94 | endif 95 | endswitch 96 | endwhile 97 | eval 98 | exit 99 | extends 100 | for 101 | foreach 102 | function 103 | global 104 | if 105 | include 106 | include_once 107 | isset 108 | list 109 | new 110 | print 111 | require 112 | require_once 113 | return 114 | static 115 | switch 116 | unset 117 | use 118 | var 119 | while 120 | __FUNCTION__ 121 | __CLASS__ 122 | __METHOD__ 123 | final 124 | php_user_filter 125 | interface 126 | implements 127 | extends 128 | public 129 | private 130 | protected 131 | abstract 132 | clone 133 | try 134 | catch 135 | throw 136 | cfunction 137 | old_function 138 | true 139 | false 140 | 141 | namespace 142 | __NAMESPACE__ 143 | goto 144 | __DIR__ 145 | 146 | 147 | 148 | 149 | ?> 150 | <?php 151 | <?= 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/properties-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | # 33 | 34 | ^(.+?)(?==|:) 35 | 36 | MULTILINE 37 | 38 | 39 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/python-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | 33 | 34 | @ 35 | ( 36 | ) 37 | 38 | # 39 | 40 | """ 41 | 42 | 43 | 44 | ''' 45 | 46 | 47 | 48 | " 49 | \ 50 | 51 | 52 | ' 53 | \ 54 | 55 | 56 | 0x 57 | l 58 | 59 | 60 | 61 | . 62 | 63 | e 64 | l 65 | 66 | 67 | 68 | and 69 | del 70 | from 71 | not 72 | while 73 | as 74 | elif 75 | global 76 | or 77 | with 78 | assert 79 | else 80 | if 81 | pass 82 | yield 83 | break 84 | except 85 | import 86 | print 87 | class 88 | exec 89 | in 90 | raise 91 | continue 92 | finally 93 | is 94 | return 95 | def 96 | for 97 | lambda 98 | try 99 | 100 | 101 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/ruby-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | # 33 | 34 | << 35 | 36 | 37 | 38 | " 39 | \ 40 | 41 | 42 | %Q{ 43 | } 44 | \ 45 | 46 | 47 | %/ 48 | / 49 | \ 50 | 51 | 52 | ' 53 | \ 54 | 55 | 56 | %q{ 57 | } 58 | \ 59 | 60 | 61 | 0x 62 | 63 | 64 | 65 | . 66 | e 67 | 68 | 69 | 70 | alias 71 | and 72 | BEGIN 73 | begin 74 | break 75 | case 76 | class 77 | def 78 | defined 79 | do 80 | else 81 | elsif 82 | END 83 | end 84 | ensure 85 | false 86 | for 87 | if 88 | in 89 | module 90 | next 91 | nil 92 | not 93 | or 94 | redo 95 | rescue 96 | retry 97 | return 98 | self 99 | super 100 | then 101 | true 102 | undef 103 | unless 104 | until 105 | when 106 | while 107 | yield 108 | 109 | 110 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/docbook/xsl/xslthl/yaml-hl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4 | 5 | " 6 | \ 7 | 8 | 9 | ' 10 | \ 11 | 12 | 13 | @ 14 | ( 15 | ) 16 | 17 | 18 | . 19 | e 20 | f 21 | d 22 | l 23 | 24 | 25 | 26 | true 27 | false 28 | 29 | 30 | { 31 | } 32 | , 33 | [ 34 | ] 35 | 36 | 37 | 38 | ^(---)$ 39 | 40 | MULTILINE 41 | 42 | 43 | ^(.+?)(?==|:) 44 | 45 | MULTILINE 46 | 47 | 48 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis-docs/src/main/xslt/dependencyVersions.xsl: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | |=== 10 | | Group ID | Artifact ID | Version 11 | 12 | 13 | 14 | 15 | | ` 16 | 17 | ` 18 | | ` 19 | 20 | ` 21 | | 22 | 23 | 24 | 25 | |=== 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | org.springframework.cloud 8 | spring-cloud-stream-binder-kinesis-parent 9 | 4.0.5-SNAPSHOT 10 | 11 | 12 | spring-cloud-stream-binder-kinesis 13 | 14 | jar 15 | spring-cloud-stream-binder-kinesis 16 | AWS Kinesis Binder Implementation 17 | 18 | 19 | 20 | software.amazon.kinesis 21 | amazon-kinesis-client 22 | 23 | 24 | software.amazon.awssdk 25 | apache-client 26 | 27 | 28 | commons-logging 29 | commons-logging 30 | 31 | 32 | 33 | 34 | com.amazonaws 35 | amazon-kinesis-producer 36 | 37 | 38 | commons-logging 39 | commons-logging 40 | 41 | 42 | 43 | 44 | org.springframework.integration 45 | spring-integration-aws 46 | 47 | 48 | org.springframework.cloud 49 | spring-cloud-stream 50 | 51 | 52 | io.awspring.cloud 53 | spring-cloud-aws-starter 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-configuration-processor 59 | true 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-actuator 65 | true 66 | 67 | 68 | 69 | org.springframework.cloud 70 | spring-cloud-stream-test-support 71 | test 72 | 73 | 74 | 75 | io.micrometer 76 | micrometer-tracing-integration-test 77 | test 78 | 79 | 80 | io.opentelemetry 81 | * 82 | 83 | 84 | com.wavefront 85 | * 86 | 87 | 88 | io.micrometer 89 | micrometer-tracing-bridge-otel 90 | 91 | 92 | 93 | 94 | 95 | org.testcontainers 96 | junit-jupiter 97 | test 98 | 99 | 100 | org.testcontainers 101 | localstack 102 | test 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/KinesisBinderHealthIndicator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 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 | 17 | package org.springframework.cloud.stream.binder.kinesis; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.concurrent.CompletionException; 22 | import java.util.concurrent.TimeUnit; 23 | 24 | import software.amazon.awssdk.services.kinesis.KinesisAsyncClient; 25 | import software.amazon.awssdk.services.kinesis.model.LimitExceededException; 26 | 27 | import org.springframework.boot.actuate.health.Health; 28 | import org.springframework.boot.actuate.health.HealthIndicator; 29 | 30 | /** 31 | * @author Artem Bilan 32 | * 33 | * @since 2.0 34 | */ 35 | public class KinesisBinderHealthIndicator implements HealthIndicator { 36 | 37 | private final KinesisMessageChannelBinder kinesisMessageChannelBinder; 38 | 39 | public KinesisBinderHealthIndicator(KinesisMessageChannelBinder kinesisMessageChannelBinder) { 40 | this.kinesisMessageChannelBinder = kinesisMessageChannelBinder; 41 | } 42 | 43 | @Override 44 | public Health health() { 45 | KinesisAsyncClient amazonKinesis = this.kinesisMessageChannelBinder.getAmazonKinesis(); 46 | List streamsInUse = new ArrayList<>(this.kinesisMessageChannelBinder.getStreamsInUse()); 47 | for (String stream : streamsInUse) { 48 | while (true) { 49 | try { 50 | amazonKinesis.listShards(request -> request.streamName(stream).maxResults(1)).join(); 51 | break; 52 | } 53 | catch (CompletionException ex) { 54 | Throwable cause = ex.getCause(); 55 | if (cause instanceof LimitExceededException) { 56 | try { 57 | TimeUnit.SECONDS.sleep(1); 58 | } 59 | catch (InterruptedException e) { 60 | Thread.currentThread().interrupt(); 61 | return Health.down().withException(ex).build(); 62 | } 63 | } 64 | else { 65 | return Health.down().withException(ex).build(); 66 | } 67 | } 68 | } 69 | } 70 | return Health.up().build(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/LegacyEmbeddedHeadersSupportBytesMessageMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2023 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 | 17 | package org.springframework.cloud.stream.binder.kinesis; 18 | 19 | import java.util.Map; 20 | 21 | import org.springframework.cloud.stream.binder.EmbeddedHeaderUtils; 22 | import org.springframework.cloud.stream.binder.MessageValues; 23 | import org.springframework.integration.mapping.BytesMessageMapper; 24 | import org.springframework.integration.support.json.EmbeddedJsonHeadersMessageMapper; 25 | import org.springframework.lang.Nullable; 26 | import org.springframework.messaging.Message; 27 | import org.springframework.messaging.MessageHeaders; 28 | 29 | /** 30 | * The {@link BytesMessageMapper} implementation to support an embedded headers 31 | * format from {@link EmbeddedHeaderUtils} to be able to receive and deserialize 32 | * properly messages published from the previous binder version. 33 | * The current Kinesis binder deals with embedded headers format from {@link EmbeddedJsonHeadersMessageMapper}. 34 | *

35 | * The {@link #toMessage(byte[], Map)} first checks for the {@link EmbeddedHeaderUtils#mayHaveEmbeddedHeaders(byte[])} 36 | * and tries to deserialize embedded headers via {@link EmbeddedHeaderUtils#extractHeaders(byte[])}, 37 | * then it falls back to the {@link EmbeddedJsonHeadersMessageMapper} for a new format. 38 | * 39 | * @author Artem Bilan 40 | * 41 | * @since 4.0 42 | */ 43 | class LegacyEmbeddedHeadersSupportBytesMessageMapper implements BytesMessageMapper { 44 | 45 | private final EmbeddedJsonHeadersMessageMapper delegate; 46 | 47 | private final String[] headersToEmbed; 48 | 49 | private final boolean legacyEmbeddedHeadersFormat; 50 | 51 | LegacyEmbeddedHeadersSupportBytesMessageMapper(boolean legacyEmbeddedHeadersFormat, String[] headersToEmbed) { 52 | this.legacyEmbeddedHeadersFormat = legacyEmbeddedHeadersFormat; 53 | this.delegate = new EmbeddedJsonHeadersMessageMapper(headersToEmbed); 54 | this.headersToEmbed = headersToEmbed; 55 | } 56 | 57 | @Override 58 | public Message toMessage(byte[] payload, @Nullable Map headers) { 59 | if (EmbeddedHeaderUtils.mayHaveEmbeddedHeaders(payload)) { 60 | MessageValues messageValues; 61 | try { 62 | messageValues = EmbeddedHeaderUtils.extractHeaders(payload); 63 | if (headers != null) { 64 | messageValues.copyHeadersIfAbsent(headers); 65 | } 66 | return messageValues.toMessage(); 67 | } 68 | catch (Exception ex) { 69 | /* 70 | * Ignore an exception since we don't know for sure that it 71 | * really is a message with embedded headers, it just meets the 72 | * criteria in EmbeddedHeaderUtils.mayHaveEmbeddedHeaders(). 73 | * Fall back to the EmbeddedJsonHeadersMessageMapper delegate for a new format attempt. 74 | */ 75 | } 76 | } 77 | 78 | return this.delegate.toMessage(payload, headers); 79 | } 80 | 81 | @Override 82 | public byte[] fromMessage(Message message) { 83 | if (this.legacyEmbeddedHeadersFormat) { 84 | MessageValues transformed = new MessageValues(message); 85 | Object contentType = transformed.get(MessageHeaders.CONTENT_TYPE); 86 | // transform content type headers to String, so that they can be properly embedded in JSON 87 | if (contentType != null) { 88 | transformed.put(MessageHeaders.CONTENT_TYPE, contentType.toString()); 89 | } 90 | return EmbeddedHeaderUtils.embedHeaders(transformed, this.headersToEmbed); 91 | } 92 | else { 93 | return this.delegate.fromMessage(message); 94 | } 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/config/ExtendedBindingHandlerMappingsProviderConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2023 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.config; 18 | 19 | import java.util.Map; 20 | 21 | import org.springframework.boot.context.properties.source.ConfigurationPropertyName; 22 | import org.springframework.cloud.stream.config.BindingHandlerAdvise.MappingsProvider; 23 | import org.springframework.context.annotation.Bean; 24 | import org.springframework.context.annotation.Configuration; 25 | 26 | /** 27 | * Configuration for extended binding metadata. 28 | * 29 | * @author Artem Bilan 30 | */ 31 | 32 | @Configuration(proxyBeanMethods = false) 33 | public class ExtendedBindingHandlerMappingsProviderConfiguration { 34 | 35 | @Bean 36 | public MappingsProvider kinesisExtendedPropertiesDefaultMappingsProvider() { 37 | return () -> 38 | Map.of(ConfigurationPropertyName.of("spring.cloud.stream.kinesis.bindings"), 39 | ConfigurationPropertyName.of("spring.cloud.stream.kinesis.default")); 40 | } 41 | 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/config/KinesisProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2023 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.config; 18 | 19 | import io.awspring.cloud.autoconfigure.AwsClientProperties; 20 | 21 | import org.springframework.boot.context.properties.ConfigurationProperties; 22 | 23 | /** 24 | * {@link ConfigurationProperties} for configuring Kinesis client. 25 | * 26 | * @author Artem Bilan 27 | * 28 | * @since 4.0.1 29 | */ 30 | @ConfigurationProperties(prefix = "spring.cloud.aws.cloudwatch") 31 | public class KinesisProperties extends AwsClientProperties { 32 | } 33 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/properties/KinesisBinderConfigurationProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2023 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.properties; 18 | 19 | import java.time.Duration; 20 | 21 | import software.amazon.awssdk.services.dynamodb.model.BillingMode; 22 | 23 | import org.springframework.boot.context.properties.ConfigurationProperties; 24 | import org.springframework.integration.aws.lock.DynamoDbLockRepository; 25 | import org.springframework.integration.aws.metadata.DynamoDbMetadataStore; 26 | 27 | /** 28 | * The Kinesis Binder specific configuration properties. 29 | * 30 | * @author Peter Oates 31 | * @author Artem Bilan 32 | * @author Jacob Severson 33 | * @author Sergiu Pantiru 34 | * @author Arnaud Lecollaire 35 | * @author Asiel Caballero 36 | */ 37 | @ConfigurationProperties(prefix = "spring.cloud.stream.kinesis.binder") 38 | public class KinesisBinderConfigurationProperties { 39 | 40 | private String[] headers = new String[] {}; 41 | 42 | private int describeStreamBackoff = 1000; 43 | 44 | private int describeStreamRetries = 50; 45 | 46 | private boolean autoCreateStream = true; 47 | 48 | private boolean autoAddShards = false; 49 | 50 | private int minShardCount = 1; 51 | 52 | /** 53 | * Enables the usage of Amazon KCL/KPL libraries for all message consumption and production. 54 | */ 55 | private boolean kplKclEnabled; 56 | 57 | /** 58 | * Enable Micrometer observation registry across all the bindings in the binder. 59 | */ 60 | private boolean enableObservation; 61 | 62 | /** 63 | * Enable serializing Kinesis records with legacy embedded headers format. 64 | */ 65 | private boolean legacyEmbeddedHeadersFormat; 66 | 67 | private final Checkpoint checkpoint = new Checkpoint(); 68 | 69 | private final Locks locks = new Locks(); 70 | 71 | public String[] getHeaders() { 72 | return this.headers; 73 | } 74 | 75 | public void setHeaders(String... headers) { 76 | this.headers = headers; 77 | } 78 | 79 | public int getDescribeStreamBackoff() { 80 | return this.describeStreamBackoff; 81 | } 82 | 83 | public void setDescribeStreamBackoff(int describeStreamBackoff) { 84 | this.describeStreamBackoff = describeStreamBackoff; 85 | } 86 | 87 | public int getDescribeStreamRetries() { 88 | return this.describeStreamRetries; 89 | } 90 | 91 | public void setDescribeStreamRetries(int describeStreamRetries) { 92 | this.describeStreamRetries = describeStreamRetries; 93 | } 94 | 95 | public boolean isAutoAddShards() { 96 | return this.autoAddShards; 97 | } 98 | 99 | public void setAutoAddShards(boolean autoAddShards) { 100 | this.autoAddShards = autoAddShards; 101 | } 102 | 103 | public int getMinShardCount() { 104 | return this.minShardCount; 105 | } 106 | 107 | public void setMinShardCount(int minShardCount) { 108 | this.minShardCount = minShardCount; 109 | } 110 | 111 | public Checkpoint getCheckpoint() { 112 | return this.checkpoint; 113 | } 114 | 115 | public Locks getLocks() { 116 | return this.locks; 117 | } 118 | 119 | public boolean isAutoCreateStream() { 120 | return this.autoCreateStream; 121 | } 122 | 123 | public void setAutoCreateStream(boolean autoCreateStream) { 124 | this.autoCreateStream = autoCreateStream; 125 | } 126 | 127 | public boolean isKplKclEnabled() { 128 | return this.kplKclEnabled; 129 | } 130 | 131 | public void setKplKclEnabled(boolean kplKclEnabled) { 132 | this.kplKclEnabled = kplKclEnabled; 133 | } 134 | 135 | 136 | public boolean isEnableObservation() { 137 | return this.enableObservation; 138 | } 139 | 140 | public void setEnableObservation(boolean enableObservation) { 141 | this.enableObservation = enableObservation; 142 | } 143 | 144 | public boolean isLegacyEmbeddedHeadersFormat() { 145 | return this.legacyEmbeddedHeadersFormat; 146 | } 147 | 148 | public void setLegacyEmbeddedHeadersFormat(boolean legacyEmbeddedHeadersFormat) { 149 | this.legacyEmbeddedHeadersFormat = legacyEmbeddedHeadersFormat; 150 | } 151 | 152 | /** 153 | * The checkpoint DynamoDB table configuration properties. 154 | */ 155 | public static class Checkpoint { 156 | 157 | private String table = DynamoDbMetadataStore.DEFAULT_TABLE_NAME; 158 | 159 | private BillingMode billingMode = BillingMode.PAY_PER_REQUEST; 160 | 161 | private long readCapacity = 1L; 162 | 163 | private long writeCapacity = 1L; 164 | 165 | private int createDelay = 1; 166 | 167 | private int createRetries = 25; 168 | 169 | private Integer timeToLive; 170 | 171 | public String getTable() { 172 | return this.table; 173 | } 174 | 175 | public void setTable(String table) { 176 | this.table = table; 177 | } 178 | 179 | public BillingMode getBillingMode() { 180 | return billingMode; 181 | } 182 | 183 | public void setBillingMode(BillingMode billingMode) { 184 | this.billingMode = billingMode; 185 | } 186 | 187 | public long getReadCapacity() { 188 | return this.readCapacity; 189 | } 190 | 191 | public void setReadCapacity(long readCapacity) { 192 | this.readCapacity = readCapacity; 193 | } 194 | 195 | public long getWriteCapacity() { 196 | return this.writeCapacity; 197 | } 198 | 199 | public void setWriteCapacity(long writeCapacity) { 200 | this.writeCapacity = writeCapacity; 201 | } 202 | 203 | public int getCreateDelay() { 204 | return this.createDelay; 205 | } 206 | 207 | public void setCreateDelay(int createDelay) { 208 | this.createDelay = createDelay; 209 | } 210 | 211 | public int getCreateRetries() { 212 | return this.createRetries; 213 | } 214 | 215 | public void setCreateRetries(int createRetries) { 216 | this.createRetries = createRetries; 217 | } 218 | 219 | public Integer getTimeToLive() { 220 | return this.timeToLive; 221 | } 222 | 223 | public void setTimeToLive(Integer timeToLive) { 224 | this.timeToLive = timeToLive; 225 | } 226 | 227 | } 228 | 229 | /** 230 | * The locks DynamoDB table configuration properties. 231 | */ 232 | public static class Locks { 233 | 234 | private String table = DynamoDbLockRepository.DEFAULT_TABLE_NAME; 235 | 236 | private BillingMode billingMode = BillingMode.PAY_PER_REQUEST; 237 | 238 | private long readCapacity = 1L; 239 | 240 | private long writeCapacity = 1L; 241 | 242 | private Duration refreshPeriod = Duration.ofSeconds(1); 243 | 244 | private Duration leaseDuration = DynamoDbLockRepository.DEFAULT_LEASE_DURATION; 245 | 246 | public String getTable() { 247 | return this.table; 248 | } 249 | 250 | public void setTable(String table) { 251 | this.table = table; 252 | } 253 | 254 | public BillingMode getBillingMode() { 255 | return billingMode; 256 | } 257 | 258 | public void setBillingMode(BillingMode billingMode) { 259 | this.billingMode = billingMode; 260 | } 261 | 262 | public long getReadCapacity() { 263 | return this.readCapacity; 264 | } 265 | 266 | public void setReadCapacity(long readCapacity) { 267 | this.readCapacity = readCapacity; 268 | } 269 | 270 | public long getWriteCapacity() { 271 | return this.writeCapacity; 272 | } 273 | 274 | public void setWriteCapacity(long writeCapacity) { 275 | this.writeCapacity = writeCapacity; 276 | } 277 | 278 | public Duration getRefreshPeriod() { 279 | return this.refreshPeriod; 280 | } 281 | 282 | public void setRefreshPeriod(Duration refreshPeriod) { 283 | this.refreshPeriod = refreshPeriod; 284 | } 285 | 286 | public Duration getLeaseDuration() { 287 | return this.leaseDuration; 288 | } 289 | 290 | public void setLeaseDuration(Duration leaseDuration) { 291 | this.leaseDuration = leaseDuration; 292 | } 293 | 294 | } 295 | 296 | } 297 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/properties/KinesisBindingProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.properties; 18 | 19 | import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider; 20 | 21 | /** 22 | * The Kinesis-specific binding configuration properties. 23 | * 24 | * @author Peter Oates 25 | * @author Artem Bilan 26 | */ 27 | public class KinesisBindingProperties implements BinderSpecificPropertiesProvider { 28 | 29 | private KinesisConsumerProperties consumer = new KinesisConsumerProperties(); 30 | 31 | private KinesisProducerProperties producer = new KinesisProducerProperties(); 32 | 33 | public KinesisConsumerProperties getConsumer() { 34 | return this.consumer; 35 | } 36 | 37 | public void setConsumer(KinesisConsumerProperties consumer) { 38 | this.consumer = consumer; 39 | } 40 | 41 | public KinesisProducerProperties getProducer() { 42 | return this.producer; 43 | } 44 | 45 | public void setProducer(KinesisProducerProperties producer) { 46 | this.producer = producer; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/properties/KinesisConsumerProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2024 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.properties; 18 | 19 | import software.amazon.kinesis.metrics.MetricsLevel; 20 | import software.amazon.kinesis.retrieval.polling.PollingConfig; 21 | 22 | import org.springframework.integration.aws.inbound.kinesis.CheckpointMode; 23 | import org.springframework.integration.aws.inbound.kinesis.ListenerMode; 24 | 25 | /** 26 | * The Kinesis-specific consumer binding configuration properties. 27 | * 28 | * @author Peter Oates 29 | * @author Jacob Severson 30 | * @author Artem Bilan 31 | * @author Arnaud Lecollaire 32 | * @author Dmytro Danilenkov 33 | * @author Minkyu Moon 34 | * 35 | */ 36 | public class KinesisConsumerProperties { 37 | 38 | private int startTimeout = 60000; 39 | 40 | private ListenerMode listenerMode = ListenerMode.record; 41 | 42 | private CheckpointMode checkpointMode = CheckpointMode.batch; 43 | 44 | /** 45 | * Interval, in milliseconds, between two checkpoints when checkpoint mode is periodic. 46 | */ 47 | private Long checkpointInterval = 5_000L; 48 | 49 | private int recordsLimit = 10000; 50 | 51 | private int idleBetweenPolls = 1000; 52 | 53 | private int consumerBackoff = 1000; 54 | 55 | private String shardIteratorType; 56 | 57 | private String shardId; 58 | 59 | /** 60 | * Worker identifier used to distinguish different workers/processes 61 | * (only used when KCL is enabled). 62 | */ 63 | private String workerId; 64 | 65 | 66 | /** 67 | * The KCL fan-out or polling retrieval mode. 68 | */ 69 | private boolean fanOut = true; 70 | 71 | /** 72 | * The KCL emptyRecordList option for batch listener mode. 73 | */ 74 | private boolean emptyRecordList = false; 75 | 76 | /** 77 | * The KCL table name for leases. 78 | */ 79 | private String leaseTableName; 80 | 81 | /** 82 | * The KCL max records for request in polling mode. 83 | */ 84 | private int pollingMaxRecords = PollingConfig.DEFAULT_MAX_RECORDS; 85 | 86 | /** 87 | * The KCL idle between requests in polling mode. 88 | */ 89 | private long pollingIdleTime = 1500L; 90 | 91 | /** 92 | * The KCL graceful shutdown timeout in milliseconds. 93 | */ 94 | private long gracefulShutdownTimeout; 95 | 96 | private boolean embedHeaders = true; 97 | 98 | /** 99 | * The {@link MetricsLevel} for emitting (or not) metrics into Cloud Watch. 100 | */ 101 | private MetricsLevel metricsLevel = MetricsLevel.DETAILED; 102 | 103 | public int getStartTimeout() { 104 | return this.startTimeout; 105 | } 106 | 107 | public void setStartTimeout(int startTimeout) { 108 | this.startTimeout = startTimeout; 109 | } 110 | 111 | public ListenerMode getListenerMode() { 112 | return this.listenerMode; 113 | } 114 | 115 | public void setListenerMode(ListenerMode listenerMode) { 116 | this.listenerMode = listenerMode; 117 | } 118 | 119 | public CheckpointMode getCheckpointMode() { 120 | return this.checkpointMode; 121 | } 122 | 123 | public void setCheckpointMode(CheckpointMode checkpointMode) { 124 | this.checkpointMode = checkpointMode; 125 | } 126 | 127 | public Long getCheckpointInterval() { 128 | return checkpointInterval; 129 | } 130 | 131 | public void setCheckpointInterval(Long checkpointInterval) { 132 | this.checkpointInterval = checkpointInterval; 133 | } 134 | 135 | public int getRecordsLimit() { 136 | return this.recordsLimit; 137 | } 138 | 139 | public void setRecordsLimit(int recordsLimit) { 140 | this.recordsLimit = recordsLimit; 141 | } 142 | 143 | public int getIdleBetweenPolls() { 144 | return this.idleBetweenPolls; 145 | } 146 | 147 | public void setIdleBetweenPolls(int idleBetweenPolls) { 148 | this.idleBetweenPolls = idleBetweenPolls; 149 | } 150 | 151 | public int getConsumerBackoff() { 152 | return this.consumerBackoff; 153 | } 154 | 155 | public void setConsumerBackoff(int consumerBackoff) { 156 | this.consumerBackoff = consumerBackoff; 157 | } 158 | 159 | public String getShardIteratorType() { 160 | return this.shardIteratorType; 161 | } 162 | 163 | public void setShardIteratorType(String shardIteratorType) { 164 | this.shardIteratorType = shardIteratorType; 165 | } 166 | 167 | public String getWorkerId() { 168 | return workerId; 169 | } 170 | 171 | public void setWorkerId(String workerId) { 172 | this.workerId = workerId; 173 | } 174 | 175 | public String getShardId() { 176 | return shardId; 177 | } 178 | 179 | public void setShardId(String shardId) { 180 | this.shardId = shardId; 181 | } 182 | 183 | public boolean isEmbedHeaders() { 184 | return this.embedHeaders; 185 | } 186 | 187 | public void setEmbedHeaders(boolean embedHeaders) { 188 | this.embedHeaders = embedHeaders; 189 | } 190 | 191 | public boolean isFanOut() { 192 | return this.fanOut; 193 | } 194 | 195 | public void setFanOut(boolean fanOut) { 196 | this.fanOut = fanOut; 197 | } 198 | 199 | public MetricsLevel getMetricsLevel() { 200 | return this.metricsLevel; 201 | } 202 | 203 | public void setMetricsLevel(MetricsLevel metricsLevel) { 204 | this.metricsLevel = metricsLevel; 205 | } 206 | 207 | public boolean isEmptyRecordList() { 208 | return this.emptyRecordList; 209 | } 210 | 211 | public void setEmptyRecordList(boolean emptyRecordList) { 212 | this.emptyRecordList = emptyRecordList; 213 | } 214 | 215 | public String getLeaseTableName() { 216 | return this.leaseTableName; 217 | } 218 | 219 | public void setLeaseTableName(String leaseTableName) { 220 | this.leaseTableName = leaseTableName; 221 | } 222 | 223 | public int getPollingMaxRecords() { 224 | return this.pollingMaxRecords; 225 | } 226 | 227 | public void setPollingMaxRecords(int pollingMaxRecords) { 228 | this.pollingMaxRecords = pollingMaxRecords; 229 | } 230 | 231 | public long getPollingIdleTime() { 232 | return this.pollingIdleTime; 233 | } 234 | 235 | public void setPollingIdleTime(long pollingIdleTime) { 236 | this.pollingIdleTime = pollingIdleTime; 237 | } 238 | 239 | public long getGracefulShutdownTimeout() { 240 | return this.gracefulShutdownTimeout; 241 | } 242 | 243 | public void setGracefulShutdownTimeout(long gracefulShutdownTimeout) { 244 | this.gracefulShutdownTimeout = gracefulShutdownTimeout; 245 | } 246 | 247 | } 248 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/properties/KinesisExtendedBindingProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2019 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.properties; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import org.springframework.boot.context.properties.ConfigurationProperties; 23 | import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider; 24 | import org.springframework.cloud.stream.binder.ExtendedBindingProperties; 25 | 26 | /** 27 | * The extended Kinesis-specific binding configuration properties. 28 | * 29 | * @author Peter Oates 30 | * @author Artem Bilan 31 | * 32 | */ 33 | @ConfigurationProperties("spring.cloud.stream.kinesis") 34 | public class KinesisExtendedBindingProperties implements 35 | ExtendedBindingProperties { 36 | 37 | private static final String DEFAULTS_PREFIX = "spring.cloud.stream.kinesis.default"; 38 | 39 | private Map bindings = new HashMap<>(); 40 | 41 | public Map getBindings() { 42 | return this.bindings; 43 | } 44 | 45 | public void setBindings(Map bindings) { 46 | this.bindings = bindings; 47 | } 48 | 49 | @Override 50 | public KinesisConsumerProperties getExtendedConsumerProperties(String channelName) { 51 | if (this.bindings.containsKey(channelName) 52 | && this.bindings.get(channelName).getConsumer() != null) { 53 | return this.bindings.get(channelName).getConsumer(); 54 | } 55 | else { 56 | return new KinesisConsumerProperties(); 57 | } 58 | } 59 | 60 | @Override 61 | public KinesisProducerProperties getExtendedProducerProperties(String channelName) { 62 | if (this.bindings.containsKey(channelName) 63 | && this.bindings.get(channelName).getProducer() != null) { 64 | return this.bindings.get(channelName).getProducer(); 65 | } 66 | else { 67 | return new KinesisProducerProperties(); 68 | } 69 | } 70 | 71 | @Override 72 | public String getDefaultsPrefix() { 73 | return DEFAULTS_PREFIX; 74 | } 75 | 76 | @Override 77 | public Class getExtendedPropertiesEntryClass() { 78 | return KinesisBindingProperties.class; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/properties/KinesisProducerProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2025 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.properties; 18 | 19 | /** 20 | * The Kinesis-specific producer binding configuration properties. 21 | * 22 | * @author Peter Oates 23 | * @author Jacob Severson 24 | * @author Artem Bilan 25 | */ 26 | public class KinesisProducerProperties { 27 | 28 | /** 29 | * Whether message handler produces in sync mode. 30 | */ 31 | private boolean sync; 32 | 33 | /** 34 | * Timeout in milliseconds to wait for future completion in sync mode. 35 | */ 36 | private long sendTimeout = 10000; 37 | 38 | /** 39 | * Whether to embed headers into Kinesis record. 40 | */ 41 | private boolean embedHeaders = true; 42 | 43 | /** 44 | * The bean name of a MessageChannel to which successful send results should be sent. 45 | * Works only for async mode. 46 | */ 47 | private String recordMetadataChannel; 48 | 49 | /** 50 | * Maximum records in flight for handling backpressure. 51 | * No backpressure by default. 52 | * When backpressure handling is enabled and number of records in flight exceeds the threshold, a 53 | * 'KplBackpressureException' would be thrown. 54 | */ 55 | private long kplBackPressureThreshold; 56 | 57 | public void setSync(boolean sync) { 58 | this.sync = sync; 59 | } 60 | 61 | public boolean isSync() { 62 | return this.sync; 63 | } 64 | 65 | public long getSendTimeout() { 66 | return this.sendTimeout; 67 | } 68 | 69 | public void setSendTimeout(long sendTimeout) { 70 | this.sendTimeout = sendTimeout; 71 | } 72 | 73 | public boolean isEmbedHeaders() { 74 | return this.embedHeaders; 75 | } 76 | 77 | public void setEmbedHeaders(boolean embedHeaders) { 78 | this.embedHeaders = embedHeaders; 79 | } 80 | 81 | public String getRecordMetadataChannel() { 82 | return this.recordMetadataChannel; 83 | } 84 | 85 | public void setRecordMetadataChannel(String recordMetadataChannel) { 86 | this.recordMetadataChannel = recordMetadataChannel; 87 | } 88 | 89 | public long getKplBackPressureThreshold() { 90 | return this.kplBackPressureThreshold; 91 | } 92 | 93 | public void setKplBackPressureThreshold(long kplBackPressureThreshold) { 94 | this.kplBackPressureThreshold = kplBackPressureThreshold; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/provisioning/KinesisConsumerDestination.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2023 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.provisioning; 18 | 19 | import java.util.List; 20 | 21 | import software.amazon.awssdk.services.kinesis.model.Shard; 22 | 23 | import org.springframework.cloud.stream.provisioning.ConsumerDestination; 24 | 25 | /** 26 | * The Kinesis-specific {@link ConsumerDestination} implementation. 27 | * 28 | * @author Artem Bilan 29 | * 30 | */ 31 | public final class KinesisConsumerDestination implements ConsumerDestination { 32 | 33 | private final String streamName; 34 | 35 | private final List shards; 36 | 37 | private final String dlqName; 38 | 39 | public KinesisConsumerDestination(String streamName, List shards) { 40 | this(streamName, shards, null); 41 | } 42 | 43 | public KinesisConsumerDestination(String streamName, List shards, String dlqName) { 44 | this.streamName = streamName; 45 | this.shards = shards; 46 | this.dlqName = dlqName; 47 | } 48 | 49 | @Override 50 | public String getName() { 51 | return this.streamName; 52 | } 53 | 54 | public List getShards() { 55 | return this.shards; 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | return "KinesisConsumerDestination{" + "streamName='" + this.streamName + '\'' 61 | + ", shards=" + this.shards + ", dlqName='" + this.dlqName + '\'' + '}'; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/provisioning/KinesisProducerDestination.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2023 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.provisioning; 18 | 19 | import java.util.List; 20 | 21 | import software.amazon.awssdk.services.kinesis.model.Shard; 22 | 23 | import org.springframework.cloud.stream.provisioning.ProducerDestination; 24 | 25 | /** 26 | * The Kinesis-specific {@link ProducerDestination} implementation. 27 | * 28 | * @author Artem Bilan 29 | * 30 | */ 31 | public final class KinesisProducerDestination implements ProducerDestination { 32 | 33 | private final String streamName; 34 | 35 | private final List shards; 36 | 37 | KinesisProducerDestination(String streamName, List shards) { 38 | this.streamName = streamName; 39 | this.shards = shards; 40 | } 41 | 42 | @Override 43 | public String getName() { 44 | return this.streamName; 45 | } 46 | 47 | @Override 48 | public String getNameForPartition(int shard) { 49 | return this.streamName; 50 | } 51 | 52 | public List getShards() { 53 | return this.shards; 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | return "KinesisProducerDestination{" + "streamName='" + this.streamName + '\'' 59 | + ", shards=" + this.shards + '}'; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/java/org/springframework/cloud/stream/binder/kinesis/provisioning/KinesisStreamProvisioner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2023 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.provisioning; 18 | 19 | import java.time.Duration; 20 | import java.util.List; 21 | import java.util.concurrent.CompletableFuture; 22 | import java.util.concurrent.CompletionException; 23 | 24 | import org.apache.commons.logging.Log; 25 | import org.apache.commons.logging.LogFactory; 26 | import software.amazon.awssdk.core.retry.backoff.FixedDelayBackoffStrategy; 27 | import software.amazon.awssdk.core.waiters.WaiterResponse; 28 | import software.amazon.awssdk.services.kinesis.KinesisAsyncClient; 29 | import software.amazon.awssdk.services.kinesis.model.DescribeStreamResponse; 30 | import software.amazon.awssdk.services.kinesis.model.ListShardsResponse; 31 | import software.amazon.awssdk.services.kinesis.model.ResourceNotFoundException; 32 | import software.amazon.awssdk.services.kinesis.model.ScalingType; 33 | import software.amazon.awssdk.services.kinesis.model.Shard; 34 | 35 | import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; 36 | import org.springframework.cloud.stream.binder.ExtendedProducerProperties; 37 | import org.springframework.cloud.stream.binder.HeaderMode; 38 | import org.springframework.cloud.stream.binder.kinesis.properties.KinesisBinderConfigurationProperties; 39 | import org.springframework.cloud.stream.binder.kinesis.properties.KinesisConsumerProperties; 40 | import org.springframework.cloud.stream.binder.kinesis.properties.KinesisProducerProperties; 41 | import org.springframework.cloud.stream.provisioning.ConsumerDestination; 42 | import org.springframework.cloud.stream.provisioning.ProducerDestination; 43 | import org.springframework.cloud.stream.provisioning.ProvisioningException; 44 | import org.springframework.cloud.stream.provisioning.ProvisioningProvider; 45 | import org.springframework.util.Assert; 46 | import org.springframework.util.StringUtils; 47 | 48 | /** 49 | * The {@link ProvisioningProvider} implementation for Amazon Kinesis. 50 | * 51 | * @author Peter Oates 52 | * @author Artem Bilan 53 | * @author Jacob Severson 54 | * @author Sergiu Pantiru 55 | * @author Matthias Wesolowski 56 | */ 57 | public class KinesisStreamProvisioner implements 58 | ProvisioningProvider, 59 | ExtendedProducerProperties> { 60 | 61 | private static final Log logger = LogFactory.getLog(KinesisStreamProvisioner.class); 62 | 63 | private final KinesisAsyncClient amazonKinesis; 64 | 65 | private final KinesisBinderConfigurationProperties configurationProperties; 66 | 67 | public KinesisStreamProvisioner(KinesisAsyncClient amazonKinesis, 68 | KinesisBinderConfigurationProperties kinesisBinderConfigurationProperties) { 69 | 70 | Assert.notNull(amazonKinesis, "'amazonKinesis' must not be null"); 71 | Assert.notNull(kinesisBinderConfigurationProperties, 72 | "'kinesisBinderConfigurationProperties' must not be null"); 73 | this.amazonKinesis = amazonKinesis; 74 | this.configurationProperties = kinesisBinderConfigurationProperties; 75 | } 76 | 77 | @Override 78 | public ProducerDestination provisionProducerDestination(String name, 79 | ExtendedProducerProperties properties) 80 | throws ProvisioningException { 81 | 82 | if (logger.isInfoEnabled()) { 83 | logger.info("Using Kinesis stream for outbound: " + name); 84 | } 85 | 86 | KinesisProducerProperties kinesisProducerProperties = properties.getExtension(); 87 | if (kinesisProducerProperties.isEmbedHeaders()) { 88 | properties.setHeaderMode(HeaderMode.none); 89 | } 90 | 91 | return new KinesisProducerDestination(name, createOrUpdate(name, properties.getPartitionCount())); 92 | } 93 | 94 | @Override 95 | public ConsumerDestination provisionConsumerDestination(String name, String group, 96 | ExtendedConsumerProperties properties) 97 | throws ProvisioningException { 98 | 99 | KinesisConsumerProperties kinesisConsumerProperties = properties.getExtension(); 100 | if (kinesisConsumerProperties.isEmbedHeaders()) { 101 | properties.setHeaderMode(HeaderMode.none); 102 | } 103 | 104 | int shardCount = properties.getInstanceCount() * properties.getConcurrency(); 105 | 106 | if (!properties.isMultiplex()) { 107 | List shardList = provisionKinesisConsumerDestination(name, shardCount); 108 | return new KinesisConsumerDestination(name, shardList); 109 | } 110 | else { 111 | String[] streams = StringUtils.commaDelimitedListToStringArray(name); 112 | for (String stream : streams) { 113 | provisionKinesisConsumerDestination(stream.trim(), shardCount); 114 | } 115 | return new KinesisConsumerDestination(name, List.of()); 116 | } 117 | } 118 | 119 | private List provisionKinesisConsumerDestination(String stream, int shards) { 120 | if (logger.isInfoEnabled()) { 121 | logger.info("Using Kinesis stream for inbound: " + stream); 122 | } 123 | 124 | return createOrUpdate(stream, shards); 125 | } 126 | 127 | private List createOrUpdate(String stream, int shards) { 128 | List shardList; 129 | try { 130 | shardList = getShardList(stream).join(); 131 | } 132 | catch (CompletionException ex) { 133 | Throwable cause = ex.getCause(); 134 | if (cause instanceof ResourceNotFoundException) { 135 | if (!this.configurationProperties.isAutoCreateStream()) { 136 | throw new ProvisioningException( 137 | "The stream [" + stream + "] was not found and auto creation is disabled.", cause); 138 | } 139 | if (logger.isInfoEnabled()) { 140 | logger.info("Stream '" + stream + "' not found. Create one..."); 141 | } 142 | 143 | shardList = createStream(stream, shards); 144 | } 145 | else { 146 | throw new ProvisioningException( 147 | "Cannot retrieve shards information for stream [" + stream + "].", cause); 148 | } 149 | } 150 | 151 | int effectiveShardCount = Math.max(this.configurationProperties.getMinShardCount(), shards); 152 | 153 | if ((shardList.size() < effectiveShardCount) && this.configurationProperties.isAutoAddShards()) { 154 | return updateShardCount(stream, shardList.size(), effectiveShardCount); 155 | } 156 | 157 | return shardList; 158 | } 159 | 160 | private CompletableFuture> getShardList(String stream) { 161 | return this.amazonKinesis.describeStreamSummary(request -> request.streamName(stream)) 162 | .thenCompose(reply -> this.amazonKinesis.listShards(request -> request.streamName(stream))) 163 | .thenApply(ListShardsResponse::shards); 164 | } 165 | 166 | private List createStream(String streamName, int shards) { 167 | try { 168 | return this.amazonKinesis.createStream(request -> request 169 | .streamName(streamName) 170 | .shardCount(Math.max(this.configurationProperties.getMinShardCount(), shards))) 171 | .thenCompose(reply -> waitForStreamToBecomeActive(streamName)) 172 | .thenCompose(reply -> getShardList(streamName)) 173 | .join(); 174 | } 175 | catch (Exception ex) { 176 | throw new ProvisioningException("Cannot create stream [" + streamName + "].", ex); 177 | } 178 | } 179 | 180 | private CompletableFuture> waitForStreamToBecomeActive(String streamName) { 181 | return this.amazonKinesis.waiter() 182 | .waitUntilStreamExists(request -> request.streamName(streamName), 183 | waiter -> waiter 184 | .maxAttempts(this.configurationProperties.getDescribeStreamRetries()) 185 | .backoffStrategy(FixedDelayBackoffStrategy.create( 186 | Duration.ofMillis(this.configurationProperties.getDescribeStreamBackoff())))); 187 | } 188 | 189 | private List updateShardCount(String streamName, int shardCount, int targetCount) { 190 | if (logger.isInfoEnabled()) { 191 | logger.info("Stream [" + streamName + "] has [" + shardCount 192 | + "] shards compared to a target configuration of [" + targetCount 193 | + "], creating shards..."); 194 | } 195 | 196 | return this.amazonKinesis.updateShardCount(request -> request 197 | .streamName(streamName) 198 | .targetShardCount(targetCount) 199 | .scalingType(ScalingType.UNIFORM_SCALING)) 200 | .thenCompose(reply -> waitForStreamToBecomeActive(streamName)) 201 | .thenCompose(reply -> getShardList(streamName)) 202 | .join(); 203 | } 204 | 205 | } 206 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/resources/META-INF/spring.binders: -------------------------------------------------------------------------------- 1 | kinesis: org.springframework.cloud.stream.binder.kinesis.config.KinesisBinderConfiguration 2 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | org.springframework.cloud.stream.binder.kinesis.config.ExtendedBindingHandlerMappingsProviderConfiguration 2 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/test/java/org/springframework/cloud/stream/binder/kinesis/KinesisBinderFunctionalTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021-2023 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 | 17 | package org.springframework.cloud.stream.binder.kinesis; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.concurrent.CountDownLatch; 23 | import java.util.concurrent.TimeUnit; 24 | import java.util.concurrent.atomic.AtomicReference; 25 | import java.util.function.Consumer; 26 | 27 | import com.fasterxml.jackson.core.JsonProcessingException; 28 | import com.fasterxml.jackson.databind.ObjectMapper; 29 | import org.assertj.core.api.Condition; 30 | import org.junit.jupiter.api.Test; 31 | import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable; 32 | import software.amazon.awssdk.core.SdkBytes; 33 | import software.amazon.awssdk.services.kinesis.model.PutRecordsRequest; 34 | import software.amazon.awssdk.services.kinesis.model.PutRecordsRequestEntry; 35 | 36 | import org.springframework.beans.factory.annotation.Autowired; 37 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 38 | import org.springframework.boot.test.context.SpringBootTest; 39 | import org.springframework.cloud.stream.binder.Binding; 40 | import org.springframework.cloud.stream.binding.BindingService; 41 | import org.springframework.context.annotation.Bean; 42 | import org.springframework.context.annotation.Configuration; 43 | import org.springframework.integration.aws.inbound.kinesis.KinesisMessageDrivenChannelAdapter; 44 | import org.springframework.integration.aws.inbound.kinesis.KinesisShardOffset; 45 | import org.springframework.integration.aws.support.AwsHeaders; 46 | import org.springframework.integration.metadata.ConcurrentMetadataStore; 47 | import org.springframework.integration.metadata.SimpleMetadataStore; 48 | import org.springframework.integration.support.MessageBuilder; 49 | import org.springframework.integration.support.json.JacksonJsonUtils; 50 | import org.springframework.integration.support.locks.DefaultLockRegistry; 51 | import org.springframework.integration.support.locks.LockRegistry; 52 | import org.springframework.integration.test.util.TestUtils; 53 | import org.springframework.messaging.Message; 54 | import org.springframework.messaging.support.GenericMessage; 55 | import org.springframework.test.annotation.DirtiesContext; 56 | 57 | import static org.assertj.core.api.Assertions.assertThat; 58 | 59 | /** 60 | * @author Artem Bilan 61 | */ 62 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, 63 | properties = { 64 | "spring.cloud.stream.bindings.eventConsumerBatchProcessingWithHeaders-in-0.consumer.multiplex=true", 65 | "spring.cloud.stream.bindings.eventConsumerBatchProcessingWithHeaders-in-0.destination=some_other_stream," + KinesisBinderFunctionalTests.KINESIS_STREAM, 66 | "spring.cloud.stream.kinesis.bindings.eventConsumerBatchProcessingWithHeaders-in-0.consumer.idleBetweenPolls = 1", 67 | "spring.cloud.stream.kinesis.bindings.eventConsumerBatchProcessingWithHeaders-in-0.consumer.listenerMode = batch", 68 | "spring.cloud.stream.kinesis.bindings.eventConsumerBatchProcessingWithHeaders-in-0.consumer.checkpointMode = manual", 69 | "spring.cloud.stream.kinesis.bindings.eventConsumerBatchProcessingWithHeaders-in-0.consumer.embedHeaders = false", 70 | "spring.cloud.stream.kinesis.binder.headers = event.eventType", 71 | "spring.cloud.stream.kinesis.binder.autoAddShards = true"}) 72 | @DirtiesContext 73 | @DisabledIfEnvironmentVariable(named = "GITHUB_ACTIONS", matches = "true") 74 | public class KinesisBinderFunctionalTests implements LocalstackContainerTest { 75 | 76 | static final String KINESIS_STREAM = "test_stream"; 77 | 78 | @Autowired 79 | private ObjectMapper objectMapper; 80 | 81 | @Autowired 82 | private CountDownLatch messageBarrier; 83 | 84 | @Autowired 85 | private AtomicReference>> messageHolder; 86 | 87 | @Autowired 88 | private BindingService bindingService; 89 | 90 | @SuppressWarnings("unchecked") 91 | @Test 92 | void testKinesisFunction() throws JsonProcessingException, InterruptedException { 93 | PutRecordsRequest.Builder putRecordsRequest = 94 | PutRecordsRequest.builder() 95 | .streamName(KINESIS_STREAM); 96 | 97 | List putRecordsRequestEntryList = new ArrayList<>(); 98 | 99 | for (int i = 0; i < 10; i++) { 100 | Message eventMessages = 101 | MessageBuilder.withPayload("Message" + i) 102 | .setHeader("event.eventType", "createEvent") 103 | .build(); 104 | PutRecordsRequestEntry putRecordsRequestEntry = 105 | PutRecordsRequestEntry.builder() 106 | .partitionKey("1") 107 | .data(SdkBytes.fromByteArray(objectMapper.writeValueAsBytes(eventMessages))) 108 | .build(); 109 | putRecordsRequestEntryList.add(putRecordsRequestEntry); 110 | } 111 | putRecordsRequest.records(putRecordsRequestEntryList); 112 | 113 | LocalstackContainerTest.kinesisClient().putRecords(putRecordsRequest.build()); 114 | 115 | assertThat(this.messageBarrier.await(60, TimeUnit.SECONDS)).isTrue(); 116 | 117 | Message> message = this.messageHolder.get(); 118 | assertThat(message.getHeaders()) 119 | .containsKeys(AwsHeaders.CHECKPOINTER, 120 | AwsHeaders.SHARD, 121 | AwsHeaders.RECEIVED_STREAM) 122 | .doesNotContainKeys(AwsHeaders.STREAM, AwsHeaders.PARTITION_KEY); 123 | 124 | List payload = message.getPayload(); 125 | assertThat(payload).hasSize(10); 126 | 127 | Object item = payload.get(0); 128 | 129 | assertThat(item).isInstanceOf(GenericMessage.class); 130 | 131 | Message messageFromBatch = (Message) item; 132 | 133 | assertThat(messageFromBatch.getPayload()).isEqualTo("Message0"); 134 | assertThat(messageFromBatch.getHeaders()) 135 | .containsEntry("event.eventType", "createEvent"); 136 | 137 | List> consumerBindings = 138 | this.bindingService.getConsumerBindings("eventConsumerBatchProcessingWithHeaders-in-0"); 139 | 140 | assertThat(consumerBindings).hasSize(1); 141 | 142 | Binding binding = consumerBindings.get(0); 143 | 144 | KinesisMessageDrivenChannelAdapter kinesisMessageDrivenChannelAdapter = 145 | TestUtils.getPropertyValue(binding, "lifecycle", KinesisMessageDrivenChannelAdapter.class); 146 | 147 | Map shardConsumers = 148 | TestUtils.getPropertyValue(kinesisMessageDrivenChannelAdapter, "shardConsumers", Map.class); 149 | assertThat(shardConsumers) 150 | .hasSize(2) 151 | .hasKeySatisfying(keySatisfyingCondition(KINESIS_STREAM)) 152 | .hasKeySatisfying(keySatisfyingCondition("some_other_stream")); 153 | } 154 | 155 | private static Condition keySatisfyingCondition(String streamName) { 156 | return new Condition<>() { 157 | 158 | @Override 159 | public boolean matches(KinesisShardOffset value) { 160 | return value.getStream().equals(streamName); 161 | } 162 | 163 | }; 164 | } 165 | 166 | @Configuration 167 | @EnableAutoConfiguration 168 | static class TestConfiguration { 169 | 170 | @Bean 171 | public LockRegistry lockRegistry() { 172 | return new DefaultLockRegistry(); 173 | } 174 | 175 | @Bean 176 | public ConcurrentMetadataStore checkpointStore() { 177 | return new SimpleMetadataStore(); 178 | } 179 | 180 | @Bean 181 | public ObjectMapper objectMapper() { 182 | return JacksonJsonUtils.messagingAwareMapper(); 183 | } 184 | 185 | @Bean 186 | public AtomicReference>>> messageHolder() { 187 | return new AtomicReference<>(); 188 | } 189 | 190 | @Bean 191 | public CountDownLatch messageBarrier() { 192 | return new CountDownLatch(1); 193 | } 194 | 195 | @Bean 196 | public Consumer>>> eventConsumerBatchProcessingWithHeaders() { 197 | return eventMessages -> { 198 | messageHolder().set(eventMessages); 199 | messageBarrier().countDown(); 200 | }; 201 | } 202 | 203 | } 204 | 205 | } 206 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/test/java/org/springframework/cloud/stream/binder/kinesis/KinesisTestBinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2022 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 | 17 | package org.springframework.cloud.stream.binder.kinesis; 18 | 19 | import java.util.concurrent.CompletableFuture; 20 | 21 | import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; 22 | import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; 23 | import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; 24 | import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; 25 | import software.amazon.awssdk.services.kinesis.KinesisAsyncClient; 26 | 27 | import org.springframework.beans.DirectFieldAccessor; 28 | import org.springframework.cloud.stream.binder.AbstractTestBinder; 29 | import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; 30 | import org.springframework.cloud.stream.binder.ExtendedProducerProperties; 31 | import org.springframework.cloud.stream.binder.PartitionTestSupport; 32 | import org.springframework.cloud.stream.binder.kinesis.properties.KinesisBinderConfigurationProperties; 33 | import org.springframework.cloud.stream.binder.kinesis.properties.KinesisConsumerProperties; 34 | import org.springframework.cloud.stream.binder.kinesis.properties.KinesisProducerProperties; 35 | import org.springframework.cloud.stream.binder.kinesis.provisioning.KinesisStreamProvisioner; 36 | import org.springframework.cloud.stream.provisioning.ConsumerDestination; 37 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 38 | import org.springframework.context.annotation.Bean; 39 | import org.springframework.context.annotation.Configuration; 40 | import org.springframework.context.support.GenericApplicationContext; 41 | import org.springframework.integration.aws.inbound.kinesis.KinesisMessageDrivenChannelAdapter; 42 | import org.springframework.integration.config.EnableIntegration; 43 | import org.springframework.integration.core.MessageProducer; 44 | 45 | /** 46 | * An {@link AbstractTestBinder} implementation for the {@link KinesisMessageChannelBinder}. 47 | * 48 | * @author Artem Bilan 49 | * @author Arnaud Lecollaire 50 | */ 51 | public class KinesisTestBinder extends 52 | AbstractTestBinder, 53 | ExtendedProducerProperties> { 54 | 55 | private final KinesisAsyncClient amazonKinesis; 56 | 57 | private final GenericApplicationContext applicationContext; 58 | 59 | public KinesisTestBinder(KinesisAsyncClient amazonKinesis, DynamoDbAsyncClient dynamoDbClient, 60 | CloudWatchAsyncClient cloudWatchClient, 61 | KinesisBinderConfigurationProperties kinesisBinderConfigurationProperties) { 62 | 63 | this.applicationContext = new AnnotationConfigApplicationContext(Config.class); 64 | 65 | this.amazonKinesis = amazonKinesis; 66 | 67 | KinesisStreamProvisioner provisioningProvider = new KinesisStreamProvisioner( 68 | amazonKinesis, kinesisBinderConfigurationProperties); 69 | 70 | KinesisMessageChannelBinder binder = new TestKinesisMessageChannelBinder( 71 | amazonKinesis, dynamoDbClient, cloudWatchClient, kinesisBinderConfigurationProperties, 72 | provisioningProvider); 73 | 74 | binder.setApplicationContext(this.applicationContext); 75 | 76 | setBinder(binder); 77 | } 78 | 79 | public GenericApplicationContext getApplicationContext() { 80 | return this.applicationContext; 81 | } 82 | 83 | @Override 84 | public void cleanup() { 85 | this.amazonKinesis.listStreams() 86 | .thenCompose(reply -> 87 | CompletableFuture.allOf( 88 | reply.streamNames() 89 | .stream() 90 | .map(streamName -> 91 | this.amazonKinesis.deleteStream(request -> 92 | request.streamName(streamName)) 93 | .thenCompose(result -> 94 | this.amazonKinesis.waiter() 95 | .waitUntilStreamNotExists(request -> 96 | request.streamName(streamName)))) 97 | .toArray(CompletableFuture[]::new))) 98 | .join(); 99 | } 100 | 101 | /** 102 | * Test configuration. 103 | */ 104 | @Configuration 105 | @EnableIntegration 106 | static class Config { 107 | 108 | @Bean 109 | public PartitionTestSupport partitionSupport() { 110 | return new PartitionTestSupport(); 111 | } 112 | 113 | } 114 | 115 | private static class TestKinesisMessageChannelBinder 116 | extends KinesisMessageChannelBinder { 117 | 118 | TestKinesisMessageChannelBinder(KinesisAsyncClient amazonKinesis, 119 | DynamoDbAsyncClient dynamoDbClient, 120 | CloudWatchAsyncClient cloudWatchClient, 121 | KinesisBinderConfigurationProperties kinesisBinderConfigurationProperties, 122 | KinesisStreamProvisioner provisioningProvider) { 123 | 124 | super(kinesisBinderConfigurationProperties, provisioningProvider, amazonKinesis, 125 | StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test")), dynamoDbClient, 126 | cloudWatchClient); 127 | } 128 | 129 | /* 130 | * Some tests use multiple instance indexes for the same topic; we need to make 131 | * the error infrastructure beans unique. 132 | */ 133 | @Override 134 | protected String errorsBaseName(ConsumerDestination destination, String group, 135 | ExtendedConsumerProperties consumerProperties) { 136 | return super.errorsBaseName(destination, group, consumerProperties) + "-" 137 | + consumerProperties.getInstanceIndex(); 138 | } 139 | 140 | @Override 141 | protected MessageProducer createConsumerEndpoint(ConsumerDestination destination, 142 | String group, 143 | ExtendedConsumerProperties properties) { 144 | 145 | MessageProducer messageProducer = super.createConsumerEndpoint(destination, 146 | group, properties); 147 | if (messageProducer instanceof KinesisMessageDrivenChannelAdapter) { 148 | DirectFieldAccessor dfa = new DirectFieldAccessor(messageProducer); 149 | dfa.setPropertyValue("describeStreamBackoff", 10); 150 | dfa.setPropertyValue("consumerBackoff", 10); 151 | dfa.setPropertyValue("idleBetweenPolls", 1); 152 | } 153 | return messageProducer; 154 | } 155 | 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/test/java/org/springframework/cloud/stream/binder/kinesis/LocalstackContainerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 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 | 17 | package org.springframework.cloud.stream.binder.kinesis; 18 | 19 | import java.util.Map; 20 | import java.util.Optional; 21 | 22 | import org.junit.jupiter.api.BeforeAll; 23 | import org.testcontainers.containers.localstack.LocalStackContainer; 24 | import org.testcontainers.junit.jupiter.Testcontainers; 25 | import org.testcontainers.utility.DockerImageName; 26 | import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; 27 | import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; 28 | import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; 29 | import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; 30 | import software.amazon.awssdk.regions.Region; 31 | import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; 32 | import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; 33 | import software.amazon.awssdk.services.kinesis.KinesisAsyncClient; 34 | 35 | import org.springframework.test.context.DynamicPropertyRegistry; 36 | import org.springframework.test.context.DynamicPropertySource; 37 | 38 | /** 39 | * The base contract for JUnit tests based on the container for Localstack. 40 | * The Testcontainers 'reuse' option must be disabled,so, Ryuk container is started 41 | * and will clean all the containers up from this test suite after JVM exit. 42 | * Since the Localstack container instance is shared via static property, it is going to be 43 | * started only once per JVM, therefore the target Docker container is reused automatically. 44 | * 45 | * @author Artem Bilan 46 | * 47 | * @since 3.0 48 | */ 49 | @Testcontainers(disabledWithoutDocker = true) 50 | public interface LocalstackContainerTest { 51 | 52 | /** 53 | * The shared {@link LocalStackContainer} instance. 54 | */ 55 | LocalStackContainer LOCAL_STACK_CONTAINER = 56 | new LocalStackContainer(DockerImageName.parse("localstack/localstack:2.2.0")) 57 | .withEnv(Optional.ofNullable(System.getenv("GITHUB_API_TOKEN")) 58 | .map(value -> Map.of("GITHUB_API_TOKEN", value)) 59 | .orElse(Map.of())); 60 | @BeforeAll 61 | static void startContainer() { 62 | LOCAL_STACK_CONTAINER.start(); 63 | } 64 | 65 | @DynamicPropertySource 66 | static void registerProperties(DynamicPropertyRegistry registry) { 67 | registry.add("spring.cloud.aws.endpoint", LOCAL_STACK_CONTAINER::getEndpoint); 68 | registry.add("spring.cloud.aws.region.static", LOCAL_STACK_CONTAINER::getRegion); 69 | registry.add("spring.cloud.aws.credentials.access-key", LOCAL_STACK_CONTAINER::getAccessKey); 70 | registry.add("spring.cloud.aws.credentials.secret-key", LOCAL_STACK_CONTAINER::getSecretKey); 71 | } 72 | 73 | static DynamoDbAsyncClient dynamoDbClient() { 74 | return applyAwsClientOptions(DynamoDbAsyncClient.builder()); 75 | } 76 | 77 | static KinesisAsyncClient kinesisClient() { 78 | return applyAwsClientOptions(KinesisAsyncClient.builder()); 79 | } 80 | 81 | static CloudWatchAsyncClient cloudWatchClient() { 82 | return applyAwsClientOptions(CloudWatchAsyncClient.builder()); 83 | } 84 | 85 | static AwsCredentialsProvider credentialsProvider() { 86 | return StaticCredentialsProvider.create( 87 | AwsBasicCredentials.create(LOCAL_STACK_CONTAINER.getAccessKey(), LOCAL_STACK_CONTAINER.getSecretKey())); 88 | } 89 | 90 | private static , T> T applyAwsClientOptions(B clientBuilder) { 91 | return clientBuilder 92 | .region(Region.of(LOCAL_STACK_CONTAINER.getRegion())) 93 | .credentialsProvider(credentialsProvider()) 94 | .endpointOverride(LOCAL_STACK_CONTAINER.getEndpoint()) 95 | .build(); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/test/java/org/springframework/cloud/stream/binder/kinesis/observation/KinesisBinderObservationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.observation; 18 | 19 | import java.util.concurrent.CountDownLatch; 20 | import java.util.concurrent.TimeUnit; 21 | import java.util.concurrent.atomic.AtomicReference; 22 | import java.util.function.Consumer; 23 | import java.util.function.Supplier; 24 | 25 | import brave.handler.SpanHandler; 26 | import brave.test.TestSpanHandler; 27 | import io.micrometer.tracing.Span; 28 | import io.micrometer.tracing.brave.bridge.BraveFinishedSpan; 29 | import io.micrometer.tracing.test.simple.SpansAssert; 30 | import org.apache.commons.logging.Log; 31 | import org.apache.commons.logging.LogFactory; 32 | import org.junit.jupiter.api.Test; 33 | import reactor.core.publisher.Flux; 34 | 35 | import org.springframework.beans.factory.annotation.Autowired; 36 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 37 | import org.springframework.boot.test.autoconfigure.actuate.observability.AutoConfigureObservability; 38 | import org.springframework.boot.test.context.SpringBootTest; 39 | import org.springframework.cloud.stream.binder.kinesis.LocalstackContainerTest; 40 | import org.springframework.context.annotation.Bean; 41 | import org.springframework.context.annotation.Configuration; 42 | import org.springframework.integration.aws.support.AwsHeaders; 43 | import org.springframework.integration.channel.QueueChannel; 44 | import org.springframework.integration.config.GlobalChannelInterceptor; 45 | import org.springframework.integration.metadata.ConcurrentMetadataStore; 46 | import org.springframework.integration.metadata.SimpleMetadataStore; 47 | import org.springframework.integration.support.locks.DefaultLockRegistry; 48 | import org.springframework.integration.support.locks.LockRegistry; 49 | import org.springframework.integration.support.management.observation.IntegrationObservation; 50 | import org.springframework.messaging.Message; 51 | import org.springframework.messaging.MessageChannel; 52 | import org.springframework.messaging.support.ChannelInterceptor; 53 | import org.springframework.messaging.support.GenericMessage; 54 | import org.springframework.test.annotation.DirtiesContext; 55 | 56 | import static org.assertj.core.api.Assertions.assertThat; 57 | import static org.awaitility.Awaitility.await; 58 | 59 | /** 60 | * @author Artem Bilan 61 | * 62 | * @since 4.0 63 | */ 64 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, 65 | properties = { 66 | "spring.cloud.function.definition=kinesisSupplier;kinesisConsumer", 67 | "spring.cloud.stream.bindings.kinesisSupplier-out-0.destination=" + KinesisBinderObservationTests.KINESIS_STREAM, 68 | "spring.cloud.stream.kinesis.bindings.kinesisSupplier-out-0.producer.recordMetadataChannel=producerResultsChannel", 69 | "spring.cloud.stream.bindings.kinesisConsumer-in-0.destination=" + KinesisBinderObservationTests.KINESIS_STREAM, 70 | "spring.cloud.stream.bindings.kinesisConsumer-in-0.group=observation-group", 71 | "spring.cloud.stream.kinesis.binder.enable-observation=true", 72 | "spring.cloud.stream.kinesis.binder.legacy-embedded-headers-format=true", 73 | "logging.level.org.springframework.cloud.stream.binder.kinesis.observation=debug", 74 | "management.tracing.sampling.probability=1.0"}) 75 | @AutoConfigureObservability 76 | @DirtiesContext 77 | public class KinesisBinderObservationTests implements LocalstackContainerTest { 78 | 79 | private static final Log LOGGER = LogFactory.getLog(KinesisBinderObservationTests.class); 80 | 81 | static final String KINESIS_STREAM = "test_observation_stream"; 82 | 83 | private static final TestSpanHandler SPANS = new TestSpanHandler(); 84 | 85 | @Autowired 86 | private CountDownLatch messageBarrier; 87 | 88 | @Autowired 89 | private AtomicReference> messageHolder; 90 | 91 | @Autowired 92 | QueueChannel producerResultsChannel; 93 | 94 | @Test 95 | void observationIsPropagatedFromSupplierToConsumer() throws InterruptedException { 96 | assertThat(this.messageBarrier.await(30, TimeUnit.SECONDS)).isTrue(); 97 | Message message = this.messageHolder.get(); 98 | assertThat(message.getHeaders()).containsKeys("traceparent"); 99 | assertThat(message.getPayload()).isEqualTo("test data"); 100 | 101 | await().until(() -> SPANS.spans().size() == 3); 102 | SpansAssert.assertThat(SPANS.spans().stream().map(BraveFinishedSpan::fromBrave).toList()) 103 | .haveSameTraceId() 104 | .hasASpanWithName("kinesisSupplier-out-0 send", 105 | spanAssert -> spanAssert.hasKindEqualTo(Span.Kind.PRODUCER) 106 | .hasTag(IntegrationObservation.ProducerTags.COMPONENT_TYPE, "producer")) 107 | .hasASpanWithName(String.format("Consumer for [%s] receive", KINESIS_STREAM), 108 | spanAssert -> spanAssert.hasKindEqualTo(Span.Kind.CONSUMER) 109 | .hasTag(IntegrationObservation.HandlerTags.COMPONENT_TYPE, "handler")) 110 | .hasASpanWithName("kinesis-consumer process"); // Function part 111 | 112 | Message producerResultMessage = producerResultsChannel.receive(10_000); 113 | assertThat(producerResultMessage.getPayload()).isEqualTo("test data".getBytes()); 114 | assertThat(producerResultMessage.getHeaders()).containsKeys(AwsHeaders.SHARD, AwsHeaders.SEQUENCE_NUMBER); 115 | } 116 | 117 | @Configuration 118 | @EnableAutoConfiguration 119 | static class TestConfiguration { 120 | 121 | 122 | @Bean 123 | SpanHandler spanHandler() { 124 | return SPANS; 125 | } 126 | 127 | @Bean 128 | public LockRegistry lockRegistry() { 129 | return new DefaultLockRegistry(); 130 | } 131 | 132 | @Bean 133 | public ConcurrentMetadataStore checkpointStore() { 134 | return new SimpleMetadataStore(); 135 | } 136 | 137 | @Bean 138 | public AtomicReference> messageHolder() { 139 | return new AtomicReference<>(); 140 | } 141 | 142 | @Bean 143 | public CountDownLatch messageBarrier() { 144 | return new CountDownLatch(1); 145 | } 146 | 147 | @Bean 148 | public Supplier>> kinesisSupplier() { 149 | return () -> Flux.just("test data").map(GenericMessage::new); 150 | } 151 | 152 | @Bean 153 | QueueChannel producerResultsChannel() { 154 | return new QueueChannel(); 155 | } 156 | 157 | @Bean 158 | @GlobalChannelInterceptor(patterns = "kinesisSupplier-out-0") 159 | ChannelInterceptor loggingChannelInterceptor() { 160 | return new ChannelInterceptor() { 161 | 162 | @Override 163 | public Message preSend(Message message, MessageChannel channel) { 164 | LOGGER.debug("Send message: " + message); 165 | return message; 166 | } 167 | 168 | }; 169 | } 170 | 171 | @Bean 172 | public Consumer> kinesisConsumer() { 173 | return message -> { 174 | LOGGER.debug("Received message: " + message); 175 | messageHolder().set(message); 176 | messageBarrier().countDown(); 177 | }; 178 | } 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/test/java/org/springframework/cloud/stream/binder/kinesis/provisioning/KinesisStreamProvisionerTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2022 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 | 17 | package org.springframework.cloud.stream.binder.kinesis.provisioning; 18 | 19 | import java.time.Duration; 20 | 21 | import org.junit.jupiter.api.BeforeAll; 22 | import org.junit.jupiter.api.Test; 23 | import software.amazon.awssdk.core.retry.backoff.FixedDelayBackoffStrategy; 24 | import software.amazon.awssdk.services.kinesis.KinesisAsyncClient; 25 | import software.amazon.awssdk.services.kinesis.model.ResourceNotFoundException; 26 | 27 | import org.springframework.cloud.stream.binder.ExtendedConsumerProperties; 28 | import org.springframework.cloud.stream.binder.ExtendedProducerProperties; 29 | import org.springframework.cloud.stream.binder.HeaderMode; 30 | import org.springframework.cloud.stream.binder.kinesis.LocalstackContainerTest; 31 | import org.springframework.cloud.stream.binder.kinesis.properties.KinesisBinderConfigurationProperties; 32 | import org.springframework.cloud.stream.binder.kinesis.properties.KinesisConsumerProperties; 33 | import org.springframework.cloud.stream.binder.kinesis.properties.KinesisProducerProperties; 34 | import org.springframework.cloud.stream.provisioning.ConsumerDestination; 35 | import org.springframework.cloud.stream.provisioning.ProducerDestination; 36 | import org.springframework.cloud.stream.provisioning.ProvisioningException; 37 | 38 | import static org.assertj.core.api.Assertions.assertThat; 39 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 40 | 41 | /** 42 | * Tests for the {@link KinesisStreamProvisioner}. 43 | * 44 | * @author Jacob Severson 45 | * @author Artem Bilan 46 | * @author Sergiu Pantiru 47 | */ 48 | class KinesisStreamProvisionerTests implements LocalstackContainerTest { 49 | 50 | private static KinesisAsyncClient AMAZON_KINESIS; 51 | 52 | @BeforeAll 53 | static void setup() { 54 | AMAZON_KINESIS = LocalstackContainerTest.kinesisClient(); 55 | } 56 | 57 | private void createStream(String streamName) { 58 | AMAZON_KINESIS.createStream(request -> request.streamName(streamName).shardCount(1)) 59 | .thenCompose(reply -> AMAZON_KINESIS.waiter() 60 | .waitUntilStreamExists(request -> request.streamName(streamName), 61 | waiter -> waiter 62 | .maxAttempts(60) 63 | .backoffStrategy(FixedDelayBackoffStrategy.create(Duration.ofSeconds(1))))) 64 | .join(); 65 | } 66 | 67 | @Test 68 | void testProvisionProducerSuccessfulWithExistingStream() { 69 | String streamName = "provisioning1"; 70 | createStream(streamName); 71 | 72 | KinesisBinderConfigurationProperties binderProperties = new KinesisBinderConfigurationProperties(); 73 | KinesisStreamProvisioner provisioner = new KinesisStreamProvisioner(AMAZON_KINESIS, binderProperties); 74 | ExtendedProducerProperties extendedProducerProperties = 75 | new ExtendedProducerProperties<>(new KinesisProducerProperties()); 76 | 77 | ProducerDestination destination = 78 | provisioner.provisionProducerDestination(streamName, extendedProducerProperties); 79 | 80 | assertThat(destination.getName()).isEqualTo(streamName); 81 | assertThat(destination).isInstanceOf(KinesisProducerDestination.class); 82 | assertThat(destination).extracting("shards").asList().hasSize(1); 83 | } 84 | 85 | @Test 86 | void testProvisionConsumerSuccessfulWithExistingStream() { 87 | String streamName = "provisioning2"; 88 | createStream(streamName); 89 | 90 | KinesisBinderConfigurationProperties binderProperties = new KinesisBinderConfigurationProperties(); 91 | KinesisStreamProvisioner provisioner = new KinesisStreamProvisioner(AMAZON_KINESIS, binderProperties); 92 | 93 | ExtendedConsumerProperties extendedConsumerProperties = 94 | new ExtendedConsumerProperties<>(new KinesisConsumerProperties()); 95 | extendedConsumerProperties.setHeaderMode(HeaderMode.embeddedHeaders); 96 | 97 | String group = "test-group"; 98 | ConsumerDestination destination = 99 | provisioner.provisionConsumerDestination(streamName, group, extendedConsumerProperties); 100 | 101 | assertThat(destination.getName()).isEqualTo(streamName); 102 | assertThat(destination).isInstanceOf(KinesisConsumerDestination.class); 103 | assertThat(destination).extracting("shards").asList().hasSize(1); 104 | assertThat(extendedConsumerProperties.getExtension().isEmbedHeaders()).isTrue(); 105 | assertThat(extendedConsumerProperties.getHeaderMode()).isEqualTo(HeaderMode.none); 106 | } 107 | 108 | @Test 109 | void testProvisionConsumerExistingStreamUpdateShards() { 110 | String streamName = "provisioning3"; 111 | createStream(streamName); 112 | 113 | KinesisBinderConfigurationProperties binderProperties = new KinesisBinderConfigurationProperties(); 114 | int targetShardCount = 2; 115 | binderProperties.setMinShardCount(targetShardCount); 116 | binderProperties.setAutoAddShards(true); 117 | KinesisStreamProvisioner provisioner = new KinesisStreamProvisioner(AMAZON_KINESIS, binderProperties); 118 | 119 | ExtendedConsumerProperties extendedConsumerProperties = 120 | new ExtendedConsumerProperties<>(new KinesisConsumerProperties()); 121 | 122 | String group = "test-group"; 123 | ConsumerDestination destination = 124 | provisioner.provisionConsumerDestination(streamName, group, extendedConsumerProperties); 125 | 126 | assertThat(destination.getName()).isEqualTo(streamName); 127 | assertThat(destination).isInstanceOf(KinesisConsumerDestination.class); 128 | assertThat(destination).extracting("shards").asList().hasSizeGreaterThanOrEqualTo(2); 129 | } 130 | 131 | @Test 132 | void testProvisionProducerSuccessfulWithNewStream() { 133 | String streamName = "provisioning4"; 134 | KinesisBinderConfigurationProperties binderProperties = new KinesisBinderConfigurationProperties(); 135 | KinesisStreamProvisioner provisioner = new KinesisStreamProvisioner(AMAZON_KINESIS, binderProperties); 136 | ExtendedProducerProperties extendedProducerProperties = 137 | new ExtendedProducerProperties<>(new KinesisProducerProperties()); 138 | 139 | ProducerDestination destination = 140 | provisioner.provisionProducerDestination(streamName, extendedProducerProperties); 141 | 142 | assertThat(destination.getName()).isEqualTo(streamName); 143 | assertThat(destination).isInstanceOf(KinesisProducerDestination.class); 144 | assertThat(destination).extracting("shards").asList().hasSize(1); 145 | } 146 | 147 | @Test 148 | void testProvisionConsumerResourceNotFoundException() { 149 | KinesisBinderConfigurationProperties binderProperties = new KinesisBinderConfigurationProperties(); 150 | binderProperties.setAutoCreateStream(false); 151 | KinesisStreamProvisioner provisioner = new KinesisStreamProvisioner(AMAZON_KINESIS, binderProperties); 152 | int instanceCount = 1; 153 | int concurrency = 1; 154 | 155 | ExtendedConsumerProperties extendedConsumerProperties = 156 | new ExtendedConsumerProperties<>(new KinesisConsumerProperties()); 157 | extendedConsumerProperties.setInstanceCount(instanceCount); 158 | extendedConsumerProperties.setConcurrency(concurrency); 159 | 160 | String name = "provisioning5"; 161 | String group = "test-group"; 162 | 163 | assertThatThrownBy(() -> provisioner.provisionConsumerDestination(name, group, 164 | extendedConsumerProperties)) 165 | .isInstanceOf(ProvisioningException.class) 166 | .hasMessageContaining( 167 | "The stream [provisioning5] was not found and auto creation is disabled.") 168 | .hasCauseInstanceOf(ResourceNotFoundException.class); 169 | } 170 | 171 | } 172 | -------------------------------------------------------------------------------- /spring-cloud-stream-binder-kinesis/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%X{traceId:-},%X{spanId:-}] - %msg%n 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | --------------------------------------------------------------------------------