{"id":89011,"date":"2019-03-04T09:00:32","date_gmt":"2019-03-04T07:00:32","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=89011"},"modified":"2019-03-11T09:24:51","modified_gmt":"2019-03-11T07:24:51","slug":"build-reactive-app-spring-boot-mongodb","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2019\/03\/build-reactive-app-spring-boot-mongodb.html","title":{"rendered":"Build a Reactive App with Spring Boot and MongoDB"},"content":{"rendered":"<p><span style=\"font-size: 20px;\"><b>\u201cI love writing authentication and authorization code.\u201d ~ No Java Developer Ever.<\/b> Tired of building the same login screens over and over? <a href=\"https:\/\/developer.okta.com\/signup\/?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Try the Okta API for hosted authentication, authorization, and multi-factor auth.<\/a><\/span><\/p>\n<p>Reactive apps allow you to scale better if you\u2019re dealing with lots of streaming data. They\u2019re non-blocking and tend to be more efficient because they\u2019re not tying up processing while waiting for stuff to happen.<\/p>\n<p>Reactive systems embrace asynchronous I\/O. The concept behind asynchronous I\/O is straightforward: alleviate inefficient resource utilization by reclaiming resources that would otherwise be idle as they waited for I\/O activity. Asynchronous I\/O inverts the normal design of I\/O processing: the clients are notified of new data instead of asking for it; this frees the client to do other things while waiting.<\/p>\n<p>If you\u2019re going to build a reactive app, you\u2019ll need it to be reactive all the way down to your database. Use a blocking JDBC driver with Spring WebFlux, and you\u2019ll be disappointed in its performance. Use a reactive NoSQL database like Cassandra, MongoDB, Couchbase and Redis \u2013 and you\u2019ll be impressed by its performance.<\/p>\n<p>In this tutorial, you\u2019ll learn how to use Spring Boot, Spring WebFlux, and Spring Data to create a reactive web service that talks to a NoSQL database backend (MongoDB, in this case).<\/p>\n<p>I just threw a handful of terms at you. Let\u2019s go over them.<\/p>\n<p><em>If you already understand NoSQL and Reactive programming and just want to see some code, feel free to skip the first two sections and start with \u201cBuild a Spring Boot Resource Server\u201d.<\/em><\/p>\n<p><strong>NOTE:<\/strong>&nbsp;The first part of this series demonstrated how to use Spring Boot and Spring Data with a relational database, PostgreSQL. You can check out that post&nbsp;<a href=\"https:\/\/developer.okta.com\/blog\/2018\/12\/13\/build-basic-app-spring-boot-jpa?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">here<\/a>.<\/p>\n<h2 class=\"wp-block-heading\" id=\"what-is-nosql-and-why-mongodb\">What is NoSQL and Why MongoDB?<\/h2>\n<p><strong>NoSQL<\/strong>&nbsp;is a term for any non-relational database. In relational databases (think SQL, MySQL, etc\u2026), data is stored in tables with strong typing and well-defined relationships between table columns. The tight, well-defined structure of relational databases is both their strength and their weakness. It\u2019s a trade-off. NoSQL databases explode this model and provide other models that allow for more flexibility and ease of scaling.<\/p>\n<p>The microservice\/cluster model of scaling created lots of problems for relational databases. They just weren\u2019t built to run and stay in sync across multiple machines. NoSQL databases were developed, in part, to address this problem. Often, they were built with clustering and horizontal scaling in mind. To present this another way, classically with SQL databases, if you needed more power, you had to resize the server that the database was running on; it was pretty monolithic, and this is hard to do dynamically, even with all the modern virtual server snazziness available these days. At internet scale, a far better model is to have a flexible cluster of databases that automatically sync between them and that allow you to spin up instances as demand requires (and spin them down when demand lessens). This means that adding more power doesn\u2019t require ever more expensive machines; you can simply add more, relatively cheap machines as needed.<\/p>\n<p>Another potential benefit of NoSQL databases is their flexibility. A document-based NoSQL database like MongoDB can store arbitrary data in documents. Fields can be added to the stored documents on the fly, without the overhead of table migrations and what not. Of course, this doesn\u2019t solve the problem of versioning and it\u2019s still up to the app to deal with the changing data structure (not always trivial), but at least you\u2019re not fighting the database.<\/p>\n<p>All that said, keep in mind that SQL\/relational databases aren\u2019t going anywhere. They\u2019re proven, fast, and super reliable. In some use cases, they\u2019re cheaper and easier. MySQL is hard to beat for a simple website or blog, for example. But even in an enterprise setting,&nbsp;<em>sometimes you want the structure that a relational database enforces.<\/em>&nbsp;If you have a fairly static data model and don\u2019t need to scale to internet scale, SQL may be the best choice. These types of design considerations are worth pondering before you dive into a database choice simply because it\u2019s new and flashy.<\/p>\n<p>I\u2019m using MongoDB in this tutorial because it\u2019s a breeze to start with. If you use Spring Data MongoDB, it\u2019s even easier!<\/p>\n<h2 class=\"wp-block-heading\" id=\"get-reactive\">Get Reactive!<\/h2>\n<p>Reactive is another great bit of jargon. It feels like the kind of word that people like to throw around at parties and conferences with only vague ideas of what it actually means. Like \u201cexistential\u201d or \u201cennui.\u201d Let\u2019s define it.<\/p>\n<p>If you take a look at&nbsp;<a href=\"https:\/\/docs.spring.io\/spring\/docs\/current\/spring-framework-reference\/web-reactive.html\">the Spring WebFlux documentation<\/a>, they give a pretty good overview of what&nbsp;<strong>reactive<\/strong>&nbsp;means.<\/p>\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The term, \u201creactive,\u201d refers to programming models that are built around reacting to change\u2009\u2014\u2009network components reacting to I\/O events, UI controllers reacting to mouse events, and others. In that sense, non-blocking is reactive, because, instead of being blocked, we are now in the mode of reacting to notifications as operations complete or data becomes available.<\/p>\n<\/blockquote>\n<p>So reactive means: non-blocking, asynchronous, and centered around stream processing.<\/p>\n<h2 class=\"wp-block-heading\" id=\"build-a-spring-boot-resource-server\">Build a Spring Boot Resource Server<\/h2>\n<p>Clone the starter project from the GitHub repository and check out the&nbsp;<strong>start<\/strong>&nbsp;branch:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">git clone -b start https:\/\/github.com\/oktadeveloper\/okta-spring-boot-mongo-webflux-example.git\n<\/pre>\n<p>The starter project is a simple Spring Boot starter project with the necessary dependencies already in the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">build.gradle<\/code>&nbsp;file.<\/p>\n<p>Let\u2019s take a quick look at the dependencies:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">compile('org.springframework.boot:spring-boot-starter-webflux')  \ncompile('org.springframework.boot:spring-boot-starter-data-mongodb-reactive')  \ncompileOnly('org.projectlombok:lombok')  \ncompile('de.flapdoodle.embed:de.flapdoodle.embed.mongo')\n<\/pre>\n<p>The first is for Spring WebFlux, the reactive version of Spring MVC. The second brings in the reactive MongoDB dependencies that Spring needs. The third is a project called Lombok that saves us from typing a bunch of constructors, getters, and setters in our Java code (you can check out the project on&nbsp;<a href=\"https:\/\/projectlombok.org\/\">their webpage<\/a>). The last dependency is an embedded, in-memory MongoDB database. This database is great for testing, simple tutorials like this, and isn\u2019t persisted.<\/p>\n<p>The application can be run using a simple Gradle command:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">.\/gradlew bootRun<\/pre>\n<p>Of course, if you run the app at this point it\u2019s not going to do much. Spring Boot will load, but there aren\u2019t any controllers, resources, or repositories defined yet, so nothing much happens.<\/p>\n<h2 class=\"wp-block-heading\" id=\"define-a-model-class-for-mongodb\">Define a Model Class for MongoDB<\/h2>\n<p>For clarity, this tutorial is going to parallel the&nbsp;<a href=\"https:\/\/developer.okta.com\/blog\/2018\/12\/13\/build-basic-app-spring-boot-jpa?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">first part of this series<\/a>&nbsp;that I mentioned earlier. You\u2019re going to build a simple server that stores types of kayaks. I always suggest starting any project by defining the data structure first.<\/p>\n<p>Create a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Kayak.java<\/code>&nbsp;class file in the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">com.okta.springbootmongo<\/code>&nbsp;package:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.springbootmongo;  \n\nimport lombok.AllArgsConstructor;  \nimport lombok.Data;  \nimport lombok.NoArgsConstructor;  \nimport org.springframework.data.mongodb.core.mapping.Document;  \n\n@Document\n@Data  \n@AllArgsConstructor  \n@NoArgsConstructor  \npublic class Kayak {  \n    private String name;  \n    private String owner;  \n    private Number value;  \n    private String makeModel;  \n}\n<\/pre>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@Document<\/code>&nbsp;annotation is the NoSQL equivalent of&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@Entity<\/code>. It tells Spring Boot that this class is defining a data model. In the NoSQL world, this means creating a document instead of a table entry. The other three annotations are Lombok helpers that autogenerate getters, setters, and constructors.<\/p>\n<p>The kayak document has five properties: name, owner, value, and type. These are automatically mapped to appropriate BSON types for MongoDB. What\u2019s a BSON type? Take a look at&nbsp;<a href=\"https:\/\/docs.mongodb.com\/manual\/reference\/bson-types\/\">the MongoDB docs on the subject<\/a>. They are the binary serialization types used to persist data in MongoDB documents. They define the primitive types that can be stored in a MongoDB database.<\/p>\n<h2 class=\"wp-block-heading\" id=\"add-a-reactivemongorepository-to-your-spring-boot-app\">Add a ReactiveMongoRepository to Your Spring Boot App<\/h2>\n<p>Defining the Kayak class with the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@Document<\/code>&nbsp;annotation tells Spring Boot about the structure of the data, but doesn\u2019t actually give us any way of saving or loading data from the database. In order to do that, you need to define a Repository.<\/p>\n<p>The code for that is beguilingly simple. Create a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">KayakRepository.java<\/code>&nbsp;class file in the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">com.okta.springbootmongo<\/code>package:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.springbootmongo;  \n  \nimport org.springframework.data.mongodb.repository.ReactiveMongoRepository;  \n\npublic interface KayakRepository extends ReactiveMongoRepository&lt;Kayak, Long&gt; {  \n}\n<\/pre>\n<p>This actually gives you all of the basic methods you need to create, update, read, and delete documents from the database. To understand how, dig into the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ReactiveMongoRepository<\/code>&nbsp;class and the various other superclasses, particularly&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ReactiveCrudRepository<\/code>. Take a look at&nbsp;<a href=\"https:\/\/docs.spring.io\/spring-data\/mongodb\/docs\/current\/api\/org\/springframework\/data\/mongodb\/repository\/ReactiveMongoRepository.html\">the docs<\/a>&nbsp;for&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ReactiveCrudRepository<\/code>&nbsp;to see the implemented methods.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p><code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ReactiveCrudRepository<\/code>&nbsp;actually provides a basic and complete set of CRUD methods.&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ReactiveMongoRepository<\/code>builds on top of that to provide some MongoDB-specific querying features.<\/p>\n<h2 class=\"wp-block-heading\" id=\"implement-a-controller-with-spring-webflux\">Implement a Controller with Spring WebFlux<\/h2>\n<p>With the repository added, you have enough to manipulate the data programmatically. However, there are no web endpoints defined. In the previous tutorial, to add REST endpoints, all that was required was to add the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">@RepositoryRestResource<\/code>annotation to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">KayakRepository<\/code>&nbsp;class. This autogenerated a fully functioning REST resource for us with all of the CRUD methods. This shortcut does not work with Spring WebFlux, however. Any public web endpoints will have to be explicitly defined.<\/p>\n<p>Add the following&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">KayakController.java<\/code>&nbsp;class<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.springbootmongo;  \n  \nimport org.springframework.beans.factory.annotation.Autowired;  \nimport org.springframework.stereotype.Controller;  \nimport org.springframework.web.bind.annotation.*;  \nimport reactor.core.publisher.Flux;  \n\n@Controller  \n@RequestMapping(path = \"\/kayaks\")  \npublic class KayakController {  \n  \n    private KayakRepository kayakRepository;  \n    \n    public KayakController(KayakRepository kayakRepository) {\n        this.kayakRepository = kayakRepository;\n    }\n  \n    @PostMapping()  \n    public @ResponseBody  \n    Mono&lt;Kayak&gt; addKayak(@RequestBody Kayak kayak) {  \n        return kayakRepository.save(kayak);  \n    }  \n  \n    @GetMapping()  \n    public @ResponseBody  \n    Flux&lt;Kayak&gt; getAllKayaks() {  \n        return kayakRepository.findAll();  \n    }\n}\n<\/pre>\n<p>This controller adds two endpoints:<\/p>\n<ul class=\"wp-block-list\">\n<li>POST&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/kayaks<\/code>&nbsp;that adds a new kayak<\/li>\n<li>GET&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/kayaks<\/code>&nbsp;that lists all of the kayaks<\/li>\n<\/ul>\n<p>You\u2019ll also notice that the class uses Spring dependency injection to autowire the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">KayakRepository<\/code>&nbsp;instance into the controller, and you\u2019ll see how the Kayak domain class is being persisted using the repository.<\/p>\n<p>This class looks an awful lot like a relational, blocking version. A lot of behind the scenes work goes into making this the case. Have no fear, however, this is 100% reactive, non-blocking code.<\/p>\n<h2 class=\"wp-block-heading\" id=\"test-your-spring-boot-server\">Test Your Spring Boot Server<\/h2>\n<p>At this point, you have a fully operational kayak REST resource server. Before you test it, add the following method to your&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">MainApplication<\/code>&nbsp;class. This simply injects some test data into the database when the application loads.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">@Bean  \nApplicationRunner init(KayakRepository repository) {  \n  \n  Object[][] data = {  \n      {\"sea\", \"Andrew\", 300.12, \"NDK\"},  \n      {\"creek\", \"Andrew\", 100.75, \"Piranha\"},  \n      {\"loaner\", \"Andrew\", 75, \"Necky\"}  \n  };  \n  \n  return args -&gt; {  \n      repository  \n          .deleteAll()  \n          .thenMany(  \n              Flux  \n                  .just(data)  \n                  .map(array -&gt; {  \n                      return new Kayak((String) array[0], (String) array[1], (Number) array[2], (String) array[3]);  \n                  })  \n                  .flatMap(repository::save)  \n          )  \n          .thenMany(repository.findAll())  \n          .subscribe(kayak -&gt; System.out.println(\"saving \" + kayak.toString()));\n  };  \n}\n<\/pre>\n<p>HTTPie is a great command line utility that makes it easy to run requests against the resource server. If you don\u2019t have HTTPie installed, install it using&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">brew install httpie<\/code>. Or head over to&nbsp;<a href=\"https:\/\/httpie.org\/\">their website<\/a>&nbsp;and make it happen. Or just follow along.<\/p>\n<p>Make sure your Spring Boot app is running. If it isn\u2019t, start it using&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/gradlew bootRun<\/code>.<\/p>\n<p>Run a GET request against your resource server:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http :8080\/kayaks<\/code>, which is shorthand for&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http GET http:\/\/localhost:8080\/kayaks<\/code>.<\/p>\n<p>You\u2019ll get this:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:js\">HTTP\/1.1 200 OK\nContent-Type: application\/json;charset=UTF-8\ntransfer-encoding: chunked\n[\n    {\n        \"makeModel\": \"NDK\",\n        \"name\": \"sea\",\n        \"owner\": \"Andrew\",\n        \"value\": 300.12\n    },\n    {\n        \"makeModel\": \"Piranha\",\n        \"name\": \"creek\",\n        \"owner\": \"Andrew\",\n        \"value\": 100.75\n    },\n    {\n        \"makeModel\": \"Necky\",\n        \"name\": \"loaner\",\n        \"owner\": \"Andrew\",\n        \"value\": 75\n    }\n]\n<\/pre>\n<p>Now try POST\u2019ing a new kayak to the server.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:js\">http POST :8080\/kayaks name=\"sea2\" owner=\"Andrew\" value=\"500\" makeModel=\"P&amp;H\"<\/pre>\n<p>You should see:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:js\">HTTP\/1.1 200 OK\nContent-Length: 62\nContent-Type: application\/json;charset=UTF-8\n{\n    \"makeModel\": \"P&amp;H\",\n    \"name\": \"sea2\",\n    \"owner\": \"Andrew\",\n    \"value\": 500\n}<\/pre>\n<p>And if you repeat the GET request,&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">http :8080\/kayaks<\/code>, you\u2019ll see the new kayak in the list!<\/p>\n<h2 class=\"wp-block-heading\" id=\"set-up-secure-authentication\">Set Up Secure Authentication<\/h2>\n<p>Now you need to integrate Okta for OAuth 2.0 and add token-based authentication to the resource server.&nbsp;<strong>This section is exactly the same as the section in Part 1 of this tutorial,<\/strong>&nbsp;so if you\u2019ve already done that, all you need is your Client ID, and you can skip forward to to the next section.<\/p>\n<p>If you haven\u2019t already, head over to&nbsp;<a href=\"http:\/\/developer.okta.com\/signup\/?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">developer.okta.com<\/a>&nbsp;and sign up for a free account. Once you have an account, open the developer dashboard and create an OpenID Connect (OIDC) application by clicking on the&nbsp;<strong>Application<\/strong>&nbsp;top-menu item, and then on the&nbsp;<strong>Add Application<\/strong>&nbsp;button.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/create-new-application.png\" alt=\"Reactive App\" class=\"wp-image-89018\" width=\"738\" height=\"383\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/create-new-application.png 984w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/create-new-application-300x156.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/create-new-application-768x399.png 768w\" sizes=\"(max-width: 738px) 100vw, 738px\" \/><\/figure>\n<\/div>\n<p>Select&nbsp;<strong>Single-Page App<\/strong>.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/select-spa-958x1024.png\" alt=\"Reactive App\" class=\"wp-image-89019\" width=\"719\" height=\"768\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/select-spa-958x1024.png 958w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/select-spa-281x300.png 281w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/select-spa-768x821.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/select-spa.png 1484w\" sizes=\"(max-width: 719px) 100vw, 719px\" \/><\/figure>\n<\/div>\n<p>The default application settings are great, except that you need to add a&nbsp;<strong>Login Redirect URI<\/strong>:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">https:\/\/oidcdebugger.com\/debug<\/code>. You\u2019re going to use this in a moment to retrieve a test token.<\/p>\n<p><strong>NOTE<\/strong>: If you\u2019re implementing a front end like Angular or React, you may need to update the default login redirect URI depending on the platform you\u2019re using. Because this tutorial is only creating a resource server without a front end, it doesn\u2019t really matter for the moment. All our resource server will be doing is validating the JSON web token with the authorization server, which doesn\u2019t require a redirect.<\/p>\n<p>Also, note your&nbsp;<strong>Client ID<\/strong>, as you\u2019ll need that in a moment.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"818\" height=\"1024\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/spa-with-client-id-818x1024.png\" alt=\"Reactive App\" class=\"wp-image-89020\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/spa-with-client-id-818x1024.png 818w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/spa-with-client-id-240x300.png 240w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/spa-with-client-id-768x961.png 768w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/spa-with-client-id.png 1488w\" sizes=\"(max-width: 818px) 100vw, 818px\" \/><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"configure-your-spring-boot-server-for-token-authentication\">Configure Your Spring Boot Server for Token Authentication<\/h2>\n<p>Now you need to update a few project files to configure Spring Boot for OAuth 2.0.<\/p>\n<p>Add the following dependencies to your&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">build.gradle<\/code>&nbsp;file:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">dependencies {\n  ...\n    compile('com.okta.spring:okta-spring-boot-starter:1.1.0')\n  ...\n}<\/pre>\n<p>Create a new configuration file called&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">src\/main\/resources\/application.yml<\/code><\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">okta:\n  oauth2:\n    issuer: https:\/\/{yourOktaDomain}\/oauth2\/default\n    groupsClaim: groups\n    clientId: {yourClientId}<\/pre>\n<p>Create a&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SecurityConfiguration.java<\/code> class in the <code class=\"highlighter-rouge\" style=\"font-size: 13px;\">com.okta.springbootmongo<\/code>&nbsp;package:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.springbootmongo;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;\nimport org.springframework.security.config.web.server.ServerHttpSecurity;\nimport org.springframework.security.web.server.SecurityWebFilterChain;\n\n@EnableWebFluxSecurity\npublic class SecurityConfiguration {\n\n    @Bean\n    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {\n        http\n            .authorizeExchange()\n            .anyExchange().authenticated()\n            .and()\n            .oauth2ResourceServer()\n            .jwt();\n        return http.build();\n    }\n}\n<\/pre>\n<h2 class=\"wp-block-heading\" id=\"test-your-protected-server\">Test Your Protected Server<\/h2>\n<p>Stop your Spring Boot server and restart it using:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.\/gradlew bootRun<\/code><\/p>\n<p>From the command line, run a simple GET request.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">http :8080\/kayaks<\/pre>\n<p>You\u2019ll get a 401\/unauthorized.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">HTTP\/1.1 401 Unauthorized\nCache-Control: no-store\nContent-Type: application\/json;charset=UTF-8\n<\/pre>\n<h2 class=\"wp-block-heading\" id=\"generate-an-access-token\">Generate an Access Token<\/h2>\n<p>To access the server now, you need a valid access token. You can use&nbsp;<strong>OpenID Connect debugger<\/strong>&nbsp;to help you do this. In another window, open&nbsp;<a href=\"https:\/\/oidcdebugger.com\/\">oidcdebugger.com<\/a>.<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>Authorize URI<\/strong>:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\"><span class=\"okta-preview-domain\">https:\/\/{yourOktaDomain}<\/span>\/oauth2\/default\/v1\/authorize<\/code><\/li>\n<li><strong>Redirect URI<\/strong>: do not change. This is the value you added to your OIDC application above.<\/li>\n<li><strong>Client ID<\/strong>: from the OIDC application you just created.<\/li>\n<li><strong>Scope<\/strong>:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">openid profile email<\/code>.<\/li>\n<li><strong>State<\/strong>: any value you want to pass through the OAuth redirect process. I set it to&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">{}<\/code>.<\/li>\n<li><strong>Nonce<\/strong>: can be left alone. Nonce means \u201cnumber used once\u201d and is a simple security measure used to prevent the same request being used multiple times.<\/li>\n<li><strong>Response Type<\/strong>:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">token<\/code>.<\/li>\n<li><strong>Response mode<\/strong>:&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">form_post<\/code>.<\/li>\n<\/ul>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"699\" height=\"912\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/oidc-debugger.png\" alt=\"Reactive App\" class=\"wp-image-89021\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/oidc-debugger.png 699w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/oidc-debugger-230x300.png 230w\" sizes=\"(max-width: 699px) 100vw, 699px\" \/><\/figure>\n<\/div>\n<p>Click <strong>Send Request<\/strong>. If you are not logged into developer.okta.com, then you\u2019ll be required to log in. If you are (as is likely) already logged in, then the token will be generated for your signed-in identity.<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"604\" height=\"701\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/access-token.png\" alt=\"Reactive App\" class=\"wp-image-89022\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/access-token.png 604w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2019\/02\/access-token-258x300.png 258w\" sizes=\"(max-width: 604px) 100vw, 604px\" \/><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"use-your-access-token\">Use Your Access Token<\/h2>\n<p>You use the token by including in an&nbsp;<strong>Authorization<\/strong>&nbsp;request header of type&nbsp;<strong>Bearer<\/strong>.<\/p>\n<p>Store the token in a shell variable:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">TOKEN=eyJraWQiOiJldjFpay1DS3UzYjJXS3QzSVl1MlJZc3VJSzBBYUl3NkU4SDJfNVJr...<\/pre>\n<p>Then make a GET request with HTTPie:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">http :8080\/kayaks \"Authorization: Bearer $TOKEN\"<\/pre>\n<p><strong>Note the double quotes above.<\/strong>&nbsp;Single quotes do not work because the shell variable is not expanded.<\/p>\n<h2 class=\"wp-block-heading\" id=\"add-group-based-authorization\">Add Group-Based Authorization<\/h2>\n<p>Now you\u2019re going to make the authorization scheme a little more refined by adding the ability to control access to specific controller endpoints based on Group membership.<\/p>\n<p>To use group-based authorization with Okta, you need to add a \u201cgroups\u201d claim to your access token. Create an&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Admin<\/code>&nbsp;group (<strong>Users<\/strong>&nbsp;&gt;&nbsp;<strong>Groups<\/strong>&nbsp;&gt;&nbsp;<strong>Add Group<\/strong>) and add your user to it. You can use the account you signed up with, or create a new user (<strong>Users<\/strong>&gt;&nbsp;<strong>Add Person<\/strong>). Navigate to&nbsp;<strong>API<\/strong>&nbsp;&gt;&nbsp;<strong>Authorization Servers<\/strong>, click the&nbsp;<strong>Authorization Servers<\/strong>&nbsp;tab and edit the default one. Click the&nbsp;<strong>Claims<\/strong>&nbsp;tab and&nbsp;<strong>Add Claim<\/strong>. Name it \u201cgroups\u201d, and include it in the access token. Set the value type to \u201cGroups\u201d and set the filter to be a Regex of&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">.*<\/code>.<\/p>\n<p>The&nbsp;<strong>groups<\/strong>&nbsp;claim carries the groups to which the user is assigned. The default user you\u2019re using to sign into the developer.okta.com website will also be a member of both the \u201cEveryone\u201d group and the \u201cAdmin\u201d group.<\/p>\n<p>The&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">SecurityConfiguration<\/code>&nbsp;class also needs to be updated to use group-based authorization. Update the Java file to match the following:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:java\">package com.okta.springbootmongo;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;\nimport org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;\nimport org.springframework.security.config.web.server.ServerHttpSecurity;\nimport org.springframework.security.web.server.SecurityWebFilterChain;\n\n@EnableWebFluxSecurity\n@EnableReactiveMethodSecurity\npublic class SecurityConfiguration {\n\n  @Bean\n  public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {\n      http\n          .authorizeExchange()\n          .pathMatchers(HttpMethod.POST, \"\/kayaks\/**\").hasAuthority(\"Admin\")\n          .anyExchange().authenticated()\n          .and()\n          .oauth2ResourceServer()\n          .jwt();\n      return http.build();\n  }\n}\n<\/pre>\n<p>In simple English, this tells Spring Boot to require the group membership&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">Admin<\/code>&nbsp;for any POST to the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">\/kayak<\/code>&nbsp;endpoint, and for all other requests, simply require a valid JWT.<\/p>\n<p>Your group-based authorization policy is defined by these two lines:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">.pathMatchers(HttpMethod.POST, \"\/kayaks\/**\").hasAuthority(\"Admin\")  \n.anyExchange().authenticated()<\/pre>\n<p>For more information, take a look at&nbsp;<a href=\"https:\/\/docs.spring.io\/spring-security\/site\/docs\/current\/api\/org\/springframework\/security\/config\/web\/server\/ServerHttpSecurity.html\">the&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">ServerHttpSecurity<\/code>&nbsp;class\u2019s documentation<\/a>.<\/p>\n<p>You might be wondering why it says&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">hasAuthority()<\/code>&nbsp;instead of&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">hasRole()<\/code>&nbsp;or&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">hasGroup()<\/code>. This is because&nbsp;<strong>authorities<\/strong>&nbsp;are what Spring calls the text strings sent by the server to denote permission membership, be it roles or groups.&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">hasRole()<\/code>assumes that roles are in a specific format: \u201cROLE_ADMIN\u201d. This can be overridden, but&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">hasAuthority()<\/code>&nbsp;is a simple way to use the authority string directly. There is no&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">hasGroup()<\/code>&nbsp;method, as this use case is covered by the former two examples, if not explicitly.<\/p>\n<h2 class=\"wp-block-heading\" id=\"create-a-non-admin-user\">Create a Non-Admin User<\/h2>\n<p>To test your group-based authorization scheme, you need a user that isn\u2019t an admin. Go to the&nbsp;<a href=\"https:\/\/developer.okta.com\/?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">developer.okta.com<\/a>&nbsp;dashboard.<\/p>\n<p>From the top-menu, select&nbsp;<strong>Users<\/strong>&nbsp;&gt;&nbsp;<strong>People<\/strong>. Click the&nbsp;<strong>Add Person<\/strong>&nbsp;button.<\/p>\n<p>Give the user a&nbsp;<strong>First Name<\/strong>,&nbsp;<strong>Last Name<\/strong>, and&nbsp;<strong>Username<\/strong>&nbsp;(which will also be the&nbsp;<strong>Primary Email<\/strong>). The values do not matter, and you won\u2019t need to be able to check the email. You simply need to know the email address\/username and password so you can log in to Okta in a minute.<\/p>\n<p><strong>Password<\/strong>: change the drop down to&nbsp;<strong>Set by admin<\/strong>.<\/p>\n<p>Assign the user a password.<\/p>\n<p>Click&nbsp;<strong>Save<\/strong>.<\/p>\n<p>You\u2019ve just created a user that is NOT a member of the&nbsp;<em>Admin<\/em>&nbsp;group but is a member of the default group&nbsp;<em>Everyone<\/em>.<\/p>\n<h2 class=\"wp-block-heading\" id=\"test-group-based-authorization\">Test Group-Based Authorization<\/h2>\n<p>Log out of your Okta developer dashboard.<\/p>\n<p>Return to the&nbsp;<a href=\"https:\/\/oidcdebugger.com\/\">OIDC Debugger<\/a>&nbsp;and generate a new token.<\/p>\n<p>This time, log in as your new non-admin user. You\u2019ll be asked to choose a security question, after which you\u2019ll be redirected to the https:\/\/oidcdebugger.com\/debug page where your token can be copied.<\/p>\n<p>If you like, you can go to&nbsp;<a href=\"https:\/\/www.jsonwebtoken.io\/\">jsonwebtoken.io<\/a>&nbsp;and decode your new token. In the payload, the&nbsp;<em>sub<\/em>&nbsp;claim will show the email\/username of the user, and the&nbsp;<em>groups<\/em>&nbsp;claim will show only the&nbsp;<em>Everyone<\/em>&nbsp;group.<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:js\">{\n  \"sub\": \"test@gmail.com\",\n  \"groups\": [\n    \"Everyone\"\n  ]\n}<\/pre>\n<p>According to the permission scheme, this user should be able to list all kayaks but shouldn\u2019t be able to add a new kayak.<\/p>\n<p>Remember, store your token in a shell script like so:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">TOKEN=eyJraWQiOiI4UlE5REJGVUJOTnJER0VGaEExekd6bWJqREpSYTRTT1lhaGpsM3d4...<\/pre>\n<p>Make a GET request to list all kayaks:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:js\">http :8080\/kayaks \"Authorization: Bearer $TOKEN\"\n\nHTTP\/1.1 200 OK\nCache-Control: no-cache, no-store, max-age=0, must-revalidate\nContent-Type: application\/json;charset=UTF-8\n...\n\n[\n    {\n        \"makeModel\": \"NDK\",\n        \"name\": \"sea\",\n        \"owner\": \"Andrew\",\n        \"value\": 300.12\n    },\n    {\n        \"makeModel\": \"Necky\",\n        \"name\": \"loaner\",\n        \"owner\": \"Andrew\",\n        \"value\": 75\n    },\n    {\n        \"makeModel\": \"Piranha\",\n        \"name\": \"creek\",\n        \"owner\": \"Andrew\",\n        \"value\": 100.75\n    }\n]\n<\/pre>\n<p>Try to add a new kayak using the non-admin user token:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">http POST :8080\/kayaks \"Authorization: Bearer $TOKEN\" name=\"sea2\" owner=\"Andrew\" value=\"500\" makeModel=\"P&amp;H\"<\/pre>\n<p>You\u2019ll be denied!<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">HTTP\/1.1 403 Forbidden\nCache-Control: no-cache, no-store, max-age=0, must-revalidate\nExpires: 0\n...<\/pre>\n<p>Now, log out of developer.okta.com, and generate a new token using the&nbsp;<a href=\"https:\/\/oidcdebugger.com\/\">OIDC Debugger<\/a>. This time log back in with your original, admin account.<\/p>\n<p>Store the new token in the shell variable&nbsp;<code class=\"highlighter-rouge\" style=\"font-size: 13px;\">TOKEN<\/code>.<\/p>\n<p>Run the POST request:<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:bash\">http POST :8080\/kayaks \"Authorization: Bearer $TOKEN\" name=\"sea2\" owner=\"Andrew\" value=\"500\" makeModel=\"P&amp;H\"<\/pre>\n<p>BAM! \ud83d\udca5<\/p>\n<pre class=\"wp-block-preformatted gutter: false;brush:js\">HTTP\/1.1 200 OK\nCache-Control: no-cache, no-store, max-age=0, must-revalidate\n...\n{\n    \"makeModel\": \"P&amp;H\",\n    \"name\": \"sea2\",\n    \"owner\": \"Andrew\",\n    \"value\": 500\n}\n<\/pre>\n<h2 class=\"wp-block-heading\" id=\"alls-well-that-ends-authenticated\">All\u2019s Well that Ends Authenticated<\/h2>\n<p>That\u2019s it! In this tutorial, you created a Spring Boot application with Spring WebFlux, used an embedded MongoDB database for persisting model classes, and added a resource server to it. After that, I showed you how to add JWT token authentication using Okta and OAuth 2.0. Finally, you saw how to use Okta and Spring Security to add group-based authorization to specific endpoints in a controller.<\/p>\n<p>If you\u2019d like to check out this complete project, you can find the repo on GitHub at&nbsp;<a href=\"https:\/\/github.com\/oktadeveloper\/okta-spring-boot-mongo-webflux-example\">oktadeveloper\/okta-spring-boot-mongo-webflux-example<\/a>.<\/p>\n<p>If you haven\u2019t already, check out Part 1 of this series:&nbsp;<a href=\"https:\/\/developer.okta.com\/blog\/2018\/12\/13\/build-basic-app-spring-boot-jpa?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Build a Basic App with Spring Boot and JPA using PostgreSQL<\/a>. It\u2019s the same app, but using a more traditional relational database and Spring MVC-style blocking web server.<\/p>\n<h2 class=\"wp-block-heading\" id=\"learn-more-about-spring-boot-mongodb-and-secure-user-management\">Learn More About Spring Boot, MongoDB, and Secure User Management<\/h2>\n<p>If you\u2019d like to learn more about Spring Boot, Spring Security, or Okta, check out any of these great tutorials:<\/p>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/09\/24\/reactive-apis-with-spring-webflux?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Build Reactive APIs with Spring WebFlux<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2017\/03\/21\/spring-boot-oauth?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Get Started with Spring Boot, OAuth 2.0, and Okta<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2017\/11\/20\/add-sso-spring-boot-15-min?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Add Single Sign-On to Your Spring Boot Web App in 15 Minutes<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/06\/12\/mfa-in-spring-boot?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Secure Your Spring Boot Application with Multi-Factor Authentication<\/a><\/li>\n<li><a href=\"https:\/\/developer.okta.com\/blog\/2018\/08\/16\/secure-api-spring-boot-graphql?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Build a Secure API with Spring Boot and GraphQL<\/a><\/li>\n<\/ul>\n<p>Here are some excellent resources from Spring:<\/p>\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/spring.io\/blog\/2016\/11\/28\/going-reactive-with-spring-data\">Going reactive with Spring Data<\/a><\/li>\n<li><a href=\"https:\/\/docs.spring.io\/spring-security\/site\/docs\/current\/reference\/html\/webflux-oauth2.html\">OAuth2 WebFlux Documentation<\/a><\/li>\n<li><a href=\"https:\/\/spring.io\/guides\/gs\/reactive-rest-service\/\">Building a Reactive RESTful Web Service<\/a><\/li>\n<li><a href=\"https:\/\/docs.spring.io\/spring\/docs\/current\/spring-framework-reference\/web-reactive.html#webflux\">Spring WebFlux Documentation<\/a><\/li>\n<\/ul>\n<p>If you liked this post, chances are you\u2019ll like others we publish. Follow&nbsp;<a href=\"https:\/\/twitter.com\/oktadev\">@oktadev<\/a>&nbsp;on Twitter and subscribe to&nbsp;<a href=\"https:\/\/www.youtube.com\/channel\/UC5AMiWqFVFxF1q9Ya1FuZ_Q\">our YouTube channel<\/a>&nbsp;for more interesting tutorials.<\/p>\n<p><a href=\"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">&#8220;Build a Reactive App with Spring Boot and MongoDB&#8221;<\/a>&nbsp;was originally published on the Okta developer blog on February 21, 2019.<\/p>\n<p><span style=\"font-size: 20px;\"><b>\u201cI love writing authentication and authorization code.\u201d ~ No Java Developer Ever.<\/b> Tired of building the same login screens over and over? <a href=\"https:\/\/developer.okta.com\/signup\/?utm_campaign=text_website_all_multiple_dev_ciam_reactive-spring-boot-app-03-19_null&amp;utm_source=jcg&amp;utm_medium=cpc\">Try the Okta API for hosted authentication, authorization, and multi-factor auth.<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u201cI love writing authentication and authorization code.\u201d ~ No Java Developer Ever. Tired of building the same login screens over and over? Try the Okta API for hosted authentication, authorization, and multi-factor auth. Reactive apps allow you to scale better if you\u2019re dealing with lots of streaming data. They\u2019re non-blocking and tend to be more &hellip;<\/p>\n","protected":false},"author":49514,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[112,30,854],"class_list":["post-89011","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-mongodb","tag-spring","tag-spring-boot"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Build a Reactive App with Spring Boot and MongoDB - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Interested to learn about Reactive App? Check our article explaining how you can build Build a Reactive App with Spring Boot and MongoDB.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build a Reactive App with Spring Boot and MongoDB - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Interested to learn about Reactive App? Check our article explaining how you can build Build a Reactive App with Spring Boot and MongoDB.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2019-03-04T07:00:32+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-03-11T07:24:51+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Andrew Hughes\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrew Hughes\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/21\\\/reactive-with-spring-boot-mongodb#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/build-reactive-app-spring-boot-mongodb.html\"},\"author\":{\"name\":\"Andrew Hughes\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/0ded99ab51010abb68790f6189ce99d3\"},\"headline\":\"Build a Reactive App with Spring Boot and MongoDB\",\"datePublished\":\"2019-03-04T07:00:32+00:00\",\"dateModified\":\"2019-03-11T07:24:51+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/build-reactive-app-spring-boot-mongodb.html\"},\"wordCount\":3247,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/21\\\/reactive-with-spring-boot-mongodb#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"MongoDB\",\"Spring\",\"Spring Boot\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/21\\\/reactive-with-spring-boot-mongodb#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2019\\\/03\\\/build-reactive-app-spring-boot-mongodb.html\",\"url\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/21\\\/reactive-with-spring-boot-mongodb\",\"name\":\"Build a Reactive App with Spring Boot and MongoDB - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/21\\\/reactive-with-spring-boot-mongodb#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/21\\\/reactive-with-spring-boot-mongodb#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2019-03-04T07:00:32+00:00\",\"dateModified\":\"2019-03-11T07:24:51+00:00\",\"description\":\"Interested to learn about Reactive App? Check our article explaining how you can build Build a Reactive App with Spring Boot and MongoDB.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/21\\\/reactive-with-spring-boot-mongodb#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/21\\\/reactive-with-spring-boot-mongodb\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/21\\\/reactive-with-spring-boot-mongodb#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/developer.okta.com\\\/blog\\\/2019\\\/02\\\/21\\\/reactive-with-spring-boot-mongodb#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Build a Reactive App with Spring Boot and MongoDB\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/0ded99ab51010abb68790f6189ce99d3\",\"name\":\"Andrew Hughes\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g\",\"caption\":\"Andrew Hughes\"},\"sameAs\":[\"https:\\\/\\\/developer.okta.com\\\/blog\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/andrew-hughes\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Build a Reactive App with Spring Boot and MongoDB - Java Code Geeks","description":"Interested to learn about Reactive App? Check our article explaining how you can build Build a Reactive App with Spring Boot and MongoDB.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb","og_locale":"en_US","og_type":"article","og_title":"Build a Reactive App with Spring Boot and MongoDB - Java Code Geeks","og_description":"Interested to learn about Reactive App? Check our article explaining how you can build Build a Reactive App with Spring Boot and MongoDB.","og_url":"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2019-03-04T07:00:32+00:00","article_modified_time":"2019-03-11T07:24:51+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Andrew Hughes","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Andrew Hughes","Est. reading time":"19 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/build-reactive-app-spring-boot-mongodb.html"},"author":{"name":"Andrew Hughes","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/0ded99ab51010abb68790f6189ce99d3"},"headline":"Build a Reactive App with Spring Boot and MongoDB","datePublished":"2019-03-04T07:00:32+00:00","dateModified":"2019-03-11T07:24:51+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/build-reactive-app-spring-boot-mongodb.html"},"wordCount":3247,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["MongoDB","Spring","Spring Boot"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2019\/03\/build-reactive-app-spring-boot-mongodb.html","url":"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb","name":"Build a Reactive App with Spring Boot and MongoDB - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb#primaryimage"},"image":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2019-03-04T07:00:32+00:00","dateModified":"2019-03-11T07:24:51+00:00","description":"Interested to learn about Reactive App? Check our article explaining how you can build Build a Reactive App with Spring Boot and MongoDB.","breadcrumb":{"@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/developer.okta.com\/blog\/2019\/02\/21\/reactive-with-spring-boot-mongodb#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Build a Reactive App with Spring Boot and MongoDB"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/0ded99ab51010abb68790f6189ce99d3","name":"Andrew Hughes","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/703689ecb161268c8a6ca8ad4057b8342d22972ec435111a055712b399716dbd?s=96&d=mm&r=g","caption":"Andrew Hughes"},"sameAs":["https:\/\/developer.okta.com\/blog"],"url":"https:\/\/www.javacodegeeks.com\/author\/andrew-hughes"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/89011","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/49514"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=89011"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/89011\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=89011"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=89011"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=89011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}