Spring Interview Questions

General Questions – Spring Interview Questions

1. What are the major features in different versions of Spring Framework?

Features of Spring Framework

Version Logo Feature
Spring 2.5 spring 2.5 logo - Spring Interview Questions - Edureka! This version was released in 2007. It was the first version which supported annotations.
Spring 3.0 spring 3.0 logo - Spring Interview Questions - Edureka! This version was released in 2009. It made full-fledged use of improvements in Java5 and also provided support to JEE6.
Spring 4.0 Spring 4.0 logo - Spring Interview Questions - Edureka!  This version was released in 2013. This was the first version to provide full support to Java 8.

2. What is a Spring Framework?

  • Spring logo - Spring Interview Questions - Edureka!Spring is a powerful open source, application framework created to reduce the complexity of enterprise application development.
  • It is light-weighted and loosely coupled.
  • It has layered architecture, which allows you to select the components to use, while also providing a cohesive framework for J2EE application development.
  • Spring framework is also called the framework of frameworks as it provides support to various other frameworks such as Struts, Hibernate, Tapestry, EJB, JSF etc.

3. List the advantages of Spring Framework.

  • Because of Spring Frameworks layered architecture, you can use what you need and leave which you don’t.
  • Spring Framework enables POJO (Plain Old Java Object) Programming which in turn enables continuous integration and testability.
  • JDBC is simplified due to Dependency Injection and Inversion of Control.
  • It is open-source and has no vendor lock-in.

4. What are the different features of Spring Framework?

Following are some of the major features of Spring Framework :

  • Lightweight: Spring is lightweight when it comes to size and transparency.
  • Inversion of control (IOC): The objects give their dependencies instead of creating or looking for dependent objects. This is called Inversion Of Control.
  • Aspect oriented Programming (AOP): Aspect oriented programming in Spring supports cohesive development by separating application business logic from system services.
  • Container: Spring Framework creates and manages the life cycle and configuration of the application objects.
  • MVC Framework: Spring Framework’s MVC web application framework is highly configurable. Other frameworks can also be used easily instead of Spring MVC Framework.
  • Transaction Management: Generic abstraction layer for transaction management is provided by the Spring Framework. Spring’s transaction support can be also used in container less environments.
  • JDBC Exception Handling: The JDBC abstraction layer of the Spring offers an exception hierarchy, which simplifies the error handling strategy.

5. How many modules are there in Spring Framework and what are they?

There are around 20 modules which are generalized into Core Container, Data Access/Integration, Web, AOP (Aspect Oriented Programming), Instrumentation and Test.Spring Framework Architecture - Spring Interview Questions - Edureka!

  • Spring Core Container – This layer is basically the core of Spring Framework. It contains the following modules :
  1. Spring Core
  2. Spring Bean
  3. SpEL (Spring Expression Language)
  4. Spring Context
  • Data Access/Integration – This layer provides support to interact with the database. It contains the following modules :
  1. JDBC (Java DataBase Connectivity)
  2. ORM (Object Relational Mapping)
  3. OXM (Object XML Mappers)
  4. JMS (Java Messaging Service)
  5. Transaction
  • Web – This layer provides support to create web application. It contains the following modules :
  1. Web
  2. Web – MVC
  3. Web – Socket
  4. Web – Portlet
  • Aspect Oriented Programming (AOP) – In this layer you can use Advices, Pointcuts etc., to decouple the code.
  • Instrumentation – This layer provides support to class instrumentation and classloader implementations.
  • Test – This layer provides support to testing with JUnit and TestNG.

Few Miscellaneous modules are given below:

  • Messaging – This module provides support for STOMP. It also supports an annotation programming model that is used for routing and processing STOMP messages from WebSocket clients.
  • Aspects – This module provides support to integration with AspectJ.

6. What is a Spring configuration file?xml file - Spring Interview Questions - Edureka!

A Spring configuration file is an XML file. This file mainly contains the classes information. It describes how those classes are configured as well as introduced to each other. The XML configuration files, however, are verbose and more clean. If it’s not planned and written correctly, it becomes very difficult to manage in big projects.

7. What are the different components of a Spring application?

A Spring application, generally consists of following components:

  • Interface: It defines the functions.
  • Bean class: It contains properties, its setter and getter methods, functions etc.
  • Spring Aspect Oriented Programming (AOP): Provides the functionality of cross-cutting concerns.
  • Bean Configuration File: Contains the information of classes and how to configure them.
  • User program: It uses the function.

8. What are the various ways of using Spring Framework?spring app - Spring Interview Questions - Edureka!

Spring Framework can be used in various ways. They are listed as follows:

  1.  As a Full-fledged Spring web application.
  2. As a third-party web framework, using Spring Frameworks middle-tier.
  3.  For remote usage.
  4. As Enterprise Java Bean which can wrap existing POJOs (Plain Old Java Objects).

The next section of Spring Interview Questions is on Dependency Injection and IoC container.

Dependency Injection/ IoC Container – Spring Interview Questions

9. What is Spring IOC Container?

ioc - Spring Interview Questions - Edureka!

At the core of the Spring Framework, lies the Spring container. The container creates the object, wires them together, configures them and manages their complete life cycle. The Spring container makes use of Dependency Injection to manage the components that make up an application. The container receives instructions for which objects to instantiate, configure, and assemble by reading the configuration metadata provided. This metadata can be provided either by XML, Java annotations or Java code.

10. What do you mean by Dependency Injection? 

In Dependency Injection, you do not have to create your objects but have to describe how they should be created. You don’t connect your components and services together in the code directly, but describe which services are needed by which components in the configuration file. The IoC container will wire them up together.

11. In how many ways can Dependency Injection be done?

In general, dependency injection can be done in three ways, namely :

  • Constructor Injection
  • Setter Injection
  • Interface Injection

In Spring Framework, only constructor and setter injections are used.

12. Differentiate between constructor injection and setter injection.

Constructor Injection vs Setter Injection

Constructor Injection Setter Injection
There is no partial injection. There can be partial injection.
It doesn’t override the setter property. It overrides the constructor property.
It will create a new instance if any modification is done. It will not create new instance if any modification is done.
It works better for many properties. It works better for few properties.

13. How many types of IOC containers are there in spring?

  1. BeanFactory: BeanFactory is like a factory class that contains a collection of beans. It instantiates the bean whenever asked for by clients.
  2. ApplicationContext: The ApplicationContext interface is built on top of the BeanFactory interface. It provides some extra functionality on top BeanFactory.

14. Differentiate between BeanFactory and ApplicationContext.

BeanFactory vs ApplicationContext

BeanFactory ApplicationContext
It is an interface defined in org.springframework.beans.factory.BeanFactory It is an interface defined in org.springframework.context.ApplicationContext
It uses Lazy initialization It uses Eager/ Aggressive initialization
It explicitly provides a resource object using the syntax It creates and manages resource objects on its own
It doesn’t supports internationalization It supports internationalization
It doesn’t supports annotation based dependency It supports annotation based dependency

