{"id":7284,"date":"2021-04-21T06:35:23","date_gmt":"2021-04-21T06:35:23","guid":{"rendered":"https:\/\/berg-software.com\/?p=7284"},"modified":"2022-07-20T11:17:18","modified_gmt":"2022-07-20T11:17:18","slug":"async-processes-in-rest-applications-with-java-spring","status":"publish","type":"post","link":"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/","title":{"rendered":"Take advantage of async processes in REST Applications with Java Spring"},"content":{"rendered":"<p>[et_pb_section fb_built=&#8221;1&#8243; fullwidth=&#8221;on&#8221; _builder_version=&#8221;4.4.1&#8243;][et_pb_fullwidth_post_title meta=&#8221;off&#8221; featured_placement=&#8221;background&#8221; _builder_version=&#8221;4.7.7&#8243; title_font=&#8221;||||||||&#8221; title_text_color=&#8221;#ff6317&#8243; title_font_size=&#8221;3.5em&#8221; meta_font=&#8221;|300|||||||&#8221; meta_text_color=&#8221;#ffffff&#8221; meta_font_size=&#8221;1em&#8221; background_enable_color=&#8221;off&#8221; use_background_color_gradient=&#8221;on&#8221; background_color_gradient_start=&#8221;rgba(248,248,248,0.85)&#8221; background_color_gradient_end=&#8221;rgba(248,248,248,0.75)&#8221; background_color_gradient_overlays_image=&#8221;on&#8221; min_height=&#8221;20vh&#8221; height=&#8221;400px&#8221; custom_padding=&#8221;6vh||6vh||false|false&#8221; global_module=&#8221;403&#8243; locked=&#8221;off&#8221;][\/et_pb_fullwidth_post_title][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; admin_label=&#8221;intro&#8221; _builder_version=&#8221;4.4.6&#8243; custom_padding=&#8221;|||0px||&#8221; locked=&#8221;off&#8221;][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.4.6&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; hover_enabled=&#8221;0&#8243; border_color_left=&#8221;#ff6317&#8243; sticky_enabled=&#8221;0&#8243;]<\/p>\n<p>In this article, we will show you how to take advantage of async processes in REST applications with Java Spring.\u00a0In a <a title=\"Go to Berg Software article: Software development\/management\" href=\"https:\/\/berg-software.com\/insights\/digitalisation-how-to-software-product-development-management-3-5\/\" target=\"_blank\" rel=\"noopener\">previous article<\/a>, we discussed how important it is for the <a href=\"https:\/\/www.berg-software.com\/\">software development<\/a> team to understand a software solution\/product\u2019s business logic, and its target functions and features. The main results are a hard focus on what matters most from a business perspective; less reworking; and clean release plans.<\/p>\n<p>But understanding a <a href=\"https:\/\/arobs.com\/\">software solution<\/a>\/product\u2019s goals can also influence some of the small details \u2013 for example, what happens when the user clicks a button or link. In the most straightforward scenario, the desired action is executed, and the result is reached\/displayed right away (i.e., following a synchronous process). In other cases, the user might need to wait for a result and have parts of the interface temporarily inaccessible\/disabled (i.e., during an async process).<\/p>\n<p>The wait\/no-wait cases are decided by the product owner and implemented by the software development team as mutually exclusive sync\/async processes:<\/p>\n<ul>\n<li><strong>Synchronous processes<\/strong> allow the user to wait for the result, then have it displayed. Once launched (e.g., by a click), the process cannot be interrupted.<\/li>\n<li><strong>Asynchronous processes<\/strong> can be launched either by the user or by an automated scheduler, as \u201cfire and forget\u201d: the action is launched but you don\u2019t wait (or care) for it to be executed and for the result to be displayed. Sometimes, a starting message is displayed, and the status can be checked during execution.<\/li>\n<\/ul>\n<p>Async processes can be used\/implemented in many different ways. We look into five concrete situations:<\/p>\n<ul>\n<li><a title=\"See on this page: 1. Sending a notification email at the end of a user operation\" href=\"#Sendinganotificationemailattheendofauseroperation\">Sending a notification email at the end of a user operation where other users are also involved<\/a><\/li>\n<li><a title=\"See on this page: 2. Uploading multiple documents with cancellation feature\" href=\"#Uploadingmultipledocumentswithcancellationfeature\">Uploading multiple documents with the cancellation feature<\/a><\/li>\n<li><a title=\"See on this page: 3. Complex backend calculations requested by a user action\" href=\"#Complexbackendcalculationsrequestedbyauseraction\">Doing some complex calculations in the backend requested by a user action<\/a><\/li>\n<li><a title=\"See on this page: 4. Automatically scheduled system actions\" href=\"#Automaticallyscheduledsystemactions\">Having some automatically scheduled system actions<\/a><\/li>\n<li><a title=\"See on this page: 5. Importing big data from an external system\" href=\"#Importingbigdatafromanexternalsystemintoourapplication\">Importing big data from an external system into our application<\/a><\/li>\n<\/ul>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; hover_enabled=&#8221;0&#8243; border_color_left=&#8221;#ff6317&#8243; sticky_enabled=&#8221;0&#8243;]<\/p>\n<h2 id=\"Sendinganotificationemailattheendofauseroperation\">1. Sending a notification email at the end of a user operation where other users are also involved<\/h2>\n<p>Some of the users will do operations that involve other users as well \u2013 for example, leaving a comment on an item created by somebody else. In this case, we want to save the comment in the backend and notify the item\u2019s author about the new comment. Therefore, when the user clicks on \u201csave comment\u201d, the single backend call will do 2 things: save the actual comment and send an email to the item creator.<\/p>\n<p>Saving the actual comment is done instantly, as the requesting user needs the feedback that it was saved. But sending the email is not something that concerns the requesting user, so the backend will trigger an async process, without waiting for the actual result. This means a faster response time for the users and not bothering them with error messages if something goes wrong while sending the email.<\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;20px||0px||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_gallery gallery_ids=&#8221;7291&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221;][\/et_pb_gallery][et_pb_code _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221;][\/et_pb_code][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;20px||0px||false|true&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Here is a code example for a backend flow, in the service that handles the comment saving:[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;20px|||20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"java\" style=\"font-family: monospace;\"><span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000000; font-weight: bold;\">class<\/span> CommentService <span style=\"color: #009900;\">{<\/span>\n\u00a0\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> saveComment<span style=\"color: #009900;\">(<\/span><span style=\"color: #003399;\">String<\/span> id, CommentRequest comment<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\u00a0\n\t\tItem item <span style=\"color: #339933;\">=<\/span> itemService.<span style=\"color: #006633;\">getItem<\/span><span style=\"color: #009900;\">(<\/span>id<span style=\"color: #009900;\">)<\/span>.<span style=\"color: #006633;\">orElseThrow<\/span><span style=\"color: #009900;\">(<\/span>ItemNotFoundException<span style=\"color: #339933;\">::<\/span><span style=\"color: #000000; font-weight: bold;\">new<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t\tUser userToNotify <span style=\"color: #339933;\">=<\/span> userService.<span style=\"color: #006633;\">get<\/span><span style=\"color: #009900;\">(<\/span>item.<span style=\"color: #006633;\">getCreator<\/span><span style=\"color: #009900;\">)<\/span>.<span style=\"color: #006633;\">orElseThrow<\/span><span style=\"color: #009900;\">(<\/span>UserNotFoundException<span style=\"color: #339933;\">::<\/span><span style=\"color: #000000; font-weight: bold;\">new<\/span><span style=\"color: #009900;\">)<\/span>\n\u00a0\n\t\tcommentService.<span style=\"color: #006633;\">save<\/span><span style=\"color: #009900;\">(<\/span>comment<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t\tmailService.<span style=\"color: #006633;\">sendCommentSavedNotification<\/span><span style=\"color: #009900;\">(<\/span>userToNotify, comment<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t<span style=\"color: #009900;\">}<\/span>\n<span style=\"color: #009900;\">}<\/span>\n\u00a0\n\u00a0\n<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000000; font-weight: bold;\">class<\/span> EmailService <span style=\"color: #009900;\">{<\/span>\n\u00a0\n\t@Async\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> sendCommentSavedNotification<span style=\"color: #009900;\">(<\/span>User userToNotify, Item item<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\u00a0\n\t\tMimeMessageHelper mimeMessage <span style=\"color: #339933;\">=<\/span> <span style=\"color: #666666; font-style: italic;\">\/\/prepare your email content here<\/span>\n\t\tjavaMailSender.<span style=\"color: #006633;\">send<\/span><span style=\"color: #009900;\">(<\/span>mimeMessage<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t<span style=\"color: #009900;\">}<\/span>\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]You can see that <em>mailService.sendCommentSavedNotification(\u2026)<\/em> looks just like a normal method call. But because of the @Async annotation on the actual method implementation, Spring comes in and does something behind the scenes: it uses a <em>ThreadExecutor<\/em> to spawn a new thread. (The actual execution of this method will happen on that new thread.) Therefore, the call <em>mailService.sendCommentSavedNotification<\/em> will return instantly. The thread executor, if not defined explicitly in the application, will be the Spring default one (<em>SimpleAsyncTaskExecutor<\/em>) and the only thing that you need to do is enable it in a configuration file like this:[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;20px|||20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"java\" style=\"font-family: monospace;\">@Configuration\n@EnableAsync\n<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000000; font-weight: bold;\">class<\/span> AsyncConfiguration <span style=\"color: #000000; font-weight: bold;\">implements<\/span> AsyncConfigurer <span style=\"color: #009900;\">{<\/span><span style=\"color: #666666; font-style: italic;\">\/\/no special body needed yet}<\/span><\/pre>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"Uploadingmultipledocumentswithcancellationfeature\">2. Uploading multiple documents with the cancellation feature<\/h2>\n<p>Another usage case is uploading multiple documents at once, in order to attach them to an item. The documents might reside on a third-party server, which means uploading can take some time to complete. While waiting, the user can see a loading bar, and be able to cancel the action.<\/p>\n<p>How does this work?<\/p>\n<p>The frontend sends the documents to the backend and receives a process ID. With this process ID, the frontend can cancel the document uploading at any time (upon the user clicking the Cancel button) by doing a cancel call and passing the process ID.<\/p>\n<p>This can only happen because the document uploading is asynchronous in the backend, and the backend can return the process ID before the upload finishes. In order for the documents upload process to support the cancelation, it has to actively check for any cancel actions, and it needs to know when it\u2019s finished.<\/p>\n<p>We therefore get a more complex process that can be started, finished, or canceled. All these process states are kept in an event table that is used by both the frontend and the backend to track its progress and to show a result to the user when finished (successfully or with errors).[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;20px||0px||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_gallery gallery_ids=&#8221;7299&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221;][\/et_pb_gallery][et_pb_code _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221;][\/et_pb_code][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;20px||0px||false|true&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Here is a code example of the backend endpoints to be used by the frontend:[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;20px|||20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"java\" style=\"font-family: monospace;\"><span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000000; font-weight: bold;\">class<\/span> DocumentController <span style=\"color: #009900;\">{<\/span>\n\u00a0\n\t@PostMapping<span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"\/files\"<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #666666; font-style: italic;\">\/\/start multiple upload, return processId right away<\/span>\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> ResponseEntity<span style=\"color: #339933;\">&lt;<\/span>ProcessIdResult<span style=\"color: #339933;\">&gt;<\/span> uploadDocuments<span style=\"color: #009900;\">(<\/span>@Valid @NotNull @RequestPart<span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"files\"<\/span><span style=\"color: #009900;\">)<\/span> List<span style=\"color: #339933;\">&lt;<\/span>MultipartFile<span style=\"color: #339933;\">&gt;<\/span> files,\n\t\t\t@RequestParam<span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"item\"<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #003399;\">String<\/span> itemId<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\t\t<span style=\"color: #003399;\">String<\/span> processId <span style=\"color: #339933;\">=<\/span> ULID.<span style=\"color: #006633;\">nextUlid<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><span style=\"color: #666666; font-style: italic;\">\/\/generate random Id\n<\/span>\n\t\tdocumentService.<span style=\"color: #006633;\">upload<\/span><span style=\"color: #009900;\">(<\/span>processId, itemId, files<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span> <span style=\"color: #666666; font-style: italic;\">\/\/call async method\n<\/span>\n\t\t<span style=\"color: #000000; font-weight: bold;\">return<\/span> <span style=\"color: #000000; font-weight: bold;\">new<\/span> ResponseEntity<span style=\"color: #339933;\">&lt;&gt;<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">new<\/span> ProcessIdResult<span style=\"color: #009900;\">(<\/span>processId<span style=\"color: #009900;\">)<\/span>, HttpStatus.<span style=\"color: #006633;\">ACCEPTED<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t<span style=\"color: #009900;\">}<\/span>\n\u00a0\n\t@PostMapping<span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"\/cancel\"<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #666666; font-style: italic;\">\/\/cancel a specific process<\/span>\n\tResponseEntity<span style=\"color: #339933;\">&lt;<\/span>ProcessIdResult<span style=\"color: #339933;\">&gt;<\/span> cancelUploadDocuments<span style=\"color: #009900;\">(<\/span>@RequestParam<span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"processId\"<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #003399;\">String<\/span> processId<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{\n<\/span>\n\t\tdocumentService.<span style=\"color: #006633;\">cancel<\/span><span style=\"color: #009900;\">(<\/span>processId<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span> <span style=\"color: #666666; font-style: italic;\">\/\/send cancel event for this processId\n<\/span>\n\t\t<span style=\"color: #000000; font-weight: bold;\">return<\/span> <span style=\"color: #000000; font-weight: bold;\">new<\/span> ResponseEntity<span style=\"color: #339933;\">&lt;&gt;<\/span><span style=\"color: #009900;\">(<\/span>HttpStatus.<span style=\"color: #006633;\">ACCEPTED<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t<span style=\"color: #009900;\">}<\/span>\n\u00a0\n\t@GetMapping<span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"\/status\"<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #666666; font-style: italic;\">\/\/get the status of a specific process<\/span>\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> ResponseEntity<span style=\"color: #339933;\">&lt;<\/span>ProcessIdStatus<span style=\"color: #339933;\">&gt;<\/span> getStatus<span style=\"color: #009900;\">(<\/span>@RequestParam<span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"processId\"<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #003399;\">String<\/span> processId<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{\n<\/span>\n\t\tProcessIdStatus status <span style=\"color: #339933;\">=<\/span> documentService.<span style=\"color: #006633;\">getStatus<\/span><span style=\"color: #009900;\">(<\/span>processId<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span> <span style=\"color: #666666; font-style: italic;\">\/\/check status for this processId<\/span>\n\t\t\n<span style=\"color: #000000; font-weight: bold;\">return<\/span> <span style=\"color: #000000; font-weight: bold;\">new<\/span> ResponseEntity<span style=\"color: #339933;\">&lt;&gt;<\/span><span style=\"color: #009900;\">(<\/span>status, HttpStatus.<span style=\"color: #006633;\">OK<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t<span style=\"color: #009900;\">}<\/span>\n\u00a0\n<span style=\"color: #009900;\">}<\/span>\n\u00a0\n\u00a0\n<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000000; font-weight: bold;\">class<\/span> DocumentService <span style=\"color: #009900;\">{<\/span>\n\u00a0\n\tAsync<span style=\"color: #666666; font-style: italic;\">\/\/using default Spring thread executor<\/span>\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> upload<span style=\"color: #009900;\">(<\/span><span style=\"color: #003399;\">String<\/span> processId, <span style=\"color: #003399;\">String<\/span> itemId, List<span style=\"color: #339933;\">&lt;<\/span>MultipartFile<span style=\"color: #339933;\">&gt;<\/span> files<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\t\t<span style=\"color: #666666; font-style: italic;\">\/\/send start event for this processId<\/span>\n\t\t<span style=\"color: #666666; font-style: italic;\">\/\/start actual upload, checking after each document upload if cancel event was received<\/span>\n\t\t<span style=\"color: #666666; font-style: italic;\">\/\/send finish\/cancel\/failed event for this processId at the end<\/span>\n\u00a0\n\t<span style=\"color: #009900;\">}<\/span>\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]As you can see, we have used:<\/p>\n<ul>\n<li>an async method,<\/li>\n<li>process-related events that reflect the current status of the process,<\/li>\n<li>and a processID that is required by the frontend to check the process status or to cancel it.<\/li>\n<\/ul>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"Complexbackendcalculationsrequestedbyauseraction\">3. Complex backend calculations, requested by a user action<\/h2>\n<p>Another usage scenario: the user wants to perform an action, but the backend must check if (s)he is authorised, before actually executing the requests. Depending on the context, the authorisation might not be straightforward, and complex calculations might be needed. In our example below, the authorisation must be checked in multiple places \/ across multiple services, with each microservice providing its own authorisation result.<\/p>\n<p>More specific: an application user wants to post a comment on an existing item (see 1. above). Depending on the business logic, only specific users might be permitted to post comments. In order to check a user\u2019s permissions, the backend might have to do multiple calls to different microservices. To speed it up, all those calls should be initiated in parallel.[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;20px||0px||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_gallery gallery_ids=&#8221;7305&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221;][\/et_pb_gallery][et_pb_code _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221;][\/et_pb_code][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;20px||0px||false|true&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Here\u2019s Java\u2019s <em>CompletableFuture<\/em> to the rescue:[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;20px|||20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"java\" style=\"font-family: monospace;\"><span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000000; font-weight: bold;\">class<\/span> AuthorizationService <span style=\"color: #009900;\">{<\/span>\n\u00a0\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000066; font-weight: bold;\">boolean<\/span> hasAccess<span style=\"color: #009900;\">(<\/span>User user, Item item<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\t\tList<span style=\"color: #339933;\">&lt;<\/span>CompletableFuture<span style=\"color: #339933;\">&lt;<\/span>Boolean<span style=\"color: #339933;\">&gt;&gt;<\/span> parallelRequests <span style=\"color: #339933;\">=<\/span> <span style=\"color: #000000; font-weight: bold;\">new<\/span> ArrayList<span style=\"color: #339933;\">&lt;&gt;<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t\tCompletableFuture<span style=\"color: #339933;\">&lt;<\/span>Boolean<span style=\"color: #339933;\">&gt;<\/span> hasRightsInService1Future <span style=\"color: #339933;\">=<\/span> createFutureCallService1<span style=\"color: #009900;\">(<\/span>user, item<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t\tCompletableFuture<span style=\"color: #339933;\">&lt;<\/span>Boolean<span style=\"color: #339933;\">&gt;<\/span> hasRightsInService1Future <span style=\"color: #339933;\">=<\/span> createFutureCallService2<span style=\"color: #009900;\">(<\/span>user, item<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\u00a0\n\t\t<span style=\"color: #666666; font-style: italic;\">\/\/run the http calls in parallel<\/span>\n\t\tCompletableFuture<span style=\"color: #339933;\">&lt;<\/span>Void<span style=\"color: #339933;\">&gt;<\/span> combinedFuture <span style=\"color: #339933;\">=<\/span> CompletableFuture.<span style=\"color: #006633;\">allOf<\/span><span style=\"color: #009900;\">(<\/span>parallelRequests.<span style=\"color: #006633;\">toArray<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">new<\/span> CompletableFuture<span style=\"color: #009900;\">[<\/span><span style=\"color: #009900;\">]<\/span><span style=\"color: #009900;\">{<\/span><span style=\"color: #009900;\">}<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\u00a0\n\t\t<span style=\"color: #000000; font-weight: bold;\">try<\/span> <span style=\"color: #009900;\">{<\/span>\n\t\t\t<span style=\"color: #666666; font-style: italic;\">\/\/wait until all are finished<\/span>\n\t\t\tcombinedFuture.<span style=\"color: #006633;\">get<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\u00a0\n\t\t\t<span style=\"color: #003399;\">Boolean<\/span> authorizedInService1 <span style=\"color: #339933;\">=<\/span> hasRightsInService1Future.<span style=\"color: #006633;\">get<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><span style=\"color: #666666; font-style: italic;\">\/\/get the actual response of the call<\/span>\n\t\t\t<span style=\"color: #003399;\">Boolean<\/span> authorizedInService2 <span style=\"color: #339933;\">=<\/span> hasRightsInService2Future.<span style=\"color: #006633;\">get<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\u00a0\n\t\t\t<span style=\"color: #000000; font-weight: bold;\">return<\/span> authorizedInService1 <span style=\"color: #339933;\">&amp;&amp;<\/span> authorizedInService2<span style=\"color: #339933;\">;<\/span>\n\u00a0\n\t\t<span style=\"color: #009900;\">}<\/span> <span style=\"color: #000000; font-weight: bold;\">catch<\/span> <span style=\"color: #009900;\">(<\/span>ExecutionException exception<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\t\t\t<span style=\"color: #000000; font-weight: bold;\">throw<\/span> <span style=\"color: #000000; font-weight: bold;\">new<\/span> CustomException<span style=\"color: #009900;\">(<\/span>exception.<span style=\"color: #006633;\">getMessage<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t\t<span style=\"color: #009900;\">}<\/span>\n\u00a0\n\t<span style=\"color: #009900;\">}<\/span>\n\u00a0\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> CompletableFuture<span style=\"color: #339933;\">&lt;<\/span>Boolean<span style=\"color: #339933;\">&gt;<\/span> createFutureCallService1 <span style=\"color: #009900;\">(<\/span>User user, Item item<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\t\t<span style=\"color: #000000; font-weight: bold;\">return<\/span> CompletableFuture.<span style=\"color: #006633;\">supplyAsync<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #339933;\">-&gt;<\/span> callService1<span style=\"color: #009900;\">(<\/span>user,item<span style=\"color: #009900;\">)<\/span>, futureExecutor<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span> \n\t<span style=\"color: #009900;\">}<\/span>\n\u00a0\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> CompletableFuture<span style=\"color: #339933;\">&lt;<\/span>Boolean<span style=\"color: #339933;\">&gt;<\/span> createFutureCallService2 <span style=\"color: #009900;\">(<\/span>User user, Item item<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\t\t<span style=\"color: #000000; font-weight: bold;\">return<\/span> CompletableFuture.<span style=\"color: #006633;\">supplyAsync<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #339933;\">-&gt;<\/span> callService2<span style=\"color: #009900;\">(<\/span>user,item<span style=\"color: #009900;\">)<\/span>, futureExecutor<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\t<span style=\"color: #009900;\">}<\/span>\n\u00a0\n\u00a0\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]We see again that an executor is needed (see <em>futureExecutor<\/em> in the last line of code) to provide the treads on which each call will be running. This can be the default Spring executor or a custom one (we\u2019ll detail below how to create it).<\/p>\n<p>Now that we have multiple parallel calls, it\u2019s important to note that each logging should be done within its own thread. For tracking down REST calls, we use Spring Sleuth, an addition to the application logger that creates a traceID for each REST call and appends it to the logs. This is great for synchronised REST calls, but when it comes to async calls, we need to tweak the <em>ThreadExecutor<\/em>, in order to have a traceID for each Thread.<\/p>\n<p>Adding Sleuth to the application is very easy:<\/p>\n<ul>\n<li>Just add this line to <em>build.graddle<\/em>:<\/li>\n<\/ul>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;|||20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"java\" style=\"font-family: monospace;\">compile <span style=\"color: #0000ff;\">\"org.springframework.cloud:spring-cloud-starter-sleuth\"<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<ul>\n<li>Then in <em>logback-spring.xml<\/em> add this property:<\/li>\n<\/ul>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;|||20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"java\" style=\"font-family: monospace;\"><span style=\"color: #339933;\">&lt;<\/span>property name<span style=\"color: #339933;\">=<\/span><span style=\"color: #0000ff;\">\"CONSOLE_LOG_PATTERN\"<\/span>\n          value<span style=\"color: #339933;\">=<\/span><span style=\"color: #0000ff;\">\"%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr([${springAppName},%X{X-B3-TraceId:-},%X{X-B3-ParentSpanId:-},%X{X-B3-SpanId:-}]) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}\"<\/span><span style=\"color: #339933;\">\/&gt;<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Adding Sleuth to a custom thread executor is done in the Async config file (created at 1. above, to enable the async feature in Spring). Here we just need to create a named Bean, that returns the new custom executor wrapped into a Sleuth specific executor:[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;20px|||20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"java\" style=\"font-family: monospace;\">@Configuration\n@EnableAsync\n<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000000; font-weight: bold;\">class<\/span> AsyncConfiguration <span style=\"color: #000000; font-weight: bold;\">implements<\/span> AsyncConfigurer <span style=\"color: #009900;\">{<\/span>\n\u00a0\n\t@Bean<span style=\"color: #009900;\">(<\/span>name <span style=\"color: #339933;\">=<\/span> <span style=\"color: #0000ff;\">\"futureExecutor\"<\/span><span style=\"color: #009900;\">)<\/span>\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> Executor getFutureExecutor<span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\t\tExecutorService executor <span style=\"color: #339933;\">=<\/span> Executors.<span style=\"color: #006633;\">newFixedThreadPool<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #cc66cc;\">10<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><span style=\"color: #666666; font-style: italic;\">\/\/added executor with 10 Threads<\/span>\n\t\t<span style=\"color: #000000; font-weight: bold;\">return<\/span> <span style=\"color: #000000; font-weight: bold;\">new<\/span> LazyTraceExecutor<span style=\"color: #009900;\">(<\/span>beanFactory, executor<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><span style=\"color: #666666; font-style: italic;\">\/\/sleuth-specific: now each thread will have a traceId<\/span>\n\t<span style=\"color: #009900;\">}<\/span>\n\u00a0\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"Automaticallyscheduledsystemactions\">4. Automatically scheduled system actions<\/h2>\n<p>Schedulers are async features that are started automatically by Spring, at a specified time. In order to enable scheduling in Spring, we only need to add one more annotation to the <em>AsyncConfig<\/em> file:[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;20px|||20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"java\" style=\"font-family: monospace;\">@Configuration\n@EnableAsync\n@EnableScheduling\n<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000000; font-weight: bold;\">class<\/span> AsyncConfiguration <span style=\"color: #000000; font-weight: bold;\">implements<\/span> AsyncConfigurer <span style=\"color: #009900;\">{<\/span><span style=\"color: #666666; font-style: italic;\">\/\/ body here}<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Then, all we need to do is to create a method in our <em>CustomScheduler<\/em> component, with this annotation:[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;20px|||20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"java\" style=\"font-family: monospace;\">@<span style=\"color: #003399;\">Component<\/span>\n<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000000; font-weight: bold;\">class<\/span> CustomScheduler<span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\u00a0\n        @Scheduled<span style=\"color: #009900;\">(<\/span>cron<span style=\"color: #339933;\">=<\/span>\u201d<span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #cc66cc;\">0<\/span> <span style=\"color: #cc66cc;\">0<\/span><span style=\"color: #339933;\">\/<\/span><span style=\"color: #cc66cc;\">2<\/span> <span style=\"color: #339933;\">*<\/span> <span style=\"color: #339933;\">*<\/span> <span style=\"color: #339933;\">?<\/span>\u201d<span style=\"color: #009900;\">)<\/span>\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> runScheduledActions<span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">{<\/span><span style=\"color: #666666; font-style: italic;\">\/\/scheduler operations here}<\/span>\n\u00a0\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]The cron expression can be customized by adding it to <em>application.yml<\/em> or any other place. (How to set it <a title=\"Go to Google search: cron expression\" href=\"https:\/\/www.google.com\/search?rls=en&amp;q=cron+expressions\" target=\"_blank\" rel=\"noopener noreferrer\">can easily be found<\/a>.) Depending on what you need, more parameters can be added to the <em>@Schedule<\/em>d annotation. Also, an <em>@Async<\/em> annotation can be added to the <em>runScheduledActions()<\/em> method to support parallel calls, so that each run is done in its separate thread.[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2 id=\"Importingbigdatafromanexternalsystemintoourapplication\">5. Importing big data from an external system into our application<\/h2>\n<p>Sometimes, the item objects are created by an external system and imported into our application. The import can be done in two ways:<\/p>\n<p>\u2014 A scheduled action on the external system side, that runs every day or at a specified date.<br \/>\n\u2014 A triggered action every time a new item has been created in the external system.<\/p>\n<p>For a triggered import, our application will get item updates (almost) instantly. The downside: if the external system has a lot of simultaneously active users, our application might get a lot of import calls because all the items are created at once. This leads to a communication overload between the two systems, with increased response times to the external system. The external system does a direct synchronised call to our application, therefore any delay from our side means a delay on their side.[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;20px||0px||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_gallery gallery_ids=&#8221;7319&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]One way to solve this is to accept all incoming requests from the external system and execute them on our own timing. A good implementation can be a request queue where each item is transformed into a job and added to this internal job queue. On our side we can have a consumer that reads and executes the queued jobs. This is an improvement, but the jobs are still executed one at a time.[\/et_pb_text][et_pb_gallery gallery_ids=&#8221;7313&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]A further optimisation would be to execute more than one job at a time. This can be done with a queue listener that starts running on a separate thread for each job. Since all the job threads will be running with a specified executor, one can also decide the maximum number of consumers, by adjusting the number of threads in the executor\u2019s thread pool. [\/et_pb_text][et_pb_gallery gallery_ids=&#8221;7315&#8243; fullwidth=&#8221;on&#8221; hover_icon=&#8221;%%186%%&#8221; _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221; max_width=&#8221;65%&#8221; module_alignment=&#8221;left&#8221;][\/et_pb_gallery][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Here is a code snippet for the queue listener, which will start an async run:[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;|300|||||||&#8221; text_font_size=&#8221;1em&#8221; text_line_height=&#8221;1.3em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;1em&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; background_color=&#8221;#f8f8f8&#8243; custom_margin=&#8221;20px|||20px|false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221; border_style_left=&#8221;none&#8221; locked=&#8221;off&#8221;]<\/p>\n<pre class=\"java\" style=\"font-family: monospace;\"><span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> itemAdded<span style=\"color: #009900;\">(<\/span>Item item<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\tMyRunnableTask jobQueueTask <span style=\"color: #339933;\">=<\/span> <span style=\"color: #000000; font-weight: bold;\">new<\/span> MyRunnableTask<span style=\"color: #009900;\">(<\/span>item<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n\tjobQueueTask.<span style=\"color: #006633;\">run<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span>\n<span style=\"color: #009900;\">}<\/span>\n\u00a0\n\u00a0\n<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000000; font-weight: bold;\">class<\/span> MyRunnableTask <span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\n\t<span style=\"color: #000000; font-weight: bold;\">private<\/span> <span style=\"color: #000066; font-weight: bold;\">int<\/span> runId<span style=\"color: #339933;\">;<\/span>\n\t<span style=\"color: #000000; font-weight: bold;\">private<\/span> List<span style=\"color: #339933;\">&lt;<\/span>String<span style=\"color: #339933;\">&gt;<\/span> usedLocks<span style=\"color: #339933;\">;<\/span>\n\u00a0\n\t@Async<span style=\"color: #009900;\">(<\/span>\u201ccustomJobExecutor\u201d<span style=\"color: #009900;\">)<\/span>\n\t<span style=\"color: #000000; font-weight: bold;\">public<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> runImportActions<span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">{<\/span><span style=\"color: #666666; font-style: italic;\">\/\/import operations here}<\/span>\n\u00a0\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;20px||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]Please note that we need to create a new runnable task for each listener notification (<em>itemAdded<\/em>), and <span style=\"text-decoration: underline;\">that<\/span> will be the one that runs async. This way we can have a separate task instance for each run, so that any internal members (like <em>runID<\/em> or <em>usedLocks<\/em>) are <span style=\"text-decoration: underline;\">not<\/span> shared between the runs\/tasks.[\/et_pb_text][et_pb_code _builder_version=&#8221;4.7.7&#8243; _module_preset=&#8221;default&#8221;][\/et_pb_code][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8221;on&#8221; _builder_version=&#8221;4.7.7&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;6vh||0px||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; hover_enabled=&#8221;0&#8243; border_color_left=&#8221;#ff6317&#8243; sticky_enabled=&#8221;0&#8243;]<\/p>\n<h2>Conclusion<\/h2>\n<p>Async processes can be used in many ways, with customised executors to help in each individual situation. An important element of the async implementation is whether the result is a \u201cwait for\u201d, or a \u201cfire and forget action\u201d.<\/p>\n<p>Special attention must be paid to parallel executions, especially if they operate on the same entities. Java synchronisation can help, but you also need to make sure that the intermediate objects used in the calculations are not shared between runs.<\/p>\n<p>***<\/p>\n<p>How do <strong>you<\/strong>\u00a0do it? <a href=\"https:\/\/berg-software.com\/contact-berg-software\/\">Care to share your solution?<\/a><\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;4.4.1&#8243; custom_padding=&#8221;|||0px||&#8221; locked=&#8221;off&#8221;][et_pb_row use_custom_gutter=&#8221;on&#8221; gutter_width=&#8221;3&#8243; admin_label=&#8221;\uff3f&#8221; _builder_version=&#8221;4.4.6&#8243; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;4vh||8vh||false|false&#8221; border_color_left=&#8221;rgba(0,0,0,0)&#8221;][et_pb_column type=&#8221;4_4&#8243; _builder_version=&#8221;4.4.6&#8243;][et_pb_text _builder_version=&#8221;4.7.7&#8243; text_font=&#8221;||||||||&#8221; text_font_size=&#8221;1.1em&#8221; text_line_height=&#8221;1.6em&#8221; quote_font=&#8221;|700|||||||&#8221; quote_text_align=&#8221;left&#8221; quote_font_size=&#8221;16px&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;1.5em&#8221; header_2_line_height=&#8221;0.9em&#8221; header_3_font_size=&#8221;23px&#8221; header_4_font=&#8221;||||||||&#8221; header_4_font_size=&#8221;16px&#8221; header_4_line_height=&#8221;1.5em&#8221; header_5_font_size=&#8221;14px&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;||||false|false&#8221; border_color_left=&#8221;#ff6317&#8243;]<\/p>\n<h2>\uff3f<\/h2>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; _builder_version=&#8221;3.22&#8243; background_color=&#8221;#eeeeee&#8221; custom_padding=&#8221;50px||50px||false|false&#8221; border_color_top=&#8221;#ff6317&#8243; global_module=&#8221;1642&#8243;][et_pb_row column_structure=&#8221;1_3,1_3,1_3&#8243; _builder_version=&#8221;4.4.1&#8243; custom_padding=&#8221;0px|||||&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;1_3&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_social_media_follow _builder_version=&#8221;4.4.4&#8243; text_orientation=&#8221;left&#8221;][et_pb_social_media_follow_network social_network=&#8221;linkedin&#8221; url=&#8221;https:\/\/www.linkedin.com\/company\/berg-computers-srl\/&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#007bb6&#8243; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]linkedin[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8221;twitter&#8221; url=&#8221;https:\/\/twitter.com\/berg_software&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#00aced&#8221; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]twitter[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8221;facebook&#8221; url=&#8221;https:\/\/www.facebook.com\/bergCOMPUTERS&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#3b5998&#8243; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]facebook[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8221;instagram&#8221; url=&#8221;https:\/\/www.instagram.com\/berg_software\/&#8221; _builder_version=&#8221;4.4.4&#8243; background_color=&#8221;#ea2c59&#8243; follow_button=&#8221;off&#8221; url_new_window=&#8221;on&#8221;]instagram[\/et_pb_social_media_follow_network][\/et_pb_social_media_follow][\/et_pb_column][et_pb_column type=&#8221;1_3&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_post_nav in_same_term=&#8221;on&#8221; show_next=&#8221;off&#8221; _builder_version=&#8221;4.4.1&#8243; title_text_color=&#8221;#ff6317&#8243; custom_padding=&#8221;|25px|||false|false&#8221;][\/et_pb_post_nav][\/et_pb_column][et_pb_column type=&#8221;1_3&#8243; _builder_version=&#8221;4.4.1&#8243;][et_pb_post_nav in_same_term=&#8221;on&#8221; show_prev=&#8221;off&#8221; _builder_version=&#8221;4.4.1&#8243; title_text_color=&#8221;#ff6317&#8243; custom_padding=&#8221;|||25px|false|false&#8221;][\/et_pb_post_nav][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8221;1&#8243; admin_label=&#8221;CONTACT&#8221; _builder_version=&#8221;4.4.1&#8243; background_color=&#8221;#d2d2d2&#8243; custom_padding=&#8221;75px||75px||false|false&#8221;][et_pb_row column_structure=&#8221;1_4,3_4&#8243; admin_label=&#8221;Service Section Title&#8221; _builder_version=&#8221;4.4.1&#8243; custom_padding=&#8221;||25px||false|false&#8221; animation_direction=&#8221;top&#8221; locked=&#8221;off&#8221;][et_pb_column type=&#8221;1_4&#8243; _builder_version=&#8221;3.25&#8243; custom_padding=&#8221;|||&#8221; custom_padding__hover=&#8221;|||&#8221;][\/et_pb_column][et_pb_column type=&#8221;3_4&#8243; _builder_version=&#8221;3.25&#8243; custom_padding=&#8221;|||&#8221; custom_padding__hover=&#8221;|||&#8221;][et_pb_text _builder_version=&#8221;4.4.1&#8243; text_font=&#8221;|300|||||||&#8221; text_text_color=&#8221;#ffffff&#8221; text_line_height=&#8221;1.1em&#8221; header_5_font=&#8221;|600|||||||&#8221; header_5_text_color=&#8221;#ffffff&#8221; header_5_font_size=&#8221;14px&#8221; header_5_line_height=&#8221;1.5em&#8221; custom_margin=&#8221;||||false|false&#8221;]29 years in business | 2700 software projects | 760 clients | 24 countries<\/p>\n<h5>We turn ideas into software. What is yours?<\/h5>\n<p>[\/et_pb_text][et_pb_text admin_label=&#8221;Title&#8221; _builder_version=&#8221;4.4.6&#8243; header_text_align=&#8221;center&#8221; header_2_font=&#8221;|300|||||||&#8221; header_2_text_align=&#8221;left&#8221; header_2_text_color=&#8221;#ff6317&#8243; header_2_font_size=&#8221;50px&#8221; header_2_line_height=&#8221;0.9em&#8221; custom_margin=&#8221;||||false|false&#8221; custom_padding=&#8221;25px||25px||false|false&#8221;]<\/p>\n<h2 id=\"Getintouch\">Get in touch<\/h2>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row column_structure=&#8221;1_4,3_4&#8243; _builder_version=&#8221;4.4.4&#8243;][et_pb_column type=&#8221;1_4&#8243; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_column][et_pb_column type=&#8221;3_4&#8243; _builder_version=&#8221;4.4.4&#8243;][et_pb_contact_form email=&#8221;contact@bergsoftprod.wpengine.com&#8221; custom_message=&#8221;WEBFORM MESSAGE||et_pb_line_break_holder||\uff3f||et_pb_line_break_holder||FROM: %%Name%%||et_pb_line_break_holder||EMAIL: %%Email%%||et_pb_line_break_holder||PHONE NUMBER: %%Phone_number%%||et_pb_line_break_holder||COMPANY: %%Company_name%%||et_pb_line_break_holder||TERMS &amp; CONDITIONS: %%Terms_and_Conditions%%||et_pb_line_break_holder||DATA PRIVACY POLICY: %%Data_Privacy_Policy%%||et_pb_line_break_holder||\uff3f||et_pb_line_break_holder||MESSAGE:||et_pb_line_break_holder||%%Message%%&#8221; success_message=&#8221;Thank you for reaching out! Your message was sent. We will get back to you right away.&#8221; _builder_version=&#8221;4.4.4&#8243; form_field_background_color=&#8221;#d2d2d2&#8243; form_field_text_color=&#8221;#ffffff&#8221; form_field_focus_background_color=&#8221;#ffffff&#8221; form_field_focus_text_color=&#8221;#000000&#8243; title_level=&#8221;h2&#8243; title_font=&#8221;|300|||||||&#8221; title_text_color=&#8221;#ff6317&#8243; title_font_size=&#8221;30px&#8221; form_field_line_height=&#8221;1.5em&#8221; custom_button=&#8221;on&#8221; button_text_size=&#8221;14px&#8221; button_text_color=&#8221;#ffffff&#8221; button_bg_color=&#8221;#ff6317&#8243; button_border_width=&#8221;0px&#8221; button_border_radius=&#8221;0px&#8221; button_icon=&#8221;%%3%%&#8221; button_on_hover=&#8221;off&#8221; border_color_all=&#8221;#ffffff&#8221; border_width_bottom=&#8221;1px&#8221;][et_pb_contact_field field_id=&#8221;Name&#8221; field_title=&#8221;Name *&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243; form_field_background_color=&#8221;#d2d2d2&#8243; form_field_text_color=&#8221;#ffffff&#8221; form_field_focus_background_color=&#8221;#ffffff&#8221; form_field_focus_text_color=&#8221;#000000&#8243; border_width_bottom=&#8221;1px&#8221; button_text_size__hover_enabled=&#8221;off&#8221; button_one_text_size__hover_enabled=&#8221;off&#8221; button_two_text_size__hover_enabled=&#8221;off&#8221; button_text_color__hover_enabled=&#8221;off&#8221; button_one_text_color__hover_enabled=&#8221;off&#8221; button_two_text_color__hover_enabled=&#8221;off&#8221; button_border_width__hover_enabled=&#8221;off&#8221; button_one_border_width__hover_enabled=&#8221;off&#8221; button_two_border_width__hover_enabled=&#8221;off&#8221; button_border_color__hover_enabled=&#8221;off&#8221; button_one_border_color__hover_enabled=&#8221;off&#8221; button_two_border_color__hover_enabled=&#8221;off&#8221; button_border_radius__hover_enabled=&#8221;off&#8221; button_one_border_radius__hover_enabled=&#8221;off&#8221; button_two_border_radius__hover_enabled=&#8221;off&#8221; button_letter_spacing__hover_enabled=&#8221;off&#8221; button_one_letter_spacing__hover_enabled=&#8221;off&#8221; button_two_letter_spacing__hover_enabled=&#8221;off&#8221; button_bg_color__hover_enabled=&#8221;off&#8221; button_one_bg_color__hover_enabled=&#8221;off&#8221; button_two_bg_color__hover_enabled=&#8221;off&#8221;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Email&#8221; field_title=&#8221;Email address *&#8221; field_type=&#8221;email&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243; button_text_size__hover_enabled=&#8221;off&#8221; button_one_text_size__hover_enabled=&#8221;off&#8221; button_two_text_size__hover_enabled=&#8221;off&#8221; button_text_color__hover_enabled=&#8221;off&#8221; button_one_text_color__hover_enabled=&#8221;off&#8221; button_two_text_color__hover_enabled=&#8221;off&#8221; button_border_width__hover_enabled=&#8221;off&#8221; button_one_border_width__hover_enabled=&#8221;off&#8221; button_two_border_width__hover_enabled=&#8221;off&#8221; button_border_color__hover_enabled=&#8221;off&#8221; button_one_border_color__hover_enabled=&#8221;off&#8221; button_two_border_color__hover_enabled=&#8221;off&#8221; button_border_radius__hover_enabled=&#8221;off&#8221; button_one_border_radius__hover_enabled=&#8221;off&#8221; button_two_border_radius__hover_enabled=&#8221;off&#8221; button_letter_spacing__hover_enabled=&#8221;off&#8221; button_one_letter_spacing__hover_enabled=&#8221;off&#8221; button_two_letter_spacing__hover_enabled=&#8221;off&#8221; button_bg_color__hover_enabled=&#8221;off&#8221; button_one_bg_color__hover_enabled=&#8221;off&#8221; button_two_bg_color__hover_enabled=&#8221;off&#8221;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Phone_number&#8221; field_title=&#8221;Phone number&#8221; required_mark=&#8221;off&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Company_name&#8221; field_title=&#8221;Company name&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Message&#8221; field_title=&#8221;Message *&#8221; field_type=&#8221;text&#8221; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243; form_field_background_color=&#8221;#d2d2d2&#8243; form_field_focus_background_color=&#8221;#ffffff&#8221; form_field_focus_text_color=&#8221;#000000&#8243; border_width_bottom=&#8221;1px&#8221; button_text_size__hover_enabled=&#8221;off&#8221; button_one_text_size__hover_enabled=&#8221;off&#8221; button_two_text_size__hover_enabled=&#8221;off&#8221; button_text_color__hover_enabled=&#8221;off&#8221; button_one_text_color__hover_enabled=&#8221;off&#8221; button_two_text_color__hover_enabled=&#8221;off&#8221; button_border_width__hover_enabled=&#8221;off&#8221; button_one_border_width__hover_enabled=&#8221;off&#8221; button_two_border_width__hover_enabled=&#8221;off&#8221; button_border_color__hover_enabled=&#8221;off&#8221; button_one_border_color__hover_enabled=&#8221;off&#8221; button_two_border_color__hover_enabled=&#8221;off&#8221; button_border_radius__hover_enabled=&#8221;off&#8221; button_one_border_radius__hover_enabled=&#8221;off&#8221; button_two_border_radius__hover_enabled=&#8221;off&#8221; button_letter_spacing__hover_enabled=&#8221;off&#8221; button_one_letter_spacing__hover_enabled=&#8221;off&#8221; button_two_letter_spacing__hover_enabled=&#8221;off&#8221; button_bg_color__hover_enabled=&#8221;off&#8221; button_one_bg_color__hover_enabled=&#8221;off&#8221; button_two_bg_color__hover_enabled=&#8221;off&#8221;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Terms_and_Conditions&#8221; field_title=&#8221; &#8221; field_type=&#8221;checkbox&#8221; checkbox_options=&#8221;%91{%22value%22:%22I have read and accepted the Terms and Conditions%22,%22checked%22:0,%22dragID%22:-1}%93&#8243; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8221;Data_Privacy_Policy&#8221; field_title=&#8221; &#8221; field_type=&#8221;checkbox&#8221; checkbox_options=&#8221;%91{%22value%22:%22I have read and accepted the Data Privacy Policy%22,%22checked%22:0,%22dragID%22:-1}%93&#8243; fullwidth_field=&#8221;on&#8221; _builder_version=&#8221;4.4.4&#8243;][\/et_pb_contact_field][\/et_pb_contact_form][\/et_pb_column][\/et_pb_row][\/et_pb_section]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Asynchronous processes can be implemented in many different ways. We look into five concrete situations.<\/p>\n","protected":false},"author":17,"featured_media":7282,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"on","_et_pb_old_content":"","_et_gb_content_width":"2880","footnotes":""},"categories":[138,33],"tags":[],"class_list":["post-7284","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-how-to","category-insights"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v16.1.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Async processes in REST Applications with Java Spring | Berg Software<\/title>\n<meta name=\"description\" content=\"In this article, we will show you how to take advantage of async processes in REST applications with Java Spring. In a previous article, we discussed\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Async processes in REST Applications with Java Spring | Berg Software\" \/>\n<meta property=\"og:description\" content=\"In this article, we will show you how to take advantage of async processes in REST applications with Java Spring. In a previous article, we discussed\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/\" \/>\n<meta property=\"og:site_name\" content=\"Berg Software\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/bergCOMPUTERS\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-04-21T06:35:23+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-07-20T11:17:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.berg-software.com\/wp-content\/uploads\/Berg-Software-Asynchronous-processes-with-Spring.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"600\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@berg_software\" \/>\n<meta name=\"twitter:site\" content=\"@berg_software\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"15 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#organization\",\"name\":\"Berg Software\",\"url\":\"https:\/\/www.berg-software.com\/en\/\",\"sameAs\":[\"https:\/\/www.facebook.com\/bergCOMPUTERS\/\",\"https:\/\/www.instagram.com\/berg_software\/\",\"https:\/\/www.linkedin.com\/company\/berg-computers-srl\/\",\"https:\/\/www.youtube.com\/channel\/UCw1FfcRJnC-CoKPwlcM10Iw\",\"https:\/\/twitter.com\/berg_software\"],\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#logo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/berg-software.com\/wp-content\/uploads\/berg-software-logo.png\",\"contentUrl\":\"https:\/\/berg-software.com\/wp-content\/uploads\/berg-software-logo.png\",\"width\":512,\"height\":512,\"caption\":\"Berg Software\"},\"image\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#logo\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#website\",\"url\":\"https:\/\/www.berg-software.com\/en\/\",\"name\":\"Berg Software\",\"description\":\"We turn ideas into software.\",\"publisher\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/www.berg-software.com\/en\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/www.berg-software.com\/wp-content\/uploads\/Berg-Software-Asynchronous-processes-with-Spring.jpg\",\"contentUrl\":\"https:\/\/www.berg-software.com\/wp-content\/uploads\/Berg-Software-Asynchronous-processes-with-Spring.jpg\",\"width\":1200,\"height\":600,\"caption\":\"Berg Software - Asynchronous processes with Spring\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/#webpage\",\"url\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/\",\"name\":\"Async processes in REST Applications with Java Spring | Berg Software\",\"isPartOf\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/#primaryimage\"},\"datePublished\":\"2021-04-21T06:35:23+00:00\",\"dateModified\":\"2022-07-20T11:17:18+00:00\",\"description\":\"In this article, we will show you how to take advantage of async processes in REST applications with Java Spring. In a previous article, we discussed\",\"breadcrumb\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/\",\"url\":\"https:\/\/www.berg-software.com\/en\/\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"position\":2,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/category\/insights\/\",\"url\":\"https:\/\/www.berg-software.com\/en\/category\/insights\/\",\"name\":\"Insights\"}},{\"@type\":\"ListItem\",\"position\":3,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/\",\"url\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/\",\"name\":\"Take advantage of async processes in REST Applications with Java Spring\"}}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/#webpage\"},\"author\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#\/schema\/person\/a220bb7cf08bdbbedd2638063a7e0f3c\"},\"headline\":\"Take advantage of async processes in REST Applications with Java Spring\",\"datePublished\":\"2021-04-21T06:35:23+00:00\",\"dateModified\":\"2022-07-20T11:17:18+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/async-processes-in-rest-applications-with-java-spring\/#primaryimage\"},\"articleSection\":\"How to,Insights\",\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.berg-software.com\/en\/#\/schema\/person\/a220bb7cf08bdbbedd2638063a7e0f3c\",\"name\":\"Cristina Olea\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","_links":{"self":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/posts\/7284","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/users\/17"}],"replies":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/comments?post=7284"}],"version-history":[{"count":0,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/posts\/7284\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/media\/7282"}],"wp:attachment":[{"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/media?parent=7284"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/categories?post=7284"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.berg-software.com\/en\/wp-json\/wp\/v2\/tags?post=7284"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}