{"id":7339,"date":"2021-04-28T06:12:29","date_gmt":"2021-04-28T06:12:29","guid":{"rendered":"https:\/\/berg-software.com\/einblicke\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/"},"modified":"2021-04-28T06:15:30","modified_gmt":"2021-04-28T06:15:30","slug":"die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen","status":"publish","type":"post","link":"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/","title":{"rendered":"Die Vorteile von asynchronen Prozessen in REST-Anwendungen mit Java Spring nutzen"},"content":{"rendered":"<p>[et_pb_section fb_built=&#8220;1&#8243; fullwidth=&#8220;on&#8220; _builder_version=&#8220;4.4.1&#8243;][et_pb_fullwidth_post_title meta=&#8220;off&#8220; featured_placement=&#8220;background&#8220; _builder_version=&#8220;4.6.6&#8243; title_font=&#8220;||||||||&#8220; title_text_color=&#8220;#ff6317&#8243; title_font_size=&#8220;3.5em&#8220; meta_font=&#8220;|300|||||||&#8220; meta_text_color=&#8220;#ffffff&#8220; meta_font_size=&#8220;1em&#8220; background_enable_color=&#8220;off&#8220; use_background_color_gradient=&#8220;on&#8220; background_color_gradient_start=&#8220;rgba(248,248,248,0.85)&#8220; background_color_gradient_end=&#8220;rgba(248,248,248,0.75)&#8220; background_color_gradient_overlays_image=&#8220;on&#8220; min_height=&#8220;20vh&#8220; height=&#8220;400px&#8220; custom_padding=&#8220;6vh||6vh||false|false&#8220; locked=&#8220;off&#8220;][\/et_pb_fullwidth_post_title][\/et_pb_section][et_pb_section fb_built=&#8220;1&#8243; admin_label=&#8220;intro&#8220; _builder_version=&#8220;4.4.6&#8243; custom_padding=&#8220;|||0px||&#8220; locked=&#8220;off&#8220;][et_pb_row use_custom_gutter=&#8220;on&#8220; _builder_version=&#8220;4.4.6&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;6vh||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; hover_enabled=&#8220;0&#8243; border_color_left=&#8220;#ff6317&#8243; sticky_enabled=&#8220;0&#8243;]<\/p>\n<p>In einem <a href=\"https:\/\/berg-software.com\/de\/einblicke\/wie-digitalisierung-funktioniert-software-produktentwicklung-produktmanagement-3-von-5\/\" target=\"_blank\" title=\"Go to Berg Software article: Software development\/management\" rel=\"noopener\">fr\u00fcheren Artikel<\/a> haben wir besprochen, wie wichtig es f\u00fcr das Softwareentwicklungsteam ist, die Gesch\u00e4ftslogik einer Softwarel\u00f6sung\/eines Softwareprodukts sowie die angestrebten Funktionen und Features zu verstehen. Die wichtigsten Ergebnisse sind ein starker Fokus auf das, was aus gesch\u00e4ftlicher Sicht am wichtigsten ist, weniger Nacharbeit und saubere Release-Pl\u00e4ne.<\/p>\n<p>Aber das Verstehen der Ziele einer Softwarel\u00f6sung\/eines Softwareprodukts kann auch einige der kleineren Details beeinflussen \u2013 zum Beispiel, was passiert, wenn der Benutzer auf eine Schaltfl\u00e4che oder einen Link klickt. Im einfachsten Fall wird die gew\u00fcnschte Aktion ausgef\u00fchrt, und das Ergebnis wird sofort erreicht\/angezeigt (d. h., es folgt ein synchroner Prozess). In anderen F\u00e4llen muss der Benutzer m\u00f6glicherweise auf ein Ergebnis warten, w\u00e4hrend Teile der Oberfl\u00e4che vor\u00fcbergehend unzug\u00e4nglich\/deaktiviert sind (d. h. w\u00e4hrend eines asynchronen Prozesses).<\/p>\n<p>Die Wait-\/No-Wait-F\u00e4lle werden vom Product Owner entschieden und vom Softwareentwicklungsteam als sich gegenseitig ausschlie\u00dfende synchrone\/asynchrone Prozesse implementiert:<\/p>\n<ul>\n<li>Bei <strong>synchronen Prozessen<\/strong> kann der Benutzer auf das Ergebnis warten und es sich dann anzeigen lassen. Einmal gestartet (z. B. durch einen Klick), kann der Prozess nicht mehr unterbrochen werden.<\/li>\n<li><strong>Asynchrone Prozesse<\/strong> k\u00f6nnen entweder vom Benutzer oder von einem automatisierten Scheduler als \u201efire and forget\u201c gestartet werden: Die Aktion wird gestartet, aber man wartet (oder k\u00fcmmert sich) nicht darum, dass sie ausgef\u00fchrt wird und das Ergebnis angezeigt wird. Manchmal wird eine Startmeldung angezeigt, und der Status kann w\u00e4hrend der Ausf\u00fchrung \u00fcberpr\u00fcft werden.<\/li>\n<\/ul>\n<p>Asynchrone Prozesse k\u00f6nnen auf viele verschiedene Arten verwendet\/implementiert werden. Wir schauen uns f\u00fcnf konkrete Situationen an:<\/p>\n<ul>\n<li><a href=\"#Sendinganotificationemailattheendofauseroperation\" title=\"See on this page: 1. Sending a notification email at the end of a user operation\">Versenden einer Benachrichtigungsmail am Ende eines Benutzervorgangs, an dem auch andere Benutzer beteiligt sind<\/a><\/li>\n<li><a href=\"#Uploadingmultipledocumentswithcancellationfeature\" title=\"See on this page: 2. Uploading multiple documents with cancellation feature\">Hochladen mehrerer Dokumente mit Abbruchfunktion<\/a><\/li>\n<li><a href=\"#Complexbackendcalculationsrequestedbyauseraction\" title=\"See on this page: 3. Complex backend calculations requested by a user action\">Ausf\u00fchren einiger komplexer Berechnungen im Backend, die durch eine Benutzeraktion angefordert werden<\/a><\/li>\n<li><a href=\"#Automaticallyscheduledsystemactions\" title=\"See on this page: 4. Automatically scheduled system actions\">Ein paar automatisch geplante Systemaktionen durchf\u00fchren lassen<\/a><\/li>\n<li><a href=\"#Importingbigdatafromanexternalsystemintoourapplication\" title=\"See on this page: 5. Importing big data from an external system\">Importieren gro\u00dfer Datenmengen aus einem externen System in unsere Anwendung<\/a><\/li>\n<\/ul>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8220;on&#8220; _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;6vh||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<h2 id=\"Sendinganotificationemailattheendofauseroperation\">1. Versenden einer Benachrichtigungsmail am Ende eines Benutzervorgangs, an dem auch andere Benutzer beteiligt sind<\/h2>\n<p>Einige der Benutzer werden Vorg\u00e4nge durchf\u00fchren, die auch andere Benutzer betreffen \u2013 zum Beispiel einen Kommentar zu einem Artikel hinterlassen, der von jemand anderem erstellt wurde. In diesem Fall wollen wir den Kommentar im Backend speichern und den Autor des Artikels \u00fcber den neuen Kommentar informieren. Wenn der Benutzer auf \u201eKommentar speichern\u201c klickt, wird der einzelne Backend-Aufruf daher zwei Dinge tun: den eigentlichen Kommentar speichern und eine E-Mail an den Ersteller des Artikels senden.<\/p>\n<p>Das Speichern des eigentlichen Kommentars wird sofort durchgef\u00fchrt, da der anfragende Benutzer die R\u00fcckmeldung ben\u00f6tigt, dass er gespeichert wurde. Aber das Versenden der E-Mail ist nicht etwas, das den anfragenden Benutzer betrifft, also wird das Backend einen asynchronen Prozess ausl\u00f6sen, ohne auf das eigentliche Ergebnis zu warten. Das bedeutet eine schnellere Antwortzeit f\u00fcr die Benutzer und keine Bel\u00e4stigung mit Fehlermeldungen, wenn beim Versenden der E-Mail etwas schiefl\u00e4uft.[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;20px||0px||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; locked=&#8220;off&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_gallery gallery_ids=&#8220;7292&#8243; fullwidth=&#8220;on&#8220; hover_icon=&#8220;%%186%%&#8220; _builder_version=&#8220;4.7.7&#8243; _module_preset=&#8220;default&#8220; max_width=&#8220;65%&#8220; module_alignment=&#8220;left&#8220;][\/et_pb_gallery][et_pb_code _builder_version=&#8220;4.7.7&#8243; _module_preset=&#8220;default&#8220;][\/et_pb_code][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8220;on&#8220; _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;20px||0px||false|true&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; locked=&#8220;off&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]Hier ist ein Code-Beispiel f\u00fcr einen Backend-Ablauf, und zwar in dem entsprechenden Dienst, der das Speichern der Kommentare \u00fcbernimmt:[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;|300|||||||&#8220; text_font_size=&#8220;1em&#8220; text_line_height=&#8220;1.3em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;1em&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; background_color=&#8220;#f8f8f8&#8243; custom_margin=&#8220;20px|||20px|false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; border_style_left=&#8220;none&#8220; locked=&#8220;off&#8220;]<\/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&nbsp;\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&nbsp;\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&nbsp;\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&nbsp;\n&nbsp;\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&nbsp;\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&nbsp;\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=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<p>Sie k\u00f6nnen sehen, dass <em>mailService.sendCommentSavedNotification(&#8230;)<\/em> wie ein normaler Methodenaufruf aussieht. Aber aufgrund der @Async-Annotation auf der eigentlichen Methodenimplementierung greift Spring ein und tut etwas im Hintergrund: Es verwendet einen <em>ThreadExecutor<\/em>, um einen neuen Thread zu erzeugen. (Die eigentliche Ausf\u00fchrung dieser Methode findet in diesem neuen Thread statt.) Daher wird der Befehl <em>mailService.sendCommentSavedNotification<\/em> sofort zur\u00fcckgegeben. Der ThreadExecutor ist, wenn er nicht explizit in der Anwendung definiert ist, der Standard-ThreadExecutor von Spring (<em>SimpleAsyncTaskExecutor<\/em>), und das Einzige, was Sie tun m\u00fcssen, ist, ihn in einer Konfigurationsdatei wie dieser zu aktivieren:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;|300|||||||&#8220; text_font_size=&#8220;1em&#8220; text_line_height=&#8220;1.3em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;1em&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; background_color=&#8220;#f8f8f8&#8243; custom_margin=&#8220;20px|||20px|false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; border_style_left=&#8220;none&#8220; locked=&#8220;off&#8220;]<\/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=&#8220;on&#8220; _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;6vh||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<h2 id=\"Uploadingmultipledocumentswithcancellationfeature\">2. Hochladen mehrerer Dokumente mit Abbruchfunktion<\/h2>\n<p>Ein weiterer Anwendungsfall ist das Hochladen mehrerer Dokumente auf einmal, um sie an einen Artikel anzuh\u00e4ngen. Die Dokumente befinden sich m\u00f6glicherweise auf einem Server eines Drittanbieters, was bedeutet, dass das Hochladen einige Zeit in Anspruch nehmen kann. W\u00e4hrend der Wartezeit kann der Benutzer einen Ladebalken sehen und den Vorgang abbrechen.<\/p>\n<p>Wie das funktioniert?<\/p>\n<p>Das Frontend sendet die Dokumente an das Backend und erh\u00e4lt eine Prozess-ID. Mit dieser Prozess-ID kann das Frontend das Hochladen des Dokuments jederzeit abbrechen (wenn der Benutzer auf die Schaltfl\u00e4che Abbrechen klickt), indem es einen Abbruchaufruf durchf\u00fchrt und die Prozess-ID \u00fcbergibt.<\/p>\n<p>Dies ist nur m\u00f6glich, weil das Hochladen von Dokumenten im Backend asynchron abl\u00e4uft, und das Backend die Prozess-ID zur\u00fcckgeben kann, bevor der Upload abgeschlossen ist. Damit der Dokumenten-Upload-Prozess den Abbruch unterst\u00fctzt, muss er aktiv auf Abbruchaktionen pr\u00fcfen und er muss wissen, wann er beendet ist.<\/p>\n<p>Wir erhalten also einen komplexeren Prozess, der gestartet, beendet oder abgebrochen werden kann. Alle diese Prozessstadien werden in einer Ereignistabelle gehalten, die sowohl vom Frontend als auch vom Backend verwendet wird, um den Fortschritt zu verfolgen und dem Benutzer ein Ergebnis anzuzeigen, wenn der Prozess (erfolgreich oder mit Fehlern) beendet ist.[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;20px||0px||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; locked=&#8220;off&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_gallery gallery_ids=&#8220;7300&#8243; fullwidth=&#8220;on&#8220; hover_icon=&#8220;%%186%%&#8220; _builder_version=&#8220;4.7.7&#8243; _module_preset=&#8220;default&#8220; max_width=&#8220;65%&#8220; module_alignment=&#8220;left&#8220;][\/et_pb_gallery][et_pb_code _builder_version=&#8220;4.7.7&#8243; _module_preset=&#8220;default&#8220;][\/et_pb_code][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8220;on&#8220; _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;20px||0px||false|true&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; locked=&#8220;off&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]Hier ist ein Codebeispiel f\u00fcr die Backend-Endpunkte, die vom Frontend verwendet werden:[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;|300|||||||&#8220; text_font_size=&#8220;1em&#8220; text_line_height=&#8220;1.3em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;1em&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; background_color=&#8220;#f8f8f8&#8243; custom_margin=&#8220;20px|||20px|false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; border_style_left=&#8220;none&#8220; locked=&#8220;off&#8220;]<\/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 \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<br\/><\/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<br\/><\/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 \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;\">{<br\/><\/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<br\/><\/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 \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;\">{<br\/><\/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<br\/><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 \n<span style=\"color: #009900;\">}<\/span>\n \n \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 \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 \n\t<span style=\"color: #009900;\">}<\/span>\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<p>Wie Sie sehen k\u00f6nnen, haben wir<\/p>\n<ul>\n<li>eine asynchrone Methode,<\/li>\n<li>prozessbezogene Ereignisse, die den aktuellen Status des Prozesses wiedergeben,<\/li>\n<li>und eine ProzessID, die vom Frontend ben\u00f6tigt wird, um den Prozessstatus zu pr\u00fcfen oder abzubrechen, verwendet.<\/li>\n<\/ul>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8220;on&#8220; _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;6vh||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<h2 id=\"Complexbackendcalculationsrequestedbyauseraction\">3. Komplexe Berechnungen im Backend, die durch eine Benutzeraktion angefordert werden<\/h2>\n<p>Ein weiteres Nutzungsszenario: Der Benutzer m\u00f6chte eine Aktion ausf\u00fchren, aber das Backend muss pr\u00fcfen, ob er autorisiert ist, bevor die Anfragen tats\u00e4chlich ausgef\u00fchrt werden. Je nach Kontext ist die Autorisierung nicht einfach, und es k\u00f6nnen komplexe Berechnungen erforderlich sein. In unserem Beispiel unten muss die Autorisierung an mehreren Stellen \/ \u00fcber mehrere Prozesse hinweg gepr\u00fcft werden, wobei jeder Microprozess sein eigenes Autorisierungsergebnis liefert.<\/p>\n<p>Konkreter: Ein Anwendungsbenutzer m\u00f6chte einen Kommentar zu einem vorhandenen Element abgeben (siehe 1. oben). Abh\u00e4ngig von der Gesch\u00e4ftslogik k\u00f6nnten nur bestimmte Benutzer berechtigt sein, Kommentare zu posten. Um die Berechtigungen eines Benutzers zu pr\u00fcfen, muss das Backend m\u00f6glicherweise mehrere Aufrufe an verschiedene Microservices durchf\u00fchren. Um dies zu beschleunigen, sollten alle diese Aufrufe parallel initiiert werden.<\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;20px||0px||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; locked=&#8220;off&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_gallery gallery_ids=&#8220;7306&#8243; fullwidth=&#8220;on&#8220; hover_icon=&#8220;%%186%%&#8220; _builder_version=&#8220;4.7.7&#8243; _module_preset=&#8220;default&#8220; max_width=&#8220;65%&#8220; module_alignment=&#8220;left&#8220;][\/et_pb_gallery][et_pb_code _builder_version=&#8220;4.7.7&#8243; _module_preset=&#8220;default&#8220;][\/et_pb_code][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8220;on&#8220; _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;20px||0px||false|true&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; locked=&#8220;off&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<p>Hier kommt Javas <em>CompletableFuture<\/em> zur Hilfe:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;|300|||||||&#8220; text_font_size=&#8220;1em&#8220; text_line_height=&#8220;1.3em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;1em&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; background_color=&#8220;#f8f8f8&#8243; custom_margin=&#8220;20px|||20px|false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; border_style_left=&#8220;none&#8220; locked=&#8220;off&#8220;]<\/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&nbsp;\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&nbsp;\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&nbsp;\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&nbsp;\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&nbsp;\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&nbsp;\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&nbsp;\n\t<span style=\"color: #009900;\">}<\/span>\n&nbsp;\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&nbsp;\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&nbsp;\n&nbsp;\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<p>Auch hier sehen wir, dass ein Executor ben\u00f6tigt wird (siehe <em>futureExecutor<\/em> in der letzten Codezeile), um die Treads bereitzustellen, auf denen die einzelnen Aufrufe ausgef\u00fchrt werden. Dies kann der Standard-Executor von Spring oder ein benutzerdefinierter Executor sein (wir werden weiter unten detailliert beschreiben, wie man ihn erstellt).<\/p>\n<p>Da wir nun mehrere parallele Aufrufe haben, ist es wichtig zu beachten, dass jede Protokollierung innerhalb eines eigenen Threads erfolgen sollte. Zum Nachverfolgen von REST-Aufrufen verwenden wir Spring Sleuth, eine Erg\u00e4nzung zum Anwendungslogger, die eine TraceID f\u00fcr jeden REST-Aufruf erstellt und an die Protokolle anh\u00e4ngt. Dies ist gro\u00dfartig f\u00fcr synchronisierte REST-Aufrufe, aber wenn es um asynchrone Aufrufe geht, m\u00fcssen wir den <em>ThreadExecutor<\/em> anpassen, um eine TraceID f\u00fcr jeden Thread zu haben.<\/p>\n<p>Das Einbinden von Sleuth in die Anwendung ist sehr einfach:<\/p>\n<ul>\n<li>Dazu f\u00fcgen Sie einfach diese Zeile in <em>build.graddle<\/em> ein:<\/li>\n<\/ul>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;|300|||||||&#8220; text_font_size=&#8220;1em&#8220; text_line_height=&#8220;1.3em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;1em&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; background_color=&#8220;#f8f8f8&#8243; custom_margin=&#8220;|||20px|false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; border_style_left=&#8220;none&#8220; locked=&#8220;off&#8220;]<\/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=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>F\u00fcgen Sie dann in <em>logback-spring.xml<\/em> diese Eigenschaft hinzu:<\/li>\n<\/ul>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;|300|||||||&#8220; text_font_size=&#8220;1em&#8220; text_line_height=&#8220;1.3em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;1em&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; background_color=&#8220;#f8f8f8&#8243; custom_margin=&#8220;|||20px|false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; border_style_left=&#8220;none&#8220; locked=&#8220;off&#8220;]<\/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=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]Das Hinzuf\u00fcgen von Sleuth zu einem benutzerdefinierten Thread-Executor erfolgt in der Async-Konfigurationsdatei (erstellt weiter oben unter 1., um das Async-Feature in Spring zu aktivieren). Hier m\u00fcssen wir nur eine benannte Bean erstellen, die den neuen benutzerdefinierten Executor zur\u00fcckgibt, der in einen Sleuth-spezifischen Executor verpackt ist:[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;|300|||||||&#8220; text_font_size=&#8220;1em&#8220; text_line_height=&#8220;1.3em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;1em&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; background_color=&#8220;#f8f8f8&#8243; custom_margin=&#8220;20px|||20px|false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; border_style_left=&#8220;none&#8220; locked=&#8220;off&#8220;]<\/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&nbsp;\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&nbsp;\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8220;on&#8220; _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;6vh||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<h2 id=\"Automaticallyscheduledsystemactions\">4. Automatisch geplante Systemaktionen<\/h2>\n<p>Scheduler sind asynchrone Features, die von Spring automatisch zu einem bestimmten Zeitpunkt gestartet werden. Um das Scheduling in Spring zu aktivieren, m\u00fcssen wir nur eine weitere Anmerkung in der <em>AsyncConfig<\/em>-Datei hinzuf\u00fcgen:[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;|300|||||||&#8220; text_font_size=&#8220;1em&#8220; text_line_height=&#8220;1.3em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;1em&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; background_color=&#8220;#f8f8f8&#8243; custom_margin=&#8220;20px|||20px|false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; border_style_left=&#8220;none&#8220; locked=&#8220;off&#8220;]<\/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=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<p>Anschlie\u00dfend m\u00fcssen wir nur noch eine Methode in unserer <em>CustomScheduler<\/em>-Komponente erstellen, die diese Anmerkung enth\u00e4lt:<\/p>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;|300|||||||&#8220; text_font_size=&#8220;1em&#8220; text_line_height=&#8220;1.3em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;1em&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; background_color=&#8220;#f8f8f8&#8243; custom_margin=&#8220;20px|||20px|false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; border_style_left=&#8220;none&#8220; locked=&#8220;off&#8220;]<\/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&nbsp;\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&nbsp;\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<p>Die Cron-Expression kann angepasst werden, indem sie in der <em>application.yml<\/em> oder an einer anderen Stelle hinzugef\u00fcgt wird. (Wie man sie einstellt, <a href=\"https:\/\/www.google.com\/search?rls=en&amp;q=cron+expressions\" target=\"_blank\" rel=\"noopener noreferrer\" title=\"Go to Google search: cron expression\">ist leicht zu finden<\/a>.) Je nach Bedarf k\u00f6nnen weitere Parameter zur <em>@Scheduled<\/em>-Annotation hinzugef\u00fcgt werden. Au\u00dferdem kann der Methode <em>runScheduledActions()<\/em> eine <em>@Async<\/em>-Anmerkung hinzugef\u00fcgt werden, um parallele Aufrufe zu unterst\u00fctzen, sodass jeder Lauf in einem eigenen Thread ausgef\u00fchrt wird.<\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8220;on&#8220; _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;6vh||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<h2 id=\"Importingbigdatafromanexternalsystemintoourapplication\">5. Importieren gro\u00dfer Datenmengen aus einem externen System in unsere Anwendung<\/h2>\n<p>Manchmal werden die Artikelobjekte von einem externen System erstellt und in unsere Anwendung importiert. Der Import kann auf zwei Arten erfolgen:<\/p>\n<p>eine geplante Aktion auf Seiten des externen Systems, die jeden Tag oder zu einem bestimmten Datum ausgef\u00fchrt wird.<br \/>\neine getriggerte Aktion, die jedes Mal ausgel\u00f6st wird, wenn ein neues Element im externen System erstellt wurde.<\/p>\n<p>Bei einem getriggerten Import erh\u00e4lt unsere Anwendung Artikelaktualisierungen (fast) sofort. Der Nachteil: Wenn das externe System viele gleichzeitig aktive Benutzer hat, kann unsere Anwendung eine Menge Importaufrufe erhalten, da alle Elemente auf einmal erstellt werden. Dies f\u00fchrt zu einer \u00dcberlastung der Kommunikation zwischen den beiden Systemen, mit erh\u00f6hten Antwortzeiten f\u00fcr das externe System. Das externe System f\u00fchrt einen direkten synchronisierten Aufruf an unsere Anwendung durch, daher bedeutet jede Verz\u00f6gerung von unserer Seite eine Verz\u00f6gerung auf deren Seite.[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;20px||0px||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; locked=&#8220;off&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_gallery gallery_ids=&#8220;7320&#8243; fullwidth=&#8220;on&#8220; hover_icon=&#8220;%%186%%&#8220; _builder_version=&#8220;4.7.7&#8243; _module_preset=&#8220;default&#8220; max_width=&#8220;65%&#8220; module_alignment=&#8220;left&#8220;][\/et_pb_gallery][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]Eine M\u00f6glichkeit, dies zu l\u00f6sen, besteht darin, alle eingehenden Anfragen vom externen System anzunehmen und sie nach unserem eigenen Zeitplan auszuf\u00fchren. Eine gute Implementierung kann eine Anforderungswarteschlange sein, bei der jedes Element in einen Auftrag umgewandelt und zu dieser internen Auftragswarteschlange hinzugef\u00fcgt wird. Auf unserer Seite k\u00f6nnen wir einen Consumer haben, der die Jobs in der Warteschlange liest und ausf\u00fchrt. Dies ist eine Verbesserung, aber die Jobs werden immer noch einzeln ausgef\u00fchrt.[\/et_pb_text][et_pb_gallery gallery_ids=&#8220;7314&#8243; fullwidth=&#8220;on&#8220; hover_icon=&#8220;%%186%%&#8220; _builder_version=&#8220;4.7.7&#8243; _module_preset=&#8220;default&#8220; max_width=&#8220;65%&#8220; module_alignment=&#8220;left&#8220;][\/et_pb_gallery][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]Eine weitere Optimierung best\u00fcnde darin, mehr als einen Job gleichzeitig auszuf\u00fchren. Dies kann mit einem Queue-Listener erfolgen, der f\u00fcr jeden Auftrag auf einem separaten Thread zu laufen beginnt. Da alle Job-Threads mit einem bestimmten Executor ausgef\u00fchrt werden, kann man auch die maximale Anzahl der Consumer bestimmen, indem man die Anzahl der Threads im Thread-Pool des Executors anpasst. [\/et_pb_text][et_pb_gallery gallery_ids=&#8220;7316&#8243; fullwidth=&#8220;on&#8220; hover_icon=&#8220;%%186%%&#8220; _builder_version=&#8220;4.7.7&#8243; _module_preset=&#8220;default&#8220; max_width=&#8220;65%&#8220; module_alignment=&#8220;left&#8220;][\/et_pb_gallery][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]Hier ist ein Codefragment f\u00fcr den Queue-Listener, der einen asynchronen Durchlauf starten wird:[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;|300|||||||&#8220; text_font_size=&#8220;1em&#8220; text_line_height=&#8220;1.3em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;1em&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; background_color=&#8220;#f8f8f8&#8243; custom_margin=&#8220;20px|||20px|false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220; border_style_left=&#8220;none&#8220; locked=&#8220;off&#8220;]<\/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&nbsp;\n&nbsp;\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&nbsp;\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&nbsp;\n<span style=\"color: #009900;\">}<\/span><\/pre>\n<p>[\/et_pb_text][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;20px||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<p>Bitte beachten Sie, dass wir f\u00fcr jede Listener-Benachrichtigung (<em>itemAdded<\/em>) eine neue runnable Aufgabe erstellen m\u00fcssen, und <span style=\"text-decoration: underline;\">diese<\/span> wird diejenige sein, die asynchron l\u00e4uft. Auf diese Weise k\u00f6nnen wir eine separate Task-Instanz f\u00fcr jeden Durchlauf haben, so dass alle internen Mitglieder (wie <em>runID<\/em> oder <em>usedLocks<\/em>) <span style=\"text-decoration: underline;\">nicht<\/span> zwischen den Durchl\u00e4ufen\/Tasks geteilt werden.<\/p>\n<p>[\/et_pb_text][et_pb_code _builder_version=&#8220;4.7.7&#8243; _module_preset=&#8220;default&#8220;][\/et_pb_code][\/et_pb_column][\/et_pb_row][et_pb_row use_custom_gutter=&#8220;on&#8220; _builder_version=&#8220;4.7.7&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;6vh||0px||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#ff6317&#8243;]<\/p>\n<h2>Fazit<\/h2>\n<p>Async-Prozesse k\u00f6nnen auf viele Arten verwendet werden, wobei angepasste Executors in jeder einzelnen Situation helfen. Ein wichtiges Element der asynchronen Implementierung ist, ob das Ergebnis eine \u201ewait for\u201c oder eine \u201efire and forget\u201c-Aktion ist.<\/p>\n<p>Besonderes Augenmerk muss auf parallele Ausf\u00fchrungen gelegt werden, vor allem wenn sie auf denselben Entit\u00e4ten operieren. Java-Synchronisation kann helfen, aber man muss auch sicherstellen, dass die in den Berechnungen verwendeten Zwischenobjekte nicht zwischen den L\u00e4ufen geteilt werden.<\/p>\n<p>***<\/p>\n<p>Und wie machen <strong>Sie<\/strong> das? <a href=\"https:\/\/berg-software.com\/de\/kontakt-berg-software\/\">M\u00f6chten Sie Ihre L\u00f6sung mit uns teilen?<\/a><\/p>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8220;1&#8243; _builder_version=&#8220;4.4.1&#8243; custom_padding=&#8220;|||0px||&#8220; locked=&#8220;off&#8220;][et_pb_row use_custom_gutter=&#8220;on&#8220; gutter_width=&#8220;3&#8243; admin_label=&#8220;\uff3f&#8220; _builder_version=&#8220;4.4.6&#8243; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;4vh||8vh||false|false&#8220; border_color_left=&#8220;rgba(0,0,0,0)&#8220;][et_pb_column type=&#8220;4_4&#8243; _builder_version=&#8220;4.4.6&#8243;][et_pb_text _builder_version=&#8220;4.7.7&#8243; text_font=&#8220;||||||||&#8220; text_font_size=&#8220;1.1em&#8220; text_line_height=&#8220;1.6em&#8220; quote_font=&#8220;|700|||||||&#8220; quote_text_align=&#8220;left&#8220; quote_font_size=&#8220;16px&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;1.5em&#8220; header_2_line_height=&#8220;0.9em&#8220; header_3_font_size=&#8220;23px&#8220; header_4_font=&#8220;||||||||&#8220; header_4_font_size=&#8220;16px&#8220; header_4_line_height=&#8220;1.5em&#8220; header_5_font_size=&#8220;14px&#8220; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;||||false|false&#8220; border_color_left=&#8220;#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=&#8220;1&#8243; _builder_version=&#8220;3.22&#8243; background_color=&#8220;#eeeeee&#8220; custom_padding=&#8220;50px||50px||false|false&#8220; border_color_top=&#8220;#ff6317&#8243;][et_pb_row column_structure=&#8220;1_3,1_3,1_3&#8243; _builder_version=&#8220;4.4.1&#8243; custom_padding=&#8220;0px|||||&#8220; locked=&#8220;off&#8220;][et_pb_column type=&#8220;1_3&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_social_media_follow _builder_version=&#8220;4.4.4&#8243; text_orientation=&#8220;left&#8220;][et_pb_social_media_follow_network social_network=&#8220;linkedin&#8220; url=&#8220;https:\/\/www.linkedin.com\/company\/berg-computers-srl\/&#8220; _builder_version=&#8220;4.4.4&#8243; background_color=&#8220;#007bb6&#8243; follow_button=&#8220;off&#8220; url_new_window=&#8220;on&#8220;]linkedin[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8220;twitter&#8220; url=&#8220;https:\/\/twitter.com\/berg_software&#8220; _builder_version=&#8220;4.4.4&#8243; background_color=&#8220;#00aced&#8220; follow_button=&#8220;off&#8220; url_new_window=&#8220;on&#8220;]twitter[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8220;facebook&#8220; url=&#8220;https:\/\/www.facebook.com\/bergCOMPUTERS&#8220; _builder_version=&#8220;4.4.4&#8243; background_color=&#8220;#3b5998&#8243; follow_button=&#8220;off&#8220; url_new_window=&#8220;on&#8220;]facebook[\/et_pb_social_media_follow_network][et_pb_social_media_follow_network social_network=&#8220;instagram&#8220; url=&#8220;https:\/\/www.instagram.com\/berg_software\/&#8220; _builder_version=&#8220;4.4.4&#8243; background_color=&#8220;#ea2c59&#8243; follow_button=&#8220;off&#8220; url_new_window=&#8220;on&#8220;]instagram[\/et_pb_social_media_follow_network][\/et_pb_social_media_follow][\/et_pb_column][et_pb_column type=&#8220;1_3&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_post_nav in_same_term=&#8220;on&#8220; show_next=&#8220;off&#8220; _builder_version=&#8220;4.4.1&#8243; title_text_color=&#8220;#ff6317&#8243; custom_padding=&#8220;|25px|||false|false&#8220;][\/et_pb_post_nav][\/et_pb_column][et_pb_column type=&#8220;1_3&#8243; _builder_version=&#8220;4.4.1&#8243;][et_pb_post_nav in_same_term=&#8220;on&#8220; show_prev=&#8220;off&#8220; _builder_version=&#8220;4.4.1&#8243; title_text_color=&#8220;#ff6317&#8243; custom_padding=&#8220;|||25px|false|false&#8220;][\/et_pb_post_nav][\/et_pb_column][\/et_pb_row][\/et_pb_section][et_pb_section fb_built=&#8220;1&#8243; admin_label=&#8220;CONTACT&#8220; _builder_version=&#8220;4.4.1&#8243; background_color=&#8220;#d2d2d2&#8243; custom_padding=&#8220;75px||75px||false|false&#8220;][et_pb_row column_structure=&#8220;1_4,3_4&#8243; admin_label=&#8220;Service Section Title&#8220; _builder_version=&#8220;4.4.1&#8243; custom_padding=&#8220;||25px||false|false&#8220; animation_direction=&#8220;top&#8220; locked=&#8220;off&#8220;][et_pb_column type=&#8220;1_4&#8243; _builder_version=&#8220;3.25&#8243; custom_padding=&#8220;|||&#8220; custom_padding__hover=&#8220;|||&#8220;][\/et_pb_column][et_pb_column type=&#8220;3_4&#8243; _builder_version=&#8220;3.25&#8243; custom_padding=&#8220;|||&#8220; custom_padding__hover=&#8220;|||&#8220;][et_pb_text _builder_version=&#8220;4.4.1&#8243; text_font=&#8220;|300|||||||&#8220; text_text_color=&#8220;#ffffff&#8220; text_line_height=&#8220;1.1em&#8220; header_5_font=&#8220;|600|||||||&#8220; header_5_text_color=&#8220;#ffffff&#8220; header_5_font_size=&#8220;14px&#8220; header_5_line_height=&#8220;1.5em&#8220; custom_margin=&#8220;||||false|false&#8220;]29 Jahre im Gesch\u00e4ft | 2700 Software-Projekte | 760 Kunden | 24 L\u00e4nder<\/p>\n<h5>Wir verwandeln Ideen in Software. Wie lautet Ihre Idee?<\/h5>\n<p>[\/et_pb_text][et_pb_text admin_label=&#8220;Title&#8220; _builder_version=&#8220;4.4.6&#8243; header_text_align=&#8220;center&#8220; header_2_font=&#8220;|300|||||||&#8220; header_2_text_align=&#8220;left&#8220; header_2_text_color=&#8220;#ff6317&#8243; header_2_font_size=&#8220;50px&#8220; header_2_line_height=&#8220;0.9em&#8220; custom_margin=&#8220;||||false|false&#8220; custom_padding=&#8220;25px||25px||false|false&#8220;]<\/p>\n<h2 id=\"Getintouch\">Kontakt aufnehmen<\/h2>\n<p>[\/et_pb_text][\/et_pb_column][\/et_pb_row][et_pb_row column_structure=&#8220;1_4,3_4&#8243; _builder_version=&#8220;4.4.4&#8243;][et_pb_column type=&#8220;1_4&#8243; _builder_version=&#8220;4.4.4&#8243;][\/et_pb_column][et_pb_column type=&#8220;3_4&#8243; _builder_version=&#8220;4.4.4&#8243;][et_pb_contact_form email=&#8220;contact@bergsoftprod.wpengine.com&#8220; custom_message=&#8220;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 &#038; 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%%&#8220; success_message=&#8220;Thank you for reaching out! Your message was sent. We will get back to you right away.&#8220; _builder_version=&#8220;4.4.4&#8243; form_field_background_color=&#8220;#d2d2d2&#8243; form_field_text_color=&#8220;#ffffff&#8220; form_field_focus_background_color=&#8220;#ffffff&#8220; form_field_focus_text_color=&#8220;#000000&#8243; title_level=&#8220;h2&#8243; title_font=&#8220;|300|||||||&#8220; title_text_color=&#8220;#ff6317&#8243; title_font_size=&#8220;30px&#8220; form_field_line_height=&#8220;1.5em&#8220; custom_button=&#8220;on&#8220; button_text_size=&#8220;14px&#8220; button_text_color=&#8220;#ffffff&#8220; button_bg_color=&#8220;#ff6317&#8243; button_border_width=&#8220;0px&#8220; button_border_radius=&#8220;0px&#8220; button_icon=&#8220;%%3%%&#8220; button_on_hover=&#8220;off&#8220; border_color_all=&#8220;#ffffff&#8220; border_width_bottom=&#8220;1px&#8220;][et_pb_contact_field field_id=&#8220;Name&#8220; field_title=&#8220;Name *&#8220; fullwidth_field=&#8220;on&#8220; _builder_version=&#8220;4.4.4&#8243; form_field_background_color=&#8220;#d2d2d2&#8243; form_field_text_color=&#8220;#ffffff&#8220; form_field_focus_background_color=&#8220;#ffffff&#8220; form_field_focus_text_color=&#8220;#000000&#8243; border_width_bottom=&#8220;1px&#8220; button_text_size__hover_enabled=&#8220;off&#8220; button_one_text_size__hover_enabled=&#8220;off&#8220; button_two_text_size__hover_enabled=&#8220;off&#8220; button_text_color__hover_enabled=&#8220;off&#8220; button_one_text_color__hover_enabled=&#8220;off&#8220; button_two_text_color__hover_enabled=&#8220;off&#8220; button_border_width__hover_enabled=&#8220;off&#8220; button_one_border_width__hover_enabled=&#8220;off&#8220; button_two_border_width__hover_enabled=&#8220;off&#8220; button_border_color__hover_enabled=&#8220;off&#8220; button_one_border_color__hover_enabled=&#8220;off&#8220; button_two_border_color__hover_enabled=&#8220;off&#8220; button_border_radius__hover_enabled=&#8220;off&#8220; button_one_border_radius__hover_enabled=&#8220;off&#8220; button_two_border_radius__hover_enabled=&#8220;off&#8220; button_letter_spacing__hover_enabled=&#8220;off&#8220; button_one_letter_spacing__hover_enabled=&#8220;off&#8220; button_two_letter_spacing__hover_enabled=&#8220;off&#8220; button_bg_color__hover_enabled=&#8220;off&#8220; button_one_bg_color__hover_enabled=&#8220;off&#8220; button_two_bg_color__hover_enabled=&#8220;off&#8220;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8220;Email&#8220; field_title=&#8220;E-Mail-Adresse *&#8220; field_type=&#8220;email&#8220; fullwidth_field=&#8220;on&#8220; _builder_version=&#8220;4.4.4&#8243; button_text_size__hover_enabled=&#8220;off&#8220; button_one_text_size__hover_enabled=&#8220;off&#8220; button_two_text_size__hover_enabled=&#8220;off&#8220; button_text_color__hover_enabled=&#8220;off&#8220; button_one_text_color__hover_enabled=&#8220;off&#8220; button_two_text_color__hover_enabled=&#8220;off&#8220; button_border_width__hover_enabled=&#8220;off&#8220; button_one_border_width__hover_enabled=&#8220;off&#8220; button_two_border_width__hover_enabled=&#8220;off&#8220; button_border_color__hover_enabled=&#8220;off&#8220; button_one_border_color__hover_enabled=&#8220;off&#8220; button_two_border_color__hover_enabled=&#8220;off&#8220; button_border_radius__hover_enabled=&#8220;off&#8220; button_one_border_radius__hover_enabled=&#8220;off&#8220; button_two_border_radius__hover_enabled=&#8220;off&#8220; button_letter_spacing__hover_enabled=&#8220;off&#8220; button_one_letter_spacing__hover_enabled=&#8220;off&#8220; button_two_letter_spacing__hover_enabled=&#8220;off&#8220; button_bg_color__hover_enabled=&#8220;off&#8220; button_one_bg_color__hover_enabled=&#8220;off&#8220; button_two_bg_color__hover_enabled=&#8220;off&#8220;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8220;Phone_number&#8220; field_title=&#8220;Telefonnummer&#8220; required_mark=&#8220;off&#8220; fullwidth_field=&#8220;on&#8220; _builder_version=&#8220;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8220;Company_name&#8220; field_title=&#8220;Name des Unternehmens&#8220; fullwidth_field=&#8220;on&#8220; _builder_version=&#8220;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8220;Message&#8220; field_title=&#8220;Nachricht *&#8220; field_type=&#8220;text&#8220; fullwidth_field=&#8220;on&#8220; _builder_version=&#8220;4.4.4&#8243; form_field_background_color=&#8220;#d2d2d2&#8243; form_field_focus_background_color=&#8220;#ffffff&#8220; form_field_focus_text_color=&#8220;#000000&#8243; border_width_bottom=&#8220;1px&#8220; button_text_size__hover_enabled=&#8220;off&#8220; button_one_text_size__hover_enabled=&#8220;off&#8220; button_two_text_size__hover_enabled=&#8220;off&#8220; button_text_color__hover_enabled=&#8220;off&#8220; button_one_text_color__hover_enabled=&#8220;off&#8220; button_two_text_color__hover_enabled=&#8220;off&#8220; button_border_width__hover_enabled=&#8220;off&#8220; button_one_border_width__hover_enabled=&#8220;off&#8220; button_two_border_width__hover_enabled=&#8220;off&#8220; button_border_color__hover_enabled=&#8220;off&#8220; button_one_border_color__hover_enabled=&#8220;off&#8220; button_two_border_color__hover_enabled=&#8220;off&#8220; button_border_radius__hover_enabled=&#8220;off&#8220; button_one_border_radius__hover_enabled=&#8220;off&#8220; button_two_border_radius__hover_enabled=&#8220;off&#8220; button_letter_spacing__hover_enabled=&#8220;off&#8220; button_one_letter_spacing__hover_enabled=&#8220;off&#8220; button_two_letter_spacing__hover_enabled=&#8220;off&#8220; button_bg_color__hover_enabled=&#8220;off&#8220; button_one_bg_color__hover_enabled=&#8220;off&#8220; button_two_bg_color__hover_enabled=&#8220;off&#8220;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8220;Terms_and_Conditions&#8220; field_title=&#8220; &#8220; field_type=&#8220;checkbox&#8220; checkbox_options=&#8220;%91{%22value%22:%22Ich habe die AGB gelesen und akzeptiert%22,%22checked%22:0,%22dragID%22:-1}%93&#8243; fullwidth_field=&#8220;on&#8220; _builder_version=&#8220;4.4.4&#8243;][\/et_pb_contact_field][et_pb_contact_field field_id=&#8220;Data_Privacy_Policy&#8220; field_title=&#8220; &#8220; field_type=&#8220;checkbox&#8220; checkbox_options=&#8220;%91{%22value%22:%22Ich habe die Datenschutzrichtlinie gelesen und akzeptiert%22,%22checked%22:0,%22dragID%22:-1}%93&#8243; fullwidth_field=&#8220;on&#8220; _builder_version=&#8220;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>Asynchrone Prozesse k\u00f6nnen auf viele verschiedene Arten implementiert werden. Wir schauen uns f\u00fcnf konkrete Situationen an.<\/p>\n","protected":false},"author":17,"featured_media":7283,"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":"","footnotes":""},"categories":[79,141],"tags":[],"class_list":["post-7339","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-einblicke","category-how-to-de"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v16.1.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Asynchrone Prozesse in REST-Anwendungen mit Java Spring | Berg Software<\/title>\n<meta name=\"description\" content=\"Asynchrone Prozesse k\u00f6nnen auf viele verschiedene Arten implementiert werden. Wir schauen uns f\u00fcnf konkrete Situationen an.\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Asynchrone Prozesse in REST-Anwendungen mit Java Spring | Berg Software\" \/>\n<meta property=\"og:description\" content=\"Asynchrone Prozesse k\u00f6nnen auf viele verschiedene Arten implementiert werden. Wir schauen uns f\u00fcnf konkrete Situationen an.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/\" \/>\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-28T06:12:29+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-04-28T06:15:30+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=\"Gesch\u00e4tzte Lesezeit\">\n\t<meta name=\"twitter:data1\" content=\"34 Minuten\">\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\":\"de-DE\",\"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\":\"de-DE\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/#primaryimage\",\"inLanguage\":\"de-DE\",\"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\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/#webpage\",\"url\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/\",\"name\":\"Asynchrone Prozesse in REST-Anwendungen mit Java Spring | Berg Software\",\"isPartOf\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/#primaryimage\"},\"datePublished\":\"2021-04-28T06:12:29+00:00\",\"dateModified\":\"2021-04-28T06:15:30+00:00\",\"description\":\"Asynchrone Prozesse k\\u00f6nnen auf viele verschiedene Arten implementiert werden. Wir schauen uns f\\u00fcnf konkrete Situationen an.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/#breadcrumb\"},\"inLanguage\":\"de-DE\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/de\/\",\"url\":\"https:\/\/www.berg-software.com\/de\/\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"position\":2,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/de\/category\/einblicke\/\",\"url\":\"https:\/\/www.berg-software.com\/de\/category\/einblicke\/\",\"name\":\"Einblicke\"}},{\"@type\":\"ListItem\",\"position\":3,\"item\":{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/\",\"url\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/\",\"name\":\"Die Vorteile von asynchronen Prozessen in REST-Anwendungen mit Java Spring nutzen\"}}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/#webpage\"},\"author\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#\/schema\/person\/a220bb7cf08bdbbedd2638063a7e0f3c\"},\"headline\":\"Die Vorteile von asynchronen Prozessen in REST-Anwendungen mit Java Spring nutzen\",\"datePublished\":\"2021-04-28T06:12:29+00:00\",\"dateModified\":\"2021-04-28T06:15:30+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/www.berg-software.com\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.berg-software.com\/de\/die-vorteile-von-asynchronen-prozessen-in-rest-anwendungen-mit-java-spring-nutzen\/#primaryimage\"},\"articleSection\":\"Einblicke,How to\",\"inLanguage\":\"de-DE\"},{\"@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\/de\/wp-json\/wp\/v2\/posts\/7339","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.berg-software.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.berg-software.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/de\/wp-json\/wp\/v2\/users\/17"}],"replies":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/de\/wp-json\/wp\/v2\/comments?post=7339"}],"version-history":[{"count":0,"href":"https:\/\/www.berg-software.com\/de\/wp-json\/wp\/v2\/posts\/7339\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.berg-software.com\/de\/wp-json\/wp\/v2\/media\/7283"}],"wp:attachment":[{"href":"https:\/\/www.berg-software.com\/de\/wp-json\/wp\/v2\/media?parent=7339"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.berg-software.com\/de\/wp-json\/wp\/v2\/categories?post=7339"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.berg-software.com\/de\/wp-json\/wp\/v2\/tags?post=7339"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}