<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrzej Korcz</title>
    <description>The latest articles on DEV Community by Andrzej Korcz (@andrzej_korcz_9009de135d8).</description>
    <link>https://dev.to/andrzej_korcz_9009de135d8</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2138528%2F867570df-1c66-40d5-a6a4-c25b7e1ee5f0.png</url>
      <title>DEV Community: Andrzej Korcz</title>
      <link>https://dev.to/andrzej_korcz_9009de135d8</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andrzej_korcz_9009de135d8"/>
    <language>en</language>
    <item>
      <title>Kafka kontra RabbitMQ</title>
      <dc:creator>Andrzej Korcz</dc:creator>
      <pubDate>Sat, 05 Oct 2024 17:13:21 +0000</pubDate>
      <link>https://dev.to/andrzej_korcz_9009de135d8/kafka-kontra-rabbitmq-163f</link>
      <guid>https://dev.to/andrzej_korcz_9009de135d8/kafka-kontra-rabbitmq-163f</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnxvccc59pqtvok5dje7f.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnxvccc59pqtvok5dje7f.jpeg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
Apache Kafka i RabbitMQ to dwa popularne systemy kolejek wiadomości, ale mają różne podejścia do przetwarzania danych i nadają się do różnych przypadków użycia. Oto ich kluczowe różnice i wskazówki, kiedy wybrać każdy z nich:&lt;/p&gt;

&lt;h3&gt;
  
  
  Apache Kafka
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Model przetwarzania:&lt;/strong&gt; Kafka to system strumieniowy oparty na przesyłaniu zdarzeń (event streaming). Każda wiadomość jest zapisywana w partycji, a konsumenci mogą odczytywać te wiadomości w sposób uporządkowany. Kafka bardziej przypomina rozproszoną bazę danych wiadomości, która umożliwia "replay" – czyli ponowne odczytywanie tych samych danych.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Szybkość i wydajność:&lt;/strong&gt; Kafka jest zoptymalizowana pod kątem wydajności i wysokiej przepustowości, dobrze nadaje się do przetwarzania dużych ilości danych w czasie rzeczywistym (np. logi, dane o zdarzeniach, strumienie danych z IoT). Może obsługiwać miliony wiadomości na sekundę.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trwałość:&lt;/strong&gt; Kafka przechowuje dane na dysku, dzięki czemu mogą być one dostępne przez długi czas, nawet po ich przetworzeniu. Konsumenci mogą odczytywać wiadomości w dowolnym momencie, od konkretnego punktu w historii.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skalowalność:&lt;/strong&gt; Kafka została zaprojektowana do pracy w rozproszonym środowisku i łatwo skalować ją na wiele węzłów (serwerów), co sprawia, że dobrze radzi sobie w dużych systemach rozproszonych.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zastosowania:&lt;/strong&gt; Najlepsza do strumieniowania danych w czasie rzeczywistym, analizy danych, systemów logów i dużych systemów rozproszonych, gdzie priorytetem jest przepustowość i trwałość.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  RabbitMQ
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Model przetwarzania:&lt;/strong&gt; RabbitMQ to tradycyjny broker wiadomości (message broker) oparty na modelu kolejek (publish-subscribe lub point-to-point). Przesyła wiadomości od producentów do konsumentów, a wiadomości są usuwane po ich przetworzeniu. RabbitMQ oferuje różne zaawansowane wzorce routingu wiadomości (direct, topic, fanout).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Szybkość i wydajność:&lt;/strong&gt; RabbitMQ dobrze radzi sobie z przetwarzaniem mniejszych ilości danych, szczególnie w scenariuszach wymagających niskiej latencji (opóźnienia). Jest bardziej zoptymalizowany pod kątem pracy w środowiskach o wysokiej dostępności (HA).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trwałość:&lt;/strong&gt; RabbitMQ oferuje przechowywanie wiadomości w pamięci lub na dysku, ale zazwyczaj wiadomości są konsumowane i usuwane natychmiast po dostarczeniu do konsumenta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skalowalność:&lt;/strong&gt; RabbitMQ może być skalowany w poziomie, ale nie na taką skalę jak Kafka. Może obsługiwać wiele węzłów, ale nie radzi sobie tak dobrze z ekstremalnymi przypadkami dużego ruchu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zastosowania:&lt;/strong&gt; Idealny do obsługi klasycznych zadań w systemach mikroserwisowych, w których kluczowa jest niezawodna komunikacja między usługami (request-response, task queues), a także w systemach wymagających zaawansowanego routingu wiadomości.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Kiedy wybrać Kafka:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Gdy potrzebujesz przetwarzania dużej ilości danych w czasie rzeczywistym.&lt;/li&gt;
&lt;li&gt;Gdy zależy Ci na wysokiej przepustowości i niskich opóźnieniach.&lt;/li&gt;
&lt;li&gt;Gdy chcesz przechowywać historię zdarzeń i móc je ponownie przetwarzać.&lt;/li&gt;
&lt;li&gt;Gdy system wymaga skalowania na dużą skalę.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kiedy wybrać RabbitMQ:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Gdy potrzebujesz zaawansowanego routingu wiadomości (np. publish-subscribe, fanout, topic routing).&lt;/li&gt;
&lt;li&gt;Gdy projekt wymaga prostszej i bardziej klasycznej architektury systemu kolejek wiadomości.&lt;/li&gt;
&lt;li&gt;Gdy zależy Ci na niskiej latencji oraz niezawodnej komunikacji między mikroserwisami lub aplikacjami.&lt;/li&gt;
&lt;li&gt;Gdy ilość danych nie jest tak wielka jak w przypadku rozbudowanych systemów strumieniowych, ale kluczowa jest spójność i pewność dostarczenia wiadomości.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Podsumowując, &lt;strong&gt;Kafka&lt;/strong&gt; jest idealna do strumieniowania dużych ilości danych i zastosowań wymagających wysokiej przepustowości, natomiast &lt;strong&gt;RabbitMQ&lt;/strong&gt; lepiej nadaje się do klasycznych zastosowań związanych z wymianą wiadomości i tasków, gdzie ważna jest elastyczność routingu i prostota integracji.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Dwa popularne standardy propagacji śledzenia komunikatów.</title>
      <dc:creator>Andrzej Korcz</dc:creator>
      <pubDate>Fri, 04 Oct 2024 13:17:32 +0000</pubDate>
      <link>https://dev.to/andrzej_korcz_9009de135d8/dwa-popularne-standardy-propagacji-sledzenia-komunikatow-3ffk</link>
      <guid>https://dev.to/andrzej_korcz_9009de135d8/dwa-popularne-standardy-propagacji-sledzenia-komunikatow-3ffk</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ljw2lkzwhs77ljhyw4a.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ljw2lkzwhs77ljhyw4a.jpeg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;W3C Trace Context&lt;/strong&gt; (standard propagacji śledzenia przyjęty przez W3C):
