Internationalization in Spring Boot

Introduction to Internationalization in Spring Boot

In this short post, we will explore how to add Internationalization in Spring Boot application.

1. Introduction

Spring Boot provides a number of build in features which help us to start application development quickly. Spring Boot provides ResourceBundleMessageSource which is a foundation to the internationalization provided by Spring as part of the Spring Boot.

We will be using thymeleaf as our front end templating engine.We can enable thymeleaf in Spring Boot application by using spring-boot-starter-thymeleaf.

 
<dependency>
   <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

 

2. Application Structure

We will be working with a Maven based Spring Boot application, here is the structure for our internationalization. (it will remain same for Gradle based project). Spring Boot application by default will look for internationalization key and values under /src/main/resources folder.

src/
|--  main/
      |--    resources/
               |--   messages.properties
               |--   messages_de.properties
               |--   messages_xx.properties

 

Default locale file will name as messages.properties and files for other locales will havemessages_xx.properties a format where xx is the locale code. In our case, we have another message file containing German data.

Keys which will be used for internationalization will be same in all the message_xx.properties file and only values will be different based on the locale.

If a key does not exist in a certain requested locale, then the application will fall back to the default locale value. 

Below is our sample message.properties file

Default

welcome.message=Welcome to Demo Application
language.change=Change Language
lang.eng=English
lang.de= German

messages_DE.properties

welcome.message=Willkommen bei der Demo-Bewerbung
change.language=Sprache ändern
lang.eng=Englisch
lang.de= Deutsche

 

3. LocaleResolver

LocalResolver is required to correctly determine which local is currently being used. LocalResolver interface allows for implementations based on a request, session, cookies, etc. The default implementation is AcceptHeaderLocaleResolver. We will be using session based LocalResolver in our sample code. Please read LocaleResolver for more details.

@Bean
public LocaleResolver localeResolver(){
       SessionLocaleResolver localeResolver = new SessionLocaleResolver();
       localeResolver.setDefaultLocale(Locale.US);
       return  localeResolver;
   }

 

4.LocaleChangeInterceptor

We need to configure an interceptor which allows for changing the current locale on every request, via a configurable request parameter 

@Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
    LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
    localeChangeInterceptor.setParamName("language");
    return localeChangeInterceptor;
}

default parameter name used by LocalCangeInterceptor is  “locale” but we will be using “language” as the request parameter.

 

We need to add our LocaleChangeInterceptor with Spring Boot so as this can be picked correctly by Spring Boot. In order to register this bean with Spring Boot, we need to override addInterceptor() method in our Configuration class.

@Override
public void addInterceptors(InterceptorRegistry registry){
    registry.addInterceptor(localeChangeInterceptor());
}

5. Controller 

In order to see this in action, we need a controller which will be used to serve a welcome page to see Spring Boot internationalization in action.

@Controller
public class WelcomeController {

    @RequestMapping("/")
    public String hello() {
        return "welcome";
    }
}

 

