<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Henry Pham</title>
    <description>The latest articles on Forem by Henry Pham (@hieuit96bk).</description>
    <link>https://forem.com/hieuit96bk</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%2F1232666%2F1598d51c-a07d-4cda-b2f3-e4c41da43d45.jpg</url>
      <title>Forem: Henry Pham</title>
      <link>https://forem.com/hieuit96bk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hieuit96bk"/>
    <language>en</language>
    <item>
      <title>Spring Boot 3 And Java 17 Migration Guide</title>
      <dc:creator>Henry Pham</dc:creator>
      <pubDate>Sat, 16 Dec 2023 14:20:09 +0000</pubDate>
      <link>https://forem.com/hieuit96bk/spring-boot-3-and-java-17-migration-guide-b8f</link>
      <guid>https://forem.com/hieuit96bk/spring-boot-3-and-java-17-migration-guide-b8f</guid>
      <description>&lt;p&gt;Spring Boot 3.0 is a new major release that offers new features and improvements. However, it requires Java 17 as a minimum version and comes with numerous compatibility issues if you intend to upgrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  I. Pros and Cons
&lt;/h2&gt;

&lt;p&gt;You need to analyze the pros and cons of our migration. In my experience, there are some points you should review:&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1. Pros
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Java 17 Baseline
&lt;/h4&gt;

&lt;p&gt;You’ll need to upgrade to JDK 17 before you can develop Spring Boot 3.0 applications. This means you can take advantage of the latest features and performance improvements that Java 17 offers.&lt;/p&gt;

&lt;h4&gt;
  
  
  GraalVM Native Image Support
&lt;/h4&gt;

&lt;p&gt;GraalVM Native Images provide a new way to deploy and run Java applications. It provides various advantages, like an instant startup and reduced memory consumption (pain points of Spring Boot apps).&lt;/p&gt;

&lt;h4&gt;
  
  
  Improved observability with Micrometer and Micrometer Tracing
&lt;/h4&gt;

&lt;p&gt;You can check more details &lt;a href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes#micrometer-updates" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.2. Cons
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Time/Resouces constraints
&lt;/h4&gt;

&lt;p&gt;Migrating to a new major release takes time and resources, especially for testing. This migration affects all your flows so needs to be tested carefully. While you can update your code within a few days, please plan for testing to span more than a week (the duration depends on the size of your project).&lt;/p&gt;

&lt;h4&gt;
  
  
  Risk of new bugs
&lt;/h4&gt;

&lt;p&gt;As mentioned earlier, the migration affects all your flows. Therefore, if your test coverage doesn't cover all your code, please be careful. Test your end-to-end flows and scrutinize the logs for any new exceptions or discrepancies compared to the previous state.&lt;/p&gt;

&lt;h2&gt;
  
  
  II. Before we start
&lt;/h2&gt;

&lt;p&gt;If you’re currently running with an earlier version of Spring Boot, I recommend that you &lt;a href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes" rel="noopener noreferrer"&gt;upgrade to Spring Boot 2.7&lt;/a&gt; before migrating to Spring Boot 3.0. It minimizes compatibility issues as much as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Review Dependencies
&lt;/h3&gt;

&lt;p&gt;You can review your dependencies and &lt;a href="https://docs.spring.io/spring-boot/docs/3.0.x/reference/html/dependency-versions.html#appendix.dependency-versions" rel="noopener noreferrer"&gt;dependency management for 3.x&lt;/a&gt; to assess how your project is affected.&lt;/p&gt;

&lt;p&gt;For dependencies that are not managed by Spring Boot, you can identify the compatible version before upgrading.&lt;/p&gt;

&lt;h3&gt;
  
  
  Review Deprecations
&lt;/h3&gt;

&lt;p&gt;Classes, methods and properties that were deprecated in Spring Boot 2.x have been removed in this release. Before upgrading, please ensure that you are not calling any deprecated methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  III. Migrate to Spring Boot 3 and Java 17
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1. Spring Boot Template Project
&lt;/h3&gt;

&lt;p&gt;I will use my project as an example for you guys to share how I migrated from Spring Boot 2.7 (Java 11) to Spring Boot 3 and Java 17.&lt;/p&gt;