&lt;/h3&gt;

&lt;p&gt;Ten standard został wprowadzony, aby zapewnić jednolity format propagacji kontekstu śledzenia między różnymi systemami, serwisami i narzędziami. Działa niezależnie od implementacji i ma na celu ujednolicenie formatu w różnych środowiskach. W3C Trace Context składa się z dwóch kluczowych nagłówków:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;traceparent&lt;/code&gt;&lt;/strong&gt;: To główny nagłówek w W3C Trace Context. Zawiera najważniejsze informacje o kontekście śledzenia:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wersja&lt;/strong&gt;: Numer wersji standardu (obecnie &lt;code&gt;00&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trace ID&lt;/strong&gt;: Globalny unikalny identyfikator całego śledzenia (np. cała ścieżka od producenta do konsumenta).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parent ID (Span ID)&lt;/strong&gt;: Identyfikator spana reprezentującego bezpośredniego rodzica w śledzeniu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flagi&lt;/strong&gt;: Informacje na temat próbkowania (czy dany span ma być śledzony i przesyłany do systemu zbierającego).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Przykład nagłówka &lt;code&gt;traceparent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gdzie:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;00&lt;/code&gt; to wersja.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;4bf92f3577b34da6a3ce929d0e0e4736&lt;/code&gt; to &lt;code&gt;Trace ID&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;00f067aa0ba902b7&lt;/code&gt; to &lt;code&gt;Parent ID&lt;/code&gt; (Span ID).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;01&lt;/code&gt; to flagi (bit flagi próbkowania, gdzie &lt;code&gt;01&lt;/code&gt; oznacza, że span ma być śledzony).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tracestate&lt;/code&gt;&lt;/strong&gt;: To dodatkowy nagłówek używany w W3C Trace Context. Zawiera bardziej zaawansowane informacje, które mogą być specyficzne dla dostawcy systemu śledzenia (np. dodatkowe dane potrzebne narzędziu śledzącemu). Pozwala na propagowanie dodatkowych metadanych związanych z śledzeniem, np. priorytety lub informacje specyficzne dla narzędzia (np. Jaeger, Zipkin).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Przykład:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  tracestate: congo=t61rcWkgMzE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;B3 Propagation&lt;/strong&gt; (standard używany przez Zipkin):
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;B3&lt;/strong&gt; to inny, popularny standard propagacji kontekstu śledzenia, stosowany głównie w systemie &lt;strong&gt;Zipkin&lt;/strong&gt;, ale obsługiwany także przez inne tracery, takie jak Jaeger. B3 działa w sposób nieco prostszy niż W3C Trace Context i składa się z kilku nagłówków:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;x-B3-TraceId&lt;/code&gt;&lt;/strong&gt;: To globalny identyfikator śledzenia (trace). Odpowiada za identyfikację całego cyklu śledzenia, podobnie jak &lt;code&gt;Trace ID&lt;/code&gt; w W3C. Ten identyfikator jest unikalny dla całego śledzenia i pozwala połączyć wszystkie spany w jeden trace.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Przykład:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  x-B3-TraceId: 4bf92f3577b34da6a3ce929d0e0e4736
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;x-B3-ParentSpanId&lt;/code&gt;&lt;/strong&gt;: Identyfikator rodzica aktualnego spana. Ten nagłówek zawiera ID spana, który bezpośrednio poprzedza obecny span. Jest on podobny do &lt;code&gt;Parent ID&lt;/code&gt; w W3C Trace Context.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Przykład:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  x-B3-ParentSpanId: 00f067aa0ba902b7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;x-B3-SpanId&lt;/code&gt;&lt;/strong&gt;: To identyfikator spana w ramach śledzenia. Każdy span w trace ma swój unikalny identyfikator, który odróżnia go od innych spanów w danym trace. Jest podobny do &lt;code&gt;Parent ID&lt;/code&gt; w W3C Trace Context, ale dotyczy konkretnego spana, a nie rodzica.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Przykład:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  x-B3-SpanId: 00f067aa0ba902b7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;x-B3-Sampled&lt;/code&gt;&lt;/strong&gt;: To flaga określająca, czy dany span (i cały trace) powinien być próbkowany i wysyłany do systemu zbierającego. Możliwe wartości to:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;1&lt;/code&gt; oznacza, że span ma być śledzony.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0&lt;/code&gt; oznacza, że span nie będzie śledzony.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Przykład:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  x-B3-Sampled: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Podział nagłówków:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;W3C Trace Context&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;traceparent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tracestate&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;B3 Propagation (Zipkin)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;x-B3-TraceId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x-B3-ParentSpanId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x-B3-SpanId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x-B3-Sampled&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Jakie są różnice między tymi standardami?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;W3C Trace Context&lt;/strong&gt; jest bardziej nowoczesnym, ujednoliconym standardem wspieranym przez organizację W3C, co oznacza, że jest neutralny w stosunku do narzędzi do śledzenia (np. Jaeger, Zipkin). Umożliwia bardziej elastyczną propagację informacji o śledzeniu, w tym dostarczanie zaawansowanych metadanych poprzez &lt;code&gt;tracestate&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;B3&lt;/strong&gt; jest starszym standardem propagacji, który został wprowadzony przez &lt;strong&gt;Zipkin&lt;/strong&gt;. Jest prostszy i używa osobnych nagłówków dla każdego elementu kontekstu śledzenia (trace ID, span ID itd.), zamiast jednej złożonej struktury, jak w W3C Trace Context.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Co to oznacza dla Twojej aplikacji?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Twoja aplikacja aktualnie obsługuje zarówno W3C Trace Context (&lt;code&gt;traceparent&lt;/code&gt;, &lt;code&gt;tracestate&lt;/code&gt;), jak i B3 (&lt;code&gt;x-B3-*&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;W wielu przypadkach, systemy takie jak Jaeger, Zipkin, lub OpenTelemetry potrafią obsługiwać oba standardy, ale powinno się wybrać jeden spójny standard propagacji. Korzystanie z obu może wprowadzać zamieszanie i niespójności, zwłaszcza gdy różne systemy interpretują nagłówki inaczej.&lt;/li&gt;
&lt;li&gt;Jeśli chcesz mieć pełną kontrolę nad śledzeniem, najlepiej jest zdecydować się na jeden standard (najczęściej rekomendowany jest &lt;strong&gt;W3C Trace Context&lt;/strong&gt;, ponieważ jest to standard uznawany przez W3C i ma szersze wsparcie).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Jeśli twój system korzysta z różnych narzędzi do śledzenia (np. Jaeger, Zipkin) i musisz wspierać oba standardy, konieczne może być skonfigurowanie odpowiednich integracji lub middleware, które będą konwertować nagłówki między tymi standardami.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Łańcuch zależności wyjątków.</title>
      <dc:creator>Andrzej Korcz</dc:creator>
      <pubDate>Thu, 03 Oct 2024 18:03:08 +0000</pubDate>
      <link>https://dev.to/andrzej_korcz_9009de135d8/lancuch-zaleznosci-wyjatkow-45ha</link>
      <guid>https://dev.to/andrzej_korcz_9009de135d8/lancuch-zaleznosci-wyjatkow-45ha</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fualln98kpewkqfezkr.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fualln98kpewkqfezkr.jpeg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Łańcuch zależności wyjątków (ang. &lt;em&gt;exception chaining&lt;/em&gt;) to koncepcja programistyczna stosowana głównie w językach takich jak Java, która pomaga zachować pełny kontekst błędu poprzez połączenie kilku wyjątków w jeden ciąg. Oznacza to, że jeden wyjątek może być „powiązany” z innym, co pozwala śledzić całą sekwencję zdarzeń, które doprowadziły do danego błędu.&lt;/p&gt;

&lt;p&gt;Aby to lepiej zrozumieć, warto rozważyć kilka elementów:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. &lt;strong&gt;Cel łańcucha wyjątków&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Wyjątki mogą występować na różnych poziomach aplikacji — od niskopoziomowych operacji (np. błąd odczytu pliku) do bardziej abstrakcyjnych problemów (np. błędy biznesowe). Dzięki łańcuchowi zależności wyjątków możemy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zachować oryginalny wyjątek (czyli przyczynę pierwotną),&lt;/li&gt;
&lt;li&gt;Owinąć go nowym, bardziej specyficznym wyjątkiem (bardziej związanym z kontekstem aplikacji),&lt;/li&gt;
&lt;li&gt;Uzyskać pełną historię tego, co się wydarzyło od początkowego błędu do końca.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2. &lt;strong&gt;Jak to działa?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;W praktyce, podczas obsługi wyjątku można przekazać oryginalny wyjątek (tzw. &lt;em&gt;cause&lt;/em&gt;) jako argument do nowego wyjątku. Umożliwia to przekazanie informacji o pierwotnym błędzie i dodanie dodatkowego kontekstu. Zasadniczo wygląda to tak:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;   &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="c1"&gt;// Kod, który może wygenerować wyjątek&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CustomException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Błąd podczas przetwarzania pliku"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;W tym przykładzie &lt;code&gt;IOException&lt;/code&gt; jest pierwotnym wyjątkiem, który zostaje złapany. Następnie rzucamy nowym wyjątkiem &lt;code&gt;CustomException&lt;/code&gt;, który zawiera wiadomość „Błąd podczas przetwarzania pliku” oraz odniesienie do oryginalnego wyjątku &lt;code&gt;IOException&lt;/code&gt;. Dzięki temu możemy śledzić cały łańcuch błędów.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Dlaczego to jest ważne?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Utrzymanie kontekstu&lt;/strong&gt;: Zamiast "zgubić" pierwotny wyjątek, możemy go przekazać dalej, co jest przydatne, gdy chcemy dowiedzieć się, co dokładnie spowodowało problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lepsze debugowanie&lt;/strong&gt;: Dzięki łańcuchowi wyjątków, gdy aplikacja wyrzuci nowy wyjątek, jesteśmy w stanie śledzić całą sekwencję wyjątków (np. z poziomu logów czy stack trace), co ułatwia diagnozowanie problemu.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Hierarchia wyjątków&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;W Javie wszystkie wyjątki dziedziczą od klasy &lt;code&gt;Throwable&lt;/code&gt;. Każdy wyjątek ma pole &lt;code&gt;cause&lt;/code&gt;, które przechowuje oryginalny wyjątek (jeśli został podany). W przypadku wystąpienia wyjątku możemy sprawdzić całą hierarchię zależności wyjątków, analizując stos wywołań (ang. &lt;em&gt;stack trace&lt;/em&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Klasa &lt;code&gt;Throwable&lt;/code&gt; zawiera metodę &lt;code&gt;getCause()&lt;/code&gt;, która zwraca wyjątek, który spowodował bieżący problem. Jeśli nie ma przyczyny, zwracany jest &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Konstruktor &lt;code&gt;Throwable&lt;/code&gt; (oraz klas pochodnych takich jak &lt;code&gt;Exception&lt;/code&gt; czy &lt;code&gt;RuntimeException&lt;/code&gt;) pozwala na przekazanie „przyczyny” poprzez drugi argument:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Throwable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="n"&gt;cause&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Spring Boot i łańcuch wyjątków&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;W Spring Boot, łańcuch zależności wyjątków jest szczególnie przydatny w kontekście aplikacji webowych. Jeśli na przykład aplikacja rzuci wyjątek na poziomie bazy danych (np. &lt;code&gt;DataAccessException&lt;/code&gt;), można przekazać ten wyjątek dalej, a Spring Boot może go automatycznie przetworzyć i zwrócić odpowiedni komunikat HTTP do klienta.&lt;/p&gt;

&lt;p&gt;Przykład w Spring Boot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;   &lt;span class="nd"&gt;@Service&lt;/span&gt;
   &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processFile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
           &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
               &lt;span class="c1"&gt;// Operacje na pliku&lt;/span&gt;
           &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
               &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FileProcessingException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Błąd przetwarzania pliku: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
           &lt;span class="o"&gt;}&lt;/span&gt;
       &lt;span class="o"&gt;}&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jeśli &lt;code&gt;IOException&lt;/code&gt; zostanie wyrzucony, &lt;code&gt;FileProcessingException&lt;/code&gt; go „owinie” i doda dodatkowe informacje. Łańcuch ten można przekazać dalej do kontrolera, który obsługuje wyjątki w aplikacji webowej.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. &lt;strong&gt;Stack trace i debugowanie&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kiedy aplikacja wyrzuci wyjątek, z którym łańcuch wyjątków jest powiązany, możemy zauważyć w stack trace wszystkie przyczyny błędów. Na przykład:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   Exception in thread "main" CustomException: Błąd podczas przetwarzania pliku
    at com.example.FileProcessor.processFile(FileProcessor.java:25)
    at com.example.Main.main(Main.java:10)
   Caused by: java.io.IOException: Plik nie istnieje
    at com.example.FileProcessor.readFile(FileProcessor.java:15)
    ... 1 more
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;W powyższym przykładzie widzimy, że &lt;code&gt;CustomException&lt;/code&gt; został wyrzucony z powodu &lt;code&gt;IOException&lt;/code&gt;. Takie informacje są kluczowe w diagnozowaniu problemów w aplikacji.&lt;/p&gt;

