<?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: Tharindu Dulshan Fernando</title>
    <description>The latest articles on DEV Community by Tharindu Dulshan Fernando (@tharindufdo).</description>
    <link>https://dev.to/tharindufdo</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%2F656829%2Fac4341b4-1b2c-4cf1-b688-f064d728386a.png</url>
      <title>DEV Community: Tharindu Dulshan Fernando</title>
      <link>https://dev.to/tharindufdo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tharindufdo"/>
    <language>en</language>
    <item>
      <title>Resolving Deadlocks in Transactions in Spring Boot</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Mon, 05 May 2025 05:17:16 +0000</pubDate>
      <link>https://dev.to/tharindufdo/resolving-deadlocks-in-transactions-in-spring-boot-5a9j</link>
      <guid>https://dev.to/tharindufdo/resolving-deadlocks-in-transactions-in-spring-boot-5a9j</guid>
      <description>&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%2Fu8rpfdtz3yfxpncl1rvx.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%2Fu8rpfdtz3yfxpncl1rvx.png" alt="Image description" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In transactional systems, deadlocks are a common concurrency issue, particularly when several threads or processes seek for the same resources. Deadlocks can cause major problems with application speed and consistency in Spring Boot applications that use relational databases and @Transactional annotations.&lt;/p&gt;

&lt;p&gt;In this blog post, we will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What a deadlock is&lt;/li&gt;
&lt;li&gt;How it occurs in Spring Boot transactional systems&lt;/li&gt;
&lt;li&gt;Real code examples&lt;/li&gt;
&lt;li&gt;How to detect and handle deadlocks&lt;/li&gt;
&lt;li&gt;Best practices to prevent them&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is a Deadlock?
&lt;/h2&gt;

&lt;p&gt;A deadlock occurs when two or more transactions block each other by holding a lock and waiting for the other’s lock to be released.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transaction A locks Row 1 and needs Row 2&lt;/li&gt;
&lt;li&gt;Transaction B locks Row 2 and needs Row 1&lt;/li&gt;
&lt;li&gt;Neither can proceed, resulting in a deadlock&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Relational databases (like MySQL, PostgreSQL) will detect the deadlock and typically abort one of the transactions, throwing an exception.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deadlock in Spring Boot Example
&lt;/h2&gt;

&lt;p&gt;Let’s consider a simple scenario using Spring Data JPA and @Transactional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Model :&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Entity
public class Account {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String email;

    private BigDecimal balance;