&lt;p&gt;Github: &lt;a href="https://github.com/hieubz/spring-boot-template-project" rel="noopener noreferrer"&gt;https://github.com/hieubz/spring-boot-template-project&lt;/a&gt;&lt;br&gt;
Original post: &lt;a href="https://phamduyhieu.com/spring-boot-3-and-java-17-migration-guide" rel="noopener noreferrer"&gt;https://phamduyhieu.com/spring-boot-3-and-java-17-migration-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This project includes the implementation of common backend features, designed to assist both myself and other Spring Boot developers in coding more efficiently. For further details, you can read more &lt;a href="https://phamduyhieu.com/spring-boot-based-project-introduction" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you find &lt;a href="https://github.com/hieubz/spring-boot-template-project" rel="noopener noreferrer"&gt;my project&lt;/a&gt; useful, please give it a star ⭐️!&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3.2. Migration Steps
&lt;/h3&gt;
&lt;h4&gt;
  
  
  3.2.1. Configuration Properties Migration
&lt;/h4&gt;

&lt;p&gt;Let's add the migrator by adding the following to your Maven &lt;strong&gt;pom.xml&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;&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-properties-migrator&amp;lt;/artifactId&amp;gt;
    &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will analyze your application’s environment and print diagnostics at startup console logs. Then you can based on that update your properties accordingly.&lt;/p&gt;

&lt;h4&gt;
  
  
  3.2.2. Update Dependencies
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;We start with the parent pom &lt;strong&gt;spring-boot-starter-parent&lt;/strong&gt; and &lt;strong&gt;Java version&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;parent&amp;gt;
        &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;spring-boot-starter-parent&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;3.1.5&amp;lt;/version&amp;gt;
        &amp;lt;relativePath/&amp;gt; &amp;lt;!-- lookup parent from repository --&amp;gt;
    &amp;lt;/parent&amp;gt;

    &amp;lt;properties&amp;gt;
        &amp;lt;java.version&amp;gt;17&amp;lt;/java.version&amp;gt;
    &amp;lt;/properties&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tips&lt;/strong&gt;: We shouldn't specify the version of &lt;strong&gt;Spring Data JPA&lt;/strong&gt;, &lt;strong&gt;Spring Web&lt;/strong&gt;, &lt;strong&gt;Spring Data Redis&lt;/strong&gt;,... because their compatible versions are already declared in the parent POM.&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-jpa&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;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-web&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you are working with MySQL, let's replace your &lt;strong&gt;mysql-connector-java&lt;/strong&gt; by:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.mysql&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;mysql-connector-j&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;8.1.0&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you are using &lt;strong&gt;logback&lt;/strong&gt; for logging, let's update it to v1.4.11
&lt;/li&gt;
&lt;/ul&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;ch.qos.logback&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;logback-classic&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;1.4.11&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you are using &lt;strong&gt;Openfeign&lt;/strong&gt; for integrations, let's update it to v4.x
&lt;/li&gt;
&lt;/ul&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.cloud&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-cloud-starter-openfeign&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;4.0.4&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you are using &lt;strong&gt;Spring JDBC&lt;/strong&gt;, let's update it to v6.x
&lt;/li&gt;
&lt;/ul&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&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-jdbc&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;6.0.12&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you are using &lt;strong&gt;Jackson&lt;/strong&gt; for data binding, let's update it to v2.15.x
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.fasterxml.jackson.core&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;jackson-databind&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;2.15.3&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;!--  support Java 8 Date/time Serialize/Deserialize  --&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.fasterxml.jackson.datatype&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;jackson-datatype-jsr310&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;2.15.3&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you are using &lt;strong&gt;Redisson&lt;/strong&gt; as a Redis client, let's update it to v3.24.x
&lt;/li&gt;
&lt;/ul&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.redisson&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;redisson-spring-boot-starter&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;3.24.3&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.redisson&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;redisson-spring-data-31&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;3.24.3&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;You should use the default &lt;strong&gt;spring-boot-starter-test&lt;/strong&gt; for unit testing. However, If you are customizing &lt;strong&gt;mockito-core&lt;/strong&gt;, let's update it to v5.3.x
&lt;/li&gt;
&lt;/ul&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.mockito&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;mockito-core&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;5.3.1&amp;lt;/version&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;ul&gt;
&lt;li&gt;If you are using &lt;strong&gt;jjwt&lt;/strong&gt; for authentication, let's update it to 0.12.x
&lt;/li&gt;
&lt;/ul&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;io.jsonwebtoken&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;jjwt&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;0.12.3&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you are using &lt;strong&gt;Springdoc&lt;/strong&gt; for API documentation, let's replace your &lt;strong&gt;springdoc-openapi-ui&lt;/strong&gt; by:
&lt;/li&gt;
&lt;/ul&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.springdoc&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;springdoc-openapi-starter-webmvc-ui&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;2.2.0&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you are using &lt;strong&gt;spring-kafka&lt;/strong&gt; as your Kafka client, let's update it to v3.0.x
&lt;/li&gt;
&lt;/ul&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.kafka&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-kafka&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;3.0.10&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3.2.3. Rebuild and change the code
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;After updating your dependencies, let's rebuild your code first and check for any issues
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  mvn clean package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Spring Boot 3.0 has migrated from &lt;strong&gt;Java EE&lt;/strong&gt; to &lt;strong&gt;Jakarta EE APIs&lt;/strong&gt; for all dependencies. So you should face the &lt;strong&gt;javax&lt;/strong&gt; issue in your first build:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6b03iubg1pdvut827h2.jpg" 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%2Fk6b03iubg1pdvut827h2.jpg" alt="Javax_persistence_not_exist" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then you just need to replace all &lt;strong&gt;javax&lt;/strong&gt; in your imports by &lt;strong&gt;jakarta&lt;/strong&gt; (should use &lt;strong&gt;Ctrl+Shift+R&lt;/strong&gt; to replace on IntelliJ)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8sx0cno6oslpesk21xws.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%2F8sx0cno6oslpesk21xws.png" alt="replace_javax_by_jakarta" width="731" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the Spring migrator is working, you can see a &lt;strong&gt;WARNING&lt;/strong&gt; log in the startup console:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fperenn1q1rrovgsjmars.jpg" 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%2Fperenn1q1rrovgsjmars.jpg" alt="spring_migrator" width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simply update as suggested.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Hibernate 6, you can use &lt;strong&gt;MySQLDialect&lt;/strong&gt; for all MySQL versions (MySQL5Dialect, MySQL8Dialect have been deprecated)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;JPA &lt;strong&gt;SpringPhysicalNamingStrategy&lt;/strong&gt; is replaced by &lt;strong&gt;CamelCaseToUnderscoresNamingStrategy&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