&lt;h3&gt;
  
  
  Podsumowanie
&lt;/h3&gt;

&lt;p&gt;Łańcuch zależności wyjątków w Javie (i w Spring Boot) pozwala na lepsze śledzenie źródeł błędów, dodając do nich dodatkowy kontekst i umożliwiając bardziej precyzyjne debugowanie. Jest to niezwykle przydatne w aplikacjach o większej złożoności, gdzie wyjątki mogą pojawiać się na różnych poziomach abstrakcji.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Korzyści z użycia wirtualnych wątków w aplikacji Spring Boot</title>
      <dc:creator>Andrzej Korcz</dc:creator>
      <pubDate>Tue, 01 Oct 2024 07:10:28 +0000</pubDate>
      <link>https://dev.to/andrzej_korcz_9009de135d8/korzysci-z-uzycia-wirtualnych-watkow-w-aplikacji-spring-boot-m4g</link>
      <guid>https://dev.to/andrzej_korcz_9009de135d8/korzysci-z-uzycia-wirtualnych-watkow-w-aplikacji-spring-boot-m4g</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh62rgbo84r8m4be3burp.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh62rgbo84r8m4be3burp.jpeg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Korzyści z użycia wirtualnych wątków w aplikacji Spring Boot są bardziej wyraźne w sytuacjach wymagających intensywnej współbieżności i asynchroniczności. Oto omówienie zalet i przykładów, gdzie wirtualne wątki mają sens:&lt;/p&gt;

