From 84671f1ffee273d4af7c9474a116570c748069b6 Mon Sep 17 00:00:00 2001 From: Jeffrey Douangpaseuth <11084623+Nephery@users.noreply.github.com> Date: Thu, 9 Dec 2021 12:04:10 -0500 Subject: [PATCH 1/5] add publishing tasks --- build.gradle | 83 +++++++++++++++++++ gradle.properties | 3 +- .../kafka/connect/sink/SolSessionHandler.java | 1 - .../kafka/connect/sink/SolaceSinkSender.java | 1 - 4 files changed, 85 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 1da9b66..8676719 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,15 @@ import com.github.spotbugs.snom.SpotBugsTask +import io.github.gradlenexus.publishplugin.InitializeNexusStagingRepository plugins { id 'java' id 'distribution' id 'jacoco' + id 'maven-publish' id 'pmd' + id 'signing' id 'com.github.spotbugs' version '4.7.6' + id 'io.github.gradle-nexus.publish-plugin' version '1.1.0' id 'org.gradle.test-retry' version '1.3.1' id 'org.unbroken-dome.test-sets' version '2.2.1' } @@ -13,6 +17,7 @@ plugins { ext { kafkaVersion = '2.8.1' solaceJavaAPIVersion = '10.12.1' + isSnapshot = project.version.endsWith('-SNAPSHOT') } repositories { @@ -186,6 +191,11 @@ project.compileJava { dependsOn generateJava } +java { + withJavadocJar() + withSourcesJar() +} + distributions { main { contents { @@ -202,3 +212,76 @@ distributions { } } } + +publishing { + publications { + maven(MavenPublication) { + from components.java + pom { + name = "Solace PubSub+ Connector for Kafka: Sink" + description = "The Solace/Kafka adapter consumes Kafka topic records and streams them to the PubSub+ Event Mesh as topic and/or queue data events." + url = "https://github.com/SolaceProducts/pubsubplus-connector-kafka-sink" + packaging = "jar" + licenses { + license { + name = "Apache License, Version 2.0" + url = "https://github.com/SolaceProducts/pubsubplus-connector-kafka-sink/blob/master/LICENSE" + distribution = "repo" + } + } + organization { + name = "Solace" + url = "https://www.solace.com" + } + developers { + developer { + name = "Support for Solace" + email = "support@solace.com" + organization = "Solace" + organizationUrl = "http://solace.community" + } + } + scm { + connection = "scm:git:git://github.com/SolaceProducts/pubsubplus-connector-kafka-sink.git" + developerConnection = "scm:git:git@github.com:SolaceProducts/pubsubplus-connector-kafka-sink.git" + url = "https://github.com/SolaceProducts/pubsubplus-connector-kafka-sink.git" + } + } + } + } +} + +nexusPublishing { + repositories { + internal { + nexusUrl = uri('http://apps-jenkins:9090/nexus/') + snapshotRepositoryUrl = uri('http://apps-jenkins:9090/nexus/content/repositories/snapshots') + // gets credentials from project.properties["internalUsername"] project.properties["internalPassword"] + } + sonatype { + nexusUrl = uri('https://oss.sonatype.org/service/local/') + snapshotRepositoryUrl = uri('https://oss.sonatype.org/content/repositories/snapshots') + // gets credentials from project.properties["sonatypeUsername"] project.properties["sonatypePassword"] + } + } +} + +signing { + required { + !isSnapshot + } + useGpgCmd() + sign publishing.publications.maven +} + +tasks.withType(Sign) { + onlyIf { + gradle.taskGraph.allTasks.any {task -> + task.name.startsWith("publish") && task.name.contains('Sonatype') + } + } +} + +tasks.withType(InitializeNexusStagingRepository).configureEach { + shouldRunAfter(tasks.withType(Sign)) +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 16cc23c..daf8797 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,2 @@ -version=2.1.0 \ No newline at end of file +group=com.solace.connector.kafka.connect +version=2.2.0 \ No newline at end of file diff --git a/src/main/java/com/solace/connector/kafka/connect/sink/SolSessionHandler.java b/src/main/java/com/solace/connector/kafka/connect/sink/SolSessionHandler.java index 2f1c37a..01b10b2 100644 --- a/src/main/java/com/solace/connector/kafka/connect/sink/SolSessionHandler.java +++ b/src/main/java/com/solace/connector/kafka/connect/sink/SolSessionHandler.java @@ -167,7 +167,6 @@ public void configureSession() { /** * Create and connect JCSMPSession - * @return * @throws JCSMPException */ public void connectSession() throws JCSMPException { diff --git a/src/main/java/com/solace/connector/kafka/connect/sink/SolaceSinkSender.java b/src/main/java/com/solace/connector/kafka/connect/sink/SolaceSinkSender.java index 2a854ae..ab9d9ee 100644 --- a/src/main/java/com/solace/connector/kafka/connect/sink/SolaceSinkSender.java +++ b/src/main/java/com/solace/connector/kafka/connect/sink/SolaceSinkSender.java @@ -208,7 +208,6 @@ public synchronized void commit() throws JCSMPException { /** * Shutdown TXProducer and Topic Producer. - * @return */ public void shutdown() { producerHandler.close(); From 17b0bac9eb691e015f318709508f0159df32535a Mon Sep 17 00:00:00 2001 From: Jeffrey Douangpaseuth <11084623+Nephery@users.noreply.github.com> Date: Thu, 9 Dec 2021 12:39:43 -0500 Subject: [PATCH 2/5] add publish dependency on test and integrationTest --- build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8676719..9326226 100644 --- a/build.gradle +++ b/build.gradle @@ -103,6 +103,7 @@ project.integrationTest { useJUnitPlatform() outputs.upToDateWhen { false } dependsOn prepDistForIntegrationTesting + shouldRunAfter test retry { maxRetries = 3 } @@ -280,8 +281,10 @@ tasks.withType(Sign) { task.name.startsWith("publish") && task.name.contains('Sonatype') } } + shouldRunAfter test, integrationTest } tasks.withType(InitializeNexusStagingRepository).configureEach { - shouldRunAfter(tasks.withType(Sign)) + dependsOn test, integrationTest + shouldRunAfter tasks.withType(Sign) } \ No newline at end of file From 3805cb781d876a27de1517219ba319c712ded71c Mon Sep 17 00:00:00 2001 From: Jeffrey Douangpaseuth <11084623+Nephery@users.noreply.github.com> Date: Thu, 9 Dec 2021 17:30:40 -0500 Subject: [PATCH 3/5] publish directly to internal nexus releases repo --- build.gradle | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 9326226..5b14953 100644 --- a/build.gradle +++ b/build.gradle @@ -250,15 +250,22 @@ publishing { } } } + repositories { + maven { + def releasesUrl = uri('http://apps-jenkins:9090/nexus/content/repositories/releases') + def snapshotRepositoryUrl = uri('http://apps-jenkins:9090/nexus/content/repositories/snapshots') + url = isSnapshot ? snapshotRepositoryUrl : releasesUrl + name = 'internal' + credentials { + username = project.properties[name + "Username"] + password = project.properties[name + "Password"] + } + } + } } nexusPublishing { repositories { - internal { - nexusUrl = uri('http://apps-jenkins:9090/nexus/') - snapshotRepositoryUrl = uri('http://apps-jenkins:9090/nexus/content/repositories/snapshots') - // gets credentials from project.properties["internalUsername"] project.properties["internalPassword"] - } sonatype { nexusUrl = uri('https://oss.sonatype.org/service/local/') snapshotRepositoryUrl = uri('https://oss.sonatype.org/content/repositories/snapshots') @@ -287,4 +294,8 @@ tasks.withType(Sign) { tasks.withType(InitializeNexusStagingRepository).configureEach { dependsOn test, integrationTest shouldRunAfter tasks.withType(Sign) -} \ No newline at end of file +} + +tasks.withType(PublishToMavenRepository).configureEach { + dependsOn test, integrationTest +} From 7ebb5334bcd0da5e1e42ea53eea291e20cb6f3b2 Mon Sep 17 00:00:00 2001 From: Jeffrey Douangpaseuth <11084623+Nephery@users.noreply.github.com> Date: Fri, 10 Dec 2021 16:51:56 -0500 Subject: [PATCH 4/5] add deployer-pom.xml --- .gitignore | 2 +- deployer-pom.xml | 396 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 397 insertions(+), 1 deletion(-) create mode 100644 deployer-pom.xml diff --git a/.gitignore b/.gitignore index 4d2299d..0e26c64 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ /bin/ # Jave related -target/** +/target/ *.jar *.war *.ear diff --git a/deployer-pom.xml b/deployer-pom.xml new file mode 100644 index 0000000..2d1b8e4 --- /dev/null +++ b/deployer-pom.xml @@ -0,0 +1,396 @@ + + 4.0.0 + com.solace.deploy + solace-deployer + Solace Deployer + 1.0.0 + A pom for publishing release version to maven central + pom + + + ${project.build.directory}/localRepository + + + + + solace-internal + + true + + http://apps-jenkins:9090/nexus/content/groups/stable/ + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0 + + + enforce-property + + enforce + + + + + release.groupId + ^com.solace*(?:systems)?.*? + release.groupId must be a valid group ID that starts with "com.solace". + + + release.artifactId + + + release.version + ^(?:\d+\.){2}\d+$ + release.version must be a non-SNAPSHOT semantic version. + + + local.staging.dir + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + regex-property + + regex-property + + + release.install.groupPath + ${release.groupId} + \. + / + true + + + + + + org.apache.maven.plugins + maven-install-plugin + 2.5.2 + + true + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.2.0 + + + copy + deploy + + copy + + + ${project.build.directory}/tmpRepository + + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.md5 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.sha1 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.sha256 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.sha512 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + pom + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + pom.md5 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + pom.sha1 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + pom.sha256 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + pom.sha512 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar + javadoc + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.md5 + javadoc + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.sha1 + javadoc + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.sha256 + javadoc + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.sha512 + javadoc + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar + sources + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.md5 + sources + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.sha1 + sources + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.sha256 + sources + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + jar.sha512 + sources + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + module + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + module.md5 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + module.sha1 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + module.sha256 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + ${release.groupId} + ${release.artifactId} + ${release.version} + module.sha512 + true + + ${local.staging.dir}/${release.install.groupPath}/${release.artifactId}/${release.version}/ + + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.7 + + true + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + false + + + + + From 929f31d869c167f2282541afa329cd553aba5db5 Mon Sep 17 00:00:00 2001 From: Jeffrey Douangpaseuth <11084623+Nephery@users.noreply.github.com> Date: Wed, 15 Dec 2021 15:31:21 -0500 Subject: [PATCH 5/5] update README for externally creating custom record processors --- README.md | 59 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index a4aadc3..ca279b0 100644 --- a/README.md +++ b/README.md @@ -337,16 +337,22 @@ Kerberos has some very specific requirements to operate correctly. Some addition JDK 8 or higher is required for this project. -First, clone this GitHub repo: -```shell -git clone https://github.com/SolaceProducts/pubsubplus-connector-kafka-sink.git -cd pubsubplus-connector-kafka-sink -``` - -Then run the build script: -```shell -./gradlew clean build -``` +1. First, clone this GitHub repo: + ```shell + git clone https://github.com/SolaceProducts/pubsubplus-connector-kafka-sink.git + cd pubsubplus-connector-kafka-sink + ``` +2. Install the test support module: + ```shell + git submodule update --init --recursive + cd solace-integration-test-support + ./mvnw clean install -DskipTests + cd .. + ``` +3. Then run the build script: + ```shell + ./gradlew clean build + ``` This script creates artifacts in the `build` directory, including the deployable packaged PubSub+ Sink Connector archives under `build\distributions`. @@ -354,27 +360,40 @@ This script creates artifacts in the `build` directory, including the deployable An integration test suite is also included, which spins up a Docker-based deployment environment that includes a PubSub+ event broker, Zookeeper, Kafka broker, Kafka Connect. It deploys the connector to Kafka Connect and runs end-to-end tests. -1. Install the test support module: - ```shell - git submodule update --init --recursive - cd solace-integration-test-support - ./mvnw clean install -DskipTests - cd .. - ``` -2. Run the tests: +1. Run the tests: ```shell ./gradlew clean test integrationTest ``` ### Build a New Record Processor -The processing of a Kafka record to create a PubSub+ message is handled by an interface defined in [`SolRecordProcessorIF.java`](/src/main/java/com/solace/connector/kafka/connect/sink/SolRecordProcessorIF.java). This is a simple interface that creates the Kafka source records from the PubSub+ messages. This project includes three examples of classes that implement this interface: +The processing of a Kafka record to create a PubSub+ message is handled by [`SolRecordProcessorIF`](/src/main/java/com/solace/connector/kafka/connect/sink/SolRecordProcessorIF.java). This is a simple interface that creates the Kafka source records from the PubSub+ messages. + +To get started, import the following dependency into your project: + +**Maven** +```xml + + com.solace.connector.kafka.connect + pubsubplus-connector-kafka-sink + 2.2.0 + +``` + +**Gradle** +```groovy +compile "com.solace.connector.kafka.connect:pubsubplus-connector-kafka-sink:2.2.0" +``` + +Now you can implement your custom `SolRecordProcessorIF`. + +For reference, this project includes three examples which you can use as starting points for implementing your own custom record processors: * [SolSimpleRecordProcessor](/src/main/java/com/solace/connector/kafka/connect/sink/recordprocessor/SolSimpleRecordProcessor.java) * [SolSimpleKeyedRecordProcessor](/src/main/java/com/solace/connector/kafka/connect/sink/recordprocessor/SolSimpleKeyedRecordProcessor.java) * [SolDynamicDestinationRecordProcessor](/src/main/java/com/solace/connector/kafka/connect/sink/recordprocessor/SolDynamicDestinationRecordProcessor.java) -You can use these examples as starting points for implementing your own custom record processors. +Once you've built the jar file for your custom record processor project, place it into the same directory as this connector, and update the connector's `sol.record_processor_class` config to point to the class of your new record processor. More information on Kafka sink connector development can be found here: - [Apache Kafka Connect](https://kafka.apache.org/documentation/)