Prepare Your Development Environment

To start running the code from the book, follow these steps:

  1. Environment Setup:

    • Ensure you are seated comfortably at your computer.

    • Install JDK 17 and verify it is set as the default by running java -version in your terminal; the output should indicate Java version 17.

  2. Project Setup:

    • Clone the project repository or download and unzip the sources from Apress. You should have a directory named pro-spring-6, which contains various modules.

  3. IDE Configuration:

    • Open IntelliJ IDEA, select File ➤ Open, and choose the pro-spring-6 directory. You will see the project and its modules in the Project View, along with Gradle and Maven configurations.

  4. Project Details:

    • The project consists of multiple modules, each representing a chapter. Modules ending in "-boot" are Spring Boot projects, while others are classic Spring projects, which can be used independently of Spring Boot.

    • The project includes configurations for both Gradle (version 7.4) and Maven (version 3.8.4), and these are set up to use wrappers, so you don’t need to install them locally.

  5. Building the Project:

    • You can build the project following the instructions in the README.adoc file. IntelliJ IDEA recognizes the wrapper configurations for building.

    • If you encounter issues with missing dependencies, try building from the command line or use options like Invalidate Caches or Reload All from Disk in the File menu.

After successfully loading and building the project, further details about Spring internals and the project configurations will be provided.

Understanding Spring Packaging

The Spring framework offers a modular packaging system, allowing developers to select only the necessary components for their applications. Each component is packaged in a JAR file, which includes compiled code, Javadoc, and source files. IntelliJ IDEA facilitates this by scanning project dependencies and enabling users to download sources and Javadocs for better code visibility.

The framework consists of 22 modules, each serving specific functionalities, such as AOP, JDBC, transaction management, and web application support. Notable modules include:

  • aop: For Spring’s AOP features.

  • jdbc: For JDBC support and database access.

  • webmvc: For Spring’s MVC framework.

For Spring Boot users, module selection is automatic through starter dependencies that simplify the setup process for common application types. These starters encapsulate necessary dependencies and configurations, such as spring-boot-starter-web for web applications and spring-boot-starter-data-* for data handling, thus streamlining the development process.

Overall, Spring’s modular architecture and the convenience of Spring Boot starters provide a flexible and efficient way to build applications tailored to specific needs.

Choosing Modules for Your Application

Accessing Spring Modules on the Maven Repository

Maven, developed by the Apache Software Foundation, is a widely-used tool for managing dependencies, building, packaging, and handling the entire build cycle of Java applications. It offers numerous plugins for various tasks and facilitates access to the Maven Central repository, which hosts many open source libraries. Users can also access additional repositories (like JBoss and Spring) by configuring their Maven settings or project POM files.

Each Maven artifact is identified by a group ID, artifact ID, packaging type, and version. The configuration for a project is specified in an XML file named pom.xml. Maven enforces a standard project structure, organizing application code and configuration files into designated directories.

Furthermore, Spring Boot enhances dependency management by ensuring compatibility of transitive dependencies, even for non-Spring Boot projects. The text concludes with a mention of Gradle, which will be introduced next.

Accessing Spring Modules Using Gradle

The Maven project structure and artifact organization are crucial because Gradle adheres to similar conventions and utilizes the Maven central repository for artifact retrieval. Gradle, a versatile build tool, has replaced complex XML configurations with Groovy for easier and more flexible setup, although excessive creativity in configuration can lead to challenges. As of now, the latest Gradle version is 7.3.3, and since version 4.x, the Spring team has adopted Gradle for all Spring product configurations. The standard Gradle configuration file is named build.gradle, which serves a similar purpose to Maven’s pom.xml. A sample build.gradle snippet demonstrates the readability and structure of Gradle configurations, using properties like group, artifact, and version to identify artifacts, albeit with different naming conventions compared to Maven. Gradle’s role will be referenced throughout the book, although it is not the primary focus.

Using Spring Boot Dependency Management

The content discusses the use of Spring Boot’s dependency management in Maven and Gradle projects. It explains how utilizing the spring-boot-starter-parent in a Maven configuration provides a simplified way to manage dependencies and their versions, allowing developers to focus on their project without specifying versions for Spring dependencies. An example pom.xml file is provided to illustrate this setup, along with a depiction of the Maven dependencies.

The text also highlights that if the spring-boot-starter-parent is not suitable for a project’s structure, developers can switch to using <dependencyManagement> to manage dependencies while still leveraging Spring Boot’s versioning benefits. An example of this alternative configuration is shown.

For Gradle, since it lacks a parent project concept, the io.spring.dependency-management plug-in is suggested to achieve similar dependency management. A corresponding Gradle configuration is provided, demonstrating how to implement and override dependencies effectively.