15.  List some of the benefits of IoC.

Some of the benefits of IoC are:

  • It will minimize the amount of code in your application.
  • It will make your application easy to test because it doesn’t require any singletons or JNDI lookup mechanisms in your unit test cases.
  • It promotes loose coupling with minimal effort and least intrusive mechanism.
  • It supports eager instantiation and lazy loading of the services.

Let’s move on to the next section of Spring Interview Questions, that is Spring Beans Interview Questions.

Spring Beans – Spring Interview Questions

16. Explain Spring Beans?

  • They are the objects that form the backbone of the user’s application.
  • Beans are managed by the Spring IoC container.
  • They are instantiated, configured, wired and managed by a Spring IoC container
  • Beans are created with the configuration metadata that the users supply to the container.Bean generation - Spring Interview Questions - Edureka!

17. How configuration metadata is provided to the Spring container?

Configuration metadata can be provided to Spring container in following ways:

  • XML-Based configuration: In Spring Framework, the dependencies and the services needed by beans are specified in configuration files which are in XML format. These configuration files usually contain a lot of bean definitions and application specific configuration options. They generally start with a bean tag. For example:
1
2
3
<bean id="studentbean" class="org.edureka.firstSpring.StudentBean">
 <property name="name" value="Edureka"></property>
</bean>
  • Annotation-Based configuration: Instead of using XML to describe a bean wiring, you can configure the bean into the component class itself by using annotations on the relevant class, method, or field declaration. By default, annotation wiring is not turned on in the Spring container. So, you need to enable it in your Spring configuration file before using it. For example:
1
2
3
4
<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>
  • Java-based configuration: The key features in Spring Framework’s new Java-configuration support are @Configuration annotated classes and @Bean annotated methods.

1. @Bean annotation plays the same role as the <bean/> element. 

2.@Configuration classes allows to define inter-bean dependencies by simply calling other @Bean methods in the same class.

For example:

1
2
3
4
5
6
7
@Configuration
public class StudentConfig
{
@Bean
public StudentBean myStudent()
{ return new StudentBean(); }
}

18. How many bean scopes are supported by Spring?

The Spring Framework supports five scopes. They are:

  • Singleton: This provides scope for the bean definition to single instance per Spring IoC container.
  • Prototype: This provides scope for a single bean definition to have any number of object instances.
  • Request: This provides scope for a bean definition to an HTTP-request.
  • Session: This provides scope for a bean definition to an HTTP-session.
  • Global-session: This provides scope for a bean definition to an Global HTTP-session.

The last three are available only if the users use a web-aware ApplicationContext.

19. What is the Bean life cycle in Spring Bean Factory Container?

Bean life cycle in Spring Bean Factory Container is as follows:

  1. The Spring container instantiates the bean from the bean’s definition in the XML file.
  2. Spring populates all of the properties using the dependency injection, as specified in the bean definition.
  3. The factory calls setBeanName() by passing the bean’s ID, if the bean implements the BeanNameAware interface.
  4. The factory calls setBeanFactory() by passing an instance of itself, if the bean implements the BeanFactoryAware interface.
  5. preProcessBeforeInitialization() methods are called if there are any BeanPostProcessors associated with the bean.
  6. If an init-method is specified for the bean, then it will be called.
  7. Finally, postProcessAfterInitialization() methods will be called if there are any BeanPostProcessors associated with the bean.

To understand it in better way check the below diagram:

beanLifeCycle - Spring Interview Questions - Edureka!

20. Explain inner beans in Spring.

A bean can be declared as an inner bean only when it is used as a property of another bean. For defining a bean, the Spring’s XML based configuration metadata provides the use of <bean> element inside the <property> or <constructor-arg>. Inner beans are always anonymous and they are always scoped as prototypes. For example, let’s say we have one Student class having reference of Person class. Here we will be creating only one instance of Person class and use it inside Student.

Here’s a Student class followed by bean configuration file:

Student.java

1
2
3
4
5
6
7
8
9
10
11
public class Student
{
private Person person;
//Setters and Getters
}
public class Person
{
private String name;
private String address;
//Setters and Getters
}

studentbean.xml

1
2
3
4
5
6
7
8
9
<bean id=“StudentBean" class="com.edureka.Student">
<property name="person">
<!--This is inner bean -->
<bean class="com.edureka.Person">
<property name="name" value=“Scott"></property>
<property name="address" value=“Bangalore"></property>
</bean>
</property>
</bean>

21. Define Bean Wiring.

When beans are combined together within the Spring container, it’s called wiring or bean wiring. The Spring container needs to know what beans are needed and how the container should use dependency injection to tie the beans together, while wiring beans.

bean wiring - Spring Framework Interview Questions - Edureka!

22. What do you understand by auto wiring and name the different modes of it?

The Spring container is able to autowire relationships between the collaborating beans. That is, it is possible to let Spring resolve collaborators for your bean automatically by inspecting the contents of the BeanFactory.
Different modes of bean auto-wiring are:

  1. no: This is default setting which means no autowiring. Explicit bean reference should be used for wiring.
  2. byName: It injects the object dependency according to name of the bean. It matches and wires its properties with the beans defined by the same names in the XML file.
  3. byType: It injects the object dependency according to type. It matches and wires a property if its type matches with exactly one of the beans name in XML file.
  4. constructor: It injects the dependency by calling the constructor of the class. It has a large number of parameters.
  5. autodetect: First the container tries to wire using autowire by constructor, if it can’t then it tries to autowire by byType.

23. What are the limitations with auto wiring?

Following are some of the limitations you might face with auto wiring:

  • Overriding possibility: You can always specify dependencies using <constructor-arg> and <property> settings which will override autowiring.
  •  Primitive data type: Simple properties such as primitives, Strings and Classes can’t be autowired.
  • Confusing nature: Always prefer using explicit wiring because autowiring is less precise.

In the next section, we will discuss on Spring Annotations Interview Questions.

Spring Annotations – Spring Interview Questions

24. What do you mean by  Annotation-based container configuration?

Instead of using XML to describe a bean wiring, the developer moves the configuration into the component class itself by using annotations on the relevant class, method, or field declaration. It acts as an alternative to XML setups. For example:

1
2
3
4
5
6
7
@Configuration
public class AnnotationConfig
{
@Bean
public MyDemo myDemo()
 { return new MyDemoImpll(); }
}

25. How annotation wiring can be turned on in Spring?

By default, Annotation wiring is not turned on in the Spring container. Thus, to use annotation based wiring we must enable it in our Spring configuration file by configuring <context:annotation-config/> element. For example:

1
2
3
4
<beans xmlns="<a href="http://www.springframework.org/schema/beans">http://www.springframework.org/schema/beans</a&gt;" xmlns:xsi="<a href="http://www.w3.org/2001/XMLSchema-instance">http://www.w3.org/2001/XMLSchema-instance</a&gt;" xmlns:context="<a href="http://www.springframework.org/schema/context">http://www.springframework.org/schema/context</a&gt;">
<context:annotation-config/>
<beans ………… />
</beans>