&lt;h3&gt;
  
  
  Zalety Wirtualnych Wątków:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Obsługa Wysokiej Liczby Współbieżnych Połączeń:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tradycyjne wątki w Javie są zasobożerne — każde stworzenie wątku systemowego wymaga pamięci i zasobów CPU. Przy dużej liczbie jednoczesnych połączeń (np. setki tysięcy żądań HTTP do serwera) system zaczyna się przeciążać. Wirtualne wątki są znacznie lżejsze, ponieważ JVM może tworzyć miliony wirtualnych wątków, które zarządzane są w bardziej efektywny sposób.&lt;/li&gt;
&lt;li&gt;W kontekście aplikacji webowych lub mikroserwisowych, które często obsługują tysiące jednoczesnych zapytań (HTTP, zapytania do bazy danych, zewnętrzne API), wirtualne wątki pozwalają na łatwiejsze skalowanie.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Efektywniejsze Przetwarzanie I/O:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;W aplikacjach Spring Boot wiele operacji opiera się na I/O (wejście-wyjście), np. odpytywanie baz danych, komunikacja z zewnętrznymi serwisami przez API, odczyt/zapis plików, przesyłanie danych po sieci. Operacje I/O są naturalnie blokujące i czekanie na odpowiedź może zablokować tradycyjny wątek systemowy.&lt;/li&gt;
&lt;li&gt;Wirtualne wątki pozwalają na bardziej efektywne zarządzanie operacjami I/O, ponieważ mogą być łatwo zawieszane i wznawiane, gdy dane są dostępne, bez blokowania zasobów systemowych (np. CPU, pamięci).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Prostszy Model Programowania:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tradycyjnie w Javie do obsługi asynchronicznych operacji używało się wątków, puli wątków lub bardziej skomplikowanych mechanizmów, takich jak &lt;code&gt;CompletableFuture&lt;/code&gt;, czy programowanie reaktywne (Reactor, RxJava). Chociaż te podejścia działają, mogą wprowadzać pewną złożoność i trudności z zarządzaniem współbieżnością.&lt;/li&gt;
&lt;li&gt;Dzięki wirtualnym wątkom, programiści mogą używać bardziej intuicyjnych konstrukcji blokujących (takich jak &lt;code&gt;Thread.sleep()&lt;/code&gt; czy klasyczne &lt;code&gt;I/O&lt;/code&gt;), a JVM sam optymalizuje zarządzanie wątkami. Zyskujemy więc prostszy model programowania, zachowując efektywność współbieżności.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lepsza Skalowalność Aplikacji:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;W przypadku serwisów mikroserwisowych czy serwerów HTTP, wirtualne wątki pozwalają na większą skalowalność bez konieczności przepisania aplikacji na programowanie reaktywne. Umożliwia to łatwe zwiększenie liczby jednoczesnych połączeń (przepustowości) przy mniejszym zużyciu zasobów.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Przykłady Użycia Wirtualnych Wątków:
&lt;/h3&gt;

