Spring Framework Interview Preparation
Spring Framework Interview Preparation
Spring Boot
Spring REST
Spring MVC
Spring JDBC
Spring AOP
Spring Boot Interview Prep
What is Spring?
Spring Boot is basically an extension of the Spring framework which eliminated the
boilerplate configurations required for setting up a Spring application.
What is the best Java IDE for Spring Framework?
Spring Tool Suite is an IDE to develop Spring applications. It is an Eclipse-based
development environment.
What is Spring Initializr?
Spring Initializr is a web-based tool (https://start.spring.io/). With the help of Spring
Initializr, we can easily generate the structure of the Spring Boot Project. The Initializr
offers a fast way to pull in all the dependencies you need for an application and does a
lot of the set up for you.
@SpringBootApplication
We use this annotation to mark the main class of a Spring Boot application:
@SpringBootApplication
class VehicleFactoryApplication {
@ComponentScan(basePackages = "com.baeldung.annotations")
class VehicleFactoryConfig {}
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}
Both arguments are arrays so that we can provide multiple packages for each.
If no argument is specified, the scanning happens from the same package where
the @ComponentScan annotated class is present.
@Component
@Component is a class level annotation. During the component scan, Spring
Framework automatically detects classes annotated with @Component.
For example:
@Component
class CarUtility {
// ...
By default, the bean instances of this class have the same name as the class name with
a lowercase initial. On top of that, we can specify a different name using the
optional value argument of this annotation.
Since @Repository, @Service, @Configuration, and @Controller are all meta-
annotations of @Component, they share the same bean naming behavior. Also, Spring
automatically picks them up during the component scanning process.
@Repository
DAO or Repository classes usually represent the database access layer in an
application, and should be annotated with @Repository:
@Repository
class VehicleRepository {
// ...
One advantage of using this annotation is that it has automatic persistence exception
translation enabled. When using a persistence framework such as Hibernate, native
exceptions thrown within classes annotated with @Repository will be automatically
translated into subclasses of Spring's DataAccessExeption.
@Service
The business logic of an application usually resides within the service layer – so we'll
use the @Service annotation to indicate that a class belongs to that layer:
@Service
public class VehicleService {
// ...
@Controller
@Controller is a class level annotation which tells the Spring Framework that this
class serves as a controller in Spring MVC:
@Controller
// ...
@Configuration
Configuration classes can contain bean definition methods annotated with @Bean:
@Configuration
class VehicleFactoryConfig {
@Bean
Engine engine() {
What Is an Actuator?
In essence, Actuator brings production-ready features to our application.
Monitoring our app, gathering metrics, understanding traffic, or the state of our
database becomes trivial with this dependency.
The main benefit of this library is that we can get production-grade tools without having
to actually implement these features ourselves.
Actuator is mainly used to expose operational information about the running
application – health, metrics, info, dump, env, etc. It uses HTTP endpoints or JMX
beans to enable us to interact with it.
Once this dependency is on the classpath several endpoints are available for us out of
the box. As with most Spring modules, we can easily configure or extend it in many
ways.
To enable Spring Boot Actuator we'll just need to add the spring-boot-
actuator dependency to our package manager. In Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
@ExceptionHandler({ EmployeeException.class })
protected ResponseEntity<Object> handleNotFound(
Exception ex, WebRequest request) {
return handleExceptionInternal(ex, "Employee not found",
new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
}
DB.url = “test”
DB.port=8990
DB.connection=myConnection
Solution is:
1. Create a class e.g. DBSettings and provide all the needed DB properties as fields and
corresponding getter/setter methods.
2. Annotate the class with @Configuration and @ConfigurationProperties(“DB”)
@Configuration
@ConfigurationProperties(“DB”)
public class DBSettings {
private int port;
private String url;
private String connection;
In order to use any logging library other than Logback, though, we need to
exclude it from our dependencies.
we need to turn it into a skinny version, and (only once) add our alternative library,
here through a starter itself:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
Spring JDBC
Spring MVC
Spring Security
Spring AOP
Spring ORM
Spring Test
Spring Boot is basically an extension of the Spring framework which eliminated the
boilerplate configurations required for setting up a Spring application.
It takes an opinionated view of the Spring platform which paved the way for a
faster and more efficient development eco-system.
Here are just a few of the features in Spring Boot:
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Finally, we can add some dependencies to Spring Boot starters, and then we're good
to go.
Q3. What Spring Boot Starters Are Available out There?
Dependency management is a crucial facet of any project. When a project is complex
enough, managing dependencies may turn into a nightmare, as there will be too many
artifacts involved.
This is where Spring Boot starters come in handy. Each starter plays a role as a one-
stop shop for all the Spring technologies we need. Other required dependencies are then
transitively pulled in and managed in a consistent way.
All starters are under the org.springframework.boot group, and their names start
with spring-boot-starter-. This naming pattern makes it easy to find starters,
especially when working with IDEs that support searching dependencies by name.
At the time of this writing, there are more than 50 starters at our disposal. The most
commonly used are:
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
When placed on a method adorned with @Bean, the target type defaults to the
method's return type:
@Configuration
public class CustomConfiguration {
@Bean
@ConditionalOnMissingBean
Q7. How to Deploy Spring Boot Web Applications as Jar and War Files?
Traditionally, we package a web application as a WAR file, then deploy it into an
external server. Doing this allows us to arrange multiple applications on the same
server. During the time that CPU and memory were scarce, this was a great way to
save resources.
However, things have changed. Computer hardware is fairly cheap now, and the
attention has turned to server configuration. A small mistake in configuring the server
during deployment may lead to catastrophic consequences.
Spring tackles this problem by providing a plugin, namely spring-boot-maven-
plugin, to package a web application as an executable JAR. To include this plugin,
just add a plugin element to pom.xml:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
With this plugin in place, we'll get a fat JAR after executing the package phase. This
JAR contains all the necessary dependencies, including an embedded server. Thus, we
no longer need to worry about configuring an external server.
We can then run the application just like we would an ordinary executable JAR.
Notice that the packaging element in the pom.xml file must be set to jar to build a
JAR file:
<packaging>jar</packaging>
If we don't include this element, it also defaults to jar.
In case we want to build a WAR file, change the packaging element to war:
<packaging>war</packaging>
And leave the container dependency off the packaged file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
After executing the Maven package phase, we'll have a deployable WAR file.
Q8. How to Use Spring Boot for Command Line Applications?
Just like any other Java program, a Spring Boot command line application must have
a main method. This method serves as an entry point, which invokes
the SpringApplication#run method to bootstrap the application:
@SpringBootApplication
SpringApplication.run(MyApplication.class);
// other statements
The SpringApplication class then fires up a Spring container and auto-configures beans.
Notice we must pass a configuration class to the run method to work as the primary
configuration source. By convention, this argument is the entry class itself.
After calling the run method, we can execute other statements as in a regular program.
Q9. What Are Possible Sources of External Configuration?
Spring Boot provides support for external configuration, allowing us to run the same
application in various environments. We can use properties files, YAML files,
environment variables, system properties, and command-line option arguments to
specify configuration properties.
We can then gain access to those properties using the @Value annotation, a bound
object via the @ConfigurationProperties annotation, or the Environment abstraction.
Here are the most common sources of external configuration:
Q10. What does it mean that Spring Boot supports relaxed binding?
Relaxed binding in Spring Boot is applicable to the type-safe binding of configuration
properties.
With relaxed binding, the key of an environment property doesn't need to be an exact
match of a property name. Such an environment property can be written in
camelCase, kebab-case, snake_case, or in uppercase with words separated by
underscores.
For example, if a property in a bean class with
the @ConfigurationProperties annotation is named myProp, it can be bound to any of
these environment properties: myProp, my-prop, my_prop, or MY_PROP.
Q11. What is Spring Boot Devtools Used For?
Spring Boot Developer Tools, or DevTools, is a set of tools making the development
process easier. To include these development-time features, we just need to add a
dependency to the pom.xml file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Spring Boot Actuator can expose operational information using either HTTP or JMX
endpoints. Most applications go for HTTP, though, where the identity of an endpoint
and the /actuator prefix form a URL path.
Here are some of the most common built-in endpoints Actuator provides:
When you use fat jar approach, your application will be deployed on embedded application
container provided by spring boot. It is possible to build so called fat JAR that is
executable *.jar file with embedded application container (Tomcat as default option).
1. application-dev.properties
2. application-test.properties
3. application-prod.properties
If I declare two Components/Beans with same name then what would happen?
Example:
@Component("EMP")
public class Employee {
. . .
@Component("EMP")
public class Manager {
. . .
Answer: It will cause build failure and will show the exception
ConflictingBeanDefinitionException
constructor-based injection
setter-based injection
field-based injection
Constructor Injection
In the Cake class above, since we have only one constructor, we don’t
have to specify the @Autowired annotation. Consider the below
example with two constructors:
When we have a class with multiple constructors, we need to
explicitly add the @Autowired annotation to any one of the
constructors so that Spring knows which constructor to use to inject
the dependencies.
Setter Injection
The Cake class requires an object of type Topping. The Topping object
is provided as an argument in the setter method of that property:
Spring will find the @Autowired annotation and call the setter to inject
the dependency.
Field Injection
Note that it’s bad practice to mix injection types on a single class as it
makes the code less readable.
The IoC container makes sure that all the arguments provided in
the constructor are available before passing them into the
constructor. This helps in preventing the
infamous NullPointerException.
Constructor injection is extremely useful since we do not have to write
separate business logic everywhere to check if all the required
dependencies are loaded, thus simplifying code complexity.
What About Optional Dependencies?
We can also pass mocks via setters, of course, but if we add a new
dependency to a class, we may forget to call the setter in the test,
potentially causing a NullPointerException in the test.
Constructor injection ensures that our test cases are executed only
when all the dependencies are available. It’s not possible to have half
created objects in unit tests (or anywhere else for that matter).
Immutability
Conclusion
Circular dependencies
If you use predominantly constructor injection, it is possible to create an unresolvable circular
dependency scenario.
For example: Class A requires an instance of class B through constructor injection, and class B
requires an instance of class A through constructor injection. If you configure beans for classes A
and B to be injected into each other, the Spring IoC container detects this circular reference at
runtime, and throws a BeanCurrentlyInCreationException .
One possible solution is to edit the source code of some classes to be configured by setters rather
than constructors. Alternatively, avoid constructor injection and use setter injection only. In other
words, although it is not recommended, you can configure circular dependencies with setter
injection.
Spring @Required Annotation
The @Required annotation in spring is a method-level annotation applied to the setter
method of a bean property and thus making the setter-injection mandatory. This
annotation indicates that the required bean property must be injected with a value at the
configuration time. Below snippet shows how to use this annotation.
The default implementation instantiates beans lazily eagerly when the application starts
when getBean() is
called
1. The Spring container instantiates the bean from the bean’s definition in
the XML file or Java.
2. Spring populates all of the properties using the dependency injection, as
specified in the bean definition.
3. If an init-method is specified for the bean, then it will be called.
When container starts – a Spring bean needs to be instantiated, based on Java or XML
bean definition. It may also be required to perform some post-initialization steps to get it
into a usable state. Same bean life cycle is for spring boot applications as well.
After that, when the bean is no longer required, it will be removed from the IoC container.
Spring bean factory is responsible for managing the life cycle of beans created through
spring container.
Life cycle callbacks
Spring bean factory controls the creation and destruction of beans. To execute some
custom code, it provides the call back methods which can be categorized broadly in two
groups:
Spring framework provides different ways for controlling life cycle events of a bean:
When a bean is a singleton, only one shared instance of the bean will be managed and
all requests for beans with an id or ids matching that bean definition will result in that
one specific bean instance being returned.
Example:
<bean id="exampleBean"
class="examples.ExampleBean" singleton="false"/>
<bean name="yetAnotherExample"
class="examples.ExampleBeanTwo" singleton="true"/>
@Scope(value="prototype")
public class Alien {
. . .
Note: when deploying a bean in the prototype mode, the lifecycle of the bean changes
slightly. By definition, Spring cannot manage the complete lifecycle of a non-
singleton/prototype bean, since after it is created, it is given to the client and the
container does not keep track of it at all any longer. You can think of Spring's role when
talking about a non-singleton/prototype bean as a replacement for the 'new' operator.
Spring returns the lookup result matched by the method's return type.
The dynamically generated code will look for the target bean in the
application context. Something like this:
Spring AOP
Concepts
One of the key components of Spring is the AOP framework. While the Spring IoC
containers (BeanFactory and ApplicationContext) do not depend on AOP, meaning you
don't need to use AOP if you don't want to, AOP complements Spring IoC to provide a
very capable middleware solution.
AOP concepts
Let us begin by defining some central AOP concepts. These terms are not Spring-specific.
Unfortunately, AOP terminology is not particularly intuitive. However, it would be even more
confusing if Spring used its own terminology.
This is the central class in the JDBC core package. It simplifies the use
of JDBC since it handles the creation and release of resources. This
helps to avoid common errors like forgetting to always close the
connection. It executes the core JDBC workflow like statement creation
and execution, leaving application code to provide SQL and extract
results. This class executes SQL queries, update statements or stored
procedure calls, imitating iteration over ResultSets and extraction of
returned parameter values. It also catches JDBC exceptions and
translates them to the generic, more informative, exception hierarchy
defined in the org.springframework.dao package.
Commonly used method:
execute(String sql)
Query given SQL to create a prepared statement from SQL and a list of arguments to
bind to the query, mapping each row to a result object via a RowMapper.
Execute a query given static SQL, mapping each row to a result object via a RowMapper.
Execute a query given static SQL, mapping a single result row to a result object via a RowMapper.
<T> T queryForObject(String sql, Object[] args, RowMapper<T> rowMapper)
Query given SQL to create a prepared statement from SQL and a list
of arguments to bind to the query, mapping a single result row
to a result object via a RowMapper.
Issue a single SQL update operation (such as an insert, update or delete statement).
DataSource
In order to work with data from a database, we need to obtain a connection to the
database. The way Spring does this is through a DataSource. A DataSource is part of the
JDBC specification and can be seen as a generalized connection factory. It allows a
container or a framework to hide connection pooling and transaction management
issues from the application code.
DriverManagerDataSource
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName( "org.hsqldb.jdbcDriver");
dataSource.setUrl( "jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername( "sa");
dataSource.setPassword( "");
BeanPropertyRowMapper
RowMapper implementation that converts a row into a new instance of the specified
mapped target class.
Constructor
BeanPropertyRowMapper(Class<T> mappedClass)
Spring BeanPropertyRowMapper, this class saves you a lot of time for the mapping.
import org.springframework.jdbc.core.BeanPropertyRowMapper;
return customers;
}
Query for a Single Value
return jdbcTemplate.queryForObject(
sql, new Object[]{id}, String.class);
Count
The code has an autowired JdbcTemplate , a handy template class that does all the
database interactions needed by the remaining code.
You also have a book method that can book multiple people. It loops through the list of
people and, for each person, inserts that person into the BOOKINGS table by using
the JdbcTemplate . This method is tagged with @Transactional , meaning that any
failure causes the entire operation to roll back to its previous state and to re-throw the
original exception. This means that none of the people are added to BOOKINGS if one
person fails to be added.
Statement,PreparedStatement and CallableStatement
<web-app>
<servlet>
<servlet-name>enrollment</servlet-name>
<servlet-
class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>golfing</servlet-name>
<url-pattern>/golfing/*</url-pattern>
</servlet-mapping>
</web-app>
With the above Servlet configuration in place, you will need to have a file
called /WEB-INF/ enrollment -servlet.xml in your application; this file will
contain all of your Spring Web MVC-specific components (beans).
@Controller
public class HelloWorldController {
@RequestMapping("/helloWorld")
public String helloWorld(Model model) {
model.addAttribute("message", "Hello World!");
return "helloWorld";
}
}
The @Controller annotation indicates that a particular class serves the role of
a controller. Spring does not require you to extend any controller base class or
reference the Servlet API. However, you can still reference Servlet-specific
features if you need to.
The @Controller annotation acts as a stereotype for the annotated class,
indicating its role. The dispatcher scans such annotated classes for mapped
methods and detects @RequestMapping annotations
To process the @PathVariable annotation, Spring MVC needs to find the
matching URI template variable by name. You can specify it in the annotation:
@RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(@PathVariable("ownerId") String theOwner, Model
model) {
// implementation omitted
}
Or if the URI template variable name matches the method argument name
you can omit that detail. As long as your code is not compiled without
debugging information, Spring MVC will match the method argument name to
the URI template variable name:
@RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(@PathVariable String ownerId, Model model) {
// implementation omitted
}