Spring Initializr & Project Setup
Spring Initializr is the official project generator for Spring Boot. You pick a build tool, a Java version and the features you need, and it gives you a ready-to-run project: build file, main class, test, configuration file and build wrapper, all set up to work together. It is the fastest and safest way to start a Spring Boot project, because the versions it picks are known to be compatible.
This tutorial explains how Spring Initializr works and what each option means: build tool, Spring Boot version, Java version, packaging and dependencies. It shows how to generate a project from the website, your IDE or the command line, and walks through every file you get. You'll then turn the generated project into a small product catalog API on Spring Boot 4.1, run and package it with Maven or Gradle, and fix the setup mistakes that most often stop a new project from starting.
1. What Is Spring Initializr?
Spring Initializr is a web service, run by the Spring team at start.spring.io, that generates the skeleton of a Spring Boot project. It doesn't write your business code. It does the error-prone setup work instead:
- creates a
pom.xmlorbuild.gradlewith the Spring Boot plugin and the right starters, which are dependencies that bundle everything one feature needs, such asspring-boot-starter-webmvcfor a web API; - adds a build wrapper (
mvnworgradlew), a script that downloads the correct Maven or Gradle version, so nobody needs to install a build tool; - creates the main application class, a first test and
application.properties, in the package you chose.
If you are new to Spring Boot itself, start with the Spring Boot introduction first.
2. Three Ways to Use Spring Initializr
| Way | How | Best for |
|---|---|---|
| Website | Open start.spring.io, choose the options, click Generate and unzip the download | Learning, and seeing every option at once |
| IDE | IntelliJ IDEA (New Project, then Spring Boot), VS Code with the Spring Boot Extension Pack, or Eclipse with Spring Tools | Creating and opening the project in one step |
| Command line / API | curl https://start.spring.io/starter.zip -d ... | Scripts, templates and repeatable setups |
All three call the same service, so they produce the same project. This is the command used for the example in this tutorial:
curl https://start.spring.io/starter.zip \
-d type=maven-project -d language=java \
-d bootVersion=4.1.2 -d javaVersion=21 \
-d groupId=com.javabytechie -d artifactId=catalog-service -d name=catalog-service \
-d description="Product catalog service" \
-d packageName=com.javabytechie.catalog -d packaging=jar \
-d dependencies=web,validation,actuator,devtools \
-o catalog-service.zip
unzip catalog-service.zip -d catalog-service
Without baseDir, the files are placed directly at the top level of the zip, with no folder around them. Add -d baseDir=catalog-service if you want one.
3. How Spring Initializr Generates a Project
The service keeps metadata: the list of supported Spring Boot and Java versions, every dependency and which starter it maps to. The website and IDEs read this metadata to build their forms. When you generate, the service resolves your choices for the selected Boot version, adds matching test dependencies, renders the build file and source templates, and streams back a zip. Because the mapping is versioned, the same checkbox can produce different starters for different Boot versions, as the version note in section 5 shows.
4. Choosing the Project Options
| Option | Default on start.spring.io | Recommendation |
|---|---|---|
| Project (build tool) | Gradle - Groovy | Whatever your team uses; Maven if you have no preference (section 4.1) |
| Language | Java | Java, unless your team writes Kotlin |
| Spring Boot | Latest stable release (4.1.2 at the time of writing) | Keep the default; avoid SNAPSHOT and RC versions |
| Group | com.example | Your organisation's reversed domain, e.g. com.javabytechie |
| Artifact | demo | A short, lower-case name with hyphens, e.g. catalog-service |
| Package name | Group + artifact | Check it: a hyphen in the artifact becomes an underscore (com.javabytechie.catalog_service), so set a clean name yourself, e.g. com.javabytechie.catalog |
| Packaging | Jar | Jar (section 4.3) |
| Configuration | Properties | Properties or YAML; see application.properties vs YAML |
| Java | 17 | The newest LTS version your servers run: 21 or 25 (section 4.2) |
4.1 Maven vs Gradle
| Maven | Gradle | |
|---|---|---|
| Build file | pom.xml (XML) | build.gradle (Groovy) or build.gradle.kts (Kotlin) |
| Style | Declarative and very uniform | Scriptable and flexible |
| Speed | Good | Faster on large projects, thanks to incremental builds and the build cache |
| Run the app | ./mvnw spring-boot:run | ./gradlew bootRun |
| Build the jar | ./mvnw package → target/ | ./gradlew build → build/libs/ |
The same choices produce this build.gradle when you pick Gradle. DevTools uses Gradle's developmentOnly configuration, the equivalent of Maven's optional runtime dependency:
plugins {
id 'java'
id 'org.springframework.boot' version '4.1.2'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'com.javabytechie'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
testImplementation 'org.springframework.boot:spring-boot-starter-actuator-test'
testImplementation 'org.springframework.boot:spring-boot-starter-validation-test'
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
4.2 Picking the Java Version
Spring Boot 4 needs Java 17 or later, and Initializr offers 17, 21, 25 and 27. Choose a long-term support (LTS) release, such as 21 or 25, that is installed both on your machine and on your servers. The choice ends up as <java.version> in Maven or a toolchain in Gradle. If it is newer than the JDK that runs the build, compilation fails (section 8.2).
4.3 Jar or War Packaging
A jar contains your app together with an embedded web server (Tomcat by default), so it runs anywhere with java -jar. That fits containers and cloud platforms. Choose war only if the app must be deployed into an existing external servlet container. Initializr then adds a ServletInitializer class for you.
4.4 Choosing Dependencies
Add only what you need now. You can always add starters to the build file later. The example uses four:
| Initializr name (id) | Starter added | Gives you |
|---|---|---|
Spring Web (web) | spring-boot-starter-webmvc | Spring MVC, JSON and embedded Tomcat |
Validation (validation) | spring-boot-starter-validation | Jakarta Bean Validation (@NotBlank, @Valid) |
Spring Boot Actuator (actuator) | spring-boot-starter-actuator | Health and info endpoints |
Spring Boot DevTools (devtools) | spring-boot-devtools | Automatic restart while developing |
5. What's Inside a Generated Spring Boot Project
catalog-service/
├── .gitattributes
├── .gitignore
├── .mvn/
│ └── wrapper/
│ └── maven-wrapper.properties
├── HELP.md
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src/
├── main/
│ ├── java/com/javabytechie/catalog/
│ │ └── CatalogServiceApplication.java
│ └── resources/
│ └── application.properties
└── test/
└── java/com/javabytechie/catalog/
└── CatalogServiceApplicationTests.java
| File | Purpose |
|---|---|
pom.xml | Build file: inherits versions from spring-boot-starter-parent, lists the starters, and adds the Spring Boot Maven plugin, which builds the runnable jar |
mvnw, mvnw.cmd, .mvn/wrapper/ | Maven Wrapper: downloads the pinned Maven version on first use |
CatalogServiceApplication.java | Entry point; its package is the root of component scanning |
application.properties | Configuration; starts with only the application name |
CatalogServiceApplicationTests.java | A test that checks the application context starts |
.gitignore, .gitattributes | Ready-made Git settings: ignore target/ and IDE files, fix line endings for the wrapper scripts |
HELP.md | Links to the documentation for each chosen dependency (ignored by Git) |
The generated build file and classes, unchanged:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.javabytechie</groupId>
<artifactId>catalog-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>catalog-service</name>
<description>Product catalog service</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.javabytechie.catalog;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class CatalogServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CatalogServiceApplication.class, args);
}
}
package com.javabytechie.catalog;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class CatalogServiceApplicationTests {
@Test
void contextLoads() {
}
}
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.10.0/apache-maven-3.10.0-bin.zip
@SpringBootApplication turns on component scanning and auto-configuration. The empty <url/>, <licenses> and <scm> elements are deliberate placeholders. They stop those values from being inherited from Spring Boot's parent POM, and you can fill them in or delete them.
spring-boot-starter-webmvc (it was spring-boot-starter-web in Spring Boot 3.x). Each starter also gets a matching test starter, such as spring-boot-starter-webmvc-test, instead of the single spring-boot-starter-test that 3.x projects had. The Maven Wrapper is now script-only (distributionType=only-script), so there is no maven-wrapper.jar to commit.6. A Complete Example: From Generated Project to Product API
Starting from the generated project, add a product sub-package with a small in-memory product API. Keep new packages below com.javabytechie.catalog, so component scanning finds them. Requests are checked with Bean Validation, invalid input returns 400, and an unknown SKU returns 404, both as ProblemDetail responses.
6.1 The Product Feature
package com.javabytechie.catalog.product;
import java.net.URI;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import jakarta.validation.Valid;
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductService productService;
public ProductController(ProductService productService) {
this.productService = productService;
}
@PostMapping
public ResponseEntity<Product> create(@Valid @RequestBody CreateProductRequest request) {
Product product = productService.create(request);
return ResponseEntity.created(URI.create("/api/products/" + product.sku())).body(product);
}
@GetMapping("/{sku}")
public Product findBySku(@PathVariable String sku) {
return productService.findBySku(sku);
}
@GetMapping
public List<Product> findAll() {
return productService.findAll();
}
@ExceptionHandler(ProductNotFoundException.class)
public ProblemDetail notFound(ProductNotFoundException ex) {
return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage());
}
}
package com.javabytechie.catalog.product;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class ProductService {
private static final Logger log = LoggerFactory.getLogger(ProductService.class);
// In memory to keep the first project small; a later step would add a database
private final Map<String, Product> products = new ConcurrentHashMap<>();
public Product create(CreateProductRequest request) {
Product product = new Product(request.sku(), request.name(), request.price());
products.put(product.sku(), product);
log.info("Created product {}", product.sku());
return product;
}
public Product findBySku(String sku) {
Product product = products.get(sku);
if (product == null) {
throw new ProductNotFoundException(sku);
}
return product;
}
public List<Product> findAll() {
return products.values().stream()
.sorted(Comparator.comparing(Product::sku))
.toList();
}
}
package com.javabytechie.catalog.product;
import java.math.BigDecimal;
public record Product(String sku, String name, BigDecimal price) {
}
package com.javabytechie.catalog.product;
import java.math.BigDecimal;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
public record CreateProductRequest(
@NotBlank @Pattern(regexp = "[A-Z]{2,4}-\\d{3}") String sku,
@NotBlank String name,
@NotNull @DecimalMin("0.01") BigDecimal price) {
}
package com.javabytechie.catalog.product;
public class ProductNotFoundException extends RuntimeException {
public ProductNotFoundException(String sku) {
super("Product not found: " + sku);
}
}
6.2 Configuration
Extend the generated application.properties. Problem details make validation errors return a structured 400, and two Actuator endpoints are exposed:
spring.application.name=catalog-service
# Return validation and other MVC errors as RFC 9457 problem details
spring.mvc.problemdetails.enabled=true
# Expose health and info over HTTP
management.endpoints.web.exposure.include=health,info
management.info.env.enabled=true
info.app.description=Product catalog service
The validation tutorial shows how to return field-level messages instead of the generic "Invalid request content."
6.3 A Test for the API
@WebMvcTest comes from the spring-boot-starter-webmvc-test dependency that Initializr already added. MockMvcTester gives AssertJ-style assertions. Each test checks the stored products before and after the request:
package com.javabytechie.catalog.product;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
@WebMvcTest(ProductController.class)
@Import(ProductService.class)
class ProductControllerTest {
@Autowired
MockMvcTester mvc;
@Autowired
ProductService productService;
@Test
void createThenFetchProduct() {
assertThat(productService.findAll()).isEmpty();
assertThat(mvc.post().uri("/api/products").contentType(MediaType.APPLICATION_JSON)
.content("""
{"sku":"KB-100","name":"Mechanical Keyboard","price":89.00}"""))
.hasStatus(HttpStatus.CREATED)
.hasHeader("Location", "/api/products/KB-100");
assertThat(mvc.get().uri("/api/products/KB-100"))
.hasStatusOk()
.bodyJson().extractingPath("$.name").isEqualTo("Mechanical Keyboard");
assertThat(productService.findAll()).hasSize(1);
}
@Test
void invalidProductIsRejectedAndNotStored() {
assertThat(mvc.post().uri("/api/products").contentType(MediaType.APPLICATION_JSON)
.content("""
{"sku":"keyboard","name":"","price":0}"""))
.hasStatus(HttpStatus.BAD_REQUEST);
assertThat(productService.findAll()).isEmpty();
}
@Test
void unknownProductReturns404() {
assertThat(mvc.get().uri("/api/products/XX-999"))
.hasStatus(HttpStatus.NOT_FOUND)
.bodyJson().extractingPath("$.detail").isEqualTo("Product not found: XX-999");
}
}
7. Running, Testing and Packaging the Project
Start the app with the wrapper. With DevTools on the classpath, the log confirms it is active, and the app restarts whenever you recompile:
INFO c.j.catalog.CatalogServiceApplication : Starting CatalogServiceApplication using Java 21.0.7
INFO .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
INFO o.s.b.a.e.web.EndpointLinksResolver : Exposing 2 endpoints beneath base path '/actuator'
INFO o.s.boot.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
INFO c.j.catalog.CatalogServiceApplication : Started CatalogServiceApplication in 0.582 seconds (process running for 0.7)
Try the API:
$ curl -s -i -X POST localhost:8080/api/products -H 'Content-Type: application/json' \
-d '{"sku":"KB-100","name":"Mechanical Keyboard","price":89.00}'
HTTP/1.1 201
Location: /api/products/KB-100
{"sku":"KB-100","name":"Mechanical Keyboard","price":89.00}
$ curl -s localhost:8080/api/products
[{"sku":"KB-100","name":"Mechanical Keyboard","price":89.00},{"sku":"MS-200","name":"Wireless Mouse","price":25.50}]
$ curl -s -i -X POST localhost:8080/api/products -H 'Content-Type: application/json' \
-d '{"sku":"keyboard","name":"","price":0}'
HTTP/1.1 400
{"detail":"Invalid request content.","instance":"/api/products","status":400,"title":"Bad Request"}
$ curl -s -i localhost:8080/api/products/XX-999
HTTP/1.1 404
{"detail":"Product not found: XX-999","instance":"/api/products/XX-999","status":404,"title":"Not Found"}
$ curl -s localhost:8080/actuator/health
{"groups":["liveness","readiness"],"status":"UP"}
$ curl -s localhost:8080/actuator/info
{"app":{"description":"Product catalog service"}}
Run the tests and build the runnable jar with ./mvnw package (Gradle: ./gradlew build), then start it like any Java program:
$ ./mvnw package
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 -- in com.javabytechie.catalog.CatalogServiceApplicationTests
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 -- in com.javabytechie.catalog.product.ProductControllerTest
[INFO] --- spring-boot:4.1.2:repackage (repackage) @ catalog-service ---
[INFO] BUILD SUCCESS
$ java -jar target/catalog-service-0.0.1-SNAPSHOT.jar
The jar is about 24 MB because it contains every dependency and Tomcat. DevTools is automatically left out of it, so production never runs with development settings. Gradle also writes a second -plain.jar to build/libs that holds only your classes. Deploy the one without -plain. The DevTools tutorial covers restarts and LiveReload.
8. Common Setup Problems and How to Fix Them
8.1 "Port 8080 Was Already in Use"
Another program, often a second copy of your own app, already listens on the port:
***************************
APPLICATION FAILED TO START
***************************
Description:
Web server failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
How to fix it: stop the other process (lsof -i :8080 on macOS and Linux shows it) or choose another port with server.port=8081.
8.2 "Release Version 25 Not Supported"
The project was generated for a newer Java than the JDK that runs the build. Here a project set to Java 25 was built with JDK 21:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.15.0:compile (default-compile) on project catalog-service: Fatal error compiling: error: release version 25 not supported
How to fix it: install the matching JDK and point JAVA_HOME (and your IDE's project SDK) at it, or lower <java.version> to the version you have.
8.3 404 "No Static Resource" for Your Controller
The controller was placed in com.javabytechie.product, a sibling of the main class's package rather than below it. Component scanning never found it, so Spring treated the URL as a static file:
$ curl -s -i localhost:8080/api/products
HTTP/1.1 404
{"detail":"No static resource api/products.","instance":"/api/products","status":404,"title":"Not Found"}
How to fix it: move the class below the main package, as in Figure 2, or leave the main class in the package that Initializr created and don't move it deeper.
8.4 The App Starts and Immediately Exits
Without a web starter there is no web server to keep the JVM running. The log shows "Started CatalogServiceApplication" and the process exits with code 0. How to fix it: add Spring Web (spring-boot-starter-webmvc) if you meant to build a web app. For command-line jobs, exiting is the correct behaviour.
8.5 The IDE Shows Red Imports
The project was opened as a plain folder, or the IDE hasn't finished downloading dependencies. How to fix it: open the folder that contains pom.xml or build.gradle (not a parent folder), import it as a Maven or Gradle project, and wait for the first sync. Using the wrapper the first time downloads the build tool, about a minute on a normal connection.
9. Best Practices
- Start every project from Spring Initializr instead of copying an old project, so you get current, compatible versions.
- Use the latest stable Spring Boot version, never a
SNAPSHOTor release candidate, for real work. - Choose an LTS Java version that your servers actually run.
- Set the package name yourself and keep all code below it.
- Leave the main class where Initializr put it, at the root of your package tree.
- Commit the wrapper scripts and always build with
./mvnwor./gradlew, so everyone uses the same build tool version. - Add dependencies only when you need them; every starter adds auto-configuration and startup work.
- Keep the generated test; it is the cheapest check that the application still starts.
- Script repeatable setups with the
curlAPI, and save the command alongside your templates.
10. Summary
Spring Initializr creates a working Spring Boot project in seconds, from the website, your IDE or a single curl command. Choose a build tool, the latest stable Spring Boot version, an LTS Java version that matches your JDK, jar packaging, a clear package name and only the starters you need. The generated project contains a build file, a wrapper, a main class whose package roots component scanning, a configuration file and a first test. From there, add features in sub-packages, run with ./mvnw spring-boot:run or ./gradlew bootRun, and package a runnable jar with ./mvnw package. The main recommendation: let Spring Initializr choose compatible versions, keep your code below the main class's package, and always build with the wrapper.
Frequently Asked Questions (FAQ)
Q1. What is start.spring.io?
It is the public Spring Initializr service, run by the Spring team. It generates Spring Boot projects with compatible versions of Spring Boot, its starters and the build plugin. IDEs such as IntelliJ IDEA, VS Code and Eclipse use the same service behind their "new Spring Boot project" wizards.
Q2. Should I choose Maven or Gradle for Spring Boot?
Both are fully supported, and Spring Boot works the same way with either. Choose the one your team already knows. Maven is very predictable and common in enterprise projects, while Gradle builds large multi-module projects faster and allows scripting.
Q3. Which Java version should I select in Spring Initializr?
Choose the newest long-term support (LTS) version that your machines and servers have installed, currently 21 or 25. Spring Boot 4 requires at least Java 17. The JDK that runs the build must be at least as new as the version you select.
Q4. Can I add dependencies after generating the project?
Yes. Add the starter to pom.xml or build.gradle without a version, because the Spring Boot parent or plugin manages it. You can also use the Explore button on start.spring.io with the new selection to see exactly which lines to add.
Q5. What is the difference between Group, Artifact, Name and Package name?
Group and Artifact identify the build output, like com.javabytechie:catalog-service. Name is the display name and is used for the main class name, such as CatalogServiceApplication. Package name is the Java package for your code; set it explicitly because hyphens in the artifact turn into underscores.
Q6. Why are there mvnw and mvnw.cmd files in my project?
They are the Maven Wrapper: scripts that download and run the Maven version pinned in .mvn/wrapper/maven-wrapper.properties. Use ./mvnw on macOS and Linux and mvnw.cmd on Windows so every developer and CI server builds with the same Maven. Commit them to Git.
Q7. Why does my generated project have several test starters?
Since Spring Boot 4, each starter has a matching test starter, such as spring-boot-starter-webmvc-test for web tests, and Initializr adds one for each selected dependency. Spring Boot 3.x projects instead had a single spring-boot-starter-test.
Q8. Can I use Spring Initializr without internet access?
The public site needs internet access. Companies that need an internal version can run their own Initializr instance, since the project is open source and can be customised with company defaults and dependencies. Once generated, building still needs access to a Maven repository for the dependencies.