{"id":715,"date":"2016-07-05T11:24:12","date_gmt":"2016-07-05T11:24:12","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/"},"modified":"2016-07-05T11:24:12","modified_gmt":"2016-07-05T11:24:12","slug":"give-some-ratpack-love-to-your-spring-boot-application","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/ko\/give-some-ratpack-love-to-your-spring-boot-application\/","title":{"rendered":"Give some Ratpack Love to your Spring Boot Application"},"content":{"rendered":"<p>I recently started working with Ratpack and I quite like it. I mostly did quick projects from scratch. But I would like to use it in an existing Spring Boot application to replace the traditional MVC part. This is actually easy to do as everything has been thought out already thanks to their <a href=\"https:\/\/ratpack.io\/manual\/current\/spring.html\">Spring module<\/a>.<\/p>\n\n\n\n<p>If you follow this blog you might remember an old post about <a href=\"https:\/\/www.couchbase.com\/blog\/ko\/storing-indexing-searching-files-couchbase-spring-boot\/\">storing, indexing and searching<\/a> files with <a href=\"https:\/\/developer.couchbase.com\/?utm_source=blogs&amp;utm_medium=link&amp;utm_campaign=blogs\">Couchbase<\/a> and Spring Boot. I will use the <a href=\"https:\/\/github.com\/ldoguin\/store-search-files\">related code<\/a> as an example. The idea is to replace Spring MVC by Ratpack, and making my legacy, synchronous, blocking services async and non blocking. The resulting code is available on <a href=\"https:\/\/github.com\/ldoguin\/store-search-files\">github<\/a> as well.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Adding the Right Dependencies<\/h2>\n\n\n\n<p>I am using Gradle. Ratpack is very well integrated with it. All you need to do to add a module is to add the right dependency by calling <code>ratpack.dependency(\"myFavoriteModule\")<\/code>. So in our case, to add support for Spring Boot, you\u00a0need to add <code>ratpack.dependency(\"spring-boot\")<\/code>. Unfortunately\u00a0the version automatically managed by Ratpack is less than 1.4.0.M3, which is the version that brings automatic Couchbase configuration. So this time I will have to add dependencies manually.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    dependencies {\r\n      compile ratpack.dependency(&quot;guice&quot;),\r\n              ratpack.dependency(&quot;rx&quot;),\r\n              ratpack.dependency(&quot;handlebars&quot;),\r\n              &quot;com.couchbase.client:java-client:2.3.1&quot;,\r\n              &quot;org.springframework.boot:spring-boot-autoconfigure:1.4.0.M3&quot;,\r\n              &quot;io.ratpack:ratpack-spring-boot:1.3.3&quot;,\r\n              &quot;org.slf4j:slf4j-simple:1.7.12&quot;,\r\n              &quot;org.codehaus.plexus:plexus-utils:3.0.21&quot;,\r\n              &quot;commons-codec:commons-codec:1.10&quot; \r\n    }\r\n<\/code><\/pre>\n\n\n\n<p>What you can see here is that <code>ratpack.dependency(\"spring-boot\")<\/code> is a shortcut to add <code>org.springframework.boot:spring-boot-autoconfigure:1.4.0.M3<\/code> and <code>io.ratpack:ratpack-spring-boot:1.3.3<\/code>. What this module gives you is the ability to integrate a Ratpack server to your Spring Application. You will be able to retrieve Spring @Beans from the Ratpack context and declare handlers as Spring configuration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Declare Ratpack Configuration<\/h2>\n\n\n\n<p>One thing you have to love with Spring Boot is the autoconfig. You only need to make sure the Couchbase SDK is in the classpath, and that the property <code>spring.couchbase.bootstrap-hosts<\/code> is declared. At that moment Spring beans will be instantiated for a default Bucket. And this bucket instance will be available as a bean or in Ratpack&#8217;s context. So you don&#8217;t have to declare any binding for Couchbase in the Ratpack layer.<\/p>\n\n\n\n<p>The first thing you traditionaly do with Ratpack is start a server and define the configuration and handlers. Here we already have a Spring Boot Application running. Every classes annotated with @Configuration will be picked up automatically and added to the application configuration. The first step to declare that configuration is create a Class that implements <em>RatpackServerCustomizer<\/em> and annotate it with @Confguration. It let\u00a0you define a list of handlers, bindings and server configuration. In the Following example I am registering some server properties and binding several classes to Ratpack&#8217;s context. The &#8216;server.maxContentLength&#8217; property is the maximum size of file you can upload.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    package org.couchbase.devex;\r\n\r\n    import java.util.ArrayList;\r\n    import java.util.Collections;\r\n    import java.util.List;\r\n    import java.util.Map;\r\n\r\n    import org.couchbase.devex.domain.StoredFileRenderer;\r\n    import org.couchbase.devex.service.SearchService;\r\n    import org.springframework.context.annotation.Configuration;\r\n\r\n    import com.google.common.collect.ImmutableMap;\r\n\r\n    import ratpack.form.Form;\r\n    import ratpack.func.Action;\r\n    import ratpack.guice.BindingsSpec;\r\n    import ratpack.handlebars.HandlebarsModule;\r\n    import ratpack.handlebars.Template;\r\n    import ratpack.handling.Chain;\r\n    import ratpack.rx.RxRatpack;\r\n    import ratpack.server.BaseDir;\r\n    import ratpack.server.ServerConfigBuilder;\r\n    import ratpack.spring.config.RatpackServerCustomizer;\r\n    import rx.Observable;\r\n\r\n    @Configuration\r\n    public class RatpackConfiguration implements RatpackServerCustomizer {\r\n\r\n        @Override\r\n        public List&lt;action&gt; getHandlers() {\r\n            List&lt;action&gt; handlers = new ArrayList&lt;action&gt;();\r\n            handlers.add(fileApi());\r\n            return handlers;\r\n        }\r\n\r\n        @Override\r\n        public Action getServerConfig() {\r\n            return config -&gt; config.baseDir(BaseDir.find())\r\n                    .props(ImmutableMap.of(&quot;server.maxContentLength&quot;, &quot;100000000&quot;, &quot;app.name&quot;, &quot;Search Store File&quot;));\r\n\r\n        }\r\n\r\n        @Override\r\n        public Action getBindings() {\r\n            return bindingConfig -&gt; bindingConfig.module(HandlebarsModule.class).bind(FileHandler.class)\r\n                    .bind(StoredFileRenderer.class).bind(ErrorHandlerImpl.class).bind(ClientHandlerImpl.class);\r\n        }\r\n\r\n        private Action fileApi() {\r\n            return chain -&gt; chain.prefix(&quot;file&quot;, FileHandler.class).post(&quot;fulltext&quot;, ctx -&gt; {\r\n                ctx.parse(Form.class).then(form -&gt; {\r\n                    String queryString = form.get(&quot;queryString&quot;);\r\n                    SearchService searchService = ctx.get(SearchService.class);\r\n                    Observable&lt;map&lt;string, object=&quot;&quot;&gt;&gt; files = searchService.searchFulltextFiles(queryString);\r\n                    RxRatpack.promise(files).then(response -&gt; ctx\r\n                            .render(Template.handlebarsTemplate(&quot;uploadForm&quot;, &quot;text\/html&quot;, m -&gt; m.put(&quot;files&quot;, response))));\r\n                });\r\n            }).post(&quot;n1ql&quot;, ctx -&gt; {\r\n                ctx.parse(Form.class).then(form -&gt; {\r\n                    String queryString = form.get(&quot;queryString&quot;);\r\n                    SearchService searchService = ctx.get(SearchService.class);\r\n                    Observable&lt;map&lt;string, object=&quot;&quot;&gt;&gt; files = searchService.searchN1QLFiles(queryString);\r\n                    RxRatpack.promise(files).then(response -&gt; ctx\r\n                            .render(Template.handlebarsTemplate(&quot;uploadForm&quot;, &quot;text\/html&quot;, m -&gt; m.put(&quot;files&quot;, response))));\r\n                });\r\n            });\r\n        }\r\n    }\r\n&lt;\/map&lt;string,&gt;&lt;\/map&lt;string,&gt;&lt;\/action&lt;\/action&lt;\/action<\/code><\/pre>\n\n\n\n<p>The application templating system relies on Handlebars so you need the HandlebarsModule. FileHandler will handle all the call to the &#8216;\/file&#8217; API and the StoredFileRenderer make sure StoredFile will be rendered correctly. The last two bindings are for error managements.<\/p>\n\n\n\n<p>The most imortant thing going on here is the <code>fileAPI<\/code> method that declares my handler. A handler defines what&#8217;s going on when a user hits a particular URL. Here we associate every &#8216;\/file\/*&#8217; call to the FileHandler class. We also define the behavior for POST on &#8216;\/fulltext&#8217; and &#8216;\/n1ql&#8217;.<\/p>\n\n\n\n<p>Ratpack uses promises. So when you parse a Form coming from a POST request, you&#8217;ll get a promise. What you can see in each of those POST is that the SearchService is fetched from Ratpack&#8217;s context. Even if it was never binded in the configuration. That&#8217;s because Spring beans are available in the context as part of the integration.<\/p>\n\n\n\n<p>The next step is to call that search service which returns an Observable. We can use Ratpack&#8217;s rx-java module that provides a wrapper for Observables. It will wrap this as a promise. Then you can simply render the response.<\/p>\n\n\n\n<p>At this point we got rid of all the Spring MVC <a href=\"https:\/\/github.com\/ldoguin\/store-search-files\/blob\/master\/src\/main\/java\/org\/couchbase\/devex\/controller\/IndexController.java\">controllers<\/a>. As you can see my service return an Observable. Which is not the case in my previous application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Migrating Services for Ratpack<\/h2>\n\n\n\n<p>Most of my services relies on Couchbase. The SDK is based on RxJava so it&#8217;s really easy to convert most of those to an async, non-blocking fashion and have them returns Observable.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Using RxJava<\/h3>\n\n\n\n<p>This is a very simple example. It&#8217;s a N1QL query that maps the results to a List of Map. The two first lines don&#8217;t change at all as they are mostly defining the query. You can see that the mapping feels more natural when using the synchronous bucket in the second version.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    public List&lt;map&lt;string, object=&quot;&quot;&gt;&gt; searchN1QLFiles(String whereClause) {\r\n        N1qlQuery query = N1qlQuery.simple(\r\n                &quot;SELECT binaryStoreLocation, binaryStoreDigest FROM `default` WHERE type= &#039;file&#039; &quot; + whereClause);\r\n        query.params().consistency(ScanConsistency.STATEMENT_PLUS);\r\n        N1qlQueryResult res = bucket.query(query);\r\n        List&lt;map&lt;string, object=&quot;&quot;&gt;&gt; filenames = res.allRows().stream().map(row -&gt; row.value().toMap())\r\n                .collect(Collectors.toList());\r\n        return filenames;\r\n    }\r\n&lt;\/map&lt;string,&gt;&lt;\/map&lt;string,&gt;<\/code><\/pre>\n\n\n\n<p>Becomes<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    public Observable&lt;map&lt;string, object=&quot;&quot;&gt;&gt; searchN1QLFiles(String whereClause) {\r\n        N1qlQuery query = N1qlQuery.simple(\r\n                &quot;SELECT binaryStoreLocation, binaryStoreDigest FROM `default` WHERE type= &#039;file&#039; &quot; + whereClause);\r\n        query.params().consistency(ScanConsistency.STATEMENT_PLUS);\r\n        return bucket.async().query(query).flatMap(AsyncN1qlQueryResult::rows).map(r -&gt; r.value().toMap());\r\n    }\r\n&lt;\/map&lt;string,&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">What about Blocking Legacy Code?<\/h3>\n\n\n\n<p>Some of my services relies on old, blocking code. While there is no magical way to make them non-blocking, we can easily wrap them in a Promise. This will allow us use them easily in the Handlers. Wrapping blocking call is super easy, all you need to do is wrap your function with &#8216;Blocking.get()&#8217;. Here&#8217;s a very simple example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    public String getSha1Digest(InputStream is) {\r\n        return DigestUtils.sha1Hex(is);\r\n    }\r\n<\/code><\/pre>\n\n\n\n<p>becomes<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    public Promise getSha1Digest(InputStream is) {\r\n        return Blocking.get(() -&gt; DigestUtils.sha1Hex(is));\r\n    }\r\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Now you know pretty much everything you need to know to give some Ratpack Love to your Spring Boot application. If you feel like anything is missing please reach out to me on <a href=\"https:\/\/twitter.com\/ldoguin\">twitter<\/a> or in the comments below.<\/p>","protected":false},"excerpt":{"rendered":"<p>I recently started working with Ratpack and I quite like it. I mostly did quick projects from scratch. But I would like to use it in an existing Spring Boot application to replace the traditional MVC part. This is actually easy to do as everything has been thought out already thanks to their Spring module. [&hellip;]<\/p>\n","protected":false},"author":49,"featured_media":18,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[136,144],"tags":[],"ppma_author":[110],"class_list":["post-715","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-best-practices-and-tutorials","category-java"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.6 (Yoast SEO v27.6) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Get start working with Ratpack - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"The idea used here in the post is to replace Spring MVC by Ratpack, and making my legacy, synchronous, blocking services async and non blocking.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/ko\/give-some-ratpack-love-to-your-spring-boot-application\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Give some Ratpack Love to your Spring Boot Application\" \/>\n<meta property=\"og:description\" content=\"The idea used here in the post is to replace Spring MVC by Ratpack, and making my legacy, synchronous, blocking services async and non blocking.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/ko\/give-some-ratpack-love-to-your-spring-boot-application\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2016-07-05T11:24:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Laurent Doguin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ldoguin\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Laurent Doguin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/\"},\"author\":{\"name\":\"Laurent Doguin\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/c0aa9b8f1ed51b7a9e2f7cb755994a5e\"},\"headline\":\"Give some Ratpack Love to your Spring Boot Application\",\"datePublished\":\"2016-07-05T11:24:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/\"},\"wordCount\":853,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Best Practices and Tutorials\",\"Java\"],\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/\",\"name\":\"Get start working with Ratpack - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2016-07-05T11:24:12+00:00\",\"description\":\"The idea used here in the post is to replace Spring MVC by Ratpack, and making my legacy, synchronous, blocking services async and non blocking.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/give-some-ratpack-love-to-your-spring-boot-application\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Give some Ratpack Love to your Spring Boot Application\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ko-KR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/06\\\/logo.svg\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/06\\\/logo.svg\",\"width\":\"1024\",\"height\":\"1024\",\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/c0aa9b8f1ed51b7a9e2f7cb755994a5e\",\"name\":\"Laurent Doguin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b8c466908092b46634af916b6921f30187a051e4367ded7ac9b1a3f2c5692fd2?s=96&d=mm&r=g12929ce99397769f362b7a90d6b85071\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b8c466908092b46634af916b6921f30187a051e4367ded7ac9b1a3f2c5692fd2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/b8c466908092b46634af916b6921f30187a051e4367ded7ac9b1a3f2c5692fd2?s=96&d=mm&r=g\",\"caption\":\"Laurent Doguin\"},\"description\":\"Laurent is a nerdy metal head who lives in Paris. He mostly writes code in Java and structured text in AsciiDoc, and often talks about data, reactive programming and other buzzwordy stuff. He is also a former Developer Advocate for Clever Cloud and Nuxeo where he devoted his time and expertise to helping those communities grow bigger and stronger. He now runs Developer Relations at Couchbase.\",\"sameAs\":[\"https:\\\/\\\/x.com\\\/ldoguin\"],\"honorificPrefix\":\"Mr\",\"birthDate\":\"1985-06-07\",\"gender\":\"male\",\"award\":[\"Devoxx Champion\",\"Couchbase Legend\"],\"knowsAbout\":[\"Java\"],\"knowsLanguage\":[\"English\",\"French\"],\"jobTitle\":\"Director Developer Relation & Strategy\",\"worksFor\":\"Couchbase\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/ko\\\/author\\\/laurent-doguin\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Get start working with Ratpack - The Couchbase Blog","description":"The idea used here in the post is to replace Spring MVC by Ratpack, and making my legacy, synchronous, blocking services async and non blocking.","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:\/\/www.couchbase.com\/blog\/ko\/give-some-ratpack-love-to-your-spring-boot-application\/","og_locale":"ko_KR","og_type":"article","og_title":"Give some Ratpack Love to your Spring Boot Application","og_description":"The idea used here in the post is to replace Spring MVC by Ratpack, and making my legacy, synchronous, blocking services async and non blocking.","og_url":"https:\/\/www.couchbase.com\/blog\/ko\/give-some-ratpack-love-to-your-spring-boot-application\/","og_site_name":"The Couchbase Blog","article_published_time":"2016-07-05T11:24:12+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"Laurent Doguin","twitter_card":"summary_large_image","twitter_creator":"@ldoguin","twitter_misc":{"Written by":"Laurent Doguin","Est. reading time":"7\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/"},"author":{"name":"Laurent Doguin","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c0aa9b8f1ed51b7a9e2f7cb755994a5e"},"headline":"Give some Ratpack Love to your Spring Boot Application","datePublished":"2016-07-05T11:24:12+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/"},"wordCount":853,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","articleSection":["Best Practices and Tutorials","Java"],"inLanguage":"ko-KR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/","url":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/","name":"Get start working with Ratpack - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","datePublished":"2016-07-05T11:24:12+00:00","description":"The idea used here in the post is to replace Spring MVC by Ratpack, and making my legacy, synchronous, blocking services async and non blocking.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/"]}]},{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/give-some-ratpack-love-to-your-spring-boot-application\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Give some Ratpack Love to your Spring Boot Application"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ko-KR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/06\/logo.svg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/06\/logo.svg","width":"1024","height":"1024","caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c0aa9b8f1ed51b7a9e2f7cb755994a5e","name":"Laurent Doguin","image":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/secure.gravatar.com\/avatar\/b8c466908092b46634af916b6921f30187a051e4367ded7ac9b1a3f2c5692fd2?s=96&d=mm&r=g12929ce99397769f362b7a90d6b85071","url":"https:\/\/secure.gravatar.com\/avatar\/b8c466908092b46634af916b6921f30187a051e4367ded7ac9b1a3f2c5692fd2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b8c466908092b46634af916b6921f30187a051e4367ded7ac9b1a3f2c5692fd2?s=96&d=mm&r=g","caption":"Laurent Doguin"},"description":"Laurent is a nerdy metal head who lives in Paris. He mostly writes code in Java and structured text in AsciiDoc, and often talks about data, reactive programming and other buzzwordy stuff. He is also a former Developer Advocate for Clever Cloud and Nuxeo where he devoted his time and expertise to helping those communities grow bigger and stronger. He now runs Developer Relations at Couchbase.","sameAs":["https:\/\/x.com\/ldoguin"],"honorificPrefix":"Mr","birthDate":"1985-06-07","gender":"male","award":["Devoxx Champion","Couchbase Legend"],"knowsAbout":["Java"],"knowsLanguage":["English","French"],"jobTitle":"Director Developer Relation & Strategy","worksFor":"Couchbase","url":"https:\/\/www.couchbase.com\/blog\/ko\/author\/laurent-doguin\/"}]}},"acf":[],"authors":[{"term_id":110,"user_id":49,"is_guest":0,"slug":"laurent-doguin","display_name":"Laurent Doguin","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/b8c466908092b46634af916b6921f30187a051e4367ded7ac9b1a3f2c5692fd2?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/715","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/users\/49"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/comments?post=715"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/715\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media\/18"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media?parent=715"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/categories?post=715"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/tags?post=715"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/ppma_author?post=715"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}