26. What’s the difference between @Component, @Controller, @Repository & @Service annotations in Spring?annotations - Spring Framework Tutorial - Edureka!

@Component: This marks a java class as a bean. It is a generic stereotype for any Spring-managed component. The component-scanning mechanism of spring now can pick it up and pull it into the application context.

@Controller: This marks a class as a Spring Web MVC controller. Beans marked with it are automatically imported into the Dependency Injection container.

@Service: This annotation is a specialization of the component annotation. It doesn’t provide any additional behavior over the @Component annotation. You can use @Service over @Component in service-layer classes as it specifies intent in a better way.

@Repository: This annotation is a specialization of the @Component annotation with similar use and functionality. It provides additional benefits specifically for DAOs. It imports the DAOs into the DI container and makes the unchecked exceptions eligible for translation into Spring DataAccessException.

27. What do you understand by @Required annotation?

@Required is applied to bean property setter methods. This annotation simply indicates that the affected bean property must be populated at the configuration time with the help of an explicit property value in a bean definition or with autowiring. If the affected bean property has not been populated, the container will throw BeanInitializationException.

For example:

1
2
3
4
5
6
7
8
9
public class Employee
{
private String name;
@Required
public void setName(String name)
{this.name=name; }
public string getName()
{ return name; }
}

28. What do you understand by @Autowired annotation?

The @Autowired annotation provides more accurate control over where and how autowiring should be done. This annotation is used to autowire bean on the setter methods, constructor, a property or methods with arbitrary names or multiple arguments. By default, it is a type driven injection.

For Example:

1
2
3
4
5
6
7
8
9
public class Employee
{
private String name;
@Autowired
public void setName(String name)
{this.name=name; }
public string getName()
{ return name; }
}

29. What do you understand by @Qualifier annotation?

When you create more than one bean of the same type and want to wire only one of them with a property  you can use the @Qualifier annotation along with @Autowired to remove the ambiguity by specifying which exact bean should be wired.

For example, here we have two classes, Employee and EmpAccount respectively. In EmpAccount, using @Qualifier its specified that bean with id emp1 must be wired.

Employee.java

1
2
3
4
5
6
7
8
9
public class Employee
{
private String name;
@Autowired
public void setName(String name)
{ this.name=name; }
public string getName()
{ return name; }
}

EmpAccount.java

1
2
3
4
5
6
7
8
9
10
public class EmpAccount
{
private Employee emp;
@Autowired
@Qualifier(emp1)
public void showName()
{
System.out.println(“Employee name : ”+emp.getName);
}
}

30.  What do you understand by @RequestMapping annotation?

@RequestMapping annotation is used for mapping a particular HTTP request method to a specific class/ method in controller that will be handling the respective request. This annotation can be applied at both levels:

  • Class level : Maps the URL of the request
  • Method level: Maps the URL as well as HTTP request method

Next section of Spring Interview Questions is on Data Access.

Data Access – Spring Interview Questions

31. Describe Spring DAO support?

The Data Access Object (DAO) support in Spring makes it easy to work with data access technologies like JDBC, Hibernate or JDO in a consistent way. This allows one to switch between the persistence technologies easily. It also allows you to code without worrying about catching exceptions that are specific to each of these technology.

32. Name the exceptions thrown by the Spring DAO classes.

See the below diagram, it depicts all the Spring DAO classes in the hierarchical order.

DAO classes - dao - Spring Framework Interview Questions - Edureka!

33.  Which classes are present in spring JDBC API?

Classes present in JDBC API are as follows:

  1. JdbcTemplate
  2. SimpleJdbcTemplate
  3. NamedParameterJdbcTemplate
  4. SimpleJdbcInsert
  5. SimpleJdbcCall

34. What are the ways by which Hibernate can be accessed using Spring?

There are two ways by which we can access Hibernate using Spring:

  1. Inversion of Control with a Hibernate Template and Callback
  2. Extending HibernateDAOSupport and Applying an AOP Interceptor node

35. Name the types of transaction management that Spring supports.

Two types of transaction management are supported by Spring. They are:

  1. Programmatic transaction management: In this, the transaction is managed with the help of programming. It provides you extreme flexibility, but it is very difficult to maintain.
  2. Declarative transaction management: In this, the transaction management is separated from the business code. Only annotations or XML based configurations are used to manage the transactions.

36. What are the different ORM’s supported by Spring?

Different ORM’s supported by Spring are depicted via the below diagram:

orms - Spring Framework Interview Questions - Edureka!The next section of Spring interview questions discusses on Spring AOP Interview Questions.

Aspect Oriented Programming (AOP) – Spring Interview Questions

37. Describe AOP.

Aspect-oriented programming or AOP is a programming technique which allows programmers to modularize crosscutting concerns or behavior that cuts across the typical divisions of responsibility. Examples of cross-cutting concerns can be logging and transaction management. The core of AOP is an aspect. It encapsulates behaviors that can affect multiple classes into reusable modules.

AOP - Spring Framework Interview Questions - Edureka!

38. What do you mean by Aspect?

Aspect is a modularization of concern which cuts across multiple objects. Transaction management is a good example of a crosscutting concern in J2EE applications. Aspects are implemented using regular classes or regular classes annotated with the @Aspect annotation in Spring Framework.

39. Explain JoinPoint.

A point during the execution of a program is called JoinPoint, such as the execution of a method or the handling of an exception. In Spring AOP, a joinpoint always represents a method execution.

40. What is an Advice?

An Action taken by an aspect at a particular joinpoint is known as an Advice. Spring AOP uses an advice as an interceptor, maintaining a chain of interceptors “around” the join point.

advice - Spring Framework Interview Questions - Edureka!

41. What are the different types of Advices?

Different types of Advices in Spring AOP are:

  1. Before: These types of advices execute before the joinpoint methods and are configured using @Before annotation mark.
  2. After returning: These types of advices execute after the joinpoint methods completes executing normally and are configured using @AfterReturning annotation mark.
  3. After throwing:  These types of advices execute only if joinpoint method exits by throwing an exception and are configured using @AfterThrowing annotation mark.
  4. After (finally): These types of advices execute after a joinpoint method, regardless of the method’s exit whether normally or exceptional return and are configured using @After annotation mark.
  5. Around: These types of advices execute before and after a joinpoint and are configured using @Around annotation mark.

42. Point out the difference between concern and cross-cutting concern in Spring AOP?

The concern is the behavior we want to have in a particular module of an application. It can be defined as a functionality we want to implement.

The cross-cutting concern is a concern which is applicable throughout the application. This affects the entire application. For example, logging, security and data transfer are the concerns needed in almost every module of an application, thus they are the cross-cutting concerns.

cross cutting concern vs concern - Spring Framework Interview Questions - Edureka!

43. What are the different AOP implementations?

Different AOP implementations are depicted by the below diagram:

