-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added ZmqTemplate and other enhancements
- Loading branch information
Showing
12 changed files
with
219 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Release Notes | ||
|
||
## 0.0.1 | ||
|
||
* Initial release | ||
|
||
## 0.0.2 | ||
|
||
* Added `headers` parameter to `MessageConverter.toMessage()` | ||
* Added `SimpleMessageConverter` class supporting `String` and `ByteArray` | ||
* Added `ZmqTemplate` class with basic `send()` operations | ||
* Deprecated `ChannelFactory` which is superceded by `ZmqTemplate` | ||
* `Channel` now implements `Closeable` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
src/main/kotlin/io/insource/framework/zeromq/SimpleMessageConverter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package io.insource.framework.zeromq | ||
|
||
import org.springframework.stereotype.Component | ||
import org.zeromq.api.Message | ||
|
||
/** | ||
* Simple message converter that simply checks the type of the provided object | ||
* for conversion to a message using the `toMessage()` method, and relies on the | ||
* the first frame containg headers with a `content-type` header to determine | ||
* the behavior of the `fromMessage()` method. | ||
*/ | ||
@Component | ||
class SimpleMessageConverter : MessageConverter { | ||
override fun toMessage(obj: Any, headers: Map<String, String>): Message { | ||
val contentType: String | ||
val payloadFrame = when (obj) { | ||
is ByteArray -> { | ||
contentType = APPLICATION_OCTET_STREAM | ||
Message.Frame.of(obj) | ||
} | ||
is String -> { | ||
contentType = TEXT_PLAIN | ||
Message.Frame.of(obj) | ||
} | ||
else -> throw IllegalArgumentException("${this.javaClass.simpleName} only supports ByteArray or String types in the payload, received ${obj.javaClass.simpleName}") | ||
} | ||
|
||
val updatedHeaders = HashMap(headers) | ||
updatedHeaders["content-type"] = contentType | ||
updatedHeaders["content-length"] = payloadFrame.size().toString() | ||
|
||
return Message() | ||
.addFrame(Message.Frame.of(updatedHeaders)) | ||
.addFrame(payloadFrame) | ||
} | ||
|
||
override fun fromMessage(message: Message): Any { | ||
val headers = message.popMap() | ||
return when (val contentType = headers["content-type"] ?: APPLICATION_OCTET_STREAM) { | ||
TEXT, | ||
TEXT_PLAIN, | ||
APPLICATION_JSON, | ||
APPLICATION_XML -> return message.popString() | ||
APPLICATION_OCTET_STREAM -> message.popBytes() | ||
else -> throw IllegalArgumentException("Unsupported content-type - $contentType") | ||
} | ||
} | ||
|
||
companion object { | ||
private val TEXT = "text" | ||
private val TEXT_PLAIN = "text/plain" | ||
private val APPLICATION_JSON = "application/json" | ||
private val APPLICATION_XML = "application/xml" | ||
private val APPLICATION_OCTET_STREAM = "application/octet-stream" | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
src/main/kotlin/io/insource/framework/zeromq/ZmqTemplate.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package io.insource.framework.zeromq | ||
|
||
import org.zeromq.ContextFactory | ||
import org.zeromq.api.Context | ||
import org.zeromq.api.SocketType | ||
|
||
/** | ||
* Helper class that simplifies synchronous ZeroMQ access (sending and receiving messages) | ||
* using socket-per-thread semantics. | ||
* | ||
* @param context The 0MQ context | ||
*/ | ||
class ZmqTemplate(private val context: Context) { | ||
/** Default constructor. */ | ||
constructor() : this(ContextFactory.context()) | ||
|
||
/** Default topic name. Cannot be changed once threads have begun sending messages. */ | ||
var topic: String = "default" | ||
|
||
/** Default routing key, used when the routing key is not specified. */ | ||
var routingKey: String = "" | ||
|
||
/** Message converter used to convert a payload to/from a 0MQ `Message`. */ | ||
var messageConverter: MessageConverter = SimpleMessageConverter() | ||
|
||
/** ThreadLocal for creating channels using socket-per-thread semantics. */ | ||
private val channels: ThreadLocal<Channel> = ThreadLocal.withInitial { | ||
Channel(context.buildSocket(SocketType.PUSH).connect("inproc://$topic"), topic) | ||
} | ||
|
||
/** | ||
* Send a message with no headers to the default topic using the default | ||
* routing key. | ||
* | ||
* @param obj The message payload | ||
*/ | ||
fun send(obj: Any) { | ||
send(routingKey, obj) | ||
} | ||
|
||
/** | ||
* Send a message with no headers to the default topic. | ||
* | ||
* @param obj The message payload | ||
*/ | ||
fun send(routingKey: String, obj: Any) { | ||
send(routingKey, obj, mapOf()) | ||
} | ||
|
||
/** | ||
* Send a message to the default topic. | ||
* | ||
* @param obj The message payload | ||
* @param headers Message headers to go with the payload | ||
*/ | ||
fun send(routingKey: String, obj: Any, headers: Map<String, String>) { | ||
val channel = channels.get() | ||
val message = messageConverter.toMessage(obj, headers) | ||
channel.send(routingKey, message) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
src/test/kotlin/io/insource/framework/zeromq/ZmqTemplateTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package io.insource.framework.zeromq | ||
|
||
import io.insource.framework.annotation.QueueBinding | ||
import io.insource.framework.annotation.ZmqHandler | ||
import io.insource.framework.annotation.ZmqSubscriber | ||
import org.hamcrest.Matchers.hasItem | ||
import org.hamcrest.Matchers.hasSize | ||
import org.junit.Assert.assertThat | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
import org.springframework.boot.test.context.SpringBootTest | ||
import org.springframework.test.context.junit4.SpringRunner | ||
import java.util.concurrent.CountDownLatch | ||
|
||
@RunWith(SpringRunner::class) | ||
@SpringBootTest(classes = [ZeromqTestConfiguration::class]) | ||
class ZmqTemplateTest { | ||
@ZmqSubscriber( | ||
QueueBinding(topic = "ZmqTemplateTest", key = "Greeting", queue = "greetings"), | ||
QueueBinding(topic = "ZmqTemplateTest", key = "Message", queue = "messages") | ||
) | ||
class Subscriber { | ||
@ZmqHandler | ||
fun onMessage(m: String) { | ||
messages += m | ||
countDownLatch.countDown() | ||
} | ||
} | ||
|
||
@Before | ||
fun setUp() { | ||
// Allow a little time for PUB and SUB to connect to each other | ||
Thread.sleep(50) | ||
} | ||
|
||
@Test | ||
fun testHello() { | ||
val zmqTemplate = ZmqTemplate().apply { | ||
topic = "ZmqTemplateTest" | ||
routingKey = "Message" | ||
messageConverter = DefaultMessageConverter() | ||
} | ||
|
||
// Received using default routing key of Message | ||
zmqTemplate.send("This is a message.") | ||
// Received using explicit routing key of Greeting | ||
zmqTemplate.send("Greeting", "Hello, World") | ||
// Not received using bunk routing key | ||
zmqTemplate.send("Nothing", "This message is not received.") | ||
|
||
countDownLatch.await() | ||
assertThat(messages, hasSize(2)) | ||
assertThat(messages, hasItem("Hello, World")) | ||
assertThat(messages, hasItem("This is a message.")) | ||
} | ||
|
||
companion object { | ||
val messages = mutableListOf<String>() | ||
val countDownLatch = CountDownLatch(2) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
zmq: | ||
publisher: | ||
topics: | ||
- test | ||
- TopicListenerTest | ||
- ZmqTemplateTest | ||
port: 52345 | ||
subscriber: | ||
port: 52345 | ||
|