    // getters and setters
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Repository :&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public interface AccountRepository extends JpaRepository&amp;lt;Account, Long&amp;gt; {}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Service with Transaction :&lt;/strong&gt;&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 AccountService {

    @Autowired
    private AccountRepository accountRepository;

    //this method will cause deadlocks if two threads access the transfer method at the same time.
    //If both threads fetch and lock their first account row and then,
    //attempt to access the other, a deadlock is likely.
    @Transactional
    public void transfer(Long fromId, Long toId, BigDecimal amount) {
        Account from = accountRepository.findById(fromId).orElseThrow();
        Account to = accountRepository.findById(toId).orElseThrow();

        from.setBalance(from.getBalance().subtract(amount));
        to.setBalance(to.getBalance().add(amount));

        accountRepository.save(from);
        accountRepository.save(to);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Thread A: transfers from Account 1 to 2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thread B: transfers from Account 2 to 1&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Detect Deadlocks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Database Logs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Databases like MySQL and PostgreSQL will log deadlocks. For example, in MySQL, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SHOW ENGINE INNODB STATUS;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Application Logs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spring will typically throw a DeadlockLoserDataAccessException or a database-specific exception. Make sure your logs include stack traces.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Handle and Prevent Deadlocks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Consistent Lock Ordering&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Always access resources in the same order. In the above example, always load accounts in order of ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Transactional
    public void transfer(Long fromId, Long toId, BigDecimal amount) {
        List&amp;lt;Account&amp;gt; accounts = accountRepository.findAllById(List.of(fromId, toId));
        Account from = fromId &amp;lt; toId ? accounts.get(0) : accounts.get(1);
        Account to = fromId &amp;lt; toId ? accounts.get(1) : accounts.get(0);

        accountRepository.save(from);
        accountRepository.save(to);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Retry Logic on Deadlocks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use Spring’s @Transactional with retry logic using @Retryable from Spring Retry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Retryable(
            value = {TransientDataAccessException.class},
            maxAttempts = 3,
            backoff = @Backoff(delay = 200))
    @Transactional
    public void transfer2(Long fromId, Long toId, BigDecimal amount) {
        Account from = accountRepository.findById(fromId).orElseThrow();
        Account to = accountRepository.findById(toId).orElseThrow();

        from.setBalance(from.getBalance().subtract(amount));
        to.setBalance(to.getBalance().add(amount));

        accountRepository.save(from);
        accountRepository.save(to);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t forget to enable Spring Retry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@EnableRetry
@SpringBootApplication
public class DeadlockexampleApplication {

 public static void main(String[] args) {
  SpringApplication.run(DeadlockexampleApplication.class, args);
 }

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;value and include are deprecated in latest versions so you can Define retry behavior via a RetryPolicy bean.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Configuration
@EnableRetry
public class RetryConfig {

    @Bean
    public RetryPolicy retryPolicy() {
        SimpleRetryPolicy policy = new SimpleRetryPolicy();
        policy.setMaxAttempts(3);
        policy.setRetryableExceptions(Map.of(
            TransientDataAccessException.class, true
        ));
        return policy;
    }

    @Bean
    public RetryTemplate retryTemplate(RetryPolicy retryPolicy) {
        RetryTemplate template = new RetryTemplate();
        template.setRetryPolicy(retryPolicy);
        return template;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Locking Strategies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Repository
public interface AccountRepository extends JpaRepository&amp;lt;Account, Long&amp;gt; {
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("SELECT a FROM Account a WHERE a.id = :id")
    Account findByIdForUpdate(@Param("id") Long id);

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

&lt;/div&gt;



&lt;p&gt;Service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @Transactional
    public void transfer(Long fromId, Long toId, BigDecimal amount) {
        Account from = accountRepository.findByIdForUpdate(fromId);
        Account to = accountRepository.findByIdForUpdate(toId);

        from.setBalance(from.getBalance().subtract(amount));
        to.setBalance(to.getBalance().add(amount));

        accountRepository.save(from);
        accountRepository.save(to);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important Notes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Pessimistic locking tells the database to acquire a row-level write lock as soon as the row is read — no other transaction can read/write it until the current one commits or rolls back.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This works well to prevent deadlocks, but can cause blocking and contention under high load. So use it carefully.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Always make sure you’re using it inside a @Transactional method — otherwise, the lock will be released immediately after the method exits.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Keep Transactions Short&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Avoid long-running transactions. Don’t perform unnecessary logic inside a transaction block.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Deadlocks are inevitable in highly concurrent systems, but with careful design, detection, and retries, you can manage them effectively in Spring Boot. Stick to consistent access patterns, use proper locking, and ensure your application is resilient to deadlocks through retries and monitoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/spring-retry" rel="noopener noreferrer"&gt;https://www.baeldung.com/spring-retry&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/java-deadlock-livelock" rel="noopener noreferrer"&gt;https://www.baeldung.com/java-deadlock-livelock&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/transaction-configuration-with-jpa-and-spring" rel="noopener noreferrer"&gt;https://www.baeldung.com/transaction-configuration-with-jpa-and-spring&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub :&lt;/strong&gt; &lt;a href="https://github.com/tharindu1998/resolve-deadlock-example" rel="noopener noreferrer"&gt;https://github.com/tharindu1998/resolve-deadlock-example&lt;/a&gt;&lt;/p&gt;

</description>
      <category>transactions</category>
      <category>springboot</category>
      <category>deadlocks</category>
      <category>deadlockprevention</category>
    </item>
    <item>
      <title>Boosting Performance: Essential Memory Optimization Techniques for Spring Boot Applications</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Wed, 30 Apr 2025 10:05:52 +0000</pubDate>
      <link>https://dev.to/tharindufdo/boosting-performance-essential-memory-optimization-techniques-for-spring-boot-applications-11ng</link>
      <guid>https://dev.to/tharindufdo/boosting-performance-essential-memory-optimization-techniques-for-spring-boot-applications-11ng</guid>
      <description>&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%2Fsyb8ag9809nmjzcw65eb.webp" 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%2Fsyb8ag9809nmjzcw65eb.webp" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Optimizing memory usage is critical for ensuring your Spring Boot applications perform efficiently, especially under heavy workloads. Proper Memory management will help to reduce latency, minimize crashes, and improve overall application scalability. In this article, we’ll explore five core techniques to optimize memory usage in Spring Boot applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Tune JVM Settings
&lt;/h2&gt;

&lt;p&gt;The Java Virtual Machine (JVM) plays a significant role in managing memory. Fine-tuning its configuration can yield considerable improvements in performance:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Heap Size Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configure the initial (-Xms) and maximum (-Xmx) heap sizes to match your application’s needs.&lt;/li&gt;
&lt;li&gt;Avoid leaving the heap size at its default value, as this can cause unexpected behavior under heavy load.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Garbage Collection (GC) Tuning&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use the G1 Garbage Collector (G1GC) for most Spring Boot applications, as it provides predictable pause times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adjust GC parameters, such as -XX:InitiatingHeapOccupancyPercent and -XX:MaxGCPauseMillis, for optimized performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Enable Class Data Sharing (CDS)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce memory consumption for frequently loaded classes by enabling Class Data Sharing with -Xshare:on.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2.Optimize Spring Boot Configurations
&lt;/h2&gt;

&lt;p&gt;Spring Boot provides various features that, if not optimized, can consume unnecessary memory. Here are some ways to streamline configurations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Profile-Specific Configurations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use application-{profile}.yml or application-{profile}.properties to load only environment-specific configurations.&lt;br&gt;
Ensure unused configurations are not included in the runtime environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disable Unused Auto-Configurations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the spring.autoconfigure.exclude property to prevent unnecessary auto-configurations from being loaded.&lt;br&gt;
For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring:
  autoconfigure:
    exclude:
-org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Manage Actuator Endpoints&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Actuator endpoints provide valuable insights but can consume resources if all are enabled.&lt;br&gt;
Only enable required endpoints using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;management:
  endpoints:
    enabled-by-default: false
  endpoint:
    health:
      enabled: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Streamline Dependencies
&lt;/h2&gt;

&lt;p&gt;Unused or excessive dependencies can unnecessarily bloat the memory footprint of your application. Follow these practices:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exclude Unnecessary Dependencies&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Review your pom.xml or build.gradle for unused dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove redundant libraries and ensure only essential dependencies are included.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Properly Scope Test Libraries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the test scope for test dependencies to ensure they are excluded from production builds:&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-test&amp;lt;/artifactId&amp;gt;
    &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Optimize Bean Initialization
&lt;/h2&gt;

&lt;p&gt;Spring Boot uses dependency injection to manage beans, which can sometimes lead to excessive memory consumption. Optimize this process as follows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enable Lazy Initialization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Load beans only when they are required by enabling lazy initialization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring:
  main:
    lazy-initialization: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Prototype Scope for Non-Singleton Beans&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For beans that are not frequently reused, use &lt;a class="mentioned-user" href="https://dev.to/scope"&gt;@scope&lt;/a&gt;("prototype") to avoid keeping them in memory unnecessarily:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Bean
@Scope("prototype")
public MyPrototypeBean myPrototypeBean() {
    return new MyPrototypeBean();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Monitor and Analyze Memory Usage
&lt;/h2&gt;

&lt;p&gt;Regular monitoring and analysis of your application’s memory usage can help identify and fix bottlenecks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leverage Spring Boot Actuator Metrics&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use Actuator’s metrics to monitor memory usage in real time.&lt;br&gt;
Integrate with monitoring tools like Prometheus and Grafana for visualization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Profile with Tools&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use tools like VisualVM, JProfiler, or YourKit to profile your application and identify memory leaks or inefficient memory usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By implementing these five core techniques, you can ensure your Spring Boot application is both efficient and scalable. Regularly profile your application and adapt these strategies as your application’s requirements evolve. DYOR for other stratergies and optimize your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/spring-boot-lazy-initialization" rel="noopener noreferrer"&gt;https://www.baeldung.com/spring-boot-lazy-initialization&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.spring.io/spring-boot/reference/actuator/metrics.html" rel="noopener noreferrer"&gt;https://docs.spring.io/spring-boot/reference/actuator/metrics.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.spring.io/spring-framework/reference/core/beans/factory-scopes.html" rel="noopener noreferrer"&gt;https://docs.spring.io/spring-framework/reference/core/beans/factory-scopes.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>memoryimprovement</category>
      <category>lazyinitialization</category>
      <category>springboot</category>
      <category>memoryoptimization</category>
    </item>
    <item>
      <title>Top five Common mistakes Developers make when using Java Streams and How to Avoid Them</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Sun, 24 Nov 2024 11:10:12 +0000</pubDate>
      <link>https://dev.to/tharindufdo/top-five-common-mistakes-developers-make-when-using-java-streams-and-how-to-avoid-them-59m</link>
      <guid>https://dev.to/tharindufdo/top-five-common-mistakes-developers-make-when-using-java-streams-and-how-to-avoid-them-59m</guid>
      <description>&lt;p&gt;Java Streams provide a powerful way to process data in a functional style, allowing developers to write concise and readable code. However, misusing Streams can lead to inefficient, buggy, or unmaintainable code. In this blog, we’ll explore developers' top five common mistakes when working with Java Streams and how to avoid them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Modifying the Source During Stream Processing
&lt;/h2&gt;

&lt;p&gt;One common mistake is changing a collection while using a stream to process it. Streams are meant to handle data without making changes to the original collection. If you modify the collection during processing, it can cause errors like a ConcurrentModificationException.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;Integer&amp;gt; list = new ArrayList&amp;lt;&amp;gt;(List.of(1, 2, 3));
list.stream().forEach(x -&amp;gt; list.add(x + 1)); // Runtime exception
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problem :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Streams are not thread-safe, and modifying the underlying collection during processing disrupts its consistency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to avoid and solve:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need to transform the data, collect the results into a new collection instead of modifying the original one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;Integer&amp;gt; transformedList = list.stream()
    .map(x -&amp;gt; x + 1)
    .collect(Collectors.toList());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Assuming Streams Can Be Reused
&lt;/h2&gt;

&lt;p&gt;Streams are single-use objects. Once consumed by a terminal operation (e.g., forEach(), collect()), they cannot be reused. Attempting to reuse a stream will throw an IllegalStateException.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Stream&amp;lt;String&amp;gt; stream = List.of("a", "b", "c").stream();
stream.forEach(System.out::println); // Works
stream.forEach(System.out::println); // Throws IllegalStateException

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This mistake often occurs when developers try to perform multiple operations on the same stream without realizing it has already been consumed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to avoid and solve:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need to process the data multiple times, create a new stream for each operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;String&amp;gt; list = List.of("a", "b", "c");
list.stream().forEach(System.out::println);
list.stream().forEach(System.out::println); // Create a new stream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Improper Handling of Parallel Streams
&lt;/h2&gt;

&lt;p&gt;Parallel streams can help speed up processing, but if not used carefully, they can cause problems. For example, using them on small datasets or shared resources can lead to errors or slow things down instead of improving performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;Integer&amp;gt; list = List.of(1, 2, 3);
list.parallelStream().forEach(System.out::println); // Non-deterministic output

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For small datasets, the overhead of parallelization often outweighs the performance gains.&lt;br&gt;
Accessing shared mutable resources in parallel streams can lead to race conditions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to avoid and solve:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use parallel streams only for large datasets where they provide a clear performance boost, and make sure to handle shared resources safely to avoid errors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;list.stream().forEach(System.out::println); // Sequential stream

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Avoid Side Effects in Stream Operations
&lt;/h2&gt;

&lt;p&gt;Streams are meant to follow a functional programming style. Adding side effects, like printing or changing external variables, in operations like map() or filter() goes against this approach and makes the code harder to maintain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;list.stream()
    .map(x -&amp;gt; {
        System.out.println(x); // Side effect
        return x * 2;
    })
    .collect(Collectors.toList());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Side effects can make the stream pipeline harder to understand and debug. They can also cause unexpected behaviour when using parallel streams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to avoid and solve:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need to debug or inspect values, use peek(). Avoid modifying external state in stream operations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;list.stream()
    .peek(System.out::println) // Use peek for debugging
    .map(x -&amp;gt; x * 2)
    .collect(Collectors.toList());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Improper Collecting with Collectors.toMap
&lt;/h2&gt;

&lt;p&gt;When using Collectors.toMap to collect data into a map, developers sometimes forget to handle key collisions. If two elements have the same key, the code will throw an IllegalStateException unless collisions are properly managed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Map&amp;lt;Integer, String&amp;gt; map = List.of("apple", "bat", "ant").stream()
    .collect(Collectors.toMap(String::length, Function.identity())); // Key collision issue

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If two elements produce the same key, the collector does not know how to merge them, leading to an exception.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to avoid and solve:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Provide a merge function to handle key collisions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Map&amp;lt;Integer, String&amp;gt; map = List.of("apple", "bat", "ant").stream()
    .collect(Collectors.toMap(
        String::length,
        Function.identity(),
        (existing, replacement) -&amp;gt; existing // Resolve collision
    ));

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Java Streams are a powerful tool for processing data, but using them incorrectly can cause inefficiency and errors. By being aware of these common mistakes and knowing how to avoid them, you can write clean, efficient, and maintainable code that makes the most of streams.&lt;/p&gt;

&lt;h2&gt;
  
  
  References :
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/java-8-streams" rel="noopener noreferrer"&gt;https://www.baeldung.com/java-8-streams&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/java-8-stream" rel="noopener noreferrer"&gt;https://www.digitalocean.com/community/tutorials/java-8-stream&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.oracle.com/javase/8/docs/api/?java/util/stream/Stream.html" rel="noopener noreferrer"&gt;https://docs.oracle.com/javase/8/docs/api/?java/util/stream/Stream.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>javastreams</category>
      <category>javacollections</category>
      <category>javaversion8</category>
    </item>
    <item>
      <title>Optimizing Spring Boot Applications with Redis Caching</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Tue, 24 Sep 2024 13:07:27 +0000</pubDate>
      <link>https://dev.to/tharindufdo/optimizing-spring-boot-applications-with-redis-caching-37i5</link>
      <guid>https://dev.to/tharindufdo/optimizing-spring-boot-applications-with-redis-caching-37i5</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/tharindufdo/spring-boot-caching-a-comprehensive-guide-to-improve-application-performance-2di8"&gt;previous blog&lt;/a&gt;, I explained what is Caching and different methods of caching used In Springboot Applications. So as promised here is an in-depth blog about Redis Caching.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Redis?
&lt;/h2&gt;

&lt;p&gt;Redis (Remote Dictionary Server) is an open-source, in-memory key-value data store that supports a variety of data structures like strings, lists, sets, hashes, and more. It’s highly performant due to its in-memory architecture, which makes it an excellent choice for caching and session management in modern applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros of Using Redis for Caching.
&lt;/h2&gt;

&lt;p&gt;Redis offers several benefits when used as a caching solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;In-memory storage&lt;/strong&gt;: It stores data in RAM, enabling lightning-fast read and write operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data persistence&lt;/strong&gt;: Redis allows data persistence through snapshots or appending to logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced data structures&lt;/strong&gt;: Beyond key-value pairs, Redis supports lists, sets, sorted sets, and more, making it a versatile tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High availability&lt;/strong&gt;: Redis can be configured in a distributed, highly available setup with clustering and replication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TTL support&lt;/strong&gt;: You can set Time-to-Live (TTL) on cached data, ensuring stale data is evicted automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let’s Set Up Redis in Spring Boot
&lt;/h2&gt;

&lt;p&gt;Let’s go step-by-step on how to set up and configure Redis caching in a Spring Boot application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Add Dependencies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To get started, add the following dependencies in your &lt;strong&gt;pom.xml&lt;/strong&gt; (for Maven) or &lt;strong&gt;build.gradle&lt;/strong&gt; (for Gradle) 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-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;&lt;strong&gt;2. Install Redis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can install Redis on your machine, or if you’re working in a cloud environment, you can use managed services like AWS ElastiCache or Redis Enterprise Cloud.&lt;/p&gt;

&lt;p&gt;For local development, you can install Redis using the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo apt-get install redis-server&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Start Redis using:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;redis-server&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can confirm that Redis is running by typing:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;redis-cli ping&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
It should return &lt;strong&gt;PONG&lt;/strong&gt; if Redis is running correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Configure Redis in Spring Boot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spring Boot makes it easy to configure Redis. All you need to do is provide Redis connection details in the application.properties or application.yml file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# application.properties
spring.redis.host=localhost
spring.redis.port=6379
spring.cache.type=redis
&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;spring:
  redis:
    host: localhost
    port: 6379
  cache:
    type: redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your Redis instance requires authentication, add the password field:&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.password=yourpassword

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Enable Caching in Spring Boot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, you need to enable caching in your Spring Boot application. This can be done by adding the @EnableCaching annotation in 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;@SpringBootApplication
@EnableCaching
public class RedisCacheApplication {
    public static void main(String[] args) {
        SpringApplication.run(RedisCacheApplication.class, args);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Implement Caching&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To apply caching to a method, simply use the @Cacheable annotation. Let’s say you have a service class that fetches user data:&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 {

    @Cacheable(value = "userCache", key = "#userId")
    public User getUserById(Long userId) {
        // Simulate a database call
        return userRepository.findById(userId).orElseThrow(() -&amp;gt; new UserNotFoundException());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@Cacheable:&lt;/strong&gt; Caches the method's return value using the given cache name (userCache in this case).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;key:&lt;/strong&gt; Specifies the key under which the value will be stored. By default, all method arguments are considered part of the key. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the getUserById method is called, it will first check the cache. The data is cached and returned if it is present; if not, it retrieves the data from the database and saves it in the cache.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Cache Eviction and Updating&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should update or invalidate the cache whenever the underlying data changes. Spring provides the @CachePut and @CacheEvict annotations for this purpose.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@CachePut:&lt;/strong&gt; Updates the values in the cache with a new value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@CacheEvict:&lt;/strong&gt; eliminates a record from the cache.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an example:&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 {

    @CacheEvict(value = "userCache", key = "#userId")
    public void deleteUserById(Long userId) {
        userRepository.deleteById(userId);
    }

    @CachePut(value = "userCache", key = "#user.id")
    public User updateUser(User user) {
        return userRepository.save(user);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In deleteUserById, the cache entry for the given userId is removed.&lt;/li&gt;
&lt;li&gt;In updateUser, the cache entry is updated with the new user data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. Customizing Cache Expiration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Redis lets you specify the time-to-live (TTL) for entries that are cached. You can set the TTL in your cache manager using Spring Boot.&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 RedisCacheConfig {

    @Bean
    public RedisCacheConfiguration cacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(10)) // Set TTL to 10 minutes
                .disableCachingNullValues();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cache values will be automatically deleted after ten minutes thanks to this configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Monitoring Redis&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In addition to integrating Redis with external tools like Redis-cli or Prometheus, Redis has its own suite of monitoring tools, such as redis-cli. Monitoring makes it easier to monitor response times, memory usage, and cache hit/miss ratios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The performance and scalability of your Spring Boot application can be greatly enhanced by integrating Redis caching. It gives end users faster response times and lessens the strain on your backend services.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://collaborationbetterstheworld.com/insights/redis-cache-in-spring-boot-applications/" rel="noopener noreferrer"&gt;https://collaborationbetterstheworld.com/insights/redis-cache-in-spring-boot-applications/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/spring-boot-redis-cache/" rel="noopener noreferrer"&gt;https://www.baeldung.com/spring-boot-redis-cache/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.spring.io/spring-data/redis/reference/redis/redis-cache.html" rel="noopener noreferrer"&gt;https://docs.spring.io/spring-data/redis/reference/redis/redis-cache.html&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Spring Boot Caching: A Comprehensive Guide to Improve Application Performance</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Tue, 17 Sep 2024 08:12:50 +0000</pubDate>
      <link>https://dev.to/tharindufdo/spring-boot-caching-a-comprehensive-guide-to-improve-application-performance-2di8</link>
      <guid>https://dev.to/tharindufdo/spring-boot-caching-a-comprehensive-guide-to-improve-application-performance-2di8</guid>
      <description>&lt;p&gt;Caching is a crucial method for increasing application performance since it stores frequently requested data in a temporary manner. Caching speeds up response times, lessens backend strain, and enhances user experience by cutting down on the number of costly activities like database searches and API requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Spring Boot Cache Annotations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spring Boot provides a set of annotations to simplify caching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;@Cacheable: Caches the result of a method based on its parameters.&lt;/li&gt;
&lt;li&gt;@CachePut: Updates the cache with the method’s result.&lt;/li&gt;
&lt;li&gt;@CacheEvict: Removes data from the cache.&lt;/li&gt;
&lt;li&gt;@Caching: Allows combining multiple caching annotations using a single method.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Enabling Caching in Spring Boot&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To enable caching in your Spring Boot application, add the @EnableCaching annotation to one of your configuration classes. This annotation triggers a post-processor that inspects each Spring bean for caching annotations.&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.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableCaching
public class CacheConfig {
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Using In-Memory Caching&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default, Spring Boot uses a simple in-memory cache with ConcurrentHashMap. Let's create a sample caching mechanism for a product service:&lt;/p&gt;

&lt;p&gt;Step 1: Create a Product Model&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 Product {
    private Long id;
    private String name;

    // Include getters , setters and the constructer here
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Implement a Service with Caching&lt;/p&gt;

&lt;p&gt;Here’s how to use @Cacheable to cache method results:&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.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class ProductService {

    @Cacheable(value = "products", key = "#id")
    public Product getProductById(Long id) {
        // Simulate a slow database query
        try {
            Thread.sleep(3000); // Simulates a delay
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new Product(id, "Sample Product");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the getProductById method is annotated with @Cacheable. The first time the method is called with a specific id, the result is stored in the cache. Subsequent calls with the same id retrieve the result from the cache instead of executing the method again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Using External Cache Providers (e.g., Redis, EhCache)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s often better to use external cache providers like Redis, EhCache, or Hazelcast for distributed caching for production applications. Let’s see how to use Redis as a cache provider.&lt;/p&gt;

&lt;p&gt;Step 1: Add Redis Dependencies&lt;/p&gt;

&lt;p&gt;Add the following dependency to your pom.xml 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-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;Step 2: Configure Redis&lt;/p&gt;

&lt;p&gt;Add Redis configuration to your application.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;spring.data.redis.host=localhost
spring.data.redis.port=6379
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: Create a Redis Cache Manager&lt;/p&gt;

&lt;p&gt;Configure the Redis cache manager in a configuration 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.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

@Configuration
@EnableCaching
public class RedisCacheConfig {

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        return RedisCacheManager.builder(redisConnectionFactory).build();
    }

    @Bean
    public RedisTemplate&amp;lt;String, Object&amp;gt; redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate&amp;lt;String, Object&amp;gt; template = new RedisTemplate&amp;lt;&amp;gt;();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration sets up Redis as the cache provider for your Spring Boot application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I will explain Redis caching in depth in a seperate blog”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;5. Conditional Caching with @Cacheable&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use the condition and unless attributes of @Cacheable to control caching behaviour conditionally.&lt;/p&gt;

&lt;p&gt;In the below example, caching occurs only if the id is greater than 10.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Cacheable(value = "products", key = "#id", condition = "#id &amp;gt; 10")
public Product getProductById(Long id) {
    // Method logic
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;6. Updating and Removing Caches with @CachePut and @CacheEvict&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updating the Cache with @CachePut&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;@CachePut allows you to update the cache when the method is called:&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 = "products", key = "#product.id")
public Product updateProduct(Product product) {
    // Update product logic
    return product;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Removing Cache Entries with @CacheEvict&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;@CacheEvict is used to remove entries from the cache. This is useful when you want to invalidate a cache after certain operations (e.g., deleting a product).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@CacheEvict(value = "products", key = "#id")
public void deleteProduct(Long id) {
    // Delete product logic
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also clear the entire cache using allEntries = true:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@CacheEvict(value = "products", allEntries = true)
public void clearCache() {
    // Logic to clear cache
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;7. Additional Configuration and Best Practices&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cache Expiration: If using an external cache provider, configure cache expiration to avoid stale data. For example, in Redis, you can set TTL (Time-To-Live) for cache entries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Logging: Enable cache logging for monitoring cache hits and misses.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid Over-Caching: Cache only data that is frequently accessed and expensive to retrieve.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Unique Cache Names: Use unique names for caches in multi-module projects to avoid cache collisions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;** Conclusion**&lt;/p&gt;

&lt;p&gt;You can significantly enhance the user experience while lowering backend load by following best practices and carefully planning your caching strategy. You can optimize application performance with a flexible toolkit thanks to Spring Boot’s caching capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Github:&lt;/strong&gt; &lt;a href="https://github.com/tharindu1998/spring-boot-caching-example" rel="noopener noreferrer"&gt;https://github.com/tharindu1998/spring-boot-caching-example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.spring.io/spring-boot/reference/io/caching.html" rel="noopener noreferrer"&gt;https://docs.spring.io/spring-boot/reference/io/caching.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/spring-cache-tutorial" rel="noopener noreferrer"&gt;https://www.baeldung.com/spring-cache-tutorial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.javatpoint.com/spring-boot-caching" rel="noopener noreferrer"&gt;https://www.javatpoint.com/spring-boot-caching&lt;/a&gt;&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>springcache</category>
      <category>redis</category>
      <category>rediscaching</category>
    </item>
    <item>
      <title>Creating the Perfect Code: Understanding Creational Patterns</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Tue, 06 Aug 2024 15:43:02 +0000</pubDate>
      <link>https://dev.to/tharindufdo/creating-the-perfect-code-understanding-creational-patterns-1ld6</link>
      <guid>https://dev.to/tharindufdo/creating-the-perfect-code-understanding-creational-patterns-1ld6</guid>
      <description>&lt;p&gt;This is a start for a series of blogs about Design Patterns. In this blog, we will discuss the first type of design pattern, Creational Patterns. Here the types which fall under creational patterns will be discussed with some real-world examples. I will be using Java as my language of selection.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Design Patterns?
&lt;/h2&gt;

&lt;p&gt;Design patterns play a crucial role in software development, providing proven solutions to common problems and promoting best practices. They are like pre-made blueprints that you can customize to solve a recurring design problem in your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring Creational Design Patterns in Java
&lt;/h2&gt;

&lt;p&gt;In object-oriented programming, creational design patterns play a significant role since they make it possible for object instantiation to be separated from their utilization thereby increasing the flexibility and scalability of object creation. This blog post will focus on five main types of creational design patterns: Factory Method, Abstract Factory, Builder, Prototype and Singleton. To show how each one works, we will use real-world examples in Java.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Factory Method&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Factory Method pattern defines an interface for creating an object but allows subclasses to alter the type of objects that will be created. This pattern supports loose coupling in Java to stop the need to bind application-specific classes into the code.&lt;/p&gt;

&lt;p&gt;Real-life Scenario: Consider a logistics company that transports goods using various vehicles such as trucks and ships. The type of vehicle depends on the transport mode required.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Product Interface
interface Transport {
    void deliver();
}

// Concrete Products
class Truck implements Transport {
    @Override
    public void deliver() {
        System.out.println("Deliver by land in a truck.");
    }
}

class Ship implements Transport {
    @Override
    public void deliver() {
        System.out.println("Deliver by sea in a ship.");
    }
}

// Creator
abstract class Logistics {
    public abstract Transport createTransport();

    public void planDelivery() {
        Transport transport = createTransport();
        transport.deliver();
    }
}

// Concrete Creators
class RoadLogistics extends Logistics {
    @Override
    public Transport createTransport() {
        return new Truck();
    }
}

class SeaLogistics extends Logistics {
    @Override
    public Transport createTransport() {
        return new Ship();
    }
}

// let's call the main class
public class Main {
    public static void main(String[] args) {
        Logistics logistics = new RoadLogistics();
        logistics.planDelivery();

        logistics = new SeaLogistics();
        logistics.planDelivery();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Abstract Factory&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. It is useful when the system needs to be independent of how its objects are created.&lt;/p&gt;

&lt;p&gt;Real-life Scenario: Imagine a furniture store that sells different types of furniture sets, such as Victorian and Modern. Each set includes products like chairs and sofas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Abstract Products
interface Chair {
    void sitOn();
}

interface Sofa {
    void lieOn();
}

// Concrete Products
class VictorianChair implements Chair {
    @Override
    public void sitOn() {
        System.out.println("Sitting on a Victorian chair.");
    }
}

class ModernChair implements Chair {
    @Override
    public void sitOn() {
        System.out.println("Sitting on a Modern chair.");
    }
}

class VictorianSofa implements Sofa {
    @Override
    public void lieOn() {
        System.out.println("Lying on a Victorian sofa.");
    }
}

class ModernSofa implements Sofa {
    @Override
    public void lieOn() {
        System.out.println("Lying on a Modern sofa.");
    }
}

// Abstract Factory
interface FurnitureFactory {
    Chair createChair();
    Sofa createSofa();
}

// Concrete Factories
class VictorianFurnitureFactory implements FurnitureFactory {
    @Override
    public Chair createChair() {
        return new VictorianChair();
    }

    @Override
    public Sofa createSofa() {
        return new VictorianSofa();
    }
}

class ModernFurnitureFactory implements FurnitureFactory {
    @Override
    public Chair createChair() {
        return new ModernChair();
    }

    @Override
    public Sofa createSofa() {
        return new ModernSofa();
    }
}

// Client code
public class Main {
    private static void createFurniture(FurnitureFactory factory) {
        Chair chair = factory.createChair();
        Sofa sofa = factory.createSofa();
        chair.sitOn();
        sofa.lieOn();
    }

    public static void main(String[] args) {
        FurnitureFactory victorianFactory = new VictorianFurnitureFactory();
        createFurniture(victorianFactory);

        FurnitureFactory modernFactory = new ModernFurnitureFactory();
        createFurniture(modernFactory);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Builder&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Builder pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations. It is particularly useful for creating objects with many optional attributes.&lt;/p&gt;

&lt;p&gt;Real-life Scenario: Consider an online pizza ordering system where customers can customize their pizzas with various toppings, sizes, and crust types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Product
class Pizza {
    private String dough = "";
    private String sauce = "";
    private String topping = "";

    public void setDough(String dough) { this.dough = dough; }
    public void setSauce(String sauce) { this.sauce = sauce; }
    public void setTopping(String topping) { this.topping = topping; }

    @Override
    public String toString() {
        return "Pizza [dough=" + dough + ", sauce=" + sauce + ", topping=" + topping + "]";
    }
}

// Builder Interface
interface PizzaBuilder {
    void buildDough();
    void buildSauce();
    void buildTopping();
    Pizza getPizza();
}

// Concrete Builders
class HawaiianPizzaBuilder implements PizzaBuilder {
    private Pizza pizza;

    public HawaiianPizzaBuilder() {
        this.pizza = new Pizza();
    }

    @Override
    public void buildDough() { pizza.setDough("cross"); }
    @Override
    public void buildSauce() { pizza.setSauce("mild"); }
    @Override
    public void buildTopping() { pizza.setTopping("ham+pineapple"); }
    @Override
    public Pizza getPizza() { return this.pizza; }
}

class SpicyPizzaBuilder implements PizzaBuilder {
    private Pizza pizza;

    public SpicyPizzaBuilder() {
        this.pizza = new Pizza();
    }

    @Override
    public void buildDough() { pizza.setDough("pan baked"); }
    @Override
    public void buildSauce() { pizza.setSauce("hot"); }
    @Override
    public void buildTopping() { pizza.setTopping("pepperoni+salami"); }
    @Override
    public Pizza getPizza() { return this.pizza; }
}

// Director
class Waiter {
    private PizzaBuilder pizzaBuilder;

    public void setPizzaBuilder(PizzaBuilder pb) { pizzaBuilder = pb; }
    public Pizza getPizza() { return pizzaBuilder.getPizza(); }

    public void constructPizza() {
        pizzaBuilder.buildDough();
        pizzaBuilder.buildSauce();
        pizzaBuilder.buildTopping();
    }
}

// Client code
public class Main {
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
        PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();

        waiter.setPizzaBuilder(hawaiianPizzaBuilder);
        waiter.constructPizza();
        Pizza pizza1 = waiter.getPizza();
        System.out.println("Pizza built: " + pizza1);

        waiter.setPizzaBuilder(spicyPizzaBuilder);
        waiter.constructPizza();
        Pizza pizza2 = waiter.getPizza();
        System.out.println("Pizza built: " + pizza2);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Prototype&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Prototype pattern is used to create a new object by copying an existing object, known as the prototype. This pattern is useful when the cost of creating a new object is expensive.&lt;/p&gt;

&lt;p&gt;Real-life Scenario: Think of a graphical editor where you can create, duplicate, and edit shapes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.HashMap;
import java.util.Map;

// Prototype
abstract class Shape implements Cloneable {
    private String id;
    protected String type;

    abstract void draw();

    public String getType() { return type; }
    public String getId() { return id; }
    public void setId(String id) { this.id = id; }

    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }
}

// Concrete Prototypes
class Rectangle extends Shape {
    public Rectangle() { type = "Rectangle"; }
    @Override
    public void draw() { System.out.println("Drawing a Rectangle."); }
}

class Circle extends Shape {
    public Circle() { type = "Circle"; }
    @Override
    public void draw() { System.out.println("Drawing a Circle."); }
}

// Prototype Registry
class ShapeCache {
    private static Map&amp;lt;String, Shape&amp;gt; shapeMap = new HashMap&amp;lt;&amp;gt;();

    public static Shape getShape(String shapeId) {
        Shape cachedShape = shapeMap.get(shapeId);
        return (Shape) cachedShape.clone();
    }

    public static void loadCache() {
        Rectangle rectangle = new Rectangle();
        rectangle.setId("1");
        shapeMap.put(rectangle.getId(), rectangle);

        Circle circle = new Circle();
        circle.setId("2");
        shapeMap.put(circle.getId(), circle);
    }
}

// Client code
public class Main {
    public static void main(String[] args) {
        ShapeCache.loadCache();

        Shape clonedShape1 = ShapeCache.getShape("1");
        System.out.println("Shape: " + clonedShape1.getType());

        Shape clonedShape2 = ShapeCache.getShape("2");
        System.out.println("Shape: " + clonedShape2.getType());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Singleton&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Singleton pattern ensures a class has only one instance and provides a global point of access to it. This pattern is commonly used for logging, caching, and thread pools.&lt;/p&gt;

&lt;p&gt;Real-life Scenario: Imagine a printer spooler where only one instance should manage all print jobs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class PrinterSpooler {
    private static PrinterSpooler instance;

    private PrinterSpooler() {
        // private constructor to prevent instantiation
    }

    public static PrinterSpooler getInstance() {
        if (instance == null) {
            instance = new PrinterSpooler();
        }
        return instance;
    }

    public void print(String document) {
        System.out.println("Printing document: " + document);
    }
}

// Client code
public class Main {
    public static void main(String[] args) {
        PrinterSpooler spooler1 = PrinterSpooler.getInstance();
        PrinterSpooler spooler2 = PrinterSpooler.getInstance();

        spooler1.print("Document 1");
        spooler2.print("Document 2");

        System.out.println("Are both spoolers the same instance? " + (spooler1 == spooler2));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://refactoring.guru/" rel="noopener noreferrer"&gt;https://refactoring.guru/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.javatpoint.com/design-patterns-in-java" rel="noopener noreferrer"&gt;https://www.javatpoint.com/design-patterns-in-java&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/java-design-patterns-example-tutorial" rel="noopener noreferrer"&gt;https://www.digitalocean.com/community/tutorials/java-design-patterns-example-tutorial&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>designpatterns</category>
      <category>creationaldesignpatterns</category>
      <category>javadesignpatterns</category>
    </item>
    <item>
      <title>5 helpful plugins for IntelliJ IDEA: Enhance your Spring Boot and Java development experience</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Thu, 11 Jul 2024 20:05:18 +0000</pubDate>
      <link>https://dev.to/tharindufdo/5-helpful-plugins-for-intellij-idea-enhance-your-spring-boot-and-java-development-experience-5gj2</link>
      <guid>https://dev.to/tharindufdo/5-helpful-plugins-for-intellij-idea-enhance-your-spring-boot-and-java-development-experience-5gj2</guid>
      <description>&lt;p&gt;For any Spring Boot developer, two primary goals are maximum productivity and high-quality code. One of the most widely applied Integrated Development Environments today is IntelliJ IDEA. More than that, it provides a huge set of plugins that facilitate development processes. In this article, we shall discover 5 IntelliJ plugins every Spring Boot developer should consider in his toolbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. SonarLint
&lt;/h2&gt;

&lt;p&gt;SonarLint is a static code analysis tool for real-time feedback within the IDE on the quality of the code. This ensures high quality and best practices of code.&lt;/p&gt;

&lt;p&gt;Key Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Instant Feedback:&lt;/strong&gt; Highlights code issues as you type, providing instant feedback on potential bugs, vulnerabilities, and code smells.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rule Customization:&lt;/strong&gt; Allows customization of rules to fit your project's coding standards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration with SonarQube:&lt;/strong&gt; Offers seamless integration with SonarQube for comprehensive code analysis.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&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%2F6wce2q4hc8n6lff0ohez.png" 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%2F6wce2q4hc8n6lff0ohez.png" alt="SonarQube"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link - &lt;a href="https://plugins.jetbrains.com/plugin/7973-sonarlint" rel="noopener noreferrer"&gt;https://plugins.jetbrains.com/plugin/7973-sonarlint&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. JRebel for IntelliJ
&lt;/h2&gt;

&lt;p&gt;JRebel is a productivity tool that enables developers to instantly see the impact of code changes without restarting the application. The JRebel plugin for IntelliJ integrates this powerful feature into the IDE.&lt;/p&gt;

&lt;p&gt;Key Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hot Reloading:&lt;/strong&gt; Reloads code changes on-the-fly, eliminating the need for application restarts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Time-Saving:&lt;/strong&gt; Significantly reduces development time by speeding up the feedback loop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Support for Various Frameworks:&lt;/strong&gt; Works seamlessly with Spring Boot and other Java frameworks.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&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%2Fhyxwle7t6ae1za8fnzz7.png" 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%2Fhyxwle7t6ae1za8fnzz7.png" alt="JRebel for IntelliJ"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link - &lt;a href="https://plugins.jetbrains.com/plugin/4441-jrebel-and-xrebel" rel="noopener noreferrer"&gt;https://plugins.jetbrains.com/plugin/4441-jrebel-and-xrebel&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. SwaggerHub Plugin
&lt;/h2&gt;

&lt;p&gt;The SwaggerHub plugin allows you to view and edit your OpenAPI definitions stored in SwaggerHub directly from within IntelliJ. You will be able to access the APIs and domains of your organization and sync the changes back into SwaggerHub.&lt;/p&gt;

&lt;p&gt;Both SwaggerHub SaaS and On-Premise are supported.&lt;/p&gt;

&lt;p&gt;Key Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API Documentation:&lt;/strong&gt; Provides tools for generating and editing Swagger/OpenAPI documentation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Generation:&lt;/strong&gt; Generates client code for various programming languages from API definitions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Visualization:&lt;/strong&gt; Allows for the visualization of API endpoints and their details within the IDE.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&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%2Fwkoafshjvox6imuzug81.png" 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%2Fwkoafshjvox6imuzug81.png" alt="SwaggerHub"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link - &lt;a href="https://support.smartbear.com/swaggerhub/docs/en/integrations/swaggerhub-plugin-for-intellij-idea.html" rel="noopener noreferrer"&gt;https://support.smartbear.com/swaggerhub/docs/en/integrations/swaggerhub-plugin-for-intellij-idea.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Lombok Plugin
&lt;/h2&gt;

&lt;p&gt;Lombok is a Java library that reduces boilerplate code. The plugin to IntelliJ IDEA, Lombok Plugin, integrates perfectly, and all the features of Lombok are at your disposal.&lt;/p&gt;

&lt;p&gt;Key Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Annotations Support:&lt;/strong&gt; Enables the use of Lombok annotations like @Getter, &lt;a class="mentioned-user" href="https://dev.to/setter"&gt;@setter&lt;/a&gt;, &lt;a class="mentioned-user" href="https://dev.to/builder"&gt;@builder&lt;/a&gt;, and more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Generation:&lt;/strong&gt; Automatically generates boilerplate code, such as getters, setters, constructors, and builders.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&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%2F1j9dnbjmxfbpbzok8r5s.png" 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%2F1j9dnbjmxfbpbzok8r5s.png" alt="Lombok Plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link - &lt;a href="https://plugins.jetbrains.com/plugin/6317-lombok" rel="noopener noreferrer"&gt;https://plugins.jetbrains.com/plugin/6317-lombok&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. RestfulTool plugin
&lt;/h2&gt;

&lt;p&gt;The RestfulTool plugin provides tools for developing and testing RESTful services, making it easier to work with APIs within IntelliJ IDEA.&lt;/p&gt;

&lt;p&gt;Key Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Request Generation:&lt;/strong&gt; Allows you to generate and test HTTP requests directly from the IDE.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;cURL Command Generation:&lt;/strong&gt; Generates cURL commands from HTTP requests, simplifying API testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Endpoint Management:&lt;/strong&gt; Helps manage and organize RESTful endpoints.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&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%2F31zlxmj49j3kypnoh278.png" 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%2F31zlxmj49j3kypnoh278.png" alt="RestfulTool"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link - &lt;a href="https://plugins.jetbrains.com/plugin/14280-restful-tool" rel="noopener noreferrer"&gt;https://plugins.jetbrains.com/plugin/14280-restful-tool&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Bonus Plugin&lt;/strong&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  6. Json2Pojo Plugin
&lt;/h2&gt;

&lt;p&gt;Allows the creation of easily Java POJOs from JSON with GSON annotations and accessors. Once installed, right-click the destination package and choose "New -&amp;gt; Generate POJOs from JSON", then fill in your root class name and source JSON text as appropriate.&lt;/p&gt;

&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%2F3bwpswx6veii8jb9t1v5.png" 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%2F3bwpswx6veii8jb9t1v5.png" alt="Json2Pojo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The JSON to POJO plugin is one very useful tool in the estimation of JSON data to Java POJO classes.&lt;/p&gt;

&lt;p&gt;Key Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Generation:&lt;/strong&gt; Automatically generates Java classes from JSON, saving time and effort.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customizable Output:&lt;/strong&gt; Allows customization of the generated code to match your coding standards.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;These plugins will smooth and increase the workflow, thus enabling the delivery of quality applications within a quicker time frame. Besides helping one save time, such tools are important in the maintenance of best practices and coding standards, thus making the overall development experience more pleasurable and productive.&lt;/p&gt;

</description>
      <category>java</category>
      <category>intellij</category>
      <category>plugins</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Understanding @Transactional in Spring Boot</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Fri, 05 Jul 2024 08:04:26 +0000</pubDate>
      <link>https://dev.to/tharindufdo/understanding-transactional-in-spring-boot-8ce</link>
      <guid>https://dev.to/tharindufdo/understanding-transactional-in-spring-boot-8ce</guid>
      <description>&lt;p&gt;Managing transactions in Spring Boot can be done using @Transactional annotation. In this blog post, we'll explore how to use @Transactional to ensure data consistency and simplify error handling in your spring boot applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Basic Usage
&lt;/h2&gt;

&lt;p&gt;To use @Transactional, you typically place it on methods of a service class where you want the transactional behaviour.&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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService{

    @Transactional
    public void createUser() {
        // enter your transactional code here
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Propagation and Isolation Levels
&lt;/h2&gt;

&lt;p&gt;You can specify the propagation and isolation levels of a transaction to control how the transaction behaves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Propagation: Defines how the transaction behaves when an existing transaction is already running.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Isolation: Defines the data visibility level of the transaction.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Transactional(propagation = Propagation.REQUIRED, 
              isolation = Isolation.READ_COMMITTED)
public void createUser() {
    // enter your transactional code here
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Rollback Rules
&lt;/h2&gt;

&lt;p&gt;You can specify which exceptions should trigger a rollback:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Transactional(rollbackFor = Exception.class)
public void createUser() {
    // your transactional code here
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Read-Only Transactions
&lt;/h2&gt;

&lt;p&gt;If your method only reads data and does not perform any write operations, you can mark it as read-only for performance optimizations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Transactional(readOnly = true)
public void getUser() {
    // your read-only code here
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Transactional on Classes
&lt;/h2&gt;

&lt;p&gt;You can also place @Transactional at the class level to apply it to all methods in the class:&lt;br&gt;
&lt;/p&gt;

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

    public void getUser() {
        // transactional code
    }

    public void createUser() {
        // transactional code
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example Service with Transactional Methods
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    @Transactional
    public void saveUser() {
        // code to save data
    }

    @Transactional(readOnly = true)
    public void fetchUser() {
        // code to fetch data
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void newTransaction() {
        // code to execute in a new transaction
    }

    @Transactional(rollbackFor = {CustomException.class})
    public void performWithRollback() {
        // risky code that may throw CustomException
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Using @Transactional Spring Boot allows you to manage transactions declaratively, specifying exactly how you want transactions to behave in various scenarios. This helps ensure data consistency and simplifies error handling in your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/spring-transactions-read-only"&gt;https://www.baeldung.com/spring-transactions-read-only&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.spring.io/spring-framework/reference/data-access/transaction/declarative/annotations.html"&gt;https://docs.spring.io/spring-framework/reference/data-access/transaction/declarative/annotations.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html"&gt;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Github:&lt;/strong&gt; &lt;a href="https://github.com/tharindu1998/transactional-blog"&gt;https://github.com/tharindu1998/transactional-blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>transactional</category>
      <category>annotations</category>
    </item>
    <item>
      <title>Understanding Lazy Initialization in Spring Boot</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Wed, 26 Jun 2024 09:38:11 +0000</pubDate>
      <link>https://dev.to/tharindufdo/understanding-lazy-initialization-in-spring-boot-2fbd</link>
      <guid>https://dev.to/tharindufdo/understanding-lazy-initialization-in-spring-boot-2fbd</guid>
      <description>&lt;p&gt;In this blog, we'll explore the concept of lazy initialization in Spring Boot, how to use the "@ Lazy" annotation, and the benefits it can bring to your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Lazy Initialization?
&lt;/h2&gt;

&lt;p&gt;Lazy initialization is a design pattern which delays the creation of an object until it is really needed. In the context of Spring, it means that a bean is not instantiated and initialized until it is first requested. This can be particularly useful for improving the startup time of an application, especially if there are many beans or if some beans are resource-intensive to create.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "@ Lazy" Annotation
&lt;/h2&gt;

&lt;p&gt;Spring provides the "@ Lazy" annotation to enable lazy initialization. This annotation can be used in several ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Using @ Lazy on Bean Definitions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To use "@ Lazy" on a bean definition, simply annotate the bean method with "@ Lazy".&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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

@Configuration
public class AppConfig {

    @Bean
    @Lazy
    public TestBean testBean() {
        return new testBean();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, "testBean" will not be created until it is first requested.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Using @ Lazy on Configuration Classes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can also apply "@ Lazy" at the class level to indicate that all beans within the configuration should be lazily initialized.&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.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Bean;

@Configuration
@Lazy
public class LazyConfig {

    @Bean
    public TestBean testBean() {
        return new TestBean();
    }

    @Bean
    public AnotherTestBean anotherTestBean() {
        return new AnotherTestBean();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, both "testBean" and "anotherTestBean" will be lazily initialized.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Using &lt;a class="mentioned-user" href="https://dev.to/lazy"&gt;@lazy&lt;/a&gt; on Dependencies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use "@ Lazy" on a field or method parameter to lazily resolve 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;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Component
public class TestComponent {

    private final TestBean testBean;

    @Autowired
    public TestComponent(@Lazy TestBean testBean) {
        this.testBean = testBean;
    }

    // you can include other methods here
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, "testBean" will only be created when it is first accessed in "TestComponent".&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Lazy Initialization
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Startup Time&lt;/strong&gt;: By deferring the creation of beans until they are needed, the initial startup time of the application can be reduced.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Management&lt;/strong&gt;: Lazy initialization can help manage resources more efficiently by only instantiating beans that are actually used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoiding Circular Dependencies&lt;/strong&gt;: Lazy initialization can help break circular dependencies by delaying the creation of beans.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By using the "@ Lazy" annotation, you can control when beans are instantiated and initialized. However, it's important to use this feature carefully and be aware of its potential impact on application performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/spring-lazy-annotation"&gt;https://www.baeldung.com/spring-lazy-annotation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Lazy.html"&gt;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Lazy.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Github&lt;/strong&gt; : &lt;a href="https://github.com/tharindu1998/lazy-annotation"&gt;https://github.com/tharindu1998/lazy-annotation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>java</category>
      <category>lazyloading</category>
      <category>lazyannotation</category>
    </item>
    <item>
      <title>Creating a Secure NestJS Backend with JWT Authentication and Prisma</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Thu, 13 Jun 2024 15:09:51 +0000</pubDate>
      <link>https://dev.to/tharindufdo/creating-a-secure-nestjs-backend-with-jwt-authentication-and-prisma-2of9</link>
      <guid>https://dev.to/tharindufdo/creating-a-secure-nestjs-backend-with-jwt-authentication-and-prisma-2of9</guid>
      <description>&lt;p&gt;In this tutorial, we will create a secure backend application using NestJS, Prisma, and JWT-based authentication. Our application will include CRUD operations for managing books, with endpoints protected by JWT authentication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we start, ensure you have the following installed on your machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js and npm(Better to have a Lts version Installed)&lt;/li&gt;
&lt;li&gt;Nest CLI: Install globally using npm install -g @nestjs/cli&lt;/li&gt;
&lt;li&gt;PostgreSQL (or any other Prisma-supported database) running and accessible&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Create a New NestJS Project
&lt;/h2&gt;

&lt;p&gt;First, create a new NestJS project using the Nest CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest new book-store
cd book-store
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Install Dependencies
&lt;/h2&gt;

&lt;p&gt;Next, install the necessary dependencies for JWT authentication and Prisma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @nestjs/jwt @nestjs/passport passport passport-jwt @prisma/client prisma

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Initialize Prisma
&lt;/h2&gt;

&lt;p&gt;If you are using the docker image of Postgresql add the below lines in the docker-compose.yml.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3.8'
services:
  postgres:
    container_name: postgres_container
    image: postgres:13
    ports:
      - 5434:5432
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: 123
      POSTGRES_DB: book-store
    volumes:
      - postgres_data:/var/lib/postgresql/data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update your .env file with your database connection string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL="postgresql://postgres:123@localhost:5434/book-store?schema=public"

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

&lt;/div&gt;



&lt;p&gt;Initialize Prisma in your project and configure the database connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx prisma init

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Configure Prisma Schema
&lt;/h2&gt;

&lt;p&gt;Edit prisma/schema.prisma to include the User and Book models:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id       Int     @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  email    String  @unique

  firstName String?
  lastName  String?

  password String
}

model Book {
  id       Int    @id @default(autoincrement())
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  title       String
  description String?
  link        String
  userId   Int
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the Prisma migration to apply the schema to 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;npx prisma migrate dev --name init

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

&lt;/div&gt;



&lt;p&gt;Generate the Prisma client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx prisma generate

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Set Up Authentication
&lt;/h2&gt;

&lt;p&gt;Generate the Auth module, controller, and service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest generate module auth
nest generate controller auth
nest generate service auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure the Auth module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { JwtStrategy } from './jwt.strategy';
import { PrismaService } from '../prisma.service';

@Module({
  imports: [
    PassportModule,
    JwtModule.register({
      secret: process.env.JWT_SECRET || 'secretKey',
      signOptions: { expiresIn: '60m' },
    }),
  ],
  providers: [AuthService, JwtStrategy, PrismaService],
  controllers: [AuthController],
})
export class AuthModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configure the auth.service.ts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implement the AuthService with registration and login functionality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { PrismaService } from '../prisma.service';
import * as bcrypt from 'bcrypt';

@Injectable()
export class AuthService {
  constructor(
    private jwtService: JwtService,
    private prisma: PrismaService
  ) {}

  async validateUser(email: string, pass: string): Promise&amp;lt;any&amp;gt; {
    const user = await this.prisma.user.findUnique({ where: { email } });
    if (user &amp;amp;&amp;amp; await bcrypt.compare(pass, user.password)) {
      const { password, ...result } = user;
      return result;
    }
    return null;
  }

  async login(user: any) {
    const payload = { email: user.email, sub: user.id };
    return {
      access_token: this.jwtService.sign(payload),
    };
  }

  async register(email: string, pass: string) {
    const salt = await bcrypt.genSalt();
    const hashedPassword = await bcrypt.hash(pass, salt);

    const user = await this.prisma.user.create({
      data: {
        email,
        password: hashedPassword,
      },
    });

    const { password, ...result } = user;
    return result;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configure the auth.controller.ts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create endpoints for login and registration in AuthController:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';

@Controller('auth')
export class AuthController {
  constructor(private authService: AuthService) {}

  @Post('login')
  async login(@Body() req) {
    return this.authService.login(req);
  }

  @Post('register')
  async register(@Body() req) {
    return this.authService.register(req.email, req.password);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configure the jwt.strategy.ts&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: false,
      secretOrKey: process.env.JWT_SECRET || 'secretKey',
    });
  }

  async validate(payload: any) {
    return { userId: payload.sub, email: payload.email };
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create the JWT authentication guard(jwt-auth.guard.ts):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Set Up Prisma Service
&lt;/h2&gt;

&lt;p&gt;Create a Prisma service(prisma.service.ts) to handle database interactions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
  async onModuleInit() {
    await this.$connect();
  }

  async onModuleDestroy() {
    await this.$disconnect();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7: Create Books Module
&lt;/h2&gt;

&lt;p&gt;Generate the Books module, controller, and service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nest generate module books
nest generate controller books
nest generate service books
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configure the Books module(books.module.ts):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Module } from '@nestjs/common';
import { BooksService } from './books.service';
import { BooksController } from './books.controller';
import { PrismaService } from '../prisma.service';

@Module({
  providers: [BooksService, PrismaService],
  controllers: [BooksController]
})
export class BooksModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Implement the BooksService(books.service.ts):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma.service';
import { Book } from '@prisma/client';

@Injectable()
export class BooksService {
  constructor(private prisma: PrismaService) {}

  async create(data: Omit&amp;lt;Book, 'id'&amp;gt;): Promise&amp;lt;Book&amp;gt; {
    return this.prisma.book.create({ data });
  }

  async findAll(userId: number): Promise&amp;lt;Book[]&amp;gt; {
    return this.prisma.book.findMany({ where: { userId } });
  }

  async findOne(id: number, userId: number): Promise&amp;lt;Book&amp;gt; {
    return this.prisma.book.findFirst({ where: { id, userId } });
  }

  async update(id: number, data: Partial&amp;lt;Book&amp;gt;, userId: number): Promise&amp;lt;Book&amp;gt; {
    return this.prisma.book.updateMany({
      where: { id, userId },
      data,
    }).then((result) =&amp;gt; result.count ? this.prisma.book.findUnique({ where: { id } }) : null);
  }

  async remove(id: number, userId: number): Promise&amp;lt;Book&amp;gt; {
    return this.prisma.book.deleteMany({
      where: { id, userId },
    }).then((result) =&amp;gt; result.count ? this.prisma.book.findUnique({ where: { id } }) : null);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Secure the BooksController with JWT authentication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards, Request } from '@nestjs/common';
import { BooksService } from './books.service';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';

@Controller('books')
@UseGuards(JwtAuthGuard)
export class BooksController {
  constructor(private readonly booksService: BooksService) {}

  @Post()
  create(@Body() createBookDto, @Request() req) {
    return this.booksService.create({ ...createBookDto, userId: req.user.userId });
  }

  @Get()
  findAll(@Request() req) {
    return this.booksService.findAll(req.user.userId);
  }

  @Get(':id')
  findOne(@Param('id') id: string, @Request() req) {
    return this.booksService.findOne(+id, req.user.userId);
  }

  @Patch(':id')
  update(@Param('id') id: string, @Body() updateBookDto, @Request() req) {
    return this.booksService.update(+id, updateBookDto, req.user.userId);
  }

  @Delete(':id')
  remove(@Param('id') id: string, @Request() req) {
    return this.booksService.remove(+id, req.user.userId);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 8: Integrate Everything
&lt;/h2&gt;

&lt;p&gt;Ensure all modules are correctly imported in the main app module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { Module } from '@nestjs/common';
import { AuthModule } from './auth/auth.module';
import { BooksModule } from './books/books.module';

@Module({
  imports: [AuthModule, BooksModule],
})
export class AppModule {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running the Application
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run start:dev

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we created a NestJS application with Prisma for database interaction and JWT for securing the API endpoints. We covered setting up the Prisma schema, creating modules for authentication and books, and securing the endpoints using JWT guards. You now have a secure NestJS backend with JWT-based authentication and CRUD operations for books.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.nestjs.com/v5/"&gt;https://docs.nestjs.com/v5/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.prisma.io/docs"&gt;https://www.prisma.io/docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jwt.io/introduction"&gt;https://jwt.io/introduction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Github : &lt;a href="https://github.com/tharindu1998/book-store"&gt;https://github.com/tharindu1998/book-store&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>prisma</category>
      <category>jwt</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Understanding Dependency Injection in Spring Boot</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Wed, 05 Jun 2024 11:35:31 +0000</pubDate>
      <link>https://dev.to/tharindufdo/understanding-dependency-injection-in-spring-boot-2ll0</link>
      <guid>https://dev.to/tharindufdo/understanding-dependency-injection-in-spring-boot-2ll0</guid>
      <description>&lt;p&gt;In simple terms DI means that objects do not initiate their dependencies directly. Instead they recive them from an external source.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When class A uses some functionality of class B, then its said that class A has a dependency of class B.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What is DI in Spring Framework?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dependency Injection (DI) is a fundamental concept in Spring Framework that makes it possible to develop loosely coupled and easily testable code. In this blog, we'll explore what dependency injection is, how it works in Spring Boot, and provide examples to illustrate its usage.&lt;/p&gt;

&lt;p&gt;There are three main types of dependency injection:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Constructor Injection&lt;/li&gt;
&lt;li&gt;Setter Injection&lt;/li&gt;
&lt;li&gt;Field Injection&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Constructor Injection
&lt;/h2&gt;

&lt;p&gt;This is the most recommended way to acheive DI in Spring.It ensures that the dependency is not null and makes the class immutable.&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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TestService {

    private final TestRepository repository;

    @Autowired
    public TestService(TestRepository  repository) {
        this.repository = repository;
    }

    public void performService() {
        repository.doSomething();
    }
}

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

&lt;/div&gt;



&lt;p&gt;In the example above, &lt;strong&gt;TestService&lt;/strong&gt; class declares a dependency on &lt;strong&gt;TestRepository&lt;/strong&gt;. The dependency is injected via the constructor, which is annotated with @Autowired.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setter Injection
&lt;/h2&gt;

&lt;p&gt;Setter injection allows the dependency to be injected through a setter method. This method is less preferred than constructor injection because it allows the object to be in an incomplete state.&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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TestService {

    private TestRepository repository;

    @Autowired
    public void setTestRepository(TestRepository repository) {
        this.repository = repository;
    }

    public void performService() {
        repository.doSomething();
    }
}

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

&lt;/div&gt;



&lt;p&gt;In this example, TestService class has a setter method setTestRepository, which is used to inject the TestRepository dependency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Field Injection
&lt;/h2&gt;

&lt;p&gt;Field injection is the least preferred method because it makes the class less testable and harder to maintain. It involves annotating the dependency field directly with @Autowired.&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.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TestService {

    @Autowired
    private TestRepository repository;

    public void performService() {
        repository.doSomething();
    }
}

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

&lt;/div&gt;



&lt;p&gt;Here, TestRepository is injected directly into the field of TestService using @Autowired.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qualifiers
&lt;/h2&gt;

&lt;p&gt;When there are multiple beans of the same type, you can use @Qualifier to specify which bean should be injected.&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.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class TestService {

    private final TestRepository myRepository;

    @Autowired
    public TestService(@Qualifier("specificRepository")TestRepository repository) {
        this.repository = repository;
    }

    public void performService() {
        repository.doSomething();
    }
}

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

&lt;/div&gt;



&lt;p&gt;In this example, @Qualifier("specificRepository") specifies that a particular implementation of TestRepository should be injected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Dependency Injection is a powerful pattern that helps to create loosely coupled, maintainable, and testable applications. Spring Boot leverages dependency injection to manage the lifecycle and configuration of application components, making development more straightforward and efficient. By understanding and applying constructor, setter, and field injection, as well as using qualifiers when necessary, you can create robust Spring Boot applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/spring-dependency-injection"&gt;https://www.baeldung.com/spring-dependency-injection&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.baeldung.com/inversion-control-and-dependency-injection-in-spring"&gt;https://www.baeldung.com/inversion-control-and-dependency-injection-in-spring&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html"&gt;https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Github : &lt;a href="https://github.com/tharindu1998/SpringDependencyInjection"&gt;https://github.com/tharindu1998/SpringDependencyInjection&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dependencyinjection</category>
      <category>java</category>
      <category>springboot</category>
      <category>programming</category>
    </item>
    <item>
      <title>Step-by-Step Guide: Setting Up Elasticsearch and Kibana with Docker</title>
      <dc:creator>Tharindu Dulshan Fernando</dc:creator>
      <pubDate>Fri, 31 May 2024 11:01:54 +0000</pubDate>
      <link>https://dev.to/tharindufdo/step-by-step-guide-setting-up-elasticsearch-and-kibana-with-docker-on-mac-4p94</link>
      <guid>https://dev.to/tharindufdo/step-by-step-guide-setting-up-elasticsearch-and-kibana-with-docker-on-mac-4p94</guid>
      <description>&lt;p&gt;Setting up Elasticsearch and Kibana using Docker on a Mac is a straightforward process. Follow this step-by-step guide to integrate and visualize your developer metrics data.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Prerequisites: Ensure you have Docker installed on your Mac. You can download it from the &lt;a href="https://docs.docker.com/get-docker/"&gt;Docker website&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create a docker-compose.yml File
&lt;/h2&gt;

&lt;p&gt;Create a directory for your project and within that directory, create a docker-compose.yml file with the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '7.16.3'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3
    container_name: elasticsearch
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
    ports:
      - "9200:9200"
    volumes:
      - esdata:/usr/share/elasticsearch/data

  kibana:
    image: docker.elastic.co/kibana/kibana:7.16.3
    container_name: kibana
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch

volumes:
  esdata:
    driver: local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration sets up both Elasticsearch and Kibana, with Elasticsearch running on port 9200 and Kibana on port 5601.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Start the Docker Containers
&lt;/h2&gt;

&lt;p&gt;Open your terminal, navigate to the directory containing your docker-compose.yml file, and run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker-compose up -d&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command will start both Elasticsearch and Kibana in the background.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Index the JSON Data into Elasticsearch
&lt;/h2&gt;

&lt;p&gt;Consider this is only an example JSON just to explain the integration.&lt;/p&gt;

&lt;p&gt;Save the following JSON data into a file named developer_metrics.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "developer": "John Doe",
  "metrics": {
    "time_spent_coding": 120,
    "review_time": 35,
    "planned_overhead_time": 20,
    "untracked_time": 25,
    "effective_work": 15,
    "other_metrics": {
      "opened_pull_requests": 18,
      "merged_pull_requests": 15,
      "closed_pull_requests": 3,
      "created_feature_branches": 10,
      "lines_of_code": 2000,
      "inactive_days": 2
    }
  },
  "dates": {
    "start_date": "2024-05-01",
    "end_date": "2024-05-28"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use curl to index this data into Elasticsearch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST "localhost:9200/developer_metrics/_doc/1?pretty" -H 'Content-Type: application/json' -d @developer_metrics.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Create a Mapping for the Index
&lt;/h2&gt;

&lt;p&gt;To ensure Elasticsearch correctly interprets our data fields, we need to define a mapping for our index.&lt;/p&gt;

&lt;p&gt;Run the following curl command to create the mapping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X PUT "localhost:9200/developer_metrics?pretty" -H 'Content-Type: application/json' -d'
{
  "mappings": {
    "properties": {
      "developer": { "type": "keyword" },
      "metrics": {
        "properties": {
          "time_spent_coding": { "type": "integer" },
          "review_time": { "type": "integer" },
          "planned_overhead_time": { "type": "integer" },
          "untracked_time": { "type": "integer" },
          "effective_work": { "type": "integer" },
          "other_metrics": {
            "properties": {
              "opened_pull_requests": { "type": "integer" },
              "merged_pull_requests": { "type": "integer" },
              "closed_pull_requests": { "type": "integer" },
              "created_feature_branches": { "type": "integer" },
              "lines_of_code": { "type": "integer" },
              "inactive_days": { "type": "integer" }
            }
          }
        }
      },
      "dates": {
        "properties": {
          "start_date": { "type": "date" },
          "end_date": { "type": "date" }
        }
      }
    }
  }
}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Visualize the Data in Kibana
&lt;/h2&gt;

&lt;p&gt;With our data indexed, it’s time to create visualizations in Kibana.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating an Index Pattern&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Kibana in your browser by navigating to &lt;a href="http://localhost:5601"&gt;http://localhost:5601&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to Stack Management -&amp;gt; Index Patterns.&lt;/li&gt;
&lt;li&gt;Click Create index pattern and specify developer_metrics as the index pattern.&lt;/li&gt;
&lt;li&gt;Follow the prompts to complete the setup.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Creating Visualizations&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the Visualize Library.&lt;/li&gt;
&lt;li&gt;Click Create visualization and choose a visualization type (e.g., bar chart, line chart).&lt;/li&gt;
&lt;li&gt;Select the developer_metrics index pattern.&lt;/li&gt;
&lt;li&gt;Configure your visualization by selecting fields like time_spent_coding, opened_pull_requests, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Building a Dashboard&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to Dashboard.&lt;/li&gt;
&lt;li&gt;Click Create new dashboard.&lt;/li&gt;
&lt;li&gt;Add your visualizations to the dashboard.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Using Docker to set up Elasticsearch and Kibana on a Mac simplifies the process and ensures a consistent environment. By following these steps, you can easily visualize and analyze developer metrics data, helping you make informed decisions and track performance effectively.&lt;/p&gt;

&lt;p&gt;This setup can be customized and expanded to suit your specific needs. Start leveraging these powerful tools today to enhance your project’s efficiency and transparency.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html"&gt;https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.elastic.co/guide/en/kibana/current/introduction.html"&gt;https://www.elastic.co/guide/en/kibana/current/introduction.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>kibana</category>
      <category>elasticsearch</category>
      <category>json</category>
    </item>
  </channel>
</rss>
