<?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: Abhishek Singh</title>
    <description>The latest articles on DEV Community by Abhishek Singh (@abhishek999).</description>
    <link>https://dev.to/abhishek999</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%2F1462593%2Fac801f8b-336b-4d47-b503-e455ab087101.jpg</url>
      <title>DEV Community: Abhishek Singh</title>
      <link>https://dev.to/abhishek999</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abhishek999"/>
    <language>en</language>
    <item>
      <title>Database Integration with Spring Boot : Best Practices and Tools</title>
      <dc:creator>Abhishek Singh</dc:creator>
      <pubDate>Sun, 23 Jun 2024 14:19:24 +0000</pubDate>
      <link>https://dev.to/abhishek999/database-integration-with-spring-boot-best-practices-and-tools-5doh</link>
      <guid>https://dev.to/abhishek999/database-integration-with-spring-boot-best-practices-and-tools-5doh</guid>
      <description>&lt;p&gt;Integrating a database with a Spring Boot application is a common task that many developers do. Spring Boot, combined with Spring Data JPA, provides a robust framework for working with relational databases like MySQL. Additionally, tools like Flyway and Liquibase help manage database migrations efficiently. This blog will cover best practices for using Spring Data JPA with relational databases, integrating with MySQL, and managing database migrations with Flyway or Liquibase&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using Spring Data JPA with Relational Databases&lt;/strong&gt;&lt;br&gt;
