From ac5c1967df47053402e7201a320e50e6c220cd5c Mon Sep 17 00:00:00 2001 From: JaXt0r Date: Sun, 25 Oct 2015 07:11:34 +0100 Subject: [PATCH 1/5] #161 - Publish Subscribe Channel realisation.Heavily based on iluwatars Message Channel implementation (#143). --- pom.xml | 1 + publish-subscribe/.gitignore | 1 + publish-subscribe/etc/publish-subscribe.png | Bin 0 -> 27741 bytes publish-subscribe/etc/publish-subscribe.ucls | 218 ++++++++++++++++++ publish-subscribe/index.md | 17 ++ publish-subscribe/pom.xml | 24 ++ .../com/iluwatar/publish/subscribe/App.java | 55 +++++ .../iluwatar/publish/subscribe/AppTest.java | 17 ++ 8 files changed, 333 insertions(+) create mode 100644 publish-subscribe/.gitignore create mode 100644 publish-subscribe/etc/publish-subscribe.png create mode 100644 publish-subscribe/etc/publish-subscribe.ucls create mode 100644 publish-subscribe/index.md create mode 100644 publish-subscribe/pom.xml create mode 100644 publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java create mode 100644 publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java diff --git a/pom.xml b/pom.xml index 3064f3c0d..e01dc1001 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,7 @@ message-channel fluentinterface reactor + publish-subscribe diff --git a/publish-subscribe/.gitignore b/publish-subscribe/.gitignore new file mode 100644 index 000000000..b83d22266 --- /dev/null +++ b/publish-subscribe/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/publish-subscribe/etc/publish-subscribe.png b/publish-subscribe/etc/publish-subscribe.png new file mode 100644 index 0000000000000000000000000000000000000000..99867da66b548a6d484d67364d4eb3dbaed3e2f9 GIT binary patch literal 27741 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