AOP Implementations - Spring Framework Interview Questions - Edureka!

44. What are the difference between Spring AOP and AspectJ AOP?

Spring AOP vs AspectJ AOP

Spring AOP AspectJ AOP
Runtime weaving through proxy is done Compile time weaving through AspectJ Java tools is done
It supports only method level PointCut It suports field level Pointcuts
It is DTD based It is schema based and Annotation configuration

45. What do you mean by Proxy in Spring Framework?

An object which is created after applying advice to a target object is known as a Proxy. In case of client objects the target object and the proxy object are the same.

proxy - Spring Framework Interview Questions - Edureka!

46. In Spring, what is Weaving?

The process of linking an aspect with other application types or objects to create an advised object is called Weaving. In Spring AOP, weaving is performed at runtime. Refer the below diagram:

Weaving - Spring Framework Interview Question - Edureka!The last section of Spring interview questions is on Spring MVC Interview Questions.

MVC (Model-View-Controller) – Spring Interview Questions

47. What do you mean by Spring MVC framework?

The Spring web MVC framework provides model-view-controller architecture and ready to use components that are used to develop flexible and loosely coupled web applications. The MVC pattern helps in separating the different aspects of the application like input logic, business logic and UI logic, while providing a loose coupling between all these elements.

48. Describe DispatcherServlet.

The DispatcherServlet is the core of Spring Web MVC framework. It handles all the HTTP requests and responses. The DispatcherServlet receives the entry of handler mapping from the configuration file and forwards the request to the controller. The controller then returns an object of Model And View. The DispatcherServlet checks the entry of view resolver in the configuration file and calls the specified view component.

dispatcherServlet - Spring Framework Interview Questions - Edureka!

49. Explain WebApplicationContext.

The WebApplicationContext is an extension of the plain ApplicationContext. It has some extra features that are necessary for web applications. It differs from a normal ApplicationContext in terms of its capability of resolving themes and in deciding which servlet it is associated with.

50. In Spring MVC framework, what is controller?

Controllers provide access to the application behavior. These behaviors are generally defined through a service interface. Controllers interpret the user input and transform it into a model which is represented to the user by the view. In Spring, controller is implemented in a very abstract way. It also enables you to create a wide variety of controllers.

controller - Spring Framework Interview Questions - Edureka!

 

I hope this set of Spring Interview Questions and Answers will help you in preparing for your interviews. All the best!

Abstraction in Java

Abstraction in Java

If you have started to learn Java then I believe you must have somewhere come across term called object-oriented programming or OOPs concept. Now there are four pillars in Oops i.e., Abstraction, polymorphism, encapsulation and inheritance. In this article we will discuss about one of the four pillars of Oops i.e., Abstraction.

Abstraction basically is the art of hiding implementation details from user and provide the user what they want. Let’s try to understand with real world example. Most of us are quite fond of owning a car. When we go to place order for the car we are really not interested to understand very fine details of implementation of each and every component insider the car engine, Gear box etc., we leave those technical details and implementation for manufacturing engineers and mechanics to understand we are simply interested in the car so does the manufacturing company. They are interested to exactly provide us what we want and hide the fine implementation details from us. Likewise, there are tons of real-world examples where abstraction is in play whether smartphone you are using or smart television you are watching all have implemented abstraction in one way or the other.

Coming back to Java programming or any object-oriented programming to be more precise same principle follows code’s implementation details are hidden and only the necessary functionality is provided to the user. There are two ways to achieve abstraction in java: –

  1. By using interfaces
  2. By using abstract classes

Interfaces- Consider a television remote which only contains functionality to operate a television and it doesn’t serve any other purpose besides operating the television. You won’t be able to operate a refrigerator with a television remote. Here remote acts as an interface between you and the television. It contains all the necessary functionalities which you require while hiding the implementation details from you. In java Interfaces are similar to classes except they contain empty methods and can contain variables also. By empty methods it means that they don’t provide any implementation details and its for the classes or clients to provide the necessary implementation details for that method (or methods) when they implement the interface.

Syntax :-

public interface XYZ {

public void method ();

}

Example :

public interface TelevisionRemote {
public void turnOnTelevision();

public void turnOffTelevision();

}

A java class can just use the implements keyword to implement the interface and provide the implementation of the methods of the interface.

Example: –

public class Television implements TelevisionRemote{

   @Override

   public void turnOnTelevision(){

   //method implementation details

   }

   @Override

   public  void turnOffTelevision(){

   //method implementation details

   }

}

Interfaces provide contract specification or sets of rules for the classes implementing them. They set rules for classes and tell them what to do and not to do. In case the class does not provide implementation for all the methods of the interface then the class must be declared abstract. We will cover abstract classes later. They provide total abstraction which means that all the methods are empty and field variables are public static and final by default. Interfaces serve several features: –

1.They provide total abstraction.

2.They help to achieve what we call multiple inheritance as java doesn’t support multiple inheritance, but you can implement several interfaces in one class and thus it helps to achieve multiple inheritance.

3.They help to achieve loose coupling in design patterns implementation.

Abstract classes

Abstract classes are just like normal java class except they use keyword abstract in front of class declaration and method declaration.

Syntax: –

public abstract class XYZ {

public abstract methodName();

}

For example :

public abstract class Automobile {

   public abstract void engine();

   public void  gearBoxGearOne(){

     //method implementation

   }

}

Abstract classes are created using abstract keyword and they may have or may not have method implementation. If a method is declared abstract then its implementation has to be provided by the class extending the abstract class. We can have abstract class without abstract method as well as they can contain final methods also. A class that extends the abstract class is a child class for that abstract class and has to provide implementation for the abstract method declared in the abstract class.

Example :-

public class Car extends Automobile{

   @Override

   public void engine(){

     //Method implementation

   }

}

Now question must be arising why we have interfaces and abstract classes. There are few key differences worth noticing : –

1.Interfaces are implicitly abstract and cannot have implementations. Abstract classes can have method implementations.

2.Variables of interfaces are final by default. Abstract classes may or may not have final variable.

3.Interface methods are public whereas abstract classes can provide all types of access modifiers for its members i.e., public, protected, private.

4.Interface can extend interface only while classes can implement multiple interfaces and can extend one class only.

Thus, both abstract classes and interfaces are used to achieve abstraction and both have their own importance while designing a java solution but most preferable choice for most developers is to use interfaces as they provide complete abstraction. I hope this article helps to clear your doubts regarding abstraction.

Kafka Consumer Overview

This article is a continuation of Part 1 – Kafka Technical OverviewPart 2 – Kafka Producer Overview and Part 3 – Kafka Producer Delivery Semantics articles. Let’s look into Kafka consumer group, consumer, and protocol used in detail.

Consumer Role

Like a Kafka Producer that optimizes writes to Kafka, a Consumer is used for optimal consumption of Kafka data. The primary role of a Kafka consumer is to take Kafka connection and consumer properties to read records from the appropriate Kafka broker. Complexities of concurrent application consumption, offset management, delivery semantics, and a lot more are taken care of by Consumer APIs.

