If you ever wanted to secure your brilliant REST API with Spring Boot but Spring Security felt too confusing, badly documented and a little overkill for the simple stuff you want to do, you can create a simple, stateless, authentication mechanism for your services using JWT Tokens.

As a proof of concept on how we are going to integrate the JWT tokens with our Spring Boot Rest api we are going to create three REST services:

  • /api/public/hello/{name} : This will be a public web service that will say hello without discrimination;
  • /api/secure/hello/{name} : This will perform the same operation as the service above, but it will be callable only by authenticated users. Otherwise it will return 401 Unauthorised. Or 406 Not Acceptable if somebody is trying to hack into your tokens :);
  • /api/public/auth/ : This service will allow the users of your API to authenticate with it.

The code can be found also on github:

Our project will be built using Spring Initialzr together with gradle. Our build.gradle file for the project will eventually look like this.

Observations:

  • The library that implements the JWT part is called jjwt and can be found here.
  • I prefer to use project lombok in my projects. It’s a cool little library that generates getters/setters/constructors/builders and other neat stuff through the use of annotations.

A good idea for the project is to keep some of the configurable properties like the time to live for the token, the authentication header and the secret key in the Spring Boot application.properties file.

They can easily be “injected” in our code at a later time using the @Value annotation.

Continue reading

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.


ByteBuffers

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

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:

Or:

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:

Output:


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:

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()”.

Java annotations are syntactic meta-information that can be added to your Java source code. You can annotate classes, methods, variables, method parameters and even packages.

The great advantage of Java annotations over javadoc tags is that those bits of information can be reflective and thus they can be made available to the VM at runtime (using the the Java Relection API).

Other than this, modern Java frameworks (like Spring) make heavy use of annotations in order to let the developer, extend, inject data and configure existent behaviors.

In this article we will define our own custom annotations, and we will use reflection to analyze and enhance the behavior of our Java beans at run-time.

Let’s suppose we want to write a mechanism that transforms (let’s say serialize) a given collection of java beans instances to a CSV file .CSV stands for Comma Separated Values. If you want to learn more about CSV files please check out this wikipedia article.

We don’t want to “serialize” all the fields, so will use annotations to mark only the fields we wish to “export”.

The first step will be the write the annotations class. We will call this one CSVExport.java :

As you can see all annotations related classes are included in the java.lang.annotation.* package. Other than this we will need to mark this annotation with a RetentionPolicy that will make it available at run-time, and we will specify that the annotation can only be used in conjunction with class methods (in our case those methods will be the bean getters).

At this point we will write a “model” java bean and we will mark the getters we want to serialize with our newly defined custom annotation.

Only the method that were annotated with @CSVExport will be serialized to the resulting file. If no annotations is present the specified getter method will be ignored.

The next step will be to write the class that actual export our collection. We will call this one CollectionToCSV.java:

The most important method buildCSVRow , as it iterates through the methods of the T.class (where T appears as a generic type, but in our case will be a TestModel instance), checks if the getter is marked with the @CSVExport annotation, and if the answer is yes the method will be invoked and the result will be included in our serialization.

If we run the main method the result will be:

If in the TestModel class we remove all the getters annotations nothing will be exported.

Recently I’ve encountered a rather strange behaviour related to Java Web Start.

If, in your .jnlp file you are referencing some signed jars, sometimes the verification fails miserably with the following stacktrace:

If you are 100% sure that your jars are correctly signed, check if your JRE setup have “Keep temporary files on my computer” option enabled. That solved the problem for me.

So if you are on Windows: Control Panel -> Java and then:

Hope it helps.