eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Regression testing is an important step in the release process, to ensure that new code doesn't break the existing functionality. As the codebase evolves, we want to run these tests frequently to help catch any issues early on.

The best way to ensure these tests run frequently on an automated basis is, of course, to include them in the CI/CD pipeline. This way, the regression tests will execute automatically whenever we commit code to the repository.

In this tutorial, we'll see how to create regression tests using Selenium, and then include them in our pipeline using GitHub Actions:, to be run on the LambdaTest cloud grid:

>> How to Run Selenium Regression Tests With GitHub Actions

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Overview

In this article, we are going to explore an interesting feature of NIO2 – the FileVisitor interface.

All operating systems and several third party applications have a file search function where a user defines search criteria.

This interface is what we need to implement such a functionality in a Java application. Should you need to search for all .mp3 files, find and delete .class files or find all files that haven’t been accessed in the last month, then this interface is what you need.

All the classes we need to implement this functionality are bundled in one package:

import java.nio.file.*;

2. How FileVisitor Works

With the FileVisitor interface, you can traverse the file tree to any depth and perform any action on the files or directories found on any branch.

A typical implementation of the FileVisitor interface looks like this:

public class FileVisitorImpl implements FileVisitor<Path> {

    @Override
    public FileVisitResult preVisitDirectory(
      Path dir, BasicFileAttributes attrs) {
        return null;
    }

    @Override
    public FileVisitResult visitFile(
      Path file, BasicFileAttributes attrs) {
        return null;
    }

    @Override
    public FileVisitResult visitFileFailed(
      Path file, IOException exc) {       
        return null;
    }

    @Override
    public FileVisitResult postVisitDirectory(
      Path dir, IOException exc) {    
        return null;
    }
}

The four interface methods allow us to specify the required behavior at key points in the traversal process: before a directory is accessed, when a file is visited, or when a failure occurs and after a directory is accessed respectively.

The return value at each stage is of type FileVisitResult and controls the flow of the traversal. Perhaps you want to walk the file tree looking for a particular directory and terminate the process when it is found or you want to skip specific directories or files.

FileVisitResult is an enum of four possible return values for the FileVisitor interface methods:

  • FileVisitResult.CONTINUE – indicates that the file tree traversal should continue after the method returning it exits
  • FileVisitResult.TERMINATE – stops the file tree traversal and no further directories or files are visited
  • FileVisitResult.SKIP_SUBTREE – this result is only meaningful when returned from the preVisitDirectory API, elsewhere, it works like CONTINUE. It indicates that the current directory and all its subdirectories should be skipped
  • FileVisitResult.SKIP_SIBLINGS – indicates that traversal should continue without visiting the siblings of the current file or directory. If called in the preVisitDirectory phase, then even the current directory is skipped and the postVisitDirectory is not invoked

Finally, there has to be a way to trigger the traversal process, perhaps when the user clicks the search button from a graphical user interface after defining search criteria. This is the simplest part.

We just have to call the static walkFileTree API of the Files class and pass to it an instance of Path class which represents the starting point of the traversal and then an instance of our FileVisitor:

Path startingDir = Paths.get("pathToDir");
FileVisitorImpl visitor = new FileVisitorImpl();
Files.walkFileTree(startingDir, visitor);

3. File Search Example

In this section, we are going to implement a file search application using the FileVisitor interface. We want to make it possible for the user to specify the complete file name with extension and a starting directory in which to look.

When we find the file, we print a success message to the screen and when the entire file tree is searched without the file being found, we also print an appropriate failure message.

3.1. The Main Class

We will call this class FileSearchExample.java:

public class FileSearchExample implements FileVisitor<Path> {
    private String fileName;
    private Path startDir;

    // standard constructors
}

We are yet to implement the interface methods. Notice that we have created a constructor which takes the name of the file to search for and the path to start searching from. We will only use the starting path as a base case to conclude that the file has not been found.

In the following subsections, we will implement each interface method and discuss it’s role in this particular example application.

3.2. The preVisitDirectory API

Let’s start by implementing the preVisitDirectory API:

@Override
public FileVisitResult preVisitDirectory(
  Path dir, BasicFileAttributes attrs) {
    return CONTINUE;
}

As we say earlier, this API is called each time the process encounters a new directory in the tree. Its return value determines what will happen next depending on what we decide. This is the point at which we would skip specific directories and eliminate them from the search sample space.

Let’s choose not to discriminate any directories and just search in all of them.

3.3. The visitFile API

Next, we will implement the visitFile API. This is where the main action happens. This API is called everytime a file is encountered. We take advantage of this to check the file attributes and compare with our criteria and return an appropriate result:

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
    String fileName = file.getFileName().toString();
    if (FILE_NAME.equals(fileName)) {
        System.out.println("File found: " + file.toString());
        return TERMINATE;
    }
    return CONTINUE;
}

In our case, we are only checking the name of the file being visited to know if it’s the one the user is searching for. If the names match, we print a success message and terminate the process.

However, there is so much one can do here, especially after reading the File Attributes section. You could check created time, last modified time or last accessed times or several attributes available in the attrs parameter and decide accordingly.

3.4. The visitFileFailed API

Next, we will implement the visitFileFailed API. This API is called when a specific file is not accessible to the JVM. Perhaps it has been locked by another application or it could just be a permission issue:

@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
    System.out.println("Failed to access file: " + file.toString());
    return CONTINUE;
}

We simply log a failure message and continue with traversal of the rest of the directory tree. Within a graphical application, you could choose to ask the user whether to continue or not using a dialog box or just log the message somewhere and compile a report for later use.

3.5. The postVisitDirectory API

Finally, we will implement the postVisitDirectory API. This API is called each time a directory has been fully traversed:

@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc){
    boolean finishedSearch = Files.isSameFile(dir, START_DIR);
    if (finishedSearch) {
        System.out.println("File:" + FILE_NAME + " not found");
        return TERMINATE;
    }
    return CONTINUE;
}

We use the Files.isSameFile API to check if the directory that has just been traversed is the directory where we started traversal from. If the return value is true, that means the search is complete and the file has not been found. So we terminate the process with a failure message.

However, if the return value is false, that means we just finished traversing a subdirectory and there is still a probability of finding the file in some other subdirectory. So we continue with traversal.

We can now add our main method to execute the FileSearchExample application:

public static void main(String[] args) {
    Path startingDir = Paths.get("C:/Users/user/Desktop");
    String fileToSearch = "hibernate-guide.txt"
    FileSearchExample crawler = new FileSearchExample(
      fileToSearch, startingDir);
    Files.walkFileTree(startingDir, crawler);
}

You can play around with this example by changing the values of startingDir and fileToSearch variables. When fileToSearch exists in startingDir or any of its subdirectories, then you will get a success message, else, a failure message.

4. Conclusion

In this article, we have explored some of the less commonly used features available in the Java 7 NIO.2 filesystem APIs, particularly the FileVisitor interface. We have also managed to go through the steps of building a file search application to demonstrate its functionality.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)