Java 9 New Features

 Java 9 New Features

In this articles, we will be covering Java 9 new features at a high level.We will explore these features along with details as what are the improvements happening to the existing features.

 

Introduction

Java 8 introduced a couple of new and exciting features like lambdas, streams and some of the API changes, Java 9 is coming up with rich feature sets like Jigsaw, Jshell (REPL),  collections and some API changes under the hood.In this, we will explore all Java 9 new features at a high level.You can get detail information of all Java 9 features available JDK 9.

 

1. Modular System – Jigsaw Project 

The modular system is one of the main and defining features of the Java 9.Jigsaw will be responsible for bringing much-needed modularity to the Java platform.One of the main reason to bring modularity to the Java provides modular JVM which can help us to run JVM on different devices with less memory. 

In another way, it’s a mechanism to run only modules and API required by a given application (e.g.application 1 need 3 modules to run completely while application 2 need only 1 module). 

Modules will be defined/ described in a file called module-info.java located at the top of our Java code hierarchy.

In order to understand Java 9 Modular system, let’s take an example of the Order placement process where we need OMS (Order Management System) to place an order but for rest of the use cases (e.g. Browsing site or adding products to the shopping cart), we might not need OMS for our application. We can have a web-based application which allows placing an order, however, we can have other channels which can place an order and we need OMS module to process these orders correctly. To achieve this, we can define 2 modules in Java 9 and can define required dependencies

module com.javadevjournal.shop.order {
requires com.javadevjournal.erp.oms;
}

Here is a pictorial representation of the Java 9 Module system

Java 9 New Features
Java 9 Modules

Based on the requires statement, JVM will try to determine if it is able to resolve all modules. I strongly believe that Java 9 Modules feature will allow us to structure our application in a better way and will strongly enforce encapsulation and defined/ explicit dependencies.

 

2. JShell (REPL)

Many modern languages provide a tool (Mostly called as REPL or scripting tool) for real-time statement interpretation.One of the benefits of such tool is that you can easily test your code without creating a complete class or project.Java 9 will be introducing REPL or JShell which can be used to quickly run your code and compare results. 

For more details and video tutorial, please read Introduction to Java 9 REPL and JShell

 

3. G1 (Default Garbage Collector)

Java 8 has 4 different Garbage Collector and default Garbage Collector in Java 8 is Parallel / Throughput Collector. G1 will be the new default Garbage Collector in Java 9. G1 was designed for better performance and know to have less number of GC pauses. 

Get more insight of the all available Garbage Collectors and their feature in our other post Java Garbage Collector.

 

 

4. HTTP 2.0 Client

Java 9 is coming up with a new HTTP 2.0 based client which can also be taken as a replacement for the famous.HttpURLConnection Java 9 will be providing full support for new HTTP 2.0 and this new client will be supporting both HTTP/2 protocol and WebSocket.

This new API will be introduced as first incubator module in Java which means it will be introduced as an experimental feature and based on the feedback it will either be added as a full featured module in next release or will be removed from the Java platform.

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("www.travellingrants.com")).build();
HttpResponse<String> response = client.send(request,HttpResponse.BodyHandler.asString());
System.out.println(response.statusCode());
System.out.println(response.body());

It’s really easy and clean API, we no longer have to use InputStream or Reader and even our old friend.HttpURLConnection

HTTP 2.0 API also support an Asynchronous call by simply using HttpClient#sendAsync() method instead of HttpClient#send method.There is also option to cancel your request if server support HTTP/2.

 

5. StackWalker API

To put Stack Walk API  in Java 9 in simple words, It provides capabilities to walk through the stack in Java. StackWalker provides a snapshot of the current thread stack trace along with some methods to access it.

Please read our article StackWalker API In Java 9 to get more insight for this new Java 9 feature.

 

6. Process API

Before Java 9 there was a limited support for controlling and managing operating systems processes, even getting hold of simpler OS related process was not a simple one liner solution and require a lot of workarounds.

Java 9 is introducing a lot of improvements to process API for controlling and managing OS related process.

java.lang.ProcessHandle class contains most of the new features of the process API. To get an understanding let’s take an example of getting PID in both Java 8 and Java 9

Java 8
public static void getProcessIdByJava8(){
try {
String[] args = new String[] { "/bin/sh", "-c", "echo $PPID" };
Process p = Runtime.getRuntime().exec(args);
InputStream p_out = p.getInputStream();
String s = (new BufferedReader(new InputStreamReader(p_out))).readLine();
p.destroy();
if (s != null)
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
}
}
Java 9
public static void getProcessIdByJava9(){
System.out.println("Your Process id is :" + ProcessHandle.current().pid());
}