Properties

Some of the consumer properties in the bootstrap servers are: fetch.min.bytesmax.partition.fetch.bytesfetch.max.bytesenable.auto.commit, and many more. We will discuss some of these properties later in the next part of the article series.

Role of Kafka Consumers
Role of Kafka consumer

Multi-App Consumption

Multiple applications can consume records from the same Kafka topic, as shown in the diagram below. Each application that consumes data from Kafka gets it’s own copy and can read at its own speed. In other words, offsets consumed by one application could be different from another application. Kafka keeps tracks of the offsets consumed by each application in an internal__consumer_offset topic.

Kafka multi app consumption

Consumer Group and Consumer

Each application consuming data from Kafka is treated as a consumer group. For example, if two applications are consuming the same topic from Kafka, then, internally, Kafka creates two consumer groups. Each consumer group can have one or more consumers. If a topic has three partitions and an application consumes it, then a consumer group would be created and a consumer in the consumer group will consume all partitions of the topic. The diagram below depicts a consumer group with a single consumer.

Kafka multi partition single consumer

Kafka multi-partition single consumer

When an application wants to increase the speed of processing and process partitions in parallel then it can add more consumers to the consumer group. Kafka takes care of keeping track of offsets consumed per consumer in a consumer group, rebalancing consumers in the consumer group when a consumer is added or removed and lot more.

Kafka multi partition multi consumer

Kafka multi-partition multi-consumer

When there are multiple consumers in a consumer group, each consumer in the group is assigned one or more partitions. Each consumer in the group will process records in parallel from each leader partition of the brokers. A consumer can read from more than one partition.

Kafka consumer and multi partition consumption

It’s very important to understand that no single partition will be assigned to two consumers in the same consumer group; in other words, the same partition will not be processed by two consumers as shown in the diagram below.

Kafka same partition multiple consumer

Kafka same partition multiple-consumer

When consumers in a consumer group are more than partitions in a topic then over-allocated consumers in the consumer group will be unused.

Kafka unused consumer

Kafka unused consumer

When you have multiple topics and multiple applications consuming the data, consumer groups and consumers of Kafka will look similar to the diagram shown below.

Multiple application and multiple kafka topic

Multiple application and multiple Kafka topic

Coordinator and Leader Discovery

In order to manage the handshake between Kafka and the application that forms the consumer group and consumer, a coordinator on the Kafka side and a leader (one of the consumers in the consumer group) is elected. The first consumer that initiates the process is automatically elected as leader in the consumer group. As explained in the diagram below, for a consumer to join a consumer group, the following handshake processes take place:

  • Find coordinator
  • Join group
  • Sync group
  • Heartbeat
  • Leave group

Kafka consumer and coordinator protocol

Kafka consumer and coordinator protocol

Coordinator

In order to create or join a group, a consumer has to first find the coordinator on the Kafka side that manages the consumer group. The consumer makes a “find coordinator” request to one of the bootstrap servers. If a coordinator already doesn’t exist it’s identified based on a hashing formula and returned as a response to “find coordinator” request.

Join Group

Once the coordinator is identified, the consumer makes a “join group” request to the coordinator. The coordinator returns the consumer group leader and metadata details. If a leader already doesn’t exist then the first consumer of the group is elected as leader. Consuming application can also control the leader elected by the coordinator node.

Kafka consumer join group

Kafka consumer join group

Sync Group

After leader details are received for the join group request, the consumer makes a “Sync group” request to the coordinator. This request triggers the rebalancing process across consumers in the consumer group, as the partitions assigned to the consumers will change after the “sync group” request.

Kafka consumer sync group

Kafka consumer sync group

Rebalance

All consumers in the consumer group will receive updated partition assignments that they need to consume when a consumer is added/removed or “sync group” request is sent. Data consumption by all consumers in the consumer group will be halted until the rebalance process is complete.

Kafka consumer rebalance group

Kafka consumer rebalance group

Heartbeat

Each consumer in the consumer group periodically sends a heartbeat signal to its group coordinator. In the case of heartbeat timeout, the consumer is considered lost and rebalancing is initiated by the coordinator.

Kafka consumer heartbeat

Kafka consumer heartbeat

Leave Group

A consumer can choose to leave the group anytime by sending a “leave group” request. The coordinator will acknowledge the request and initiate a rebalance. In case the leader node leaves the group, a new leader is elected from the group and a rebalance is initiated.

Kafka consumer leave group

Kafka consumer leave group

Summary

As explained in Part 1of this series, “partitions” are units of parallelism. As consumers in a consumer group are limited by the partition in a topic, it’s very important to decide you partitions based on the SLA and scale your consumers accordingly. Consumer offsets are managed and stored by Kafka in an internal __consumer_offset topic. Each consumer in a consumer group follows the find coordinator, join group, sync group, heartbeat, and leave group protocols. In the next article in this series, we’ll look into Kafka consumer properties and delivery semantics.

 

Java Concurrency: Thread Confinement

Thread Confinement

Most concurrency problems occur only when we want to share a mutable variable, or mutable state, between threads. If a mutable state is shared between multiple threads, then all of them will be able to read and modify the value of the state, thus resulting in incorrect or unexpected behavior. One way to avoid this problem is to simply not share the data between the threads. This technique is known as thread confinement and is one of the simplest ways of achieving thread safety in our application.

The Java language, in itself, does not have any way of enforcing thread confinement. Thread confinement is achieved by designing your program in a way that does not allow your state to be used by multiple threads and is, thus, enforced by the implementation. There are a few types of thread confinement, as described below.

Ad-Hoc Thread Confinement

Ad-hoc thread confinement describes a way of thread confinement, where it is the total responsibility of the developer, or the group of developers working on that program, to ensure that the use of the object is restricted to a single thread. This approach is very very fragile and should be avoided in most cases.

One special case that comes under Ad-hoc thread confinement applies to volatile variables. It is safe to perform read-modify-write operations on the shared volatile variable as long as you ensure that the volatile variable is only written from a single thread. In this case, you are confining the modification to a single thread to prevent race conditions, and the visibility guarantees for volatile variables ensure that other threads see the most up to date value.

Stack Confinement

Stack confinement is confining a variable, or an object, to the stack of the thread. This is much stronger than Ad-hoc thread confinement, as it is limiting the scope of the object even more, by defining the state of the variable in the stack itself. For example, consider the following piece of code:

private long numberOfPeopleNamedJohn(List<Person> people) {
  List<Person> localPeople = new ArrayList<>();
  localPeople.addAll(people);
  return localPeople.stream().filter(person -> person.getFirstName().equals("John")).count();
}

In the above code, we pass on a list of person but do not directly use it. We, instead, create our own list, which is local to the currently executing thread, and add all the person in people to localPeople. Since we are defining our list in the  numberOfPeopleNamedJohn method only, this makes the variable  localPeople stack confined, as it exists on stack of one thread, and thus cannot be accessed by any other thread. This makes localPeople thread safe. The only thing we need to take care of here is that we should not allow localPeople to escape the scope of this method, to keep it stack confined. This should also be documented or commented when defining this variable, as generally, it’s only in the current developer’s mind to not let it escape, and in future, another developer may mess up.

