Derik Lima's Blog

How to Start a Java Project with Spring configured by XML

By Derik Lima on Mar 26, 2020

Nowadays it’s quite rare to use XML to configure Spring beans, but it doesn’t hurt to know how you can go about making use of Spring Inversion of Control (IoC) and Dependency Injection (DI) through XML configuration.

The complete source code is available on my github on the following link.

Creating the project

First step is to use the maven command-line to actually create the project:

mvn archetype:generate
	-DgroupId={project-packaging}
	-DartifactId={project-name}
	-DarchetypeArtifactId=maven-archetype-quickstart
	-DinteractiveMode=false

In my case, I’d go for something like:

mvn archetype:generate
	-DgroupId=com.deriklima
	-DartifactId=spring-xml-demo
	-DarchetypeArtifactId=maven-archetype-quickstart
	-DinteractiveMode=false

After maven is done bootstrapping your project, you can open it with an IDE of your preference.

Setting maven to compile with Java 8

Let’s set maven to compile our project using Java 8.

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

Adding the Spring dependency

In order to use Spring’s IoC and DI, you only need one dependency (Actually it’s more as spring-context brings spring-core and others, but you get the point).

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.2.3.RELEASE</version>
</dependency>

The basic boilerplate

As we’re going to use the xml approach, we need to create the config file. You can name it whatever you want, however, I’m gonna go for applicationContext.xml

It’s important to create this file in the src/main/resources folder so it can be available on your classpath.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

</beans>

Then, on App.java, you can load this configuration file with the following:

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
  public static void main(String[] args) {
    try (ClassPathXmlApplicationContext context =
        new ClassPathXmlApplicationContext("applicationContext.xml")) {

        }
  }
}

I’m using a try-with-resources here because the Spring context needs to be closed.

Loading a bean

Let’s create a class named UserService that will just return a random User id:

import java.security.SecureRandom;

public class UserService {

  private SecureRandom random;

  public UserService() {
    random = new SecureRandom();
  }

  public String getCurrentUser() {
    return "User " + random.ints(1, 100).findFirst().getAsInt();
  }
}

Now, we need to declare this bean on applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

	<bean id="userService" class="com.deriklima.springxmldemo.UserService" />

</beans>

Finally, we can get an instance of this bean on our App.java class

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
  public static void main(String[] args) {
    try (ClassPathXmlApplicationContext context =
        new ClassPathXmlApplicationContext("applicationContext.xml")) {

      UserService userService = context.getBean("userService", UserService.class);

      System.out.println(userService.getCurrentUser());
      System.out.println(userService.save("Test User"));
    }
  }
}

And that’s it! You’ve successfully used Spring IoC (Inversion of Control) as you’ve delegated the instantiation of your object to Spring.

Adding dependencies to beans

Now, let’s suppose UserService needs to expose a method to persist a user and therefore needs access to UserDAO, how can you ask Spring to inject that specific dependency for you?

Simple, let’s first create a mocked version of UserDAO with a save method:

import java.security.SecureRandom;

public class UserDAO {

  private SecureRandom secureRandom;

  public UserDAO() {
    secureRandom = new SecureRandom();
  }

  public Integer save(String user) {
    return secureRandom.ints(1, 100).findFirst().getAsInt();
  }
}

Then we do a few things:

  • Create constructor in UserService that receives a UserDAO as a parameter and assigns it to an instance of UserDAO
  • Create the save method that receives a String as a parameter and returns an Integer which would be the User ID in this case.

Notice that I’m not really implementing a User class here just for the sake of simplicity, so a String is used instead.

import java.security.SecureRandom;

public class UserService {

  private SecureRandom random;
  private UserDAO userDAO;

  public UserService(UserDAO userDAO) {
    random = new SecureRandom();
    this.userDAO = userDAO;
  }

  public String getCurrentUser() {
    return "User " + random.nextInt(10);
  }

  public Integer save(String user) {
    return userDAO.save(user);
  }
}

And last but not least, we need to add this new bean (UserDAO) to applicationContext.xml and tell Spring to inject this new instance in UserService for us.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

	<bean id="userDao" class="com.deriklima.UserDAO" />

	<bean id="userService" class="com.deriklima.UserService">
		<constructor-arg ref="userDao" />
	</bean>

</beans>

Congratulations again! You’ve successfully used the Spring DI (Dependency Injection)!

I guess the name is very self-explanatory, but you’ve delegated the instantiation and construction of UserService to Spring and Spring automagically inject UserDAO for you.

Things can get more interesting if you make use of Interfaces instead of implementations, but the scope of this post is just to show you how to use Spring with XML.

If something is not working for you, you can check out the complete source code on my github on the following link.

That will do it for this post. Hope it helps!

© Copyright 2024 by Derik Lima.