Spring Boot / Basic: composition and HTTP contracts / Lesson 1
Boot runtime and a managed build
Explain what Spring Boot contributes to a Java application and establish a reproducible version, dependency, and startup contract before adding business features.
On this page
Lesson goals
- Distinguish Boot, Framework, starters, and application code.
- Pin a coherent Java and dependency baseline.
- Read startup and build examples without assuming execution.
Separate conventions from domain decisions
Spring Boot supplies conventions, dependency management, auto-configuration, packaging, and operational integration around Spring Framework. It does not decide an order's validity, authorize a customer, or make every method transactional. A starter brings a related dependency set; auto-configuration reacts to classes, properties, and existing beans. Keep those responsibilities distinct when explaining why a component exists.
The course targets servlet-style applications on Spring Boot3.5.16, Spring Framework6.2.19, and Java17. Official versioned documentation was checked for that baseline; no claim is made that it is the newest release. Do not mix a4.x package or default with3.5 examples simply because an unversioned documentation link currently resolves to a newer line.
Let one release train manage compatible dependencies
The illustrative Maven fragment uses the Boot parent and a Java17 target. The web starter supplies the servlet MVC stack for this selected architecture. It is not an instruction to install dependencies into the shared project, and no build or server is started here. A complete project also needs source layout, tests, application decisions, and a controlled repository/build environment.
Prefer managed versions for Spring components unless a reviewed compatibility reason requires an override. Adding arbitrary Framework, Security, or Hibernate versions can produce runtime linkage failures even when source compilation succeeds. Record the resolved dependency graph and artifact identity. A machine's globally installed Gradle version is not proof that it satisfies this Boot line's supported build-tool requirements.
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.16</version>
</parent>
<groupId>training</groupId><artifactId>catalog</artifactId><version>1.0.0</version>
<properties><java.version>17</java.version></properties>
<dependencies>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>
</project>
The XML selects the pinned Boot parent and web starter. Syntax can be parsed locally; dependency resolution and framework startup are not claimed.
Read the application entry point as a composition boundary
@SpringBootApplication combines configuration, auto-configuration enablement, and component scanning. Place it in a deliberate root package so scanning finds intended components without wandering across unrelated packages. The entry class below is a framework fragment requiring the selected dependencies. Its SpringApplication.run would create a context and may start a listener when integrated; it is therefore not executed as a training shortcut.
An application context contains managed beans and their lifecycle. Starting it can also initialize database clients, schedules, or custom startup code. A test that needs only configuration should choose a restricted context or slice, not silently load every integration. Distinguish a valid compile/build from successful startup and from a ready business endpoint.
package training.catalog;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CatalogApplication {
public static void main(String[] args) {
SpringApplication.run(CatalogApplication.class, args);
}
}
The class establishes the scan/composition root. It is incomplete without the pinned project dependencies and controlled runtime configuration.
Inspect conditions instead of treating Boot as magic
Auto-configuration can back off when the application supplies a bean or when prerequisites are absent. An added starter may change the condition graph, while a custom configuration can replace expected defaults. Diagnose a mismatch by checking the actual classpath, properties, bean definitions, and condition report under an approved local test environment. Do not respond by enabling every annotation or excluding random components.
Adding the data-JPA starter, for example, introduces persistence expectations; it is not needed just to return a static catalog DTO. Keep the initial dependency surface narrow. A missing database URL after adding persistence may be evidence of an unfinished architecture rather than a reason to suppress all datasource configuration permanently.
Keep build and execution evidence honest
A useful record includes the source revision, Boot/BOM version, compiler target, runtime, effective dependency graph, configuration sources, and test command. Never label an HTTP response observed when it is only a proposed contract. This course parses suitable fixtures and compiles dependency-free models separately; framework, build, and deployment fragments remain non-runnable unless actually tested in the stated scope.
No project database, credential, external service, or network listener is required for the editorial examples. Later lessons show how scoped tests can verify web and configuration behavior without assuming a live port. The aim is explainable application composition and truthful evidence, not a large collection of annotations that happens to look like a working service.
Common errors and fixes
NoSuchMethodError after changing a dependency
- Why it happens
- Resolved libraries no longer match the managed release train.
- How to fix it
- Inspect the actual graph and restore a reviewed compatible set.
- Prevent it next time
- Version the BOM and overrides explicitly.
A component is not discovered
- Why it happens
- Its package or scan configuration lies outside the intended root.
- How to fix it
- Place or import it deliberately rather than widening scans blindly.
- Prevent it next time
- Test the composition boundary.
A successful build was called a ready service
- Why it happens
- Compilation was confused with context startup and business readiness.
- How to fix it
- Verify each boundary with an appropriately scoped test.
- Prevent it next time
- Separate observed and intended results.
Check your understanding
1. Why can adding a persistence starter break a previously simple MVC application?
Show worked solution
It changes the classpath and may enable configurations needing a datasource, entities, and a transaction manager. Add it only for a deliberate persistence design and test the resulting context; do not randomly exclude failures just to recover a green startup.
2. Which version controls a Boot3.5 example when an unversioned docs page displays4.x?
Show worked solution
The pinned3.5 project and its resolved dependencies control the example. Use matching versioned references, verify changed APIs before upgrading, and distinguish documentation freshness from the supported baseline. A newer page does not make a4.x-only package available in3.5.
Key takeaways
- Boot conventions compose an application; domain contracts remain explicit.
- Pin Java and a coherent managed dependency train.
- A proposed fragment is not observed runtime evidence.