How to Write a Minimal Spring Application

Spring framework and spring boot are very popular these days for building enterprise java applications. Over years spring framework ecosystem has grown considerably. Almost all infrastructural component needs are now provided by spring framework. Spring boot simplifies development further by providing a set of defaults and automatic configuration.

Under the hood, spring framework is powered by an IoC container providing dependency injection. Spring manages the dependencies between objects providing object instances automatically whenever needed. A set of libraries known as the core container provides the basic features for a spring application. Core container consists of spring-core, spring-beans, spring-context, spring-context-support and spring-expression.

The minimal set of libraries required to build a spring application using dependency injection include spring-core and spring-beans. Our aim here is to build the simplest spring application and hence we have excluded spring-context. However for any non-trivial spring application, spring-context is needed since it contains features such as annotation configuration, java configuration and an enhanced bean factory called application context.

The following hello world spring application demo uses,

  • Java 8
  • Spring framework 4.7.3 (spring-core and spring-beans)
  • Gradle 3.4
  • Spring Tool Suite IDE

Writing a Minimalist Spring Framework App

Install Spring Tool Suite (STS) and create a simple gradle java application. Add the following classes under src/main/java folder. To demonstrate the use of dependency injection, our application has two classes. SpringCoreDemoApp contains the entry point to the application (main method). It uses an instance of a class HelloWord to print a message on the console using apache commons logging (it is always available to spring applications as a transitive dependency). Since HelloWorld is created and supplied by spring, we just provide a setter and getter method for the same in SpringCoreDemoApp. Note that we are using the IoC container to provide an instance of SpringCoreDemoApp itself.

HelloWorld.java

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class HelloWorld {
    public static final Log LOG = LogFactory.getLog(HelloWorld.class);

    public void sayHello() {
        LOG.info("Hello World!");
    }
}

SpringCoreDemoApp.java

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;

public class SpringCoreDemoApp {
    // This will be created and injected by spring IoC
    private HelloWorld hello;

    public HelloWorld getHello() {
        return hello;
    }

    public void setHello(HelloWorld hello) {
        this.hello = hello;
    }

    public static void main(String[] args) {
        BeanFactory beanFactory = getBeanFactory();

        SpringCoreDemoApp app = beanFactory.getBean("app", SpringCoreDemoApp.class);
        app.runApp();
    }

    public void runApp() {
        hello.sayHello();
    }

    public static BeanFactory getBeanFactory() {
        DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf);
        reader.loadBeanDefinitions(new ClassPathResource("beans.xml", SpringCoreDemoApp.class));
        return xbf;
    }

}

We then write a simple XML file (beans.xml) configuring all the beans that we expect spring IoC container to manage. We also specify the dependency of SpringCoreDemoApp on HelloWorld. This file needs to be in classpath and hence we create it under src/main/resources. Gradle adds this folder automatically to the classpath.

beans.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:c="http://www.springframework.org/schema/c"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <bean id="helloWorld" class="HelloWorld">
    </bean>

    <bean id="app" class="SpringCoreDemoApp">
        <property name="hello" ref="helloWorld"></property>
    </bean>

</beans>

Finally we modify the gradle build file to specify the dependency on spring-beans. The spring-core is automatically added since it is a dependency of spring-beans. The only other library loaded through transitive dependency is apache commons logging 1.2.

build.gradle

apply plugin: 'application'

mainClassName = "SpringCoreDemoApp"

repositories {
    jcenter()
}

dependencies {
    compile 'org.springframework:spring-beans:4.3.7.RELEASE'

}

From the STS IDE, open gradle tasks window and execute the run task under application group. You will see Hello World! printed on the console. We have built a spring application using the minimal set of libraries possible!