Writing an unified validation mechanism for REST APIs using Spring Boot and JSR-380

JSR-380 defines a metadata model and API for Java Bean validation. It can be used an “architectural-agnostic” way and it is particularly useful when it comes to validating the RESTful APIs (syntactic validation).

The default metadata source is @Annotations, with the ability to override and extend the metadata through the use of XML validation descriptors or custom code:

JSR-380 was finished in August, 2017 and it’s now a Java EE 8 standard. It’s also included by default in Spring Boot through the only available implementation – Hibernate Validator.

By default, JSR-380 doesn’t standardise a big list of validating @Annotations. Hibernate Validator adds a few extra, and enhances the existing ones, but it’s still not enough. As a developer working for a real world application you will probably need to write custom constraints.

That’s why i’ve compiled myself a library of common annotations (that are not in the standard or in Hibernate Validator). The library and code can be found on github under the name JBVExt (Java Bean Validation Extensions).

The project setup

The “example” project is a simple Spring Boot project. The main dependencies are:

By default the spring-boot-starter-web includes Hibernate Validator, so there’s no need to explicitly define it as a dependency.

Decorating the RESTful API

The API we are going to validate is composed by two REST web-services:

POST /user/ : For creating an user;
POST /post/ : For submitting the text;

The requestBodies are being mapped to the following two classes.

The comments describe each of the field-level constraints.

For example in the above class the field appCode needs to always start with “A” and end in “00”.

Note: The @Data, @AllArgsConstructor and @NoArgsConstructor are not related with JSR-380, but are part of Project Lombok.

In order to implement the constraints at the field level we would normally to write custom Java code. This type of code can become repetitive (and less readable) as soon the application grows.

JSR-380 proposes a new “decorative” approach. So instead to add the validation code at the controller level, we could just decorate the model layer with @Annotations.

In conclusion the CreateUserReq.java becomes:

And the CreatePostReq.java class becomes:

Creating an unified way of intercepting validation errors.

The JBVExt library contains an util method SimpleValidation.validate(…) that will throw a BeanValidationException exception the first time a constraint is violated.

So we will make each controller of our API invoke this method before doing anything else:

The next step will be define a “Global” Exception Handler that will intercept any BeanValidationException thrown from our Controllers and treat them in the same manner.

The @ControllerAdvice and @ExceptionHandler annotations (part of Spring) will become handy:

So instead of having to repeat all the try/catch code in each controller, we can define this unified strategy in a separate class, that will threat each exception (of type BeanValidationException) in the same way.

Running the code

The code is available on git:

The Spring Boot application will run by default on port 8080.

If we try to POST http://localhost:8080 with an invalid bodyRequest (as described by the JSR380 validation):

Simple authentication with Spring Boot and JWT Tokens

In the following article I am going to prove how you can secure a REST API (developed with Spring Boot) with JWT tokens. For simplicity Spring Security will not be used.

It is assumed the reader is already familiar with JWT.

Our Rest API will contain 3 endpoints, 2 public and 1 private (that can only be accepted with JWT):

  • /api/public/hello/{name} : Public web service that prints hello.
  • /api/secure/hello/{name} : Private web service that prints hello. Can only be called if the JWT token exist on the header. Otherwise returns HTTP 403.
  • /api/public/auth/ : Authentication service. Based on user/pass credentials generates and valid JWT token.

All the code is available on github:

Project is bootstrapped using Spring Initialzr together with gradle.

The generated build.gradle file is:


  • The library that coverts the JWT functionality is called jjwt.
  • I prefer to use project lombok in my projects. It’s an useful library that can generate getters, setters, constructors, etc. through @Annotations.

We will be starting the project by defining some of the constants. A good idea is to store them in the application.properties file, so we can easily inject them at runtime using @Value annotation.

Read More

How to use SeekableByteChannel interface for Random Access to Files (RAF)

RAFs, Random Access Files permit asynchronous (random) access to a file contents. To access a file randomly we open the file, seek a particular position, and then we read or write to that file.