ThreadLocal

ThreadLocalallows you to associate a per-thread value with a value-holding object. It allows you to store different objects for different threads and maintains which object corresponds to which thread. It has set and get accessor methods which maintain a separate copy of the value for each thread that uses it. The  get() method always returns the most updated value passed to  set() from the currently executing thread. Let’s look at an example:

public class ThreadConfinementUsingThreadLocal {
    public static void main(String[] args) {
        ThreadLocal<String> stringHolder = new ThreadLocal<>();
        Runnable runnable1 = () -> {
            stringHolder.set("Thread in runnable1");
            try {
                Thread.sleep(5000);
                System.out.println(stringHolder.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable runnable2 = () -> {
            stringHolder.set("Thread in runnable2");
            try {
                Thread.sleep(2000);
                stringHolder.set("string in runnable2 changed");
                Thread.sleep(2000);
                System.out.println(stringHolder.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Runnable runnable3 = () -> {
            stringHolder.set("Thread in runnable3");
            try {
                Thread.sleep(5000);
                System.out.println(stringHolder.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        Thread thread1 = new Thread(runnable1);
        Thread thread2 = new Thread(runnable2);
        Thread thread3 = new Thread(runnable3);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

In the above example, we have executed three threads, using the same  ThreadLocal object stringHolder. As you can see here, we have, first of all, set one string in every thread in the stringHolder object, making it contain three strings. Then, after some pause, we have changed the value from just the second thread. Below was the output of the program:

string in runnable2 changed
Thread in runnable1
Thread in runnable3

As you can see in the above output, the String for thread 2 changed, but the strings for thread 1 and thread 3 were unaffected. If we do not set any value before getting the value on a specific thread from ThreadLocal, then it returns null. After a thread is terminated, thread-specific objects in ThreadLocal become ready for garbage collection.

Top 10 Spring Boot Interview Questions

25+ Spring Boots Interview Questions

In this article, we will discuss some top 10 interview questions in Spring Boot. These questions are a bit tricky and trending heavily, nowadays, in the job market.

1) What does the @SpringBootApplication annotation do internally?

As per the Spring Boot doc, the @SpringBootApplication annotation is equivalent to using @Configuration@EnableAutoConfiguration, and @ComponentScan with their default attributes. Spring Boot enables the developer to use a single annotation instead of using multiple. But, as we know, Spring provided loosely coupled features that we can use for each individual annotation as per our project needs.

2) How to exclude any package without using the basePackages filter?

There are different ways you can filter any package. But Spring Boot provides a trickier option for achieving this without touching the component scan. You can use the exclude attribute while using the annotation  @SpringBootApplication. See the following code snippet:

@SpringBootApplication(exclude= {Employee.class})
public class FooAppConfiguration {}

3) How to disable a specific auto-configuration class?

You can use the exclude attribute of@EnableAutoConfiguration, if you find any specific auto-configuration classes that you do not want are being applied.

//By using “exclude”
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})

On the other foot, if the class is not on the classpath, you can use the excludeName attribute of the annotation and specify the fully qualified name instead.

//By using “excludeName”
@EnableAutoConfiguration(excludeName={Foo.class})

Also, Spring Boot provides the facility to control the list of auto-configuration classes to exclude by using the spring.autoconfigure.exclude property. You can add into the application.properties. And you can add multiple classes with comma separated.

//By using property file
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

4) What is Spring Actuator? What are its advantages?

This is one of the most common interview questions in Spring Boot. As per the Spring doc:

“An actuator is a manufacturing term that refers to a mechanical device for moving or controlling something. Actuators can generate a large amount of motion from a small change.”

As we know, Spring Boot provides lots of auto-configuration features that help developers quickly develop production components. But if you think about debugging and how to debug, if something goes wrong, we always need to analyze the logs and dig through the data flow of our application to check to see what’s going on. So, the Spring Actuator provides easy access to those kinds of features. It provides many features, i.e. what beans are created, the mapping in the controller, the CPU usage, etc. Automatically gathering and auditing health and metrics can then be applied to your application.

It provides a very easy way to access the few production-ready REST endpoints and fetch all kinds of information from the web. But by using these endpoints, you can do many things to see here the endpoint docs. There is no need to worry about security; if Spring Security is present, then these endpoints are secured by default using Spring Security’s content-negotiation strategy. Or else, we can configure custom security by the help of RequestMatcher.

5) How to enable/disable the Actuator?

Enabling/disabling the actuator is easy; the simplest way is to enable features to add the dependency (Maven/Gradle) to the spring-boot-starter-actuator, i.e. Starter. If you don’t want the actuator to be enabled, then don’t add the dependency.

Maven dependency:

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

6) What is the Spring Initializer?

This may not be a difficult question, but the interviewer always checks the subject knowledge of the candidate. It’s often that you can’t always expect questions that you have prepared. However, this is a very common question asked almost all of the time.

The Spring Initializer is a web application that generates a Spring Boot project with everything you need to start it quickly. As always, we need a good skeleton of the project; it helps you to create a project structure/skeleton properly. You can learn more about the Initializer here.

7) What is a shutdown in the actuator?

Shutdown is an endpoint that allows the application to be gracefully shutdown. This feature is not enabled by default. You can enable this by using management.endpoint.shutdown.enabled=true in your application.properties file. But be careful about this if you are using this.

8) Is this possible to change the port of Embedded Tomcat server in Spring boot?

Yes, it’s possible to change the port. You can use the application.properties file to change the port. But you need to mention “server.port” (i.e. server.port=8081). Make sure you have application.properties in your project classpath; REST Spring framework will take care of the rest. If you mention server.port=0 , then it will automatically assign any available port.

9) Can we override or replace the Embedded Tomcat server in Spring Boot?

Yes, we can replace the Embedded Tomcat with any other servers by using the Starter dependencies. You can use spring-boot-starter-jetty  or spring-boot-starter-undertow as a dependency for each project as you need.

10) Can we disable the default web server in the Spring Boot application?

The major strong point in Spring is to provide flexibility to build your application loosely coupled. Spring provides features to disable the web server in a quick configuration. Yes, we can use the application.properties to configure the web application type, i.e.  spring.main.web-application-type=none.

All the best!

For More : https://www.bipinwebacademy.com/2019/04/spring-boot-interview-questions.html

Java Streams Overview, Part II

In my previous article, I wrote about the fundamentals of streams in Java 8. Now, let’s augment our skills with some additional information about streams, like how we can chain them, and we can use them to access files.

Chaining Streams

When working with streams, they are often chained together.

Let us see what are the advantages of using chained streams:

  • One stream instance leverages another stream instance.
  • This creates a higher level of functionality. We can have one stream accessing the data, then we have another stream that takes the results of that and processes more complex functionality.
  • This simplifies reusability because you can organize your streams in a way that allows each of them performs a specific job. In this way, they do not need to know each other’s inner workings.

