diff --git a/examples/myapp/src/main/java/app/MyApp.java b/examples/myapp/src/main/java/app/MyApp.java index 1975e14a..0fd222a6 100644 --- a/examples/myapp/src/main/java/app/MyApp.java +++ b/examples/myapp/src/main/java/app/MyApp.java @@ -6,7 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; -// tag::install[] +// #region install @SpringBootApplication @EnableQueryResponse public class MyApp { @@ -16,4 +16,4 @@ public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } } -// end::install[] +// #endregion install diff --git a/examples/myapp/src/main/java/app/Queries.java b/examples/myapp/src/main/java/app/Queries.java index 97b04d35..3112fd43 100644 --- a/examples/myapp/src/main/java/app/Queries.java +++ b/examples/myapp/src/main/java/app/Queries.java @@ -15,7 +15,7 @@ import java.util.Collection; -// tag::query[] +// #region query @Component public class Queries { @@ -34,4 +34,4 @@ public void query() { polos.stream().map("marco? "::concat).forEach(System.out::println); } } -// end::query[] +// #endregion query diff --git a/examples/myapp/src/main/java/app/Responses.java b/examples/myapp/src/main/java/app/Responses.java index cf139154..3c79fcd2 100644 --- a/examples/myapp/src/main/java/app/Responses.java +++ b/examples/myapp/src/main/java/app/Responses.java @@ -13,7 +13,7 @@ import org.springframework.stereotype.Component; -// tag::response[] +// #region response @Component public class Responses { @@ -29,4 +29,4 @@ public void response() { .from("polo", "yolo"); // <3> } } -// end::response[] +// #endregion response diff --git a/xdocs/attributes.js b/xdocs/attributes.js deleted file mode 100644 index 2d512f2f..00000000 --- a/xdocs/attributes.js +++ /dev/null @@ -1,25 +0,0 @@ -// code-src: ../java/com/studiomediatech/queryresponse, -// test-src: ../../test/java/com/studiomediatech/queryresponse, -// examples-src: ../../../examples, - -// java-required-version: 11, -// java-name: Java, -// java-name-and-version: {java-name} {java-required-version}, -// java-name-and-latest-version: {java-name} {java-version}, - -export const springname = "Spring"; -export const springamqpname = "Spring AMQP"; -export const springbootversion = "2.x"; -export const springbootverifiedversion = "3.0.3"; -export const springbootname = "Spring Boot"; -export const springbootnameandversion = `${springbootname} ${springbootversion}`; -export const springbootnameandverifiedversion = `${springbootname} ${springbootverifiedversion}`; - -export const qrcurrentversion = "0.0.0-SNAPSHOT"; -export const qrpfx = "Query/Response"; -export const qrname = `${qrpfx} for ${springamqpname}`; -export const qruiname = `${qrpfx} Monitoring UI`; -export const qrnameandversion = `${qrname} ${qrcurrentversion}`; - -// qr-gh-link: https://github.com/olle/query-response-spring-amqp, -// qr-ui-link: https://github.com/olle/query-response-spring-amqraw/main/ui/query-response-ui.jar, diff --git a/xdocs/guide/getting-started.md b/xdocs/guide/getting-started.md index 38a9d58d..b3a25438 100644 --- a/xdocs/guide/getting-started.md +++ b/xdocs/guide/getting-started.md @@ -1,41 +1,33 @@ # Getting Started -{{attr.qrname}} makes it really easy to extend {spring-boot-name} stand-alone, -production-grade applications, that are using {spring-amqp-name}. We have taken +{{BRAND}} makes it really easy to extend Spring Boot stand-alone, +production-grade applications, that are using Spring AMQP. We have taken a working pattern for building highly decoupled evolving service architectures, and wrapped it in a developer friendly library. ## System Requirements -{qr-name-and-version} requires at least **{spring-boot-name-and-version}** and -**{java-name-and-version}**, and should work for later releases too. We are -building and running it successfully with **{java-name-and-latest-version}** and -the **{spring-boot-name-and-verified-version}** version. +{{BRAND}} requires at least **Spring Boot 2.x** and **Java 11**, and should work +for later releases too. We are building and running it successfully with +**Java 11** and the **Spring Boot 3.0.3** version. ## Installation & Configuration -:Maven: https://maven.apache.org -:Gradle: https://gradle.org -:Quickstart: https://github.com/olle/query-response-spring-amqp#quickstart +It is distributed as a [Maven](https://maven.apache.org) dependency, and is +known to work well with Maven 3.3+. Using the dependency with [Gradle](https://gradle.org) +should work too. Please see the [Quickstart](https://github.com/olle/query-response-spring-amqp#quickstart) +information, available on the project [Github page](https://github.com/olle/query-response-spring-amqp), +for information on how to get the Maven dependency. -It is distributed as a {Maven}[Maven] dependency, and is known to work well with -Maven 3.3+. Using the dependency with {Gradle}[Gradle] should work too. Please -see the {Quickstart}[Quickstart] information, available on the project -{qr-gh-link}[Github page], for information on how to get the Maven dependency. - -Enabling {qr-name} is done by loading the `QueryResponseConfiguration` -class. The most simple way to do this, is by annotating your {spring-boot-name} +Enabling {{BRAND}} is done by loading the `QueryResponseConfiguration` +class. The most simple way to do this, is by annotating your Spring Boot application with the `@EnableQueryResponse` annotation. -## [source,java] - -<<<@../../examples/myapp/src/main/java/app/MyApp.java{java} - -## include::{examples-src}/myapp/src/main/java/app/MyApp.java[tags=install] +<<<@../../examples/myapp/src/main/java/app/MyApp.java#install{java} NOTE: This annotation will do nothing more but to import the `QueryResponseConfiguration` class. @@ -46,29 +38,29 @@ be done. **It's just that easy.** ### Connecting to an AMQP broker Before you can run your application you need to make sure there is an AMQP -broker available. By default {spring-amqp-name} tries to connect to a +broker available. By default {{BRAND}} tries to connect to a https://www.rabbitmq.com[RabbitMQ], running locally on port `5672`. Start an and run RabbitMQ using `docker`: -.... +```sh $ docker run -p 5672:5672 -p 15672:15672 rabbitmq:3-management -.... +``` NOTE: The `3-management` tag will enable the RabbitMQ Management UI. When the broker is running, it can be accessed at http://localhost:15672 with -username and password `guest`. +username and password `guest/guest`. -Now running your application, will enable {qr-name}, connect to the broker and +Now running your application, will enable {{BRAND}}, connect to the broker and create all the resources necessary on the broker. -.... +```sh $ mvn spring-boot:run -.... +``` Now is a good time to use the RabbitMQ Management UI, available at http://localhost:15672, to inspect the exchange, queues and bindings created -by {qr-name} by default. +by {{BRAND}} by default. ## Queries @@ -76,39 +68,47 @@ Publishing **queries** is a way for your application to ask for information that it may need in order to accomplish tasks. Queries express a _need_, and are not addressed to any specific service or component. -{qr-name} makes it really really easy, to create and publish a query using +{{BRAND}} makes it really really easy, to create and publish a query using the `QueryBuilder`. -## [source,java] +<<<@../../examples/myapp/src/main/java/app/Queries.java#query{java} -## include::{examples-src}/myapp/src/main/java/app/Queries.java[tags=query] +::: info Note +We are using the `@Order` annotation in our example only to ensure that +responses are built and registered before queries, when they are built +in one and the same app. +::: -<1> Initiates a query for the term `marco`, with any results being consumed as, +::: tip <1> +Initiates a query for the term `marco`, with any results being consumed as, or _mapped_ to, the type `String.class`. Returned results are always gathered in a collection. Either **none, one or many** elements may be returned. +::: -<2> Queries require a timeout, here we set it to `1000L` milliseconds. This +::: tip <2> +Queries require a timeout, here we set it to `1000L` milliseconds. This means that this specific query will **always** block for 1 second. +::: -<3> The query may not receive any responses, so it _always_ needs to specify +::: tip <3> +The query may not receive any responses, so it _always_ needs to specify how that case should be handled. Default here is an empty collection, of the declared return type `String.class`. +::: -==== -Hopefully this shows, how concise and powerful the `QueryBuilder` is, dealing +_Hopefully this shows, how concise and powerful the `QueryBuilder` is, dealing with results mapping, fault tolerance and default values in just a couple of -lines of code. -==== +lines of code._ If you run the application now, it will publish a **query** to the message broker, which we can see in the logs. -.... +```sh $ mvn spring-boot:run ... c.s.queryresponse.RabbitFacade : |<-- Published query: marco - (Body:'{}' MessageProperties [headers={x-qr-published=1589642002076}, replyTo=94f0fff4-c4f3-4491-831d-00809edb6f95, contentType=application/json, contentLength=2, deliveryMode=NON_PERSISTENT, priority=0, deliveryTag=0]) -.... +``` At the moment there are no responses to be consumed, so after blocking for 1 second, nothing is printed `STDOUT`. @@ -116,31 +116,33 @@ second, nothing is printed `STDOUT`. ## Responses Building services, medium, large or _micro_ (who cares), that publish -**responses** to queries is also really easy with {qr-name}, using the +**responses** to queries is also really easy with {{BRAND}}, using the `ResponseBuilder`. -## [source,java] +<<<@../../examples/myapp/src/main/java/app/Responses.java#response{java} -## include::{examples-src}/myapp/src/main/java/app/Responses.java[tags=response] - -<1> Initializes a response to queries for `marco`, providing the type-hint on +::: tip <1> +Initializes a response to queries for `marco`, providing the type-hint on how to map entries in the response. Set to `String.class` here. +::: -<2> The response `withAll()` will publish all elements in one single response. +::: tip <2> +The response `withAll()` will publish all elements in one single response. +::: -<3> And finally this response is provided the elements `"polo", "yolo"` as the +::: tip <3> +And finally this response is provided the elements `"polo", "yolo"` as the actual data to publish. _The builder varags method, used here, is mostly for trying out {qr-name}, or for static responses._ +::: -==== -Again, the builder makes it really easy to create a responding service, without -any special setup or complicated configurations. -==== +_Again, the builder makes it really easy to create a responding service, without +any special setup or complicated configurations._ Now if you run the application again, with the response component registered before the query publisher, it will publish the response. -.... +```sh $ mvn spring-boot:run ... c.s.queryresponse.RabbitFacade : |<-- Published query: marco - (Body:'{}' MessageProperties [headers={x-qr-published=1589642489894}, replyTo=c77a8a1d-c959-4f2a-bd51-85b7e6b5b69b, contentType=application/json, contentLength=2, deliveryMode=NON_PERSISTENT, priority=0, deliveryTag=0]) @@ -149,12 +151,8 @@ c.s.queryresponse.RabbitFacade : |<-- Published response: c77a8a1d-c959-4f2a-bd5 c.s.queryresponse.Query : |--> Received response message: MessageProperties [headers={x-qr-published=1589642489941}, contentType=application/json, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=NON_PERSISTENT, priority=0, redelivered=false, receivedExchange=, receivedRoutingKey=c77a8a1d-c959-4f2a-bd51-85b7e6b5b69b, deliveryTag=1, consumerTag=amq.ctag-Q_ghWp4TWU9EYhi_rqErcg, consumerQueue=c77a8a1d-c959-4f2a-bd51-85b7e6b5b69b] marco? polo marco? yolo -.... +``` Now you can see a full roundtrip of the **query** being published and consumed, and the **response** being published and also consumed. And the finished output is "polo" and "yolo" printed on `STDOUT`. - -NOTE: We are using the `@Order` annotation in our example only to ensure that -responses are built and registered before queries, when they are built -in one and the same app.