Java NIO.2 introduces a new interface – SeekableByteChannel for working with Random Access Files. Also improves the well-known FileChannel class by implementing this interface.

Before we start to talk about about FileChannel and SeekableByteChannel it is advisable to first talk a little bit about ByteBuffers and Channels.


A byte-buffer is an in-memory array of bytes. It usually contains data that was recently read, or that will be written from/to a destination.

A buffer has three important properties:

  • The buffer’s capacity represents the “maximum amount of information” that can be stored in the buffer.
  • The buffer’s position represents how much data has been read or written. The position is an index in the buffer’s array, and cannot have a negative value or a value bigger than the buffer’s capacity.
  • The buffer’s limit is the difference between buffer’s capacity and the buffer’s position.


Channels are in a way similar with the classical I/O streams, the difference is that while streams are one-way directed (read or write), channels can support both operations in the same time. Also Channels allow you to write and read asynchronously.

Using SeekableByteChannel to write / read to / from files

The SeekableByteChannel interface has 6 methods:

  • position(): Returns the channels current position.
  • position(long): Sets the channel position to the specified value. The value needs to be a positive number.
  • truncate(long): Truncates the entity connected to the SeekableByteChannel to the specified value.
  • read(ByteBuffer): Reads into the buffer (from the channe).
  • write(ByteBuffer): Writes bytes from the buffer to the channel.
  • size(): Returns the current size of the entity to which the channel is connected.

To open a SeekableByteChannel we will need to use the the two methods from the java.nio.file.Files class:


As you can see to open a seekable channel you need to supply as input the Path you want to open (basically the file) and also open options, which are enum constants.

The possible enum options are as follow:

READ The file is opened with READ access.
WRITE The file is opened with WRITE access.
CREATE Creates the file if the file does not already exist.
CREATE_NEW Creates the file if the file does not already exist. If the file exists throw an exception.
APPPEND Appends to the file. It is used in conjunction with CREATE and WRITE.
DELETE_ON_CLOSE Deletes the file after the channel is closed. Use this when creating and editing / reading from temporary files.
TRUNCATE_EXISTING Truncates the file to size 0. It is used in conjunction with WRITE and it’s useful when you want to clean the contents of a file.
SPARSE Usually used in conjunction with CREATE or CREATE_NEW. On some file systems large files that have big “data gaps” are stored in a more efficient way.
SYNC File content + metadata is synchronized with the underlying file system.
DSYNC File content is synchronized with the underlying file system.

Reading a file using a SeekableByteChannel

Please follow the comments:


Writing a file using SeekableByteChannel

Please follow the comments:

If we are going to open the file called “file2.txt” from our home folder the content will be:

If we run multiple times the program the content of the file will look like this (the text is appended):

Using the SeekableByteChannel to read characters from different file locations

Given the following acrostic:

We want to read the first 3 letters at the beginning of every word and print on the standard output.

Code example:

And the output of the code:

Writing a simple file/folder monitor using the Watch Service API

The Watch Service was introduced in Java 7 as a “thread-safe” service responsible for watching objects for changes.

The most popular use of this API would be to use it as way to monitor a folder of files for changes such as: addition of new files, deletion of files, file renames, etc.

Implementing a WatchService

The WatchService is dependent on the FileSystem, the first step of creating a new Service is to obtain the underlying file system:

Every object needs to be explicitly registered with the newly created service. In our particular case we will register a Path instance (a folder).

After we register the object, we also need to specific events the service need to watch.


  • StandardWatchEventKinds.ENTRY_CREATE: This event triggers when a folder entry is created, or a new entry is moved or renamed.
  • StandardWatchEventKinds..ENTRY_DELETE: This event is triggered when a folder/file is deleted, moved or renamed.
  • StandardWatchEventKinds.ENTRY_MODIFY: This event is pretty-platform dependent. Usually is triggered when the contents of a file is modified. But on some file systems it can also trigger when the attributes of that particular file are modified.
  • StandardWatchEventKinds.OVERFLOW: Indicates that an event has been lost.