Lastly, the document contrasts the readability and flexibility of Gradle with the consistency and ease of learning offered by Maven’s XML schema, particularly in larger projects that may require shared configurations across multiple modules.

Using Spring Documentation

The Spring Framework is highly valued for its comprehensive and well-organized documentation, which includes both Javadoc and a reference manual. The documentation team ensures that all features are thoroughly documented with each release. This summary emphasizes the importance of familiarizing oneself with these resources and mentions that the provided book serves as a complementary guide for building Spring-based applications. Additionally, it offers URLs for accessing the Spring Javadoc and the official reference documentation for further study.

Putting a Spring into Hello World

Building the Sample Hello World Application

The provided content discusses the evolution of a simple "Hello World" Java application, illustrating how to enhance its design for flexibility and extensibility.

  1. Basic Example: The initial example is a straightforward Java application that prints "Hello World!" to the console. However, changing the message or output method requires modifying and recompiling the code.

  2. Command-Line Arguments: The next iteration allows the message to be provided via command-line arguments, improving flexibility but still coupling the message retrieval with the rendering logic.

  3. Decoupling Components: To further enhance the application, the author introduces two interfaces: MessageProvider, which retrieves messages, and MessageRenderer, which handles output. This separation allows for greater flexibility and easier testing.

  4. Implementing Interfaces: Concrete implementations of these interfaces, such as HelloWorldMessageProvider and StandardOutMessageRenderer, are created, allowing for different message retrieval and rendering strategies without changing the main application logic.

  5. Factory Pattern: A MessageSupportFactory class is introduced to manage the creation of MessageProvider and MessageRenderer instances, enabling configuration through a properties file.

  6. ServiceLoader: An alternative to the factory approach is presented using Java’s ServiceLoader mechanism, which simplifies the instantiation of interface implementations by allowing configurations to be specified through files in the META-INF/services directory.

  7. Recap: The document concludes by summarizing the key enhancements made to the application: introducing interfaces for decoupling, using a factory for instantiation, and leveraging ServiceLoader for dynamic service discovery.

Overall, the content illustrates a transition from a basic application to a more robust and flexible design, setting the stage for further integration with Spring frameworks in future discussions.

Classic Hello World Java Project:

Classic Hello World Java Project with Arguments:

MessageProvider Interface:

MessageRenderer Interface:

MessageProvider Implementation:

MessageRenderer Implementation:

New main(..) Method:

Instance Factory Class Tasked with Retrieving the Two Implementation Types and Instantiating Them:

HelloWorld Version Using MessageSupportFactory:

HelloWorld Version Using ServiceLoader:

Refactoring with Spring

Using Spring XML Configuration

The content explains the transition from using SpringLoader to ApplicationContext in Spring. The ApplicationContext interface is crucial for managing the environment of a Spring application, extending ListableBeanFactory for managing Spring beans.

A code snippet demonstrates a simple Spring application (HelloWorldSpringDI), where the main method initializes the application context from an XML configuration file (app-context.xml). This file defines two beans: provider and renderer, with the renderer bean depending on the provider for message retrieval.

The XML configuration specifies bean relationships and dependency injection using the p namespace. Spring automatically resolves and injects dependencies, allowing the MessageRenderer bean to access the MessageProvider without direct references to Spring in the classes.

The document also outlines how to build and run the project using Gradle or Maven, resulting in an executable JAR file. It notes that Spring 5 has deprecated XML configurations, emphasizing the evolution of Spring configuration practices, while still acknowledging their use in legacy projects.

Listing 2-19. HelloWorld Version Using Spring

chapter02/src/main/java/com/apress/prospring6/two/HelloWorldSpringDI.java

Listing 2-20. Spring XML Configuration File

chapter02/src/main/resources/spring/app-context.xml

Example 1. jbang

Spring Configuration Using Annotations

Starting with Spring 3.0, XML configuration files are no longer required for Spring applications, as they can now be substituted with annotations and Java configuration classes. These configuration classes, annotated with @Configuration, define beans using methods annotated with @Bean or through component scanning with @ComponentScanning.

An example provided illustrates a Java configuration class, HelloWorldConfiguration, which defines two beans: a MessageProvider and a MessageRenderer. In the main(..) method, the ClassPathXmlApplicationContext is replaced with AnnotationConfigApplicationContext to read bean definitions from these configuration classes.

This shift towards Java configuration and annotations enhances flexibility in Spring configuration. Future chapters of the book will delve further into this topic, presenting examples and code in a more concise format while maintaining code reusability across modules.

Listing 2-23. Spring Java Configuration Class

chapter02/src/main/java/com/apress/prospring6/two/annotated/HelloWorldConfiguration.java

Listing 2-24. main(..) Method to Start a Spring Application Configured Using Java Configuration

chapter02/src/main/java/com/apress/prospring6/two/annotated/HelloWorldSpringAnnotated.java