We perform chaining using a constructor. We construct a higher level instance of the stream and then pass an instance of a lower level stream.

A good example of a chained stream is the InputStreamReader class, which is what we talked about in my previous article.

This class leverages chaining by providing reader behavior over an  InputStream. It translates the binary response to character behavior.

Let us see how it works.

void doChain(InputStream in) throws IOException{
int length;
char[] buffer = new char[128];
try(InputStreamReader rdr = new InputStreamReader(in)) {
while((length = rdr.read(buffer)) >= 0) {
//do something
}
}
}

As you can see, we do not need to care about how the  InputStream works. Whether it is backed by a file or network, it does not matter.

The only thing we know that it gives us binary data, we will pass it to our InputStreamReader and it converts it and can work with it as a character data.

Notice that we use try-with-resources here as well. If we close the InputStreamReader, it automatically closes theInputStream as well. This a very powerful concept, that you should know about.

File and Buffered Streams

We often use streams for accessing files.

There are several classes for that in the java.io package to use, like:

  • FileReader
  • FileWriter 
  • FileInputStream 
  • FileOutputStream 

The real thing is that these file streams are deprecated now. Despite that, they are still widely used in codes. So, you probably will face them in the near future, so it’s worth a notation.

Let us look at new ways to interact with files.

Buffered Streams

Buffered Streams are introduced to replace the FileStream classes in the java.io package. These new Streams are placed under the java.nio package.

It was necessary because direct file access can be inefficient and buffered streams can significantly improve efficiency with the following:

  • Buffer content in memory
  • Perform reads/writes in large chunks
  • Reduce underlying stream interaction

Buffering available for all four stream types:

  • BufferReader 
  • BufferWriter 
  • BufferedInputStream 
  • BufferedOutputStream 

Using them is very straightforward.

try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))){
int value;
while((value = br.read()) >= 0) {
char charValue = (char)value;
//do something
}
}

Additional benefits to using BufferedStreams includes:

  • It handles linebreaks for various platforms like Windows or Unix
  • Uses correct value for the current platform
  • The BufferedWriter has a method:newLine(). It will create a new line with the appropriate character.
  • TheBufferedReader has a method for line based read: readLine().

Let us see how they work.

BufferedWriter:

void writeData(String[] data) throws IOException {
try(BufferedWriter bw = new BufferedWriter(new FileWriter("file.txt"))){
int value;
for(String str : data) {
bw.write(str);
bw.newLine();
}
}

BufferedReader:

void readData(String[] data) throws IOException {
try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))){
String inValue;
while((inValue = br.readLine()) != null) {
System.out.println(inValue);
}
}

The code above will write out the file’s content line by line.

Accessing Files With the java.nio.file package

In Java 8, the java.io.FileXXX streams are deprecated. There is a new package to handle file streams called the java.nio.file package.

The package has several benefits over java.io:

  • Better exception reporting
  • Greater scalability, they work much better with large files
  • More file system feature support
  • Simplifies common tasks

Bellow, we will talk about the most fundamental Types In this new package.

Paths and Path Types

Path

  • Used to locate a file system item
  • It can be a file or directory

Paths

  • Used to get the Path objects through static Path factory methods
  • It translates a string-based hierarchical path or URI to Path.

Example: Path p = Paths.get(“\\documents\\foo.txt”)

Files Type

  • Static methods for interacting with files
  • Create, copy, delete, etc…
  • Open files streams
    • newBufferedReader 
    • newBufferedWriter 
    • newInputStream 
    • newOutputStream 
  • Read/Write file contents
    • readAllLines
    • write 

Reading Lines With BufferedReader

Let us see some quick example of how you can use it.

void readData(String[] data) throws IOException {
try(BufferedReader br = Files.newBufferedReader(Paths.get("data.txt")){
String inValue;
while((inValue = br.readLine()) != null) {
System.out.println(inValue);
}
}
}

Read All lines

void readAllLines(String[] data) throws IOException {
List<String> lines = Files.readAllLines(Paths.get("data.txt"));
for(String line:lines) {
System.out.println();
}
}

File Systems

When we work with files from a Java program, those files are contained within a file system. Most commonly, we use the computer’s default file system.

Java also supports specialized file systems, such as the Zip file system.

Path instances are tied to a file system and thePath class works only for the default one. So, we need another solution. Fortunately, in the Java.nio package, we have the opportunity to deal with this.

File System Types

FileSystem

  • Represents an individual file system
  • Factory for Path instances

FileSystems

  • Used to get the FileSystem objects through static FileSystem factory methods
  • Open or create a file system
    •  newFileSystem

Accessing File Systems

File systems identified by URIs

  • Specifics of URI vary greatly among the file systems
  • Zip file system uses “jar:file” scheme
    • jar:file:/documents/data.zip

File systems support custom properties

  • Different for each file system type
  • Examples: String encoding, whether to create if it does not exist

Creating a Zip Filesystem

public static void main(String[] args) throws FileNotFoundException, IOException {
try (FileSystem zipFileSystem = openZip(Paths.get("data.zip"))){ //pass the Path where we would like to create our FileSystem
}catch (Exception e) {
System.out.println(e.getClass().getSimpleName() + " - " + e.getLocalizedMessage());;
}
}
private static FileSystem openZip(Path path) throws URISyntaxException, IOException {
Map<String, String> properties = new HashMap<>();
properties.put("create", "true"); //set the property to allow creating
URI zipUri = new URI("jar:file", path.toUri().getPath(), null); //make a new URI from the path
FileSystem zipFileSystem = FileSystems.newFileSystem(zipUri, properties); //create the filesystem
return zipFileSystem;
}

After the code above, you should see your data.zip file in your directory.

Copying Files to Zip Filesystem

Let us augment the above example with a File copy operation.

In this example, I created a file called file.txt in my project library. We will copy this file to our data.zip Filesystem.

Streams in Java 8
public static void main(String[] args) throws FileNotFoundException, IOException {
try (FileSystem zipFileSystem = openZip(Paths.get("data.zip"))){
copyFileToZip(zipFileSystem); //Here we call the file copy
}catch (Exception e) {
System.out.println(e.getClass().getSimpleName() + " - " + e.getLocalizedMessage());;
}
}
private static FileSystem openZip(Path path) throws URISyntaxException, IOException {
Map<String, String> properties = new HashMap<>();
properties.put("create", "true");
URI zipUri = new URI("jar:file", path.toUri().getPath(), null);
FileSystem zipFileSystem = FileSystems.newFileSystem(zipUri, properties);
return zipFileSystem;
}
static void copyFileToZip(FileSystem zipFileSystem) throws IOException{
Path sourceFile = FileSystems.getDefault().getPath("file.txt"); //Read the file to copy
Path destFile = zipFileSystem.getPath("/fileCopied.txt"); //get the path of the new file
Files.copy(sourceFile, destFile);//Copy the file to our zip FileSystem
}

After you run the code, you should see the fileCopied.txt int our zip-file. Its context should be the same as in our file.txt.

Summary

In this article, we went further into streams in Java 8. I demonstrated how stream chaining works, as well as how you can deal with files through the new java.nio package. We also touched on why you should use more up-to-date, buffered versions of the Filestreams.

Hope you enjoyed!

Using Cache in Spring Boot

Let’s imagine a web application, where for each request received, it must read some configuration data of a database. That data doesn’t change usually, but the application, in each request, must connect, execute the correct instructions to read the data, pick it up from the network, etc. Imagine also that the database is very busy or the connection is slow. What would happen? We would have a slow application because it is reading continuously data that hardly changes.

A solution to that problem could be using a cache, but how do you implement it? In that article, I explain how to use a basic cache in Spring Boot.

A Little Theory

The cache is replicated over functions, where for the same entry value, we are waiting for the same return value. That’s why we always have at least one parameter for entry and exit.

A typical example will be this:

@Cacheable(cacheNames="headers")
public int cachedFunction(int value){
..... complicated and difficult calculations ....
  return N;
}

And now, let’s suppose we have the next code for calling that function:

int value=cachedFunction(1);
int otherValue=cachedFunction(2);
int thirdValue=cachedFunction(1);

When executing the program, in the first line, Spring will execute the function and save the result that returns. In the second line, if it doesn’t know the value it must return for the input “2.” Nevertheless, in the third line, Spring will detect that a function tagged as @Cacheable   with the name “headers” was already called with the value “1.” It won’t execute the function, it will only return the value that in the first call it saved.

The cache’s name is important because, among other things, it permits us to have different independent caches, which we could clean to instruct Spring Boot to execute the functions again.

So, the idea is that in each call to a function tagged as @Cacheable it will save the return values for each call in an internal table, in such a way that if it already has a return value for one entry, it doesn’t call to the function.

The Practice

And now, let’s get to the practice.

An example project can be found here.

First, we must include the following dependency in our project.

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

Now, we can use the tags that will allow us to use Cache  in our application.

The first tag set is  @EnableCaching. With this label, we tell Spring that it must prepare the support to use Cache. If we do not put it, it will simply not use Cache, regardless of whether we then mark the functions with cache tags.

@SpringBootApplication
@EnableCaching
public class CacheExampleApplication {
    public static void main(String[] args) {
          SpringApplication.run(CacheExampleApplication.class, args);
    }
}

In this example, we read the data of a database using REST requests.

Data  in the CacheDataImpl.java class which is in the package com.profesorp.cacheexample.impl

The function that reads the data is the following:

@Cacheable(cacheNames="headers", condition="#id > 1")
public DtoResponse getDataCache(int id) {         
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
    }                              
    DtoResponse requestResponse=new DtoResponse();                     
    Optional<Invoiceheader> invoice=invoiceHeaderRepository.findById(id);
    .....MORE CODE WITHOUT IMPORTANCE ...
}