Above Controller will be come in to picture when we open our application home page (in our case it is http://localhost:8080). It will pick welcome.html template located at src/main/resources/templates.

 

6. UI / HTML

Here is our sample HTML 

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>

    <h1 th:text="#{welcome.message}"></h1>

    <span th:text="#{lang.change}"></span>:
    <select id="locales">
        <option value=""></option>
        <option value="en" th:text="#{lang.eng}"></option>
        <option value="de" th:text="#{lang.de}"></option>
    </select>

</body>
</html>

 

7. Demo Application

If we run our Spring Boot application using main class and open http://localhost:8080

@SpringBootApplication
public class JavadevspringbootApplication extends WebMvcConfigurerAdapter {

   public static void main(String[] args) {
      SpringApplication.run(JavadevspringbootApplication.class, args);
   }

   @Bean
   public LocaleResolver localeResolver(){
        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        localeResolver.setDefaultLocale(Locale.US);
        return  localeResolver;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        return localeChangeInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(localeChangeInterceptor());
    }
}

We will get following HTML Page

Internationalization in Spring Boot
Internationalization in Spring Boot

 

On changing the URL by adding language in the URL (http://localhost:8080/?language=de), we will get German version of the site

Internationalization in Spring Boot
Internationalization in Spring Boot

 

7. Summary

In this post, we learned how to use Internationalization in Spring Boot.We get an understanding about Spring Boot build in support for Internationalization.

Join multiple lists in Java

How to Join multiple lists in Java

In this short post, we will learn how to join multiple lists in Java. We will be covering how to do this in Java 8, Java 7 and how we can use Apache Common API to join these lists.

 

1.  Using  Java 8 Stream API

Java 8 Stream API provides a couple of different options to join multiple lists. We will be exploring concat() and flatMap() method provided by the Stream API.

 

1. 1 Using  Concat method

We can use concat() method to combine two streams, concat() method will work by contacting all elements of the first stream with the second stream.

public class JoinListJava8 {

    public static void main(String[] args) {

        List<String> listA= asList("A", "B","C");
        List<String> listB=asList("C","D","E","F");

        concactStream(listA,listB);
    }


    public static void concactStream(List<String> listA, List<String> listB){

        List<String> newList= Stream.concat(listA.stream(),listB.stream()).collect(Collectors.toList());
        newList.forEach(item-> System.out.println(item));
    }


}

Output


A
B
C
C
D
E
F

In case we have more than 2 Streams to combine, we can use concat() method within original method

Stream.concat(Stream.concat(c.stream(), c2.stream()), c3.stream());
 
1. 2 Using  flatMap method

In case we have a number of lists, we can use flatMap() method to join multiple lists in Java.flatMap method will return a Stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.

Please read Stream#flatMap for more detail

 

public class JoinListJava8 {

    public static void main(String[] args) {

        List<String> listA= asList("A", "B","C");
        List<String> listB=asList("C","D","E","F");

        flatMap(listA,listB);
    }


    public static void flatMap(List<String> listA, List<String> listB){

        List<String> newList= Stream.of(listA,listB).flatMap(Collection::stream).collect(Collectors.toList());
        newList.forEach(item-> System.out.println(item));
    }

}

 

2.  Using  Java 7 

If you are not using Java 8 and do not want to use any third party API (like Apache Common Collections or Guava), you can use addAll() method to accomplish your goal. You need to call addAll() method multiple times to join lists in Java.

public class JoinListJava7 {

    public static void main(String[] args) {

        List<String> listA= asList("A", "B","C");
        List<String> listB=asList("C","D","E","F");

        List<String> listC = new ArrayList<String>();
        listC.addAll(listA);
        listC.addAll(listB);

        //print results

        for(String output: listC){
            System.out.println(output);
        }
    }
}

You can even shorten above code by using 

List<String> listC = new ArrayList<String>(listA);
listC.addAll(listB);

 

3. Apache Commons Collections

Apache Commons Collections API provides utility methods to join multiple lists in Java.

public class JoinListApacheCommons {

    public static void main(String[] args) {

        List<String> listA= asList("A", "B","C");
        List<String> listB=asList("C","D","E","F");

        Iterable<String> newList= CollectionUtils.union(listA,listB);
    }
}

 

4. Summary

In this post, we discussed how to join multiple lists in Java. We covered how to do it in JDK using Java 7 and Java 8 along with an option to use Apache Common Collection API.

All the code of this article is available Over on Github. This is a Maven-based project.

JVM Parameters

Introduction to JVM Parameters

In this post, we will be covering some of the most important and critical JVM Parameters which can be used to configure and fine tune JVM.

Performace of the JVM depends on the factor as to how well JVM is configured for a given application. Let’s cover few of the well known JVM parameters to start with. 

 

This post will serve as a starting point to understand some of the key parameters for the JVM, this post does not cover advanced JVM optimization techniques.

 

1. Heap Memory

One of the main optimization features involves assigning correct heap size to the JVM based on our application. It is recommended to specify minimum and maximum heap size to the JVM

1.1 -Xmxsize (Maximum Heap Size)

Xmx is used to specify the maximum size of the memory, to specify maximum heap size, we can use the following convention

-Xmx<Heap Size>[Unit]

HeapSize denotes the size of the heap and should be multiple of 1024.Unit indicates the unit of the memory in which we want to specify to the JVM.Append the letter k or K to indicate kilobytes, m or M to indicate megabytes, g or G to indicate gigabytes.

For example, if we want to assign maximum of 6GB to our JVM, all of the following parameters are valid

-Xmx6442450944
 -Xmx6000m
 -Xmx6G

 

1.2 -Xmssize (Minimum Heap Size)

Xms is used to specify the minimum size of the memory, to specify minimum heap size, we can use the following convention

-Xms<Heap Size>[Unit]

HeapSize denotes the size of the heap and should be multiple of 1024.Unit indicates the unit of the memory in which we want to specify to the JVM.Append the letter k or K to indicate kilobytes, m or M to indicate megabytes, g or G to indicate gigabytes.

For example, if we want to assign minimum of 4GB to our JVM, all of the following parameters are valid

-Xms4294967296
 -Xms4000m
 -Xms4G

 

For assigning minimum 4GB and maximum 6GB to JVM, we can use following parameters.

-Xms4G -Xmx6G

 

1.3  -XX:NewSize=size (Young Generation Heap Size)

To understand this parameter, we need to understand about young generation region in the heap, young generation region of the heap is used for new objects and due to it, this is known as one of the most important JVM parameters apart from -Xmx and -Xms.

Keep in mind that GC (Garbage collection) is performed more often in this region of the memory, so this needs special consideration as if the size is too low, then JVM will perform a large number of minor GC operation and if size is too large a full GC will be performed which can be time-consuming, this entire activity can have a major impact on the application based on the configured GC. 

We can use the following convention to set size for young generation

-XX:NewSize=<young size>[k|m|G]

For example, to set initial size of the young generation to 1GB, we can use one of the following conventions

-XX:NewSize=1024m
 -XX:NewSize=1G 

We can use -XX:MaxNewSize=size to set a maximum size of the heap for the young generation.

Following JVM parameters has been removed from Java 8, setting those parameters will not perform any modification or optimization to the JVM. It is recommended not to use these parameters -XX:MaxPermSize=size
-XX:PermSize=size

 

2. Garbage Collection Options

Garbage collector can play a vital role in your application and choose a correct Garbage Collector (GC) is really important. JVM provide following type of Gargabe collector

  • Serial Garbage Collector (XX:+UseSerialGC)
  • Parallel Garbage Collector (XX:+UseParallelGC)
  • CMS Garbage Collector (XX:+USeParNewGC)
  • G1 Garbage Collector (XX:+USeG1GC)

Please read  Java Garbage Collector for more details.

 

3. Java Garbage Collection Log (GC Logging)

To debug memory issues or application performance, We can enable GC logging in JVM. GC log provides a lot of information and statics about the Garbage collection process, some of the information (but not limited) provided by GC logging are

  • How Long GC Run
  • Information about when full GC run.
  • Information about the JVM pause when GC was running.
  • Information about Young and Old generation regions.

To understand GC logging, we need to enable GC log in the JVM

3.1 -XX:+PrintGCDetails (Print GC details Messages)

This option is disabled by default, we need to use this flag to enable printing detail messages at every GC.

3.2 -XX:+PrintGCDateStamps (Print GC details Messages)

Can be used for the printing of a date stamp at every GC, this option is also disabled by default.

3.3 -Xloggc:filename

This can be used to set file name and location to which GC output will be redirected.

3.4  -XX:+UseGCLogFileRotation

Should be used to enable log rotation.This can be really helpful for handling large log files produced by long running Java Applications.This property must be used with -Xloggc:<filename>.

3.5  -XX:NumberOfGClogFiles=<number of files>

Sets the number of files to use when rotating logs, default value is 1 and it should be always >=1

3.6 -XX:GCLogFileSize=<number>M (or K)

Defines the size of the log file at which point the log will be rotated, default will be set to 512K

Here is an example with above configurations

-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/home/DATA/gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=20M

Please note that using  +PrintGCDateStamps can add some overhead since an additional thread will be required to monitor system time.

 

4. -Dproperty=value (32 /64 bit)

Sets a system property value. The property variable is a string with no spaces that represents the name of the property.To run an application on 32 or a 64-bit environment, we can use this property as

-d<OS bit>

e.g. -d32 for 32-bit environment or -d64 for 64-bit environment.

 

5. Additional Properties

-server : Selects the Java HotSpot Server VM.For 64 bit, this option is implicit.

-XX:MaxHeapFreeRatio=percent : Sets the maximum allowed percentage of free heap space after a GC event (e.g. -XX:MaxHeapFreeRatio=75 for setting maximum free heap ratio to 75%:)

-XX:MaxMetaspaceSize=size : Sets the maximum amount of native memory that can be allocated for class metadata, there is no limit by default and it will be dependent upon the size/type of application. (-XX:MaxMetaspaceSize=512m to set maximum class meta data size to512 MB)

XX:SurvivorRatio=ratio : Sets the ratio between Eden space size and survivor space size.

 

Summary

In this post, we covered some of the main JVM Parameters which can be used to optimize and configure JVM based on our application. As mentioned in the beginning this post just outlines few of the important JVM Parameters. Please refer to Java HotSpot VM Options for more details (Please refer to correct JDK version for updated list).

Creating a Web Application with Spring Boot

Creating a Web Application with Spring Boot

In this post, we will explore details of Creating a Web Application with Spring Boot. We will explore how Spring Boot can help you to accelerate your application development.We will be building a simple web application with Spring Boot and add some useful services to it.

 

1. Introduction

One of the main challenges to starting up a new project is an initial setup for the project. We need to take a call about the different directory structure and also need to make sure we are following all the industry standards.For creating a web application with Spring Boot, we need following tools

  • Our preferred IDE (I will be using IntelliJ) 
  • Maven
  • JDK 1.8+

 

 

2. Creating Project Structure

There are multiple ways to use Spring Boot Initializr to generate project structure for you.

  1. Using  Spring Initializr Web Interface.
  2. Use Spring Boot CLI tool.
  3. Use your IDE

For the simplicity of this post, we are using Spring Initializer web interface to generate project Structure.

Spring Initializr Web interface your browser and you will be presented with a wizard to start your configurations.

Spring Initializr

You are required to fill some information in the web interface to start with

 

  1. What kind of project you want to generate (Maven or Gradle)
  2. What is your preferred language (Apart from Java you will get an option for Kotlin and Groovy)?
  3. Spring Boot Version
  4. Standard project group and artifact details.
  5. Dependencies.

Dependencies is an interesting feature in the web interface, based on your selected Dependencies, web interface will automatically add Spring Boot Starter dependencies in the generated pom.xml file.In case you want a more control on the generated project structure or not sure what all dependencies you want to add to your project, click on the “Switch to the full version”. 

We will be using The Web and Thymeleaf (For UI) for this post.

 

3. Project Structure

Spring Boot does not require any specific code layout or structure.We can always follow some of the best practices suggested by Spring Boot team, however, final structure will be driven by your project requirement.

 

Here is the layout of our sample application

Project Structure

 

 

4. Pom.xml

Let’s start looking into pom.xml file to understand Spring Boot configurations in more detail. I will be covering only Spring Boot related changes in pom.xml. Here is the pom.xml file from our sample project.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>

   <groupId>com.javadevjournal</groupId>
   <artifactId>javadevspringboot</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>war</packaging>

   <name>javadevspringboot</name>
   <description>Java Dev Journal project for Spring Boot</description>

   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.5.4.RELEASE</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>

   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-tomcat</artifactId>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
   </dependencies>

</project>

One of the main features of Spring Boot is the “Starters”, they are an easy way to add required dependencies (jars) in our class path. When using Spring Boot, we don’t have to add jar/dependencies in our class path (In case a starter is not available, you might have to add these dependencies in the pom.xml or can create your own custom starter). We just need to add correct “Starters” in our pom.xml file and Spring Boot will make sure to add those dependencies automatically.

 

5. Main Application

Here is our main Spring Boot application class, this is a Spring Configuration class. The annotation @SpringBootApplication enables the Spring Context and all the startup magic of Spring Boot.

 

@SpringBootApplication
public class WebApplication extends WebMvcConfigurerAdapter {

   public static void main(String[] args) {
      SpringApplication.run(WebApplication.class, args);
   }
}

 

5. 1 @SpringBootApplication Annotation

@SpringBootApplication annotation. @SpringBootApplication is equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan with their default values.If you are starting your project, it’s recommended to use annotation.

 

Using @SpringBootApplication in your main class is equivalent to following 3 annotations

 

  • @Configuration as a source of bean definitions
  • @EnableAutoConfiguration It gives Spring Boot an idea as to how you want to configure your application.
  • @ComponentScan to automatically pick up all Spring components, including @Configuration classes

 

5. 2 Main Method

Another interesting feature of our main class is the main method. This is a standard method that will follow standard Java workflow. Our main class will pass on control to Spring Boot SpringApplication class.

SpringApplication Class run method will be used to BootStrap an application.

 

6. Welcome Controller

Last part of our setup, we will create a welcome controller which will be responsible to handles GET requests for /greeting by returning the name of a View, in this case, “welcome”. A View is responsible for rendering the HTML content.

 

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller
public class WelcomeController {

    @RequestMapping("/welcome")
    public String welcome() {

        return "welcome";
    }
}

This is a very simple controller but has covered a lot of points in our setup.

  • @Controller annotation indicates that an annotated class is a "Controller" (e.g. a web controller).
  • @RequestMapping annotation ensures that HTTP requests to /welcome are mapped to the welcome() method.
  • We have not specified any method to the @RequestMapping annotation as default maps all HTTP operations by default.
  • As we are using Thymeleaf for view technology and returning “welcome” from welcome() method, Thymeleaf parses the template welcome.html and produce the output.

 

6. 1 UI Template 

Here is our simple Thymeleaf HTML template.

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Getting Started: Serving Web Content</title>

</head>
<body>
Hello and Welcome to our Web Application
</body>
</html>

While using Thymeleaf as our template engine, Spring Boot will look for resources by surrounding the view name with a prefix and suffix (externalized to spring.thymeleaf.prefix and spring.thymeleaf.suffix, defaults ‘classpath:/templates/’ and ‘.html’ respectively).

 

 

7. Run Application

We are done with our simple web application, it’s time to run our application. Although it is possible to package this service as a traditional WAR file for deployment to an external application server, the simpler approach demonstrated is to create a standalone application. To run our application from IDE, We need to run our web application as a standalone java application.

  • With Maven, we can run the application using mvn spring-boot:run command.
  • we can build the JAR file with mvn clean package command and run jar by using java -jar target/demo-app-0.1.0.jar.

Now the site is up and running, visit,http://localhost:8080/welcome and if everything is in place, you should have following output on your web browser.

"Hello and Welcome to our Web Application"

 

8. Summary

In this post, we learned Creating a Web Application with Spring Boot. Spring Boot comes with many builds in feature to create and run web application more quickly and with minimal efforts.

Spring MVC Custom Validator

Spring MVC Custom Validator

In this post, we will learn about using Spring MVC Custom Validator. We will explore as to how to create and use your own custom validator.

Introduction

Spring MVC provides first-hand support for JSR-303 Bean Validation API. We can use this API to validate our input data. Bean Validation API ship with a number of different validators which can be used with the use of simple annotation, however in case we need to validate data based on custom business rules, we have the option to create our own custom validator and hook it with Spring MVC validation framework.

We will be exploring Spring MVC Custom Validator and see how to hook it in our application.

 

1. Maven Setup

In order to create and use the custom validator, we need to validation API and JSR-303 compliance validation API in our class path, we will be using Hibernate validator in our example. To start we need to add following entry in our pom.xml file

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.4.1.Final</version>
</dependency>

We will be using Spring Boot for this post, so we will be using Spring Boot starters for add validation API in our class path. To use Hibernate validation API in your Spring Boot application, you need to add the following starter in your pom.xml file


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
As we know, you do not need to specify the version when using Spring Boot as it will be handled automatically by Spring Boot.

2. Custom Class Level Validation

To understand it, let’s take a simple example where we want to create a custom validator to validate two fields in our input form to make sure they are equal. (let’s assume we want to confirm customer email address)

2.1 Annotation

We will start by creating a new @interface to define our new custom constraint.

@Constraint(validatedBy = FieldMatchValidator.class)
@Documented
@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
public @interface FieldMatch {
    String message() default "Fields are not matching";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    /**
     * @return The first field
     */
    String first();

    /**
     * @return The second field
     */
    String second();

    /**
     * Defines several <code>@FieldMatch</code> annotations on the same element
     *
     * @see FieldMatch
     */
    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Documented
    @interface List {
        FieldMatch[] value();
    }
}

With @Constraint annotation, we are specifying which class will actually be performing validation, in our case FieldMatchValidator class will be doing the actual validation, message() will define the message which will be shown to the customer when validation fails, this is the default message and it can be changed through configuration (we will see that shortly).

 

2.2 Validation Class

Let’s have a look at the actual validation class which will be responsible for performing our custom validation.

public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> {


    private String firstFieldName;
    private String secondFieldName;

    public void initialize(final FieldMatch constraintAnnotation) {
        this.firstFieldName = constraintAnnotation.first();
        this.secondFieldName = constraintAnnotation.second();
    }

    public boolean isValid(final Object value, final ConstraintValidatorContext context) {
        try {
            final Object firstObj = PropertyUtils.getProperty(value, this.firstFieldName);
            final Object secondObj = PropertyUtils.getProperty(value, this.secondFieldName);
            return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
        } catch (final Exception ex) {
            //LOG.info("Error while getting values from object", ex);
            return false;
        }

    }
}

Our Validation class implements ConstraintValidator interface and should implement isValid method, all our validation logic will go inside this method.In our custom validation, we are fetching values from the both fields and matching them to return a boolean value.

 

3. Validation in Action

It’s time to see our custom validation in action, to demonstrate it, we will be using a simple Spring Boot based web application where we will be validating 2 fields and will throw an error in case both fields do not match with each other.

3.1 Sample Controller
@Controller
public class CustomValidatorController {

    @RequestMapping("/custom-validator")
    public String hello(Person person) {
        return "customValidator";
    }

    @PostMapping("/custom-validator")
    public String demoValidation(@Valid Person person, BindingResult bindingResult) {

        if (bindingResult.hasErrors()) {

            return "customValidator";
        }

        return "redirect:/results";
    }

    @RequestMapping("/success")
    public String welcome() {
        return "welcome";
    }
}
3.2 Person Object
@FieldMatch(first = "email", second = "confirmEmail", message = "Email does not match")
public class Person {

    @NotNull
    private String name;
    private String email;
    private String confirmEmail;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getConfirmEmail() {
        return confirmEmail;
    }

    public void setConfirmEmail(String confirmEmail) {
        this.confirmEmail = confirmEmail;
    }
}

As you can see, we have added @FieldMatch annotation on the top of our Person class which will compare email and confirmEmail fields and in case they don’t match, it will throw a validation error.

3.3 View
<html>
<body>
<form action="#" th:action="@{/custom-validator}" th:object="${person}" method="post">
    <table>
        <p th:if="${#fields.hasErrors('global')}" th:errors="*{global}">
            Incorrect date
        </p>
        <tr>
            <td>Name:</td>
            <td><input type="text" th:field="*{name}" /></td>
            <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name Error</td>
        </tr>
        <tr>
            <td>Email:</td>
            <td><input type="text" th:field="*{email}" /></td>
            <td th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Email Error</td>
        </tr>
        <tr>
            <td>Confirm Email:</td>
            <td><input type="text" th:field="*{confirmEmail}" /></td>
            <td th:if="${#fields.hasErrors('confirmEmail')}" th:errors="*{confirmEmail}">Email Error</td>
        </tr>
        <tr>
            <td><button type="submit">Submit</button></td>
        </tr>
    </table>
</form>
</body>
</html>

If we run our application and add non-matching email id’s, we will get “Email does not match” error on the front end.

Spring MVC Custom Validator

We can also define custom validation on the field level. We need to use the same approach to define field level annotation.

4. Custom Field Level Validation

We can also define custom validation on the field level. We need to use the similar approach to define field level annotation.

4.1 Annotation
@Constraint(validatedBy = CountryMatchValidator.class)
@Documented
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RUNTIME)
public @interface CountryMatch {
    String message() default "Invalid Country";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    /**
     * Defines several <code>@FieldMatch</code> annotations on the same element
     *
     * @see FieldMatch
     */
    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Documented
    @interface List {
        FieldMatch[] value();
    }
}

4.2 Validation Class
public class CountryMatchValidator implements ConstraintValidator<CountryMatch, String> {


    /**
     * Initializes the validator in preparation for
     * {@link #isValid(Object, ConstraintValidatorContext)} calls.
     * The constraint annotation for a given constraint declaration
     * is passed.
     * <p/>
     * This method is guaranteed to be called before any use of this instance for
     * validation.
     *
     * @param constraintAnnotation annotation instance for a given constraint declaration
     */
    @Override
    public void initialize(CountryMatch constraintAnnotation) {

    }

    /**
     * Implements the validation logic.
     * The state of {@code value} must not be altered.
     * <p/>
     * This method can be accessed concurrently, thread-safety must be ensured
     * by the implementation.
     *
     * @param country  country
     * @param context context in which the constraint is evaluated
     * @return {@code false} if {@code value} does not pass the constraint
     */
    @Override
    public boolean isValid(String country, ConstraintValidatorContext context) {
        try {
            return country == null && country.equals("US");
        } catch (final Exception ex) {
            //LOG.info("Error while getting values from object", ex);
            return false;
        }
    }
}
4.3 Person Object
@FieldMatch(first = "email", second = "confirmEmail", message = "Email does not match")
public class Person {

    @NotNull
    private String name;
    private String email;
    private String confirmEmail;

    @CountryMatch(message = "Country should be US")
    private String country;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getConfirmEmail() {
        return confirmEmail;
    }

    public void setConfirmEmail(String confirmEmail) {
        this.confirmEmail = confirmEmail;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}

In order to initiate Spring MVC JSR validation, you need to annotate your model with @Valid annotation in your controller

5. Summary

In this post, we learn about using Spring MVC Custom Validator. We covered how to create and use class and field level validation.

 

All the code of this article is available Over on Github. This is a Maven-based project.

Split a String in Java

Split a String in Java

In this small post, we will explore how to split a string in Java.

 

Introduction

Splitting a String in Java is a very common operation, we will discuss different method available in Java to split a String.

 

1. String#split() Method

Java String class provide a convenient and easy split() method to split String a String.The split method comes in 2 flavours and takes a regular expression as an input. Split method is powerful and mostly sufficient for most use cases.

public void split(){
    String input = "This-is-a-sample-input";
    String[] parts= input.split("-");
    for(int i =0; i< parts.length;i++){
        System.out.println(parts[i]);
    }
}

If you want to limit the number of resulting parts, you can pass the second argument (limit) to the split method.The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. Here is an another variation of the above example

public void splitWithLimit(){
    String input = "This-is-a-sample-input";
    String[] parts= input.split("-", 2);
    for(int i =0; i< parts.length;i++){
        System.out.println(parts[i]);
    }
}

If you run above example, output will be

This
is-a-sample-input

Please note that split() method takes a regular expression as an input and we need to escape special character if needed (Please check different special character available in regular expression ). We can use \ to escape special characters or Pattern.quote() for it.

 

2. Split String Using Java 8

With Java 8, we can use Stream and Collector to split String. Here is a simple code to split a string in Java 8

public void splitStringJava8(){
    String input = "This-is-a-sample-input";
    List<String> parts = Pattern.compile("-")
                         .splitAsStream(input)
                         .collect(Collectors.toList());
    parts.forEach(s-> System.out.println(s));
}

 

3. Split String Apache Utils

Apache StringUtils provide null safe methods to split a string, here is a sample code for the same

public void apacheStringUtils(){
    String input = "This-is-a-sample-input";
    String[] parts =StringUtils.split(input ,"-");
    for(int i =0; i< parts.length;i++){
        System.out.println(parts[i]);
    }
}

In case you are not passing any delimiter to above method, whitespace will be taken as a default delimiter by it.

 

Conclusion

In this post, we saw different methods to split a string in Java including methods available in Apache’s StringUtils class. I believe that for most of the case split() method provided by the String class will serve our purpose.

 

All the code of this article is available Over on Github. This is a Maven-based project.

Iterate through a Map in Java

How to iterate through a Map in Java

In this articles, we will explore the different ways to Iterate through a Map in Java. We will start with a simple use case and will explore how we can do this using Java 8 Stream API.

 

Introduction

Iterating through Java Map is very common tasks and we face this tasks daily basis. Java Map API provides keySet(), valueSet() or entrySet() option to fetch content/data from the Map.

The Map.entrySet method returns a collection-view of the map, whose elements are of this class. The only way to obtain a reference to a map entry is from the iterator of this collection view. These Map.Entry objects are valid only for the duration of the iteration.

Entry.getKey() returns the key corresponding to this entry. Let’s explore different options to Iterate through a Map in Java.

 

Example

To start working on the different options, let take a simple Map contains few values. Here is code for the simple Map.

Map<String, String> sampleMap= new HashMap<String,String>();

sampleMap.put("one", "one");
sampleMap.put("two", "two");
sampleMap.put("three", "three");
sampleMap.put("four", "four");
sampleMap.put("five", "five");
sampleMap.put("six", "six");

1.  EntrySet with for Loop 

public void iterateForEach(Map<String, String> sampleMap){
    for(Map.Entry<String,String> mapValue : sampleMap.entrySet()){
        System.out.println(mapValue.getKey()+" :" + mapValue.getValue());
    }
}

In above code, we have we converted Map to entry set and then we iterated through the entries using for each loop.

2.  EntrySet with for Loop 

If you don’t want to use For Each loop, we can convert entrySet() to the iterator and use an iterator to loop through the map content.

public void iterator(Map<String, String> map){
    Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
    while(iterator.hasNext()){
        Map.Entry<String, String> entry = iterator.next();
        System.out.println(entry.getKey()+" :" + entry.getValue());
    }
}

I will not prefer this approach and will go with for each loop.

3.  For Each with Java 8 Lambdas

The introduction of Lambdas in Java 8 provides a more concise and easy to read solution.

public void lambdas(Map<String, String> map){
    map.forEach((key,value) ->System.out.println(key + ":"+ value));
}

One of the interesting thing with above approach is that we don’t need to convert the map to entry set for iteration.

4.  Java 8 Stream API

Stream was introduced in Java 8 as one of the main features, we can use Stream API to iterate through the map.

public void stream(Map<String, String> map){
    map.entrySet().stream().forEach(entry-> System.out.println(entry.getKey() +": "+entry.getValue()));
}

I will not use this since we are converting Map to entry set and iterating through the element which is more or less equivalent to for each loop.

If you want you can use Java 8 Stream API parallel method but I will not cover that in this post.

5.  Performance

For small map size (<=100), Java 8 based for each loop have the best performance. In the case of Map size is greater than 10000 elements, simple for each loop seems to be faster than other approaches.Please execute your own benchmarking before taking a call for your implementation.

6.  Conclusion

In this short post, we covered some of the methods to Iterate through a Map in Java along with few options provided by Java 8. 

All the code of this article is available Over on Github. This is a Maven-based project.

Java Weekly Newsletter Issue 5

Java Weekly Newsletter Issue 5

Hello and welcome to the  Java Weekly Newsletter Issue 5

 

1.  Blog Posts

In case you have missed any of my posts, here is the list of articles we published this week.

  1. FailureAnalyzer in Spring Boot
  2. Java Base64 Encoding and Decoding

 

2. Spring & Java Community

  1. Why serverless? Meet AWS Lambda
  2. Using String.join to Concatenate Strings
  3. Spring Boot – JMSTemplate with Embedded ActiveMQ
  4. 5 Step Recipe: Everything You Need to Know for Staying Up-to-Date in Java
  5. Kotlin and Java: Where Do They Fit In?
  6. Avoiding Benchmarking Pitfalls on the JVM
  7. Memory Puzzle with Lambdas

 

3. JPA / Persistence

I do not work very closely in JPA or Hibernate but following few of the blogs for some of the interesting insight into Persistence 

  1. 5 Things You Need to Know When Using Hibernate with Mysql

4. Spring and Java Releases

  1. Spring Tool Suite 3.9.0 released
  2. Spring for Apache Hadoop 2.5.0 GA released
  3. Servlet 4.0 Specification Proposed Final Draft

 

5. Presentations and Videos

  1. Ben Evans on Java 9
  2. A Few Hidden Treasures in Java 8
  3. Shopizer Setup

 

We will be back with our next weekly newsletter with some more insight details about Java and Spring community.

Happy Coding !!!!

 

If you haven’t Signup to our weekly newsletter, Signup Now

FailureAnalyzer in Spring Boot

FailureAnalyzer in Spring Boot

In this post, we will be exploring  FailureAnalyzer in Spring Boot. We will also learn to Create a Custom FailureAnalyzer in Spring Boot.

 

Introduction

Most of the time when we encounter an exception at the server startup time, we need to read it very closely to understand what went wrong before we try to fix it.

Through FailureAnalyzer, Spring Boot provides a great way to intercept exception at the startup and will turn them in more human readable format (We don’t have to scroll through the entire stack trace). Spring Boot comes with a number of  FailureAnalyzer starting from application context related exceptions, JSR-303 validations and more.

Here is an example where port 8080 was already in use and when we tried to run our Spring Boot application on port 8080, PortInUseFailureAnalyzer intercepted this exception and provided a more readable and user-friendly error message.

***************************
APPLICATION FAILED TO START
***************************
Description:
Embedded servlet container failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

Here is a list of the few FailureAnalyzer provided by Spring Boot

  1. PortInUseFailureAnalyzer
  2. NoUniqueBeanDefinitionFailureAnalyzer
  3. BeanCurrentlyInCreationFailureAnalyzer

You can find a complete list of FailureAnalyzer by checking org.springframework.boot.diagnostics package under Spring Boot. 

Spring Boot provides an easy way to create our own custom FailureAnalyzer.

 

1. Creating Custom FailureAnalyzer

To create our own custom FailureAnalyzer, we can use AbstractFailureAnalyzer as our convenient extension point.AbstractFailureAnalyzer will check if a specified exception is present and will allow our custom analyzer to handle it.

Let’s create a custom FailureAnalyzer in Spring Boot for the following use case

  1. We will try to inject a different bean for a given dependencies.
  2. When we will try to inject it, Spring will throw BeanNotOfRequiredTypeException since we are trying to inject a different bean.

Here is our sample FailureAnalyzer code

public class CustomFailureAnalyzer extends AbstractFailureAnalyzer<BeanNotOfRequiredTypeException> {

    /**
     * Returns an analysis of the given {@code failure}, or {@code null} if no analysis
     * was possible.
     *
     * @param rootFailure the root failure passed to the analyzer
     * @param cause       the actual found cause
     * @return the analysis or {@code null}
     */
    @Override
    protected FailureAnalysis analyze(Throwable rootFailure, BeanNotOfRequiredTypeException cause) {
        String message ="####################### This is a custom fail Message ################ %n"+
                getDescription(cause);
        return new FailureAnalysis(message , (String)null, cause);
    }

    private String getDescription(BeanNotOfRequiredTypeException ex) {

        StringWriter description = new StringWriter();
        PrintWriter printer = new PrintWriter(description);
        printer.printf(
                "The bean %s could not be injected"
                        + "due to %s",
                ex.getBeanName(), ex.getRequiredType().getName());
        return description.toString();
    }
}

The main point is the analyze() method which will get triggered and Spring Boot will pass on a Throwable object along with the case (Exception which was thrown by Spring for our case).  We can get detail information from the cause instance to print a user-friendly message.

 

2. Registering Custom FailureAnalyzer

We need a special way to register our custom FailureAnalyzer with Spring Boot so as Spring Boot should be able to call our custom FailureAnalyzer in case exception is thrown by the system. We need to register it using spring.factories property file in META-INF folder.

In case META-INF or spring.factories properties file is not present, we need to create it manually. To register custom FailureAnalyzer, add following entry in spring.factories

org.springframework.boot.diagnostics.FailureAnalyzer=\
  com.umeshawasthi.failureanalyzer.CustomFailureAnalyzer

if you have multipleFailureAnalyzer You can register all of those in as a comma separated entries

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.umeshawasthi.failureanalyzer.CustomFailureAnalyzer,\ com.umeshawasthi.failureanalyzer.CustomFailureAnalyzer1

At this point, we are all set with our CustomFailureAnalyzer and ready to test it.

 

3. FailureAnalyzer in Action

I have created 2 classes in my demo project with the following signature

public class AdminDAO {

    public void helloAdmin(){
        System.out.println("Hello Admin");
    }
}
@Repository("adminDAO")
public class AdminDAOImpl {

    public void setupAdmin(){
        //default implimentation
    }
}

I have created another Controller where I am trying to inject “adminDAO” bean to AdminDAO.

@RestController
public class HelloWorldController {
   @Resource(name = "adminDAO")
   private AdminDAO adminDAO;
   //some methods
}

If I run my Spring Boot Application, Spring will try to inject adminDao of type AdminDAOImpl in AdminDAO, since these are not compatible, Spring will throw BeanNotOfRequiredTypeException. In the current use case, Spring Boot will check to determine a valid FailureAnalyzer is registered and will pass on information to registered FailureAnalyzer.

In our case, we have registered CustomFailureAnalyzer to handle such case, Spring Boot will pass on this information to our custom FailureAnalyzer to produce a more user-friendly message.

Here is the output when we will run our application
***************************
APPLICATION FAILED TO START
***************************
Description:
################# This is a custom fail Message ################ %nThe bean adminDAO could not be injecteddue to com.umeshawasthi.service.AdminDAO

Summary

In this article, we explored an interesting feature provided by Spring Boot. We saw how Spring Boot FailureAnalyzer work and how to create our own custom FailureAnalyzer.

All the code of this article is available Over on Github. This is a Maven-based project.

Java NIO2 File Attributes

Introduction to Java NIO2 File Attributes API

In this post, we will cover Java NIo2 File Attributes. File attributes are also known as metadata. Metadata can be used to find out information about the file systems like if it’s a regular file or a directory, who is the owner of the file or directory.

I have already covered Java NIO2Java NIO Path and Java NIO Selector as part of the new NIO features introduced in Java 7. 

 

Introduction

File metadata can be used to get information about the file ranging from the size of the file to the access permissions. These File Attributes can be used to check critical information before moving ahead with real file-based operations. 

I will be covering different metadata attributes in this post.

 

1.   Basic File Attributes

To get information about all the basic attributes of the file, we can use Files.readAttribute() method. This method will return BasicFileAttributes which can be used to access various basic file attributes.This approach is more efficient as we are not required to make a separate call to the underlying file system to read individual attributes.

We will get BasicFileAttributes for a given path and then check what all information we can get from this

Path path = Paths.get("/Users/umesh/personal/tutorials/source");
BasicFileAttributeView fileAttributeView = Files.getFileAttributeView(path, BasicFileAttributeView.class);
BasicFileAttributes basicFileAttributes = fileAttributeView.readAttributes();

We first retrieved BasicFileAttributeView and retrieved.BasicFileAttributes from it.We went this route since BasicFileAttributeView contains set of file attributes consist of mandatory and optional file attributes as defined by the BasicFileAttributes interface.

Once we have BasicFileAttribute, we can get all basic file attribute information from it.

1.1   Check Creation Time

To find creation time of the file, use creationTime() method

basicFileAttributes.creationTime()

 

1.2  Last Access Time

basicFileAttributes.lastAccessTime()

 

1.3  Check for Directory

We can also check if a given path is a file or directory 

basicFileAttributes.isDirectory()

 

1.4  Basic Attribute Example

Here is complete example demonstrating various methods available to get basic file information.

Path path = Paths.get("/Users/umesh/personal/tutorials/source");
BasicFileAttributeView fileAttributeView = Files.getFileAttributeView(path, BasicFileAttributeView.class);
BasicFileAttributes basicFileAttributes = fileAttributeView.readAttributes();

System.out.println("creationTime: " + basicFileAttributes.creationTime());
System.out.println("lastAccessTime: " + basicFileAttributes.lastAccessTime());
System.out.println("lastModifiedTime: " + basicFileAttributes.lastModifiedTime());

System.out.println("isDirectory: " + basicFileAttributes.isDirectory());
System.out.println("isOther: " + basicFileAttributes.isOther());
System.out.println("isRegularFile: " + basicFileAttributes.isRegularFile());
System.out.println("isSymbolicLink: " + basicFileAttributes.isSymbolicLink());
System.out.println("size: " + basicFileAttributes.size());

All method related to getting time returns FileTime object which is different than simple TimeStamp 

2.  File Owner Information

In order to get high-level file ownership information, We can use FileOwnerAttributeView provided by Java NIO2 API.

FileOwnerAttributeView fileOwner=Files.getFileAttributeView(path, FileOwnerAttributeView.class);
System.out.println("File Owner Name " +fileOwner.getOwner());

You can get information about the POSIX or DOS file attributes by passing DosFileAttributes.class or PosixFileAttributes.class to Files.getFileAttributeView() method.

 

3. File Store Attributes

Java NIO2 API provides a convenient FileStore class to get information about the file. We can use this class to get information about the underlying file system like how much space is available, how much used etc. 

FileStore store = Files.getFileStore(path);

long total = store.getTotalSpace() / 1024;
long used = (store.getTotalSpace() - store.getUnallocatedSpace()) /1024;
long available = store.getUsableSpace() /1024;

Summary

In this post, we covered basics as how to get information about the basic file attributes using Java 7 NIO2 File Attributes.

 

All the code of this article is available Over on Github. This is a Maven-based project.