├── .github ├── dependabot.yml └── workflows │ ├── codeql-analysis.yml │ └── test.yml ├── .gitignore ├── README.md ├── pom.xml └── src ├── main ├── java │ └── io │ │ └── github │ │ └── majusko │ │ └── java │ │ └── pulsar │ │ └── example │ │ ├── JavaPulsarExampleApplication.java │ │ ├── configuration │ │ ├── ProducerConfiguration.java │ │ └── Topics.java │ │ ├── consumer │ │ └── ConsumerService.java │ │ ├── data │ │ └── MyMsg.java │ │ ├── error │ │ └── PulsarErrorHandler.java │ │ └── producer │ │ └── ProducerService.java └── resources │ └── application.properties └── test └── java └── io └── github └── majusko └── java └── pulsar └── example └── JavaPulsarExampleApplicationTests.java /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | ignore: 9 | - dependency-name: org.springframework.boot:spring-boot-starter-parent 10 | versions: 11 | - 2.4.3 12 | - 2.4.4 13 | - dependency-name: org.testcontainers:pulsar 14 | versions: 15 | - 1.15.2 16 | - dependency-name: org.testcontainers:junit-jupiter 17 | versions: 18 | - 1.15.2 19 | - dependency-name: org.testcontainers:testcontainers 20 | versions: 21 | - 1.15.2 22 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | schedule: 9 | - cron: '43 18 * * 0' 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | language: [ 'java' ] 24 | 25 | steps: 26 | - name: Checkout repository 27 | uses: actions/checkout@v2 28 | 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v1 31 | with: 32 | languages: ${{ matrix.language }} 33 | - name: Autobuild 34 | uses: github/codeql-action/autobuild@v1 35 | - name: Perform CodeQL Analysis 36 | uses: github/codeql-action/analyze@v1 37 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | branches: 7 | - master 8 | push: 9 | branches: 10 | - master 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 11 23 | - name: Build with Maven 24 | run: mvn -B test 25 | - name: Upload coverage to Codecov 26 | uses: codecov/codecov-action@v2 27 | with: 28 | verbose: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Example project for [Pulsar Spring Boot Starter](https://github.com/majusko/pulsar-java-spring-boot-starter) 2 | 3 | [![Build Status](https://github.com/majusko/java-pulsar-example/actions/workflows/test.yml/badge.svg)](https://github.com/majusko/java-pulsar-example/actions/workflows/test.yml) 4 | [![Test Coverage](https://codecov.io/gh/majusko/java-pulsar-example/branch/master/graph/badge.svg)](https://codecov.io/gh/majusko/java-pulsar-example/branch/master) 5 | [![TCode Quality](https://github.com/majusko/java-pulsar-example/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/majusko/java-pulsar-example/actions/workflows/codeql-analysis.yml) 6 | 7 | 8 | ### Project consists of 9 | 1. Consumer registration example 10 | 2. Producer registration example 11 | 3. Simple error handler 12 | 4. Integration test usage example -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.6.6 9 | 10 | 11 | io.github.majusko 12 | java-pulsar-example 13 | 0.0.1-SNAPSHOT 14 | java-pulsar-example 15 | Example project for Spring boot starter for Apache Pulsar 16 | 17 | 18 | 11 19 | 20 | 21 | 1.17.6 22 | 5.9.1 23 | 4.2.0 24 | 25 | 26 | 27 | 28 | io.github.majusko 29 | pulsar-java-spring-boot-starter 30 | 1.1.2 31 | 32 | 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-test 38 | test 39 | 40 | 41 | 42 | junit 43 | junit 44 | 45 | 46 | org.junit.vintage 47 | junit-vintage-engine 48 | 49 | 50 | 51 | 52 | 53 | 54 | org.junit.jupiter 55 | junit-jupiter-engine 56 | ${junit-jupiter.version} 57 | test 58 | 59 | 60 | 61 | 62 | org.testcontainers 63 | testcontainers 64 | ${testcontainers.version} 65 | test 66 | 67 | 68 | 69 | org.testcontainers 70 | junit-jupiter 71 | ${testcontainers.version} 72 | test 73 | 74 | 75 | 76 | org.testcontainers 77 | pulsar 78 | ${testcontainers.version} 79 | test 80 | 81 | 82 | 83 | org.awaitility 84 | awaitility 85 | ${awaitility.version} 86 | test 87 | 88 | 89 | 90 | 91 | 92 | 93 | org.springframework.boot 94 | spring-boot-maven-plugin 95 | 96 | 97 | org.jacoco 98 | jacoco-maven-plugin 99 | 0.8.8 100 | 101 | 102 | **/*Properties.* 103 | **/*Configuration.* 104 | **/*Application.* 105 | 106 | 107 | 108 | 109 | 110 | prepare-agent 111 | 112 | 113 | 114 | report 115 | test 116 | 117 | report 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /src/main/java/io/github/majusko/java/pulsar/example/JavaPulsarExampleApplication.java: -------------------------------------------------------------------------------- 1 | package io.github.majusko.java.pulsar.example; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class JavaPulsarExampleApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(JavaPulsarExampleApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/io/github/majusko/java/pulsar/example/configuration/ProducerConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.github.majusko.java.pulsar.example.configuration; 2 | 3 | import io.github.majusko.java.pulsar.example.data.MyMsg; 4 | import io.github.majusko.pulsar.producer.ProducerFactory; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class ProducerConfiguration { 10 | 11 | @Bean 12 | public ProducerFactory producerFactory() { 13 | return new ProducerFactory() 14 | .addProducer(Topics.STRING, String.class) 15 | .addProducer(Topics.CLASS, MyMsg.class); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/io/github/majusko/java/pulsar/example/configuration/Topics.java: -------------------------------------------------------------------------------- 1 | package io.github.majusko.java.pulsar.example.configuration; 2 | 3 | public class Topics { 4 | private Topics() { 5 | } 6 | 7 | public static final String STRING = "example-string-topic"; 8 | public static final String CLASS = "example-class-topic"; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/io/github/majusko/java/pulsar/example/consumer/ConsumerService.java: -------------------------------------------------------------------------------- 1 | package io.github.majusko.java.pulsar.example.consumer; 2 | 3 | import io.github.majusko.java.pulsar.example.configuration.Topics; 4 | import io.github.majusko.java.pulsar.example.data.MyMsg; 5 | import io.github.majusko.pulsar.annotation.PulsarConsumer; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.concurrent.atomic.AtomicBoolean; 9 | 10 | @Service 11 | public class ConsumerService { 12 | public AtomicBoolean stringReceived = new AtomicBoolean(false); 13 | public AtomicBoolean classReceived = new AtomicBoolean(false); 14 | 15 | @PulsarConsumer(topic = Topics.STRING, clazz = String.class) 16 | public void consumeString(String message) { 17 | System.out.println(message); 18 | stringReceived.set(true); 19 | } 20 | 21 | @PulsarConsumer(topic = Topics.CLASS, clazz = MyMsg.class) 22 | public void consumeClass(MyMsg message) { 23 | System.out.println(message.getData()); 24 | classReceived.set(true); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/github/majusko/java/pulsar/example/data/MyMsg.java: -------------------------------------------------------------------------------- 1 | package io.github.majusko.java.pulsar.example.data; 2 | 3 | public class MyMsg { 4 | 5 | private String data; 6 | 7 | public MyMsg(String data) { 8 | this.data = data; 9 | } 10 | 11 | public MyMsg() {} 12 | 13 | public String getData() { 14 | return data; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/github/majusko/java/pulsar/example/error/PulsarErrorHandler.java: -------------------------------------------------------------------------------- 1 | package io.github.majusko.java.pulsar.example.error; 2 | 3 | import io.github.majusko.pulsar.consumer.ConsumerAggregator; 4 | import org.springframework.boot.context.event.ApplicationReadyEvent; 5 | import org.springframework.context.event.EventListener; 6 | import org.springframework.stereotype.Service; 7 | 8 | @Service 9 | public class PulsarErrorHandler { 10 | 11 | private final ConsumerAggregator aggregator; 12 | 13 | public PulsarErrorHandler(ConsumerAggregator aggregator) { 14 | this.aggregator = aggregator; 15 | } 16 | 17 | @EventListener(ApplicationReadyEvent.class) 18 | public void pulsarErrorHandler() { 19 | aggregator.onError(failedMessage -> failedMessage.getException().printStackTrace()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/github/majusko/java/pulsar/example/producer/ProducerService.java: -------------------------------------------------------------------------------- 1 | package io.github.majusko.java.pulsar.example.producer; 2 | 3 | import io.github.majusko.java.pulsar.example.configuration.Topics; 4 | import io.github.majusko.java.pulsar.example.data.MyMsg; 5 | import io.github.majusko.pulsar.producer.PulsarTemplate; 6 | import org.apache.pulsar.client.api.PulsarClientException; 7 | import org.springframework.stereotype.Service; 8 | 9 | @Service 10 | public class ProducerService { 11 | 12 | private final PulsarTemplate stringProducer; 13 | 14 | private final PulsarTemplate classProducer; 15 | 16 | public ProducerService(PulsarTemplate stringProducer, PulsarTemplate classProducer) { 17 | this.stringProducer = stringProducer; 18 | this.classProducer = classProducer; 19 | } 20 | 21 | public void sendStringMsg() throws PulsarClientException { 22 | stringProducer.send(Topics.STRING, "Hello World String!"); 23 | } 24 | 25 | public void sendClassMsg() throws PulsarClientException { 26 | classProducer.send(Topics.CLASS, new MyMsg("Hello World Class!")); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/test/java/io/github/majusko/java/pulsar/example/JavaPulsarExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package io.github.majusko.java.pulsar.example; 2 | 3 | import io.github.majusko.java.pulsar.example.consumer.ConsumerService; 4 | import io.github.majusko.java.pulsar.example.producer.ProducerService; 5 | import org.apache.pulsar.client.api.PulsarClientException; 6 | import org.junit.jupiter.api.Test; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.context.DynamicPropertyRegistry; 10 | import org.springframework.test.context.DynamicPropertySource; 11 | import org.testcontainers.containers.PulsarContainer; 12 | import org.testcontainers.junit.jupiter.Container; 13 | import org.testcontainers.junit.jupiter.Testcontainers; 14 | import org.testcontainers.utility.DockerImageName; 15 | 16 | import static org.awaitility.Awaitility.await; 17 | 18 | @SpringBootTest 19 | @Testcontainers 20 | class JavaPulsarExampleApplicationTests { 21 | 22 | @Autowired 23 | private ProducerService producerService; 24 | 25 | @Autowired 26 | private ConsumerService consumerService; 27 | 28 | @Container 29 | static PulsarContainer pulsarContainer = new PulsarContainer(DockerImageName.parse("apachepulsar/pulsar:latest")); 30 | 31 | @DynamicPropertySource 32 | static void propertySettings(DynamicPropertyRegistry registry) { 33 | registry.add("pulsar.serviceUrl", pulsarContainer::getPulsarBrokerUrl); 34 | } 35 | 36 | @Test 37 | void stringTest() throws PulsarClientException { 38 | await().untilFalse(consumerService.stringReceived); 39 | 40 | producerService.sendStringMsg(); 41 | 42 | await().untilTrue(consumerService.stringReceived); 43 | } 44 | 45 | @Test 46 | void classTest() throws PulsarClientException { 47 | await().untilFalse(consumerService.classReceived); 48 | 49 | producerService.sendClassMsg(); 50 | 51 | await().untilTrue(consumerService.classReceived); 52 | } 53 | } 54 | --------------------------------------------------------------------------------