&lt;p&gt;Aby lepiej zrozumieć, gdzie wirtualne wątki mogą mieć sens, przyjrzyjmy się bardziej realistycznym scenariuszom:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Serwisy Mikroserwisowe (HTTP i Bazy Danych)&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Załóżmy, że mamy serwis mikroserwisowy, który obsługuje wiele zapytań HTTP, a każde z tych zapytań odpytywało bazę danych oraz zewnętrzny serwis przez API. W takim przypadku tradycyjne wątki byłyby blokowane podczas oczekiwania na odpowiedzi z bazy danych oraz z zewnętrznego serwisu, co zmniejsza wydajność.&lt;/p&gt;

&lt;p&gt;W przypadku wirtualnych wątków można napisać kod w sposób blokujący (czyli używać klasycznych operacji I/O), ale JVM nie będzie blokował systemowych zasobów, gdy wątek czeka na dane z bazy lub z sieci.&lt;/p&gt;

&lt;p&gt;Przykład:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/data"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Wirtualny wątek pobiera dane z bazy&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;dbResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;databaseService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;queryData&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Operacja blokująca (I/O)&lt;/span&gt;

        &lt;span class="c1"&gt;// Wirtualny wątek pobiera dane z zewnętrznego serwisu&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;apiResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;externalApiService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fetchData&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Operacja blokująca (I/O)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Wynik: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dbResult&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;", "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;apiResult&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Błąd podczas przetwarzania danych!"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;W tym przykładzie:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tradycyjnie użycie blokujących zapytań do bazy danych i zewnętrznych API mogłoby wymagać reaktywnego programowania lub specjalnego zarządzania wątkami.&lt;/li&gt;
