Skip to content

Commit 14812f9

Browse files
authored
Merge pull request #19 from GSamuel/master
Shorter extension functions on QueryGateway
2 parents e2c67a7 + ac29d05 commit 14812f9

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

kotlin/src/main/kotlin/org/axonframework/extensions/kotlin/QueryGatewayExtensions.kt

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,20 @@ import org.axonframework.queryhandling.QueryGateway
2020
import java.util.*
2121
import java.util.concurrent.CompletableFuture
2222

23+
/**
24+
* Reified version of [QueryGateway.query]
25+
* which expects a collection as a response using [org.axonframework.messaging.responsetypes.MultipleInstancesResponseType]
26+
* @param query Query to send
27+
* @param [Q] the type of payload of the query
28+
* @param [R] the type of result of the query
29+
* @return [CompletableFuture] wrapping the result of the query
30+
* @see QueryGateway.query
31+
* @see ResponseTypes
32+
*/
33+
inline fun <reified R, reified Q> QueryGateway.queryForMultiple(query: Q): CompletableFuture<List<R>> {
34+
return this.query(query, ResponseTypes.multipleInstancesOf(R::class.java))
35+
}
36+
2337
/**
2438
* Reified version of [QueryGateway.query] with explicit query name
2539
* which expects a collection as a response using [org.axonframework.messaging.responsetypes.MultipleInstancesResponseType]
@@ -35,6 +49,20 @@ inline fun <reified R, reified Q> QueryGateway.queryForMultiple(queryName: Strin
3549
return this.query(queryName, query, ResponseTypes.multipleInstancesOf(R::class.java))
3650
}
3751

52+
/**
53+
* Reified version of [QueryGateway.query]
54+
* which expects a single object as a response using [org.axonframework.messaging.responsetypes.InstanceResponseType]
55+
* @param query Query to send
56+
* @param [Q] the type of payload of the query
57+
* @param [R] the type of result of the query
58+
* @return [CompletableFuture] wrapping the result of the query
59+
* @see QueryGateway.query
60+
* @see ResponseTypes
61+
*/
62+
inline fun <reified R, reified Q> QueryGateway.queryForSingle(query: Q): CompletableFuture<R> {
63+
return this.query(query, ResponseTypes.instanceOf(R::class.java))
64+
}
65+
3866
/**
3967
* Reified version of [QueryGateway.query] with explicit query name
4068
* which expects a single object as a response using [org.axonframework.messaging.responsetypes.InstanceResponseType]
@@ -50,6 +78,20 @@ inline fun <reified R, reified Q> QueryGateway.queryForSingle(queryName: String,
5078
return this.query(queryName, query, ResponseTypes.instanceOf(R::class.java))
5179
}
5280

81+
/**
82+
* Reified version of [QueryGateway.query]
83+
* which expects an Optional object as a response using [org.axonframework.messaging.responsetypes.OptionalResponseType]
84+
* @param query Query to send
85+
* @param [Q] the type of payload of the query
86+
* @param [R] the type of result of the query
87+
* @return [CompletableFuture] wrapping the result of the query
88+
* @see QueryGateway.query
89+
* @see ResponseTypes
90+
*/
91+
inline fun <reified R, reified Q> QueryGateway.queryForOptional(query: Q): CompletableFuture<Optional<R>> {
92+
return this.query(query, ResponseTypes.optionalInstanceOf(R::class.java))
93+
}
94+
5395
/**
5496
* Reified version of [QueryGateway.query] with explicit query name
5597
* which expects an Optional object as a response using [org.axonframework.messaging.responsetypes.OptionalResponseType]

kotlin/src/test/kotlin/org/axonframework/extensions/kotlin/QueryGatewayExtensionsTest.kt

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ class QueryGatewayExtensionsTest {
4646

4747
@BeforeTest
4848
fun before() {
49+
every { subjectGateway.query(exampleQuery, matchInstanceResponseType<String>()) } returns instanceReturnValue
50+
every { subjectGateway.query(exampleQuery, matchOptionalResponseType<String>()) } returns optionalReturnValue
51+
every { subjectGateway.query(exampleQuery, matchMultipleInstancesResponseType<String>()) } returns listReturnValue
4952
every { subjectGateway.query(queryName, exampleQuery, matchInstanceResponseType<String>()) } returns instanceReturnValue
5053
every { subjectGateway.query(queryName, exampleQuery, matchOptionalResponseType<String>()) } returns optionalReturnValue
5154
every { subjectGateway.query(queryName, exampleQuery, matchMultipleInstancesResponseType<String>()) } returns listReturnValue
@@ -56,6 +59,71 @@ class QueryGatewayExtensionsTest {
5659
clearMocks(subjectGateway)
5760
}
5861

62+
@Test
63+
fun `Query without queryName for Single should invoke query method with correct generic parameters`() {
64+
val queryResult = subjectGateway.queryForSingle<String, ExampleQuery>(query = exampleQuery)
65+
assertSame(queryResult, instanceReturnValue)
66+
verify(exactly = 1) {
67+
subjectGateway.query(exampleQuery, matchExpectedResponseType(String::class.java))
68+
}
69+
}
70+
71+
@Test
72+
fun `Query without queryName for Single should invoke query method and not require explicit generic types`() {
73+
val queryResult:CompletableFuture<String> = subjectGateway.queryForSingle(query = exampleQuery)
74+
assertSame(queryResult, instanceReturnValue)
75+
verify(exactly = 1) {
76+
subjectGateway.query(exampleQuery, matchExpectedResponseType(String::class.java))
77+
}
78+
}
79+
80+
@Test
81+
fun `Query without queryName for Optional should invoke query method with correct generic parameters`() {
82+
val queryResult = subjectGateway.queryForOptional<String, ExampleQuery>(query = exampleQuery)
83+
84+
assertSame(queryResult, optionalReturnValue)
85+
verify(exactly = 1) { subjectGateway.query(exampleQuery, matchExpectedResponseType(String::class.java)) }
86+
}
87+
88+
@Test
89+
fun `Query without queryName for Optional should invoke query method and not require explicit generic types`() {
90+
val queryResult: CompletableFuture<Optional<String>> = subjectGateway.queryForOptional(query = exampleQuery)
91+
92+
assertSame(queryResult, optionalReturnValue)
93+
verify(exactly = 1) { subjectGateway.query(exampleQuery, matchExpectedResponseType(String::class.java)) }
94+
}
95+
96+
@Test
97+
fun `Query without queryName for Multiple should invoke query method with correct generic parameters`() {
98+
val queryResult = subjectGateway.queryForMultiple<String, ExampleQuery>(query = exampleQuery)
99+
100+
assertSame(queryResult, listReturnValue)
101+
verify(exactly = 1) { subjectGateway.query(exampleQuery, matchExpectedResponseType(String::class.java)) }
102+
}
103+
104+
@Test
105+
fun `Query without queryName for Multiple should invoke query method and not require explicit generic types`() {
106+
val queryResult: CompletableFuture<List<String>> = subjectGateway.queryForMultiple(query = exampleQuery)
107+
108+
assertSame(queryResult, listReturnValue)
109+
verify(exactly = 1) { subjectGateway.query(exampleQuery, matchExpectedResponseType(String::class.java)) }
110+
}
111+
112+
@Test
113+
fun `Query without queryName for Single should handle nullable responses`() {
114+
val nullInstanceReturnValue: CompletableFuture<String?> = CompletableFuture.completedFuture(null)
115+
val nullableQueryGateway = mockk<QueryGateway> {
116+
every { query(exampleQuery, match { i: AbstractResponseType<String?> -> i is InstanceResponseType }) } returns nullInstanceReturnValue
117+
}
118+
119+
val queryResult = nullableQueryGateway.queryForSingle<String?, ExampleQuery>(query = exampleQuery)
120+
121+
assertSame(queryResult, nullInstanceReturnValue)
122+
assertTrue(nullInstanceReturnValue.get() == null)
123+
verify(exactly = 1) { nullableQueryGateway.query(exampleQuery, matchExpectedResponseType(String::class.java)) }
124+
}
125+
126+
59127
@Test
60128
fun `Query for Single should invoke query method with correct generic parameters`() {
61129
val queryResult = subjectGateway.queryForSingle<String, ExampleQuery>(queryName = queryName, query = exampleQuery)

0 commit comments

Comments
 (0)