==&amp;gt; org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spring Security&lt;/strong&gt; is not working if you are using &lt;strong&gt;WebSecurityConfigurerAdapter&lt;/strong&gt; (deprecated). Besides, in v3.x, you have to use &lt;strong&gt;lambda&lt;/strong&gt; to configure filterChain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So you have to remove the extension of &lt;strong&gt;WebSecurityConfigurerAdapter&lt;/strong&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Now
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {}

// Then without extension
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class WebSecurityConfig {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then do several updates for &lt;strong&gt;AuthenticationManager&lt;/strong&gt; bean creation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Now with the class extends WebSecurityConfigurerAdapter
  @Bean
  @Override
  public AuthenticationManager authenticationManagerBean() throws Exception {
    // Get AuthenticationManager bean
    return super.authenticationManagerBean();
  }

// Then without extension
  @Bean
  public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
    return authConfig.getAuthenticationManager();
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;strong&gt;SecurityFilterChain&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;/** We have to use Lambda for SecurityFilterChain configuration **/

// Now with the class extends WebSecurityConfigurerAdapter
  @Override
  protected void configure(HttpSecurity http) throws Exception {
      http.cors().and().csrf().disable();
      http.authorizeRequests().antMatchers(AUTH_WHITELIST).permitAll().anyRequest().authenticated();
      http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
      http.exceptionHandling().authenticationEntryPoint(authEntryPointJwt);
      http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
  }

// Then with lambda
  @Bean
  protected SecurityFilterChain configure(HttpSecurity http) throws Exception {
      http.cors(AbstractHttpConfigurer::disable).csrf(AbstractHttpConfigurer::disable);
      http.authorizeHttpRequests(auth -&amp;gt; auth.requestMatchers(AUTH_WHITELIST).permitAll().anyRequest().authenticated());
      http.sessionManagement(s -&amp;gt; s.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
      http.exceptionHandling(ex -&amp;gt; ex.authenticationEntryPoint(authEntryPointJwt));
      http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
      return http.build();
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Powermock&lt;/strong&gt; is not working with Spring Boot 3 and JDK 17. Its latest update is in Feb 2022. So you need to move to &lt;strong&gt;Mockito&lt;/strong&gt; if you are using &lt;strong&gt;Powermock&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;jjwt&lt;/strong&gt; library updates its API, so we update our code:&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;// Now
  public String generateJwtToken(Long userId) {
    return Jwts.builder()
        .setSubject(userId.toString())
        .setIssuedAt(new Date())
        .setExpiration(new Date(new Date().getTime() + jwtExpirationMs))
        .signWith(SignatureAlgorithm.HS256, jwtSecret.getBytes(StandardCharsets.UTF_8))
        .compact();
  }


// Then
  public String generateJwtToken(Long userId) {
    return Jwts.builder()
        .subject(userId.toString())
        .issuedAt(new Date())
        .expiration(new Date(new Date().getTime() + jwtExpirationMs))
        .signWith(Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8)), Jwts.SIG.HS256)
        .compact();
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the JWT parser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Now
public Claims getJwtTokenClaim(String jwt) {
   return Jwts.parser()
        .setSigningKey(jwtSecret.getBytes(StandardCharsets.UTF_8))
        .parseClaimsJws(jwt)
        .getBody();
}

// Then
public Claims getJwtTokenClaim(String jwt) {
    return Jwts.parser()
        .verifyWith(Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8)))
        .build()
        .parseSignedClaims(jwt)
        .getPayload();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Finally, rebuild and check for any issues. In my project, there are no issues left, so I stopped updating the code here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3.2.4. Testing
&lt;/h4&gt;

&lt;p&gt;Since this is a major upgrade, carefully test all APIs for discrepancies or exceptions. Review them one by one and monitor logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  IV. Conclusion
&lt;/h2&gt;

&lt;p&gt;We just completed the migration to Spring Boot 3 and JDK 17. There are many issues during this process, so stay calm and get things done :))). I hope this is helpful for anyone planning the migration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Anw, If you find &lt;a href="https://github.com/hieubz/spring-boot-template-project" rel="noopener noreferrer"&gt;this project&lt;/a&gt; useful, please give it a star ⭐️!&lt;/strong&gt;&lt;br&gt;
Henry Pham.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>java</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Spring Boot Template Project Introduction</title>
      <dc:creator>Henry Pham</dc:creator>
      <pubDate>Wed, 13 Dec 2023 16:04:09 +0000</pubDate>
      <link>https://forem.com/hieuit96bk/spring-boot-template-project-introduction-37l7</link>
      <guid>https://forem.com/hieuit96bk/spring-boot-template-project-introduction-37l7</guid>
      <description>&lt;p&gt;Whenever I need to implement a new feature, I typically start by researching available solutions on Google. Then I will experiment with one or more solutions to select the best one.&lt;/p&gt;

