properties = new Hashtable<>();
33 | properties.put("java.naming.factory.initial", "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
34 | properties.put("connectionFactory.ConnectionFactory", "failover:(amqp://localhost:61616)");
35 | properties.put("queue.queue/exampleQueue", "exampleQueue");
36 | InitialContext context = new InitialContext(properties);
37 |
38 | Queue queue = (Queue) context.lookup("queue/exampleQueue");
39 |
40 | ConnectionFactory cf = (ConnectionFactory) context.lookup("ConnectionFactory");
41 |
42 | try (
43 | Connection connection = cf.createConnection();
44 | ) {
45 | Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
46 | MessageProducer producer = session.createProducer(queue);
47 | int i = 0;
48 | while (true) {
49 | for (int j = 0 ; j < 10; j++) {
50 | TextMessage textMessage = session.createTextMessage("message " + i++);
51 | producer.send(textMessage);
52 | }
53 | try {
54 | session.commit();
55 | } catch (TransactionRolledBackException e) {
56 | System.out.println("tx was rolled back after fail over");
57 | }
58 | Thread.sleep(1000);
59 | }
60 | }
61 | } catch (Exception e) {
62 | e.printStackTrace();
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/demos/broker/high-availability/src/main/java/com/redhat/workshop/amq7/ha/Receiver.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.workshop.amq7.ha;
18 |
19 | import javax.jms.Connection;
20 | import javax.jms.ConnectionFactory;
21 | import javax.jms.MessageConsumer;
22 | import javax.jms.Queue;
23 | import javax.jms.Session;
24 | import javax.jms.TextMessage;
25 | import javax.naming.InitialContext;
26 |
27 | public class Receiver {
28 | public static void main(String args[]) throws Exception{
29 |
30 | try {
31 | InitialContext context = new InitialContext();
32 |
33 | Queue queue = (Queue) context.lookup("queue/exampleQueue");
34 |
35 | ConnectionFactory cf = (ConnectionFactory) context.lookup("ConnectionFactory");
36 |
37 | try (
38 | Connection connection = cf.createConnection();
39 | ) {
40 | Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
41 | MessageConsumer consumer = session.createConsumer(queue);
42 | connection.start();
43 | while (true) {
44 | for (int j = 0 ; j < 10; j++) {
45 | TextMessage receive = (TextMessage) consumer.receive(0);
46 | System.out.println("received message " + receive.getText());
47 | }
48 | session.commit();
49 | }
50 | }
51 | } catch (Exception e) {
52 | e.printStackTrace();
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/demos/broker/high-availability/src/main/java/com/redhat/workshop/amq7/ha/Sender.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.workshop.amq7.ha;
18 |
19 | import javax.jms.Connection;
20 | import javax.jms.ConnectionFactory;
21 | import javax.jms.JMSException;
22 | import javax.jms.MessageProducer;
23 | import javax.jms.Queue;
24 | import javax.jms.Session;
25 | import javax.jms.TextMessage;
26 | import javax.jms.TransactionRolledBackException;
27 | import javax.naming.InitialContext;
28 |
29 | public class Sender {
30 | public static void main(String args[]) throws Exception{
31 |
32 | try {
33 | InitialContext context = new InitialContext();
34 |
35 | Queue queue = (Queue) context.lookup("queue/exampleQueue");
36 |
37 | ConnectionFactory cf = (ConnectionFactory) context.lookup("ConnectionFactory");
38 |
39 | try (
40 | Connection connection = cf.createConnection();
41 | ) {
42 | Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
43 | MessageProducer producer = session.createProducer(queue);
44 | int i = 0;
45 | while (true) {
46 | for (int j = 0 ; j < 10; j++) {
47 | TextMessage textMessage = session.createTextMessage("message " + i++);
48 | producer.send(textMessage);
49 | System.out.println("sent message " + (i - 1));
50 | }
51 | try {
52 | session.commit();
53 | } catch (TransactionRolledBackException e) {
54 | System.out.println("tx was rolled back after fail over");
55 | }
56 | Thread.sleep(1000);
57 | }
58 | }
59 | } catch (Exception e) {
60 | e.printStackTrace();
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/demos/broker/high-availability/src/main/resources/jndi.properties:
--------------------------------------------------------------------------------
1 | java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory
2 | connectionFactory.ConnectionFactory=tcp://localhost:61616?ha=true&retryInterval=1000&retryIntervalMultiplier=1.0&reconnectAttempts=-1
3 | queue.queue/exampleQueue=exampleQueue
--------------------------------------------------------------------------------
/demos/broker/large-messages/README.md:
--------------------------------------------------------------------------------
1 | ## Large Messages in AMQ 7 Broker
2 |
3 | This worksheet covers handling large messages in the AMQ7 Broker. By the end of this you should know:
4 |
5 | 1. The large message concepts of AMQ 7
6 | * Memory limits in the broker
7 | * Sending large messages
8 | * Streaming large messages
9 |
10 | 2. How to configure Large Messages
11 | * Configuring a broker to handle large messages
12 | * Configuring a client to use large messages
13 | * Configuring a client to stream messages
14 |
15 |
16 | ### Large Message Concepts
17 |
18 | There are 2 main issues that can happen when you send or receive messages to an AMQ 7 Broker.
19 |
20 | 1. Memory limits are exceeded in the broker
21 | 2. Memory limits are exceeded within the client
22 |
23 | #### Memory Limits Within the Broker
24 |
25 | Any message that is sent or consumed from a Broker has to exist in memory at some point before
26 | it can either be persisted to disk after receipt, or delivered to a consumer. This can be problematic
27 | when running in an environment with limited memory. The AMQ 7 broker handles large messages by never
28 | fully reading them into memory, instead the broker writes the large message directly to its large message store
29 | located on disk. The location of this is configured in the broker.xml file like so:
30 |
31 | ```xml
32 | largemessagesdir
33 | ```
34 | This is always configured by default.
35 |
36 | #### Large Messages and Clients
37 |
38 | Currently only the Core JMS client can handle large messages
39 |
40 | ##### Sending a Large Message
41 |
42 | To configure the core JMS client to send a message you need to configure `min-large-message-size` on
43 | the connection factory. The `min-large-message-size` parameter is used in the client to determine when to mark a message
44 | as *large*. There are a handful of ways to configure the `min-large-message-size` parameter on the connection factory.
45 |
46 | 1. Using JNDI
47 |
48 | If JNDI is used to instantiate and look up the connection factory, the minimum large message size is configured in the
49 | JNDI context environment, e.g. `jndi.properties`. Here's a simple example using the "ConnectionFactory" connection factory
50 | which is available in the context by default:
51 |
52 | ```properties
53 | java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory
54 | connectionFactory.myConnectionFactory=tcp://localhost:61616?minLargeMessageSize=10240
55 | ```
56 |
57 | 2. In Java code
58 |
59 | If the connection factory is being instantiated directly in Java, the minimum
60 | large message size can be specified like so:
61 |
62 | ```java
63 | ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory();
64 | cf.setMinLargeMessageSize(10240);
65 | ```
66 |
67 | or using the URL:
68 |
69 | ```java
70 | new ActiveMQConnectionFactory("tcp://localhost:61616?minLargeMessageSize=10240");
71 | ```
72 |
73 | To see this in action start a broker in the usual fashion.
74 |
75 | Use the `com.redhat.workshop.amq7.largemessage.Sender` to send a large message:
76 |
77 | ```sh
78 | $ mvn verify -PLargeMessageSender
79 | ```
80 |
81 | Since the `minLargeMessageSize` size in the example is set to `10240` bytes and the `Sender` client is sending
82 | a bytes message of size `20480` bytes, the client will treat this as a large message and send it in chunks.
83 |
84 | The broker will then write these chunks to its large message store without having to keep them in memory.
85 | Obviously, in reality the large message can be as large as the client can fit into memory.
86 |
87 | Take a look in the `large-messages-directory`. You will notice a new file that contains the content of the message
88 | Note: The content is encoded so it's not human readable.
89 |
90 | You can consume the message using the `com.redhat.workshop.amq7.largemessage.Receiver` client by running:
91 |
92 | ```sh
93 | $ mvn verify -PLargeMessageReceiver
94 | ```
95 |
96 | Note that the large message file has now disappeared.
97 |
98 | #### Memory Limits within the Broker
99 |
100 | In the previous example, we created a single byte array that contained the whole large message. If client
101 | memory is also constrained this may not be possible.
102 |
103 | ##### Streaming a Large Message
104 |
105 | However, it is possible to stream a message straight from disk or another type of Input Stream. This can only be done via the JMS API by sending a JMS BytesMessage and setting an input stream as an Object property, like so
106 |
107 | ```java
108 | BytesMessage bytesMessage = session.createBytesMessage();
109 | FileInputStream fileInputStream = new FileInputStream(inputFile);
110 | BufferedInputStream bufferedInput = new BufferedInputStream(fileInputStream);
111 | bytesMessage.setObjectProperty("JMS_AMQ_InputStream", bufferedInput);
112 | ```
113 |
114 | The client will stream the contents of the file direct to the TCP stream in chunks.
115 | This is then handled by the Broker as a large message. To see this in action use the
116 | `com.redhat.workshop.amq7.streammessage.Sender`.
117 |
118 | ```sh
119 | $ mvn verify -PStreamMessageSender
120 | ```
121 |
122 | Inspect the large message store and you will again see the large message file.
123 |
124 | To consume a stream message you simple consume a JMS BytesMessage with an OutputStream using the JMS API like so:
125 |
126 |
127 | ```java
128 | BytesMessage messageReceived = (BytesMessage) messageConsumer.receive(120000);
129 | File outputFile = new File("huge_message_received.dat");
130 | FileOutputStream fileOutputStream = new FileOutputStream(outputFile)
131 | BufferedOutputStream bufferedOutput = new BufferedOutputStream(fileOutputStream);
132 |
133 | //This will save the stream and wait until the entire message is written before continuing.
134 | messageReceived.setObjectProperty("JMS_AMQ_SaveStream", bufferedOutput);
135 | ```
136 |
137 | To see this in action use the
138 | `com.redhat.workshop.amq7.streammessage.Receiver` to receive a stream message like so:
139 |
140 | ```sh
141 | $ mvn verify -PStreamMessageReceiver
142 | ```
143 |
144 | > ##### Note
145 | >
146 | > Stream messages and large messages are interchangeable so you can send a large
147 | > message and consume a stream message and vice versa.
148 |
--------------------------------------------------------------------------------
/demos/broker/large-messages/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 | 4.0.0
23 |
24 |
25 | com.redhat.workshop.amq
26 | broker-demos
27 | 1.0.0
28 |
29 |
30 | largeMessage
31 | 1.0.0
32 | jar
33 | AMQ 7 JMS Large Message Example
34 |
35 |
36 |
37 | org.apache.geronimo.specs
38 | geronimo-jms_2.0_spec
39 |
40 |
41 | org.apache.activemq
42 | artemis-commons
43 |
44 |
45 | org.apache.activemq
46 | artemis-jms-client
47 |
48 |
49 |
50 |
51 |
52 | LargeMessageSender
53 |
54 |
55 |
56 | org.codehaus.mojo
57 | exec-maven-plugin
58 | 1.1
59 |
60 |
61 | verify
62 |
63 | java
64 |
65 |
66 |
67 |
68 | com.redhat.workshop.amq7.largemessage.Sender
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | LargeMessageReceiver
77 |
78 |
79 |
80 | org.codehaus.mojo
81 | exec-maven-plugin
82 | 1.1
83 |
84 |
85 | verify
86 |
87 | java
88 |
89 |
90 |
91 |
92 | com.redhat.workshop.amq7.largemessage.Receiver
93 |
94 |
95 |
96 |
97 |
98 |
99 | StreamMessageSender
100 |
101 |
102 |
103 | org.codehaus.mojo
104 | exec-maven-plugin
105 | 1.1
106 |
107 |
108 | verify
109 |
110 | java
111 |
112 |
113 |
114 |
115 | com.redhat.workshop.amq7.streammessage.Sender
116 |
117 |
118 |
119 |
120 |
121 |
122 | StreamMessageReceiver
123 |
124 |
125 |
126 | org.codehaus.mojo
127 | exec-maven-plugin
128 | 1.1
129 |
130 |
131 | verify
132 |
133 | java
134 |
135 |
136 |
137 |
138 | com.redhat.workshop.amq7.streammessage.Receiver
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/demos/broker/large-messages/src/main/java/com/redhat/workshop/amq7/largemessage/Receiver.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.workshop.amq7.largemessage;
18 |
19 | import javax.jms.Connection;
20 | import javax.jms.ConnectionFactory;
21 | import javax.jms.Message;
22 | import javax.jms.MessageConsumer;
23 | import javax.jms.Queue;
24 | import javax.jms.Session;
25 | import javax.naming.InitialContext;
26 |
27 | public class Receiver {
28 | public static void main(String args[]) throws Exception{
29 |
30 | try {
31 | InitialContext context = new InitialContext();
32 |
33 | Queue queue = (Queue) context.lookup("queue/exampleQueue");
34 |
35 | ConnectionFactory cf = (ConnectionFactory) context.lookup("ConnectionFactory");
36 |
37 | try (
38 | Connection connection = cf.createConnection();
39 | ) {
40 | Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
41 | MessageConsumer consumer = session.createConsumer(queue);
42 | connection.start();
43 | Message message = consumer.receiveNoWait();
44 | System.out.println("received message from broker " + message);
45 | }
46 | } catch (Exception e) {
47 | e.printStackTrace();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/demos/broker/large-messages/src/main/java/com/redhat/workshop/amq7/largemessage/Sender.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.workshop.amq7.largemessage;
18 |
19 |
20 | import javax.jms.BytesMessage;
21 | import javax.jms.Connection;
22 | import javax.jms.MessageProducer;
23 | import javax.jms.Queue;
24 | import javax.jms.Session;
25 | import javax.naming.InitialContext;
26 | import javax.jms.ConnectionFactory;
27 |
28 | public class Sender {
29 | public static void main(String args[]) throws Exception{
30 |
31 | try {
32 | InitialContext context = new InitialContext();
33 |
34 | Queue queue = (Queue) context.lookup("queue/exampleQueue");
35 |
36 | ConnectionFactory cf = (ConnectionFactory) context.lookup("ConnectionFactory");
37 |
38 | try (
39 | Connection connection = cf.createConnection();
40 | ) {
41 | Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
42 | MessageProducer producer = session.createProducer(queue);
43 | BytesMessage bytesMessage = session.createBytesMessage();
44 |
45 | // Send a 100MB message
46 | byte[] bytes = new byte[100 * 1024 * 1024];
47 | bytesMessage.writeBytes(bytes);
48 | producer.send(bytesMessage);
49 | }
50 | } catch (Exception e) {
51 | e.printStackTrace();
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/demos/broker/large-messages/src/main/java/com/redhat/workshop/amq7/streammessage/Receiver.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.workshop.amq7.streammessage;
18 |
19 |
20 | import javax.jms.BytesMessage;
21 | import javax.jms.Connection;
22 | import javax.jms.ConnectionFactory;
23 | import javax.jms.MessageConsumer;
24 | import javax.jms.Queue;
25 | import javax.jms.Session;
26 | import javax.naming.InitialContext;
27 | import java.io.BufferedOutputStream;
28 | import java.io.File;
29 | import java.io.FileOutputStream;
30 |
31 | public class Receiver {
32 | public static void main(String args[]) throws Exception{
33 |
34 | try {
35 | InitialContext context = new InitialContext();
36 |
37 | Queue queue = (Queue) context.lookup("queue/exampleQueue");
38 |
39 | ConnectionFactory cf = (ConnectionFactory) context.lookup("ConnectionFactory");
40 |
41 | try (
42 | Connection connection = cf.createConnection();
43 | ) {
44 | Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
45 |
46 | connection.start();
47 |
48 | MessageConsumer messageConsumer = session.createConsumer(queue);
49 |
50 | connection.start();
51 |
52 | BytesMessage messageReceived = (BytesMessage) messageConsumer.receive(120000);
53 |
54 | File outputFile = new File("huge_message_received.dat");
55 |
56 | try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {
57 | BufferedOutputStream bufferedOutput = new BufferedOutputStream(fileOutputStream);
58 |
59 | //This will save the stream and wait until the entire message is written before continuing.
60 | messageReceived.setObjectProperty("JMS_AMQ_SaveStream", bufferedOutput);
61 | }
62 | }
63 | } catch (Exception e) {
64 | e.printStackTrace();
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/demos/broker/large-messages/src/main/java/com/redhat/workshop/amq7/streammessage/Sender.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.redhat.workshop.amq7.streammessage;
18 |
19 |
20 | import javax.jms.BytesMessage;
21 | import javax.jms.Connection;
22 | import javax.jms.ConnectionFactory;
23 | import javax.jms.MessageProducer;
24 | import javax.jms.Queue;
25 | import javax.jms.Session;
26 | import javax.naming.InitialContext;
27 | import java.io.BufferedInputStream;
28 | import java.io.BufferedOutputStream;
29 | import java.io.File;
30 | import java.io.FileInputStream;
31 | import java.io.FileOutputStream;
32 | import java.io.IOException;
33 | import java.util.Random;
34 |
35 | import org.apache.activemq.artemis.utils.RandomUtil;
36 |
37 | public class Sender {
38 |
39 | private static final long FILE_SIZE = 1L;//1 GiB message
40 |
41 | public static void main(String args[]) {
42 | try {
43 | File inputFile = new File("huge_message_to_send.dat");
44 |
45 | createFile(inputFile, FILE_SIZE);
46 |
47 | InitialContext context = new InitialContext();
48 |
49 | Queue queue = (Queue) context.lookup("queue/exampleQueue");
50 |
51 | ConnectionFactory cf = (ConnectionFactory) context.lookup("ConnectionFactory");
52 |
53 | try (
54 | Connection connection = cf.createConnection();
55 | ) {
56 | Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
57 | MessageProducer producer = session.createProducer(queue);
58 | BytesMessage bytesMessage = session.createBytesMessage();
59 | FileInputStream fileInputStream = new FileInputStream(inputFile);
60 | BufferedInputStream bufferedInput = new BufferedInputStream(fileInputStream);
61 | bytesMessage.setObjectProperty("JMS_AMQ_InputStream", bufferedInput);
62 | producer.send(bytesMessage);
63 | }
64 | } catch (Exception e) {
65 | e.printStackTrace();
66 | }
67 | }
68 | private static void createFile(final File file, final long fileSize) throws IOException {
69 | FileOutputStream fileOut = new FileOutputStream(file);
70 | try (BufferedOutputStream buffOut = new BufferedOutputStream(fileOut)) {
71 |
72 | // Sends a 10MB file
73 | for (int r = 0; r < 10 * 1024; r++) {
74 | for (long c = 0; c < 1023; c ++) {
75 | buffOut.write(RandomUtil.randomChar());
76 | }
77 | buffOut.write('\n');
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/demos/broker/large-messages/src/main/resources/jndi.properties:
--------------------------------------------------------------------------------
1 | java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory
2 | connectionFactory.ConnectionFactory=tcp://localhost:61616?minLargeMessageSize=10240
3 | queue.queue/exampleQueue=exampleQueue
--------------------------------------------------------------------------------
/demos/broker/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 | 4.0.0
23 |
24 | com.redhat.workshop.amq
25 | broker-demos
26 | 1.0.0
27 | pom
28 | AMQ 7 Broker Demos
29 |
30 |
31 | 1.8
32 | 1.8
33 | 2.0.0.amq-700005-redhat-1
34 | 1.0.0.alpha-2-redhat-2
35 | 0.23.0
36 |
37 |
38 |
39 |
40 | Red Hat Maven
41 | redhat
42 | https://maven.repository.redhat.com/ga/
43 |
44 |
45 |
46 |
47 | addressing
48 | large-messages
49 | high-availability
50 |
51 |
52 |
53 |
54 |
55 | org.apache.qpid
56 | qpid-jms-client
57 | ${qpid.jms.version}
58 |
59 |
60 | org.apache.activemq
61 | artemis-commons
62 | ${amq7.version}
63 |
64 |
69 |
70 | org.apache.activemq
71 | artemis-jms-client
72 | ${amq7.version}
73 |
74 |
75 | org.apache.geronimo.specs
76 | geronimo-jms_2.0_spec
77 | ${geronimo.spec.version}
78 |
79 |
80 | org.apache.qpid
81 | qpid-jms-client
82 | 0.21.0.redhat-1
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/demos/broker/security/README.md:
--------------------------------------------------------------------------------
1 | # Security in AMQ 7 broker
2 |
3 | This worksheet covers security in the AMQ 7 broker. By the end of this you should know:
4 |
5 | 1. How the AMQ 7 security architecture compares to AMQ 6
6 | 2. How to require authentication and manipulate user data using the default JAAS properties login module
7 | 3. How to grant a user access to certain permissions via role-based authorization
8 | 4. How to configure SSL
9 |
10 | ## AMQ 7 vs. AMQ 6
11 |
12 | Those familiar with AMQ 6 security will find lots of similarities in AMQ 7. Both brokers leverage JAAS. If you're unfamiliar with JAAS you can get a quick overview [here](https://en.wikipedia.org/wiki/Java_Authentication_and_Authorization_Service). These JAAS login modules have ported over from AMQ 6 to AMQ 7 with minimal changes:
13 | * Properties files
14 | * LDAP
15 | * SSL certificate
16 | * Guest
17 |
18 | The "dual" authentication feature is also present in AMQ 7. This feature allows independent JAAS domains for SSL and non-SSL connections.
19 |
20 | AMQ 6 has these permission types:
21 |
22 | * **read**
23 | * **write**
24 | * **admin**
25 |
26 | Whereas AMQ 7 has these permission types:
27 |
28 | * **createDurableQueue** allows the user to create a durable queue
29 | * **deleteDurableQueue** allows the user to delete a durable queue
30 | * **createNonDurableQueue** allows the user to create a non-durable queue
31 | * **deleteNonDurableQueue** allows the user to delete a non-durable queue
32 | * **send** allows the user to send a message
33 | * **consume** allows the user to consume a message from a queue bound to matching addresses
34 | * **browse** allows the user to browse a queue bound to the matching address
35 | * **manage** allows the user to invoke management operations by sending management messages to the management address
36 |
37 | Creating and deleting queues is particularly important in AMQ 7 as that is how subscriptions are implemented. For example, a JMS client wanting to create a durable subscription would need the `createDurableQueue` permission.
38 |
39 | ## Authentication
40 |
41 | Configuration starts in `AMQ_INSTANCE/etc/bootstrap.xml`. This is the default configuration:
42 |
43 |
44 |
45 | The `domain` attribute refers to the relevant login module entry in `AMQ_INSTANCE/etc/login.config`. For example, if an instance were created with the following command:
46 |
47 | ```
48 | $ /bin/artemis create --user admin --password password --role admin --allow-anonymous /instances/mybroker
49 | ```
50 |
51 | Then this would appear in `login.config`:
52 |
53 | activemq {
54 | org.apache.activemq.artemis.spi.core.security.jaas.PropertiesLoginModule sufficient
55 | debug=false
56 | reload=true
57 | org.apache.activemq.jaas.properties.user="artemis-users.properties"
58 | org.apache.activemq.jaas.properties.role="artemis-roles.properties";
59 |
60 | org.apache.activemq.artemis.spi.core.security.jaas.GuestLoginModule sufficient
61 | debug=false
62 | org.apache.activemq.jaas.guest.user="admin"
63 | org.apache.activemq.jaas.guest.role="admin";
64 | };
65 |
66 | The `--allow-anonymous` switch in the `artemis create` command ensures the "guest" login module is added to `login.config` so that anonymous users can access the broker. By default, anonymous are assigned the user and role also specified in the `artemis create` command via the `user` and `role` switches. Alternatively one can omit `--allow-anonymous` and specify `--require-login` instead and the "guest" login module will be omitted from `login.config`.
67 |
68 | By default user credentials and role information are stored in the properties files `artemis-users.properties` and `artemis-roles.properties` respectively.
69 |
70 | The `artemis-users.properties` file consists of a list of properties of the form, `UserName=Password`. For example, to define the users `system`, `user`, and `guest`, you could create a file like the following:
71 |
72 | ```properties
73 | system=systemPassword
74 | user=userPassword
75 | guest=guestPassword
76 | ```
77 |
78 | The `artemis-roles.properties` file consists of a list of properties of the form, `Role=UserList`, where UserList is a comma-separated list of users. For example, to define the roles `admins`, `users`, and `guests`, you could create a file like the following:
79 |
80 | ```properties
81 | admins=system
82 | users=system,user
83 | guests=guest
84 | ```
85 |
86 |
87 | By default passwords are hashed using `PBKDF2WithHmacSHA1`. However, un-hashed passwords can be manually added if desired by creating an entry without the ENC() syntax.
88 |
89 | The CLI support commands to manipulate these files, e.g.:
90 |
91 | ```
92 | $ /bin/artemis user add|rm|list|reset
93 | ```
94 |
95 | ### Hands on
96 |
97 | Create a new broker instance using this command where `` and `` are whatever you choose:
98 |
99 | ```
100 | $ /bin/artemis create --user --password --role admin --require-login /instances/mysecurebroker
101 | ```
102 |
103 | Start that instance using this command:
104 |
105 | ```
106 | $ /bin/artemis run
107 | ```
108 |
109 | Run this command, passing in the user and password specified when the instance was created.
110 |
111 | ```
112 | $ /bin/artemis producer --message-count 1 --user --password
113 | ```
114 |
115 | Now run it again with a new user and password.
116 |
117 | ```
118 | $ /bin/artemis producer --message-count 1 --user --password
119 | ```
120 |
121 | This will fail because the broker doesn't recognize the user.
122 |
123 | Add this new user to the broker (make sure the `role` is the same as when the instance was created):
124 |
125 | ```
126 | $ /bin/artemis user add --user --password --role admin
127 | ```
128 |
129 | The broker will automatically reload the properties files so that the new user is now valid. Run this command, passing in the *new* user and *new* password which were just added.
130 |
131 | ```
132 | $ /bin/artemis producer --message-count 1 --user --password
133 | ```
134 |
135 | Open `AMQ_INSTANCE/etc/artemis-users.properties` and see the new user and its hashed password.
136 |
137 | ## Authorization
138 |
139 | Authorization is configured in `AMQ_INSTANCE/etc/broker.xml` in the `` element. Here is the default configuration from an instance created via this command:
140 |
141 | ```
142 | $ /bin/artemis create --user admin --password password --role admin --allow-anonymous /instances/mybroker
143 | ```
144 |
145 | The role specified in the command via the `role` switch is inserted into the `roles` attribute.
146 |
147 | ```xml
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 | ```
164 |
165 | A `security-setting` matches one or more addresses via the `match` attribute. The matching functionality supports wildcards like `#` which signifies "any sequence of words." See [the documentation](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_amq_broker/addresses#wildcard_syntax) for more details about the wildcard syntax.
166 |
167 | Since the default `security-setting` matches `#` and refers only to the `admin` role that means only users in the `admin` role can perform any real work.
168 |
169 | ### Hands on
170 |
171 | Remove the user you created previously (which was in the `admin` role):
172 |
173 | ```
174 | $ /bin/artemis user rm --user
175 | ```
176 |
177 | Recreate that user in a different role:
178 |
179 | ```
180 | $ /bin/artemis user add --user --password --role
181 | ```
182 |
183 | Attempt to send a message with this user:
184 |
185 | ```
186 | $ /bin/artemis producer --message-count 1 --user --password
187 | ```
188 |
189 | You should see an error with something like this:
190 |
191 | ```
192 | User: does not have permission='SEND' on address TEST
193 | ```
194 |
195 | Modify the `security-setting` to allow your new user to send:
196 |
197 | ```xml
198 |
199 | ```
200 |
201 | The running broker will automatically reload the modified `security-settings`. Now attempt to send again:
202 |
203 | ```
204 | $ /bin/artemis producer --message-count 1 --user --password
205 | ```
206 |
207 | The send will now succeed.
208 |
209 | ## SSL
210 |
211 | Both one-way and two-way SSL are supported.
212 |
213 | SSL artifact configuration can be done a few different ways:
214 |
215 | * Standard system properties:
216 |
217 | ```text
218 | javax.net.ssl.keyStore
219 | javax.net.ssl.keyStorePassword
220 | javax.net.ssl.trustStore
221 | javax.net.ssl.trustStorePassword
222 | ```
223 |
224 | * Broker-specific system properties (will override standard system properties):
225 |
226 | ```text
227 | org.apache.activemq.ssl.keyStore
228 | org.apache.activemq.ssl.keyStorePassword
229 | org.apache.activemq.ssl.trurestStore
230 | org.apache.activemq.ssl.trustStorePassword
231 | ```
232 |
233 | * URL (either on a connector or acceptor):
234 |
235 | tcp://localhost:5500?sslEnabled=true;__keyStorePath__=../etc/activemq.example.keystore;__keyStorePassword__=activemqexample;__trustStorePath__=../etc/activemq.example.truststore;__trustStorePassword__=activemqexample
236 |
237 | Regardless of how the SSL artifacts are configured the `sslEnabled` URL property must always be `true`.
238 |
239 | An acceptor can require a client-side certificate by setting the `needClientAuth` URL property to `true`.
240 |
241 | ## Misc
242 |
243 | To disable security completely simply set the `security-enabled` property to false in the `broker.xml` file.
244 |
245 | For performance reasons security is cached and invalidated every so long. To change this period set the property `security-invalidation-interval`, which is in milliseconds. The default is `10000` ms.
246 |
247 | Password masking is supported.
248 |
--------------------------------------------------------------------------------
/dockerfiles/interconnnect/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM registry.access.redhat.com/rhel7/rhel
2 |
3 | MAINTAINER Andrew Block
4 |
5 | LABEL io.k8s.description="Lightweight AMQP message router for building scalable, available, and performant messaging networks." \
6 | io.k8s.display-name="AMQ Interconnect Dispatch Router" \
7 | io.openshift.tags="amq,java,interconnect,router" \
8 | io.openshift.expose-services="5671,5001,5672,55672,10002,10003"
9 |
10 |
11 | RUN yum repolist > /dev/null && \
12 | yum-config-manager --enable amq-interconnect-1-for-rhel-7-server-rpms --enable a-mq-clients-1-for-rhel-7-server-rpms && \
13 | yum clean all && \
14 | INSTALL_PKGS="qpid-proton-c \
15 | python-qpid-proton \
16 | qpid-dispatch-router \
17 | qpid-dispatch-tools" && \
18 | yum install -y --setopt=tsflags=nodocs install $INSTALL_PKGS && \
19 | rpm -V $INSTALL_PKGS && \
20 | yum clean all
21 |
22 | EXPOSE 5001 5672 55672 10002 10003
23 |
24 | CMD ["/usr/sbin/qdrouterd", "-c", "/etc/qpid-dispatch/qdrouterd.conf"]
--------------------------------------------------------------------------------
/dockerfiles/qdr/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM centos:centos7.3.1611
2 |
3 | RUN rpm -i https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
4 | RUN yum -y update
5 | RUN yum -y install qpid-proton-c-devel python-qpid-proton man
6 |
7 | WORKDIR /opt/amq7
8 |
9 | RUN mkdir -p /opt/amq7/router
10 |
11 | COPY ./rpms ./router
12 |
13 | RUN rpm -Uvh ./router/*.rpm
14 |
15 | VOLUME /etc/qpid-dispatch/
16 |
17 | EXPOSE 5672 55672 5671
18 | CMD ["/usr/sbin/qdrouterd", "--conf", "/etc/qpid-dispatch/qdrouterd.conf"]
--------------------------------------------------------------------------------
/labs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/.gitkeep
--------------------------------------------------------------------------------
/labs/00-install-broker.md:
--------------------------------------------------------------------------------
1 | # Installing the AMQ7 Broker
2 |
3 | To begin, verify you have [all of the prerequisites](README.md) for these labs.
4 |
5 | As a reminder, JBoss AMQ7 comes with four main components:
6 |
7 | * AMQ7 Broker
8 | * AMQ7 Interconnect Router
9 | * AMQ7 Clients
10 | * Management Console
11 |
12 | The Broker comes with the management console, but the Interconnect Router and each individual client comes as a separate binary/download/installation.
13 |
14 | We'll start by downloading the binaries for JBoss AMQ 7 Broker. In later labs, we'll get to the [clients](20-clients.md) as well as the [interconnect router](80-install-qdr.md)
15 |
16 | All of the components are available at the [Downloads page](https://developers.redhat.com/products/amq/download/) of [https://developers.redhat.com/products/amq/overview/](https://developers.redhat.com/products/amq/overview/). Navigate to that page and download the AMQ7 Broker:
17 |
18 | 
19 |
20 | Alternatively, if you are a current Red Hat customer, you can download the latest AMQ7 (and any associated patches) from the [Red Hat Customer Portal](https://access.redhat.com/products/red-hat-jboss-amq/). Even if you don't currently have JBoss AMQ subscriptions, you still have access to all of the Red Hat products and documentation for development/evaluation purposes.
21 |
22 | Once you click one of the download links and you have the broker downloaded, navigate to your command line (Powershell, Bash, Cygwin, etc) and locate the newly downloaded file (e.g. `jboss-amq-7.0.0.redhat-1-bin.zip`). You can move this .zip file to a location of your choosing (e.g. ~/dev/labs or similar).
23 |
24 | Using your favorite `unzip` utility, unzip the `jboss-amq-7.0.0.redhat-1-bin.zip` binary file and navigate into the newly created directory:
25 |
26 | $ unzip jboss-amq-7.0.0.redhat-1-bin.zip
27 | $ cd jboss-amq-7.0.0.redhat-1
28 |
29 | If you do a listing of the directory, you should see something similar to this:
30 |
31 | $ ls -l
32 |
33 | ```
34 | total 56
35 | -rw-r--r--@ 1 ceposta staff 15K Apr 21 11:25 LICENSE
36 | -rw-r--r--@ 1 ceposta staff 179B Apr 21 11:25 NOTICE
37 | -rw-r--r--@ 1 ceposta staff 4.7K Apr 21 11:25 README.html
38 | drwxrwxr-x@ 5 ceposta staff 170B May 3 06:55 bin
39 | drwxrwxr-x@ 3 ceposta staff 102B May 3 06:55 etc
40 | drwxrwxr-x@ 7 ceposta staff 238B May 3 06:55 examples
41 | drwxrwxr-x@ 49 ceposta staff 1.6K Apr 21 11:48 lib
42 | drwxrwxr-x@ 5 ceposta staff 170B May 3 06:55 schema
43 | drwxrwxr-x@ 16 ceposta staff 544B May 3 06:55 web
44 |
45 | ```
46 |
47 | Let's have a look at each folder:
48 |
49 | * `bin` -- Set up scripts for creating and managing brokers
50 | * `etc` -- Bootstrap settings for running `artemis` commands
51 | * `examples` -- handful of useful examples for getting started with AMQ7
52 | * `lib` -- where the AMQ7 libs and dependencies are packaged
53 | * `schema` -- config files schemas
54 | * `web` -- where the main web console configuration and libraries are stored
55 |
56 | ## Creating a Broker
57 |
58 | Up until this point, we've just download the main binaries and bootstrap configuration, but we still don't have a broker.
59 |
60 | > Note this is a bit different from AMQ6 if you've used that in the past. In AMQ6, the initial binary download was the broker itself. With AMQ7, we need to explicitly create a broker with the settings that we prefer.
61 |
62 | Let's create a new folder in a location we choose (could be inside the installation folder if we'd like) called `brokers` and let's create a new broker inside of it:
63 |
64 | $ mkdir brokers
65 | $ ./bin/artemis create brokers/myfirstbroker
66 |
67 | You'll be prompted to enter information that we've left off the command line. Fill in the user, password, and other information similar to this:
68 |
69 | ```
70 | Creating ActiveMQ Artemis instance at: /Users/ceposta/dev/activemq/jboss-amq-7.0.0.redhat-1/brokers/myfirstbroker
71 |
72 | --user: is a mandatory property!
73 | Please provide the default username:
74 | admin
75 |
76 | --password: is mandatory with this configuration:
77 | Please provide the default password:
78 |
79 |
80 | --allow-anonymous | --require-login: is a mandatory property!
81 | Allow anonymous access?, valid values are Y,N,True,False
82 | Y
83 |
84 | Auto tuning journal ...
85 | done! Your system can make 14.71 writes per millisecond, your journal-buffer-timeout will be 68000
86 |
87 | You can now start the broker by executing:
88 |
89 | "/Users/ceposta/dev/activemq/jboss-amq-7.0.0.redhat-1/brokers/myfirstbroker/bin/artemis" run
90 |
91 | Or you can run the broker in the background using:
92 |
93 | "/Users/ceposta/dev/activemq/jboss-amq-7.0.0.redhat-1/brokers/myfirstbroker/bin/artemis-service" start
94 | ```
95 |
96 | Congrats! You've just created your *first* AMQ7 broker :)
97 |
98 | Note that some auto-tuning was done based on your environment. This is pretty handy when it comes to selecting the appropriate configuration for your persistent messaging use cases, but we'll come back to that in a subsequent lab.
99 |
100 | If you're curious what command-line arguments you *can* pass to the `create` command, use the `help` command like this:
101 |
102 | $ ./bin/artemis help
103 |
104 | So in this case, we'd list the help documentation for the `create` command like this:
105 |
106 | $ ./bin/artemis help create
107 |
108 | ## Starting our new broker
109 |
110 | In the previous section, we created a new broker and in the output of the command we saw instructions for how to start the broker.
111 | Before we do that, let's navigate to our new `brokers/myfirstbroker` folder and check out the directory structure and see what was created.
112 |
113 | $ cd brokers/myfirstbroker
114 | $ ls -l
115 |
116 | ```
117 | drwxr-xr-x 4 ceposta staff 136B May 10 13:58 bin
118 | drwxr-xr-x 2 ceposta staff 68B May 10 13:58 data
119 | drwxr-xr-x 9 ceposta staff 306B May 10 13:58 etc
120 | drwxr-xr-x 2 ceposta staff 68B May 10 13:58 log
121 | drwxr-xr-x 2 ceposta staff 68B May 10 13:58 tmp
122 | ```
123 |
124 | These are the folders in the newly created broker `myfirstbroker`. Let's see what they have in them:
125 |
126 | * `bin` -- scripts to control the lifecycle of our new broker
127 | * `data` -- where all of the transaction/journal logs are stored for our messages
128 | * `etc` -- the configuration for our broker
129 | * `log` -- the log output from running our broker
130 | * `tmp` -- temporary disk usage
131 |
132 | We'll start the new broker in the foreground with the following:
133 |
134 | $ ./bin/artemis run
135 |
136 | ```
137 | __ __ ____ ____ _
138 | /\ | \/ |/ __ \ | _ \ | |
139 | / \ | \ / | | | | | |_) |_ __ ___ | | _____ _ __
140 | / /\ \ | |\/| | | | | | _ <| '__/ _ \| |/ / _ \ '__|
141 | / ____ \| | | | |__| | | |_) | | | (_) | < __/ |
142 | /_/ \_\_| |_|\___\_\ |____/|_| \___/|_|\_\___|_|
143 |
144 | Red Hat JBoss AMQ 7.0.0.redhat-1
145 |
146 |
147 | 14:07:31,490 INFO [org.apache.activemq.artemis.integration.bootstrap] AMQ101000: Starting ActiveMQ Artemis Server
148 | 14:07:31,540 INFO [org.apache.activemq.artemis.core.server] AMQ221000: live Message Broker is starting with configuration Broker Configuration (clustered=false,journalDirectory=./data/journal,bindingsDirectory=./data/bindings,largeMessagesDirectory=./data/large-messages,pagingDirectory=./data/paging)
149 | 14:07:31,578 INFO [org.apache.activemq.artemis.core.server] AMQ221013: Using NIO Journal
150 | 14:07:31,671 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-server]. Adding protocol support for: CORE
151 | 14:07:31,671 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-amqp-protocol]. Adding protocol support for: AMQP
152 | 14:07:31,671 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-hornetq-protocol]. Adding protocol support for: HORNETQ
153 | 14:07:31,672 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-mqtt-protocol]. Adding protocol support for: MQTT
154 | 14:07:31,672 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-openwire-protocol]. Adding protocol support for: OPENWIRE
155 | 14:07:31,672 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-stomp-protocol]. Adding protocol support for: STOMP
156 | 14:07:31,716 INFO [org.apache.activemq.artemis.core.server] AMQ221034: Waiting indefinitely to obtain live lock
157 | 14:07:31,717 INFO [org.apache.activemq.artemis.core.server] AMQ221035: Live Server Obtained live lock
158 | 14:07:31,865 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue DLQ
159 | 14:07:31,931 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue ExpiryQueue
160 | 14:07:32,733 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started NIO Acceptor at 0.0.0.0:61616 for protocols [CORE,MQTT,AMQP,STOMP,HORNETQ,OPENWIRE]
161 | 14:07:32,735 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started NIO Acceptor at 0.0.0.0:5445 for protocols [HORNETQ,STOMP]
162 | 14:07:32,737 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started NIO Acceptor at 0.0.0.0:5672 for protocols [AMQP]
163 | 14:07:32,739 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started NIO Acceptor at 0.0.0.0:1883 for protocols [MQTT]
164 | 14:07:32,741 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started NIO Acceptor at 0.0.0.0:61613 for protocols [STOMP]
165 | 14:07:32,741 INFO [org.apache.activemq.artemis.core.server] AMQ221007: Server is now live
166 | 14:07:32,742 INFO [org.apache.activemq.artemis.core.server] AMQ221001: Apache ActiveMQ Artemis Message Broker version 2.0.0.amq-700005-redhat-1 [0.0.0.0, nodeID=ae7bf278-35c4-11e7-97d9-0a0027000001]
167 | INFO | main | Initialized artemis-plugin plugin
168 | INFO | main | Initialized dispatch-hawtio-console plugin
169 | 14:07:35,393 INFO [org.apache.activemq.artemis] AMQ241001: HTTP Server started at http://localhost:8161
170 | 14:07:35,394 INFO [org.apache.activemq.artemis] AMQ241002: Artemis Jolokia REST API available at http://localhost:8161/jolokia
171 | ```
172 |
173 | Yay! We've got our broker installed and running!
174 |
175 | Take a quick glance at the log output and note a few things:
176 |
177 | * The location of our transaction logs and cluster configuration
178 | * We're using the NIO Journal for persistence
179 | * We have a single port, `61616` that can accept connections for multiple protocols (i.e. `CORE`, `MQTT`, `AMQP`, `STOMP`, `HORNETQ`, `OPENWIRE`)
180 | * We have individual ports for each protocol as well
181 | * We see that the web console has been started at `http://localhost:8161`
182 | * We see that the Jolokia (a JMX over REST) service has been started at `http://localhost:8161/jolokia`
183 |
184 | That's it for this lab!
185 |
186 | To learn more about getting started, see the [product documentation at the Red Hat support portal!](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_amq_broker/getting_started)
187 |
--------------------------------------------------------------------------------
/labs/10-configure-broker.md:
--------------------------------------------------------------------------------
1 | # Configuring AMQ 7
2 |
3 | In this lab, we'll take a look at the AMQ7 configuration files and some basic configuration options and things to be aware of. We'll dig into more specific configurations (like persistence, clustering, etc) in later labs.
4 |
5 | If we navigate back to our `brokers/myfirstbroker` installation that we created in the previous lab we can examine our configuration. AMQ7 configuration is stored in `etc/` folder. If we do a listing of the `etc/` folder we should see something similar to the following:
6 |
7 | $ cd brokers/myfirstbroker
8 | $ ls -l ./etc/
9 |
10 | ```
11 | total 64
12 | -rw-r--r-- 1 ceposta staff 961B May 10 13:58 artemis-roles.properties
13 | -rw-r--r-- 1 ceposta staff 1.1K May 10 13:58 artemis-users.properties
14 | -rw-r--r-- 1 ceposta staff 2.0K May 10 13:58 artemis.profile
15 | -rw-r--r-- 1 ceposta staff 1.6K May 10 13:58 bootstrap.xml
16 | -rw-r--r-- 1 ceposta staff 8.0K May 10 13:58 broker.xml
17 | -rw-r--r-- 1 ceposta staff 2.2K May 10 13:58 logging.properties
18 | -rw-r--r-- 1 ceposta staff 1.3K May 10 13:58 login.config
19 | ```
20 |
21 |
22 | For the sake of this lab, we're going to look closer at the following files
23 |
24 | * `bootstrap.xml` -- the entry point to starting a broker
25 | * `broker.xml` -- the main broker configuration file; configures network connections, security, message addresses, etc.
26 |
27 | If you'd like more information on the rest of the files, [see the product documentation on the Red Hat Customer Support portal](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_amq_broker/basic_configuration#configuration_files_and_locations).
28 |
29 | ### bootstrap.xml
30 |
31 | The `bootstrap.xml` file is fairly straight forward and contains a small set of configurations for starting a broker. The most important configuration here is the `` element. This configuration setting allows us to instruct the bootstrap runtime where the main configuration file is. We may opt to keep these configuration settings in a version controlled repository that gets installed into the server where the AMQ7 broker runs independently of how/when the broker gets created. Alternatively, if we choose to run our broker in a container environment, we may want to mount in the config files independently of the broker/container. The default setting is:
32 |
33 |
34 |
35 | The `bootstrap.xml` file also designates what applications are installed on the webserver that hosts the management console for our broker. We can configure details about this server (where it binds to, etc) as well as what application are exposed. Have a look at the `bootstrap.xml` file for more details and default configuration.
36 |
37 | Lastly, we can specify the bootstrap security configurations, like the JAAS domain name.
38 |
39 | ### broker.xml
40 |
41 | The most important configuration file is the `broker.xml` file. We'll cover some of the specifics of these configuration settings in subsequent labs, but just be aware, the major sections of configuration:
42 |
43 | * persistence
44 | * security
45 | * acceptors
46 | * addresses
47 |
48 | #### Configuration Reload
49 |
50 | Often times we'd like to make changes to the broker while it's running without taking the broker down. For some certain configurations, we're able to make changes at runtime while the broker is up and have those changes take effect. By default, every 5s the broker will poll its `broker.xml` configs and merge in changes it finds. The following sections are allowed to be changed at runtime (and will take effect upon change detection):
51 |
52 | * Security
53 | * Address settings
54 | * JMS Queues/Topics
55 |
56 | Note, if we were to remove addresses/queues, these would not be removed upon reload. This could introduce a scenario where we lose messages as a result. We can remove queues using the management features, but not by auto-reload.
57 |
58 | #### Persistence
59 |
60 | In the persistence section, we can configure whether we will use persistence (true/false), what type of journal impelemntation we'll use (NIO/AIO/JDBC) and the location on disk where the journals will be held for potentially different classes of messages (bindings, large-messages, main journal, etc). You can also tune the journal write buffers, number of files to keep etc, using this group of configuration settings.
61 |
62 | #### Security
63 |
64 | AMQ7 has fine grained Role Based Access Control for specifying what users can do when they connect and interact with addresses in the messaging system. Using the Security section of the `broker.xml` configuration file, we can assign roles to specific permissions such as `createDurableQueues` or `browse`, `send`, or `consume`, etc.
65 |
66 | #### Acceptors
67 |
68 | Acceptors are the "window" into the broker and is what clients connect to. Using acceptors we can expose different protocols on different ports, configure things like SSL/TLS and associated keystores, etc. If you look at the configuration for the `` section in the `broker.xml` file, you'll see something similar to this:
69 |
70 | ```
71 |
72 |
73 |
74 | tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300
75 |
76 |
77 | tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpMinCredits=300
78 |
79 |
80 | tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true
81 |
82 |
83 | tcp://0.0.0.0:5445?protocols=HORNETQ,STOMP;useEpoll=true
84 |
85 |
86 | tcp://0.0.0.0:1883?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=MQTT;useEpoll=true
87 |
88 |
89 |
90 | ```
91 |
92 | For example, to connect as an AMQP client, you'd configure your client to connect on port `5672` which is the default AMQP port. Alternatively, as you can see, there is a single acceptor that's capable of detecting and serving multiple protocols that listens on port `61616`. An AMQP (or STOMP, etc) client could also connect to this port.
93 |
94 | #### Addresses
95 |
96 | Lastly, the `` and `` section of the configuration define more granular properties for sets of destinations defined as *addresses*. In AMQ7, an *address* is an abstraction of any physical destination (actually, it can be many destinations). An *address* has a name, 0 or more destinations, and a routing type, of which that can be:
97 |
98 |
99 | | Routing Type | Description |
100 | |---|---|
101 | | Anycast | Deliver messages in a point-to-point manner |
102 | | Multicast | Deliver messages to all consumers in a group |
103 |
104 | We can associate an address with 0 or more physical queues. By default, AMQ7 configuration has the following addresses configured:
105 |
106 | ```
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | ```
120 |
121 | ## Exercise
122 |
123 | In this lab, we're going to do two things:
124 |
125 | 1. Remove all of the `acceptors` except the default one on port `61616` which can handle all protocols
126 | 2. Add a new address and route it to a queue
127 |
128 | First, make sure your broker is stopped. In the previous lab we started the broker in the foreground; if it's still running, do a CTRL+C (^C) to gracefully bring it down.
129 |
130 |
131 | ### 1. Remove all acceptors
132 | Now, using your favorite text editor, open the `etc/broker.xml` file and find the section for the `acceptors`:
133 |
134 | ```
135 |
136 |
137 |
138 | tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300
139 |
140 |
141 | tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpMinCredits=300
142 |
143 |
144 | tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true
145 |
146 |
147 | tcp://0.0.0.0:5445?protocols=HORNETQ,STOMP;useEpoll=true
148 |
149 |
150 | tcp://0.0.0.0:1883?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=MQTT;useEpoll=true
151 |
152 |
153 |
154 | ```
155 |
156 | Delete all of the acceptors **except** the one listening on port `61616`. Your configuration for `acceptors` should look like this:
157 |
158 | ```
159 |
160 |
161 |
162 | tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300
163 |
164 |
165 |
166 | ```
167 |
168 | Now start up your broker in the foreground like we did in the previous lab:
169 |
170 | ./bin/artemis run
171 |
172 | When the broker starts up, you should see ONLY the single acceptor in the logs (see below). You will see logs saying protocol modules have been found, but that's OKAY.
173 |
174 | 
175 |
176 |
177 | ### 2. Add a new address
178 |
179 | Now that our broker is running, let's try adding a new address and watch it reload the configuration automatically. Fire up your favorite editor again and edit the `etc/broker.xml` file.
180 |
181 | Add the following section to the `addresses` section:
182 |
183 | ```
184 |
185 |
186 |
187 |
188 |
189 | ```
190 |
191 | The configuration should look like this once edited:
192 |
193 | ```
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 | ```
212 |
213 | Now save your configuration file, wait at most 5s (the default refresh scan) and watch the broker logs to see if any changes have been detected:
214 |
215 | You should see something similar to the following:
216 |
217 | ```
218 | 15:39:33,873 INFO [org.apache.activemq.artemis.core.server] AMQ221056: Reloading configuration ...security
219 | 15:39:33,875 INFO [org.apache.activemq.artemis.core.server] AMQ221056: Reloading configuration ...address settings
220 | 15:39:33,875 INFO [org.apache.activemq.artemis.core.server] AMQ221056: Reloading configuration ...diverts
221 | 15:39:33,875 INFO [org.apache.activemq.artemis.core.server] AMQ221056: Reloading configuration ...addresses
222 | 15:39:33,879 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue foo
223 | 15:39:33,887 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue DLQ
224 | 15:39:33,887 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue ExpiryQueue
225 |
226 | ```
227 |
228 | That completes this lab! To see more in depth, follow the [product documentation on the Red Hat Customer Support portal](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_amq_broker/basic_configuration#configuration_files_and_locations)
229 |
--------------------------------------------------------------------------------
/labs/100-brokerless.md:
--------------------------------------------------------------------------------
1 | # Brokerless routing
2 |
3 | Although the Interconnect Router can be used to build large-scale, geographically distributed broker clusters, it also provides a mechanism to do inter-network RPC against a transparent backplane where producers and consumers are decoupled in location (just like with a broker, but without a broker). This gives some of the best of both the messaging and RPC worlds. Let's take a look.
4 |
5 |
6 | In this lab we'll take a look at configuring the Interconnect Router to route messages to and from an AMQ7 broker. Clients can talk directly to the router and think they're talking to a broker.
7 |
8 | Take a look in the `labs/qdr/brokerless` folder. We have three different Interconnect configuration files and a couple different scripts to control the demo. We'll be using docker to run this demo, so verify you have access to a docker host (either on your laptop with Docker for Mac/Windows, or using Minikube, or using Red Hat CDK 3.0).
9 |
10 |
11 | Let's take a look at the salient parts of the configuration:
12 |
13 | router3.conf:
14 |
15 | ```json
16 | listener {
17 | role: normal
18 | host: 0.0.0.0
19 | port: 5672
20 | linkCapacity: 1000
21 | }
22 |
23 | ...
24 |
25 | listener {
26 | role: inter-router
27 | host: 0.0.0.0
28 | port: 10003
29 | }
30 |
31 | ```
32 |
33 | Here we see that we're opening a listener for port `5672` and for `10003`. The `5672` port is for AMQP clients to connect directly to the router mesh. Port `10003` is for other routers to connect. Note the `role` each listener has (ie, `normal` and `inter-router`). We would expect the other routers to connect to this router via is listener on `10003`. Also, this router doesn't have any connectors to any other routers.
34 |
35 | router2.conf:
36 |
37 | ```json
38 | listener {
39 | role: inter-router
40 | host: 0.0.0.0
41 | port: 10002
42 | }
43 |
44 | ...
45 |
46 | connector {
47 | role: inter-router
48 | host: router3
49 | port: 10003
50 | saslMechanisms: ANONYMOUS
51 | }
52 |
53 | ```
54 |
55 | In this configuration file, we see that there are *no* AMQP listeners (nothing listening on `5672`, and no listeners labeled `normal`). There is a single listener on port `10002`. We do see a single connector pointing to the router3 `10003` port. Let's look at the last router:
56 |
57 | router1.conf:
58 |
59 | ```json
60 |
61 | listener {
62 | role: normal
63 | host: 0.0.0.0
64 | port: 5672
65 | linkCapacity: 1000
66 | }
67 |
68 |
69 | ...
70 |
71 | connector {
72 | role: inter-router
73 | host: router2
74 | port: 10002
75 | saslMechanisms: ANONYMOUS
76 | }
77 |
78 | connector {
79 | role: inter-router
80 | host: router3
81 | port: 10003
82 | saslMechanisms: ANONYMOUS
83 | }
84 |
85 | ```
86 |
87 | In this configuration, we see that this router also exposes an AMQP port on `5672`. It also connects to the other routers, router 2 on port `10002` and router 3 on `10003`
88 |
89 | Now that we see how the routers are connected with each other, let's bootstrap the router mesh. Make sure you're in the `labs/qdr/brokerless` folder and type:
90 |
91 | ```bash
92 | ./start.sh
93 | ```
94 |
95 | This will bootstrap each broker with their respective configuration files and link them together properly. The containers will be running in the background, so you can take a look at each ones logs to verify they're up correctly:
96 |
97 | ```bash
98 | docker logs router1
99 | 4area\xa1\x010"
100 | Thu May 25 13:42:50 2017 ROUTER_CORE (trace) Core action 'delete_delivery'
101 | Thu May 25 13:42:50 2017 ROUTER_CORE (trace) Core action 'delete_delivery'
102 | Thu May 25 13:42:50 2017 ROUTER_CORE (trace) Core action 'link_flow'
103 | Thu May 25 13:42:50 2017 ROUTER_CORE (trace) Core action 'link_flow'
104 | Thu May 25 13:42:50 2017 SERVER (trace) [2]:1 <- @flow(19) [next-incoming-id=2600, incoming-window=2147483647, next-outgoing-id=0, outgoing-window=2147483647, handle=0, delivery-count=2600, link-credit=250, drain=false]
105 | Thu May 25 13:42:50 2017 SERVER (trace) [2]:0 <- @transfer(20) [handle=0, delivery-id=2604, delivery-tag=b"X\x14\x00\x00\x00\x00\x00\x00", message-format=0, settled=true, more=false] (229) "\x00Sr\xd1\x00\x00\x00E\x00\x00\x00\x04\xa3\x0ex-opt-qd.trace\xd0\x00\x00\x00\x0f\x00\x00\x00\x01\xa1\x090/Router3\xa3\x10x-opt-qd.ingress\xa1\x090/Router3\x00Ss\xd0\x00\x00\x00\x1f\x00\x00\x00\x06@@\xa1\x14amqp:/_local/qdhello@@@\x00St\xd1\x00\x00\x00\x13\x00\x00\x00\x02\xa1\x06opcode\xa1\x05HELLO\x00Sw\xd1\x00\x00\x00N\x00\x00\x00\x08\xa1\x04seen\xd0\x00\x00\x00\x16\x00\x00\x00\x02\xa1\x07Router2\xa1\x07Router1\xa1\x08instance\x81\x00\x00\x00\x00Y&\xd5\xd9\xa1\x02id\xa1\x07Router3\xa1\x04area\xa1\x010"
106 |
107 | ```
108 |
109 | To run the demo, make sure you start a receiver first:
110 |
111 | ```bash
112 | ./receiver_router3.sh
113 | ```
114 |
115 | This will connect to router 3 on its AMQP port (`5672`) and begin listening for messages on address `/myAddress`.
116 |
117 | Let's start the sender:
118 |
119 | ```bash
120 | ./sender_router1.sh
121 | ```
122 |
123 | This will connect to the router 1 on its AMQP port and send messages to address `/myAddress`. You should see indications of a single message flowing through the mesh (via the sender/receiver logs).
124 |
--------------------------------------------------------------------------------
/labs/110-enmasse.md:
--------------------------------------------------------------------------------
1 | # Messaging as a Service with Enmasse
2 |
3 | Red Hat AMQ Online is a new Messaging as a Service (MaaS) offering built on OpenShift. It offers a self-service approach to managing brokers, giving developers the ability to create and manage their own queues and topics. This lab steps you through this process using the technical preview environment from Red Hat.
4 |
5 | To get started:
6 |
7 | 1. Request an Red Hat AMQ Online account by [email](amq-online-tech-preview-owner@redhat.com).
8 | 2. Login to Enmasse using the credentials given in the response email. Ensure you can login and view the Dashboard
9 | 3. Click on "Addresses", then click "Create". Create a new address called "queue" using the standard plan
10 | 4. Git clone the qpid-jms project from [here](https://github.com/apache/qpid-jms) to a local directory
11 | 5. Update the `jndi.properties` file located in `qpid-jms-examples/src/main/resources/jndi.properties` with the following:
12 |
13 | ```
14 | connectionfactory.myFactoryLookup = amqps://?transport.trustAll=true&transport.verifyHost=false
15 | queue.myQueueLookup = queue
16 | ```
17 | 6. Via the command line, execute the following command in the `qpid-jms-examples` directory:
18 |
19 | ```
20 | java -cp "target/classes/:target/dependency/*" -DUSER="" -DPASSWORD="" org.apache.qpid.jms.example.Sender
21 | ```
22 | 7. Check the Enmasse dashboard and it's been updated with the messages sent to "queue". You should see "10 messages sent".
23 | 8. Via the command line, execute the following command to consume the messages:
24 |
25 | ```
26 | java -cp "target/classes/:target/dependency/*" -DUSER="" -DPASSWORD="" org.apache.qpid.jms.example.Receiver
27 | ```
28 | 9. The metrics in the Dashboard should be updated with 10 messages sent / received
29 |
--------------------------------------------------------------------------------
/labs/20-clients.md:
--------------------------------------------------------------------------------
1 | # AMQ 7 Clients
2 |
3 | AMQ 7 comes with several new clients covering a variety of protocols and programming languages. In the past, any supported clients were only released when we released new versions of the AMQ product. With AMQ7 that has changed; each client has its own lifecycle and is released independently from the AMQ broker/server components.
4 |
5 | AMQ7 includes the following supported clients:
6 |
7 | * AMQ JMS Client ([official docs](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_the_amq_jms_client/))
8 | * AMQ C++ Client ([official docs](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_the_amq_cpp_client/))
9 | * AMQ JavaScript/NodeJS Client ([official docs](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_the_amq_javascript_client/))
10 | * AMQ Python Client ([official docs](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_the_amq_python_client/))
11 | * AMQ .NET Client ([official docs](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_the_amq_.net_client/))
12 |
13 | Let's explore the clients.
14 |
15 | ## AMQ JMS Client
16 |
17 | To use the AMQ JMS client, navigate to [https://developers.redhat.com/products/amq/download/](https://developers.redhat.com/products/amq/download/) and locate the AMQ JMS Client.
18 |
19 | 
20 |
21 | When you've downloaded the file, copy it to a location where you'd like to unzip this client.
22 |
23 | $ mv ~/Downloads/apache-qpid-jms-0.21.0.redhat-1-bin.zip ./clients/
24 | $ cd clients
25 | $ unzip apache-qpid-jms-0.21.0.redhat-1-bin.zip
26 | $ cd apache-qpid-jms-0.21.0.redhat-1
27 |
28 |
29 | Now we'll explore the client. In the distribution we just unzipped, there's an `examples` folder. Navigate into it and you'll find a Java Maven project. Let's build the project:
30 |
31 |
32 | $ cd examples
33 | $ mvn -s example-settings.xml install
34 |
35 | If successful, you should see output like this:
36 |
37 | ```
38 | [INFO]
39 | [INFO] --- maven-install-plugin:2.5.2:install (default-install) @ qpid-jms-examples ---
40 | [INFO] Skipping artifact installation
41 | [INFO] ------------------------------------------------------------------------
42 | [INFO] BUILD SUCCESS
43 | [INFO] ------------------------------------------------------------------------
44 | [INFO] Total time: 4.063 s
45 | [INFO] Finished at: 2017-05-11T15:52:15-07:00
46 | [INFO] Final Memory: 28M/456M
47 | [INFO] ------------------------------------------------------------------------
48 | ```
49 |
50 | Feel free to open this project in your favorite IDE (like [JBoss Developer Studio](https://developers.redhat.com/products/devstudio/overview/)).
51 |
52 | A couple of things to notice about this example:
53 |
54 | * Our JMS ConnectionFactory and destination names are configured in the `src/main/resources/jndi.properties` file
55 | * Our `org.apache.qpid.jms.example.HelloWorld` main() class bootstraps the `MessageConsumer` and `MessageProducer` used in this example
56 | * We lookup the JMS connection information from JNDI as specified in our `jndi.properties` file
57 | * We send one message and receive one message.
58 |
59 | Review the code closer to get an idea of what it's doing:
60 |
61 | ```java
62 | public static void main(String[] args) throws Exception {
63 | try {
64 | // The configuration for the Qpid InitialContextFactory has been supplied in
65 | // a jndi.properties file in the classpath, which results in it being picked
66 | // up automatically by the InitialContext constructor.
67 | Context context = new InitialContext();
68 |
69 | ConnectionFactory factory = (ConnectionFactory) context.lookup("myFactoryLookup");
70 | Destination queue = (Destination) context.lookup("myQueueLookup");
71 |
72 | Connection connection = factory.createConnection(System.getProperty("USER"), System.getProperty("PASSWORD"));
73 | connection.setExceptionListener(new MyExceptionListener());
74 | connection.start();
75 |
76 | Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
77 |
78 | MessageProducer messageProducer = session.createProducer(queue);
79 | MessageConsumer messageConsumer = session.createConsumer(queue);
80 |
81 | TextMessage message = session.createTextMessage("Hello world!");
82 | messageProducer.send(message, DeliveryMode.NON_PERSISTENT, Message.DEFAULT_PRIORITY, Message.DEFAULT_TIME_TO_LIVE);
83 | TextMessage receivedMessage = (TextMessage) messageConsumer.receive(2000L);
84 |
85 | if (receivedMessage != null) {
86 | System.out.println(receivedMessage.getText());
87 | } else {
88 | System.out.println("No message received within the given timeout!");
89 | }
90 |
91 | connection.close();
92 | } catch (Exception exp) {
93 | System.out.println("Caught exception, exiting.");
94 | exp.printStackTrace(System.out);
95 | System.exit(1);
96 | }
97 | }
98 | ```
99 |
100 | To run this example, we'll first download all of the project's dependencies:
101 |
102 | $ mvn -s example-settings.xml clean package dependency:copy-dependencies -DincludeScope=runtime -DskipTests
103 |
104 | Next, we need to make sure our broker is running. If you've followed from the previous labs, you have a broker running with a single `Acceptor` running on port `61616`. Let's change our `jndi.properties` file to reflect this change. (if you're coming to this lab from your own installation/running instance of the AMQ7 broker, adjust the properties as needed; e.g., if you still have the dedicated AMQP `Acceptor` running, then no need to make this change).
105 |
106 | Our `jndi.properties` file should look like this, with the `connectionfactory.myFactoryLookup` property set to `61616`
107 |
108 | NOTE: We need to change the connection factory URL to `61616` since our `acceptor` does not have the other ports open.
109 |
110 | ```
111 | # Set the InitialContextFactory class to use
112 | java.naming.factory.initial = org.apache.qpid.jms.jndi.JmsInitialContextFactory
113 |
114 | # Define the required ConnectionFactory instances
115 | # connectionfactory. =
116 | connectionfactory.myFactoryLookup = amqp://localhost:61616
117 |
118 | # Configure the necessary Queue and Topic objects
119 | # queue. =
120 | # topic. =
121 | queue.myQueueLookup = queue
122 | topic.myTopicLookup = topic
123 | ```
124 |
125 | Now let's build our project and run:
126 |
127 | $ mvn -s example-settings.xml clean install
128 | $ mvn -s example-settings.xml clean package dependency:copy-dependencies -DincludeScope=runtime -DskipTests
129 | $ java -cp "target/classes/:target/dependency/*" org.apache.qpid.jms.example.HelloWorld
130 |
131 | If everything completed properly, you should see the following output:
132 |
133 | ```
134 | Hello world!
135 | ```
136 |
137 | #### Some things to note:
138 |
139 | The URL we passed to the connection factory should be in the following form:
140 |
141 | > amqp[s]://hostname:port[?option=value[&option2=value...]]
142 |
143 | We can also use the failover URI (discussed in future lab) like this:
144 |
145 | > failover:(amqp://host1:port[,amqp://host2:port...])[?option=value[&option2=value...]]
146 |
147 | Options for configuration can be [found at the AMQ7 JMS Client product documentation](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_the_amq_jms_client/configuration#connection_uri_options_jms)
148 |
149 |
150 | ## AMQ NodeJS Client
151 |
152 | The AMQ NodeJS client can be used to connect to the AMQ7 broker (or any compatible AMQP 1.0 broker) and can send and receive messages regardless of what clients produced them (ie, they could be MQTT IoT producers for example).
153 |
154 | To use the AMQ NodeJS client, navigate to [https://developers.redhat.com/products/amq/download/](https://developers.redhat.com/products/amq/download/) and locate the AMQ NodeJS (called "JavaScript" in the download portal) Client.
155 |
156 | 
157 |
158 | When you've downloaded the file, copy it to a location where you'd like to unzip this client.
159 |
160 | $ mv ~/Downloads/nodejs-rhea-0.2.0-1.zip . ./clients/
161 | $ cd clients
162 | $ unzip nodejs-rhea-0.2.0-1.zip
163 | $ cd nodejs-rhea-0.2.0-1
164 |
165 | To run the examples, we'll need to install two dependencies:
166 |
167 | $ npm install debug
168 | $ npm install yargs
169 |
170 | Now let's navigate to the `examples` folder and take a look at the application that will receive messages from the broker:
171 |
172 | $ cd node_modules/rhea/examples
173 |
174 | Open up the `simple_recv.js` file in your favorite editor:
175 |
176 | ```js
177 | var args = require('yargs').options({
178 | 'm': { alias: 'messages', default: 100, describe: 'number of messages to expect'},
179 | 'n': { alias: 'node', default: 'examples', describe: 'name of node (e.g. queue) from which messages are received'},
180 | 'p': { alias: 'port', default: 5672, describe: 'port to connect to'}
181 | }).help('help').argv;
182 |
183 | var received = 0;
184 | var expected = args.messages;
185 |
186 | container.on('message', function (context) {
187 | if (context.message.id && context.message.id < received) {
188 | // ignore duplicate message
189 | return;
190 | }
191 | if (expected === 0 || received < expected) {
192 | console.log(JSON.stringify(context.message.body))
193 | if (++received === expected) {
194 | context.receiver.detach();
195 | context.connection.close();
196 | }
197 | }
198 | });
199 |
200 | container.connect({'port':args.port}).open_receiver(args.node);
201 | ```
202 |
203 |
204 | We see that this simple receiver application tries to connect to a broker on port `5672` by default (which is also the AMQP default port) and tries to read messages from the `examples` queue. Since we have our broker running on port `61616`, let's run our receiver and direct it to connect to our broker on the correct port:
205 |
206 | $ node simple_recv.js -p 61616
207 |
208 | Open another window to run our sender. Navigate back to the same directory where the examples where and run:
209 |
210 | $ node simple_send.js -p 61616
211 |
212 | Note that for the sender, we're also changing its port. Hit enter to run the sender. You should see similar output:
213 |
214 | From the receiver:
215 |
216 | ```
217 | {"sequence":1}
218 | .
219 | .
220 | .
221 | {"sequence":90}
222 | {"sequence":91}
223 | {"sequence":92}
224 | {"sequence":93}
225 | {"sequence":94}
226 | {"sequence":95}
227 | {"sequence":96}
228 | {"sequence":97}
229 | {"sequence":98}
230 | {"sequence":99}
231 | {"sequence":100}
232 | ```
233 |
234 | From the sender:
235 |
236 | ```
237 | sent 1
238 | .
239 | .
240 | .
241 | sent 90
242 | sent 91
243 | sent 92
244 | sent 93
245 | sent 94
246 | sent 95
247 | sent 96
248 | sent 97
249 | sent 98
250 | sent 99
251 | sent 100
252 | all messages confirmed
253 | ```
254 |
255 |
256 |
257 |
258 | ## Other clients
259 |
260 | You can download the other clients from the Red Hat support portal or the developers.redhat.com site. At the moment all the clients are available for download there EXCEPT the *Python* and *Linux C++* libraries (for RHEL). Those are available as RPMs through your RHEL subscription.
261 |
--------------------------------------------------------------------------------
/labs/30-produce-consume.md:
--------------------------------------------------------------------------------
1 | # Producing and Consuming
2 |
3 | AMQ7 has many features. We are going to work through a couple of those features, but at the end of this lab you should feel comfortable with some of the basics. We'll leave suggestions at the end for where to learn more about the other features not covered in this lab.
4 |
5 | ## Use cases:
6 |
7 | * Send messages to the broker
8 | * Receive messages from the broker
9 | * Request Reply
10 | * Dead Letter Queue (DLQ)
11 | * Last Value queue
12 |
13 |
14 | ## Before we begin
15 |
16 | In the previous labs we've installed and configured our broker. We eliminated the individual ports/protocols and are happy to have all protocols go through the default `Acceptor` at port `61616`. For the remainder of this section, please verify that your broker is running and able to take connections. Each of the next sections assumes this is the case.
17 |
18 | ### Send
19 | Let's look at how to easily send and consume messages from a queue. In the [previous lab](./20-clients.md), we explored some of the client APIs. How we send messages to the broker will depend on what programming language and API you wish to use. But what if you just want to quickly test whether the broker is up? Or that some configuration you changed is working as expcted? What if you just want to send some sample load to the broker and don't want to build a producer/client from scratch? Luckily, Artemis comes with some tools for exploring these scenarios.
20 |
21 | You should have your `myfirstbroker` running with:
22 |
23 | ```bash
24 | $ ./bin/artemis run
25 | ```
26 |
27 | This should give you a broker running in the foreground.
28 |
29 | In a different window try running the following command:
30 |
31 | ```bash
32 | $ ./bin/artemis help producer
33 | ```
34 |
35 |
36 | This should show a help guide for how to use a simple producer to send messages to the AMQ7 broker.
37 |
38 | Let's try sending messages:
39 |
40 | ```bash
41 | $ ./bin/artemis producer --destination address.helloworld --message-count 100 --url tcp://localhost:61616
42 | ```
43 |
44 |
45 |
46 | If we [go to the Broker web console](http://localhost:8161/hawtio) at [http://localhost:8161/hawtio](http://localhost:8161/hawtio) we should see that we now have `100` messages in the `foo` queue. Remember from the first lab, we created a new address called `address.helloworld` and bound it as an `Anycast` address to the `foo` queue.
47 |
48 | > Note: use the credentials you set when we created the broker; admin/admin
49 |
50 | 
51 |
52 | Let's use the same tools to consume messages.
53 |
54 | ### Receive
55 |
56 | Let' use the same CLI tools to simulate consumption from addresses on the broker. Let's try to consume from the same address `address.helloworld` -- but let's not consume all the messages. Let's start by consuming `50` of the messages. Just like in the previous section, we want to make sure the broker is up and running and listening on port `61616`. In a separate window, let's take a look at the parameters for the `consumer` command:
57 |
58 | ```bash
59 | $ ./bin/artemis help consumer
60 | ```
61 |
62 | Now let's try to consume 50 messages from the `foo` queue (remember, our `Anycast` address was bound to `foo`):
63 |
64 | ```bash
65 | $ ./bin/artemis consumer --destination foo --message-count=50 --url tcp://localhost:61616
66 | ```
67 |
68 | You should get output similar to this:
69 |
70 | ```bash
71 | Consumer:: filter = null
72 | Consumer ActiveMQQueue[foo], thread=0 wait until 50 messages are consumed
73 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 0
74 | .
75 | .
76 | .
77 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 39
78 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 40
79 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 41
80 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 42
81 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 43
82 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 44
83 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 45
84 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 46
85 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 47
86 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 48
87 | Consumer ActiveMQQueue[foo], thread=0 Received test message: 49
88 | ```
89 |
90 |
91 | So now if we look at our console, we should see that `50` messages are still left on our queue `foo`:
92 |
93 | 
94 |
95 | No go find where your broker is running and let's kill the broker. If we try to consume from the broker at this point, we should see that we cannot establish a connection. When we restart the broker, we exepct our messages to still be on the broker and availabe for consumption. Let's fire up the broker again:
96 |
97 | ```bash
98 | $ ./bin/artemis run
99 | ```
100 |
101 | Navigate back to the web console and verify we still have `50` messages on the queue `foo`.
102 |
103 | Let's consume the last `50` messages:
104 |
105 | ```bash
106 | $ ./bin/artemis consumer --destination foo --message-count=50 --url tcp://localhost:61616
107 | ```
108 |
109 | And we should see our queue is now empty:
110 |
111 | 
112 |
113 |
114 | ### Request Reply
115 |
116 | Messaging is typically used to decouple producers and consumers in two main dimensions: time, and space. When will a consumer see messages? Who knows, but it's not the producer's responsibility. Where do the consumers even live? Again, not a detail a producer should be coupled to. However, there are use cases where producing messages/events will necessitate a response from *some* consumer downstream. You may already have usecases implemented like this using some legacy proprietary queuing system and would like a nice replacement for that legacy system but cannot change your application. However you come across a request-reply usecase here's what it looks like with JBoss AMQ7.
117 |
118 | In the root of the AMQ7 broker installation, there is an `examples` folder. There are a handful of nice examples here. Navigate to:
119 |
120 | ```bash
121 | $ cd $AMQ7_BASE/examples/features/standard/request-reply
122 | ```
123 |
124 | Copy the example-settings.xml you used in previous labs to the request-reply directory. Let's run the example. Note, just like in the previous sections, we need to have a broker running:
125 |
126 | ```bash
127 | $ mvn -s example-settings.xml verify -DnoServer=true
128 | ```
129 |
130 | We should see an output like this:
131 |
132 | ```bash
133 | [INFO] --- artemis-maven-plugin:2.0.0.amq-700005-redhat-1:runClient (runClient) @ request-reply ---
134 | Request message sent.
135 | Received request message: A request message
136 | Reply to queue: ActiveMQTemporaryQueue[d6677193-fef2-4fee-9f8b-d84b08eaff37]
137 | Reply sent
138 | Received reply: A reply message
139 | CorrelatedId: ID:76c9b485-39ba-11e7-b79b-0a0027000003
140 | We found matched request: A request message
141 | [INFO]
142 | [INFO] --- artemis-maven-plugin:2.0.0.amq-700005-redhat-1:cli (stop) @ request-reply ---
143 | [INFO] ------------------------------------------------------------------------
144 | [INFO] BUILD SUCCESS
145 | [INFO] ------------------------------------------------------------------------
146 | [INFO] Total time: 4.427 s
147 | [INFO] Finished at: 2017-05-15T15:04:27-07:00
148 | [INFO] Final Memory: 37M/457M
149 | [INFO] ------------------------------------------------------------------------
150 | ```
151 |
152 | So what happened here? We sent a message to a queue and got a response. But what does this look like?
153 |
154 | If you open the `Java` source file in the `request-reply` project `src/main/java//org/apache/activemq/artemis/jms/example/RequestReplyExample.java` we can see a little about how this happens.
155 |
156 | First we set up the connection-factory infromation and make a connection to the broker. Then we do the following:
157 |
158 | 1. Set up the producer
159 |
160 | For this, we create a producer to the "request queue" but we also create a temporary destination and attach a consumer to that temporary destination. This simulates the producer sending a message and also waiting for a response on the temporary destination:
161 |
162 | ```java
163 | MessageProducer producer = session.createProducer(requestQueue);
164 |
165 | TemporaryQueue replyQueue = session.createTemporaryQueue();
166 |
167 | MessageConsumer replyConsumer = session.createConsumer(replyQueue);
168 | ```
169 |
170 | Next, we create our message and send it. Before we send it, however, we set a JMS property to specify where the response should be sent. It should, of course, be sent to our temporary destination like we are expecting:
171 |
172 | ```java
173 | TextMessage requestMsg = session.createTextMessage("A request message");
174 |
175 | requestMsg.setJMSReplyTo(replyQueue);
176 |
177 | producer.send(requestMsg);
178 | ```
179 |
180 | We should optionally try to coordinate/correlate the response when it comes back to us. We'll save the message ID or some correlation ID that we specify:
181 |
182 | ```java
183 | requestMap.put(requestMsg.getJMSMessageID(), requestMsg);
184 | ```
185 |
186 | 2. Set up the consumer
187 |
188 | On the consumer side, we should consume the message like normal (either using a `receive` method or `onMessage` listener) but also check the `ReplyTo` header. We should generate a response and send that response to the destination specified in the `ReplyTo` header:
189 |
190 |
191 | ```java
192 | public void onMessage(final Message request) {
193 | try {
194 | System.out.println("Received request message: " + ((TextMessage) request).getText());
195 |
196 | // Extract the ReplyTo destination
197 | Destination replyDestination = request.getJMSReplyTo();
198 |
199 | System.out.println("Reply to queue: " + replyDestination);
200 |
201 | // Create the reply message
202 | TextMessage replyMessage = session.createTextMessage("A reply message");
203 |
204 | // Set the CorrelationID, using message id.
205 | replyMessage.setJMSCorrelationID(request.getJMSMessageID());
206 |
207 | // Send out the reply message
208 | replyProducer.send(replyDestination, replyMessage);
209 |
210 | System.out.println("Reply sent");
211 | } catch (JMSException e) {
212 | e.printStackTrace();
213 | }
214 | }
215 | ```
216 |
217 |
218 | ### Dead Letter Queue
219 |
220 | What happens when a consumer cannot process a message? Or what happens when a transaction is rolled back? A JMS message in the AMQ7 broker will be redelivered (and possibly to other consumers) if a consumer is having trouble with it. The problem is, we cannot just redeliver for ever because it will starve other consumers and messages it that come later in the queue. To deal with this, we can send the non-consumable message to the "dead letter queue".
221 |
222 | First, we'll need to configure the broker for dead-letter queue (DLQ) behavior. Let's open our `myfirstbroker` configuration file in `etc/broker.xml` and navigate to the `address-settings` location. We should see an entry similar to this:
223 |
224 | ```xml
225 |
226 | DLQ
227 | ExpiryQueue
228 | 0
229 |
230 | -1
231 | 10
232 | PAGE
233 | true
234 | true
235 | true
236 | true
237 |
238 | ```
239 |
240 | This configuration sets up a "dead-letter queue" for "#" (which is all, recursive) destinations set to a value of `DLQ`. If you look in the web console, you'll see a queue named `DLQ`.
241 |
242 | By default, the max number of retries is `10` but for this lab, we want to change it to a smaller number. Let's change it to `3` by adding a configuration `3` to our `address-settings`. Your config should look like this:
243 |
244 | ```xml
245 |
246 | DLQ
247 | 3
248 | ExpiryQueue
249 | 0
250 |
251 | -1
252 | 10
253 | PAGE
254 | true
255 | true
256 | true
257 | true
258 |
259 | ```
260 |
261 | Now save your `broker.xml` file. If you had your broker running while you made the change, you should see the configuration auto-reload with a message similar to this in the broker logs:
262 |
263 | ```bash
264 | 15:26:47,336 INFO [org.apache.activemq.artemis.core.server] AMQ221056: Reloading configuration ...security
265 | 15:26:47,339 INFO [org.apache.activemq.artemis.core.server] AMQ221056: Reloading configuration ...address settings
266 | 15:26:47,340 INFO [org.apache.activemq.artemis.core.server] AMQ221056: Reloading configuration ...diverts
267 | 15:26:47,340 INFO [org.apache.activemq.artemis.core.server] AMQ221056: Reloading configuration ...addresses
268 | 15:26:47,351 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue foo
269 | 15:26:47,352 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue DLQ
270 | 15:26:47,352 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue ExpiryQueue
271 | ```
272 |
273 | Now, let's go to the `dead-letter` example from the examples that ship with the AMQ7 broker:
274 |
275 | ```bash
276 | $ cd $AMQ7_BASE/examples/features/standard/dead-letter
277 | ```
278 |
279 | The example will try to consume messages a few times and try rolling them back 3 times to force the message to the `DLQ` queue. One thing we want to change: we want to configure out example to use `DLQ` as the dead-letter queue. To do this, let's open the `src/main/resources/jndi.properties` file dn change the `queue.queue/deadLetterQueue` to be `DLQ`
280 |
281 | Your file should look like this:
282 |
283 | ```java
284 | java.naming.factory.initial=org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory
285 | connectionFactory.ConnectionFactory=tcp://localhost:61616
286 | queue.queue/exampleQueue=exampleQueue
287 | queue.queue/deadLetterQueue=DLQ
288 | ```
289 |
290 | Let's run the example
291 |
292 | ```bash
293 | $ mvn verify -DnoServer=true
294 | ```
295 |
296 | We should see output like this:
297 |
298 | ```bash
299 | Sent message to exampleQueue: this is a text message
300 | 1st delivery from exampleQueue: this is a text message
301 | 2nd delivery from exampleQueue: this is a text message
302 | 3rd delivery from exampleQueue: this is a text message
303 | 4th delivery from exampleQueue: null
304 | ```
305 |
306 | If we check the `DLQ` queue in the web console, we can see that it now has one message in it:
307 |
308 | 
309 |
310 | ### Last Value queue
311 |
312 | A last-value queue is a special kind of queue that keeps only the most recent message for a specific type of message (defined by a `Last-Value` property). This could be useful for stock price updates where we really only care about the most recent updates.
313 |
314 | First, we'll need to configure the broker for last-value queue behavior for the destinations we define. We don't want all of our queues to be last-value, so we need to explicitly set up a specific queue. Let's open our `myfirstbroker` configuration file in `etc/broker.xml` and navigate to the `address-settings` location. We will add a configuration for a queue named `exampleQueue` to be a last-value queue:
315 |
316 | ```xml
317 |
318 | true
319 |
320 | ```
321 |
322 | We will also add a new `Anycast` address and bind it to a queue named `exampleQueue`:
323 |
324 | ```xml
325 | "
326 |
327 |
328 |
329 |
330 | ```
331 |
332 |
333 | Now, let's go to the `last-value-queue` example from the examples that ship with the AMQ7 broker:
334 |
335 | ```bash
336 | $ cd $AMQ7_BASE/examples/features/standard/last-value-queue
337 | ```
338 |
339 | Let's run the example
340 |
341 | ```bash
342 | $ mvn verify -DnoServer=true
343 | ```
344 |
345 | We should see output like this:
346 |
347 | ```bash
348 | [INFO] --- artemis-maven-plugin:2.0.0.amq-700005-redhat-1:runClient (runClient) @ last-value-queue ---
349 | Sent message: 1st message with Last-Value property set
350 | Sent message: 2nd message with Last-Value property set
351 | Sent message: 3rd message with Last-Value property set
352 | Message in the queue: 3rd message with Last-Value property set
353 | Received message: 3rd message with Last-Value property set
354 | Received message: null
355 | ```
356 |
357 | Let's take a closer look at what's going on.
358 |
359 | If you open the `Java` source file in the `last-value-queue` project `src/main/java//org/apache/activemq/artemis/jms/example/LastValueQueueExample.java` we can see a little about how this happens.
360 |
361 | When we send messages to the `exampleQueue` queue (which was earlier configured for Last Value semantics), we are adding a JMS property named `_AMQ_LVQ_NAME` which is the field that the last-value queue implementation will match on:
362 |
363 | ```java
364 | TextMessage message = session.createTextMessage("1st message with Last-Value property set");
365 | message.setStringProperty("_AMQ_LVQ_NAME", "STOCK_NAME");
366 | producer.send(message);
367 | ```
368 |
369 | If the queue sees multiple messages with the same `_AMQ_LVQ_NAME` property, then it will only keep the most recent message. The example sends in three messages with the same value (`_AMQ_LVQ_NAME1` equal to `STOCK_NAME`) and tries to consume from the `exampleQueue` queue. It finds only the 3rd message sent.
370 |
371 |
372 |
373 | ## Where to go from here
374 |
375 | Check out the examples in the distro
376 |
--------------------------------------------------------------------------------
/labs/40-master-slave.md:
--------------------------------------------------------------------------------
1 | # Master/Slave - Shared Store
2 |
3 | A-MQ 7 has the ability to run in a master/slave (ie, active/passive) configuration so that if an active node goes down, another can immediately take its place and continue serving clients and processing messages. There are a few different options that can be used to achieve this:
4 |
5 | * Shared store
6 | * Replicated store (ie, "shared nothing")
7 | * Co-located
8 |
9 | For the purpose of this lab, we will focus on the "Shared store" option for persistence, and use the "Static" option for clustering.
10 |
11 | ## Prerequisites
12 |
13 | Download and install the A-MQ 7 broker package as described in [Lab 1](00-install-broker.md).
14 |
15 | ## Creating the brokers
16 |
17 | ```
18 | $ $AMQ_HOME/bin/artemis create brokers/master --name master --user admin --password admin --allow-anonymous
19 | $ $AMQ_HOME/bin/artemis create brokers/slave --name slave --user admin --password admin --allow-anonymous --port-offset 1
20 | ```
21 |
22 | _Note: We could have passed in some extra arguments to configure our master/slave pair with some defaults, but instead we're going to manually configure them via the `broker.xml` file so we can become familiar with the available options._
23 |
24 | ## Editing the configuration
25 |
26 | __Master__
27 |
28 | 1. Open up the `brokers/master/etc/broker.xml` file in your favorite text editor.
29 |
30 | 2. Modify the existing `paging-directory`, `bindings-directory`, `journal-directory`, and `large-messages-directory` elements to point to a shared mount. In the real world, this would likely point to a directory on a SAN that is mounted on both the master and slave machines.
31 |
32 | ```xml
33 | ../sharedstore/data/paging
34 | ../sharedstore/data/bindings
35 | ../sharedstore/data/journal
36 | ../sharedstore/data/large-messages
37 | ```
38 |
39 | 3. Add the following elements anywhere under the `` element:
40 |
41 | ```xml
42 |
43 | tcp://localhost:61616
44 | tcp://localhost:61617
45 |
46 |
47 | admin
48 | admin
49 |
50 |
51 |
52 | master-connector
53 |
54 | slave-connector
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | true
63 |
64 |
65 |
66 | ```
67 |
68 | 4. Start the broker:
69 |
70 | ```
71 | $ ./brokers/node1/bin/artemis run
72 | ```
73 |
74 | __Slave__
75 |
76 | 1. Open up the `brokers/slave/etc/broker.xml` file in your favorite text editor.
77 |
78 | 2. Modify the existing `paging-directory`, `bindings-directory`, `journal-directory`, and `large-messages-directory` elements to point to a shared mount. In the real world, this would likely point to a directory on a SAN that is mounted on both the master and slave machines.
79 |
80 | ```xml
81 | ../sharedstore/data/paging
82 | ../sharedstore/data/bindings
83 | ../sharedstore/data/journal
84 | ../sharedstore/data/large-messages
85 | ```
86 |
87 | 3. Add the following elements anywhere under the `` element:
88 |
89 | ```xml
90 |
91 | tcp://localhost:61616
92 | tcp://localhost:61617
93 |
94 |
95 | admin
96 | admin
97 |
98 |
99 |
100 | slave-connector
101 |
102 | master-connector
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | true
111 | true
112 |
113 |
114 |
115 | ```
116 |
117 | 4. Start the broker:
118 |
119 | ```
120 | $ ./brokers/node2/bin/artemis run
121 | ```
122 |
123 | ## Testing
124 |
125 | 1. Open up a new terminal window and run the following command:
126 |
127 | ```
128 | $ $AMQ_HOME/bin/artemis producer --verbose --user admin --password admin --message-count 100 --url 'tcp://localhost:61616'
129 | ```
130 |
131 | 2. Shut down the master broker (ie, by hitting ctrl-c on its terminal). You should see the slave broker log a few messages indicating that it has come online (this might take a couple of seconds).
132 |
133 | 3. In the same terminal window that you ran the producer command, run the following command:
134 |
135 | ```
136 | $ $AMQ_HOME/bin/artemis consumer --verbose --user admin --password admin --message-count 100 --url 'tcp://localhost:61617'
137 | ```
138 |
139 | All of the messages that you produced to the master broker in step 1 should be consumed from the slave broker.
140 |
141 | 4. (optional) Restart the master broker and you should see that it will take over and the slave will shut down/go back into slave mode (this might take a couple of seconds).
142 |
--------------------------------------------------------------------------------
/labs/50-replication.md:
--------------------------------------------------------------------------------
1 | # AMQ 7 Message Persistence & Replication
2 |
3 | AMQ7 has various message persistence options:
4 |
5 | * NIO (Java NIO, journal-based persistence)
6 | * ASYNCIO (Linux Asynchronous IO, journal-based persistence)
7 | * JDBC (persist to the relational database of your choice)
8 | * Memory (in-memory stateless message persistence)
9 |
10 | The default, out-of-the-box settin is NIO file journal-based persistence. You can configure message persistence by updating the `/jboss-amq-7.0.0.redhat-1/brokers/myfirstbroker/etc/broker.xml` file. Here is the section in `broker.xml`:
11 |
12 | ```
13 |
14 |
15 | ...
16 | true
17 |
18 | NIO
19 | ./data/paging
20 | ./data/bindings
21 | ./data/journal
22 | ./data/large-messages
23 | true
24 | 2
25 | -1
26 | ...
27 |
28 |
29 | ```
30 |
31 | For further details around message persistence, refer to the product documentation [here](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_amq_broker/basic_configuration#configuring_persistence).
32 |
33 | ## Replication
34 |
35 | The following lab demonstrates setting up a 2-node master / slave cluster with shared-nothing replication.
36 |
37 | ### Lab - Shared-nothing replication between Master / Slave cluster
38 |
39 | #### Prerequisites
40 |
41 | Download the legacy ActiveMQ client JAR which supports OpenWire failover [here](https://mvnrepository.com/artifact/org.apache.activemq/activemq-all/5.14.5)
42 |
43 | 1. Create a master and slave broker pair by running the following commands:
44 |
45 | ```
46 | $ ./bin/artemis create brokers/master
47 | $ ./bin/artemis create brokers/slave --port-offset 1
48 | ```
49 |
50 | Be sure to give each broker the `admin/admin` username / password combo and allow anonymous access.
51 |
52 | 2. Replace the etc/broker.xml file from the examples directory for both master and slave:
53 |
54 | ```
55 | cp /jboss-amq-7.0.0.redhat-1/examples/features/clustered/clustered-static-discovery/src/main/resources/activemq/server0/broker.xml /brokers/master/etc/broker.xml
56 | cp /jboss-amq-7.0.0.redhat-1/examples/features/clustered/clustered-static-discovery/src/main/resources/activemq/server1/broker.xml /brokers/slave/etc/broker.xml
57 | ```
58 | 3. Replace the security-settings section of both master / slave broker.xml files with the following text (this will allow the producer / consumer to dynamically create queues):
59 |
60 | ```
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | ```
77 |
78 | 4. Update the cluster-connection section by replacing the message-load-balacing line with the following:
79 |
80 | ```
81 | ON_DEMAND
82 | ```
83 |
84 | This will prevent message starvation and enable message redistribution between nodes, as described [here](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_amq_broker/clustering#enabling_message_redistribution)
85 |
86 | 5. Startup both the master and slave brokers in separate consoles
87 |
88 | ```
89 | ./brokers/master/bin/artemis run
90 | ./brokers/slave/bin/artemis run
91 | ```
92 |
93 | 6. Using the legacy activemq client, run the following commands in two separate console windows:
94 |
95 | ```
96 | java -jar activemq-all-5.11.0.redhat-630187.jar consumer --brokerUrl 'failover:(tcp://localhost:61616,tcp://localhost:61617)' --user admin --password admin --destination queue://TEST
97 |
98 | java -jar activemq-all-5.11.0.redhat-630187.jar producer --sleep 100 --messageCount 1000 --user admin --password admin --brokerUrl 'failover:(tcp://localhost:61616,tcp://localhost:61617)' —destination queue://TEST
99 | ```
100 |
101 | 7. Kill the master broker, and observe failover of both consumer / producer processes to the slave broker
102 |
103 | 8. Startup the original master broker again. Kill the slave broker, and notice failover back to the original master.
104 |
105 |
--------------------------------------------------------------------------------
/labs/60-clustering.md:
--------------------------------------------------------------------------------
1 | # Clustering AMQ7 brokers
2 |
3 | A-MQ 7 has the ability intelligently store & forward messages around a cluster of brokers in order to load-balance and prevent "starvation". In addition to that, however, a clustered setup is required in order to do any type of master/slave (whether shared store, or replicated).
4 |
5 | There are a few different options for configuring a clustered setup:
6 |
7 | * Multicast
8 | * JGroups
9 | * Static
10 |
11 | For the purposes of this lab, we will use the static option. You can refer to the product documentation [here](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_amq_broker/clustering) for more information on the other types.
12 |
13 | ## Prerequisites
14 |
15 | Download and install the A-MQ 7 broker package as described in [Lab 1](00-install-broker.md).
16 |
17 | ## Creating the brokers
18 |
19 | ```
20 | $ $AMQ_HOME/bin/artemis create brokers/node1 --name node1 --user admin --password admin --allow-anonymous
21 | $ $AMQ_HOME/bin/artemis create brokers/node2 --name node2 --user admin --password admin --allow-anonymous --port-offset 1
22 | ```
23 |
24 | _Note: We could have passed in some extra arguments to configure our cluster with some defaults, but instead we're going to manually configure the cluster via the `broker.xml` file so we can become familiar with the available options._
25 |
26 | ## Editing the configuration
27 |
28 | __Node 1__
29 |
30 | 1. Open up the `brokers/node1/etc/broker.xml` file in your favorite text editor.
31 |
32 | 2. Add the following elements anywhere under the `` element:
33 |
34 | ```xml
35 |
36 | tcp://localhost:61616
37 | tcp://localhost:61617
38 |
39 |
40 | admin
41 | admin
42 |
43 |
44 |
45 | node1-connector
46 | ON_DEMAND
47 |
48 | node2-connector
49 |
50 |
51 |
52 | ```
53 |
54 | 3. Add the following elements anywhere under the `` element whose `match` attribute is equal to "#" (meaning it matches all addresses):
55 |
56 | ```xml
57 | 0
58 | ```
59 |
60 | 4. Start the broker:
61 |
62 | ```
63 | $ ./brokers/node1/bin/artemis run
64 | ```
65 |
66 | __Node 2__
67 |
68 | 1. Open up the `brokers/node2/etc/broker.xml` file in your favorite text editor.
69 |
70 | 2. Add the following elements anywhere under the `` element:
71 |
72 | ```xml
73 |
74 | tcp://localhost:61616
75 | tcp://localhost:61617
76 |
77 |
78 | admin
79 | admin
80 |
81 |
82 |
83 | node2-connector
84 | ON_DEMAND
85 |
86 | node1-connector
87 |
88 |
89 |
90 | ```
91 |
92 | 3. Add the following elements anywhere under the `` element whose `match` attribute is equal to "#" (meaning it matches all addresses):
93 |
94 | ```xml
95 | 0
96 | ```
97 |
98 | 4. Start the broker:
99 |
100 | ```
101 | $ ./brokers/node2/bin/artemis run
102 | ```
103 |
104 | ## Testing
105 |
106 | Open up two terminal windows and run the following commands:
107 |
108 | __Terminal 1__
109 |
110 | ```
111 | $ $AMQ_HOME/bin/artemis producer --verbose --user admin --password admin --sleep 1000 --message-count 100 --url 'tcp://localhost:61616'
112 | ```
113 |
114 | __Terminal 2__
115 |
116 | ```
117 | $ $AMQ_HOME/bin/artemis consumer --verbose --user admin --password admin --message-count 100 --url 'tcp://localhost:61617'
118 | ```
119 |
120 | You should see that the messages are produced to node1, but consumed from node2.
121 |
--------------------------------------------------------------------------------
/labs/70-admin.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/70-admin.md
--------------------------------------------------------------------------------
/labs/75-security.md:
--------------------------------------------------------------------------------
1 | # AMQ 7 Security
2 |
3 | One of the key differences with AMQ 7 is the addition of new permissions. AMQ 6 only had 3 permissions:
4 |
5 | 1. read
6 | 2. write
7 | 3. admin
8 |
9 | which are described in more detail [here](http://activemq.apache.org/security.html).
10 |
11 | AMQ 7 on the other hand extends to 10 permissions. They are:
12 |
13 | * createAddress
14 | * deleteAddress
15 | * createDurableQueue
16 | * deleteDurableQueue
17 | * createNonDurableQueue
18 | * deleteNonDurableQueue
19 | * send
20 | * consume
21 | * manage
22 | * browse
23 |
24 | With the additional 7 permissions, we have finer grain control over assigning roles to our users. For more information about these new roles and how they map to the legacy AMQ 6 roles, please refer to the AMQ 7 [docs](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_amq_broker/security#ldap_authz).
25 |
26 | ## Security Labs
27 |
28 | ### Permissions / Roles Lab 1
29 |
30 | This lab demonstrates how to setup a read-only user on A-MQ i.e. the user can only consumer from a given queue.
31 |
32 | 1. Create a new broker by executing the following command:
33 |
34 | ```
35 | ./bin/artemis create
36 | ```
37 |
38 | Name the broker "securitybroker" and give it an admin user with the credentials admin/admin.
39 |
40 | 2. `cd` to `brokers/securitybroker/bin`
41 | 3. Execute `./artemis user add --user read-only-user --password Abcd1234 --role read-only` to create a read-only user
42 | 4. `cd` to `brokers/securitybroker/etc` and open the broker.xml file.
43 | 5. Under the security-settings section, add the following text:
44 |
45 | ```
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | ```
60 | Notice we have a specific match for any queue starting with "test.*". Also notice that we have assigned the "read-only" role to ensure that our read-only user can only consume from our test.* queue.
61 |
62 | 5. Save the broker.xml file
63 |
64 | 6. Start up our new broker using the following command: `./brokers/securitybroker/bin/artemis run`
65 |
66 | 7. Try out our new "read only" role / user by typing the following command in a separate command windo:
67 |
68 | ```
69 | java -jar activemq-all-5.11.0.redhat-630187.jar producer --sleep 100 --messageCount 1000 --user read-only-user --password Abcd1234 --brokerUrl 'failover:(tcp://localhost:61616,tcp://localhost:61617)' --destination queue://test.readonly.queue
70 | ```
71 |
72 | Notice that this command fails because our read-only-user cannot create a durable queue. This means our user is working correctly.
73 |
74 | 8. Change the command and execute the following instead to use the admin user, which coincidently has admin permissions to create and write to queues:
75 |
76 | ```
77 | java -jar activemq-all-5.11.0.redhat-630187.jar producer --sleep 100 --messageCount 1000 --user admin --password admin --brokerUrl 'failover:(tcp://localhost:61616,tcp://localhost:61617)' --destination queue://test.readonly.queue
78 | ```
79 |
80 | 9. Now lets try consuming from the test.readonly.queue using the read-only-user credentials:
81 |
82 | ```
83 | java -jar activemq-all-5.11.0.redhat-630187.jar consumer --sleep 100 --messageCount 1000 --user read-only-user --password Abcd1234 --brokerUrl 'failover:(tcp://localhost:61616,tcp://localhost:61617)' --destination queue://test.readonly.queue
84 | ```
85 |
86 | If all goes well, the client should connect and start consuming messages from our queue.
87 |
88 | 10. For the sake of testing, try the same to write messages to the queue. Again, this should fail but with a different permission error:
89 |
90 | ```
91 | java -jar activemq-all-5.11.0.redhat-630187.jar producer --sleep 100 --messageCount 1000 --user read-only-user --password Abcd1234 --brokerUrl 'failover:(tcp://localhost:61616,tcp://localhost:61617)' --destination queue://test.readonly.queue
92 | ```
93 | ### SSL
94 |
95 | This lab demonstrates generating keys and truststores to use for SSL with the broker.
96 |
97 | 1. Ensure openssl is installed
98 |
99 | ```
100 | sudo yum install openssl
101 | ```
102 |
103 | 2. Use openssl to generate the pem and p12 files. Other file formats can be used by the pem and p12 are compatiable for usage with both the Artemis brokers and then Interconnect Routers
104 |
105 | ```
106 | openssl req -newkey rsa:2048 -nodes -keyout keyout.pem -x509 -days 65000 -out certificate.pem
107 | openssl x509 -text -noout -in certificate.pem
108 | openssl pkcs12 -inkey keyout.pem -in certificate.pem -export -out certificate.p12
109 | openssl pkcs12 -in certificate.p12 -noout -info
110 | ```
111 | Notice this results in the following files
112 | ```
113 | keyout.pem
114 | certificate.pem
115 | certificate.p12
116 | ```
117 |
118 | 3. Configure SSL usage on the connectors and acceptors in the broker.xml
119 |
120 | ```
121 |
122 | tcp://localhost:61616?sslEnabled=true;keyStorePath=certificate.p12;keyStorePassword=password;enabledProtocols=TLSv1,TLSv1.1,TLSv1.2;trustStorePath=certificate.p12;
123 | trustStorePassword=password
124 |
125 |
126 | tcp://localhost:61616?sslEnabled=true;keyStorePath=certificate.p12;keyStorePassword=password;enabledProtocols=TLSv1,TLSv1.1,TLSv1.2;trustStorePath=certificate.p12;
127 | trustStorePassword=password
128 |
129 | ```
130 |
131 | 4. If you have multiple brokers configure those as well to ensure any clustering between the brokers will be able to communicate.
132 |
133 | 5. Start up the brokers, notice that the Cluster Bridge connections should still occur, but this time over SSL
134 |
135 | 6. Configure your client to use ssl, using a URL similar to the following
136 |
137 | ```
138 | amqps://localhost:5672?transport.verifyHost=false&transport.storeType=PKCS12&transport.trustStoreLocation=/home/example/broker-secure/certificate.p12&transport.trustStorePassword=password
139 | ```
140 |
141 | 7. Start up your client and see it connect with SSL and consume or produce
142 |
--------------------------------------------------------------------------------
/labs/80-install-qdr.md:
--------------------------------------------------------------------------------
1 | # Installing and Configuring AMQ7 Interconnect Router
2 |
3 | The AMQ7 Interconnect Router components are written in native code (C++) and are supported on RHEL. In this lab, we'll take a look at two ways to bootstrap Interconnect Router for the purposes of demonstrating routing and broker to router connectivity. If you're looking to do an installation of Interconnect Router on your machines (ie, not just for following this lab), then the official documentation is quite good. [Check it out at access.redhat.com](https://access.redhat.com/documentation/en-us/red_hat_jboss_amq/7.0/html/using_amq_interconnect/installation) for doing a proper installation.
4 |
5 |
6 | ### Option 1 Install into a fresh copy of RHEL 7
7 |
8 | Option one requires you to have a RHEL host already provisioned. Either you can use one you already have, or for the purposes of this lab you can install a developer copy. If you go to [http://developers.redhat.com](http://developers.redhat.com), you'll notice lots of helpful tools for developers including e-books, cheatsheets, and community software. Go to the [Red Hat Enterprise Linux](https://developers.redhat.com/products/rhel/overview/) landing page and click "Download" to get yourself a free, developers edition of RHEL. From there you can install it as a *.iso (ie, so you can import it into virtualbox or something)
9 |
10 | If you're using the developers.redhat.com developer's copy of RHEL, you should automatically have a subscription to the right repos/channels to download and install Interconnect Router.
11 |
12 | You should be able to:
13 |
14 | ```bash
15 | sudo yum install qpid-proton-c python-qpid-proton
16 | sudo yum install qpid-dispatch-router qpid-dispatch-tools
17 | ```
18 |
19 | If you've got your own RHEL 7 instance or you cannot install based on the above commands, we'll try to manually install. The binaries can be given out during in-person workshops.
20 |
21 | Once you've got RHEL set up, you can then install the Interconnect Router. First [Download a RHEL7 build of the Interconnect Router]() onto your RHEL machine (again, these binaries would be given out in person)
22 |
23 |
24 | Known to work on base RHEL7.x/Centos7.x distros:
25 |
26 | ```bash
27 | # Enable EPEL
28 | sudo rpm -i https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
29 |
30 | # Yum update
31 | sudo yum -y update
32 |
33 | # Install preprequisites
34 | sudo yum -y install qpid-proton-c-devel python-qpid-proton
35 |
36 | # Install Official release of router
37 | sudo rpm -Uvh libwebsockets-2.1.0-3.el7.x86_64.rpm
38 | sudo rpm -Uvh qpid-dispatch-router-0.8.0-9.el7.x86_64.rpm
39 | ```
40 |
41 | ### Option 2 Using Docker
42 |
43 | With option 2, you can choose to use Docker and grab docker images. Note you'll need some kind of Linux machine (or VM) if your Host machine isn't Linux. This could be Docker for Mac/Windows, Minikube, or the Red Hat CDK 3.0. In any event, setting up Linux for Docker usage is beyond the scope of this installation documentation. Also, when doing any kind of port forwarding between the docker guest VM and your local workstation host, it's up to you to figure out how to open up the ports if you're trying to communicate locally with it.
44 |
45 | To get the docker image that contains the AMQ7 Interconnect Router:
46 |
47 | ```bash
48 | docker pull ceposta/qdr:latest
49 | ```
50 |
51 | You can run the image like this:
52 |
53 | ```bash
54 | docker run -itd --name qdr ceposta/qdr:latest
55 | ```
56 |
57 | In the next labs, we'll see how to attach configuration to the router. Default configuration is in `/etc/qpid-dispatch/qdrouterd.conf`
58 |
59 |
--------------------------------------------------------------------------------
/labs/90-broker-to-router.md:
--------------------------------------------------------------------------------
1 | # Connecting the Interconnect Router to an AMQ7 Broker
2 |
3 | In this lab we'll take a look at configuring the Interconnect Router to route messages to and from an AMQ7 broker. Clients can talk directly to the router and think they're talking to a broker.
4 |
5 | In this lab, we'll use the Docker images from the [installing interconnect router](./80-install-qdr.md) lab. You can use the same configuration files that we'll use here in your full version of RHEL/CentOS if you've installed Interconnect Router there. The broker we'll use comes from the earlier labs; it will be running locally on your laptop. Remember, you'll need to configure port forwarding between your docker guest VM and your developer host machine.
6 |
7 | First thing we'll do is look at and modify the configuration where needed. If you look in the lab files [for the Interconnect Router configurations](./qdr/conf), you'll see a configuration file named `router-to-broker.conf` that looks like this:
8 |
9 |
10 | ```xml
11 | router {
12 | mode: standalone
13 | id: routerToBroker
14 | workerThreads: 4
15 | }
16 |
17 | listener {
18 | role: normal
19 | host: 0.0.0.0
20 | port: 5672
21 | linkCapacity: 1000
22 | }
23 |
24 | log {
25 | module: DEFAULT
26 | enable: trace+
27 | timestamp: true
28 | }
29 |
30 | address {
31 | prefix: foo
32 | waypoint: yes
33 | }
34 |
35 | autoLink {
36 | addr: foo
37 | dir: in
38 | connection: myfirstbrokerConnector
39 | }
40 |
41 | autoLink {
42 | addr: foo
43 | dir: out
44 | connection: myfirstbrokerConnector
45 | }
46 |
47 | connector {
48 | host: 10.0.1.35
49 | name: myfirstbrokerConnector
50 | port: 61616
51 | role: route-container
52 | allowRedirect: no
53 | }
54 |
55 |
56 | ```
57 |
58 | In this configuration, we're setting up a `listener` which listens for incoming connections to the router; for example, an AMQP client could connect directly to this listener (in this case, we're listening on port `5672` which is the default AMQP port). Also locate the `connector` section of the configuration. This describes how we'll connect to the AMQ7 broker. You'll want to change the host/port config to match that of your broker. For example, if you're running the broker on your local machine and the router in a docker container locally on a guest OS, you'd want to use your host IP for the broker's `connector.host` field.
59 |
60 | Let's make sure our broker from Lab 1, `myfirstbroker` is up and running:
61 |
62 | ```bash
63 | __ __ ____ ____ _
64 | /\ | \/ |/ __ \ | _ \ | |
65 | / \ | \ / | | | | | |_) |_ __ ___ | | _____ _ __
66 | / /\ \ | |\/| | | | | | _ <| '__/ _ \| |/ / _ \ '__|
67 | / ____ \| | | | |__| | | |_) | | | (_) | < __/ |
68 | /_/ \_\_| |_|\___\_\ |____/|_| \___/|_|\_\___|_|
69 |
70 | Red Hat JBoss AMQ 7.0.0.redhat-1
71 |
72 |
73 | 09:42:46,451 INFO [org.apache.activemq.artemis.integration.bootstrap] AMQ101000: Starting ActiveMQ Artemis Server
74 | 09:42:46,467 INFO [org.apache.activemq.artemis.core.server] AMQ221000: live Message Broker is starting with configuration Broker Configuration (clustered=false,journalDirectory=./data/journal,bindingsDirectory=./data/bindings,largeMessagesDirectory=./data/large-messages,pagingDirectory=./data/paging)
75 | 09:42:46,512 INFO [org.apache.activemq.artemis.core.server] AMQ221013: Using NIO Journal
76 | 09:42:46,611 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-server]. Adding protocol support for: CORE
77 | 09:42:46,612 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-amqp-protocol]. Adding protocol support for: AMQP
78 | 09:42:46,612 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-hornetq-protocol]. Adding protocol support for: HORNETQ
79 | 09:42:46,612 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-mqtt-protocol]. Adding protocol support for: MQTT
80 | 09:42:46,613 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-openwire-protocol]. Adding protocol support for: OPENWIRE
81 | 09:42:46,613 INFO [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-stomp-protocol]. Adding protocol support for: STOMP
82 | 09:42:46,658 INFO [org.apache.activemq.artemis.core.server] AMQ221034: Waiting indefinitely to obtain live lock
83 | 09:42:46,658 INFO [org.apache.activemq.artemis.core.server] AMQ221035: Live Server Obtained live lock
84 | 09:42:47,152 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue exampleQueue
85 | 09:42:47,153 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue foo
86 | 09:42:47,153 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue DLQ
87 | 09:42:47,154 INFO [org.apache.activemq.artemis.core.server] AMQ221003: Deploying queue ExpiryQueue
88 | 09:42:47,858 INFO [org.apache.activemq.artemis.core.server] AMQ221020: Started NIO Acceptor at 0.0.0.0:61616 for protocols [CORE,MQTT,AMQP,STOMP,HORNETQ,OPENWIRE]
89 | 09:42:47,860 INFO [org.apache.activemq.artemis.core.server] AMQ221007: Server is now live
90 | 09:42:47,860 INFO [org.apache.activemq.artemis.core.server] AMQ221001: Apache ActiveMQ Artemis Message Broker version 2.0.0.amq-700005-redhat-1 [0.0.0.0, nodeID=ae7bf278-35c4-11e7-97d9-0a0027000001]
91 | INFO | main | Initialized artemis-plugin plugin
92 | INFO | main | Initialized dispatch-hawtio-console plugin
93 | 09:42:50,441 INFO [org.apache.activemq.artemis] AMQ241001: HTTP Server started at http://localhost:8161
94 | 09:42:50,441 INFO [org.apache.activemq.artemis] AMQ241002: Artemis Jolokia REST API available at http://localhost:8161/jolokia
95 | ```
96 |
97 | Now let's try running the Interconnect Router with the above configuration (ie, change the `connector` host IP and port to match your settings):
98 |
99 | ```bash
100 | docker run -it --rm --name qdr -p 5672:5672 -v $(pwd)/qdr/conf/router-to-broker.conf:/etc/qpid-dispatch/qdrouterd.conf ceposta/qdr
101 | ```
102 |
103 | Note how we map the configuration file into the docker container. When we run this, we should see output from the Interconnect Router similar to this:
104 |
105 | ```bash
106 | Thu May 25 09:46:19 2017 SERVER (trace) Connecting to 10.0.1.35:61616
107 | Thu May 25 09:46:19 2017 SERVER (trace) [1]: -> SASL
108 | Thu May 25 09:46:19 2017 SERVER (trace) [1]: <- SASL
109 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:0 <- @sasl-mechanisms(64) [sasl-server-mechanisms=@PN_SYMBOL[:PLAIN, :ANONYMOUS]]
110 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:0 -> @sasl-init(65) [mechanism=:ANONYMOUS, initial-response=b"anonymous@0993bdacc124"]
111 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:0 <- @sasl-outcome(68) [code=0]
112 | Thu May 25 09:46:19 2017 SERVER (trace) [1]: <- AMQP
113 | Thu May 25 09:46:19 2017 SERVER (trace) [1]: -> AMQP
114 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:0 -> @open(16) [container-id="routerToBroker", hostname="10.0.1.35", max-frame-size=16384, channel-max=32767, idle-time-out=8000, offered-capabilities=:"ANONYMOUS-RELAY", properties={:product="qpid-dispatch-router", :version="0.8.0"}]
115 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:0 <- @open(16) [container-id="0.0.0.0", max-frame-size=4294967295, channel-max=65535, idle-time-out=30000, offered-capabilities=@PN_SYMBOL[:"sole-connection-for-container", :"DELAYED_DELIVERY", :"SHARED-SUBS", :"ANONYMOUS-RELAY"], properties={:product="apache-activemq-artemis", :version="2.0.0.amq-700005-redhat-1"}]
116 | Thu May 25 09:46:19 2017 ROUTER_CORE (trace) Core action 'connection_opened'
117 | Thu May 25 09:46:19 2017 ROUTER_CORE (info) Auto Link Activated 'autoLink/0' on connection myfirstbrokerConnector
118 | Thu May 25 09:46:19 2017 ROUTER_CORE (info) Auto Link Activated 'autoLink/1' on connection myfirstbrokerConnector
119 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:0 -> @begin(17) [next-outgoing-id=0, incoming-window=2147483647, outgoing-window=2147483647]
120 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:1 -> @begin(17) [next-outgoing-id=0, incoming-window=2147483647, outgoing-window=2147483647]
121 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:0 -> @attach(18) [name="qdlink.nxYIQdO8Jvut7LX", handle=0, role=true, snd-settle-mode=2, rcv-settle-mode=0, source=@source(40) [address="foo", durable=0, expiry-policy=:"link-detach", timeout=0, dynamic=false], target=@target(41) [durable=0, timeout=0, dynamic=false], initial-delivery-count=0, max-message-size=0]
122 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:1 -> @attach(18) [name="qdlink.NqqnFJ7_SOW_EWu", handle=0, role=false, snd-settle-mode=2, rcv-settle-mode=0, source=@source(40) [durable=0, timeout=0, dynamic=false], target=@target(41) [address="foo", durable=0, expiry-policy=:"link-detach", timeout=0, dynamic=false], initial-delivery-count=0, max-message-size=0]
123 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:0 <- @begin(17) [remote-channel=0, next-outgoing-id=1, incoming-window=2147483647, outgoing-window=2147483647, handle-max=65535]
124 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:1 <- @begin(17) [remote-channel=1, next-outgoing-id=1, incoming-window=2147483647, outgoing-window=2147483647, handle-max=65535]
125 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:0 <- @attach(18) [name="qdlink.nxYIQdO8Jvut7LX", handle=0, role=false, snd-settle-mode=2, rcv-settle-mode=0, source=@source(40) [address="foo", durable=0, expiry-policy=:"link-detach"], target=@target(41) [], incomplete-unsettled=false, initial-delivery-count=0]
126 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:1 <- @attach(18) [name="qdlink.NqqnFJ7_SOW_EWu", handle=0, role=true, snd-settle-mode=2, rcv-settle-mode=0, source=@source(40) [], target=@target(41) [address="foo", durable=0, expiry-policy=:"link-detach"]]
127 | Thu May 25 09:46:19 2017 SERVER (trace) [1]:1 <- @flow(19) [next-incoming-id=0, incoming-window=2147483647, next-outgoing-id=1, outgoing-window=2147483647, handle=0, delivery-count=0, link-credit=1000]
128 | Thu May 25 09:46:19 2017 ROUTER_CORE (trace) Core action 'link_second_attach'
129 | Thu May 25 09:46:19 2017 ROUTER_CORE (trace) Core action 'link_second_attach'
130 | Thu May 25 09:46:19 2017 ROUTER_CORE (trace) Core action 'link_flow'
131 | ```
132 |
133 | Fire up the web console for the broker at [http://localhost:8161/hawtio](http://localhost:8161/hawtio) and try to find the `address.hellowrold` destination.
134 |
135 | 
136 |
137 | As we send messages in to the router, you should watch the `foo` queue and see its message count increase.
138 |
139 | ### Sending messages into the Router
140 |
141 | To send messages into the router, we'll go [back to the JMS AMQP client in the Clients Lab](./20-clients.md) and configure it to send messages to the `5672` port (which is the default AMQP port:
142 |
143 | Our `jndi.properties` file should look like this, with the `connectionfactory.myFactoryLookup` property set to `5672`
144 |
145 | ```
146 | # Set the InitialContextFactory class to use
147 | java.naming.factory.initial = org.apache.qpid.jms.jndi.JmsInitialContextFactory
148 |
149 | # Define the required ConnectionFactory instances
150 | # connectionfactory. =
151 | connectionfactory.myFactoryLookup = amqp://localhost:5672
152 |
153 | # Configure the necessary Queue and Topic objects
154 | # queue. =
155 | # topic. =
156 | queue.myQueueLookup = queue
157 | topic.myTopicLookup = topic
158 | ```
159 |
160 | The last thing we need to do is port-forward the guest OS to our host OS. If you recall, when we started the docker container for our router, we passed in the `-p 5672:5672` flag which exposes the `5672` port on the docker container to the host. Except, since the docker daemon is running in our guest VM, it cannot be seen on the host.
161 |
162 | If using minikube, do this achieve the port forwarding:
163 |
164 | ```bash
165 | minikube ssh -- -vnNTL *:5672:$(minikube ip):5672
166 | ```
167 |
168 | Now run your JMS client:
169 |
170 | ```bash
171 | java -cp "target/classes/:target/dependency/*" org.apache.qpid.jms.example.HelloWorld
172 | Hello world!
173 | ```
174 |
175 | If we see the `Hello world!` response, it means our message went to the router, into the broker, and back out that way to the JMS consumer as we expected!
--------------------------------------------------------------------------------
/labs/README.md:
--------------------------------------------------------------------------------
1 | # Red Hat JBoss AMQ 7 Labs
2 |
3 | These set of labs will help a new user learn how to install, configure and use JBoss AMQ 7. We'll cover topics like clustering, high availability, persistence, and the new Interconnect Router.
4 |
5 | ## Prerequisites
6 |
7 | To get started with these labs, you'll want to install (and have correctly configured) the following prerequisites:
8 |
9 | * JDK 8 ([OpenJDK](http://openjdk.java.net/install/) or [OracleJDK](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html))
10 | * [Apache Maven 3.3+](https://maven.apache.org/download.cgi)
11 | * Zip/Unzip utility
12 | * [Git Command Line](https://git-scm.com/downloads)
13 |
14 | ## Contributing to the labs
15 |
16 | We are always happy to accept contributions in the form of correcting errors, adding new labs, making certain points more clear, etc. Please open [Issues](https://github.com/RedHatWorkshops/amqv7-workshop/issues) on this GitHub repo identifying what things you'd like to contribute and then send [Pull Requests](https://github.com/RedHatWorkshops/amqv7-workshop/pulls)!
17 |
18 | The Lab guides are written in [Markdown](https://daringfireball.net/projects/markdown/syntax) and are organized/compiled with [Gitbook](https://www.gitbook.com). When you make changes, please also take the time to build/compile/preview the changes using gitbook. See below for instructions on how to build the source.
19 |
20 | ## Building the Gitbook
21 | We are using Gitbook to organize and build the lab guide. We highly recommend you [install the gitbook-cli](https://github.com/GitbookIO/gitbook-cli) tools to help you build and preview the labs in Gitbook format. If you have the `gitbook-cli` tools installed, you can navigate to this folder (ie, `amqv7-workshop/labs`) and run the following commands:
22 |
23 |
24 | $ gitbook install
25 | $ gitbook build .
26 |
27 | Then if you look in the `_book` folder, you should see the HTML files generated for this book. Open the `index.html` file from that folder to have your book.
28 |
29 | You can also set up live preview of the book by running this command:
30 |
31 | $ gitbook serve
32 |
33 | Then you should see something similar to this:
34 |
35 | ```
36 | info: loading book configuration....OK
37 | info: load plugin gitbook-plugin-anchors ....OK
38 | info: load plugin gitbook-plugin-highlight ....OK
39 | info: load plugin gitbook-plugin-search ....OK
40 | info: load plugin gitbook-plugin-sharing ....OK
41 | info: load plugin gitbook-plugin-fontsettings ....OK
42 | info: load plugin gitbook-plugin-livereload ....OK
43 | info: >> 6 plugins loaded
44 | info: start generation with website generator
45 | info: clean website generator
46 | info: OK
47 | info: generation is finished
48 |
49 | Starting server ...
50 | Serving book on http://localhost:4000
51 | ```
52 |
53 | Now navigate to [http://localhost:4000](http://localhost:4000) to see the live-updating Gitbook. If you make changes to the source they'll automatically be built and updated in the web page.
54 |
55 |
56 | Lastly, to build the Gitbook as a PDF file, run the following command (from the `./labs` folder):
57 |
58 | $ gitbook pdf .
59 |
60 | You should see a file named `book.pdf` in the `./labs` folder.
61 |
62 |
63 | ## Updating the https://redhatworkshops.github.io/ labs website
64 |
65 | To do this, first build the gitbook HTML source, then push to the `gh-pages` branch:
66 |
67 | rm -fr _book
68 | gitbook build .
69 | cd _book
70 | git init
71 | git commit --allow-empty -m 'initial commit'
72 | git checkout -b gh-pages
73 | git add .
74 | git commit -am 'updated docs'
75 | git push --force https://github.com/RedHatWorkshops/amqv7-workshop.git gh-pages
76 |
77 | All of this can be found in the `publish-labs.sh` script.
78 |
--------------------------------------------------------------------------------
/labs/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Table of contents
2 |
3 | * [Installing the AMQ7 Broker](00-install-broker.md)
4 | * [Configuring AMQ 7](10-configure-broker.md)
5 | * [AMQ 7 Clients](20-clients.md)
6 | * [Producing and Consuming](30-produce-consume.md)
7 | * [Persistence / Master-Slave](40-master-slave.md)
8 | * [Persistence / Replication](50-replication.md)
9 | * [Simple Clustering](60-clustering.md)
10 | * [Administration](70-admin.md)
11 | * [Security](75-security.md)
12 | * [Installing Interconnect Router](80-install-qdr.md)
13 | * [Connect router to broker](90-broker-to-router.md)
14 | * [Brokerless routing](100-brokerless.md)
15 |
--------------------------------------------------------------------------------
/labs/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "JBoss AMQ 7 Labs",
3 | "description": "A series of labs intended to go along with the AMQ 7 workshop to help users understand JBoss AMQ 7",
4 | "extension": "pdf",
5 | "github": "RedHatWorkshops/amqv7-workshop",
6 | "githubHost": "https://github.com/",
7 | "gitbook": ">=2.0.0",
8 |
9 | "links": {
10 | "home": "https://github.com/RedHatWorkshops/amqv7-workshop",
11 | "issues": "https://github.com/RedHatWorkshops/amqv7-workshopissues?milestone=none&state=closed"
12 | },
13 | "plugins": [
14 | "anchors"
15 | ],
16 |
17 | "pdf": {
18 | "toc": true,
19 | "fontSize": 12,
20 | "paperSize": "a4",
21 | "margin": {
22 | "right": 62,
23 | "left": 62,
24 | "top": 36,
25 | "bottom": 36
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/labs/images/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/images/.gitkeep
--------------------------------------------------------------------------------
/labs/images/broker-to-router/helloworldaddress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/images/broker-to-router/helloworldaddress.png
--------------------------------------------------------------------------------
/labs/images/client/download-jms-client.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/images/client/download-jms-client.png
--------------------------------------------------------------------------------
/labs/images/client/download-node-client.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/images/client/download-node-client.png
--------------------------------------------------------------------------------
/labs/images/configuration/startup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/images/configuration/startup.png
--------------------------------------------------------------------------------
/labs/images/install/downloadbroker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/images/install/downloadbroker.png
--------------------------------------------------------------------------------
/labs/images/produce-consume/consume-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/images/produce-consume/consume-50.png
--------------------------------------------------------------------------------
/labs/images/produce-consume/consumer-drain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/images/produce-consume/consumer-drain.png
--------------------------------------------------------------------------------
/labs/images/produce-consume/dlq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/images/produce-consume/dlq.png
--------------------------------------------------------------------------------
/labs/images/produce-consume/producer-message-count.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/labs/images/produce-consume/producer-message-count.png
--------------------------------------------------------------------------------
/labs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "AMQ7 Labs",
3 | "version": "1.0.0",
4 | "scripts": {
5 | "docs:prepare": "gitbook install",
6 | "docs:watch": "npm run docs:prepare && gitbook serve"
7 | }
8 | }
--------------------------------------------------------------------------------
/labs/publish-labs.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | rm -fr _book
3 | gitbook build .
4 | cd _book
5 | git init
6 | git commit --allow-empty -m 'initial commit'
7 | git checkout -b gh-pages
8 | git add .
9 | git commit -am 'updated docs'
10 | git push --force https://github.com/RedHatWorkshops/amqv7-workshop.git gh-pages
11 |
--------------------------------------------------------------------------------
/labs/qdr/brokerless/receiver_router3.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | docker run -e QPID_LOG_ENABLE=trace+ --link router3:router3 -t -i scholzj/qpid-cpp:latest qpid-receive -b router3:5672 --connection-options "{protocol: amqp1.0}" -a "'/myAddress'" -m 1 -f --print-headers yes
--------------------------------------------------------------------------------
/labs/qdr/brokerless/router1.conf:
--------------------------------------------------------------------------------
1 | router {
2 | mode: interior
3 | id: Router1
4 | workerThreads: 4
5 | }
6 |
7 | listener {
8 | role: normal
9 | host: 0.0.0.0
10 | port: 5672
11 | linkCapacity: 1000
12 | }
13 |
14 | listener {
15 | role: inter-router
16 | host: 0.0.0.0
17 | port: 10001
18 | }
19 |
20 | listener {
21 | role: normal
22 | host: 0.0.0.0
23 | port: 2009
24 | linkCapacity: 1000
25 | }
26 |
27 | log {
28 | module: DEFAULT
29 | enable: trace+
30 | timestamp: true
31 | }
32 |
33 | connector {
34 | role: inter-router
35 | host: router2
36 | port: 10002
37 | saslMechanisms: ANONYMOUS
38 | }
39 |
40 | connector {
41 | role: inter-router
42 | host: router3
43 | port: 10003
44 | saslMechanisms: ANONYMOUS
45 | }
46 |
47 | address {
48 | prefix: /myAddress
49 | distribution: closest
50 | }
51 |
--------------------------------------------------------------------------------
/labs/qdr/brokerless/router2.conf:
--------------------------------------------------------------------------------
1 | router {
2 | mode: interior
3 | id: Router2
4 | workerThreads: 4
5 | }
6 |
7 | listener {
8 | role: inter-router
9 | host: 0.0.0.0
10 | port: 10002
11 | }
12 |
13 | log {
14 | module: DEFAULT
15 | enable: trace+
16 | timestamp: true
17 | }
18 |
19 | connector {
20 | role: inter-router
21 | host: router3
22 | port: 10003
23 | saslMechanisms: ANONYMOUS
24 | }
25 |
26 | address {
27 | prefix: /myAddress
28 | distribution: closest
29 | }
30 |
--------------------------------------------------------------------------------
/labs/qdr/brokerless/router3.conf:
--------------------------------------------------------------------------------
1 | router {
2 | mode: interior
3 | id: Router3
4 | workerThreads: 4
5 | }
6 |
7 | listener {
8 | role: normal
9 | host: 0.0.0.0
10 | port: 5672
11 | linkCapacity: 1000
12 | }
13 |
14 | listener {
15 | role: inter-router
16 | host: 0.0.0.0
17 | port: 10003
18 | }
19 |
20 | log {
21 | module: DEFAULT
22 | enable: trace+
23 | timestamp: true
24 | }
25 |
26 | address {
27 | prefix: /myAddress
28 | distribution: closest
29 | }
30 |
--------------------------------------------------------------------------------
/labs/qdr/brokerless/sender_router1.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | docker run -e QPID_LOG_ENABLE=trace+ --link router1:router1 -t -i scholzj/qpid-cpp:latest qpid-send -b router1:5672 --connection-options "{protocol: amqp1.0}" -a "'/myAddress'" -m 1
--------------------------------------------------------------------------------
/labs/qdr/brokerless/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 |
4 | docker run -itd --name router3 -v $(pwd)/router3.conf:/etc/qpid-dispatch/qdrouterd.conf ceposta/qdr
5 | docker run -itd --name router2 --link router3 -v $(pwd)/router2.conf:/etc/qpid-dispatch/qdrouterd.conf ceposta/qdr
6 | docker run -itd --name router1 --link router3 --link router2 -v $(pwd)/router1.conf:/etc/qpid-dispatch/qdrouterd.conf ceposta/qdr
--------------------------------------------------------------------------------
/labs/qdr/brokerless/stop.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 |
4 | docker rm -f router1 router2 router3
--------------------------------------------------------------------------------
/labs/qdr/conf/router-to-broker.conf:
--------------------------------------------------------------------------------
1 | router {
2 | mode: standalone
3 | id: routerToBroker
4 | workerThreads: 4
5 | }
6 |
7 | listener {
8 | role: normal
9 | host: 0.0.0.0
10 | port: 5672
11 | linkCapacity: 1000
12 | }
13 |
14 | log {
15 | module: DEFAULT
16 | enable: trace+
17 | timestamp: true
18 | }
19 |
20 | address {
21 | prefix: foo
22 | waypoint: yes
23 | }
24 |
25 | autoLink {
26 | addr: foo
27 | dir: in
28 | connection: myfirstbrokerConnector
29 | }
30 |
31 | autoLink {
32 | addr: foo
33 | dir: out
34 | connection: myfirstbrokerConnector
35 | }
36 |
37 | connector {
38 | host: 10.0.1.35
39 | name: myfirstbrokerConnector
40 | port: 61616
41 | role: route-container
42 | allowRedirect: no
43 | }
44 |
--------------------------------------------------------------------------------
/slides/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/slides/.gitkeep
--------------------------------------------------------------------------------
/slides/AMQ-Deepdive-Slides.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/slides/AMQ-Deepdive-Slides.pptx
--------------------------------------------------------------------------------
/slides/IntroducingJBossAMQ7.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedHatWorkshops/amqv7-workshop/2d2fbc52d3f5d47387b02257ccb3b7085aa4e9f5/slides/IntroducingJBossAMQ7.pptx
--------------------------------------------------------------------------------
/usecases/banking-service/README.md:
--------------------------------------------------------------------------------
1 | # JBoss A-MQ 7 Banking Service Usecase
2 |
--------------------------------------------------------------------------------
/usecases/call-center/README.md:
--------------------------------------------------------------------------------
1 | # JBoss A-MQ 7 Call Center Service Usecase
2 |
--------------------------------------------------------------------------------
/usecases/healthcare-institution/README.md:
--------------------------------------------------------------------------------
1 | # JBoss A-MQ 7 Healthcare Institution Usecase
2 |
--------------------------------------------------------------------------------
/usecases/online-retail/README.md:
--------------------------------------------------------------------------------
1 | # JBoss A-MQ 7 Online Retail Service Usecase
2 |
--------------------------------------------------------------------------------
/usecases/telecom-service-provider/README.md:
--------------------------------------------------------------------------------
1 | # JBoss A-MQ 7 Telecom Service Provider Usecase
2 |
--------------------------------------------------------------------------------
/usecases/transportation-ticket-service/README.md:
--------------------------------------------------------------------------------
1 | # JBoss A-MQ 7 Transportation Ticket Service Usecase
2 |
--------------------------------------------------------------------------------