As can be seen, we have the tag  @Cacheable(cacheNames="headers", condition="#id > 1") 

With this, we told Spring two things:

  1. We want to cache the result of this function.
  2. We put it as a condition that it must store the results in cache if the input is greater than one.

Later, in the function flushCache we put the tag @CacheEvict that cleans the indicated cache. Also, in this case, we tell it to delete all the entries that it has in cache.

@CacheEvict(cacheNames="headers", allEntries=true)
public void flushCache() { }

In the function update we update the database and with the label @CachePut, we inform Spring that it updates the data for the existing value in dtoRequest.id.

Of course, this function must return an object equal to the function labeled with the tag @Cacheable , and we must indicate the input value on which we want to update the data

Running

To understand the application better, we will execute it and give it a request .

The application at the beginning has four invoices in the invoiceHeader table. You can see how it fills the table in the data.sql file

Let’s run the get function of the PrincipalController class. For this we write this:

> curl -s http://localhost:8080/2

The application will return the following:

{"interval":507,"httpStatus":"OK","invoiceHeader":{"id":2,"active":"N","yearFiscal":2019,"numberInvoice":2,"customerId":2}}

The field interval is the time in milliseconds that has takes the application making the request. As can be seen, it has taken more than half a second, because in the getDataCachefunction of CacheDataImpl.java we have a sleep 500instruction.

Now, we execute the call again:

> curl -s http://localhost:8080/2
{"interval":1,"httpStatus":"OK","invoiceHeader":{"id":2,"activo":"N","yearFiscal":2019,"numberInvoice":2,"customerId":2}}

Now the time the call has taken is 1, because Spring hasn’t executed the code of the function, and it has simply returned the value that it had cached.

However, if we request the id as 1, we have indicated that you should not cache this value, always execute the function and therefore we will have a time exceeding 500 milliseconds:

>curl -s http://localhost:8080/1
{"interval":503,"httpStatus":"OK","invoiceHeader":{"id":1,"activo":"S","yearFiscal":2019,"numberInvoice":1,"customerId":1}}
>curl -s http://localhost:8080/1
{"interval":502,"httpStatus":"OK","invoiceHeader":{"id":1,"activo":"S","yearFiscal":2019,"numberInvoice":1,"customerId":1}}
>curl -s http://localhost:8080/1
{"interval":503,"httpStatus":"OK","invoiceHeader":{"id":1,"activo":"S","yearFiscal":2019,"numberInvoice":1,"customerId":1}}

If we call to the flushcache function, we’ll clean the cache and therefore, the next call to the function will execute the code in it.

> curl -s http://localhost:8080/flushcache
Cache Flushed!
> curl -s http://localhost:8080/2
{"interval":508,"httpStatus":"OK","invoiceHeader":{"id":2,"activo":"N","yearFiscal":2019,"numberInvoice":2,"customerId":2}}
> curl -s http://localhost:8080/2
{"interval":0,"httpStatus":"OK","invoiceHeader":{"id":2,"activo":"N","yearFiscal":2019,"numberInvoice":2,"customerId":2}}

Finally, we will see as if we change the value of the field activo to N, since the function that makes the change is labeled with @CacheEvict, it will update the value of the cache, but the getDataCache function won’t execute in the next call.

> curl -X PUT   http://localhost:8080/   -H "Content-Type: application/json"   -d "{\"id\": 2, \"active\": \"N\"}"
>curl -s http://localhost:8080/2
{"interval":0,"httpStatus":"OK","invoiceHeader":{"id":2,"activo":"N","yearFiscal":2019,"numberInvoice":2,"customerId":2}}

Conclusions

Spring without any difficulty allows us to cache the results of the functions. However, you have to take into account that cache is very basic and it is realized in memory. Spring Boot permits us to use external libraries that will allow us to save the data in disc or database.

In the documentation, you can find the different implementations of cache that Spring Boot supports, one of which is EhCache with which you will can different kinds of backend for the data, as well as specify validity times for the data, and more.