&lt;li&gt;Wirtualne wątki pozwalają na blokujący kod bez wydajnościowych kompromisów — można efektywnie skalować aplikację bez dodawania złożoności.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Asynchroniczne Pobieranie Danych z Kilku Źródeł&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Często w aplikacjach webowych konieczne jest pobranie danych z kilku różnych źródeł (np. API, bazy danych, innych serwisów) w odpowiedzi na jedno zapytanie użytkownika.&lt;/p&gt;

&lt;p&gt;Z wirtualnymi wątkami możemy łatwo uruchomić te zapytania asynchronicznie, korzystając z prostego modelu wątków, bez potrzeby używania bardziej skomplikowanych mechanizmów jak &lt;code&gt;CompletableFuture&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/fetch-multiple"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;fetchMultipleSources&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Executor&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newVirtualThreadPerTaskExecutor&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;future1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;supplyAsync&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;service1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getData&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;future2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CompletableFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;supplyAsync&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;service2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getData&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Czekamy na wyniki obu operacji&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;result1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;future1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;future2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Wyniki: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;result1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" oraz "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tutaj:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Każde zapytanie do serwisów&lt;/strong&gt; (service1 i service2) uruchamiane jest w osobnym wirtualnym wątku.&lt;/li&gt;
&lt;li&gt;W przypadku aplikacji mikroserwisowych, gdzie aplikacja często komunikuje się z wieloma zewnętrznymi serwisami, takie rozwiązanie pozwala na prostą obsługę dużej liczby równoczesnych połączeń, bez obciążenia zasobów systemu.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Podsumowanie
&lt;/h3&gt;

&lt;p&gt;Wirtualne wątki w Javie 21 przynoszą ogromne korzyści w aplikacjach, które są mocno współbieżne i zależne od operacji I/O. Dzięki nim można:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skalować aplikację do obsługi większej liczby jednoczesnych żądań przy niższym zużyciu zasobów.&lt;/li&gt;
&lt;li&gt;Upraszczać kod współbieżny (mniej kodu reaktywnego lub zaawansowanego zarządzania wątkami).&lt;/li&gt;
&lt;li&gt;Używać prostszego modelu programowania (blokującego), ale z efektywnością asynchronicznego wykonania.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wirtualne wątki umożliwiają łatwe tworzenie aplikacji webowych czy mikroserwisów, które mogą obsługiwać więcej użytkowników i połączeń bez konieczności pisania złożonego kodu.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Różnice między bibliotekami a starterami w Spring Boot</title>
      <dc:creator>Andrzej Korcz</dc:creator>
      <pubDate>Sat, 28 Sep 2024 11:00:11 +0000</pubDate>
      <link>https://dev.to/andrzej_korcz_9009de135d8/roznice-miedzy-bibliotekami-a-starterami-w-spring-boot-4mlo</link>
      <guid>https://dev.to/andrzej_korcz_9009de135d8/roznice-miedzy-bibliotekami-a-starterami-w-spring-boot-4mlo</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzho5ysx1gjl5aq0w0ib1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzho5ysx1gjl5aq0w0ib1.jpeg" alt="Image description"&gt;&lt;/a&gt;Biblioteki &lt;strong&gt;Spring Boot Starter&lt;/strong&gt; to specjalne, predefiniowane pakiety w ekosystemie Spring, które mają na celu uproszczenie zarządzania zależnościami i konfiguracją dla różnych funkcjonalności. Ich zadaniem jest zapewnienie gotowej paczki zależności i podstawowej konfiguracji dla konkretnych scenariuszy, takich jak dostęp do bazy danych, obsługa aplikacji webowych czy logowanie.&lt;/p&gt;

