<?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>Forem: Rachid</title>
    <description>The latest articles on Forem by Rachid (@rachidrabou).</description>
    <link>https://forem.com/rachidrabou</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2928167%2Fa908ca37-8d98-4621-9957-65d65ecd7f5f.jpeg</url>
      <title>Forem: Rachid</title>
      <link>https://forem.com/rachidrabou</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rachidrabou"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Rachid</dc:creator>
      <pubDate>Wed, 29 Oct 2025 09:52:12 +0000</pubDate>
      <link>https://forem.com/rachidrabou/-19a9</link>
      <guid>https://forem.com/rachidrabou/-19a9</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/rachidrabou" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2928167%2Fa908ca37-8d98-4621-9957-65d65ecd7f5f.jpeg" alt="rachidrabou"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/rachidrabou/spring-boot-stop-using-value-everywhere-discover-configurationproperties-1h93" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Spring Boot: Stop Using @Value Everywhere! Discover @ConfigurationProperties&lt;/h2&gt;
      &lt;h3&gt;Rachid ・ Oct 29&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#springboot&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#java&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#bestofdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>springboot</category>
      <category>java</category>
      <category>tutorial</category>
      <category>bestofdev</category>
    </item>
    <item>
      <title>Spring Boot: Stop Using @Value Everywhere! Discover @ConfigurationProperties</title>
      <dc:creator>Rachid</dc:creator>
      <pubDate>Wed, 29 Oct 2025 09:45:45 +0000</pubDate>
      <link>https://forem.com/rachidrabou/spring-boot-stop-using-value-everywhere-discover-configurationproperties-1h93</link>
      <guid>https://forem.com/rachidrabou/spring-boot-stop-using-value-everywhere-discover-configurationproperties-1h93</guid>
      <description>&lt;p&gt;Hey dev community! &lt;/p&gt;

&lt;p&gt;When working on Spring Boot projects, we all need to read values from our application.properties or application.yml files.&lt;/p&gt;

&lt;p&gt;Most of us start by using the @Value annotation to inject each property one by one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem (The "Old Way")&lt;/strong&gt;&lt;br&gt;
As your application grows, your service or configuration class starts to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Service
public class MyOldService {

    @Value("${app.api.url}")
    private String apiUrl;

    @Value("${app.api.key}")
    private String apiKey;

    @Value("${app.feature.toggle.new-feature}")
    private boolean featureToggle;

    @Value("${app.thread-pool-size}")
    private int poolSize;