As we saw, getting operating system information using Java 9 process API is quite easy and clean.It gives Java developer an API to interact with the operating system and can be used to get information on the status of the JVM.

We can get a lot of other information from the process API. Read here for more details.

 

7.  Collection Factory Methods

Collection Factory Methods are introduced in Java 9 like Scala. Static methods have been provided by Java 9 on List, Set and Map interfaces which can easily returned unmodifiable collections by calling of() method of the respective interface.

For more detail, please read Collection Factory Methods in Java 9

 

8. Try With Resources Improvement

Java 7 introduced try-with-resources for managing resources automatically and to ensure that resources will be closed after execution of the program.

Before Java 9, in order to use try-with-resources, we will have to use something like this

try (BufferedReader br = new BufferedReader(new FileReader("/input.txt"))) {
String line;
while (null != (line = br.readLine())) {
// processing each line of file
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}

Or we will be using a very similar syntax, Above syntax provide a lot of features and auto management of the resources, however, we still need to declare a local variable to work with, Java 9 is a further refinement to this feature to avoid verbosity.

 

BufferedReader br = new BufferedReader(new FileReader("/input.txt"));
// Java 9 make it simple
try (br) {
String line;
while (null != (line = br.readLine())) {
// processing each line of file
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}

 

9. Interface Private Method

Java 8 came with certain enhancement while declaring interfaces, few of those features are

  1. Method implementation in interface using default and static methods

However, it still not provide a way to create a private method in Interface. Java 9 will provide a way to have a private method in an interface.This feature will really be useful to avoid redundant code and promote code reusability.

public interface PrivateMethodExample {
private static String getDBDetails(){
return "MySQL";
}
private boolean checkConnection(String DBDetails){
return  DBDetails.equalsIgnoreCase("MySQL") ? true : false;
}
default void checkDBConnection(){
String dbName = getDBDetails();
boolean isAlive =   checkConnection(dbName);  
}
}

 

10. Мulti-Resolution Image API

Java 9 will be introducing a new API defined under java.awt.image package, it will allow a set of images with different resolutions to be encapsulated into a single multi-resolution image.

For more details read Multi-Resolution Images.

 

 

11. Miscellaneous Java 9 Features

There are other features introduced in Java 9 which I will be covering in another post in more details, here is the list of some of the other features introduced in Java 9

  1. Improvement to Optional API. Read java 8 optional to get a basic understanding of Optional API introduced in Java 8.
  2. Unified JVM Logging.
  3. Stream API Improvement.
  4. Reactive Streams
  5. CompletableFuture API Improvements
  6. Improved Javadoc

 

Summary

In this post, we covered  Java 9 new features. Java 9 is coming up with modular JVM which is going to be one of the defining features of Java 9 along with a number of improvements in the JDK.

Spring Events

Introduction to Spring Events

In this post, we will be covering Spring Events which is a way to loosely couple component in your application for better design and easy exchange of information.

 

1. Introduction

Spring Events are part of the Spring Framework for the very easy phase of the framework, however, I believe that this is one of the most overlooked features of the Spring Framework. Spring Events provide a lot of features and capabilities and one of the most interesting among those are event publishing provided by ApplicationContext.

Application events are not used that frequently in the real world application, however, Spring Framework internally use a lot of these events to communicate various events, with the introduction of the Spring Boot, it has become more interesting.

Spring 4.1 introduced @EventListener,  annotation driven event Listener which removed all the complexities of defining your EventListner.@EventListener is a core annotation that is handled transparently in a similar fashion as @Autowired and others: no extra configuration is necessary with java config

 

2. Custom Events

To understand it more clearly, we will create and publish a custom Spring Event. Spring provides flexibility to create and publish custom events which by default will be synchronous.

We will work on a  simple example of customer registration, we will publish a simple CustomerRegistration event whenever a new customer registers with our application. We will let all listeners handle this event and perform applicable action (e.g sending email on customer registrations)

2.1 Custom Events

In this example, we will create simple CustomerRegistrationEvent which will be used to store customer data (in our case just customer name)

public class CustomerRegistrationEvent {
private String name;
public CustomerRegistrationEvent(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

Before Spring 4.2, we were required to extend ApplicationEvent which is no longer required, this change has its own merits as it is much easier to publish events while it can be hard to trek events in large applications.

 

2.2 Custom Events Listener

As part of our example, we need a listener which should listen to the event being published and make sure to act accordingly in case event published by the service is of interest (if given listener is registered for the given event) 

 

@Component
public class CustomerRegistrationEventListener {
@EventListener
void handleRegistration(CustomerRegistrationEvent event){
System.out.println("Registration event got triggered for customer::  " + event.getName());
}
}

 

With Spring 4.2, you are not required to implement ApplicationListener or something similar but a simple @EventListener annotation is sufficient to declare it as a Listener.

Spring will create an ApplicationListener instance for the event with a type taken from the method argument. There is no limitation on the number of annotated methods in one class – all related event handlers can be grouped into one class.

 

2.3 Publishing Events

We will create a publisher which will be responsible for the following tasks

  1. It will create an event object.
  2. It will publish that event to all who are listening to this event.

We need ApplicationEventPublisher in our code to simply publish given event.

@Autowired
private ApplicationEventPublisher publisher;
public void publishEvent(final String name) {
publisher.publishEvent(new CustomerRegistrationEvent(name));
}

 

3. Async Events

As mentioned earlier, these events work in Async mode, which means publisher thread will block until all the listeners (who are listing to this event) have finished processing this event.This can lead to a certain issue in terms of application scaling where we want to run these events in Async mode and let rest of the application to work normally.

To allow Spring to handle events asynchronously, we need to redefine ApplicationEventMulticaster with an executor.

@Bean(name = "applicationEventMulticaster")
ApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();
eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
eventMulticaster.setErrorHandler(TaskUtils.LOG_AND_SUPPRESS_ERROR_HANDLER);
return eventMulticaster;
}

This will enable asynchronously mode at the global level (at the ApplicationContext level), this means that all method annotated with @EventListener will be executed asynchronously.

Another most easier way is to use @Async annotation

@Async
@EventListener
void handleRegistration(CustomerRegistrationEvent event){
System.out.println("Registration event got triggered for customer::  " + event.getName());
}

We need to make to enable asynchronous method execution by enabling @EnableAsync

 

4. Filtering

We can also use condition attribute on our listener to filter certain events.Let’s say we want to listen to only CustomerRegistration event if this is a B2B customer.

 

@EventListener(condition = "#event.customerType=B2C")
void handleRegistration(CustomerRegistrationEvent event){
System.out.println("Registration event got triggered for customer::  " + event.getName());
}

 

5. Transaction bound events

Spring provides a way to bound events to a certain phase of a transaction (e.g. publish an event when a transaction is complete). We can use @TransactionalEventListener annotation to achieve this behavior. When @TransactionalEventListener is present, Spring will automatically register this in place of default one.

To put it in simple words, this Listener will only invoke if there is a transaction running, in case of no running transaction, this will not be invoked at all.

 

Summary

In this post, we got an introduction to Spring Events.We learned how we can create custom events and how to use publish Spring events synchronously and asynchronously.We briefly covered as to how to use condition to filter events and transaction capabilities of the Spring Framework event system.

Convert a Map to Set in Java

Convert a Map to Set in Java

In this post, we will learn as how to Convert a Map to Set in Java.We will see how to do this using JDK.

 

1. Conventional Method

To convert, Java Map to Set, we can use the conventional constructor with HashSet, however, there are few things to consider before we proceed with the conversion. 

 Java Map has 2 values while Set contains only single value while converting Map to Set, we need to take a call of converting either map values or keys, so either we will get a set of keys or set of values (we can get both by using some wrapper to have both values).

public class MapToSet {
public static void main(String[] args) {
Map<Integer,String> map= getMap();
//Convert Map keys to Set
Set<Integer> keySet= new HashSet<Integer>(map.keySet());
keySet.forEach(key-> System.out.println(key));
//Convert Map values to Set
Set<String> valueSet= new HashSet<String>(map.values());
valueSet.forEach(value-> System.out.println(value));
}
static Map<Integer,String> getMap(){
Map<Integer, String> sampleMap=new HashMap<Integer,String>();
sampleMap.put(1,"Sunday");
sampleMap.put(2,"Monday");
sampleMap.put(3,"Tuesday");
sampleMap.put(4,"Wednesday");
return sampleMap;
}
}

Output for the above programme will be

1
2
3
4

For valueMap

Sunday
Monday
Tuesday
Wednesday

2. Using Java 8

We can also use Java 8 Stream API to convert Map to Set in Java.

public class MapToSetJava8 {
public static void main(String[] args) {
Map<Integer,String> map= getMap();
Set keySet=map.keySet().stream().collect(Collectors.toSet());
keySet.forEach(key-> System.out.println(key));
Set valueSet=map.values().stream().collect(Collectors.toSet());
valueSet.forEach(value-> System.out.println(value));
}
static Map<Integer,String> getMap(){
Map<Integer, String> sampleMap=new HashMap<Integer,String>();
sampleMap.put(1,"Sunday");
sampleMap.put(2,"Monday");
sampleMap.put(3,"Tuesday");
sampleMap.put(4,"Wednesday");
return sampleMap;
}
}

My preference will be for the constructor based approach as it is more straight forward and easy to read rather than the Java 8 Stream API.

3. Summary

In this post, we explored as to how to convert a Map to Set in Java, we learned how to convert it using a constructor and Java 8 Stream API.Please read  … to see how to convert Map to List in Java

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

Spring Boot Web Application Configuration

Spring Boot Web Application Configuration

In this short post, we will cover some of the interesting aspects of the Spring Boot web application configuration.We will be covering some of the most commonly used configurations for a web application.

 

1. Introduction

Spring Boot comes with build in intelligence which makes it easy to create the web or standalone application.Spring Boot can do a lot of things for us without even writing a single line of code for our web application and we will be covering few of those configurations.

 

2. HTTP Port

One of the common configuration for a web application is the HTTP port number, we can easily configure HTTP port number for our application using following options

  • Using application.properties file
  • By YAML based configuration
  • Setting HTTP port number programmatically.

 

2.1 Setting HTTP Port by Configuration

For properties file

server.port=9001

For YAML

server:
        port: 8083

 

2.2 Setting HTTP Port by Programmatically

We can also set HTTP port programmatically in Spring Boot

@Component
public class CustomConfiguration implements EmbeddedServletContainerCustomizer {
/**
* Customize the specified {@link ConfigurableEmbeddedServletContainer}.
*
* @param container the container to customize
*/
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(9001);
}
}

 

3. Context Path

Default context for a Spring Boot web application is "/", Spring Boot provides the option to set context either through configuration or programmatically.

 

3.1 Setting Context by Configuration

For properties file

server.contextPath=/javadevjournal

For YAML

server:
        contextPath:/javadevjournal

 

3.2 Setting Context by Programmatically

We can also set context programmatically in Spring Boot

@Component
public class CustomConfiguration implements EmbeddedServletContainerCustomizer {
/**
* Customize the specified {@link ConfigurableEmbeddedServletContainer}.
*
* @param container the container to customize
*/
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(9001);
container.setContextPath("/javadevjournal");
}
}

 

4. BasicErrorController

If you are working with Spring Boot application, you should be familiar with While Label Error Page. Spring Boot automatically register BasciErrorController bean if we do not specify our own custom bean.We can customize this by extending ErrorController.

@Controller
public class CustomErrorController implements ErrorController {
private static final String PATH = "/error";
@RequestMapping(value = PATH)
public String error() {
return "errorHandling";
}
/**
* Returns the path of the error page.
*
* @return the error path
*/
@Override
public String getErrorPath() {
return PATH;
}
}

5. Custom Error Pages

Spring Boot provides a way to use your own custom error pages based on the error code. We need to add error code based pages under the /error directory and Spring Boot will use correct page based on the error code.

We can use either static HTML or can use a template to build our custom error pages. The name of the file should be the exact status code or a series mask.

We can use a similar structure to organize our templates.

src/
 +- main/
          +- java/
          |      + <source code>
          +- resources/
                  +- public/
                          +- error/
                           |     +- 404.html
                           +- <other public assets>

 

src/
 +- main/
          +- java/
          |      + <source code>
          +- resources/
                  +- public/
                          +- error/
                           |     +- 5xx.html
                           +- <other public assets>

 

6. Configure Logging

Spring Boot has no required dependencies for the logging (except common logging API). Spring Boot internally use LoggingSystem abstraction that attempts to configure logging based on the content of the classpath.

We can fine tune log out in Spring Boot application by setting log level in the application.properties file using logging.level as a predefined prefix

logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

 

We can use different logging framework (Logback, Log4j2) in Spring Boot application.

 

Summary

In this post, we covered  Spring Boot Web Application Configuration which is required for setting up your web application correctly or as per your need.For more details, you can always refer to Spring Boot documentation.

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.