&lt;p&gt;Różnica między starterami a zwykłymi bibliotekami, polega głównie na &lt;strong&gt;celu&lt;/strong&gt; i &lt;strong&gt;strukturze&lt;/strong&gt;. Wyjaśnię to bardziej szczegółowo:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Co to są biblioteki typu "starter"?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Startery Spring Boot to specjalne pakiety, które zawierają &lt;strong&gt;predefiniowane zestawy zależności&lt;/strong&gt; niezbędne do implementacji określonej funkcji. Są to głównie paczki ułatwiające życie programistom, pozwalając na szybkie dodanie odpowiednich bibliotek do projektu i eliminując potrzebę ręcznego zarządzania wieloma zależnościami. &lt;/p&gt;

&lt;p&gt;Na przykład:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;spring-boot-starter-web&lt;/code&gt; to starter odpowiedzialny za aplikacje webowe. Zawiera wszystkie niezbędne zależności, takie jak &lt;strong&gt;Spring MVC&lt;/strong&gt;, &lt;strong&gt;Tomcat&lt;/strong&gt; jako domyślny kontener aplikacji, oraz inne kluczowe biblioteki do tworzenia aplikacji webowych.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;spring-boot-starter-data-jpa&lt;/code&gt; to starter do obsługi &lt;strong&gt;JPA&lt;/strong&gt; (Java Persistence API), który automatycznie dodaje zależności do &lt;strong&gt;Hibernate&lt;/strong&gt;, &lt;strong&gt;Spring Data JPA&lt;/strong&gt; oraz baz danych.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;W porównaniu do zwykłej biblioteki, starter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nie oferuje bezpośrednio logiki biznesowej lub narzędzi, ale dostarcza &lt;strong&gt;zestaw zależności&lt;/strong&gt;, które są typowo potrzebne dla konkretnego rodzaju aplikacji.&lt;/li&gt;
&lt;li&gt;Startery mają na celu &lt;strong&gt;ułatwienie konfiguracji&lt;/strong&gt; oraz szybszy start w pracy z różnymi komponentami Spring Boot.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Różnica między starterami a zwykłą biblioteką&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Przykładowo biblioteka (np. &lt;code&gt;StringUtils&lt;/code&gt;) jest zazwyczaj prostą biblioteką narzędziową, która dostarczała konkretne funkcje (metody) do pracy z ciągami znaków. W przeciwieństwie do tego, startery &lt;strong&gt;Spring Boot&lt;/strong&gt; są bardziej zestawami zależności i konfiguracji, a nie konkretnymi implementacjami logiki.&lt;/p&gt;

&lt;h4&gt;
  
  
  Kluczowe różnice:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cel&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zwykła biblioteka&lt;/strong&gt; (jak nasz przykład &lt;code&gt;StringUtils&lt;/code&gt;) dostarcza pewne narzędzia lub logikę biznesową do użycia w aplikacjach.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Starter&lt;/strong&gt; dostarcza zestaw &lt;strong&gt;zależności i konfiguracji&lt;/strong&gt;, potrzebnych do korzystania z określonej technologii lub komponentu Spring Boot.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Zarządzanie zależnościami&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;W przypadku zwykłej biblioteki sam definiujesz jej zależności i konfigurację.&lt;/li&gt;