s(c{+6#Xc&>ImMwHl&y7=u7` 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 xk&%Jtkpd1f + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/publish-subscribe/index.md b/publish-subscribe/index.md new file mode 100644 index 000000000..efd40f021 --- /dev/null +++ b/publish-subscribe/index.md @@ -0,0 +1,17 @@ +--- +layout: pattern +title: Publish Subscribe +folder: publish-subscribe +permalink: /patterns/publish-subscribe/ +categories: Integration +tags: Java +--- + +**Intent:** When applications communicate using a messaging system they do it by using logical addresses +of the system, so called Publish Subscribe Channel. The publisher broadcasts a message to all registered Subscriber. + +![alt text](./etc/publish-subscribe.png "Publish Subscribe Channel") + +**Applicability:** Use the Publish Subscribe Channel pattern when + +* two or more applications need to communicate using a messaging system for broadcasts. diff --git a/publish-subscribe/pom.xml b/publish-subscribe/pom.xml new file mode 100644 index 000000000..04b76690a --- /dev/null +++ b/publish-subscribe/pom.xml @@ -0,0 +1,24 @@ + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.7.0 + + publish-subscribe + + + org.apache.camel + camel-core + + + org.apache.camel + camel-stream + + + junit + junit + + + \ No newline at end of file diff --git a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java b/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java new file mode 100644 index 000000000..1f433f517 --- /dev/null +++ b/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java @@ -0,0 +1,55 @@ +package com.iluwatar.publish.subscribe; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.impl.DefaultCamelContext; + +/** + * + * When applications communicate with each other using a messaging system + * they first need to establish a communication channel that will carry the + * data. Message Channel decouples Message producers (publisher) and consumers (subscriber). + *

+ * The sending application doesn't necessarily know what particular applications + * will end up retrieving it, but it can be assured that the application that + * retrieves the information is interested in that information. This is because + * the messaging system has different Message Channels for different types of + * information the applications want to communicate. When an application sends + * information, it doesn't randomly add the information to any channel available; + * it adds it to a channel whose specific purpose is to communicate that sort of + * information. Likewise, an application that wants to receive particular information + * doesn't pull info off some random channel; it selects what channel to get information + * from based on what type of information it wants. + *

+ * In this example we use Apache Camel to establish different Message Channels. The first + * one reads from standard input and delivers messages to Direct endpoints (Publish; Broadcast). The other Message + * Channels are established from the Direct component to different Endpoints (Subscriber). No actual messages are sent, + * only the established routes are printed to standard output. + * + */ +public class App { + + /** + * Program entry point + * + * @param args command line args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + CamelContext context = new DefaultCamelContext(); + + context.addRoutes(new RouteBuilder() { + + @Override + public void configure() throws Exception { + from("stream:in") + .multicast() + .to("direct:greetings1", "direct:greetings2", "direct:greetings3"); + } + }); + + context.start(); + context.getRoutes().stream().forEach((r) -> System.out.println(r)); + context.stop(); + } +} diff --git a/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java b/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java new file mode 100644 index 000000000..743e4200d --- /dev/null +++ b/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.publish.subscribe; + +import org.junit.Test; + +/** + * + * Application test + * + */ +public class AppTest { + + @Test + public void test() throws Exception { + String[] args = {}; + App.main(args); + } +} \ No newline at end of file From b97e9207a7782672df183ac3ef37b5960f27fa18 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Sat, 21 Nov 2015 15:03:27 +0200 Subject: [PATCH 2/5] Update version number for Publish-Subscribe --- publish-subscribe/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/publish-subscribe/pom.xml b/publish-subscribe/pom.xml index 04b76690a..07d704719 100644 --- a/publish-subscribe/pom.xml +++ b/publish-subscribe/pom.xml @@ -4,7 +4,7 @@ com.iluwatar java-design-patterns - 1.7.0 + 1.8.0-SNAPSHOT publish-subscribe From 230c02fb249bcc1fb16d1aad8354613aa40e7f34 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Sat, 21 Nov 2015 15:09:23 +0200 Subject: [PATCH 3/5] Fix spelling --- publish-subscribe/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/publish-subscribe/index.md b/publish-subscribe/index.md index efd40f021..48908beb4 100644 --- a/publish-subscribe/index.md +++ b/publish-subscribe/index.md @@ -8,7 +8,7 @@ tags: Java --- **Intent:** When applications communicate using a messaging system they do it by using logical addresses -of the system, so called Publish Subscribe Channel. The publisher broadcasts a message to all registered Subscriber. +of the system, so called Publish Subscribe Channel. The publisher broadcasts a message to all registered subscribers. ![alt text](./etc/publish-subscribe.png "Publish Subscribe Channel") From 78853806336b0d1ca42d374580591f02b72c21f6 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Sat, 21 Nov 2015 15:12:31 +0200 Subject: [PATCH 4/5] Apply Google coding conventions --- .../com/iluwatar/publish/subscribe/App.java | 77 +++++++++---------- .../iluwatar/publish/subscribe/AppTest.java | 12 +-- 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java b/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java index 1f433f517..237847936 100644 --- a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java +++ b/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java @@ -6,50 +6,49 @@ import org.apache.camel.impl.DefaultCamelContext; /** * - * When applications communicate with each other using a messaging system - * they first need to establish a communication channel that will carry the - * data. Message Channel decouples Message producers (publisher) and consumers (subscriber). + * When applications communicate with each other using a messaging system they first need to + * establish a communication channel that will carry the data. Message Channel decouples Message + * producers (publisher) and consumers (subscriber). *

- * The sending application doesn't necessarily know what particular applications - * will end up retrieving it, but it can be assured that the application that - * retrieves the information is interested in that information. This is because - * the messaging system has different Message Channels for different types of - * information the applications want to communicate. When an application sends - * information, it doesn't randomly add the information to any channel available; - * it adds it to a channel whose specific purpose is to communicate that sort of - * information. Likewise, an application that wants to receive particular information - * doesn't pull info off some random channel; it selects what channel to get information - * from based on what type of information it wants. + * The sending application doesn't necessarily know what particular applications will end up + * retrieving it, but it can be assured that the application that retrieves the information is + * interested in that information. This is because the messaging system has different Message + * Channels for different types of information the applications want to communicate. When an + * application sends information, it doesn't randomly add the information to any channel available; + * it adds it to a channel whose specific purpose is to communicate that sort of information. + * Likewise, an application that wants to receive particular information doesn't pull info off some + * random channel; it selects what channel to get information from based on what type of information + * it wants. *

- * In this example we use Apache Camel to establish different Message Channels. The first - * one reads from standard input and delivers messages to Direct endpoints (Publish; Broadcast). The other Message - * Channels are established from the Direct component to different Endpoints (Subscriber). No actual messages are sent, - * only the established routes are printed to standard output. + * In this example we use Apache Camel to establish different Message Channels. The first one reads + * from standard input and delivers messages to Direct endpoints (Publish; Broadcast). The other + * Message Channels are established from the Direct component to different Endpoints (Subscriber). + * No actual messages are sent, only the established routes are printed to standard output. * */ public class App { - /** - * Program entry point - * - * @param args command line args - * @throws Exception - */ - public static void main(String[] args) throws Exception { - CamelContext context = new DefaultCamelContext(); - - context.addRoutes(new RouteBuilder() { + /** + * Program entry point + * + * @param args + * command line args + * @throws Exception + */ + public static void main(String[] args) throws Exception { + CamelContext context = new DefaultCamelContext(); - @Override - public void configure() throws Exception { - from("stream:in") - .multicast() - .to("direct:greetings1", "direct:greetings2", "direct:greetings3"); - } - }); - - context.start(); - context.getRoutes().stream().forEach((r) -> System.out.println(r)); - context.stop(); - } + context.addRoutes(new RouteBuilder() { + + @Override + public void configure() throws Exception { + from("stream:in").multicast().to("direct:greetings1", "direct:greetings2", + "direct:greetings3"); + } + }); + + context.start(); + context.getRoutes().stream().forEach((r) -> System.out.println(r)); + context.stop(); + } } diff --git a/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java b/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java index 743e4200d..bc8b0153e 100644 --- a/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java +++ b/publish-subscribe/src/test/java/com/iluwatar/publish/subscribe/AppTest.java @@ -9,9 +9,9 @@ import org.junit.Test; */ public class AppTest { - @Test - public void test() throws Exception { - String[] args = {}; - App.main(args); - } -} \ No newline at end of file + @Test + public void test() throws Exception { + String[] args = {}; + App.main(args); + } +} From d0fca6d3184183b6b37f0519e54375bb3e7ca3d4 Mon Sep 17 00:00:00 2001 From: Ilkka Seppala Date: Sat, 21 Nov 2015 16:05:55 +0200 Subject: [PATCH 5/5] Improve the example and documentation --- publish-subscribe/index.md | 3 +- .../com/iluwatar/publish/subscribe/App.java | 38 +++++++++---------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/publish-subscribe/index.md b/publish-subscribe/index.md index 48908beb4..b60954ec5 100644 --- a/publish-subscribe/index.md +++ b/publish-subscribe/index.md @@ -7,8 +7,7 @@ categories: Integration tags: Java --- -**Intent:** When applications communicate using a messaging system they do it by using logical addresses -of the system, so called Publish Subscribe Channel. The publisher broadcasts a message to all registered subscribers. +**Intent:** Broadcast messages from sender to all the interested receivers. ![alt text](./etc/publish-subscribe.png "Publish Subscribe Channel") diff --git a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java b/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java index 237847936..30f982ed1 100644 --- a/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java +++ b/publish-subscribe/src/main/java/com/iluwatar/publish/subscribe/App.java @@ -1,29 +1,27 @@ package com.iluwatar.publish.subscribe; import org.apache.camel.CamelContext; +import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.impl.DefaultCamelContext; /** * - * When applications communicate with each other using a messaging system they first need to - * establish a communication channel that will carry the data. Message Channel decouples Message - * producers (publisher) and consumers (subscriber). + * There are well-established patterns for implementing broadcasting. The Observer pattern describes + * the need to decouple observers from their subject (that is, the originator of the event) so that + * the subject can easily provide event notification to all interested observers no matter how many + * observers there are (even none). The Publish-Subscribe pattern expands upon Observer by adding + * the notion of an event channel for communicating event notifications. *

- * The sending application doesn't necessarily know what particular applications will end up - * retrieving it, but it can be assured that the application that retrieves the information is - * interested in that information. This is because the messaging system has different Message - * Channels for different types of information the applications want to communicate. When an - * application sends information, it doesn't randomly add the information to any channel available; - * it adds it to a channel whose specific purpose is to communicate that sort of information. - * Likewise, an application that wants to receive particular information doesn't pull info off some - * random channel; it selects what channel to get information from based on what type of information - * it wants. + * A Publish-Subscribe Channel works like this: It has one input channel that splits into multiple + * output channels, one for each subscriber. When an event is published into the channel, the + * Publish-Subscribe Channel delivers a copy of the message to each of the output channels. Each + * output end of the channel has only one subscriber, which is allowed to consume a message only + * once. In this way, each subscriber gets the message only once, and consumed copies disappear from + * their channels. *

- * In this example we use Apache Camel to establish different Message Channels. The first one reads - * from standard input and delivers messages to Direct endpoints (Publish; Broadcast). The other - * Message Channels are established from the Direct component to different Endpoints (Subscriber). - * No actual messages are sent, only the established routes are printed to standard output. + * In this example we use Apache Camel to establish a Publish-Subscribe Channel from "direct-origin" + * to "mock:foo", "mock:bar" and "stream:out". * */ public class App { @@ -37,18 +35,16 @@ public class App { */ public static void main(String[] args) throws Exception { CamelContext context = new DefaultCamelContext(); - context.addRoutes(new RouteBuilder() { - @Override public void configure() throws Exception { - from("stream:in").multicast().to("direct:greetings1", "direct:greetings2", - "direct:greetings3"); + from("direct:origin").multicast().to("mock:foo", "mock:bar", "stream:out"); } }); - + ProducerTemplate template = context.createProducerTemplate(); context.start(); context.getRoutes().stream().forEach((r) -> System.out.println(r)); + template.sendBody("direct:origin", "Hello from origin"); context.stop(); } }