The following code will register ENTRY_CREATE, ENTRY_DELETE and ENTRY_MODIFY to the home folder:

For every Path instance we are registering we will receive an WatchKey instance.

To wait for incoming events we will need to write an infinite loop:

In this loop we will be able to poll for obtaining WatchKey instances.

We can also add a timing interval for polling (if we don’t need an instant feedback on the events):

A WatchKey can have the following states:

  • Ready: The WatchKey is ready to accept events.
  • Signaled: In this state the WatchKey has at least one event that occurred and it was queued.
  • Invalid: In this state the key is considered to be no longer valid.

So the next step will be to retrieve the pending events from the WatchKey. There can be multiple events that were triggered. Those events are queued. The code to retrieve the pending events is:

To obtain the Path from the watchEvent we will need to do something like this:

The last step of the implementation is to put key back into it’s Ready step.

Also you should also take in consideration that if the loops break (eg.: because of an error) you need to explicitly close the Watch Service:

Or, since Java 7, include the opening of the WatchService in the new try() block:

Putting all the code togheter

Please take in consideration that in our particular case we are only going to watch the Home folder, and not the whole sub-tree of folders. If you wish to watch the whole sub-tree for modifications you will need to register a watch service for every folder in the tree.

To obtain the list of sub-folders of a given folder, I recommend you to read my previous article called: Java 7 NIO.2 – Recursive folder walks

Also you will need to maintain the collection of watchers in the case you are creating/deleting new/existing sub-folders.

The Watch Service API is a low-level approach, so maybe it’s best for you if you write your own high-level mechanism, or use an already-existing solution.

I will create new files/folders inside my home directory the output will look like:

Recursive folder walks using NIO.2 API

FileVisitor Interface

The FileVisitor interface allows us to recursively traverse file structures – folders, sub-folders and files.

Every method of this interface can return 4 possible results (instances of the FileVisitResult enum):

This FileVisitor interface has 4 methods:

  • visitFile():
    The method is invoked for a file. The method should return a FileVisitResult.CONTINUE result or a FileVisitResult.TERMINATE result. The method receive a reference to the file (a Path object) and to the BasicFileAttributes object associated with the Path.
  • preVisitDirectory():
    This method is invoked for a directory before visiting its children. The method returns FileVisitResult.CONTINUE if we want it’s children to be visited or FileVisitResult.SKIP_SUBTREE if we want the process to stop. If we want to skip visiting the siblings of the directory we need to return FileVisitResult.SKIP_SIBLINGS .
  • postVisitDirectory():
    This method is invoked after we visit all the children of a directory (including other folders and their descendants).
  • visitFileFailed():
    This method is invoked if a file (or folder) cannot be accessed.

In practice it is also possible to use the SimpleFileVisitor class if we want to traverse only the directories.

Once we have created the “recursive-walking-mechanism” by implementing FileVisitor interface or by extending the SimpleFileVisitor class we can start the recursive process by calling the walkFileTree() method .

Example: Writing an application that search for files bigger than a pre-defined size

In this example we are going to implement a FileVisitor that walks a folder and logs to output all files that are bigger than certain amount.

The first step is to write the FileVisitor:

The main method:

And some sample output from my machine:

Writing a file search application based on a criteria

We can extend the example from above and create a more general approach.

The idea is to write an abstract implementation of the FileVisitor interface, that contains an abstract method “criteria(Path, BasicFileAttributes)“.

Later we can use anonymous classes to define a new behavior of our visitors specifying only the criteria and avoiding to write the boiler-plate-code necessary to implement a FileVisitor.

We will name our FileVisitor implementation FileSearchByCriteriaVisitor:

This class will have two instance variables called results and failedVisits:

The “criteria(Path, BasicFileAttributes)” mentioned before will be used like this:

Now everytime we implement a new FileSearchByCriteriaVisitor we must supply an implementation for the abstract method defined before.

Example how to use the FileSearchByCriteriaVisitor:

The results and the paths with errors are available in “sizeVisitor.getResults()” and “sizeVisitor.getFailedVisits()”.