    // ... and it goes on and on
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is verbose, hard to maintain, and not type-safe (just Strings and primitives). If you mistype a prefix, everything breaks at runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution: @ConfigurationProperties&lt;/strong&gt;&lt;br&gt;
Spring Boot offers a much cleaner, safer, and more organized way to manage your configuration: the @ConfigurationProperties annotation.&lt;/p&gt;

&lt;p&gt;The idea is simple: map an entire block of your configuration file to a single Java object (a POJO or a Record).&lt;/p&gt;

&lt;p&gt;Let's see how.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 1: Your application.yml file&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Structure your properties logically. It's much more readable!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app:
  name: "My Awesome Service"
  feature-toggle:
    new-feature: true
    beta-access: false
  api:
    url: "https://api.example.com"
    key: "your-secret-api-key"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 2: Create the Configuration Class&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
We'll create a class (or even better, a Java 17+ record) that represents this structure.&lt;/p&gt;

&lt;p&gt;Note: For this to work with records (constructor binding), you need a recent version of Spring Boot (3+). Otherwise, use a classic class with getters and setters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.springframework.boot.context.properties.ConfigurationProperties;

// The "app" prefix matches the root of our config
@ConfigurationProperties(prefix = "app")
public record AppProperties(
    String name, 
    ApiConfig api,
    FeatureToggle featureToggle
) {

    // We can even have nested objects!
    public record ApiConfig(String url, String key) {}

    public record FeatureToggle(boolean newFeature, boolean betaAccess) {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 3: Enable the Configuration&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
We need to tell Spring to scan and activate this class. The easiest way is on your main application class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class) // &amp;lt;-- The key step!
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 4: Use Your Configuration (The Clean Way!)&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Now, instead of injecting 10 @Value fields, you just inject one single bean, perfectly typed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Service
public class MyNewService {

    private final AppProperties appProperties;

    // Constructor injection (always a good practice!)
    public MyNewService(AppProperties appProperties) {
        this.appProperties = appProperties;
    }

    public void doSomething() {
        String url = appProperties.api().url(); // Clean!
        String key = appProperties.api().key(); // Type-safe!

        if (appProperties.featureToggle().newFeature()) {
            // ... new feature logic
        }

        System.out.println("App name: " + appProperties.name());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why This is 100x Better&lt;/strong&gt;&lt;br&gt;
Type-Safe: No more 'String' vs. 'int' errors. You're handling a real Java object.&lt;/p&gt;

&lt;p&gt;Centralized: All 'app'-related configuration is in one single class.&lt;/p&gt;

&lt;p&gt;Validation: You can add validation annotations (@Validated, &lt;a class="mentioned-user" href="https://dev.to/min"&gt;@min&lt;/a&gt;, @NotEmpty) directly to the fields of your AppProperties class!&lt;/p&gt;

&lt;p&gt;Auto-completion (The Pro-Tip):&lt;br&gt;
If you add this dependency to your pom.xml (or Gradle), your IDE will give you auto-completion right in your .yml or .properties file!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-boot-configuration-processor&amp;lt;/artifactId&amp;gt;
    &amp;lt;optional&amp;gt;true&amp;lt;/optional&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
Stop fighting with @Value. For any configuration that's more than two or three keys, switch to @ConfigurationProperties. It's cleaner, more robust, and much more maintainable.&lt;/p&gt;

&lt;p&gt;What's your favorite Spring Boot tip? Let me know in the comments! 👇&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>java</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Spring Boot Pro Tip: Boost Performance with @Cacheable + Java 17</title>
      <dc:creator>Rachid</dc:creator>
      <pubDate>Mon, 17 Mar 2025 13:45:58 +0000</pubDate>
      <link>https://forem.com/rachidrabou/spring-boot-pro-tip-boost-performance-with-cacheable-java-17-2dgm</link>
      <guid>https://forem.com/rachidrabou/spring-boot-pro-tip-boost-performance-with-cacheable-java-17-2dgm</guid>
      <description>&lt;p&gt;If your Spring Boot app is hitting the database too often and slowing down, you need caching! Using @Cacheable, you can reduce unnecessary queries, speed up responses, and improve scalability.&lt;/p&gt;

&lt;p&gt;Let’s explore how to cache efficiently and avoid common pitfalls.&lt;/p&gt;

&lt;p&gt;The Problem: Too Many Database Calls&lt;br&gt;
Imagine we have a user service fetching data from the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Service
public class UserService {
    @Autowired private UserRepository userRepository;

    public User getUserById(Long id) {
        return userRepository.findById(id).orElseThrow();
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every time getUserById() is called, it hits the database. But do we really need to fetch the same user multiple times?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The Solution: @Cacheable&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Spring Boot makes caching easy. Just add @EnableCaching in your main class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@SpringBootApplication
@EnableCaching
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, modify your service to cache users:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Service
public class UserService {
    @Autowired private UserRepository userRepository;

    @Cacheable("users")
    public User getUserById(Long id) {
        return userRepository.findById(id).orElseThrow();
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when getUserById(id) is called multiple times, it returns the cached result instead of querying the database again!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Fine-Tuning the Cache&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
By default, @Cacheable caches results forever. To control expiration, use Caffeine or Redis.&lt;br&gt;
&lt;strong&gt;Use Caffeine for In-Memory Caching (Fast &amp;amp; Lightweight)&lt;/strong&gt;&lt;br&gt;
Add the dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.github.ben-manes.caffeine&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;caffeine&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;3.0.6&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, configure the cache with TTL (Time-To-Live) settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Configuration
public class CacheConfig {
    @Bean
    public CacheManager cacheManager() {
        return new CaffeineCacheManager("users");
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures cached users expire after a certain period, preventing stale data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Use Redis for Distributed Caching (Great for Microservices)&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
For scalability, store cached data in Redis:&lt;/p&gt;

&lt;p&gt;Add Redis dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-boot-starter-data-redis&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure Redis in application.yml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring:
  redis:
    host: localhost
    port: 6379

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use Redis as Cache Manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Configuration
public class RedisConfig {
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        return RedisCacheManager.builder(connectionFactory).build();
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result: The cache is shared across multiple instances, perfect for cloud deployments!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Common Cache Mistakes to Avoid&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Forgetting to update the cache when data changes&lt;br&gt;
 Use @CachePut to update cache when saving new data&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@CachePut(value = "users", key = "#user.id")
public User saveUser(User user) {
    return userRepository.save(user);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caching large objects&lt;br&gt;
 Cache only frequent, small, and non-sensitive data&lt;/p&gt;

&lt;p&gt;Not setting an expiration time&lt;br&gt;
 Always define TTL to prevent outdated data issues&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>java</category>
      <category>caching</category>
      <category>redis</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Rachid</dc:creator>
      <pubDate>Mon, 10 Mar 2025 15:36:08 +0000</pubDate>
      <link>https://forem.com/rachidrabou/-4321</link>
      <guid>https://forem.com/rachidrabou/-4321</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/rachidrabou" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2928167%2Fa908ca37-8d98-4621-9957-65d65ecd7f5f.jpeg" alt="rachidrabou"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/rachidrabou/spring-boot-pro-tip-the-hidden-power-of-transactionaleventlistener-1h0d" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;🚀 Spring Boot Pro Tip: The Hidden Power of @TransactionalEventListener!&lt;/h2&gt;
      &lt;h3&gt;Rachid ・ Mar 10&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#springboot&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#java&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>springboot</category>
      <category>java</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>💻 6+ years of coding… and still learning!</title>
      <dc:creator>Rachid</dc:creator>
      <pubDate>Mon, 10 Mar 2025 12:27:29 +0000</pubDate>
      <link>https://forem.com/rachidrabou/6-years-of-coding-and-still-learning-771</link>
      <guid>https://forem.com/rachidrabou/6-years-of-coding-and-still-learning-771</guid>
      <description>&lt;p&gt;I just took a look at my GitHub activity since 2018, and it made me realize how far I’ve come. From my first commits back then to my peak in 2021 (where I was super active with 287 contributions), I’ve been on a non-stop journey of learning, building, and improving.&lt;/p&gt;

&lt;p&gt;Lately, I’ve been more focused on freelance projects and real-world applications with Spring Boot &amp;amp; Angular, which means fewer open-source contributions. But I’m planning to change that!&lt;/p&gt;

&lt;p&gt;🚀 My goals for 2024-2025:&lt;br&gt;
✅ Get back into open-source &amp;amp; share more code&lt;br&gt;
✅ Keep refining my skills in Spring Boot &amp;amp; Angular&lt;br&gt;
✅ Build &amp;amp; contribute to projects that actually help developers&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fcjxwb5w9g3nhcv1lqvod.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcjxwb5w9g3nhcv1lqvod.PNG" alt=" " width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>angular</category>
      <category>aws</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>🚀 Spring Boot Pro Tip: The Hidden Power of @TransactionalEventListener!</title>
      <dc:creator>Rachid</dc:creator>
      <pubDate>Mon, 10 Mar 2025 11:36:05 +0000</pubDate>
      <link>https://forem.com/rachidrabou/spring-boot-pro-tip-the-hidden-power-of-transactionaleventlistener-1h0d</link>
      <guid>https://forem.com/rachidrabou/spring-boot-pro-tip-the-hidden-power-of-transactionaleventlistener-1h0d</guid>
      <description>&lt;p&gt;Did you know that Spring Boot allows you to execute code after a transaction is committed using @TransactionalEventListener? Most developers use @EventListener, but this hidden gem ensures your logic only runs if the transaction succeeds.&lt;br&gt;
&lt;strong&gt;Problem: When Events Fire Too Early&lt;/strong&gt;&lt;br&gt;
Imagine you're saving a user and sending a welcome email before the transaction commits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class UserCreatedEvent {
    private final User user;

    public UserCreatedEvent(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component
public class UserEventListener {
    @EventListener
    public void handleUserCreated(UserCreatedEvent event) {
        emailService.sendWelcomeEmail(event.getUser()); //  Runs even if transaction fails!
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the database transaction fails, the email is still sent, leading to inconsistencies.&lt;/p&gt;

&lt;p&gt;Solution: @TransactionalEventListener&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component
public class UserEventListener {
    @TransactionalEventListener
    public void handleUserCreated(UserCreatedEvent event) {
        emailService.sendWelcomeEmail(event.getUser()); //  Runs ONLY if the transaction is committed!
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the event fires only if the transaction succeeds!&lt;br&gt;
&lt;strong&gt;How to Use It in a Spring Boot App&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Publish an Event Inside a Transaction
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Service
public class UserService {
    @Autowired private ApplicationEventPublisher publisher;
    @Autowired private UserRepository userRepository;

    @Transactional
    public void createUser(String name, String email) {
        User user = userRepository.save(new User(name, email));
        publisher.publishEvent(new UserCreatedEvent(user)); //  Event is published
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Listen to the Event After Transaction Commits
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component
public class UserEventListener {
    @TransactionalEventListener
    public void handleUserCreated(UserCreatedEvent event) {
        System.out.println("User created: " + event.getUser().getEmail());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Guaranteed execution only if the transaction is successful.&lt;br&gt;
&lt;strong&gt;Why is This Useful?&lt;/strong&gt;&lt;br&gt;
Prevents sending emails, messages, or notifications for failed transactions.&lt;br&gt;
Ensures event-driven logic only executes when the database is consistent.&lt;br&gt;
Perfect for logging, auditing, and triggering external services.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>java</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Say Goodbye to Boilerplate with Java 17 Records</title>
      <dc:creator>Rachid</dc:creator>
      <pubDate>Mon, 10 Mar 2025 11:28:51 +0000</pubDate>
      <link>https://forem.com/rachidrabou/say-goodbye-to-boilerplate-with-java-17-records-2ae8</link>
      <guid>https://forem.com/rachidrabou/say-goodbye-to-boilerplate-with-java-17-records-2ae8</guid>
      <description>&lt;p&gt;Spring Boot applications deal a lot with DTOs, responses, and immutable objects. Java 17’s record feature makes our lives easier:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class User {
    private String name;
    private String email;
    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }
    public String getName() { return name; }
    public String getEmail() { return email; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After (Using Java 17 record 🎉)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public record User(String name, String email) {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ No more boilerplate.&lt;br&gt;
✅ Automatic toString(), equals(), and hashCode().&lt;br&gt;
✅ Immutable by default.&lt;/p&gt;

&lt;p&gt;When to use records? Perfect for DTOs and API responses, but avoid them for JPA entities!&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
    </item>
  </channel>
</rss>