&lt;p&gt;However, after several months, I might forget how to implement that feature. Consequently, I end up having to revisit internet resources, conduct research once again, and reattempt the implementation.&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%2Ftgicn5mombxrtr32hu6w.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%2Ftgicn5mombxrtr32hu6w.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above situation is very common, not just for me but also among my friends and colleagues. We waste a lot of time recalling and researching solutions - things could be synthesized in a template project for the next implementation.&lt;/p&gt;

&lt;p&gt;So I have developed this project which includes implementations designed to assist both myself and other Spring Boot developers in seamlessly diving into coding. Each commit within the project represents the implementation of a specific technique.&lt;/p&gt;

&lt;p&gt;Github: &lt;a href="https://github.com/hieubz/spring-boot-template-project" rel="noopener noreferrer"&gt;Spring Boot Template Project&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tech stack: Java 17, Spring Boot 3.1.5&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%2Fjrss483e99jwac4o6su7.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%2Fjrss483e99jwac4o6su7.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whenever I need to implement a feature in my list, I simply search by relevant keywords associated with that feature (e.g., Redis, retry, email,...) to find the corresponding commit. By doing so, I can apply the code of that commit for my feature, with no need to Google or remember boilerplate code.&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%2Fj2ng4lfv9oiro90gjlyc.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%2Fj2ng4lfv9oiro90gjlyc.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;p&gt;We have basic features as below:&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%2Fe35wmknqza4rvdxfun3f.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%2Fe35wmknqza4rvdxfun3f.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;or advanced things:&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%2Fkwi4souh6r67otgmp1l9.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%2Fkwi4souh6r67otgmp1l9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are also modules related to Unit Tests and monitoring:&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%2Fdzfr6h897apd24iinizt.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%2Fdzfr6h897apd24iinizt.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;I hope this project helps Spring Boot developers increase their productivity, allowing them to allocate more time to other important activities.&lt;/p&gt;

&lt;p&gt;If you find &lt;a href="https://github.com/hieubz/spring-boot-template-project" rel="noopener noreferrer"&gt;this project&lt;/a&gt; useful, please give it a star ⭐️!&lt;/p&gt;

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