Spring Data JPA simplifies the implementation of data access layers by reducing the amount of boilerplate code. It provides a powerful repository abstraction for various data stores, making database interactions more straightforward&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices for Using Spring Data JPA :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integrating with SQL Databases like MySQL :&lt;/strong&gt; &lt;br&gt;
MySQL is one of the most popular relational databases, and integrating it with Spring Boot is straightforward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps to Integrate MySQL with Spring Boot :&lt;/strong&gt; &lt;br&gt;
&lt;strong&gt;Add Dependencies:&lt;/strong&gt; Add the necessary dependencies for Spring Data JPA and MySQL connector in your pom.xml&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;mysql&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;mysql-connector-java&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;Database Configuration :&lt;/strong&gt; Configure the database connection details in application.properties or application.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydatabase
    username: root
    password: rootpassword
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Define Your Entities :&lt;/strong&gt; Start by defining your JPA entities Each entity represents a table in 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;@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(unique = true, nullable = false)
    private String email;

    // Getters and Setters
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create Repositories :&lt;/strong&gt; Create repository interfaces to perform CRUD operations. Extend JpaRepository to leverage built-in methods and custom query methods&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 UserRepository extends JpaRepository&amp;lt;User, Long&amp;gt; {
    Optional&amp;lt;User&amp;gt; findByEmail(String email);
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create Service Layer:&lt;/strong&gt; Use a service layer to encapsulate business logic and interact with the repository&lt;br&gt;
&lt;/p&gt;

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

    @Autowired
    private UserRepository userRepository;

    // Create operation
    public User createUser(User user) {
        // Perform validation or business logic if needed
        return userRepository.save(user);
    }

    // Read operations

    public Optional&amp;lt;User&amp;gt; findUserById(Long id) {
        return userRepository.findById(id);
    }

    public Optional&amp;lt;User&amp;gt; findUserByEmail(String email) {
        return userRepository.findByEmail(email);
    }

    public List&amp;lt;User&amp;gt; getAllUsers() {
        return userRepository.findAll();
    }

    // Update operation
    public User updateUser(Long id, User userDetails) {
        // Ensure the user exists
        User existingUser = userRepository.findById(id)
                .orElseThrow(() -&amp;gt; new ResourceNotFoundException("User not found with id: " + id));

        // Update user details
        existingUser.setName(userDetails.getName());
        existingUser.setEmail(userDetails.getEmail());

        // Save updated user
        return userRepository.save(existingUser);
    }

    // Delete operation
    public void deleteUser(Long id) {
        // Ensure the user exists
        User existingUser = userRepository.findById(id)
                .orElseThrow(() -&amp;gt; new ResourceNotFoundException("User not found with id: " + id));

        // Delete user
        userRepository.delete(existingUser);
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Exception Handling :&lt;/strong&gt; &lt;br&gt;
In the updateUser and deleteUser methods, you may want to handle cases where the user with the specified ID doesn't exist. You can create a custom exception (e.g., ResourceNotFoundException) and throw it if necessary&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run MySQL Server :&lt;/strong&gt; Ensure that the MySQL server is running, and the specified database (mydatabase) exists. You can create the database using MySQL CLI or a GUI tool like MySQL Workbench&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test the Connection :&lt;/strong&gt; Run your Spring Boot application to verify the connection to the MySQL database. If configured correctly, Spring Boot will automatically create the necessary tables based on your entities&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database Migration with Flyway or Liquibase :&lt;/strong&gt;&lt;br&gt;
Managing database schema changes is essential for maintaining the integrity and consistency of your application. Flyway and Liquibase are two popular tools for handling database migrations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using Flyway for Database Migrations&lt;/strong&gt;&lt;br&gt;
Flyway is a migration tool that uses SQL scripts to manage database versioning&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add Dependencies :&lt;/strong&gt; Add Flyway dependencies to your pom.xml&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.flywaydb&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;flyway-core&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;Configure Flyway :&lt;/strong&gt; Configure Flyway in application.properties or application.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring:
  flyway:
    enabled: true
    locations: classpath:db/migration

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create Migration Scripts :&lt;/strong&gt; Place your SQL migration scripts in the src/main/resources/db/migration directory. Name the scripts following Flyway's naming convention (V1_&lt;em&gt;Initial_Setup.sql, V2&lt;/em&gt;_Add_User_Table.sql, etc.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-- V1__Initial_Setup.sql
CREATE TABLE user (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE
);

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run Migrations :&lt;/strong&gt; Flyway will automatically run the migrations on application startup&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using Liquibase for Database Migrations :&lt;/strong&gt;&lt;br&gt;
Liquibase is another powerful tool for managing database migrations, supporting XML, YAML, JSON, and SQL formats.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add Dependencies :&lt;/strong&gt; Add Liquibase dependencies to your pom.xml&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.liquibase&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;liquibase-core&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;Configure Liquibase :&lt;/strong&gt; Configure Liquibase in application.properties or application.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring:
  liquibase:
    enabled: true
    change-log: classpath:db/changelog/db.changelog-master.yaml

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create ChangeLog Files :&lt;/strong&gt; Define your database changes in src/main/resources/db/changelog. Create a master changelog file (db.changelog-master.yaml) that includes other changelog files&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;databaseChangeLog:
  - changeSet:
      id: 1
      author: yourname
      changes:
        - createTable:
            tableName: user
            columns:
              - column:
                  name: id
                  type: BIGINT
                  autoIncrement: true
                  constraints:
                    primaryKey: true
              - column:
                  name: name
                  type: VARCHAR(100)
                  constraints:
                    nullable: false
              - column:
                  name: email
                  type: VARCHAR(100)
                  constraints:
                    nullable: false
                    unique: true

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run Migrations :&lt;/strong&gt; Liquibase will automatically run the migrations on application startup&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
Integrating databases with Spring Boot is seamless, thanks to Spring Data JPA, and tools like Flyway and Liquibase make managing database migrations straightforward. By following the best practices outlined in this blog, you can ensure your Spring Boot application interacts efficiently with relational databases like MySQL, and your database schema evolves smoothly as your application grows&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>jpa</category>
      <category>mysql</category>
    </item>
    <item>
      <title>Spring Boot Testing Best Practices</title>
      <dc:creator>Abhishek Singh</dc:creator>
      <pubDate>Sun, 23 Jun 2024 13:48:21 +0000</pubDate>
      <link>https://dev.to/abhishek999/spring-boot-testing-best-practices-1h0b</link>
      <guid>https://dev.to/abhishek999/spring-boot-testing-best-practices-1h0b</guid>
      <description>&lt;p&gt;Testing is a crucial aspect of software development, ensuring that your application behaves as expected and is free from bugs. Spring Boot provides excellent support for testing, making it easier to write unit tests, integration tests, and test RESTful services. In this blog, we will explore best practices for testing Spring Boot applications, covering unit testing, integration testing, and using MockMvc for testing RESTful services&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Writing Unit Tests for Spring Boot Applications&lt;/strong&gt;&lt;br&gt;
Unit tests are the foundation of a solid test suite. They focus on testing individual components in isolation, such as methods or classes, without depending on external systems like databases or web servers&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices for Unit Testing:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use JUnit 5:&lt;/strong&gt; JUnit 5 is the latest version of the popular testing framework and provides powerful features for writing tests. Ensure you include the necessary dependencies in your pom.xml or build.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.junit.jupiter&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;junit-jupiter&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;5.8.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;p&gt;&lt;strong&gt;Mock Dependencies:&lt;/strong&gt; Use mocking frameworks like Mockito to mock dependencies and focus on testing the logic of the class under test&lt;br&gt;
&lt;/p&gt;

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

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @Test
    void testFindUserById() {
        User user = new User(1L, "John");    

when(userRepository.findById(1L)).thenReturn(Optional.of(user));

        User result = userService.findUserById(1L);

        assertEquals("John", result.getName());
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test Boundary Conditions:&lt;/strong&gt; Ensure you test edge cases, null values, and invalid inputs to make your tests comprehensive&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write Fast and Isolated Tests:&lt;/strong&gt; Unit tests should run quickly and independently. Avoid using external resources like databases or file systems&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Test Doubles for Dependencies:&lt;/strong&gt; When necessary, create stub or mock implementations for dependencies that your class under test interacts with. This helps isolate the component being tested&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
void testUserCreation() {
    User user = new User(null, "Jane");
    when(userRepository.save(any(User.class))).thenReturn(new User(1L, "Jane"));

    User createdUser = userService.createUser(user);

    assertNotNull(createdUser.getId());
    assertEquals("Jane", createdUser.getName());
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Integration Testing with Spring Boot :&lt;/strong&gt; &lt;br&gt;
Integration tests verify that different parts of the application work together as expected. They test the application’s behavior in a realistic environment, including interactions with databases, web servers, and other systems&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices for Integration Testing :&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use @SpringBootTest:&lt;/strong&gt; The @SpringBootTest annotation loads the full application context and is useful for writing integration tests&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@SpringBootTest
@ExtendWith(SpringExtension.class)
public class UserServiceIntegrationTest {

    @Autowired
    private UserService userService;

    @Autowired
    private UserRepository userRepository;

    @Test
    void testFindUserById() {
        User user = new User(1L, "John");
        userRepository.save(user);
        User result = userService.findUserById(1L);
        assertEquals("John", result.getName());
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use @Transactional for Database Tests:&lt;/strong&gt; Use the @Transactional annotation to ensure that database changes are rolled back after each test, maintaining a clean state&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@SpringBootTest
@Transactional
public class UserServiceIntegrationTest {
    // Integration tests
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Profile-Specific Configuration:&lt;/strong&gt; Use different application properties for testing to avoid conflicts with development or production environments&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# src/test/resources/application-test.yml
spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password: password

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test Slices:&lt;/strong&gt; Use test slices like @WebMvcTest, @DataJpaTest, @RestClientTest to load only the necessary parts of the application context, making tests faster and more focused&lt;br&gt;
&lt;/p&gt;

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

    @Autowired
    private UserRepository userRepository;

    @Test
    void testSaveUser() {
        User user = new User(null, "Alice");
        User savedUser = userRepository.save(user);
        assertNotNull(savedUser.getId());
        assertEquals("Alice", savedUser.getName());
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Using MockMvc for Testing RESTful Services&lt;/strong&gt;&lt;br&gt;
MockMvc is a powerful tool for testing Spring MVC controllers. It allows you to perform HTTP requests and assert responses without starting the entire web server&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Practices for Using MockMvc&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup MockMvc with @WebMvcTest:&lt;/strong&gt; Use the @WebMvcTest annotation to test only the web layer and configure MockMvc&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@WebMvcTest(UserController.class)
public class UserControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    void testGetUserById() throws Exception {
        User user = new User(1L, "John");
        when(userService.findUserById(1L)).thenReturn(user);

        mockMvc.perform(get("/users/1"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$.name").value("John"));
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test Different Scenarios:&lt;/strong&gt; Ensure you test various scenarios, including success, failure, and edge cases&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
void testGetUserById_NotFound() throws Exception {
    when(userService.findUserById(1L)).thenThrow(new UserNotFoundException());

    mockMvc.perform(get("/users/1"))
           .andExpect(status().isNotFound());
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use JSONPath for Response Assertions:&lt;/strong&gt; Use JSONPath expressions to assert specific parts of the JSON response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mockMvc.perform(get("/users/1"))
       .andExpect(status().isOk())
       .andExpect(jsonPath("$.id").value(1))
       .andExpect(jsonPath("$.name").value("John"));

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Verify Interactions:&lt;/strong&gt; Use Mockito to verify that service methods are called as expected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;verify(userService).findUserById(1L);

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test with Different HTTP Methods:&lt;/strong&gt; Test various HTTP methods (GET, POST, PUT, DELETE) to ensure your RESTful services handle them correctly&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
void testCreateUser() throws Exception {
    User user = new User(null, "Jane");
    when(userService.createUser(any(User.class))).thenReturn(new User(1L, "Jane"));

    mockMvc.perform(post("/users")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"name\": \"Jane\"}"))
            .andExpect(status().isCreated())
            .andExpect(jsonPath("$.id").value(1))
            .andExpect(jsonPath("$.name").value("Jane"));
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test Error Handling:&lt;/strong&gt; Ensure your tests cover error scenarios and that your application returns appropriate error responses&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Test
void testCreateUser_InvalidInput() throws Exception {
    mockMvc.perform(post("/users")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"name\": \"\"}"))
            .andExpect(status().isBadRequest())
            .andExpect(jsonPath("$.errors").isNotEmpty());
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
Testing is a vital part of developing reliable and maintainable Spring Boot applications. By following these best practices for unit testing, integration testing, and using MockMvc, you can ensure that your application is robust and behaves as expected. Remember to write tests that are fast, isolated, and comprehensive to cover various scenarios and edge cases &lt;/p&gt;

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

</description>
      <category>spring</category>
      <category>springboot</category>
      <category>junit</category>
      <category>mockito</category>
    </item>
    <item>
      <title>SQL VS NoSQL</title>
      <dc:creator>Abhishek Singh</dc:creator>
      <pubDate>Mon, 10 Jun 2024 14:49:01 +0000</pubDate>
      <link>https://dev.to/abhishek999/sql-vs-nosql-21id</link>
      <guid>https://dev.to/abhishek999/sql-vs-nosql-21id</guid>
      <description>&lt;p&gt;&lt;strong&gt;Choosing Between SQL and NoSQL Databases: A Comprehensive Guide&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The decision to use SQL (Structured Query Language) or NoSQL (Not Only SQL) databases depends on various factors such as the nature of the data, scalability requirements, and the specific needs of your application. Here are some guidelines to consider&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Structure and Schema Flexibility:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use SQL databases when you have a structured data model with a fixed schema. SQL databases enforce a schema, which ensures data consistency and integrity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use NoSQL databases when you have unstructured or semi-structured data, or when your data model is expected to evolve frequently. NoSQL databases offer schema flexibility, allowing you to store and retrieve data without a predefined schema.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use NoSQL databases for horizontal scalability. They are designed to scale out across multiple servers or clusters, making them suitable for handling large volumes of data and high write loads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SQL databases can also scale vertically (by increasing server capacity) but may face limitations in horizontal scaling due to the rigid structure enforced by the relational model. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Complex Queries and Transactions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use SQL databases when your application requires complex queries involving multiple tables, joins, and aggregations. SQL databases excel at handling complex relational queries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NoSQL databases may not be as suitable for complex queries involving multiple entities or relationships. They typically prioritize fast data retrieval and simple queries over complex relational operations. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ACID Compliance:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use SQL databases when your application requires ACID (Atomicity, Consistency, Isolation, Durability) compliance for transactions. SQL databases provide strong consistency guarantees and ensure data integrity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NoSQL databases often sacrifice strong consistency for performance and scalability. They may offer eventual consistency or relaxed transaction guarantees, which might be acceptable depending on your application's requirements. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Volume and Speed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use NoSQL databases when dealing with large volumes of rapidly changing data, such as in real-time analytics, IoT (Internet of Things) applications, or social media platforms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SQL databases are suitable for applications with structured data and moderate to high transactional requirements, such as e-commerce platforms, financial systems, and enterprise applications. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Development and Deployment Flexibility:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;NoSQL databases are often favored for agile development and rapid iteration, as they offer more flexibility in data modeling and schema evolution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SQL databases may require more upfront planning and schema design but can offer better tooling, mature ecosystems, and robust transactional support for enterprise applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ultimately, the choice between SQL and NoSQL databases depends on your specific use case, performance requirements, scalability needs, and development preferences. In some cases, a combination of both types of databases (polyglot persistence) might be appropriate, leveraging the strengths of each for different parts of your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep Reading...&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>nosql</category>
    </item>
    <item>
      <title>Java 8 Lambda Expressions and Functional Interfaces</title>
      <dc:creator>Abhishek Singh</dc:creator>
      <pubDate>Sun, 09 Jun 2024 14:01:39 +0000</pubDate>
      <link>https://dev.to/abhishek999/java-8-lambda-expressions-and-functional-interfaces-3403</link>
      <guid>https://dev.to/abhishek999/java-8-lambda-expressions-and-functional-interfaces-3403</guid>
      <description>&lt;p&gt;&lt;strong&gt;Overview :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Java 8 introduced Lambda Expressions and Functional Interfaces, which bring functional programming capabilities to Java. These features allow for more concise and readable code, especially when working with collections and performing common tasks like filtering, mapping, and reducing&lt;/p&gt;

&lt;p&gt;By the end of this blog, we will understand:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Lambda Expressions are?&lt;br&gt;
What Functional Interfaces are?&lt;br&gt;
How to create and use Lambda Expressions?&lt;br&gt;
Common use cases for Lambda Expressions and Functional Interfaces&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are Lambda Expressions?&lt;/strong&gt;&lt;br&gt;
Lambda Expressions are a way to provide clear and concise syntax for writing anonymous methods (functions). They enable you to treat functionality as a method argument, or pass a block of code around as data&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax of Lambda Expressions :&lt;/strong&gt;&lt;br&gt;
The basic syntax of a lambda expression is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(parameters) -&amp;gt; expression
or
(parameters) -&amp;gt; { statements; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example: Simple Lambda Expression&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;// Traditional way using an anonymous class
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello, world!");
    }
};

// Using a lambda expression
Runnable lambdaRunnable = () -&amp;gt; System.out.println("Hello, world!");

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What are Functional Interfaces?&lt;/strong&gt;&lt;br&gt;
A Functional Interface is an interface with a single abstract method. They can have multiple default or static methods but only one abstract method. Lambda expressions can be used to instantiate functional interfaces.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Defining a Functional Interface&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;@FunctionalInterface
public interface MyFunctionalInterface {
    void myMethod();
}

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

&lt;/div&gt;



&lt;p&gt;Java 8 includes several built-in functional interfaces in the java.util.function package, such as Predicate, Function, Consumer, and Supplier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating and Using Lambda Expressions :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Using Predicate Interface&lt;/strong&gt;&lt;br&gt;
The Predicate interface represents a boolean-valued function of one argument.&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.function.Predicate;

public class Main {
    public static void main(String[] args) {
        Predicate&amp;lt;String&amp;gt; isEmpty = (str) -&amp;gt; str.isEmpty();

        System.out.println(isEmpty.test("")); // Output: true
        System.out.println(isEmpty.test("Hello")); // Output: false
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 2: Using Function Interface&lt;/strong&gt;&lt;br&gt;
The Function interface represents a function that takes one argument and produces a result.&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.function.Function;

public class Main {
    public static void main(String[] args) {
        Function&amp;lt;Integer, String&amp;gt; intToString = (num) -&amp;gt; "Number: " + num;

        System.out.println(intToString.apply(5)); // Output: Number: 5
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 3: Using Consumer Interface&lt;/strong&gt;&lt;br&gt;
The Consumer interface represents an operation that takes a single argument and returns no result.&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.function.Consumer;

public class Main {
    public static void main(String[] args) {
        Consumer&amp;lt;String&amp;gt; printUpperCase = (str) -&amp;gt; System.out.println(str.toUpperCase());

        printUpperCase.accept("hello"); // Output: HELLO
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 4: Using Supplier Interface&lt;/strong&gt;&lt;br&gt;
The Supplier interface represents a supplier of results, which doesn't take any arguments and returns a result.&lt;br&gt;
import java.util.function.Supplier;&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 Main {
    public static void main(String[] args) {
        Supplier&amp;lt;String&amp;gt; helloSupplier = () -&amp;gt; "Hello, world!";

        System.out.println(helloSupplier.get()); // Output: Hello, world!
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Common Use Cases for Lambda Expressions and Functional Interfaces :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Case 1: Filtering Collections&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 java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List&amp;lt;String&amp;gt; names = Arrays.asList("Alice", "Bob", "Charlie", "David");

        // Filter names that start with 'A'
        List&amp;lt;String&amp;gt; filteredNames = names.stream()
          .filter(name -&amp;gt; name.startsWith("A"))
              .collect(Collectors.toList());

        filteredNames.forEach(System.out::println);             // Output: Alice
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Case 2: Mapping Collections&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 java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List&amp;lt;String&amp;gt; names = Arrays.asList("Alice", "Bob", "Charlie", "David");

        // Convert names to uppercase
        List&amp;lt;String&amp;gt; upperCaseNames = names.stream()
                                           .map(String::toUpperCase)
                                           .collect(Collectors.toList());

        upperCaseNames.forEach(System.out::println); // Output: ALICE, BOB, CHARLIE, DAVID
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Case 3: Reducing Collections&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 java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List&amp;lt;Integer&amp;gt; numbers = Arrays.asList(1, 2, 3, 4, 5);

        // Sum of all numbers
        int sum = numbers.stream()
                         .reduce(0, Integer::sum);

        System.out.println("Sum: " + sum); // Output: Sum: 15
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Case 4: Creating Custom Functional Interfaces&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;@FunctionalInterface
interface MathOperation {
    int operate(int a, int b);
}

public class Main {
    public static void main(String[] args) {
        // Define lambda expressions for addition and multiplication
        MathOperation addition = (a, b) -&amp;gt; a + b;
        MathOperation multiplication = (a, b) -&amp;gt; a * b;

        System.out.println("Addition: " + addition.operate(5, 3)); // Output: Addition: 8
        System.out.println("Multiplication: " + multiplication.operate(5, 3)); // Output: Multiplication: 15
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br&gt;
Lambda Expressions and Functional Interfaces are powerful features in Java 8 that enable you to write more concise, readable, and functional-style code. They are particularly useful for operations on collections and data, allowing you to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filter:&lt;/strong&gt; Select elements based on a condition.&lt;br&gt;
&lt;strong&gt;Map:&lt;/strong&gt; Transform elements.&lt;br&gt;
&lt;strong&gt;Reduce:&lt;/strong&gt; Combine elements into a single result.&lt;br&gt;
&lt;strong&gt;Custom Functional Interfaces:&lt;/strong&gt; Define your own interfaces for specific tasks&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Coding...&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>java8</category>
      <category>lambda</category>
      <category>functionalinterfaces</category>
    </item>
    <item>
      <title>Java Stream API</title>
      <dc:creator>Abhishek Singh</dc:creator>
      <pubDate>Sun, 09 Jun 2024 13:37:34 +0000</pubDate>
      <link>https://dev.to/abhishek999/java-stream-api-lh2</link>
      <guid>https://dev.to/abhishek999/java-stream-api-lh2</guid>
      <description>&lt;p&gt;&lt;strong&gt;Overview :&lt;/strong&gt; &lt;br&gt;
The Java Stream API facilitates processing sequences of elements, offering operations like filtering, mapping, and reducing. Streams can be used to perform operations in a declarative way, resembling SQL-like operations on data&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Concepts :&lt;/strong&gt; &lt;br&gt;
&lt;strong&gt;Stream:&lt;/strong&gt; A sequence of elements supporting sequential and parallel aggregate operations&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Intermediate Operations:&lt;/strong&gt; Operations that return another stream and are lazy (e.g., filter, map)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terminal Operations:&lt;/strong&gt; Operations that produce a result or a side-effect and are not lazy (e.g., collect, forEach)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Scenario :&lt;/strong&gt; &lt;br&gt;
Suppose we have a list of Person objects and we want to perform various operations on this list using the Stream API&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 Person {
    private String name;
    private int age;
    private String city;

    public Person(String name, int age, String city) {
        this.name = name;
        this.age = age;
        this.city = city;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getCity() {
        return city;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + ", city='" + city + "'}";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use Cases : &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Filtering&lt;/li&gt;
&lt;li&gt;Mapping&lt;/li&gt;
&lt;li&gt;Collecting&lt;/li&gt;
&lt;li&gt;Reducing&lt;/li&gt;
&lt;li&gt;FlatMapping&lt;/li&gt;
&lt;li&gt;Sorting&lt;/li&gt;
&lt;li&gt;Finding and Matching&lt;/li&gt;
&lt;li&gt;Statistics&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;Filtering :&lt;/strong&gt; Filtering allows you to select elements that match a given condition&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.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List&amp;lt;Person&amp;gt; people = Arrays.asList(
            new Person("Alice", 30, "New York"),
            new Person("Bob", 20, "Los Angeles"),
            new Person("Charlie", 25, "New York"),
            new Person("David", 40, "Chicago")
        );

        // Filter people older than 25
        List&amp;lt;Person&amp;gt; filteredPeople = people.stream().filter(person -&amp;gt; person.getAge() &amp;gt; 25)                                       .collect(Collectors.toList());
        filteredPeople.forEach(System.out::println);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Mapping :&lt;/strong&gt;  Mapping transforms each element to another form using a function&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 Main {
    public static void main(String[] args) {
        List&amp;lt;Person&amp;gt; people = Arrays.asList(
            new Person("Alice", 30, "New York"),
            new Person("Bob", 20, "Los Angeles"),
            new Person("Charlie", 25, "New York"),
            new Person("David", 40, "Chicago")
        );
        // Get list of names
        List&amp;lt;String&amp;gt; names = people.stream()
                                   .map(Person::getName)
                                   .collect(Collectors.toList());
        names.forEach(System.out::println);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Collecting :&lt;/strong&gt; Collecting gathers the elements of a stream into a collection or other data structures&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 Main {
    public static void main(String[] args) {
        List&amp;lt;Person&amp;gt; people = Arrays.asList(
            new Person("Alice", 30, "New York"),
            new Person("Bob", 20, "Los Angeles"),
            new Person("Charlie", 25, "New York"),
            new Person("David", 40, "Chicago")
        );
        // Collect names into a set
        Set&amp;lt;String&amp;gt; uniqueCities = people.stream()
         .map(Person::getCity).collect(Collectors.toSet());
        uniqueCities.forEach(System.out::println);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Reducing :&lt;/strong&gt; Reducing performs a reduction on the elements of the stream using an associative accumulation function and returns an Optional&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 Main {
    public static void main(String[] args) {
         List&amp;lt;Person&amp;gt; people = Arrays.asList(
            new Person("Alice", 30, "New York"),
            new Person("Bob", 20, "Los Angeles"),
            new Person("Charlie", 25, "New York"),
            new Person("David", 40, "Chicago")
        );
        // Sum of ages
        int totalAge = people.stream()
                 .map(Person::getAge).reduce(0, Integer::sum);
        System.out.println("Total Age: " + totalAge);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;FlatMapping :&lt;/strong&gt; FlatMapping flattens nested structures into a single stream.&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 Main {
    public static void main(String[] args) {
        List&amp;lt;List&amp;lt;String&amp;gt;&amp;gt; namesNested = Arrays.asList(
            Arrays.asList("John", "Doe"),
            Arrays.asList("Jane", "Smith"),
            Arrays.asList("Peter", "Parker")
        );

        List&amp;lt;String&amp;gt; namesFlat = namesNested.stream()
             .flatMap(List::stream).collect(Collectors.toList());
        namesFlat.forEach(System.out::println);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Sorting :&lt;/strong&gt; Sorting allows you to sort the elements of a stream&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 Main {
    public static void main(String[] args) {
        List&amp;lt;Person&amp;gt; people = Arrays.asList(
            new Person("Alice", 30, "New York"),
            new Person("Bob", 20, "Los Angeles"),
            new Person("Charlie", 25, "New York"),
            new Person("David", 40, "Chicago")
        );

        // Sort by age
        List&amp;lt;Person&amp;gt; sortedPeople = people.stream()
            .sorted(Comparator.comparing(Person::getAge))
            .collect(Collectors.toList());
        sortedPeople.forEach(System.out::println);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Finding and Matching :&lt;/strong&gt; &lt;br&gt;
Finding and matching operations check the elements of a stream to see if they match a given predicate&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 Main {
    public static void main(String[] args) {
        List&amp;lt;Person&amp;gt; people = Arrays.asList(
            new Person("Alice", 30, "New York"),
            new Person("Bob", 20, "Los Angeles"),
            new Person("Charlie", 25, "New York"),
            new Person("David", 40, "Chicago")
        );

        // Find any person living in New York
        Optional&amp;lt;Person&amp;gt; personInNY = people.stream()
               .filter(person -&amp;gt; "NewYork".equals(person.getCity())).findAny();

        personInNY.ifPresent(System.out::println);

        // Check if all people are older than 18
        boolean allAdults = people.stream()
          .allMatch(person -&amp;gt; person.getAge() &amp;gt; 18);

        System.out.println("All adults: " + allAdults);
    }
}

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

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Statistics :&lt;/strong&gt; The Stream API can also be used to perform various statistical operations like counting, averaging, etc.&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 Main {
    public static void main(String[] args) {
       List&amp;lt;Person&amp;gt; people = Arrays.asList(
            new Person("Alice", 30, "New York"),
            new Person("Bob", 20, "Los Angeles"),
            new Person("Charlie", 25, "New York"),
            new Person("David", 40, "Chicago")
        );

        // Count number of people
        long count = people.stream().count();
        System.out.println("Number of people: " + count);

        // Calculate average age
        Double averageAge = people.stream()
        .collect(Collectors.averagingInt(Person::getAge));

        System.out.println("Average Age: " + averageAge);
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Practical Example :&lt;/strong&gt; &lt;br&gt;
Here's a comprehensive example that uses several of the features mentioned above:&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.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        List&amp;lt;Person&amp;gt; people = Arrays.asList(
            new Person("Alice", 30, "New York"),
            new Person("Bob", 20, "Los Angeles"),
            new Person("Charlie", 25, "New York"),
            new Person("David", 40, "Chicago")
        );

        // Filter, map, sort, and collect
        List&amp;lt;String&amp;gt; names = people.stream()
                                   .filter(person -&amp;gt; person.getAge() &amp;gt; 20)
                                   .map(Person::getName)
                                   .sorted()
                                   .collect(Collectors.toList());

        names.forEach(System.out::println);

        // Find the oldest person
        Optional&amp;lt;Person&amp;gt; oldestPerson = people.stream()
                                              .max(Comparator.comparing(Person::getAge));

        oldestPerson.ifPresent(person -&amp;gt; System.out.println("Oldest Person: " + person));

        // Group by city
        Map&amp;lt;String, List&amp;lt;Person&amp;gt;&amp;gt; peopleByCity = people.stream()
                                                       .collect(Collectors.groupingBy(Person::getCity));

        peopleByCity.forEach((city, peopleInCity) -&amp;gt; {
            System.out.println("People in " + city + ": " + peopleInCity);
        });

        // Calculate total and average age
        IntSummaryStatistics ageStatistics = people.stream()
                                                   .collect(Collectors.summarizingInt(Person::getAge));

        System.out.println("Total Age: " + ageStatistics.getSum());
        System.out.println("Average Age: " + ageStatistics.getAverage());
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Summary :&lt;/strong&gt;&lt;br&gt;
The Java Stream API is a powerful tool for working with collections and data. It allows for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filtering:&lt;/strong&gt; Select elements based on a condition&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mapping:&lt;/strong&gt; Transform elements&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collecting:&lt;/strong&gt; Gather elements into collections or other data structures&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reducing:&lt;/strong&gt; Combine elements into a single result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FlatMapping:&lt;/strong&gt; Flatten nested structures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sorting:&lt;/strong&gt; Order elements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding and Matching:&lt;/strong&gt; Check elements against a condition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Statistics:&lt;/strong&gt; Perform statistical operations.&lt;/p&gt;

&lt;p&gt;Understanding these features will help you write cleaner, more concise, and more readable code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Coding...&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>java</category>
      <category>stream</category>
      <category>java8</category>
    </item>
    <item>
      <title>Java Records</title>
      <dc:creator>Abhishek Singh</dc:creator>
      <pubDate>Sun, 09 Jun 2024 13:12:41 +0000</pubDate>
      <link>https://dev.to/abhishek999/java-records-1bil</link>
      <guid>https://dev.to/abhishek999/java-records-1bil</guid>
      <description>&lt;p&gt;&lt;strong&gt;All About Java Records :&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overview :&lt;/strong&gt; &lt;br&gt;
Java Records, introduced in Java 14 as a preview feature and finalized in Java 16, provides a concise way to model immutable data. They simplify the boilerplate code needed for data-carrying classes by automatically generating methods like equals(), hashCode() and toString()&lt;/p&gt;

&lt;p&gt;By the end of this post we will understand:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What records are in Java?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;How to create and use records in Java?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;The benefits of using records in Java?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;And some limitations of records in Java?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are Records?&lt;/strong&gt;&lt;br&gt;
A record in Java is a special kind of class that is designed to hold immutable data. It automatically provides implementations for methods like:&lt;/p&gt;

&lt;p&gt;equals()&lt;br&gt;
hashCode()&lt;br&gt;
toString()&lt;br&gt;
Getters for all fields&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use Records?&lt;/strong&gt;&lt;br&gt;
Records help reduce boilerplate code in data classes. Instead of writing constructors, getters, equals(), hashCode(), and toString() methods manually, we can define all of this with a single line of code&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to Define a Record?&lt;/strong&gt; &lt;br&gt;
Here's how we can define a simple record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public record Point(int x, int y) {
}

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

&lt;/div&gt;



&lt;p&gt;This single line of code automatically provides:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A constructor&lt;/li&gt;
&lt;li&gt;Getters (x() and y())&lt;/li&gt;
&lt;li&gt;equals(), hashCode(), and toString() methods&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example: How to use Records?&lt;/strong&gt;&lt;br&gt;
Let's see how we can use the Point record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Point point = new Point(3, 4);

        // Using the auto-generated toString() method
        System.out.println(point);  // Output: Point[x=3, y=4]

        // Accessing the fields using auto-generated methods
        System.out.println("X: " + point.x());  // Output: X: 3
        System.out.println("Y: " + point.y());  // Output: Y: 4
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example: Custom Methods in Records :&lt;/strong&gt; &lt;br&gt;
You can also add custom methods to records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public record Point(int x, int y) {
    public double distanceFromOrigin() {
        return Math.sqrt(x * x + y * y);
    }
}

public class Main {
    public static void main(String[] args) {
        Point point = new Point(3, 4);
        System.out.println("Distance from origin: " + point.distanceFromOrigin());  // Output: 5.0
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Custom Constructors :&lt;/strong&gt;&lt;br&gt;
We can also define custom constructors in records, but they must delegate to the canonical constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public record Point(int x, int y) {
    public Point(int x) {
        this(x, 0);  // Delegating to the canonical constructor
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Limitations of Records :&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Immutability:&lt;/strong&gt; Records are immutable by design. You cannot change the values of their fields after creation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. No Inheritance:&lt;/strong&gt; Records cannot extend other classes. They implicitly extend java.lang.Record&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. All-Args Constructor:&lt;/strong&gt; We cannot create a no-argument constructor directly in records. We must always provide all the components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to Use Records :&lt;/strong&gt; &lt;br&gt;
Use records when:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We need a simple, immutable data carrier class&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We want to reduce boilerplate code for equals(), hashCode(), and toString() methods&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We don't need to extend another class or implement complex behavior&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Practical Example :&lt;/strong&gt;&lt;br&gt;
Let's create a more complex example with a Person record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public record Person(String name, int age) {
    public Person {
        // Custom constructor with validation
        if (age &amp;lt; 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
    }

    // Custom method
    public String greeting() {
        return "Hello, my name is " + name + " and I am " + age + " years old.";
    }
}

public class Main {
    public static void main(String[] args) {
        Person person = new Person("Alice", 30);
        System.out.println(person.greeting());  // Output: Hello, my name is Alice and I am 30 years old.
        System.out.println(person);  // Output: Person[name=Alice, age=30]
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Points :&lt;/strong&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; &lt;br&gt;
public record Person(String name, int age) {}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom Constructor:&lt;/strong&gt; &lt;br&gt;
Validates that age is non-negative&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom Method:&lt;/strong&gt; &lt;br&gt;
Adds a greeting() method&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Conclusion :&lt;/strong&gt; &lt;br&gt;
Java Records provide a simple and powerful way to create immutable data classes with minimal boilerplate code. They are especially useful for modeling data transfer objects and other simple data carriers. By understanding and using records, you can write cleaner and more concise code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Coding...&lt;/strong&gt;&lt;/p&gt;

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