&lt;li&gt;Starter automatycznie dodaje wszystkie niezbędne zależności oraz domyślne konfiguracje, eliminując konieczność ręcznego zarządzania nimi.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Użyteczność&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Biblioteka dostarcza &lt;strong&gt;konkretne funkcje&lt;/strong&gt; lub klasy do użycia w kodzie (np. &lt;code&gt;StringUtils&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Starter dostarcza &lt;strong&gt;komponenty, konfiguracje i zależności&lt;/strong&gt;, które są używane przez Spring Boot do automatycznego zarządzania komponentami aplikacji (np. konfiguracja bazy danych, systemu logowania).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Jak stworzyć własny starter?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Możesz stworzyć własny starter Spring Boot, który będzie działał podobnie jak oficjalne startery. Taki starter będzie zawierał gotową paczkę zależności i może dodać domyślną konfigurację dla innych projektów.&lt;/p&gt;

&lt;h4&gt;
  
  
  Przykład tworzenia własnego startera:
&lt;/h4&gt;

&lt;p&gt;Załóżmy, że chcemy stworzyć starter, który automatycznie dodaje naszą klasę &lt;code&gt;StringUtils&lt;/code&gt; oraz pewne domyślne zależności. Poniżej pokazuję, jak to zrobić.&lt;/p&gt;

&lt;h4&gt;
  
  
  Krok 1: Struktura projektu
&lt;/h4&gt;

&lt;p&gt;Struktura projektu wygląda podobnie jak w przypadku zwykłej biblioteki, ale z tą różnicą, że starter będzie zawierał &lt;strong&gt;domyślną konfigurację&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Krok 2: Konfiguracja &lt;code&gt;build.gradle&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;plugins&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="s1"&gt;'java'&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="s1"&gt;'maven-publish'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'com.example'&lt;/span&gt;
&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'1.0.0'&lt;/span&gt;
&lt;span class="n"&gt;sourceCompatibility&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'22'&lt;/span&gt;

&lt;span class="n"&gt;repositories&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;mavenCentral&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Domyślne zależności, które będą dodane automatycznie&lt;/span&gt;
    &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="s1"&gt;'org.springframework.boot:spring-boot-starter:3.3.4'&lt;/span&gt;
    &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="s1"&gt;'org.springframework.boot:spring-boot-starter-logging'&lt;/span&gt;

    &lt;span class="c1"&gt;// Możesz dodać więcej zależności, np. do baz danych, logowania itp.&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;publishing&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;publications&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;mavenJava&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MavenPublication&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;java&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Krok 3: Automatyczna konfiguracja
&lt;/h4&gt;

&lt;p&gt;W Spring Boot startery mogą również automatycznie konfigurować różne komponenty przy uruchomieniu aplikacji. Stwórz klasę konfiguracyjną w swoim starterze.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.example.common&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.context.annotation.Bean&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.context.annotation.Configuration&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Configuration&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CommonLibraryAutoConfiguration&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;StringUtils&lt;/span&gt; &lt;span class="nf"&gt;stringUtils&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;StringUtils&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Klasa &lt;code&gt;CommonLibraryAutoConfiguration&lt;/code&gt; jest oznaczona adnotacją &lt;code&gt;@Configuration&lt;/code&gt;, co oznacza, że Spring Boot automatycznie wykryje i skonfiguruje komponenty (w tym wypadku klasę &lt;code&gt;StringUtils&lt;/code&gt;) w aplikacji, która będzie używać tego startera.&lt;/p&gt;

&lt;h4&gt;
  
  
  Krok 4: Plik &lt;code&gt;spring.factories&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Aby Spring Boot wiedział, że Twoja konfiguracja powinna być automatycznie załadowana, musisz dodać plik &lt;code&gt;spring.factories&lt;/code&gt; do katalogu &lt;code&gt;resources/META-INF/&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources/
└── META-INF/
    └── spring.factories
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;W pliku &lt;code&gt;spring.factories&lt;/code&gt; wpisz:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.common.CommonLibraryAutoConfiguration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dzięki temu Spring Boot będzie wiedział, że klasa &lt;code&gt;CommonLibraryAutoConfiguration&lt;/code&gt; powinna być automatycznie załadowana przy starcie aplikacji.&lt;/p&gt;

&lt;h4&gt;
  
  
  Krok 5: Publikacja startera
&lt;/h4&gt;

&lt;p&gt;Podobnie jak w przypadku zwykłej biblioteki, opublikuj swój starter, korzystając z polecenia:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew publishToMavenLocal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Krok 6: Użycie startera
&lt;/h4&gt;

&lt;p&gt;Aby użyć tego startera w innym projekcie, wystarczy dodać jego zależność w pliku &lt;code&gt;build.gradle&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;implementation&lt;/span&gt; &lt;span class="s1"&gt;'com.example:my-starter:1.0.0'&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Spring Boot automatycznie załaduje konfigurację i zarejestruje komponent &lt;code&gt;StringUtils&lt;/code&gt; bez potrzeby ręcznej konfiguracji.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Podsumowanie różnic&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Starter&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zawiera zestaw zależności.&lt;/li&gt;
&lt;li&gt;Może dodawać domyślną konfigurację i automatycznie rejestrować komponenty Spring Boot.&lt;/li&gt;
&lt;li&gt;Upraszcza pracę poprzez automatyczne zarządzanie konfiguracją i komponentami.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Zwykła biblioteka&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zawiera konkretne funkcje lub narzędzia, ale nie zarządza zależnościami czy konfiguracją automatycznie.&lt;/li&gt;
&lt;li&gt;Użytkownik musi sam dodać zależności i odpowiednio skonfigurować komponenty.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Startery są więc bardziej "plug-and-play", a zwykłe biblioteki wymagają więcej ręcznego zarządzania zależnościami i konfiguracją.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
