├── .gitignore
├── README.md
├── disruptor-billing-mbean-browser.PNG
├── pom.xml
└── src
└── main
├── java
└── org
│ └── anair
│ ├── billing
│ ├── disruptor
│ │ ├── eventfactory
│ │ │ └── BillingEvent.java
│ │ ├── eventprocessor
│ │ │ ├── BillingBusinessEventProcessor.java
│ │ │ ├── BillingOutboundFormattingEventProcessor.java
│ │ │ ├── BillingValidationEventProcessor.java
│ │ │ ├── CorporateBillingBusinessEventProcessor.java
│ │ │ ├── CustomerSpecificBillingBusinessEventProcessor.java
│ │ │ └── JournalBillingEventProcessor.java
│ │ ├── eventtranslator
│ │ │ └── BillingEventTranslator.java
│ │ └── publisher
│ │ │ └── BillingEventPublisher.java
│ ├── message
│ │ └── listener
│ │ │ └── BillingMessageListener.java
│ ├── model
│ │ └── BillingRecord.java
│ └── service
│ │ ├── BillingService.java
│ │ └── BillingServiceImpl.java
│ ├── datastream
│ ├── disruptor
│ │ ├── eventfactory
│ │ │ └── DataStreamEvent.java
│ │ ├── eventprocessor
│ │ │ ├── FormatDataStreamEventProcessor.java
│ │ │ ├── JournalDataStreamEventProcessor.java
│ │ │ ├── ProcessADataStreamEventProcessor.java
│ │ │ └── ProcessBDataStreamEventProcessor.java
│ │ ├── eventtranslator
│ │ │ └── DataStreamEventTranslator.java
│ │ └── publisher
│ │ │ └── DataStreamEventPublisher.java
│ ├── message
│ │ └── listener
│ │ │ └── DataStreamMessageListener.java
│ ├── model
│ │ └── DataStream.java
│ └── service
│ │ ├── DatastreamService.java
│ │ └── DatastreamServiceImpl.java
│ ├── main
│ └── SpringBootMQApplication.java
│ └── spring
│ └── config
│ └── jms
│ └── JmsConfiguration.java
└── resources
├── application.yml
├── log4j.properties
├── spring-billing-disruptor.xml
├── spring-datastream-disruptor.xml
├── spring-jms.xml
├── spring-jmx.xml
└── spring-service.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | .settings
2 | target
3 | .classpath
4 | .project
5 | .springBeans
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Spring Boot managed LMAX Disruptor Example project
2 | ==================
3 | This project uses [disruptor-spring-manager](https://github.com/anair-it/disruptor-spring-manager) to create disruptor spring beans and perform message transactions.
4 | The project uses spring boot to load up the application as a JMS listener. Integration with IBM Websphere MQ is required to run this project. Ofcourse you can make minor modifications to get this running against ActiveMQ etc.
5 |
6 | The example uses 2 disruptor beans. One to process billing records and another to process data streams. Both disruptors are configured as spring beans.
7 |
8 | Software pre-requisite
9 | --------
10 | 1. JDK 8+
11 | 2. Maven 3+
12 | 3. Git
13 | 4. IBM Websphere MQ 7.5 server and client jars
14 | 5. Spring boot 1.5.x
15 |
16 |
17 | Setting up your environment
18 | ----
19 | 1. Create a local queue manager. Name it as you wish.
20 | 2. Create a billing input queue. Name it as your wish.
21 | 3. Create a data stream input queue. Name it as your wish.
22 | 3. Start queue manager
23 | 4. Update _src/main/resources/application.yml_ with queue manager and queue names
24 |
25 |
26 | Configuring the disruptor
27 | ----------
28 |
29 | [Billing disruptor spring configuration](src/main/webapp/WEB-INF/spring-billing-disruptor.xml) is based on the Consumer Dependency diamond graph that looks like this:
30 |
31 | | journalBillingEventProcessor | billingBusinessEventProcessor |
32 | | / | / |
33 | | / | / |
34 | billingEventPublisher -> Ring Buffer ->| - | - corporateBillingBusinessEventProcessor | -billingOutboundFormattingEventProcessor
35 | | \ | \ |
36 | | \ | \ |
37 | | billingValidationEventProcessor | customerSpecificBillingBusinessEventProcessor |
38 |
39 |
40 | ---------
41 | [Data Stream disruptor spring configuration](src/main/webapp/WEB-INF/spring-datastream-disruptor.xml) is based on the Consumer Dependency diamond graph that looks like this:
42 |
43 | | | processADataStreamEventProcessor |
44 | | | / |
45 | | | / |
46 | dataStreamEventPublisher -> Ring Buffer ->| - journalBillingEventProcessor | | -formatDataStreamEventProcessor
47 | | | \ |
48 | | | \ |
49 | | | processBDataStreamEventProcessor |
50 |
51 |
52 | Components
53 | ----
54 | 1. [BillingRecord](src/main/java/org/anair/billing/model/BillingRecord.java) represents a Billing data model.
55 | 2. [BillingEvent](src/main/java/org/anair/billing/disruptor/eventfactory/BillingEvent.java) is used to preload the ringbuffer with BillingRecord objects so that they don't get GCed.
56 | 3. [BillingServiceImpl](src/main/java/org/anair/billing/service/BillingServiceImpl.java) performs billing business logic.
57 | 4. [BillingEventPublisher](src/main/java/org/anair/billing/disruptor/publisher/BillingEventPublisher.java) prepares to publish billing records to the ring buffer
58 | 5. [BillingEventTranslator](src/main/java/org/anair/billing/disruptor/eventtranslator/BillingEventTranslator.java) actually puts the data in ring buffer
59 | 6. [Event Processors/consumers](src/main/java/org/anair/billing/disruptor/eventprocessor) consume off the ring buffer and can perform parallel operations on the data
60 | 4. [BillingMessageListener](src/main/java/org/anair/billing/message/listener/BillingMessageListener.java) receives the MQ message and calls BillingEventPublisher.
61 | 5. [Billing Disruptor bean configuration](src/main/resources/spring-billing-disruptor.xml)
62 | 6. [Data stream Disruptor bean configuration](src/main/resources/spring-datastream-disruptor.xml)
63 | 7. [Spring configuration files](src/main/resources)
64 |
65 | Run it
66 | ----
67 | 1.Start application
68 |
69 | mvn clean package
70 | java -jar target/disruptor-billing.jar
71 | You will see the following log messages that prints the disruptor configuration and dependency graph:
72 |
73 | 15:58:17.269 localhost-startStop-1 INFO [BaseDisruptorConfig] Created and configured LMAX disruptor {Thread Name: billingThread | Ringbuffer slot size: 1024 | Producer type: SINGLE | Wait strategy: BLOCKING}
74 | 15:58:17.279 localhost-startStop-1 INFO [DefaultDisruptorConfig]
75 | {JournalBillingEventProcessor | BillingValidationEventProcessor} -> {BillingBusinessEventProcessor | CorporateBillingBusinessEventProcessor | CustomerSpecificBillingBusinessEventProcessor}
76 | {BillingBusinessEventProcessor | CorporateBillingBusinessEventProcessor | CustomerSpecificBillingBusinessEventProcessor} -> {BillingOutboundFormattingEventProcessor}
77 | 15:58:17.289 localhost-startStop-1 INFO [JmxDisruptor] disruptor-spring:name=billingDisruptor,type=disruptor MBean defined for Disruptors.
78 |
79 | 2.Drop a message to any/both input queue. The message should be a long that relays the number of billing messages to be generated and processed.
80 | If you put in message of "20", 20 messages will be processed and here is the log output summary:
81 |
82 | 16:11:37.189 billingListenerContainer-1 INFO [BillingEventTranslator] Published Id [0] to sequence: 0
83 | 16:11:37.189 billingListenerContainer-1 INFO [BillingEventTranslator] Published Id [10] to sequence: 10
84 | 16:11:37.199 billingThread-1 INFO [BillingValidationEventProcessor] Sequence: 0. Id [0]
85 | 16:11:37.269 billingThread-1 INFO [BillingValidationEventProcessor] Sequence: 10. Id [10]
86 | 16:11:37.199 billingThread-2 INFO [JournalBillingEventProcessor] Sequence: 0. Id [0]
87 | 16:11:37.289 billingThread-3 INFO [BillingBusinessEventProcessor] Sequence: 0. Id [0]
88 | 16:11:37.289 billingThread-4 INFO [CustomerSpecificBillingBusinessEventProcessor] Sequence: 0. Id [0]
89 | 16:11:37.299 billingThread-5 INFO [CorporateBillingBusinessEventProcessor] Sequence: 0. Id [0]
90 | 16:11:37.299 billingThread-2 INFO [JournalBillingEventProcessor] Sequence: 10. Id [10]
91 | 16:11:37.309 billingThread-4 INFO [CustomerSpecificBillingBusinessEventProcessor] Sequence: 10. Id [10]
92 | 16:11:37.309 billingThread-3 INFO [BillingBusinessEventProcessor] Sequence: 10. Id [10]
93 | 16:11:37.309 billingThread-6 INFO [BillingOutboundFormattingEventProcessor] Sequence: 0. Id [0]
94 | 16:11:37.309 billingThread-5 INFO [CorporateBillingBusinessEventProcessor] Sequence: 10. Id [10]
95 | 16:11:37.310 billingThread-6 INFO [BillingOutboundFormattingEventProcessor] Sequence: 10. Id [10]
96 |
97 |
98 | JMX
99 | ---
100 | 1.On application context startup, all Disruptor beans will be automatically identified and registered as MBeans
101 | 2.View Disruptor MBeans through JConsole/Visual VM that looks like: 
102 |
--------------------------------------------------------------------------------
/disruptor-billing-mbean-browser.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anair-it/disruptor-billing-example/4b0246730fd3d567f05f9cfb467d713867b59b09/disruptor-billing-mbean-browser.PNG
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | org.anair.disruptor.poc
5 | disruptor-billing
6 | jar
7 | 0.0.1
8 | disruptor-billing spring boot example application
9 |
10 |
11 | org.springframework.boot
12 | spring-boot-starter-parent
13 | 1.5.4.RELEASE
14 |
15 |
16 |
17 |
18 | Anoop Nair
19 | anoopnair.it@gmail.com
20 |
21 |
22 |
23 | 2014
24 |
25 |
26 | 1.8
27 | 0.0.1
28 | 7.0.1.3
29 |
30 |
31 |
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-maven-plugin
36 |
37 | true
38 |
39 |
40 |
41 | org.apache.maven.plugins
42 | maven-compiler-plugin
43 |
44 | ${java.version}
45 | ${java.version}
46 | UTF-8
47 |
48 |
49 |
50 | disruptor-billing
51 |
52 |
53 | src/main/resources
54 | true
55 |
56 |
57 |
58 |
59 |
60 |
61 | org.springframework.boot
62 | spring-boot-starter-activemq
63 |
64 |
65 | org.anair.disruptor
66 | disruptor-spring-manager
67 | ${disruptor.spring.manager.version}
68 |
69 |
70 | javax.jms
71 | jms
72 | 1.1
73 | compile
74 |
75 |
76 | com.ibm
77 | com.ibm.mqjms
78 | ${wmq.version}
79 | jar
80 | compile
81 |
82 |
83 | com.ibm
84 | com.ibm.mq
85 | ${wmq.version}
86 | jar
87 | compile
88 |
89 |
90 | com.ibm
91 | com.ibm.dhbcore
92 | ${wmq.version}
93 | jar
94 | compile
95 |
96 |
97 | com.ibm
98 | com.ibm.mq.jmqi
99 | ${wmq.version}
100 | jar
101 | compile
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/disruptor/eventfactory/BillingEvent.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.disruptor.eventfactory;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 |
5 | import com.lmax.disruptor.EventFactory;
6 |
7 | public class BillingEvent implements EventFactory {
8 |
9 | @Override
10 | public BillingRecord newInstance() {
11 | return new BillingRecord();
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/disruptor/eventprocessor/BillingBusinessEventProcessor.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.disruptor.eventprocessor;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 | import org.anair.billing.service.BillingService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Required;
8 |
9 | import com.lmax.disruptor.EventHandler;
10 |
11 | public class BillingBusinessEventProcessor implements EventHandler {
12 |
13 | private static final Logger LOG = LoggerFactory.getLogger(BillingBusinessEventProcessor.class);
14 | private BillingService billingService;
15 |
16 | @Override
17 | public void onEvent(BillingRecord billingRecord, long sequence, boolean endOfBatch)
18 | throws Exception {
19 | LOG.trace("Sequence: {}. Going to process {}", sequence, billingRecord.toString());
20 | billingService.processBillingRecord(billingRecord);
21 | if(sequence%100==0){
22 | LOG.info("Sequence: {}. {}",sequence, billingRecord.toString());
23 | }
24 | }
25 |
26 | @Required
27 | public void setBillingService(BillingService billingService) {
28 | this.billingService = billingService;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/disruptor/eventprocessor/BillingOutboundFormattingEventProcessor.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.disruptor.eventprocessor;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 | import org.anair.billing.service.BillingService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Required;
8 |
9 | import com.lmax.disruptor.EventHandler;
10 |
11 | public class BillingOutboundFormattingEventProcessor implements EventHandler {
12 |
13 | private static final Logger LOG = LoggerFactory.getLogger(BillingOutboundFormattingEventProcessor.class);
14 | private BillingService billingService;
15 |
16 | @Override
17 | public void onEvent(BillingRecord billingRecord, long sequence, boolean endOfBatch)
18 | throws Exception {
19 | LOG.trace("Sequence: {}. Going to process {}",sequence, billingRecord.toString());
20 | billingService.formatBillingRecord(billingRecord);
21 | if(sequence%10==0){
22 | LOG.info("Sequence: {}. {}",sequence, billingRecord.toString());
23 | }
24 | }
25 |
26 | @Required
27 | public void setBillingService(BillingService billingService) {
28 | this.billingService = billingService;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/disruptor/eventprocessor/BillingValidationEventProcessor.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.disruptor.eventprocessor;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 | import org.anair.billing.service.BillingService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Required;
8 |
9 | import com.lmax.disruptor.EventHandler;
10 |
11 | public class BillingValidationEventProcessor implements EventHandler {
12 |
13 | private static final Logger LOG = LoggerFactory.getLogger(BillingValidationEventProcessor.class);
14 | private BillingService billingService;
15 |
16 | @Override
17 | public void onEvent(BillingRecord billingRecord, long sequence, boolean endOfBatch)
18 | throws Exception {
19 | LOG.trace("Sequence: {}. Validating {}",sequence, billingRecord.toString());
20 | billingService.validateBillingRecord(billingRecord);
21 | if(sequence%10==0){
22 | LOG.info("Sequence: {}. {}",sequence, billingRecord.toString());
23 | }
24 | }
25 |
26 | @Required
27 | public void setBillingService(BillingService billingService) {
28 | this.billingService = billingService;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/disruptor/eventprocessor/CorporateBillingBusinessEventProcessor.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.disruptor.eventprocessor;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 | import org.anair.billing.service.BillingService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Required;
8 |
9 | import com.lmax.disruptor.EventHandler;
10 |
11 | public class CorporateBillingBusinessEventProcessor implements EventHandler {
12 |
13 | private static final Logger LOG = LoggerFactory.getLogger(CorporateBillingBusinessEventProcessor.class);
14 | private BillingService billingService;
15 |
16 | @Override
17 | public void onEvent(BillingRecord billingRecord, long sequence, boolean endOfBatch)
18 | throws Exception {
19 | LOG.trace("Sequence: {}. Going to process {}",sequence, billingRecord.toString());
20 | billingService.processCorporateBillingRecord(billingRecord);
21 | if(sequence%10==0){
22 | LOG.info("Sequence: {}. ",sequence, billingRecord.toString());
23 | }
24 | }
25 |
26 | @Required
27 | public void setBillingService(BillingService billingService) {
28 | this.billingService = billingService;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/disruptor/eventprocessor/CustomerSpecificBillingBusinessEventProcessor.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.disruptor.eventprocessor;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 | import org.anair.billing.service.BillingService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Required;
8 |
9 | import com.lmax.disruptor.EventHandler;
10 |
11 | public class CustomerSpecificBillingBusinessEventProcessor implements EventHandler {
12 |
13 | private static final Logger LOG = LoggerFactory.getLogger(CustomerSpecificBillingBusinessEventProcessor.class);
14 | private BillingService billingService;
15 |
16 | @Override
17 | public void onEvent(BillingRecord billingRecord, long sequence, boolean endOfBatch)
18 | throws Exception {
19 | if(billingRecord.getCustomerName().startsWith("anair")){
20 | LOG.trace("Sequence: {}. Going to process {}",sequence, billingRecord.toString());
21 | billingService.processCustomerSpecificBillingRecord(billingRecord);
22 | if(sequence%10==0){
23 | LOG.info("Sequence: {}. {}",sequence, billingRecord.toString());
24 | }
25 | }
26 | }
27 |
28 | @Required
29 | public void setBillingService(BillingService billingService) {
30 | this.billingService = billingService;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/disruptor/eventprocessor/JournalBillingEventProcessor.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.disruptor.eventprocessor;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 | import org.anair.billing.service.BillingService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Required;
8 |
9 | import com.lmax.disruptor.EventHandler;
10 |
11 | public class JournalBillingEventProcessor implements EventHandler {
12 |
13 | private static final Logger LOG = LoggerFactory.getLogger(JournalBillingEventProcessor.class);
14 | private BillingService billingService;
15 |
16 | @Override
17 | public void onEvent(BillingRecord billingRecord, long sequence, boolean endOfBatch)
18 | throws Exception {
19 | LOG.trace("Sequence: {}. Going to process {}",sequence, billingRecord.toString());
20 | billingService.journalBillingRecord(billingRecord);
21 | if(sequence%10==0){
22 | LOG.info("Sequence: {}. {}",sequence, billingRecord.toString());
23 | }
24 | }
25 |
26 | @Required
27 | public void setBillingService(BillingService billingService) {
28 | this.billingService = billingService;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/disruptor/eventtranslator/BillingEventTranslator.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.disruptor.eventtranslator;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import com.lmax.disruptor.EventTranslator;
8 |
9 | public class BillingEventTranslator implements EventTranslator{
10 |
11 | private static final Logger LOG = LoggerFactory.getLogger(BillingEventTranslator.class);
12 | private BillingRecord billingRecord;
13 |
14 | public BillingEventTranslator(BillingRecord billingRecord) {
15 | this.billingRecord = billingRecord;
16 | }
17 |
18 | @Override
19 | public void translateTo(BillingRecord billingRecord, long sequence) {
20 | billingRecord.setBillingId(this.billingRecord.getBillingId());
21 | billingRecord.setBillable(this.billingRecord.isBillable());
22 | billingRecord.setQuantity(this.billingRecord.getQuantity());
23 | billingRecord.setBillableArtifactName(this.billingRecord.getBillableArtifactName());
24 | billingRecord.setCustomerName(this.billingRecord.getCustomerName());
25 |
26 | if(sequence%10==0){
27 | LOG.info("Published {} to sequence: {}",billingRecord.toString(), sequence);
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/disruptor/publisher/BillingEventPublisher.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.disruptor.publisher;
2 |
3 | import org.anair.billing.disruptor.eventtranslator.BillingEventTranslator;
4 | import org.anair.billing.model.BillingRecord;
5 | import org.anair.disruptor.DisruptorConfig;
6 | import org.anair.disruptor.publisher.EventPublisher;
7 |
8 | public class BillingEventPublisher implements EventPublisher{
9 |
10 | private DisruptorConfig disruptorConfig;
11 |
12 | @Override
13 | public void publish(BillingRecord billingRecord){
14 | disruptorConfig.publish(new BillingEventTranslator(billingRecord));
15 | }
16 |
17 | @Override
18 | public void setDisruptorConfig(DisruptorConfig disruptorConfig) {
19 | this.disruptorConfig = disruptorConfig;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/message/listener/BillingMessageListener.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.message.listener;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 | import org.anair.disruptor.publisher.EventPublisher;
5 | import org.apache.commons.lang3.StringUtils;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class BillingMessageListener {
10 | private static final Logger LOG = LoggerFactory.getLogger(BillingMessageListener.class);
11 |
12 | private EventPublisher billingEventPublisher;
13 |
14 | public void inMessage(String number){
15 | if(StringUtils.isBlank(number) || !StringUtils.isNumeric(number.trim())){
16 | LOG.error("Enter a valid long number");
17 | return;
18 | }
19 | long inboundMessageCount = Long.parseLong(number.trim());
20 | for(long l=0;l billingEventPublisher) {
42 | this.billingEventPublisher = billingEventPublisher;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/model/BillingRecord.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.model;
2 |
3 | import java.io.Serializable;
4 |
5 | public class BillingRecord implements Serializable {
6 |
7 | private static final long serialVersionUID = 3299746082013341934L;
8 |
9 | private long billingId;
10 | private boolean billable;
11 | private int quantity;
12 | private String billableArtifactName;
13 | private String customerName;
14 |
15 |
16 | public long getBillingId() {
17 | return billingId;
18 | }
19 | public void setBillingId(long billingId) {
20 | this.billingId = billingId;
21 | }
22 | public boolean isBillable() {
23 | return billable;
24 | }
25 | public void setBillable(boolean billable) {
26 | this.billable = billable;
27 | }
28 | public int getQuantity() {
29 | return quantity;
30 | }
31 | public void setQuantity(int quantity) {
32 | this.quantity = quantity;
33 | }
34 | public String getBillableArtifactName() {
35 | return billableArtifactName;
36 | }
37 | public void setBillableArtifactName(String billableArtifactName) {
38 | this.billableArtifactName = billableArtifactName;
39 | }
40 | public String getCustomerName() {
41 | return customerName;
42 | }
43 | public void setCustomerName(String customerName) {
44 | this.customerName = customerName;
45 | }
46 |
47 | @Override
48 | public String toString() {
49 | return "Id [" + billingId + "]";
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/service/BillingService.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.service;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 |
5 | public interface BillingService {
6 | static final long delay = 999999L;
7 |
8 | void validateBillingRecord(BillingRecord billingRecord);
9 |
10 | void formatBillingRecord(BillingRecord billingRecord);
11 |
12 | void journalBillingRecord(BillingRecord billingRecord);
13 |
14 | void processBillingRecord(BillingRecord billingRecord);
15 |
16 | void processCorporateBillingRecord(BillingRecord billingRecord);
17 |
18 | void processCustomerSpecificBillingRecord(BillingRecord billingRecord);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/billing/service/BillingServiceImpl.java:
--------------------------------------------------------------------------------
1 | package org.anair.billing.service;
2 |
3 | import org.anair.billing.model.BillingRecord;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | public class BillingServiceImpl implements BillingService {
8 | private static final Logger LOG = LoggerFactory.getLogger(BillingServiceImpl.class);
9 |
10 | @Override
11 | public void processBillingRecord(BillingRecord billingRecord) {
12 | for(long l=0;l {
8 |
9 | @Override
10 | public DataStream newInstance() {
11 | return new DataStream();
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/datastream/disruptor/eventprocessor/FormatDataStreamEventProcessor.java:
--------------------------------------------------------------------------------
1 | package org.anair.datastream.disruptor.eventprocessor;
2 |
3 | import org.anair.datastream.model.DataStream;
4 | import org.anair.datastream.service.DatastreamService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Required;
8 |
9 | import com.lmax.disruptor.EventHandler;
10 |
11 | public class FormatDataStreamEventProcessor implements EventHandler {
12 |
13 | private static final Logger LOG = LoggerFactory.getLogger(FormatDataStreamEventProcessor.class);
14 | private DatastreamService dataStreamService;
15 |
16 | @Override
17 | public void onEvent(DataStream dataStream, long sequence, boolean endOfBatch)
18 | throws Exception {
19 | LOG.trace("Sequence: {}. Going to process {}",sequence, dataStream.toString());
20 | dataStreamService.formatDatastream(dataStream);
21 | if(sequence%10==0){
22 | LOG.info("Sequence: {}. {}",sequence, dataStream.toString());
23 | }
24 | }
25 |
26 | @Required
27 | public void setDataStreamService(DatastreamService dataStreamService) {
28 | this.dataStreamService = dataStreamService;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/datastream/disruptor/eventprocessor/JournalDataStreamEventProcessor.java:
--------------------------------------------------------------------------------
1 | package org.anair.datastream.disruptor.eventprocessor;
2 |
3 | import org.anair.datastream.model.DataStream;
4 | import org.anair.datastream.service.DatastreamService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Required;
8 |
9 | import com.lmax.disruptor.EventHandler;
10 |
11 | public class JournalDataStreamEventProcessor implements EventHandler {
12 |
13 | private static final Logger LOG = LoggerFactory.getLogger(JournalDataStreamEventProcessor.class);
14 | private DatastreamService dataStreamService;
15 |
16 | @Override
17 | public void onEvent(DataStream dataStream, long sequence, boolean endOfBatch)
18 | throws Exception {
19 | LOG.trace("Sequence: {}. Going to process {}",sequence, dataStream.toString());
20 | dataStreamService.journalDatastream(dataStream);
21 | if(sequence%10==0){
22 | LOG.info("Sequence: {}. {}",sequence, dataStream.toString());
23 | }
24 | }
25 |
26 | @Required
27 | public void setDataStreamService(DatastreamService dataStreamService) {
28 | this.dataStreamService = dataStreamService;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/datastream/disruptor/eventprocessor/ProcessADataStreamEventProcessor.java:
--------------------------------------------------------------------------------
1 | package org.anair.datastream.disruptor.eventprocessor;
2 |
3 | import org.anair.datastream.model.DataStream;
4 | import org.anair.datastream.service.DatastreamService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Required;
8 |
9 | import com.lmax.disruptor.EventHandler;
10 |
11 | public class ProcessADataStreamEventProcessor implements EventHandler {
12 |
13 | private static final Logger LOG = LoggerFactory.getLogger(ProcessADataStreamEventProcessor.class);
14 | private DatastreamService dataStreamService;
15 |
16 | @Override
17 | public void onEvent(DataStream dataStream, long sequence, boolean endOfBatch)
18 | throws Exception {
19 | LOG.trace("Sequence: {}. Going to process {}",sequence, dataStream.toString());
20 | dataStreamService.processDatastream_A(dataStream);
21 | if(sequence%10==0){
22 | LOG.info("Sequence: {}. {}",sequence, dataStream.toString());
23 | }
24 | }
25 |
26 | @Required
27 | public void setDataStreamService(DatastreamService dataStreamService) {
28 | this.dataStreamService = dataStreamService;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/datastream/disruptor/eventprocessor/ProcessBDataStreamEventProcessor.java:
--------------------------------------------------------------------------------
1 | package org.anair.datastream.disruptor.eventprocessor;
2 |
3 | import org.anair.datastream.model.DataStream;
4 | import org.anair.datastream.service.DatastreamService;
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.beans.factory.annotation.Required;
8 |
9 | import com.lmax.disruptor.EventHandler;
10 |
11 | public class ProcessBDataStreamEventProcessor implements EventHandler {
12 |
13 | private static final Logger LOG = LoggerFactory.getLogger(ProcessBDataStreamEventProcessor.class);
14 | private DatastreamService dataStreamService;
15 |
16 | @Override
17 | public void onEvent(DataStream dataStream, long sequence, boolean endOfBatch)
18 | throws Exception {
19 | LOG.trace("Sequence: {}. Going to process {}",sequence, dataStream.toString());
20 | dataStreamService.processDatastream_B(dataStream);
21 | if(sequence%10==0){
22 | LOG.info("Sequence: {}. {}",sequence, dataStream.toString());
23 | }
24 | }
25 |
26 | @Required
27 | public void setDataStreamService(DatastreamService dataStreamService) {
28 | this.dataStreamService = dataStreamService;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/datastream/disruptor/eventtranslator/DataStreamEventTranslator.java:
--------------------------------------------------------------------------------
1 | package org.anair.datastream.disruptor.eventtranslator;
2 |
3 | import org.anair.datastream.model.DataStream;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import com.lmax.disruptor.EventTranslator;
8 |
9 | public class DataStreamEventTranslator implements EventTranslator{
10 |
11 | private static final Logger LOG = LoggerFactory.getLogger(DataStreamEventTranslator.class);
12 | private DataStream dataStream;
13 |
14 | public DataStreamEventTranslator(DataStream dataStream) {
15 | this.dataStream = dataStream;
16 | }
17 |
18 | @Override
19 | public void translateTo(DataStream dataStream, long sequence) {
20 | dataStream.setDataStreamId(this.dataStream.getDataStreamId());
21 | dataStream.setDataStreamType(this.dataStream.getDataStreamType());
22 | dataStream.setDataStream(this.dataStream.getDataStream());
23 | dataStream.setDataSource(this.dataStream.getDataSource());
24 | dataStream.setDataTarget(this.dataStream.getDataTarget());
25 |
26 | if(sequence%10==0){
27 | LOG.info("Published {} to sequence: {}",dataStream.toString(), sequence);
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/datastream/disruptor/publisher/DataStreamEventPublisher.java:
--------------------------------------------------------------------------------
1 | package org.anair.datastream.disruptor.publisher;
2 |
3 | import org.anair.datastream.disruptor.eventtranslator.DataStreamEventTranslator;
4 | import org.anair.datastream.model.DataStream;
5 | import org.anair.disruptor.DisruptorConfig;
6 | import org.anair.disruptor.publisher.EventPublisher;
7 |
8 | public class DataStreamEventPublisher implements EventPublisher{
9 |
10 | private DisruptorConfig disruptorConfig;
11 |
12 | @Override
13 | public void publish(DataStream dataStream){
14 | disruptorConfig.publish(new DataStreamEventTranslator(dataStream));
15 | }
16 |
17 | @Override
18 | public void setDisruptorConfig(DisruptorConfig disruptorConfig) {
19 | this.disruptorConfig = disruptorConfig;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/datastream/message/listener/DataStreamMessageListener.java:
--------------------------------------------------------------------------------
1 | package org.anair.datastream.message.listener;
2 |
3 | import org.anair.datastream.model.DataStream;
4 | import org.anair.disruptor.publisher.EventPublisher;
5 | import org.apache.commons.lang3.StringUtils;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | public class DataStreamMessageListener {
10 | private static final Logger LOG = LoggerFactory.getLogger(DataStreamMessageListener.class);
11 |
12 | private EventPublisher dataStreamEventPublisher;
13 |
14 | public void inMessage(String number){
15 | if(StringUtils.isBlank(number) || !StringUtils.isNumeric(number.trim())){
16 | LOG.error("Enter a valid long number");
17 | return;
18 | }
19 | long inboundMessageCount = Long.parseLong(number.trim());
20 | for(long l=0;l dataStreamEventPublisher) {
38 | this.dataStreamEventPublisher = dataStreamEventPublisher;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/datastream/model/DataStream.java:
--------------------------------------------------------------------------------
1 | package org.anair.datastream.model;
2 |
3 | import java.io.Serializable;
4 |
5 | public class DataStream implements Serializable {
6 |
7 | private static final long serialVersionUID = -5915976976824831395L;
8 |
9 | private long dataStreamId;
10 | private String dataStreamType;
11 | private String dataStream;
12 | private String dataSource;
13 | private String dataTarget;
14 | public long getDataStreamId() {
15 | return dataStreamId;
16 | }
17 | public void setDataStreamId(long dataStreamId) {
18 | this.dataStreamId = dataStreamId;
19 | }
20 | public String getDataStreamType() {
21 | return dataStreamType;
22 | }
23 | public void setDataStreamType(String dataStreamType) {
24 | this.dataStreamType = dataStreamType;
25 | }
26 | public String getDataStream() {
27 | return dataStream;
28 | }
29 | public void setDataStream(String dataStream) {
30 | this.dataStream = dataStream;
31 | }
32 | public String getDataSource() {
33 | return dataSource;
34 | }
35 | public void setDataSource(String dataSource) {
36 | this.dataSource = dataSource;
37 | }
38 | public String getDataTarget() {
39 | return dataTarget;
40 | }
41 | public void setDataTarget(String dataTarget) {
42 | this.dataTarget = dataTarget;
43 | }
44 | @Override
45 | public String toString() {
46 | return "DataStreamId [" + dataStreamId + "]";
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/datastream/service/DatastreamService.java:
--------------------------------------------------------------------------------
1 | package org.anair.datastream.service;
2 |
3 | import org.anair.datastream.model.DataStream;
4 |
5 | public interface DatastreamService {
6 | static final long delay = 555555L;
7 |
8 | void journalDatastream(DataStream dataStream);
9 |
10 | void processDatastream_A(DataStream dataStream);
11 |
12 | void processDatastream_B(DataStream dataStream);
13 |
14 | DataStream formatDatastream(DataStream dataStream);
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/org/anair/datastream/service/DatastreamServiceImpl.java:
--------------------------------------------------------------------------------
1 | package org.anair.datastream.service;
2 |
3 | import org.anair.datastream.model.DataStream;
4 |
5 | public class DatastreamServiceImpl implements DatastreamService {
6 |
7 | @Override
8 | public void journalDatastream(DataStream dataStream) {
9 | for(long l=0;l
2 |
5 |
6 |
16 |
17 |
19 |
20 |
21 |
22 |
24 |
25 |
26 |
27 |
28 |
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 |
61 |
62 |
65 |
66 |
69 |
70 |
73 |
74 |
77 |
78 |
81 |
82 |
85 |
86 |
87 |
88 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/src/main/resources/spring-datastream-disruptor.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
18 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
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 |
61 |
62 |
65 |
66 |
69 |
70 |
73 |
74 |
75 |
76 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/main/resources/spring-jms.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
15 |
16 |
20 |
21 |
24 |
25 |
26 |
27 |
33 |
34 |
38 |
39 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/main/resources/spring-jmx.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
10 |
11 |
13 |
14 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/resources/spring-service.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
10 |
11 |
13 |
14 |
15 |
--------------------------------------------------------------------------------