From 73334c01f30272a2de001b2a7d308a8c6a6f8627 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:21:16 +0200 Subject: [PATCH 01/35] Add Wicket Spring Boot Starter with examples and documentation --- pom.xml | 2 + wicket-spring-boot-starter-parent/README.md | 174 ++++++++++++++++++ wicket-spring-boot-starter-parent/pom.xml | 29 +++ .../pom.xml | 52 ++++++ .../starter/example/ExampleApplication.java | 15 ++ .../springboot/starter/example/HomePage.java | 20 ++ .../starter/example/SpringService.java | 14 ++ .../starter/example/WicketApplication.java | 22 +++ .../src/main/resources/application.properties | 7 + .../springboot/starter/example/HomePage.html | 20 ++ .../example/ExampleApplicationTest.java | 23 +++ .../wicket-spring-boot-starter/pom.xml | 71 +++++++ .../starter/WicketAutoConfiguration.java | 95 ++++++++++ .../springboot/starter/WicketProperties.java | 96 ++++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + 15 files changed, 641 insertions(+) create mode 100644 wicket-spring-boot-starter-parent/README.md create mode 100644 wicket-spring-boot-starter-parent/pom.xml create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/HomePage.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/SpringService.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/WicketApplication.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/application.properties create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/org/wicketstuff/springboot/starter/example/HomePage.html create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/pom.xml b/pom.xml index 05b4be926b..cd467ba95d 100644 --- a/pom.xml +++ b/pom.xml @@ -172,6 +172,7 @@ wicketstuff-servlet3-examples wicketstuff-clipboardjs-examples wicketstuff-springreference-examples + wicket-spring-boot-starter-examples jasperreports-examples editable-grid-examples wicketstuff-sitemap-xml-examples @@ -463,6 +464,7 @@ wicket-servlet3-parent wicketstuff-clipboard-js-parent wicketstuff-springreference-parent + wicket-spring-boot-starter-parent wicket-security-parent yui-parent diff --git a/wicket-spring-boot-starter-parent/README.md b/wicket-spring-boot-starter-parent/README.md new file mode 100644 index 0000000000..13fe4c6b4d --- /dev/null +++ b/wicket-spring-boot-starter-parent/README.md @@ -0,0 +1,174 @@ +# Wicket Spring Boot Starter + +A lightweight, zero-boilerplate starter that integrates **Apache Wicket 10.x** with **Spring Boot 4.x**. It configures the Wicket web context automatically, bridges Spring injection into Wicket components, and enables simple configuration via `application.properties` or `application.yml`. + +--- + +## Features + +- **Auto-Configuration**: Automatically registers Wicket's `WicketFilter` in Spring Boot's embedded servlet container. +- **Auto-Discovery**: Detects any subclass of Wicket's `WebApplication` registered as a Spring bean/component and binds it. +- **Spring Injection Support**: Automatically adds `SpringComponentInjector` to the application, allowing you to use `@SpringBean` to inject Spring-managed components directly into Wicket Pages and Panels. +- **Externalized Settings**: Configure Wicket's execution mode (`DEVELOPMENT` vs `DEPLOYMENT`), filter paths, and filter names directly from Spring properties. +- **IDE Auto-Completion Support**: Ships with built-in configuration metadata, enabling auto-completion and documentation tooltips for Wicket properties in popular IDEs (IntelliJ, Eclipse, VS Code). + +--- + +## Dependency Configuration + +To use the starter, add the following dependency to your Maven `pom.xml`: + +```xml + + org.wicketstuff + wicket-spring-boot-starter + ${wicketstuff.version} + +``` + +--- + +## Compatibility Matrix + +Ensure you match the correct starter version with your Spring Boot and Java environment: + +| WicketStuff / Starter Version | Spring Boot Version | Spring Framework Version | Minimum Java Version | +| :--- | :--- | :--- | :--- | +| **`10.x.y`** (Current) | `4.x.y` | `7.x.y` | Java 17 | +| **`9.x.y`** | `3.x.y` | `6.x.y` | Java 11 | + +--- + +## Quickstart + +### 1. Create a Wicket Application Component +Subclass `WebApplication` and register it as a Spring bean using `@Component`: + +```java +package com.example; + +import org.apache.wicket.Page; +import org.apache.wicket.protocol.http.WebApplication; +import org.springframework.stereotype.Component; + +@Component +public class WicketApplication extends WebApplication { + + @Override + public Class getHomePage() { + return HomePage.class; + } + + @Override + protected void init() { + super.init(); + // Additional custom Wicket configurations... + } +} +``` + +### 2. Inject Spring Beans into Pages +Use Wicket's standard `@SpringBean` annotation to inject Spring-managed services: + +```java +package com.example; + +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.spring.injection.annot.SpringBean; + +public class HomePage extends WebPage { + private static final long serialVersionUID = 1L; + + @SpringBean + private MySpringService mySpringService; + + public HomePage() { + add(new Label("message", mySpringService.sayHello())); + } +} +``` + +### 3. Bootstrap your Spring Boot App +Annotate your entry point with `@SpringBootApplication` and run it: + +```java +package com.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(ExampleApplication.class, args); + } +} +``` + +--- + +## Configuration Properties + +The following properties can be configured in your `application.properties` or `application.yml` file: + +| Property | Default Value | Description | +|---|---|---| +| `wicket.filter-path` | `/*` | URL mapping pattern for the Wicket filter. | +| `wicket.filter-name` | `wicket-filter` | The name of the registered Wicket servlet filter. | +| `wicket.configuration` | `DEVELOPMENT` | The configuration type: `DEVELOPMENT` or `DEPLOYMENT`. | + +For example: +```properties +wicket.configuration=DEPLOYMENT +wicket.filter-path=/app/* +wicket.filter-name=my-custom-wicket-filter +``` + +--- + +## Spring Initializr Metadata Registration + +If you are requesting this starter to be listed on `start.spring.io` (or registering it in an internal Initializr instance), configure the dependency metadata as follows: + +### YAML Configuration (e.g. `application.yml`) +```yaml +initializr: + dependencies: + - name: Web + content: + - name: Wicket + id: wicket + description: Apache Wicket component-oriented web application framework integrated with Spring Boot. + groupId: org.wicketstuff + artifactId: wicket-spring-boot-starter + versionRange: "[4.0.0,4.1.0-M1)" + links: + - rel: reference + href: https://github.com/wicketstuff/core/tree/master/wicket-spring-boot-starter-parent + - rel: guide + href: https://wicket.apache.org/start/quickstart.html +``` + +### JSON Metadata API Representation +```json +{ + "name": "Wicket", + "id": "wicket", + "description": "Apache Wicket component-oriented web application framework integrated with Spring Boot.", + "groupId": "org.wicketstuff", + "artifactId": "wicket-spring-boot-starter", + "versionRange": "[4.0.0,4.1.0-M1)", + "links": [ + { + "rel": "reference", + "href": "https://github.com/wicketstuff/core/tree/master/wicket-spring-boot-starter-parent" + }, + { + "rel": "guide", + "href": "https://wicket.apache.org/start/quickstart.html" + } + ] +} +``` diff --git a/wicket-spring-boot-starter-parent/pom.xml b/wicket-spring-boot-starter-parent/pom.xml new file mode 100644 index 0000000000..9b573b6df9 --- /dev/null +++ b/wicket-spring-boot-starter-parent/pom.xml @@ -0,0 +1,29 @@ + + + + 4.0.0 + + + org.wicketstuff + wicketstuff-core + 10.10.0-SNAPSHOT + + + wicket-spring-boot-starter-parent + pom + + Wicket Spring Boot Starter - Parent + + Parent project for Wicket Spring Boot Starter module and its example application. + + + + 4.0.6 + + + + wicket-spring-boot-starter + wicket-spring-boot-starter-examples + + diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml new file mode 100644 index 0000000000..4fc9daa041 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml @@ -0,0 +1,52 @@ + + + + 4.0.0 + + + org.wicketstuff + wicket-spring-boot-starter-parent + 10.10.0-SNAPSHOT + ../pom.xml + + + wicket-spring-boot-starter-examples + jar + + Wicket Spring Boot Starter - Examples + + Example application demonstrating the use of Wicket Spring Boot Starter. + + + + + + org.wicketstuff + wicket-spring-boot-starter + ${project.version} + + + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot.version} + + + + + org.springframework.boot + spring-boot-starter-logging + ${spring-boot.version} + + + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + test + + + diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java new file mode 100644 index 0000000000..9f15884332 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java @@ -0,0 +1,15 @@ +package org.wicketstuff.springboot.starter.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Spring Boot main application class. + */ +@SpringBootApplication +public class ExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(ExampleApplication.class, args); + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/HomePage.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/HomePage.java new file mode 100644 index 0000000000..a49ea11fd9 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/HomePage.java @@ -0,0 +1,20 @@ +package org.wicketstuff.springboot.starter.example; + +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.spring.injection.annot.SpringBean; + +/** + * Example Home Page. + */ +public class HomePage extends WebPage { + private static final long serialVersionUID = 1L; + + @SpringBean + private SpringService springService; + + public HomePage() { + add(new Label("message", "Welcome to Wicket + Spring Boot!")); + add(new Label("springMessage", springService.getMessage())); + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/SpringService.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/SpringService.java new file mode 100644 index 0000000000..18fd857aa0 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/SpringService.java @@ -0,0 +1,14 @@ +package org.wicketstuff.springboot.starter.example; + +import org.springframework.stereotype.Service; + +/** + * A simple Spring-managed service. + */ +@Service +public class SpringService { + + public String getMessage() { + return "Hello from Spring Service injection!"; + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/WicketApplication.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/WicketApplication.java new file mode 100644 index 0000000000..8835e9226e --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/WicketApplication.java @@ -0,0 +1,22 @@ +package org.wicketstuff.springboot.starter.example; + +import org.apache.wicket.Page; +import org.apache.wicket.protocol.http.WebApplication; +import org.springframework.stereotype.Component; + +/** + * The Wicket WebApplication registered as a Spring Component. + */ +@Component +public class WicketApplication extends WebApplication { + + @Override + public Class getHomePage() { + return HomePage.class; + } + + @Override + public void init() { + super.init(); + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/application.properties b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/application.properties new file mode 100644 index 0000000000..9d9ffbaf8b --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/application.properties @@ -0,0 +1,7 @@ +# Custom Wicket settings configured via properties +wicket.configuration=DEVELOPMENT +wicket.filter-path=/* +wicket.filter-name=wicket-example-filter + +# Disable banner for cleaner startup logs +spring.main.banner-mode=off diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/org/wicketstuff/springboot/starter/example/HomePage.html b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/org/wicketstuff/springboot/starter/example/HomePage.html new file mode 100644 index 0000000000..d1a93a112f --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/org/wicketstuff/springboot/starter/example/HomePage.html @@ -0,0 +1,20 @@ + + + + + Wicket Spring Boot Example + + + +
+

Wicket Starter Example

+
Message goes here.
+
Spring service message goes here.
+
+ + diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java new file mode 100644 index 0000000000..81739c25bc --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java @@ -0,0 +1,23 @@ +package org.wicketstuff.springboot.starter.example; + +import org.apache.wicket.protocol.http.WebApplication; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * Basic Spring Boot context integration test. + */ +@SpringBootTest +public class ExampleApplicationTest { + + @Autowired + private WebApplication webApplication; + + @Test + public void contextLoads() { + assertNotNull(webApplication); + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml new file mode 100644 index 0000000000..22231a151e --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml @@ -0,0 +1,71 @@ + + + + 4.0.0 + + + org.wicketstuff + wicket-spring-boot-starter-parent + 10.10.0-SNAPSHOT + ../pom.xml + + + wicket-spring-boot-starter + jar + + Wicket Spring Boot Starter + + Lightweight auto-configuration and integration starter for Apache Wicket and Spring Boot. + + + + + + org.apache.wicket + wicket-core + + + org.apache.wicket + wicket-spring + + + org.springframework + spring-core + + + org.springframework + spring-beans + + + org.springframework + spring-context + + + org.springframework + spring-web + + + + + + + org.springframework.boot + spring-boot-autoconfigure + ${spring-boot.version} + + + org.springframework.boot + spring-boot-configuration-processor + ${spring-boot.version} + true + + + + + jakarta.servlet + jakarta.servlet-api + provided + + + diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java new file mode 100644 index 0000000000..da0d717077 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -0,0 +1,95 @@ +package org.wicketstuff.springboot.starter; + +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import org.apache.wicket.RuntimeConfigurationType; +import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.protocol.http.WicketFilter; +import org.apache.wicket.spring.injection.annot.SpringComponentInjector; +import org.jspecify.annotations.NonNull; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; + +/** + * Spring Boot auto-configuration for Apache Wicket. + *

+ * This auto-configuration is activated when Wicket's core classes are present on the classpath. + * It registers Wicket's {@link WicketFilter} into the embedded servlet container and binds the + * registered {@link WebApplication} bean. Additionally, it registers the {@link SpringComponentInjector} + * to enable Spring bean injection (via {@link org.apache.wicket.spring.injection.annot.SpringBean}) + * inside Wicket pages and components. + *

+ * + * @author WicketStuff + */ +@AutoConfiguration +@ConditionalOnClass({WebApplication.class, WicketFilter.class}) +@EnableConfigurationProperties(WicketProperties.class) +public class WicketAutoConfiguration { + + /** + * Creates and configures the {@link FilterRegistrationBean} for the {@link WicketFilter}. + *

+ * Instantiates WicketFilter with the provided {@link WebApplication} bean and attaches + * a {@link SpringComponentInjector} during filter initialization to enable Spring bean injection. + *

+ * + * @param webApplication the auto-discovered Wicket WebApplication subclass bean + * @param properties the externalized Wicket properties + * @param applicationContext the Spring application context + * @return the configured FilterRegistrationBean for WicketFilter + */ + @Bean + @ConditionalOnMissingBean(WicketFilter.class) + public FilterRegistrationBean wicketFilterRegistration( + WebApplication webApplication, + WicketProperties properties, + ApplicationContext applicationContext) { + + WicketFilter filter = new WicketFilter(webApplication) { + @Override + public void init(boolean isServlet, FilterConfig filterConfig) throws ServletException { + super.init(isServlet, filterConfig); + // Register SpringComponentInjector so Wicket pages can inject Spring @Components / @Beans using @SpringBean. + webApplication.getComponentInstantiationListeners().add( + new SpringComponentInjector(webApplication, applicationContext) + ); + } + }; + + return configureWicketFilter(properties, filter); + + } + + /** + * Configures a {@link FilterRegistrationBean} for a given {@link WicketFilter}. + * Sets up the filter mapping path, filter name, and configuration type for Wicket. + * + * @param properties the {@link WicketProperties} containing configuration details such as filter path, + * filter name, and runtime configuration type + * @param filter the {@link WicketFilter} to be configured and registered + * @return a configured {@link FilterRegistrationBean} instance for the provided {@link WicketFilter} + */ + private static @NonNull FilterRegistrationBean configureWicketFilter( + WicketProperties properties, WicketFilter filter) { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + registration.setFilter(filter); + registration.addUrlPatterns(properties.getFilterPath()); + registration.setName(properties.getFilterName()); + + // Specify configuration parameter mapping for Wicket + registration.addInitParameter(WicketFilter.FILTER_MAPPING_PARAM, properties.getFilterPath()); + + RuntimeConfigurationType configType = properties.getConfiguration(); + if (configType == null) { + configType = RuntimeConfigurationType.DEVELOPMENT; + } + registration.addInitParameter("configuration", configType.name()); + return registration; + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java new file mode 100644 index 0000000000..9ac006f422 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java @@ -0,0 +1,96 @@ +package org.wicketstuff.springboot.starter; + +import org.apache.wicket.RuntimeConfigurationType; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Configuration properties for Apache Wicket integration in Spring Boot. + *

+ * These properties can be customized in application configuration files (e.g., {@code application.properties} + * or {@code application.yml}) under the {@code wicket} prefix. + *

+ * + * @author WicketStuff + */ +@ConfigurationProperties(prefix = "wicket") +public class WicketProperties { + + /** + * URL mapping pattern for the Wicket Filter. + *

+ * Determines which incoming requests are processed by Wicket. Default is {@code "/*"}. + *

+ */ + private String filterPath = "/*"; + + /** + * Servlet name of the registered Wicket Filter. + *

+ * Helps identify the filter in registration logs and configuration contexts. Default is {@code "wicket-filter"}. + *

+ */ + private String filterName = "wicket-filter"; + + /** + * Wicket execution configuration type. + *

+ * Can be set to {@link RuntimeConfigurationType#DEVELOPMENT} or {@link RuntimeConfigurationType#DEPLOYMENT}. + * If not explicitly defined, it defaults to {@code DEVELOPMENT}. + *

+ */ + private RuntimeConfigurationType configuration; + + /** + * Gets the URL mapping pattern for the Wicket Filter. + * + * @return the filter URL mapping path pattern + */ + public String getFilterPath() { + return filterPath; + } + + /** + * Sets the URL mapping pattern for the Wicket Filter. + * + * @param filterPath the filter URL mapping path pattern to set + */ + public void setFilterPath(String filterPath) { + this.filterPath = filterPath; + } + + /** + * Gets the servlet name of the registered Wicket Filter. + * + * @return the servlet filter name + */ + public String getFilterName() { + return filterName; + } + + /** + * Sets the servlet name of the registered Wicket Filter. + * + * @param filterName the servlet filter name to set + */ + public void setFilterName(String filterName) { + this.filterName = filterName; + } + + /** + * Gets the Wicket execution configuration type. + * + * @return the configuration type, or {@code null} if not configured + */ + public RuntimeConfigurationType getConfiguration() { + return configuration; + } + + /** + * Sets the Wicket execution configuration type. + * + * @param configuration the configuration type to set (DEVELOPMENT or DEPLOYMENT) + */ + public void setConfiguration(RuntimeConfigurationType configuration) { + this.configuration = configuration; + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000000..564dc1ac5d --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.wicketstuff.springboot.starter.WicketAutoConfiguration From 56f919c96fcda457bc2c5440649e5a2b7e3bf349 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Tue, 9 Jun 2026 22:49:07 +0200 Subject: [PATCH 02/35] Add default `WebApplication` and `HomePage` for Wicket Spring Boot Starter --- .../example/DefaultWebApplicationTest.java | 35 +++ .../springboot/starter/DefaultHomePage.java | 14 + .../starter/DefaultWebApplication.java | 16 ++ .../starter/WicketAutoConfiguration.java | 12 + .../springboot/starter/DefaultHomePage.html | 250 ++++++++++++++++++ 5 files changed, 327 insertions(+) create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java new file mode 100644 index 0000000000..bbd09704fa --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java @@ -0,0 +1,35 @@ +package org.wicketstuff.springboot.starter.example; + +import org.apache.wicket.protocol.http.WebApplication; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; +import org.wicketstuff.springboot.starter.DefaultWebApplication; +import org.wicketstuff.springboot.starter.WicketAutoConfiguration; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Verifies that the starter auto-configures {@link DefaultWebApplication} + * when no custom {@link WebApplication} bean is present in the application context. + */ +@SpringBootTest(classes = DefaultWebApplicationTest.TestConfig.class) +public class DefaultWebApplicationTest { + + @Configuration + @ImportAutoConfiguration(WicketAutoConfiguration.class) + static class TestConfig { + } + + @Autowired + private WebApplication webApplication; + + @Test + public void testDefaultWebApplicationIsLoaded() { + assertNotNull(webApplication); + assertTrue(webApplication instanceof DefaultWebApplication); + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java new file mode 100644 index 0000000000..39d3ac464a --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java @@ -0,0 +1,14 @@ +package org.wicketstuff.springboot.starter; + +import org.apache.wicket.markup.html.WebPage; + +/** + * The default home page loaded by the Wicket Spring Boot Starter + * when no custom WebApplication bean is provided by the application. + */ +public class DefaultHomePage extends WebPage { + private static final long serialVersionUID = 1L; + + public DefaultHomePage() { + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java new file mode 100644 index 0000000000..3b59a014cc --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java @@ -0,0 +1,16 @@ +package org.wicketstuff.springboot.starter; + +import org.apache.wicket.Page; +import org.apache.wicket.protocol.http.WebApplication; + +/** + * The default {@link WebApplication} used by the Wicket Spring Boot Starter + * when the user does not provide their own custom implementation bean. + */ +public class DefaultWebApplication extends WebApplication { + + @Override + public Class getHomePage() { + return DefaultHomePage.class; + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index da0d717077..3a1636aaf8 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -32,6 +32,18 @@ @EnableConfigurationProperties(WicketProperties.class) public class WicketAutoConfiguration { + /** + * Registers a default {@link WebApplication} bean if the application does not define one. + * This registers the {@link DefaultWebApplication} which serves the starter's {@link DefaultHomePage}. + * + * @return the default WebApplication + */ + @Bean + @ConditionalOnMissingBean(WebApplication.class) + public WebApplication webApplication() { + return new DefaultWebApplication(); + } + /** * Creates and configures the {@link FilterRegistrationBean} for the {@link WicketFilter}. *

diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html new file mode 100644 index 0000000000..0d3fe7630a --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html @@ -0,0 +1,250 @@ + + + + + Wicket Spring Boot Starter + + + + + + +

+
+ W +
+

Apache Wicket + Spring Boot

+

Your application is up and running!

+ +
+
How to customize this application
+
    +
  1. +
    Create a custom Wicket WebPage:
    +
    package com.example;
    +
    +import org.apache.wicket.markup.html.WebPage;
    +import org.apache.wicket.markup.html.basic.Label;
    +
    +public class MyNewHomePage extends WebPage {
    +    public MyNewHomePage() {
    +        add(new Label("message", "Hello, Wicket!"));
    +    }
    +}
    +
  2. +
  3. +
    Create your custom WebApplication & register it as a Spring Bean:
    +
    package com.example;
    +
    +import org.apache.wicket.Page;
    +import org.apache.wicket.protocol.http.WebApplication;
    +import org.springframework.stereotype.Component;
    +
    +@Component
    +public class WicketApplication extends WebApplication {
    +    @Override
    +    public Class<? extends Page> getHomePage() {
    +        return MyNewHomePage.class;
    +    }
    +}
    +
  4. +
+
+ +

+ Once you register your own WebApplication component, this default starter page and the auto-configured application class will automatically deactivate. +

+ + Documentation + + +
+ + From 7497eda44ebc3be0e400d3f27ed40f3b776e6923 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Sat, 20 Jun 2026 20:09:10 +0200 Subject: [PATCH 03/35] Replace example application with a streamlined default starter, updated dependencies, and static resources integration --- wicket-spring-boot-starter-parent/README.md | 4 +- wicket-spring-boot-starter-parent/pom.xml | 2 +- .../springboot/starter/example/HomePage.java | 20 -- .../starter/example/SpringService.java | 14 - .../starter/example/WicketApplication.java | 22 -- .../springboot/starter/example/HomePage.html | 20 -- .../springboot/starter/DefaultHomePage.java | 2 + .../starter/DefaultWebApplication.java | 17 + .../springboot/starter/DefaultHomePage.html | 293 +++--------------- .../wicketstuff/springboot/starter/logo.png | Bin 0 -> 12244 bytes .../wicketstuff/springboot/starter/style.css | 68 ++++ 11 files changed, 141 insertions(+), 321 deletions(-) delete mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/HomePage.java delete mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/SpringService.java delete mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/WicketApplication.java delete mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/org/wicketstuff/springboot/starter/example/HomePage.html create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/logo.png create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css diff --git a/wicket-spring-boot-starter-parent/README.md b/wicket-spring-boot-starter-parent/README.md index 13fe4c6b4d..b66ba741fc 100644 --- a/wicket-spring-boot-starter-parent/README.md +++ b/wicket-spring-boot-starter-parent/README.md @@ -143,7 +143,7 @@ initializr: description: Apache Wicket component-oriented web application framework integrated with Spring Boot. groupId: org.wicketstuff artifactId: wicket-spring-boot-starter - versionRange: "[4.0.0,4.1.0-M1)" + versionRange: "[4.0.0,4.2.0-M1)" links: - rel: reference href: https://github.com/wicketstuff/core/tree/master/wicket-spring-boot-starter-parent @@ -159,7 +159,7 @@ initializr: "description": "Apache Wicket component-oriented web application framework integrated with Spring Boot.", "groupId": "org.wicketstuff", "artifactId": "wicket-spring-boot-starter", - "versionRange": "[4.0.0,4.1.0-M1)", + "versionRange": "[4.0.0,4.2.0-M1)", "links": [ { "rel": "reference", diff --git a/wicket-spring-boot-starter-parent/pom.xml b/wicket-spring-boot-starter-parent/pom.xml index 9b573b6df9..83bceed7c4 100644 --- a/wicket-spring-boot-starter-parent/pom.xml +++ b/wicket-spring-boot-starter-parent/pom.xml @@ -19,7 +19,7 @@ - 4.0.6 + 4.1.0 diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/HomePage.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/HomePage.java deleted file mode 100644 index a49ea11fd9..0000000000 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/HomePage.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.wicketstuff.springboot.starter.example; - -import org.apache.wicket.markup.html.WebPage; -import org.apache.wicket.markup.html.basic.Label; -import org.apache.wicket.spring.injection.annot.SpringBean; - -/** - * Example Home Page. - */ -public class HomePage extends WebPage { - private static final long serialVersionUID = 1L; - - @SpringBean - private SpringService springService; - - public HomePage() { - add(new Label("message", "Welcome to Wicket + Spring Boot!")); - add(new Label("springMessage", springService.getMessage())); - } -} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/SpringService.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/SpringService.java deleted file mode 100644 index 18fd857aa0..0000000000 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/SpringService.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.wicketstuff.springboot.starter.example; - -import org.springframework.stereotype.Service; - -/** - * A simple Spring-managed service. - */ -@Service -public class SpringService { - - public String getMessage() { - return "Hello from Spring Service injection!"; - } -} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/WicketApplication.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/WicketApplication.java deleted file mode 100644 index 8835e9226e..0000000000 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/WicketApplication.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.wicketstuff.springboot.starter.example; - -import org.apache.wicket.Page; -import org.apache.wicket.protocol.http.WebApplication; -import org.springframework.stereotype.Component; - -/** - * The Wicket WebApplication registered as a Spring Component. - */ -@Component -public class WicketApplication extends WebApplication { - - @Override - public Class getHomePage() { - return HomePage.class; - } - - @Override - public void init() { - super.init(); - } -} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/org/wicketstuff/springboot/starter/example/HomePage.html b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/org/wicketstuff/springboot/starter/example/HomePage.html deleted file mode 100644 index d1a93a112f..0000000000 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/org/wicketstuff/springboot/starter/example/HomePage.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Wicket Spring Boot Example - - - -
-

Wicket Starter Example

-
Message goes here.
-
Spring service message goes here.
-
- - diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java index 39d3ac464a..a54b8a542e 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java @@ -1,6 +1,7 @@ package org.wicketstuff.springboot.starter; import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; /** * The default home page loaded by the Wicket Spring Boot Starter @@ -10,5 +11,6 @@ public class DefaultHomePage extends WebPage { private static final long serialVersionUID = 1L; public DefaultHomePage() { + add(new Label("version", getApplication().getFrameworkSettings().getVersion())); } } diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java index 3b59a014cc..44f92f448d 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java @@ -13,4 +13,21 @@ public class DefaultWebApplication extends WebApplication { public Class getHomePage() { return DefaultHomePage.class; } + + @Override + protected void init() { + super.init(); + + // Mount resources to serve style.css and logo.png from the application root path + mountResource("style.css", new org.apache.wicket.request.resource.PackageResourceReference(DefaultHomePage.class, "style.css")); + mountResource("logo.png", new org.apache.wicket.request.resource.PackageResourceReference(DefaultHomePage.class, "logo.png")); + + // Ensure the package resource guard allows requests for these resources + org.apache.wicket.markup.html.IPackageResourceGuard guard = getResourceSettings().getPackageResourceGuard(); + if (guard instanceof org.apache.wicket.markup.html.SecurePackageResourceGuard) { + org.apache.wicket.markup.html.SecurePackageResourceGuard secureGuard = (org.apache.wicket.markup.html.SecurePackageResourceGuard) guard; + secureGuard.addPattern("+*.css"); + secureGuard.addPattern("+*.png"); + } + } } diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html index 0d3fe7630a..1054476db5 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html @@ -1,250 +1,59 @@ - - - Wicket Spring Boot Starter - - - - - - -
-
- W + + + Apache Wicket Quickstart + + + + +
+
-

Apache Wicket + Spring Boot

-

Your application is up and running!

- -
-
How to customize this application
+
+

Congratulations!

+

+ Your quick start works! This project is especially useful to + start developing your Wicket application or to create a test + case for a bug report. +

+

Get started

+

+ From here you can start hacking away at your application and + wow your clients: +

+ +

Get help

+

+ We are here to help! +

+ +

Reporting a bug

+

+ Help us help you: +

    -
  1. -
    Create a custom Wicket WebPage:
    -
    package com.example;
    -
    -import org.apache.wicket.markup.html.WebPage;
    -import org.apache.wicket.markup.html.basic.Label;
    -
    -public class MyNewHomePage extends WebPage {
    -    public MyNewHomePage() {
    -        add(new Label("message", "Hello, Wicket!"));
    -    }
    -}
    -
  2. -
  3. -
    Create your custom WebApplication & register it as a Spring Bean:
    -
    package com.example;
    -
    -import org.apache.wicket.Page;
    -import org.apache.wicket.protocol.http.WebApplication;
    -import org.springframework.stereotype.Component;
    -
    -@Component
    -public class WicketApplication extends WebApplication {
    -    @Override
    -    public Class<? extends Page> getHomePage() {
    -        return MyNewHomePage.class;
    -    }
    -}
    -
  4. +
  5. reproduce the bug with the least amount of code
  6. +
  7. create a unit test that shows the bug
  8. +
  9. fix the bug and create a patch
  10. +
  11. attach the result of step 1, 2 or 3 to a JIRA issue
  12. +
  13. profit!
+

+ Please mention the correct Wicket version: 1.5-SNAPSHOT. +

- -

- Once you register your own WebApplication component, this default starter page and the auto-configured application class will automatically deactivate. -

- - Documentation - - - + diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/logo.png b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..39ec54854b748ab6aeb6b3965d88f452772d7d8e GIT binary patch literal 12244 zcmV;_FDuZAP)4Tx0C)j~RL^S@K@|QrZmG~B2wH0nvUrdpNm;9CMbtL^5n^i$+aIn^?(HA4aZWV5ov6ELTdbo0FI&wK{O>*+w4vx20?>!`FrQsdJlnHR>OPy zcd~b_n$otK2Za4V;76L-DzNVtaSB-y0*E}{p()372;bw_^6ZZ}PI-92wGS&j#91PI zKs7DSe@(bk%_Y-7gGe}(^>I=@oY#w#*Bu9GZf3^F5WP>3rn}7Ut74&?PWBFvy`A)a zPP5)V!Xd&78LdA?xQ(9mjMYElVd13a#D+Z_7&Y|xU=_C-srWU*6kiZcC!$nw*)9$7 zn6CX+@=AhmkT}X@VSsa5NKe;HZuq)~1$`#h6R+ZTR#D-3j}vF!)ZOnz+5)dI4jl{{ z44Mr{P!L4~VVJN`K!!XTF*LGrKO?IK8z<8w`3e3jI8lUGNUta*C8 zn(P`s>{pjD=7Kek#B;Fw@hxAK%$F&Q6vg9J^Xf~4by_hu-=A!MJ3Znq&n~srbFGPs zH&&aMXZ>nO`|hf|ljc?VPhR!${AbO?W8x_>CU%PFA&Hm8F7cAsOREdwU~R_;ot1_u z(ruCYB-LPGn!NQdT|ZlRy+(fw^-+`=%+gee_kY4FWHg<*4sZI8+sFJD270UUORdLHO0nA4V) z%{fwsET5CQ>B?eK%uw4yQc~9?*JVo2}ze(;aRcp*ceL#HUJSllrgm5wQKR zQu+C;QrUh^8rFfA`ftFz{YAidi-`aL010qNS#tmY3ljhU3ljkVnw%H_03ZNKL_t(| z0quPWm|R8G_PIUT$wKx__KhSgVF>{e0tpEi_JANDvIr;&Xb?eB5y1rn5&ac}5BWp_ zs34$xEV3#PNPs{LkU$7a$i6{B$i7YA`ro%_PIukg-80=YJu}_6>paitsybD-mUGYB zwcdL@V~jXzQVq03X}!Qbz#VG1z2$EU|2FVu@Rk~v{`KHBHM|S1qbAZoizX_koQi3M z#tsFKsNunIdxI-$-0pBaa6{-bTui{M1}_4C6yi+?J1UR{JlB&nNR#Xh4yob&;1U>v zz!l);q?IWA%@7kzj_RQS2a?>C#()1&;PGGu#z6Q>g*aTB0iF(i5&RZ74t7+B1{_Fg zS5QwxPX-?Y{sNdorG`;FE@u4-kx!Rm#__qBEgM9(ZUke5v<>cdOhZ~>TGAHNl(v|% zwCgAy-A*XFYhUrY^bu*v5nY1`1t&oBEZj%IOB$SGL^E(8Nx!kfAUYF#GMGas_8_?v z7DCMGkHjo`8)o;em}Tz+5CFy6PsDtVKlAkfgWtf#lJ;%I>%2Qa(+xA7f#UVW6sYfT z@%rrv|K1{P+T~u~R7&xCffw}a~W?X#oJn?#Csx)MTc*FJwA1vOUJzC-hs!8*L?t*Tqm*1 zdkH)Z{4khH(Pc;F2oesbrh?A_cdGS{bN=w&3^B6+j5nS~Z}DNnhf1{;*mRLzZ_IHH zJWOJTe@VR2Cy2CYSy$l%$lc)IgBRA7I7;#51d>U(ahHRS181LS5EyShCH}Mbig^V+ z#>TBty5E`G(yono2agr+u#+Wr*y&g-sP(_YM<$%N{1(jBvdB}^K|(N`2>vnn;M(q{ znfHSD&rK8a@-rgqu*y`f)Vd|WGC^X;U0B`2V2)D@y@9x2fFG|VP02?^86+4($aUcT zvfd@mF`l?p%wqt@3T|LK3TU85XNetkig;6|VljZD)U5P6Vy*$>A0~PfMUafgZMqRW zHrwqo3ulY}@XccW^ECD)c4kZF!HSg_U{zD#bhRD$HFjz?xykN&aG#coDc{=PRWOk{(bx z!SN+<8kq$%#lQ7CZdjG3nZ^@%dkmD=)ZdA>|Kx0i`~?y0?bl{YP^|J&1POt0I~coR zK{9KXiGK&c@f`lN+{0u+4%Z!Ep0NrN zHURy9-YEWEH)Hg>BN*pGO|OAgEhTp5*Cci>78x_2SiTRHB3MddL#k9j!sXn*fd_&E zWEQ+C{>>MP`QYP#+y$Cn1Kxn%61(zF@ka8nLmKfA<=Nm@(qf8CQ0yS#OpxpD+|>=P zH&*Qu|L*UL|F=Kk(ILOc)at5})BsNiyrrlCZ|~s}`{_T$>p3V~{Vfoj3;t&~qB+B{<}5rz*_S}} z1ULW?^YNP!zi^ZTNCt(KqR71azQn(Nh?v>D)dAWKp@+bHq@if2m_WiK4BQ|LoN@4H zJRtE)CW%?aC3Z)V(ZGhy693*AI7@eRxJk6h-+=!B4%k9CVN->RVYo%5aC7jR;YR!S z{s?;?x44bLuwo(><_2WN)&I!!0tbnC20lBWgzZ};e&gw4o_{_d zc7f<>fTxQqZp2B6E|uX%z6imI;LYKPrV2MFNLrzh4}iI%k)jQsq8rBW>ix2Mj5^i+ zGWI2wiEnyByaD@$weT7Q$AUi(M>Ivaxj@nujpGUiSF)01)~yi#vLnPSS&@`EPnl@| z?-Z-J@xe?Fck#Volfj=hwMLp_;!c1(2@V2e^+NH#J}EJ3 zX%cEmklczEoo=_vESW3u?_iku*(O`;{7wVa8o=8z{a;KK|E2rG8aV<2p2}#FeUzpG z$@kG9?xrWne7Z#9SD;fVhnK%4TkSk~YXB#_{hxhP%F58wX0cmwydFXO{R+?8*%Ly?UMlAfseY;a$2HN~qWe$`|#ufC=d z=Q<7Kr2(&3SE;yT7Ix-)+t+PHfD`(8wy;qC#+sApQf~?%sB!$}a~wblb?3@7AF~=m z^&cLM(_F+wlG?$?o}^P!Qb12*f#gQik>C7C5+9Z_|9UhTb{?mJ`f9)|SSazIpB%n? zC~-KgWImRMb7Uu&>#(%88d{Z#6!e`kXMCd4GtE1 zPBH*BdJCL9I$+i=mH7Fi@$_=D9pY@Tl3WHwssTI>TyfL=__oRvyMlbV#CY&4wy+`o zLV|?7(hFc#u$nkgpNc2Y-g!?Y&UG3ntOh!^lZrph60g?~JKseJa0#p+yVQjoZha4x zN&y6c_#ZEI0D&GHHKGQv8SP(t3XHAFE`$%y|G^eC#9t_o?2AhL!mfy!{Vy?pzsD9i zztcdYXnd)P~aF;AU2OcA%%bp4u#L2>Znzveo$F zKpG|}=vSW#)fXh+L19E^H4(kP`<8o&oa)25&8`9e@6*IAUtrgxEdsx?1-bg`1Cp-D zJaA~ne+1t||8Q}xWx8}u1C6hNU3f3;QHuO~f9wt~rqtnlMWzA&mhWOkiDw>@bQpYj zEeYof5+FiaX>oj+ga42FH0WHXfuhrZS%fb#Kli`kdi^{ss4biiNO%nX0y{H*8m1;Y zcG)85cN!=<4VZiI3}Em8koGVCrAcOPlO#Eqh01Ph=bL2Eo3K}r?-3)sTjCu}2y#tSSWNSyRAmLgX zHxLtK)-DtC%o7@PuG2u#Yk=pv{HN~-*OSjc)k(R4gqtupZ;~Saf$Ll^l2V8Bm52t+ zLut=poq(zjudDjGfaEL4q)Rd*?2DKu9!dtC$7!HcG{BWE^V%bJbv*>IMqE4P0ur1z zNs<33j%;lW93D$WI-k=(k!!$zAZ_FOEL6FDZPl&|Bx7;$0d@xFv1xYD`JDzzN&{xj zTVfXTg+56lKzLjwE7b*(3+*e}RhboQY?1Rj4V0V){QtWpT<3tDha+nP$!?6hmdKc>k_jX{^pzwt^TDJ)ik_8jZc^)Qt)7eY zPo(ki;9}&BC4zGDN8fP%$XhD zSlk~iNge1#APkcIAWIF>w{HY@7enXKXl0*@wfui0Uh9iZOEnAYt>4wA&c& zNdgG+{|k^roOt77v6!sv&|ltjyYR`o9qvV_Cz86!gc0zVxvz#>5m?=|K|(DY8c6;2 zD}i8?0`|Y60_Da2?o5~7<8UuRxveuz7X{ZWct1QZ*$eIJsBN=BG7Q4hgasdyHwzbQ zx=6Y9zoGi+uI@BQ-ghU2B~ve=08xEK${==DiJ3p$ZW3{kJhxYp)qf<~9EYxg1w3e^vF6-6@h(?(56JlHJ`?5de}UW%eFl5NtPPXYbB`Q%SJ z50#I)^-88IH&3`1QT^CDilR=;2mcK>i%Y=?vO&V--z1p@X%{8qqT zZP-y!X=2{(sH+!=YEL2`%@6A;i3bG9eVc@gSB^`rVwSM?HEjVw)@mn3kZ!>yr#hA&$X2u3kr8v@(M zaM&0&RF0HY{eu6lQPf2)y$Js_TC`}9`16RO4%jBM{KIh5vV+7d|0tX|(qRRNf<#>! z#)3mmk96DFxLkV?f`lAdTC*bDw1E_8Ptq?CyJmSH7}Ws5V3UG{;LtJnroQ{jngIjt zWRddc+lxebP9p0*4d2^76evg%fn_k(cx!DRt>rKBK+e}j;b=u zx((r`RYHInstDiIxVs&jA+a4DS-*mVt^$OHvAO>!SvP2KleBv$%H9#`;To&pe0mWM zv)GG7dbqW7m&nFI2f?vrPl6>qhBT^b*o(Z- z{UDj%V|1hUCiU$_BHfel?rvNczQ_wK=vAeFoP;hXlrCj(L6;F<4QyNHi=Ur$YsN$B5 zfnd1?v?rl!&rLo#{*p#fiS{Cz`BwBO)4LDSU_ssb^dbtD$oC}MH-~lImLN%fRW}if z!;Owo8VG}>YS=j0G(2&nCzYsyzHl$XGD$D>IH=&gNqu_}f+O;)TU7cktZ)UX4MEa2 zAlnf*E*yv|mw*in?MXQN(D}({Cr&M>D(qfF0m1^pRhtv<^sj?g#|SEnpj|`V}Y~cF|bkBMz6%BZe15HM`Jja7Bw0E|1}tdLDw_BzQ8Q zz6EP9qUC6r43pWuOmh*t7fFDmFx9DVGaC20sHK8FNtYI+ zWiMkzYfGz+Nq{g@mPKM&+gf*&S9%4{pC%&f@xxw3^R``i7} zv<k?)1I;1|TP}9z>X+4S8HZ?|$vNG!1HX0UL4VMPJ`P3`&%I>wwp;)!r zJ@F5&`KcQQh#D~G1AfOIvS9cDd6o4-ze8&+$1YFHV%rD`dqs>=M^?s8ZC{rb?ep%gQfey z{-;X3qPiZbnq~Ga?A%>e;f<7Gip0{qOmg{ z#&Q(a01b?!hDO&mwk@Z9KYU5X@SFWc$c}bh1J~O5s9*oJ)mRA-vUI7Gh5H1TjWZSm z;f$e2lbD6I`s@UFC8Ra=kj}VVOT5K!ZuLUnANz<-kh7%-kZc> zU~`5|PW~%v9${C35jI#FE`hRa+&OjjCQG{alux>iNE&vy42HFLpsOHY8CpJFhP92F zKAV0@Ufu>PTlijmh}Q6LVQoOz22b-cv7?L{2m{6LQR?bV-Wf7dcD3)3W^`(>>Z(!N zhN}P}NGiJZlNF-_-l=F=lNc_kVQb!W)lU#=yxnuLECq|!LDSKVDtTQ4PmQpd zJjnPtLBbPVcxE?6UiY*aek#)W5<@Ok13^N=p^??ro3IyoZ@-h1lV80?4OU&-Sn1b) za~*D}`{|@_h~FZ!!LF?AE$e&lo9q!ZPc1{sR#${F^YN8zs}3-i z1RCBm_}F_OuFL~=Poe-(rFo1d$d$_?3tVlGp!maT{ToSM!NcsuC4+k(VKMd zCu_$}%y>869eqj~K$suPu*+1Lx(Y}I3&V`#HQGjPf5w7KUDzY|(jYWv8JnaaSsG|x z&){pg0&!&=2pb3uhcdd#nR*i+t5J)`o|O>@G(t5*^{a8xwGCInqVD=*r>6BLYy0|g=L9)n>_4*X%)Ty0k)cgd8f=2!N zFCFepR*f1bJ{Cl1d}^fX(f~8b6$o_Mb7^$+Wyi^S50!daZ+& zuVrYM>9kFBwViI zO=Ja%wmoXDH(+GANr9f^Jv-JLnEc3(Eq4Bp1~T;|`p>)hwC^QSugAQ>>)I~>3N=I; zuNtszv|+i%soZuex?^}XesZF$PmcL!03e!9uh()3IL2vMT}@AyAkntaRe)%lL#inK zAU1iu{%L39-etq|AWq;l@?IszX07pX&5pF^eM?^%1!@8RS(WJbeLvZw#N%2L1ExVUof<2z-S)*RrRAEXi85Pl+m3aBr%S`4LAGe$S>ii(Bn>}d(2&!3Nt#xT zm_|sD&~Rz2>gqo{^JN+uuw5RnkG1b4EqCrr z?Two24IdS5(wi#C3KDPlXfcmJqUoHQg9h}UmWD{OZ~$#WrB(p@5^G~V1wjU z71H$v`MDL8DSWnP*$T@uqOKs0|fWKE;-lxtbM&d!_V+2L?GnwORl8MjqS@eVvT+?-lL z@|>O88+wpPS3L8+Zlf)B{#rCZV^Tw;UyY3hs6+!*xf(9xDA#{*+hA?EUd!v1C{tp7 z%tMLk6eM&>l#!W^<)}-)oxhf$uI3pf*V`9Iuv!IPht1c@zhbvBb?2(3E8)xoW0Rzs zyaUFF`S-ILbZ!O>gpEkUwz2Xu%9Ux1G+H%W#;bwSRfAO{=5-pcdGHz~#$^Hs)3OZa z6E2I_Xjxhw>r5HlOyy7(r2&_B$kD1ob)SbPIUk`g3=+zSh!jW;JIR5BS^?1rGZE!9 zo=g-rUK*nst}fN;b(E`d+Q!N}7-zG6jqPVzC4z$2uzuOfQb4H7^mZPam%7<>pz)>V zdWU`~T;-?3f|N#6F;Aqt_;(wNOj>2alAS6#{#=Z}{zuN%a@(N8hEJf7ISc3E16mZ@=?o_T0p>94K4Z1pH5xi_evc>My$QTQ+Tc(@Ijtp8;s zS_iIvhPQ18@kSk3_N!b99(4&68W+PfCUwIK*035JjZo9-^>!LN9pwx&oys+BCRfvH z55lsPvX!NI^V)D3T2IY`;V6+e{)BLIW<#(%EX)KF9_o4we7+|3CY%~6kc|BF&BVAG zc9AfQ7B&C4E%EQ(3cIgu+Tau}mS7Xyx|Os6w{FGb<@onc^a2>SS3q?H2cA0gX~^`e z!fIT<#;6j;Mwt&l!C{zPxW+R|iTNlc3>QbZ6Zu;C+i95A&PU6Np)C6K2HR;gf6Yh1 z;pJGCmuOe2o|<2&x!#fIgsYtK92VLezO{+#2(eVRvvs3Xoz%}Aoe!(jg-ccg9BNhE z6MWVXjp0{g(~iDpnv<~M&wx4Ps-|}M$jsQoG~`^Tfs)sNH~EZk8+f2G4IoUE4J2Fw zdyol~yraLWUgtUul(q&iM2;PMQMe6%3kx)y4J3^Jt0tlw8*{2i_uXxg^E(Zcqz1gv zqw%`f-ge#DDco-hY=3Pa;jSYOJXRAXx3ObR*N}6a21-@~-ihA`*PZik9`MabwSj~) z`aA8byeXHVODX+T4ZBUwUtSvUdf{c|jC z8F)PhiZ{+p;8h>aEj}6vKCkV!@fFp=2dpk`JDzzM*}$V z8$0nk;riYNLFz%Da4f=gfrOX**1pc$XM%Wp54T0m?=(;n8t{%eQ6%`0s%@xvtwSv~ zEEkac7wKMPVkPg4E7a>;r-9PY0GEBwx;9+bX%MUr3&Y`DK*DQowl9oLI7_?%fh9CM z+WDOZicSOG#3RM4_q}! zQK+lJ`GSOVlONfcdV7r*@2JVP$oZWHib4aivo017Ujws<`yv7Rwc@gR^92brda8z# znZ_sN*W!f65L0`&q2>(!8+gx8b!R2Sc_ zQcc^pNc@6*#4KN<66ZP%G>HbhefO4%TVGGS>d7jQdm>j`;k>XpZ8!=8| z=S{Um&hIqPs2cF5{vr$z{zIP!ZV*6N=|X^n`P=~xzC-w&>xJE)Bd38z*T94cQgPh3 z!o~2w*6gsbKH)+Px3t_I@XQ6LR=d_N#ry={IQe{&rg5&*KtVNN`t*?4opbPs?#}kR zj5*9Y5WJ%hg%zqNVO>4}pKn)+n~W7dy%!JO7qS?;1m`bj4H$my;949`Z`a9I!xjWi z2Nwh&%(&3j%OfklW5!C}sG}uzQDDlVQO}?4GkA^PGZ-k7Xov@l}X{Q z?GnFqteAJ-Pl}w!X`ntDh>zM&yc?bu51+x{_f=}XvGOMJ8VfGiFiY#!7(EH|UJX7C z%!lo(35U%pZhS_(-rZH=T&ID&HQ@K@Ddy^bCSEY7-&H{-8^HJ^Tj2r13N{uMd1aPI;>H9CtHCj1 z;L$LzKaLLE@Q{1{B#)cqlH%YMcGRn`dq`rvha~`_y~wUzyDn)PTWf_;y|MXNm1`aAN+UiSTX6>)N($`)3U|mfKhp z_i%mNK=2>%p>~A-%ERJcjja`T#>-ZV^IIA)c-u+U)&C>>l(hX3RD8zpK72*^JS2rT z^EVBxY#QWkik^fO+zvh-{1yXBF*f`sx8ZB@6)JMB(?C)K1W5eq+tUDo1TWli#~l~K zZFGRJGELQ!uq+anwq62{U_i;A`JnjMejP{Al1~I{lyl2e1N^FS{Oa2zcKDfrIS5cO zYwp~+M~@yonrEFN2@>A&K41c6Fat_v_7f7n>TL8mJ5}V|GSz@--BSFY{83_Kv0;c; zlqxj`Kv;HD_axfhf$%&J9;5=gX5RA>{{gmFHgB`V&R<3vFuP&;`pf&p8+l}+)d~_! z(zOTK$Ov{JO{JFR0tws49_8QQz|hMqnJfO4Cx}_KmT4T7kp@f`Jhyiv_CfYID9~z5 z*k>(TwCLy|LxwatKv^3J}&ISre^M6T3WKKN0+DpxiE%QgO>`;vIf?Kb!iLFec)47pss)KRpS5o_wF@Cs*nh|oK$$H zpDh&^-5&nfCnxND+Lgzen*Buy#R3xEdM;z!1pXcaHksESllafSCbDshEq4A=)&P!~ z#D4I5iA_8=+zMicr!)e`nZk*hGF(g`(RN=9&n;j)c9tTudLi~wP7(9ohbf`+m81r| zfqf-*-6O(td?Dg7_w&FHgyhW{EJlz}A>+Y3@0EOBo3_@oyFXfuzpHJ1IAd=O$F+jInRiH^F{8ps;ZD;a=Ues z*k!*Fel{=zvDY{Y{9J~(q7sz~NT{?*@HBAxXSMMBynomC#DDM}ckCVtYIcg@6Xqv; zQ7SIMARzd>@BbSLU1^*J9HuE#f-xL4VZ;5&JHAFjV4h?vt z4v^T?--|b7bf)4zhwyUn-I*ebRaR;sQ9TZV=a1kosK9p38;=7lSBP1>+!i~3BWl3w z-&?#(Zp<|A&{7|Rhs*n%YnBw1Do9kx+===vxT^}1Zagmj)Bhvp-kaQE$)r*m!PB)P zJ_UH0#7@Q@a7AEiOAF&kRrdb(tDw}}QU?k3-5q=#`0L>G)w-%(;{WSb@$dT$Uc|Z{ zNgNeI170t@vE+=Y5}N}14}P0av**gyUEr(0C4Hnj3Lw#&!jr^&#p)3%2)Mg;ivQH@ zVjlW~m?b6G;|H43oB^+2rFdswF0skq%+_*SF1)JDBhHd@i^_5v3$bylZ^Bpq(1^bnlZLSg;4|vZ$$-| zYw*{C2ZJ+`SvW`h$8Ht#pT}`{a%;vkWi8}<tFJ^>C`qZmGD;KF&D^j;At5M@w2RAhGY-cm%kibpn{+$xa*BivQC6VrD*y`OBM; zdO?MUFGR_xL&ZDjSc#3nG_G!7Y=olz0_OhI-0Vt=UQ9WHMDJp6c)kke@rYUn+=&bD zat`zUD`I9pjUm}|G4G(4*}5YURT4iqN9FCcKS1#X45y~lHOH`hNH%PIhz4`4?h&J*+T$Hf7h4(-I-V;I)=4gfIF zTkJhvyl(yKZc{1+pKN;w%x8MuPKnFY=Rgv?@2wG>3?^8nfV+ZoC-ydL0F-6(#VlJO zX2l0M!iVshm0~_$j}NSFF5Dc4^N4Pp@nWX_B7KMADZf3%8?ZN)C-8xru6=T^b1J0* zgWw3fjy9E~Jbex%+3!2&D-*ycf+vATg0pTAATBrB@Tr(}%SAo|aJFs`*#_Y3z$j*W z4P&J(u@B+JkROWUo&>(=B%OPS*ByZ9(H|gy+o4NtbId?0vK4Re>j z_7yWEXad@XGUkEb0KZ=2z7N+2JIYf74kURhtd8WZ5I+da)iRs8lGYQ<-l$L@;^!<@ zfpaq)512N#ny~yVbb#w*=F`ZRSyrPr<9e i1O^!^0gjqN1OFf9qq%!F8)!QK0000`K literal 0 HcmV?d00001 diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css new file mode 100644 index 0000000000..87576a78c7 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css @@ -0,0 +1,68 @@ +body, p, li, a { font-family: georgia, times, serif;font-size:13pt;} +h1, h2, h3 { font-family: 'Yanone Kaffeesatz', arial, serif; } +body { margin:0;padding:0;} +#hd { + width : 100%; + height : 87px; + background-color : #092E67; + margin-top : 0; + padding-top : 10px; + border-bottom : 1px solid #888; + z-index : 0; +} +#ft { + position : absolute; + bottom : 0; + width : 100%; + height : 99px; + background-color : #6493D2; + border-top : 1px solid #888; + z-index : 0; +} +#logo,#bd { + width : 650px; + margin: 0 auto; + padding: 25px 50px 0 50px; +} +#logo h1 { + color : white; + font-size:36pt; + display: inline; +} +#logo img { + display:inline; + vertical-align: bottom; + margin-left : 50px; + margin-right : 5px; +} +body { margin-top : 0; padding-top : 0;} +#logo, #logo h1 { margin-top : 0; padding-top : 0;} +#bd { + position : absolute; + top : 75px; + bottom : 75px; + left : 50%; + margin-left : -325px; + z-index : 1; + overflow: auto; + background-color : #fff; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; + -moz-box-shadow: 0px 0px 10px #888; + -webkit-box-shadow: 0px 0px 10px #888; + box-shadow: 0px 0px 10px #888; +} +a, a:visited, a:hover, a:active { + color : #6493D2; +} +h2 { + padding : 0; margin:0; + font-size:36pt; + color:#FF5500; +} +h3 { + padding : 0; margin:0; + font-size:24pt; + color:#092E67; +} From 68657bc2e847d034ed96d6ddd8971574b36199c8 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Sat, 20 Jun 2026 20:33:43 +0200 Subject: [PATCH 04/35] Remove outdated version details from README --- wicket-spring-boot-starter-parent/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/wicket-spring-boot-starter-parent/README.md b/wicket-spring-boot-starter-parent/README.md index b66ba741fc..83d04972c0 100644 --- a/wicket-spring-boot-starter-parent/README.md +++ b/wicket-spring-boot-starter-parent/README.md @@ -35,7 +35,6 @@ Ensure you match the correct starter version with your Spring Boot and Java envi | WicketStuff / Starter Version | Spring Boot Version | Spring Framework Version | Minimum Java Version | | :--- | :--- | :--- | :--- | | **`10.x.y`** (Current) | `4.x.y` | `7.x.y` | Java 17 | -| **`9.x.y`** | `3.x.y` | `6.x.y` | Java 11 | --- From 7a1b06973ffde476317c8f11079a3d452b9b7a47 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Thu, 17 Sep 2026 23:00:04 +0200 Subject: [PATCH 05/35] Fix stale parent version in Wicket Spring Boot Starter modules The starter module was added while the root reactor was at 10.10.0-SNAPSHOT; the root has since moved to 10.12.0-SNAPSHOT but the starter, examples, and their aggregator parent POM were left pointing at the old version, breaking parent resolution. Co-Authored-By: Claude Sonnet 5 --- wicket-spring-boot-starter-parent/pom.xml | 2 +- .../wicket-spring-boot-starter-examples/pom.xml | 2 +- .../wicket-spring-boot-starter/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wicket-spring-boot-starter-parent/pom.xml b/wicket-spring-boot-starter-parent/pom.xml index 83bceed7c4..a57ea48958 100644 --- a/wicket-spring-boot-starter-parent/pom.xml +++ b/wicket-spring-boot-starter-parent/pom.xml @@ -7,7 +7,7 @@ org.wicketstuff wicketstuff-core - 10.10.0-SNAPSHOT + 10.12.0-SNAPSHOT wicket-spring-boot-starter-parent diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml index 4fc9daa041..08b2e48bbb 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml @@ -7,7 +7,7 @@ org.wicketstuff wicket-spring-boot-starter-parent - 10.10.0-SNAPSHOT + 10.12.0-SNAPSHOT ../pom.xml diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml index 22231a151e..ae656530dd 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml @@ -7,7 +7,7 @@ org.wicketstuff wicket-spring-boot-starter-parent - 10.10.0-SNAPSHOT + 10.12.0-SNAPSHOT ../pom.xml From 6cfb013993ee08d43d93df1805f2ade16ae278ba Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Thu, 17 Sep 2026 23:15:43 +0200 Subject: [PATCH 06/35] Fix architecture issues in Wicket Spring Boot Starter - Import spring-boot-dependencies as a BOM instead of hardcoding spring-boot.version on every individual Spring Boot dependency, so versions stay consistent and are managed from one place. - Guard WicketAutoConfiguration with @ConditionalOnWebApplication(SERVLET) so it doesn't try to register a servlet FilterRegistrationBean in a non-servlet (e.g. reactive) application. - Add spring-boot-maven-plugin's repackage goal to the examples module so it produces a runnable jar. Co-Authored-By: Claude Sonnet 5 --- wicket-spring-boot-starter-parent/pom.xml | 14 +++++++++++ .../pom.xml | 23 +++++++++++++++---- .../wicket-spring-boot-starter/pom.xml | 5 ++-- .../starter/WicketAutoConfiguration.java | 3 +++ 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/wicket-spring-boot-starter-parent/pom.xml b/wicket-spring-boot-starter-parent/pom.xml index a57ea48958..a808663cd1 100644 --- a/wicket-spring-boot-starter-parent/pom.xml +++ b/wicket-spring-boot-starter-parent/pom.xml @@ -22,6 +22,20 @@ 4.1.0 + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + wicket-spring-boot-starter wicket-spring-boot-starter-examples diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml index 08b2e48bbb..fcf0e9553e 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml @@ -27,26 +27,41 @@ ${project.version} - + org.springframework.boot spring-boot-starter-web - ${spring-boot.version} org.springframework.boot spring-boot-starter-logging - ${spring-boot.version} org.springframework.boot spring-boot-starter-test - ${spring-boot.version} test + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml index ae656530dd..21c6c00ab3 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml @@ -48,16 +48,15 @@ - + org.springframework.boot spring-boot-autoconfigure - ${spring-boot.version} org.springframework.boot spring-boot-configuration-processor - ${spring-boot.version} true diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index 3a1636aaf8..141d0f21d7 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -10,6 +10,8 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.ApplicationContext; @@ -28,6 +30,7 @@ * @author WicketStuff */ @AutoConfiguration +@ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({WebApplication.class, WicketFilter.class}) @EnableConfigurationProperties(WicketProperties.class) public class WicketAutoConfiguration { From 14b86821fa646e10d5e8525e84700bc0ea68f4e5 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Thu, 17 Sep 2026 23:44:09 +0200 Subject: [PATCH 07/35] Add test coverage for Wicket Spring Boot Starter - wicket-spring-boot-starter: WicketAutoConfigurationTest exercises the autoconfiguration in isolation via ApplicationContextRunner (default bean wiring, custom wicket.* property binding, @ConditionalOnMissingBean back-off, and the SERVLET-only guard); DefaultWebApplicationTest uses WicketTester to verify the default home page renders and the mounted CSS/PNG resources are actually servable. - wicket-spring-boot-starter-examples: WicketPropertiesBindingTest proves application.properties values reach the registered filter; SpringBeanInjectionQuickstartTest is an end-to-end proof of the README's Quickstart pattern (custom WebApplication + @SpringBean injection) over real HTTP through an embedded servlet container. Also fixes dependency issues surfaced by actually running this suite: - wicket-spring-boot-starter needs spring-web (test scope) for WebApplicationContextRunner; nothing else on its classpath supplies it since spring-boot-autoconfigure's own deps are optional and wicket-spring excludes spring-web. - wicket-spring-boot-starter-parent pins the JUnit Platform/Jupiter family and logback-core to the versions the root pom already manages, ahead of the spring-boot-dependencies BOM import: the BOM's own versions of those artifacts were binary-incompatible with root-managed sibling artifacts (junit-jupiter-api/junit-platform-commons, logback-classic/logback-core). - wicket-spring-boot-starter-examples needs spring-boot-restclient (test scope): spring-boot-resttestclient's own autoconfiguration needs RestTemplateBuilder from it but doesn't declare it as a dependency. Co-Authored-By: Claude Sonnet 5 --- wicket-spring-boot-starter-parent/pom.xml | 36 ++++++++ .../pom.xml | 16 ++++ .../starter/example/GreetingService.java | 6 ++ .../starter/example/QuickstartHomePage.java | 20 +++++ .../example/QuickstartWebApplication.java | 17 ++++ .../SpringBeanInjectionQuickstartTest.java | 49 +++++++++++ .../example/WicketPropertiesBindingTest.java | 38 +++++++++ .../starter/example/QuickstartHomePage.html | 5 ++ .../wicket-spring-boot-starter/pom.xml | 21 +++++ .../starter/DefaultWebApplicationTest.java | 52 ++++++++++++ .../starter/WicketAutoConfigurationTest.java | 85 +++++++++++++++++++ 11 files changed, 345 insertions(+) create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java diff --git a/wicket-spring-boot-starter-parent/pom.xml b/wicket-spring-boot-starter-parent/pom.xml index a808663cd1..834abe2cfa 100644 --- a/wicket-spring-boot-starter-parent/pom.xml +++ b/wicket-spring-boot-starter-parent/pom.xml @@ -24,6 +24,42 @@ + + + org.junit.jupiter + junit-jupiter + ${junit.version} + + + org.junit.jupiter + junit-jupiter-params + ${junit.version} + + + org.junit.platform + junit-platform-commons + ${junit.version} + + + org.junit.platform + junit-platform-engine + ${junit.version} + + + + + ch.qos.logback + logback-core + ${logback.version} + + diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml index fcf0e9553e..96d266b32a 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml @@ -46,6 +46,22 @@ spring-boot-starter-test test + + + + org.springframework.boot + spring-boot-resttestclient + test + + + + org.springframework.boot + spring-boot-restclient + test + diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java new file mode 100644 index 0000000000..2bf2609791 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java @@ -0,0 +1,6 @@ +package org.wicketstuff.springboot.starter.example; + +interface GreetingService { + + String greet(); +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java new file mode 100644 index 0000000000..5487599696 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java @@ -0,0 +1,20 @@ +package org.wicketstuff.springboot.starter.example; + +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.spring.injection.annot.SpringBean; + +/** + * Mirrors the custom {@code HomePage} from the README's Quickstart section: a Wicket page + * that has a Spring-managed service injected via {@code @SpringBean}. + */ +public class QuickstartHomePage extends WebPage { + private static final long serialVersionUID = 1L; + + @SpringBean + private GreetingService greetingService; + + public QuickstartHomePage() { + add(new Label("message", greetingService.greet())); + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java new file mode 100644 index 0000000000..fe137d9ac8 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java @@ -0,0 +1,17 @@ +package org.wicketstuff.springboot.starter.example; + +import org.apache.wicket.Page; +import org.apache.wicket.protocol.http.WebApplication; + +/** + * Mirrors the custom {@code WebApplication} from the README's Quickstart section: a + * hand-written subclass that the starter's {@code @ConditionalOnMissingBean} default backs + * off for, once it is registered as a Spring bean. + */ +class QuickstartWebApplication extends WebApplication { + + @Override + public Class getHomePage() { + return QuickstartHomePage.class; + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java new file mode 100644 index 0000000000..175a3fbff9 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java @@ -0,0 +1,49 @@ +package org.wicketstuff.springboot.starter.example; + +import org.apache.wicket.protocol.http.WebApplication; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.resttestclient.TestRestTemplate; +import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * End-to-end proof of the README's Quickstart pattern: registering a custom + * {@link WebApplication} bean makes the starter's {@code @ConditionalOnMissingBean} default + * back off, and {@code @SpringBean} injects a Spring-managed service into the page that gets + * rendered through a real embedded servlet container. + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureTestRestTemplate +@Import(SpringBeanInjectionQuickstartTest.QuickstartConfig.class) +class SpringBeanInjectionQuickstartTest { + + @Autowired + private TestRestTemplate restTemplate; + + @Test + void rendersCustomHomePageWithTheSpringInjectedGreeting() { + String body = restTemplate.getForObject("/", String.class); + + assertThat(body).contains("Hello from Spring, Wicket!"); + } + + @TestConfiguration + static class QuickstartConfig { + + @Bean + WebApplication webApplication() { + return new QuickstartWebApplication(); + } + + @Bean + GreetingService greetingService() { + return () -> "Hello from Spring, Wicket!"; + } + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java new file mode 100644 index 0000000000..9225a1f323 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java @@ -0,0 +1,38 @@ +package org.wicketstuff.springboot.starter.example; + +import org.apache.wicket.RuntimeConfigurationType; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.wicketstuff.springboot.starter.WicketProperties; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Verifies that the {@code wicket.*} properties set in this example's + * {@code application.properties} are actually bound and applied to the registered Wicket + * filter, rather than the starter's built-in defaults. + */ +@SpringBootTest +class WicketPropertiesBindingTest { + + @Autowired + private WicketProperties wicketProperties; + + @Autowired + private FilterRegistrationBean wicketFilterRegistration; + + @Test + void bindsWicketPropertiesFromApplicationProperties() { + assertThat(wicketProperties.getFilterPath()).isEqualTo("/*"); + assertThat(wicketProperties.getFilterName()).isEqualTo("wicket-example-filter"); + assertThat(wicketProperties.getConfiguration()).isEqualTo(RuntimeConfigurationType.DEVELOPMENT); + } + + @Test + void appliesThePropertiesToTheRegisteredWicketFilter() { + assertThat(wicketFilterRegistration.getFilterName()).isEqualTo("wicket-example-filter"); + assertThat(wicketFilterRegistration.getUrlPatterns()).containsExactly("/*"); + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html new file mode 100644 index 0000000000..3b0bf1d76a --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html @@ -0,0 +1,5 @@ + + +placeholder + + diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml index 21c6c00ab3..af6af0accc 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml @@ -66,5 +66,26 @@ jakarta.servlet-api provided + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.apache.wicket + wicket-tester + test + + + + org.springframework + spring-web + test + diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java new file mode 100644 index 0000000000..aa79a24364 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java @@ -0,0 +1,52 @@ +package org.wicketstuff.springboot.starter; + +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.request.resource.PackageResourceReference; +import org.apache.wicket.util.tester.WicketTester; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class DefaultWebApplicationTest { + + private WicketTester tester; + + @BeforeEach + void setUp() { + tester = new WicketTester(new DefaultWebApplication()); + } + + @AfterEach + void tearDown() { + tester.destroy(); + } + + @Test + void homePageIsTheDefaultHomePage() { + assertThat(tester.getApplication().getHomePage()).isEqualTo(DefaultHomePage.class); + } + + @Test + void rendersDefaultHomePageWithTheWicketVersionLabel() { + tester.startPage(DefaultHomePage.class); + + tester.assertRenderedPage(DefaultHomePage.class); + tester.assertComponent("version", Label.class); + } + + @Test + void servesTheMountedCssResource() { + tester.startResourceReference(new PackageResourceReference(DefaultHomePage.class, "style.css")); + + assertThat(tester.getLastResponse().getStatus()).isEqualTo(200); + } + + @Test + void servesTheMountedPngResource() { + tester.startResourceReference(new PackageResourceReference(DefaultHomePage.class, "logo.png")); + + assertThat(tester.getLastResponse().getStatus()).isEqualTo(200); + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java new file mode 100644 index 0000000000..29192c8627 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java @@ -0,0 +1,85 @@ +package org.wicketstuff.springboot.starter; + +import org.apache.wicket.Page; +import org.apache.wicket.RuntimeConfigurationType; +import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.protocol.http.WicketFilter; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +class WicketAutoConfigurationTest { + + private final WebApplicationContextRunner servletContextRunner = new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WicketAutoConfiguration.class)); + + @Test + void registersDefaultWebApplicationAndFilterWhenNoneProvided() { + servletContextRunner.run(context -> { + assertThat(context).hasSingleBean(WebApplication.class); + assertThat(context.getBean(WebApplication.class)).isInstanceOf(DefaultWebApplication.class); + + assertThat(context).hasSingleBean(FilterRegistrationBean.class); + FilterRegistrationBean registration = context.getBean(FilterRegistrationBean.class); + assertThat(registration.getFilter()).isInstanceOf(WicketFilter.class); + assertThat(registration.getUrlPatterns()).containsExactly("/*"); + assertThat(registration.getFilterName()).isEqualTo("wicket-filter"); + assertThat(registration.getInitParameters()) + .containsEntry("configuration", RuntimeConfigurationType.DEVELOPMENT.name()); + }); + } + + @Test + void bindsCustomWicketPropertiesOntoTheFilterRegistration() { + servletContextRunner + .withPropertyValues( + "wicket.filter-path=/app/*", + "wicket.filter-name=custom-wicket-filter", + "wicket.configuration=DEPLOYMENT") + .run(context -> { + FilterRegistrationBean registration = context.getBean(FilterRegistrationBean.class); + assertThat(registration.getUrlPatterns()).containsExactly("/app/*"); + assertThat(registration.getFilterName()).isEqualTo("custom-wicket-filter"); + assertThat(registration.getInitParameters()) + .containsEntry("configuration", RuntimeConfigurationType.DEPLOYMENT.name()); + }); + } + + @Test + void backsOffWhenACustomWebApplicationBeanIsPresent() { + servletContextRunner.withUserConfiguration(CustomWebApplicationConfig.class).run(context -> { + assertThat(context).hasSingleBean(WebApplication.class); + assertThat(context.getBean(WebApplication.class)).isInstanceOf(CustomWebApplication.class); + }); + } + + @Test + void doesNotActivateOutsideServletWebApplications() { + new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(WicketAutoConfiguration.class)) + .run(context -> assertThat(context).doesNotHaveBean(WebApplication.class)); + } + + @Configuration + static class CustomWebApplicationConfig { + + @Bean + WebApplication webApplication() { + return new CustomWebApplication(); + } + } + + static class CustomWebApplication extends WebApplication { + + @Override + public Class getHomePage() { + return DefaultHomePage.class; + } + } +} From 0d2a37ab8fdeda18dfd692764f23be4d0c96e382 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Thu, 17 Sep 2026 23:50:57 +0200 Subject: [PATCH 08/35] Fix inaccuracies in Wicket Spring Boot Starter README - Replace the dependency snippet's undefined \${wicketstuff.version} property (not declared in any pom) with the actual current version and a pointer to Maven Central for the released version. - Fix the Spring Initializr versionRange, which was copy-pasted from an unrelated example (a stray 4.2.0-M1 patch-level bound). Left it open-ended (4.0.0 and later) rather than guessing an unconfirmed future Spring Boot major version number. Co-Authored-By: Claude Sonnet 5 --- wicket-spring-boot-starter-parent/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/wicket-spring-boot-starter-parent/README.md b/wicket-spring-boot-starter-parent/README.md index 83d04972c0..ca31365364 100644 --- a/wicket-spring-boot-starter-parent/README.md +++ b/wicket-spring-boot-starter-parent/README.md @@ -16,13 +16,15 @@ A lightweight, zero-boilerplate starter that integrates **Apache Wicket 10.x** w ## Dependency Configuration -To use the starter, add the following dependency to your Maven `pom.xml`: +To use the starter, add the following dependency to your Maven `pom.xml` (check +[Maven Central](https://central.sonatype.com/artifact/org.wicketstuff/wicket-spring-boot-starter) +for the latest released version): ```xml org.wicketstuff wicket-spring-boot-starter - ${wicketstuff.version} + 10.12.0-SNAPSHOT ``` @@ -129,7 +131,7 @@ wicket.filter-name=my-custom-wicket-filter ## Spring Initializr Metadata Registration -If you are requesting this starter to be listed on `start.spring.io` (or registering it in an internal Initializr instance), configure the dependency metadata as follows: +If you are requesting this starter to be listed on `start.spring.io` (or registering it in an internal Initializr instance), configure the dependency metadata as follows. `versionRange` expresses the Spring Boot versions this starter supports (see the Compatibility Matrix above), not the starter's own version. It's left open-ended here (`4.0.0` and any later version) since nothing in the starter's autoconfiguration mechanism is expected to break across future Spring Boot majors — add an explicit upper bound only once a specific incompatibility is found: ### YAML Configuration (e.g. `application.yml`) ```yaml @@ -142,7 +144,7 @@ initializr: description: Apache Wicket component-oriented web application framework integrated with Spring Boot. groupId: org.wicketstuff artifactId: wicket-spring-boot-starter - versionRange: "[4.0.0,4.2.0-M1)" + versionRange: "4.0.0" links: - rel: reference href: https://github.com/wicketstuff/core/tree/master/wicket-spring-boot-starter-parent @@ -158,7 +160,7 @@ initializr: "description": "Apache Wicket component-oriented web application framework integrated with Spring Boot.", "groupId": "org.wicketstuff", "artifactId": "wicket-spring-boot-starter", - "versionRange": "[4.0.0,4.2.0-M1)", + "versionRange": "4.0.0", "links": [ { "rel": "reference", From 44e182843ee6fb6610e09c939ae0bd9c6fed7a6b Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 02:10:40 +0200 Subject: [PATCH 09/35] Refresh the starter's default home page content Replace the copy inherited from Wicket's old quickstart archetype with content specific to this starter: drop the dead Freenode IRC link and outdated JIRA bug-report walkthrough, explain why the page is shown, and link to the starter's own README Quickstart and the Wicket docs instead. Also fixes the static "1.5-SNAPSHOT" placeholder text (cosmetic only -- always overwritten at runtime by the version Label). Co-Authored-By: Claude Sonnet 5 --- .../springboot/starter/DefaultHomePage.html | 49 +++++++------------ 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html index 1054476db5..4ddf2a2824 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html @@ -2,7 +2,7 @@ - Apache Wicket Quickstart + Wicket Spring Boot Starter @@ -10,47 +10,32 @@
-

Congratulations!

+

It works!

- Your quick start works! This project is especially useful to - start developing your Wicket application or to create a test - case for a bug report. + This is the default page served by the Wicket Spring Boot Starter, running on + Apache Wicket 10.x. + It's shown because your application hasn't registered its own WebApplication + bean yet.

-

Get started

+

Next steps

- From here you can start hacking away at your application and - wow your clients: -

- -

Get help

-

- We are here to help! -

- -

Reporting a bug

-

- Help us help you: + Replace this page by registering your own Wicket application as a Spring bean:

    -
  1. reproduce the bug with the least amount of code
  2. -
  3. create a unit test that shows the bug
  4. -
  5. fix the bug and create a patch
  6. -
  7. attach the result of step 1, 2 or 3 to a JIRA issue
  8. -
  9. profit!
  10. +
  11. Create a WebApplication subclass annotated with @Component.
  12. +
  13. Point its getHomePage() to your own WebPage.
  14. +
  15. Optionally inject Spring beans into your pages with @SpringBean.

- Please mention the correct Wicket version: 1.5-SNAPSHOT. + See the starter's + README + for the full Quickstart, or the + Apache Wicket documentation + to learn more about building pages and components.

From fd8090d09e24716adef308b622420eeab21d0262 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 02:14:36 +0200 Subject: [PATCH 10/35] Add LICENSE file to Wicket Spring Boot Starter module The root pom.xml already declares Apache License 2.0 (inherited by this module and its children), but there was no physical LICENSE file anywhere in the repo to make that unambiguous to someone browsing this module's directory directly, e.g. Spring Initializr maintainers reviewing the submission. Co-Authored-By: Claude Sonnet 5 --- wicket-spring-boot-starter-parent/LICENSE | 201 ++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 wicket-spring-boot-starter-parent/LICENSE diff --git a/wicket-spring-boot-starter-parent/LICENSE b/wicket-spring-boot-starter-parent/LICENSE new file mode 100644 index 0000000000..9af2673380 --- /dev/null +++ b/wicket-spring-boot-starter-parent/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the + purposes of this License, Derivative Works shall not include works + that remain separable from, or merely link (or bind by name) to the + interfaces of, the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including the + original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 89bfe58dc1a67316c983994c8fc836d2029209d7 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 02:21:50 +0200 Subject: [PATCH 11/35] Give wicket.configuration a real default and clean up imports WicketProperties.configuration was left null unless explicitly set, with the DEVELOPMENT fallback only applied manually inside WicketAutoConfiguration. This meant the property's generated IDE metadata (spring-configuration-metadata.json) had no defaultValue, unlike the other two wicket.* properties, contradicting both its own Javadoc and the README's documented default. Initializing the field directly fixes the metadata and lets the now-dead null-check in WicketAutoConfiguration go away, along with its now-unused RuntimeConfigurationType import. Also cleans up DefaultWebApplication to use proper imports and Java 17 pattern-matching instanceof instead of inline fully-qualified names and a manual cast. Co-Authored-By: Claude Sonnet 5 --- .../springboot/starter/DefaultWebApplication.java | 12 +++++++----- .../springboot/starter/WicketAutoConfiguration.java | 8 +------- .../springboot/starter/WicketProperties.java | 6 +++--- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java index 44f92f448d..ca4c894cf9 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java @@ -1,7 +1,10 @@ package org.wicketstuff.springboot.starter; import org.apache.wicket.Page; +import org.apache.wicket.markup.html.IPackageResourceGuard; +import org.apache.wicket.markup.html.SecurePackageResourceGuard; import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.request.resource.PackageResourceReference; /** * The default {@link WebApplication} used by the Wicket Spring Boot Starter @@ -19,13 +22,12 @@ protected void init() { super.init(); // Mount resources to serve style.css and logo.png from the application root path - mountResource("style.css", new org.apache.wicket.request.resource.PackageResourceReference(DefaultHomePage.class, "style.css")); - mountResource("logo.png", new org.apache.wicket.request.resource.PackageResourceReference(DefaultHomePage.class, "logo.png")); + mountResource("style.css", new PackageResourceReference(DefaultHomePage.class, "style.css")); + mountResource("logo.png", new PackageResourceReference(DefaultHomePage.class, "logo.png")); // Ensure the package resource guard allows requests for these resources - org.apache.wicket.markup.html.IPackageResourceGuard guard = getResourceSettings().getPackageResourceGuard(); - if (guard instanceof org.apache.wicket.markup.html.SecurePackageResourceGuard) { - org.apache.wicket.markup.html.SecurePackageResourceGuard secureGuard = (org.apache.wicket.markup.html.SecurePackageResourceGuard) guard; + IPackageResourceGuard guard = getResourceSettings().getPackageResourceGuard(); + if (guard instanceof SecurePackageResourceGuard secureGuard) { secureGuard.addPattern("+*.css"); secureGuard.addPattern("+*.png"); } diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index 141d0f21d7..cace1636b9 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -2,7 +2,6 @@ import jakarta.servlet.FilterConfig; import jakarta.servlet.ServletException; -import org.apache.wicket.RuntimeConfigurationType; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.http.WicketFilter; import org.apache.wicket.spring.injection.annot.SpringComponentInjector; @@ -99,12 +98,7 @@ public void init(boolean isServlet, FilterConfig filterConfig) throws ServletExc // Specify configuration parameter mapping for Wicket registration.addInitParameter(WicketFilter.FILTER_MAPPING_PARAM, properties.getFilterPath()); - - RuntimeConfigurationType configType = properties.getConfiguration(); - if (configType == null) { - configType = RuntimeConfigurationType.DEVELOPMENT; - } - registration.addInitParameter("configuration", configType.name()); + registration.addInitParameter("configuration", properties.getConfiguration().name()); return registration; } } diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java index 9ac006f422..782cafc3d8 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java @@ -35,10 +35,10 @@ public class WicketProperties { * Wicket execution configuration type. *

* Can be set to {@link RuntimeConfigurationType#DEVELOPMENT} or {@link RuntimeConfigurationType#DEPLOYMENT}. - * If not explicitly defined, it defaults to {@code DEVELOPMENT}. + * Default is {@link RuntimeConfigurationType#DEVELOPMENT}. *

*/ - private RuntimeConfigurationType configuration; + private RuntimeConfigurationType configuration = RuntimeConfigurationType.DEVELOPMENT; /** * Gets the URL mapping pattern for the Wicket Filter. @@ -79,7 +79,7 @@ public void setFilterName(String filterName) { /** * Gets the Wicket execution configuration type. * - * @return the configuration type, or {@code null} if not configured + * @return the configuration type */ public RuntimeConfigurationType getConfiguration() { return configuration; From 88d893e3d08daddecdf5362a7351d00a0b978fa7 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 02:28:02 +0200 Subject: [PATCH 12/35] Fix filter registration not backing off for custom registrations @ConditionalOnMissingBean(WicketFilter.class) was declared on a method producing a FilterRegistrationBean, so the condition never examined what the method actually creates. A user registering their own FilterRegistrationBean -- the customization path the README points at -- ended up with two Wicket filters, ours silently mapped at /*. Conversely a raw WicketFilter bean made us back off entirely, leaving Boot to auto-register it with no init parameters and no SpringComponentInjector, quietly breaking @SpringBean. Using a bare @ConditionalOnMissingBean lets Boot deduce the bean type from the return value including its generics, so a user-supplied FilterRegistrationBean now correctly wins. Covered by a new regression test. Also removes two pieces of dead/fragile code found while reviewing: - DefaultWebApplication re-added "+*.css"/"+*.png" resource guard patterns that SecurePackageResourceGuard's constructor already registers by default. - The @NonNull on a private helper's return type came from org.jspecify, which this module never declared and only got transitively via Wicket. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012N3ZXf1gtmcbQ2jWcqyDTF --- .../starter/DefaultWebApplication.java | 9 ------- .../starter/WicketAutoConfiguration.java | 5 ++-- .../starter/WicketAutoConfigurationTest.java | 24 +++++++++++++++++++ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java index ca4c894cf9..c094a29d2b 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java @@ -1,8 +1,6 @@ package org.wicketstuff.springboot.starter; import org.apache.wicket.Page; -import org.apache.wicket.markup.html.IPackageResourceGuard; -import org.apache.wicket.markup.html.SecurePackageResourceGuard; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.request.resource.PackageResourceReference; @@ -24,12 +22,5 @@ protected void init() { // Mount resources to serve style.css and logo.png from the application root path mountResource("style.css", new PackageResourceReference(DefaultHomePage.class, "style.css")); mountResource("logo.png", new PackageResourceReference(DefaultHomePage.class, "logo.png")); - - // Ensure the package resource guard allows requests for these resources - IPackageResourceGuard guard = getResourceSettings().getPackageResourceGuard(); - if (guard instanceof SecurePackageResourceGuard secureGuard) { - secureGuard.addPattern("+*.css"); - secureGuard.addPattern("+*.png"); - } } } diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index cace1636b9..8c637c065b 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -5,7 +5,6 @@ import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.http.WicketFilter; import org.apache.wicket.spring.injection.annot.SpringComponentInjector; -import org.jspecify.annotations.NonNull; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -59,7 +58,7 @@ public WebApplication webApplication() { * @return the configured FilterRegistrationBean for WicketFilter */ @Bean - @ConditionalOnMissingBean(WicketFilter.class) + @ConditionalOnMissingBean public FilterRegistrationBean wicketFilterRegistration( WebApplication webApplication, WicketProperties properties, @@ -89,7 +88,7 @@ public void init(boolean isServlet, FilterConfig filterConfig) throws ServletExc * @param filter the {@link WicketFilter} to be configured and registered * @return a configured {@link FilterRegistrationBean} instance for the provided {@link WicketFilter} */ - private static @NonNull FilterRegistrationBean configureWicketFilter( + private static FilterRegistrationBean configureWicketFilter( WicketProperties properties, WicketFilter filter) { FilterRegistrationBean registration = new FilterRegistrationBean<>(); registration.setFilter(filter); diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java index 29192c8627..3b42601b6e 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java @@ -59,6 +59,17 @@ void backsOffWhenACustomWebApplicationBeanIsPresent() { }); } + @Test + void backsOffWhenACustomWicketFilterRegistrationIsPresent() { + servletContextRunner.withUserConfiguration(CustomFilterRegistrationConfig.class).run(context -> { + assertThat(context).hasSingleBean(FilterRegistrationBean.class); + + FilterRegistrationBean registration = context.getBean(FilterRegistrationBean.class); + assertThat(registration.getFilterName()).isEqualTo("custom-wicket-filter"); + assertThat(registration.getUrlPatterns()).containsExactly("/custom/*"); + }); + } + @Test void doesNotActivateOutsideServletWebApplications() { new ApplicationContextRunner() @@ -75,6 +86,19 @@ WebApplication webApplication() { } } + @Configuration + static class CustomFilterRegistrationConfig { + + @Bean + FilterRegistrationBean customWicketFilterRegistration() { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + registration.setFilter(new WicketFilter(new CustomWebApplication())); + registration.addUrlPatterns("/custom/*"); + registration.setName("custom-wicket-filter"); + return registration; + } + } + static class CustomWebApplication extends WebApplication { @Override From f549859df32b70ead4e3da1e3099d0f0e5bc7856 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 02:38:03 +0200 Subject: [PATCH 13/35] Bind SpringComponentInjector to the WebApplication, not the filter The injector was registered inside an anonymous WicketFilter subclass's init(). Now that the filter registration correctly backs off for an application-supplied FilterRegistrationBean, that back-off took Spring injection with it: requesting a page in that setup returned HTTP 500, because @SpringBean fields were never injected and the page NPE'd. Wicket's own documentation registers the injector on the WebApplication rather than the filter, and SpringComponentInjector's constructor only sets application metadata and binds, so it has no dependency on filter initialisation. Moving it to its own bean keyed off the WebApplication keeps injection working whoever owns the filter registration, and drops the anonymous subclass entirely. Exposing it as a @ConditionalOnMissingBean bean also gives applications migrating from a hand-wired Wicket/Spring setup a way to suppress it, instead of silently ending up with two injectors when their own WebApplication.init() already registers one. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012N3ZXf1gtmcbQ2jWcqyDTF --- ...ctionWithCustomFilterRegistrationTest.java | 65 +++++++++++++++++++ .../starter/WicketAutoConfiguration.java | 45 +++++++------ 2 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java new file mode 100644 index 0000000000..280e90c0f7 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java @@ -0,0 +1,65 @@ +package org.wicketstuff.springboot.starter.example; + +import org.apache.wicket.protocol.http.WebApplication; +import org.apache.wicket.protocol.http.WicketFilter; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.resttestclient.TestRestTemplate; +import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * An application that supplies its own {@link FilterRegistrationBean} makes the starter's + * registration back off. Spring injection must keep working regardless, which is why the + * {@code SpringComponentInjector} is bound to the {@link WebApplication} bean rather than to the + * filter registration. + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureTestRestTemplate +@Import(SpringBeanInjectionWithCustomFilterRegistrationTest.CustomRegistrationConfig.class) +class SpringBeanInjectionWithCustomFilterRegistrationTest { + + @Autowired + private TestRestTemplate restTemplate; + + @Test + void stillInjectsSpringBeansWhenTheFilterRegistrationIsOverridden() { + ResponseEntity response = restTemplate.getForEntity("/", String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).contains("Hello from Spring, Wicket!"); + } + + @TestConfiguration + static class CustomRegistrationConfig { + + @Bean + WebApplication webApplication() { + return new QuickstartWebApplication(); + } + + @Bean + GreetingService greetingService() { + return () -> "Hello from Spring, Wicket!"; + } + + @Bean + FilterRegistrationBean customWicketFilterRegistration(WebApplication webApplication) { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + registration.setFilter(new WicketFilter(webApplication)); + registration.addUrlPatterns("/*"); + registration.setName("custom-wicket-filter"); + registration.addInitParameter(WicketFilter.FILTER_MAPPING_PARAM, "/*"); + registration.addInitParameter("configuration", "DEVELOPMENT"); + return registration; + } + } +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index 8c637c065b..0c83ffb623 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -1,7 +1,5 @@ package org.wicketstuff.springboot.starter; -import jakarta.servlet.FilterConfig; -import jakarta.servlet.ServletException; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.http.WicketFilter; import org.apache.wicket.spring.injection.annot.SpringComponentInjector; @@ -46,37 +44,44 @@ public WebApplication webApplication() { } /** - * Creates and configures the {@link FilterRegistrationBean} for the {@link WicketFilter}. + * Registers the {@link SpringComponentInjector} against the {@link WebApplication} bean so that + * Wicket pages and components can inject Spring beans via + * {@link org.apache.wicket.spring.injection.annot.SpringBean}. *

- * Instantiates WicketFilter with the provided {@link WebApplication} bean and attaches - * a {@link SpringComponentInjector} during filter initialization to enable Spring bean injection. + * This is deliberately bound to the {@link WebApplication} rather than to the filter + * registration: an application that supplies its own {@link FilterRegistrationBean} still gets + * working Spring injection. *

* * @param webApplication the auto-discovered Wicket WebApplication subclass bean - * @param properties the externalized Wicket properties * @param applicationContext the Spring application context - * @return the configured FilterRegistrationBean for WicketFilter + * @return the injector registered as a component instantiation listener */ @Bean @ConditionalOnMissingBean - public FilterRegistrationBean wicketFilterRegistration( + public SpringComponentInjector springComponentInjector( WebApplication webApplication, - WicketProperties properties, ApplicationContext applicationContext) { - WicketFilter filter = new WicketFilter(webApplication) { - @Override - public void init(boolean isServlet, FilterConfig filterConfig) throws ServletException { - super.init(isServlet, filterConfig); - // Register SpringComponentInjector so Wicket pages can inject Spring @Components / @Beans using @SpringBean. - webApplication.getComponentInstantiationListeners().add( - new SpringComponentInjector(webApplication, applicationContext) - ); - } - }; + SpringComponentInjector injector = new SpringComponentInjector(webApplication, applicationContext); + webApplication.getComponentInstantiationListeners().add(injector); + return injector; + } - return configureWicketFilter(properties, filter); + /** + * Creates and configures the {@link FilterRegistrationBean} for the {@link WicketFilter}. + * + * @param webApplication the auto-discovered Wicket WebApplication subclass bean + * @param properties the externalized Wicket properties + * @return the configured FilterRegistrationBean for WicketFilter + */ + @Bean + @ConditionalOnMissingBean + public FilterRegistrationBean wicketFilterRegistration( + WebApplication webApplication, + WicketProperties properties) { + return configureWicketFilter(properties, new WicketFilter(webApplication)); } /** From 683a96e552172e4eb326edc84547e6f9cb0c1c2e Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 02:41:08 +0200 Subject: [PATCH 14/35] Add wicket.enabled to switch the auto-configuration off Third-party starters are generally expected to offer an opt-out, and there was no way to keep the starter on the classpath while disabling it. @ConditionalOnProperty sits on the auto-configuration class rather than on individual beans so the default WebApplication, the injector and the filter registration all switch off together instead of leaving a half-configured application. matchIfMissing keeps it on by default, so existing applications are unaffected. The property is read only by the condition and never bound to a field, so it is documented through additional-spring-configuration-metadata.json rather than by adding an unused field to WicketProperties. The annotation processor merges it into the generated metadata, so IDE completion covers it alongside the other wicket.* properties. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012N3ZXf1gtmcbQ2jWcqyDTF --- wicket-spring-boot-starter-parent/README.md | 1 + .../springboot/starter/WicketAutoConfiguration.java | 5 +++++ .../additional-spring-configuration-metadata.json | 10 ++++++++++ .../starter/WicketAutoConfigurationTest.java | 10 ++++++++++ 4 files changed, 26 insertions(+) create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json diff --git a/wicket-spring-boot-starter-parent/README.md b/wicket-spring-boot-starter-parent/README.md index ca31365364..e618901301 100644 --- a/wicket-spring-boot-starter-parent/README.md +++ b/wicket-spring-boot-starter-parent/README.md @@ -116,6 +116,7 @@ The following properties can be configured in your `application.properties` or ` | Property | Default Value | Description | |---|---|---| +| `wicket.enabled` | `true` | Set to `false` to switch the auto-configuration off entirely. | | `wicket.filter-path` | `/*` | URL mapping pattern for the Wicket filter. | | `wicket.filter-name` | `wicket-filter` | The name of the registered Wicket servlet filter. | | `wicket.configuration` | `DEVELOPMENT` | The configuration type: `DEVELOPMENT` or `DEPLOYMENT`. | diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index 0c83ffb623..e8e538c239 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -6,6 +6,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -22,12 +23,16 @@ * to enable Spring bean injection (via {@link org.apache.wicket.spring.injection.annot.SpringBean}) * inside Wicket pages and components. *

+ *

+ * Set {@code wicket.enabled=false} to switch the whole auto-configuration off. + *

* * @author WicketStuff */ @AutoConfiguration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({WebApplication.class, WicketFilter.class}) +@ConditionalOnProperty(prefix = "wicket", name = "enabled", havingValue = "true", matchIfMissing = true) @EnableConfigurationProperties(WicketProperties.class) public class WicketAutoConfiguration { diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 0000000000..5f4afde051 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,10 @@ +{ + "properties": [ + { + "name": "wicket.enabled", + "type": "java.lang.Boolean", + "description": "Whether the Wicket auto-configuration is enabled. When false, no WebApplication, SpringComponentInjector or Wicket filter registration is contributed.", + "defaultValue": true + } + ] +} diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java index 3b42601b6e..5d1c24bec3 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java @@ -4,6 +4,7 @@ import org.apache.wicket.RuntimeConfigurationType; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.protocol.http.WicketFilter; +import org.apache.wicket.spring.injection.annot.SpringComponentInjector; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; @@ -70,6 +71,15 @@ void backsOffWhenACustomWicketFilterRegistrationIsPresent() { }); } + @Test + void doesNotActivateWhenDisabledByProperty() { + servletContextRunner.withPropertyValues("wicket.enabled=false").run(context -> { + assertThat(context).doesNotHaveBean(WebApplication.class); + assertThat(context).doesNotHaveBean(FilterRegistrationBean.class); + assertThat(context).doesNotHaveBean(SpringComponentInjector.class); + }); + } + @Test void doesNotActivateOutsideServletWebApplications() { new ApplicationContextRunner() From bfbeab88cb44f70602906ce4d90f33ba9af9e89c Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 02:50:54 +0200 Subject: [PATCH 15/35] Make the starter self-sufficient by bringing the web stack A project whose only dependency is this starter got no embedded servlet container, no spring-web, and jakarta.servlet-api only at provided scope. Spring Boot therefore booted it as a non-web application, @ConditionalOnWebApplication(SERVLET) declined, and the application exited having served nothing. That is precisely the project Spring Initializr generates when a user selects Wicket and nothing else, and Initializr metadata has no way to express "also add Spring Web", so every generated project would have been dead on arrival. Depending on spring-boot-starter-web fixes it: the same minimal project now starts Tomcat, registers the WebApplication and serves the default page. The examples module drops its own spring-boot-starter-web and spring-boot-starter-logging declarations as a result, so it now depends on nothing but the starter and demonstrates that one dependency is genuinely enough. Also drops the Google Fonts stylesheet from the default page. It was fetched on every render of a page shipped into every generated project, which breaks in offline and air-gapped environments and makes the page hotlink a third-party service by default, for no benefit given the CSS already declared fallback fonts. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012N3ZXf1gtmcbQ2jWcqyDTF --- wicket-spring-boot-starter-parent/README.md | 3 ++- .../wicket-spring-boot-starter-examples/pom.xml | 16 ++-------------- .../wicket-spring-boot-starter/pom.xml | 7 +++++++ .../springboot/starter/DefaultHomePage.html | 1 - .../org/wicketstuff/springboot/starter/style.css | 2 +- 5 files changed, 12 insertions(+), 17 deletions(-) diff --git a/wicket-spring-boot-starter-parent/README.md b/wicket-spring-boot-starter-parent/README.md index e618901301..676b2ab563 100644 --- a/wicket-spring-boot-starter-parent/README.md +++ b/wicket-spring-boot-starter-parent/README.md @@ -16,7 +16,8 @@ A lightweight, zero-boilerplate starter that integrates **Apache Wicket 10.x** w ## Dependency Configuration -To use the starter, add the following dependency to your Maven `pom.xml` (check +This is the only dependency you need: it brings Apache Wicket, the Wicket/Spring bridge and the +embedded servlet container with it. Add it to your Maven `pom.xml` (check [Maven Central](https://central.sonatype.com/artifact/org.wicketstuff/wicket-spring-boot-starter) for the latest released version): diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml index 96d266b32a..3a2ba14d2a 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml @@ -20,26 +20,14 @@ - + org.wicketstuff wicket-spring-boot-starter ${project.version} - - - org.springframework.boot - spring-boot-starter-web - - - - - org.springframework.boot - spring-boot-starter-logging - - org.springframework.boot diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml index af6af0accc..8f7ce135bf 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml @@ -54,6 +54,13 @@ org.springframework.boot spring-boot-autoconfigure + + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-configuration-processor diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html index 4ddf2a2824..02a6aa8c5c 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html @@ -3,7 +3,6 @@ Wicket Spring Boot Starter - diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css index 87576a78c7..9829f1e162 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css @@ -1,5 +1,5 @@ body, p, li, a { font-family: georgia, times, serif;font-size:13pt;} -h1, h2, h3 { font-family: 'Yanone Kaffeesatz', arial, serif; } +h1, h2, h3 { font-family: "Helvetica Neue", helvetica, arial, sans-serif; } body { margin:0;padding:0;} #hd { width : 100%; From 47e7d2af8c1754cefc2d2790184d297e2da90800 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 03:08:52 +0200 Subject: [PATCH 16/35] Guard the starter's self-sufficiency with a smoke test The packaging bug fixed in the previous commit -- the starter not bringing a servlet container, so a project depending only on it booted as a non-web application -- was invisible to the whole test suite, because both modules used to declare the web stack themselves. StarterSelfSufficiencyTest closes that gap. This module declares nothing but the starter at compile scope, so the container it boots can only have come transitively from the starter. A bannedDependencies enforcer rule keeps that precondition honest: declaring a Spring Boot starter here would satisfy the test without the starter supplying anything, so the rule fails the build and points at the starter instead. Only direct declarations are checked, leaving the starter's own transitives alone. Both guards were verified by deliberately breaking them. Note that when the starter stops supplying the web stack the build fails during test compilation, in the test that legitimately needs jakarta.servlet.Filter, rather than with this test's assertion message. The regression is caught either way, and the enforcer blocks the tempting local fix. Also documents a footgun this surfaced: Wicket keys its application registry by filter name and Spring caches test contexts, so tests that each start a container must set distinct wicket.filter-name values. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012N3ZXf1gtmcbQ2jWcqyDTF --- wicket-spring-boot-starter-parent/README.md | 22 +++++++ .../pom.xml | 36 +++++++++++ .../example/StarterSelfSufficiencyTest.java | 61 +++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java diff --git a/wicket-spring-boot-starter-parent/README.md b/wicket-spring-boot-starter-parent/README.md index 676b2ab563..423a03aab2 100644 --- a/wicket-spring-boot-starter-parent/README.md +++ b/wicket-spring-boot-starter-parent/README.md @@ -131,6 +131,28 @@ wicket.filter-name=my-custom-wicket-filter --- +## Testing + +Wicket keys its application registry by the filter name, and Spring keeps test contexts cached for +the lifetime of the JVM. Two tests that each start a real servlet container therefore collide on the +default filter name, failing with `Application with name 'wicket-filter' already exists`. + +Give each such test its own filter name: + +```java +@SpringBootTest( + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = "wicket.filter-name=my-test-filter") +class MyIntegrationTest { + // ... +} +``` + +Tests that do not start a container (the default `MOCK` web environment) are unaffected, because the +filter is never initialised. + +--- + ## Spring Initializr Metadata Registration If you are requesting this starter to be listed on `start.spring.io` (or registering it in an internal Initializr instance), configure the dependency metadata as follows. `versionRange` expresses the Spring Boot versions this starter supports (see the Compatibility Matrix above), not the starter's own version. It's left open-ended here (`4.0.0` and any later version) since nothing in the starter's autoconfiguration mechanism is expected to break across future Spring Boot majors — add an explicit upper bound only once a specific incompatibility is found: diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml index 3a2ba14d2a..e27ffc80a2 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml @@ -54,6 +54,42 @@ + + + org.apache.maven.plugins + maven-enforcer-plugin + + + enforce-starter-is-the-only-compile-dependency + + enforce + + + + + false + + org.springframework.boot:spring-boot-starter-* + + + org.springframework.boot:spring-boot-starter-*:*:*:test + + + This example must depend on nothing but wicket-spring-boot-starter at + compile scope, so that StarterSelfSufficiencyTest proves the starter + brings a working web application on its own. Declaring a Spring Boot + starter here would satisfy that test without the starter supplying + anything. Add the dependency to the starter instead. + + + + + + + org.springframework.boot spring-boot-maven-plugin diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java new file mode 100644 index 0000000000..283efc0fe4 --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java @@ -0,0 +1,61 @@ +package org.wicketstuff.springboot.starter.example; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.resttestclient.TestRestTemplate; +import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Guards the contract that {@code wicket-spring-boot-starter} is the only dependency an + * application needs. + *

+ * This module deliberately declares nothing but the starter at compile scope, so the embedded + * servlet container exercised here can only have arrived transitively from the starter itself. + * Without that, a project generated by Spring Initializr with just "Wicket" selected boots as a + * plain non-web application and silently serves nothing. + *

+ *

+ * A {@code bannedDependencies} enforcer rule in this module's pom keeps that precondition true: + * declaring a Spring Boot starter here at compile scope would make this test pass without the + * starter supplying anything. + *

+ *

+ * The filter name is overridden because Wicket keys its application registry by it, so two tests + * that each start a real container in the same JVM collide on the default name. + *

+ */ +@SpringBootTest( + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = "wicket.filter-name=self-sufficiency-filter") +@AutoConfigureTestRestTemplate +class StarterSelfSufficiencyTest { + + @Autowired + private ApplicationContext context; + + @Autowired + private TestRestTemplate restTemplate; + + /** + * Asserted on the class name rather than the type so that this class does not itself need a + * servlet-only import, which would make it fail to compile rather than fail as a test. + */ + @Test + void theStarterAloneBootsAServletWebApplication() { + assertThat(context.getClass().getName()).endsWith("ServletWebServerApplicationContext"); + } + + @Test + void theStarterAloneServesTheDefaultHomePage() { + ResponseEntity response = restTemplate.getForEntity("/", String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).contains("Wicket Spring Boot Starter"); + } +} From c7e5ec498aa43e69c32f2bf0993372ed8ef0c961 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 03:20:21 +0200 Subject: [PATCH 17/35] Document what the starter actually contributes The README explained what to type but never what the starter does. It did not mention the beans the auto-configuration contributes, that each steps aside when you define your own, the conditions under which it applies at all, or that a project gets a placeholder home page until it registers a WebApplication -- which is the first thing a generated project shows. Adds How It Works (activation conditions and the three beans), The Default Page, Overriding the Defaults, and a migration note for applications that already register a SpringComponentInjector by hand and would otherwise end up with two. Every claim was checked against WicketAutoConfiguration rather than against the previous wording. Also answers a question the previous commit created. Depending on spring-boot-starter-web means every application now has Spring MVC's DispatcherServlet alongside Wicket's filter at /*, so whether @RestController endpoints still work is the obvious thing to ask. WicketAndSpringMvcCoexistenceTest establishes that they do -- Wicket forwards what it does not handle down the filter chain -- so the README documents verified behaviour with a regression test behind it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012N3ZXf1gtmcbQ2jWcqyDTF --- wicket-spring-boot-starter-parent/README.md | 96 +++++++++++++++++++ .../WicketAndSpringMvcCoexistenceTest.java | 56 +++++++++++ 2 files changed, 152 insertions(+) create mode 100644 wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java diff --git a/wicket-spring-boot-starter-parent/README.md b/wicket-spring-boot-starter-parent/README.md index 423a03aab2..0b7644aca9 100644 --- a/wicket-spring-boot-starter-parent/README.md +++ b/wicket-spring-boot-starter-parent/README.md @@ -14,6 +14,46 @@ A lightweight, zero-boilerplate starter that integrates **Apache Wicket 10.x** w --- +## How It Works + +The starter contributes a single auto-configuration, `WicketAutoConfiguration`. It applies only when +all of the following hold: + +- the application is a **servlet** web application (a reactive application is left alone); +- Wicket's `WebApplication` and `WicketFilter` are on the classpath; +- `wicket.enabled` is not set to `false`. + +When it applies, three beans are contributed: + +| Bean | What it does | +|---|---| +| `webApplication` | The Wicket `WebApplication`. Falls back to a built-in default (see below) if you have not defined one. | +| `springComponentInjector` | Registers Wicket's `SpringComponentInjector` against the `WebApplication`, which is what makes `@SpringBean` work inside pages and components. | +| `wicketFilterRegistration` | Registers `WicketFilter` with the servlet container, mapped at `wicket.filter-path`, passing Wicket's filter-mapping and `configuration` init parameters from your settings. | + +### Living alongside Spring MVC + +The starter brings `spring-boot-starter-web`, so your application also has Spring MVC available. +Wicket's filter is mapped at `/*` but forwards anything it does not handle further down the filter +chain, so `@RestController` endpoints keep working next to Wicket pages: + +```java +@RestController +class GreetingController { + + @GetMapping("/api/greeting") + String greeting() { + return "hello"; + } +} +``` + +With the defaults, `/api/greeting` reaches the controller while `/` renders your Wicket home page. +If you would rather keep the two strictly apart, confine Wicket to its own prefix with +`wicket.filter-path=/app/*`. + +--- + ## Dependency Configuration This is the only dependency you need: it brings Apache Wicket, the Wicket/Spring bridge and the @@ -41,6 +81,18 @@ Ensure you match the correct starter version with your Spring Boot and Java envi --- +## The Default Page + +Add the dependency, start the application, and you already have a running Wicket application: with +no `WebApplication` bean of your own, the starter registers a built-in one that serves a placeholder +home page telling you how to replace it. + +That default disappears the moment you declare your own `WebApplication` bean, which is what the +Quickstart below does. It exists so a freshly generated project runs and shows something, not as a +page you are meant to keep. + +--- + ## Quickstart ### 1. Create a Wicket Application Component @@ -111,6 +163,40 @@ public class ExampleApplication { --- +## Overriding the Defaults + +Every bean the starter contributes steps aside as soon as you define your own, so you can take over +as much or as little as you need: + +| Bean | Steps aside when | Define your own to | +|---|---|---| +| `webApplication` | any `WebApplication` bean exists | use your own Wicket application (the usual case — see the Quickstart) | +| `springComponentInjector` | any `SpringComponentInjector` bean exists | control how Spring injection is wired | +| `wicketFilterRegistration` | a `FilterRegistrationBean` bean exists | control the filter registration, e.g. its order relative to other filters | + +Overriding the filter registration does **not** cost you Spring injection: the injector is bound to +the `WebApplication` rather than to the filter, so `@SpringBean` keeps working in your pages either +way. + +### Migrating an existing Wicket + Spring application + +Applications that wire Wicket and Spring by hand usually register the injector themselves, along +these lines: + +```java +@Override +protected void init() { + super.init(); + getComponentInstantiationListeners().add(new SpringComponentInjector(this)); +} +``` + +Keeping that line as well as the starter's bean would register two injectors. Either drop it and let +the starter do it, or, if you want to keep control of the wiring, declare your own +`SpringComponentInjector` bean so the starter's backs off. + +--- + ## Configuration Properties The following properties can be configured in your `application.properties` or `application.yml` file: @@ -197,3 +283,13 @@ initializr: ] } ``` + +--- + +## Further Reading + +- [Apache Wicket documentation](https://wicket.apache.org/) — writing pages, components and markup. +- [WicketStuff wiki](https://github.com/wicketstuff/core/wiki) — documentation for the other modules + in this project. +- [API documentation](https://www.javadoc.io/doc/org.wicketstuff/wicket-spring-boot-starter) — the + starter's own Javadoc, published per release. diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java new file mode 100644 index 0000000000..f7ac41019b --- /dev/null +++ b/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java @@ -0,0 +1,56 @@ +package org.wicketstuff.springboot.starter.example; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.resttestclient.TestRestTemplate; +import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * The starter depends on {@code spring-boot-starter-web}, so every application also has Spring + * MVC's {@code DispatcherServlet} while Wicket's filter is mapped at {@code /*}. This pins down + * that the two coexist: Wicket serves its pages and passes anything it does not handle further + * down the filter chain, so {@code @RestController} endpoints stay reachable. + */ +@SpringBootTest( + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = "wicket.filter-name=mvc-coexistence-filter") +@AutoConfigureTestRestTemplate +@Import(WicketAndSpringMvcCoexistenceTest.GreetingController.class) +class WicketAndSpringMvcCoexistenceTest { + + @Autowired + private TestRestTemplate restTemplate; + + @Test + void springMvcEndpointsRemainReachableBehindTheWicketFilter() { + ResponseEntity response = restTemplate.getForEntity("/api/greeting", String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isEqualTo("hello from spring mvc"); + } + + @Test + void wicketStillServesItsOwnPages() { + ResponseEntity response = restTemplate.getForEntity("/", String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).contains("Wicket Spring Boot Starter"); + } + + @RestController + static class GreetingController { + + @GetMapping("/api/greeting") + String greeting() { + return "hello from spring mvc"; + } + } +} From 9d5b1ac3eddee105d4176c522408f83b128ef354 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 03:42:53 +0200 Subject: [PATCH 18/35] Rename to wicketstuff-spring-boot-starter and explain the motivation The artifact followed Spring's documented convention for third-party starters ({name}-spring-boot-starter), but so does the established com.giffing.wicket.spring.boot.starter:wicket-spring-boot-starter, so both landed on an identical artifactId differing only by groupId. That is legal and causes tooling no trouble, but it is confusing when searching Maven Central, and claiming an existing project's name reads as territorial when the two are better described as complementary. Using "wicketstuff" as the name segment stays within the convention, matches the sibling wicketstuff-* modules in this repo, and says where the artifact comes from. The pom display names move with it, since leaving them identical to the other project would have defeated the point. The Java package was already org.wicketstuff.springboot.starter and is unchanged. Also adds a Motivation section to the README covering why a deliberately small starter is worth having: it supplies the three pieces every Wicket application on Spring Boot needs and stops there, which keeps it cheap to re-verify across major versions, and it releases with wicketstuff-core so the version matching your Wicket version is the one to use. It names the broader alternative and describes what each is good for, so readers can choose deliberately. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012N3ZXf1gtmcbQ2jWcqyDTF --- pom.xml | 4 +- .../LICENSE | 0 .../README.md | 45 +++++++++++++++--- .../pom.xml | 8 ++-- .../pom.xml | 12 ++--- .../starter/example/ExampleApplication.java | 0 .../src/main/resources/application.properties | 0 .../example/DefaultWebApplicationTest.java | 0 .../example/ExampleApplicationTest.java | 0 .../starter/example/GreetingService.java | 0 .../starter/example/QuickstartHomePage.java | 0 .../example/QuickstartWebApplication.java | 0 .../SpringBeanInjectionQuickstartTest.java | 0 ...ctionWithCustomFilterRegistrationTest.java | 0 .../example/StarterSelfSufficiencyTest.java | 2 +- .../WicketAndSpringMvcCoexistenceTest.java | 0 .../example/WicketPropertiesBindingTest.java | 0 .../starter/example/QuickstartHomePage.html | 0 .../wicketstuff-spring-boot-starter}/pom.xml | 6 +-- .../springboot/starter/DefaultHomePage.java | 0 .../starter/DefaultWebApplication.java | 0 .../starter/WicketAutoConfiguration.java | 0 .../springboot/starter/WicketProperties.java | 0 ...itional-spring-configuration-metadata.json | 0 ...ot.autoconfigure.AutoConfiguration.imports | 0 .../springboot/starter/DefaultHomePage.html | 2 +- .../wicketstuff/springboot/starter/logo.png | Bin .../wicketstuff/springboot/starter/style.css | 0 .../starter/DefaultWebApplicationTest.java | 0 .../starter/WicketAutoConfigurationTest.java | 0 30 files changed, 55 insertions(+), 24 deletions(-) rename {wicket-spring-boot-starter-parent => wicketstuff-spring-boot-starter-parent}/LICENSE (100%) rename {wicket-spring-boot-starter-parent => wicketstuff-spring-boot-starter-parent}/README.md (83%) rename {wicket-spring-boot-starter-parent => wicketstuff-spring-boot-starter-parent}/pom.xml (92%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/pom.xml (88%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/main/resources/application.properties (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java (96%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples}/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/pom.xml (94%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/main/resources/META-INF/additional-spring-configuration-metadata.json (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html (95%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/main/resources/org/wicketstuff/springboot/starter/logo.png (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/main/resources/org/wicketstuff/springboot/starter/style.css (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java (100%) rename {wicket-spring-boot-starter-parent/wicket-spring-boot-starter => wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter}/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java (100%) diff --git a/pom.xml b/pom.xml index cd467ba95d..fa01cb36a4 100644 --- a/pom.xml +++ b/pom.xml @@ -172,7 +172,7 @@ wicketstuff-servlet3-examples wicketstuff-clipboardjs-examples wicketstuff-springreference-examples - wicket-spring-boot-starter-examples + wicketstuff-spring-boot-starter-examples jasperreports-examples editable-grid-examples wicketstuff-sitemap-xml-examples @@ -464,7 +464,7 @@ wicket-servlet3-parent wicketstuff-clipboard-js-parent wicketstuff-springreference-parent - wicket-spring-boot-starter-parent + wicketstuff-spring-boot-starter-parent wicket-security-parent yui-parent diff --git a/wicket-spring-boot-starter-parent/LICENSE b/wicketstuff-spring-boot-starter-parent/LICENSE similarity index 100% rename from wicket-spring-boot-starter-parent/LICENSE rename to wicketstuff-spring-boot-starter-parent/LICENSE diff --git a/wicket-spring-boot-starter-parent/README.md b/wicketstuff-spring-boot-starter-parent/README.md similarity index 83% rename from wicket-spring-boot-starter-parent/README.md rename to wicketstuff-spring-boot-starter-parent/README.md index 0b7644aca9..9fb6eeb17c 100644 --- a/wicket-spring-boot-starter-parent/README.md +++ b/wicketstuff-spring-boot-starter-parent/README.md @@ -4,6 +4,37 @@ A lightweight, zero-boilerplate starter that integrates **Apache Wicket 10.x** w --- +## Motivation + +Running Wicket on Spring Boot always needs the same handful of pieces: a `WebApplication`, a filter +registration for it, and a `SpringComponentInjector` so that `@SpringBean` works. None of it is +difficult, but it is the same every time, it is easy to get subtly wrong, and it is the first thing +standing between someone and a running Wicket page. + +This starter supplies exactly those pieces and then gets out of the way. Everything past that point +is ordinary Wicket and ordinary Spring, documented in their own projects. + +**Staying small is the point, not a limitation.** A deliberately narrow starter is cheap to keep +alive: when Wicket or Spring Boot publishes a new major version, there is very little surface to +re-verify. It also lives inside `wicketstuff-core` and is released with it, so the version you need +is simply the one matching your Wicket version — there is no separate compatibility matrix to +consult and no second release cycle to wait for. + +### Is this the right starter for you? + +There is an established alternative, [`MarcGiffing/wicket-spring-boot`][giffing] +(`com.giffing.wicket.spring.boot.starter`), which is a much broader integration: Spring Security, +native WebSockets, bean validation, CSRF protection, several serializers, session datastores, +monitoring and a set of development-mode helpers. + +Pick that one if you want those batteries included. Pick this one if you would rather start from the +smallest thing that works and add what you need yourself. They solve the same problem with opposite +philosophies, and neither is a replacement for the other. + +[giffing]: https://github.com/MarcGiffing/wicket-spring-boot + +--- + ## Features - **Auto-Configuration**: Automatically registers Wicket's `WicketFilter` in Spring Boot's embedded servlet container. @@ -58,13 +89,13 @@ If you would rather keep the two strictly apart, confine Wicket to its own prefi This is the only dependency you need: it brings Apache Wicket, the Wicket/Spring bridge and the embedded servlet container with it. Add it to your Maven `pom.xml` (check -[Maven Central](https://central.sonatype.com/artifact/org.wicketstuff/wicket-spring-boot-starter) +[Maven Central](https://central.sonatype.com/artifact/org.wicketstuff/wicketstuff-spring-boot-starter) for the latest released version): ```xml org.wicketstuff - wicket-spring-boot-starter + wicketstuff-spring-boot-starter 10.12.0-SNAPSHOT ``` @@ -253,11 +284,11 @@ initializr: id: wicket description: Apache Wicket component-oriented web application framework integrated with Spring Boot. groupId: org.wicketstuff - artifactId: wicket-spring-boot-starter + artifactId: wicketstuff-spring-boot-starter versionRange: "4.0.0" links: - rel: reference - href: https://github.com/wicketstuff/core/tree/master/wicket-spring-boot-starter-parent + href: https://github.com/wicketstuff/core/tree/master/wicketstuff-spring-boot-starter-parent - rel: guide href: https://wicket.apache.org/start/quickstart.html ``` @@ -269,12 +300,12 @@ initializr: "id": "wicket", "description": "Apache Wicket component-oriented web application framework integrated with Spring Boot.", "groupId": "org.wicketstuff", - "artifactId": "wicket-spring-boot-starter", + "artifactId": "wicketstuff-spring-boot-starter", "versionRange": "4.0.0", "links": [ { "rel": "reference", - "href": "https://github.com/wicketstuff/core/tree/master/wicket-spring-boot-starter-parent" + "href": "https://github.com/wicketstuff/core/tree/master/wicketstuff-spring-boot-starter-parent" }, { "rel": "guide", @@ -291,5 +322,5 @@ initializr: - [Apache Wicket documentation](https://wicket.apache.org/) — writing pages, components and markup. - [WicketStuff wiki](https://github.com/wicketstuff/core/wiki) — documentation for the other modules in this project. -- [API documentation](https://www.javadoc.io/doc/org.wicketstuff/wicket-spring-boot-starter) — the +- [API documentation](https://www.javadoc.io/doc/org.wicketstuff/wicketstuff-spring-boot-starter) — the starter's own Javadoc, published per release. diff --git a/wicket-spring-boot-starter-parent/pom.xml b/wicketstuff-spring-boot-starter-parent/pom.xml similarity index 92% rename from wicket-spring-boot-starter-parent/pom.xml rename to wicketstuff-spring-boot-starter-parent/pom.xml index 834abe2cfa..c5c69c3b24 100644 --- a/wicket-spring-boot-starter-parent/pom.xml +++ b/wicketstuff-spring-boot-starter-parent/pom.xml @@ -10,10 +10,10 @@ 10.12.0-SNAPSHOT - wicket-spring-boot-starter-parent + wicketstuff-spring-boot-starter-parent pom - Wicket Spring Boot Starter - Parent + WicketStuff Spring Boot Starter - Parent Parent project for Wicket Spring Boot Starter module and its example application. @@ -73,7 +73,7 @@ - wicket-spring-boot-starter - wicket-spring-boot-starter-examples + wicketstuff-spring-boot-starter + wicketstuff-spring-boot-starter-examples diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/pom.xml similarity index 88% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/pom.xml index e27ffc80a2..310f92345d 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/pom.xml +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/pom.xml @@ -6,15 +6,15 @@ org.wicketstuff - wicket-spring-boot-starter-parent + wicketstuff-spring-boot-starter-parent 10.12.0-SNAPSHOT ../pom.xml - wicket-spring-boot-starter-examples + wicketstuff-spring-boot-starter-examples jar - Wicket Spring Boot Starter - Examples + WicketStuff Spring Boot Starter - Examples Example application demonstrating the use of Wicket Spring Boot Starter. @@ -24,7 +24,7 @@ declares nothing else at compile scope. --> org.wicketstuff - wicket-spring-boot-starter + wicketstuff-spring-boot-starter ${project.version} @@ -55,7 +55,7 @@ @@ -78,7 +78,7 @@ org.springframework.boot:spring-boot-starter-*:*:*:test - This example must depend on nothing but wicket-spring-boot-starter at + This example must depend on nothing but wicketstuff-spring-boot-starter at compile scope, so that StarterSelfSufficiencyTest proves the starter brings a working web application on its own. Declaring a Spring Boot starter here would satisfy that test without the starter supplying diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/application.properties b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/resources/application.properties similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/main/resources/application.properties rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/resources/application.properties diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java similarity index 96% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java index 283efc0fe4..f7a3059add 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java @@ -12,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; /** - * Guards the contract that {@code wicket-spring-boot-starter} is the only dependency an + * Guards the contract that {@code wicketstuff-spring-boot-starter} is the only dependency an * application needs. *

* This module deliberately declares nothing but the starter at compile scope, so the embedded diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml similarity index 94% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml index 8f7ce135bf..c91930fa3f 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/pom.xml +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml @@ -6,15 +6,15 @@ org.wicketstuff - wicket-spring-boot-starter-parent + wicketstuff-spring-boot-starter-parent 10.12.0-SNAPSHOT ../pom.xml - wicket-spring-boot-starter + wicketstuff-spring-boot-starter jar - Wicket Spring Boot Starter + WicketStuff Spring Boot Starter Lightweight auto-configuration and integration starter for Apache Wicket and Spring Boot. diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html similarity index 95% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html index 02a6aa8c5c..89e17c1c6c 100644 --- a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html @@ -31,7 +31,7 @@

Next steps

See the starter's - README + README for the full Quickstart, or the Apache Wicket documentation to learn more about building pages and components. diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/logo.png b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/logo.png similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/logo.png rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/logo.png diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java diff --git a/wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java similarity index 100% rename from wicket-spring-boot-starter-parent/wicket-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java rename to wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java From d63f34bc885353753a351c1103a9da356d7e6dc8 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 03:52:25 +0200 Subject: [PATCH 19/35] Explain what the examples module actually demonstrates The module is called "examples" but its main source is a bare @SpringBootApplication, so a reader browsing it learns nothing and the emptiness looks like an oversight rather than the point. Meanwhile the patterns the README documents -- a custom WebApplication, @SpringBean injection, overriding the filter registration, REST controllers beside Wicket pages -- are all demonstrated in the integration tests, where nobody thinks to look. Rather than move those demonstrations into src/main, where they would be unverified sample code free to drift, this documents where they already are: a module README mapping each pattern to the test that shows it, a pom description saying what the module is for, javadoc on ExampleApplication explaining that having nothing in it is the demonstration, and comments in application.properties noting that none of those settings are required. Also records the compatibility result behind the Initializr metadata's versionRange of 4.0.0: an application built on spring-boot-starter-parent 4.0.3 resolves Spring Boot 4.0.3 rather than being pulled to the 4.1.0 this starter is built against, and boots and serves correctly on it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012N3ZXf1gtmcbQ2jWcqyDTF --- .../README.md | 43 +++++++++++++++++++ .../pom.xml | 5 ++- .../starter/example/ExampleApplication.java | 13 +++++- .../src/main/resources/application.properties | 8 +++- 4 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/README.md diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/README.md b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/README.md new file mode 100644 index 0000000000..ea92ffbe38 --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/README.md @@ -0,0 +1,43 @@ +# WicketStuff Spring Boot Starter — Examples + +A runnable example for the starter, plus the integration tests that demonstrate and verify its +documented behaviour. + +## Running it + +```bash +mvn -pl wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples -am spring-boot:run +``` + +Then open . + +`ExampleApplication` contains nothing but a Spring Boot entry point — no `WebApplication`, no page, +no Wicket configuration. That is deliberate: it shows what the starter gives you on its own, which +is a working Wicket application serving the built-in placeholder page. + +`src/main/resources/application.properties` overrides a couple of `wicket.*` settings purely to +show that externalised configuration reaches Wicket; none of it is required. + +## Where each pattern is demonstrated + +The patterns you would write in a real application live in `src/test/java`, so they are exercised on +every build rather than drifting out of date as untested sample code: + +| What you want to see | Where | +|---|---| +| A custom `WebApplication` and a page using `@SpringBean` | `SpringBeanInjectionQuickstartTest` (with `QuickstartWebApplication`, `QuickstartHomePage`, `GreetingService`) | +| That `@SpringBean` still works if you supply your own filter registration | `SpringBeanInjectionWithCustomFilterRegistrationTest` | +| REST controllers living alongside Wicket pages | `WicketAndSpringMvcCoexistenceTest` | +| `wicket.*` properties actually reaching the filter | `WicketPropertiesBindingTest` | +| That the starter alone is enough to boot a web application | `StarterSelfSufficiencyTest` | + +## A note on the dependencies + +This module depends on **nothing but the starter** at compile scope, and an enforcer rule in its +`pom.xml` keeps it that way. That is what makes `StarterSelfSufficiencyTest` meaningful: the +embedded servlet container it boots can only have come from the starter. If you need another +dependency here, it almost certainly belongs in the starter instead. + +Note also that each test which starts a real servlet container sets its own `wicket.filter-name`. +Wicket keys its application registry by that name and Spring caches test contexts, so tests would +otherwise collide — see the Testing section of the [starter README](../README.md). diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/pom.xml b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/pom.xml index 310f92345d..5c078f0c29 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/pom.xml +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/pom.xml @@ -16,7 +16,10 @@ WicketStuff Spring Boot Starter - Examples - Example application demonstrating the use of Wicket Spring Boot Starter. + Runnable example for the WicketStuff Spring Boot Starter. The application itself is + deliberately empty, showing what the starter gives you with no configuration at all; the + integration tests alongside it demonstrate and verify the documented patterns, from + injecting Spring beans into pages to overriding the filter registration. diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java index 9f15884332..c0b1fa48a3 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java @@ -4,7 +4,18 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; /** - * Spring Boot main application class. + * Runnable example for the starter. + *

+ * There is deliberately nothing here beyond the Spring Boot entry point: no {@code WebApplication}, + * no page, no Wicket configuration. That is the point of the example — run this class and the + * starter alone gives you a working Wicket application on + * http://localhost:8080, serving its built-in placeholder page. + *

+ *

+ * The patterns you would actually write in your own application are demonstrated by the + * integration tests in {@code src/test/java}, where they are also verified on every build. See this + * module's README for a map of which test shows what. + *

*/ @SpringBootApplication public class ExampleApplication { diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/resources/application.properties b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/resources/application.properties index 9d9ffbaf8b..2d28e4f58a 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/resources/application.properties +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/resources/application.properties @@ -1,5 +1,11 @@ -# Custom Wicket settings configured via properties +# None of these are required -- the starter works with no configuration at all. They are set here +# to show that externalised wicket.* properties reach Wicket, and are asserted by +# WicketPropertiesBindingTest. +# +# DEVELOPMENT is Wicket's default and enables its development-time checks; switch to DEPLOYMENT in +# production, typically via a Spring profile. wicket.configuration=DEVELOPMENT +# /* is also the default; shown here to make the mapping explicit. wicket.filter-path=/* wicket.filter-name=wicket-example-filter From a246cddb7b6316768d16c47b449d62455e0a8f4d Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 07:17:20 +0200 Subject: [PATCH 20/35] Depend on spring-boot-starter-webmvc instead of the deprecated -web spring-boot-starter-web is deprecated as of Spring Boot 4; its own pom description says "deprecated in favor of spring-boot-starter-webmvc". The replacement carries the same four dependencies plus spring-boot-starter itself, so logging arrives explicitly rather than incidentally, and it is what Vaadin's Initializr-listed starter depends on. Also documents WAR deployment. The starter ships an embedded Tomcat but does not commit anyone to it: declaring spring-boot-starter-tomcat at provided scope demotes the whole embedded chain even though it arrives transitively through the starter. Verified by packaging a war against the installed artifact -- no tomcat jars in WEB-INF/lib, while wicket-core, the starter and spring-boot-webmvc are packaged as normal. That also settles whether to adopt the conventional split between an autoconfigure module and a dependency-only starter. Supporting an external servlet container was the concrete reason to want it, and it turns out not to need one, so the single combined module stays -- which Spring's documentation explicitly allows, and which can still be split later without changing any consumer's coordinates. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012N3ZXf1gtmcbQ2jWcqyDTF --- .../README.md | 19 ++++++++++++++++++- .../wicketstuff-spring-boot-starter/pom.xml | 5 +++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/wicketstuff-spring-boot-starter-parent/README.md b/wicketstuff-spring-boot-starter-parent/README.md index 9fb6eeb17c..4650e437f7 100644 --- a/wicketstuff-spring-boot-starter-parent/README.md +++ b/wicketstuff-spring-boot-starter-parent/README.md @@ -64,7 +64,7 @@ When it applies, three beans are contributed: ### Living alongside Spring MVC -The starter brings `spring-boot-starter-web`, so your application also has Spring MVC available. +The starter brings `spring-boot-starter-webmvc`, so your application also has Spring MVC available. Wicket's filter is mapped at `/*` but forwards anything it does not handle further down the filter chain, so `@RestController` endpoints keep working next to Wicket pages: @@ -83,6 +83,23 @@ With the defaults, `/api/greeting` reaches the controller while `/` renders your If you would rather keep the two strictly apart, confine Wicket to its own prefix with `wicket.filter-path=/app/*`. +### Deploying as a WAR + +The starter brings an embedded Tomcat, but it does not commit you to it. Spring Boot's usual recipe +for deploying to an external servlet container works unchanged — set `war` packaging, extend +`SpringBootServletInitializer`, and re-declare the container at `provided` scope: + +```xml + + org.springframework.boot + spring-boot-starter-tomcat + provided + +``` + +A direct declaration wins over the transitive one, so the embedded container is demoted to +`provided` and stays out of `WEB-INF/lib` while Wicket and the starter are packaged as normal. + --- ## Dependency Configuration diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml index c91930fa3f..2fd1d20917 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml @@ -56,10 +56,11 @@
+ non-web application, and the auto-configuration would never activate. + spring-boot-starter-web is deprecated as of Spring Boot 4 in favour of this. --> org.springframework.boot - spring-boot-starter-web + spring-boot-starter-webmvc org.springframework.boot From 25bd5e9677fc01beca68bed5ec373e1f67bcc075 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 07:21:43 +0200 Subject: [PATCH 21/35] Bump Spring Boot to 4.1.1 4.1.1 is the current stable release; the starter was pinned to 4.1.0. This is the one dependency version the module pins itself rather than inheriting from the root pom, so it does not move with the reactor and needs bumping deliberately. Tomcat moves 11.0.22 to 11.0.24 with it. Found while sweeping for deprecated dependencies before a first release. That sweep came up clean otherwise: all 83 resolved artifacts checked for deprecation notices (the four hits were false positives, matching only their own showDeprecation compiler settings), and a clean recompile of all sources with deprecation warnings enabled produced none. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012N3ZXf1gtmcbQ2jWcqyDTF --- wicketstuff-spring-boot-starter-parent/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wicketstuff-spring-boot-starter-parent/pom.xml b/wicketstuff-spring-boot-starter-parent/pom.xml index c5c69c3b24..f68038524c 100644 --- a/wicketstuff-spring-boot-starter-parent/pom.xml +++ b/wicketstuff-spring-boot-starter-parent/pom.xml @@ -19,7 +19,7 @@ - 4.1.0 + 4.1.1 From 328771c293fc4c6c038837dac4d54a5258283849 Mon Sep 17 00:00:00 2001 From: danielbartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 13:01:28 +0200 Subject: [PATCH 22/35] style(starter): standardize "autoconfiguration" term and add `@Serial` annotation --- .../wicketstuff/springboot/starter/DefaultHomePage.java | 7 +++++-- .../springboot/starter/WicketAutoConfiguration.java | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java index a54b8a542e..5caea67fc3 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java @@ -3,12 +3,15 @@ import org.apache.wicket.markup.html.WebPage; import org.apache.wicket.markup.html.basic.Label; +import java.io.Serial; + /** * The default home page loaded by the Wicket Spring Boot Starter - * when no custom WebApplication bean is provided by the application. + * when the application provides no custom WebApplication bean. */ public class DefaultHomePage extends WebPage { - private static final long serialVersionUID = 1L; + @Serial + private static final long serialVersionUID = 1L; public DefaultHomePage() { add(new Label("version", getApplication().getFrameworkSettings().getVersion())); diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index e8e538c239..7ed3861b1d 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -15,16 +15,16 @@ import org.springframework.context.annotation.Bean; /** - * Spring Boot auto-configuration for Apache Wicket. + * Spring Boot autoconfiguration for Apache Wicket. *

- * This auto-configuration is activated when Wicket's core classes are present on the classpath. + * This autoconfiguration is activated when Wicket's core classes are present on the classpath. * It registers Wicket's {@link WicketFilter} into the embedded servlet container and binds the * registered {@link WebApplication} bean. Additionally, it registers the {@link SpringComponentInjector} * to enable Spring bean injection (via {@link org.apache.wicket.spring.injection.annot.SpringBean}) * inside Wicket pages and components. *

*

- * Set {@code wicket.enabled=false} to switch the whole auto-configuration off. + * Set {@code wicket.enabled=false} to switch the whole autoconfiguration off. *

* * @author WicketStuff From 9acfdf80d844cb7b12b45f262f5c646bb25f801b Mon Sep 17 00:00:00 2001 From: danielbartl <630704+danielbartl@users.noreply.github.com> Date: Fri, 18 Sep 2026 13:13:15 +0200 Subject: [PATCH 23/35] docs(starter): attribute authorship to Daniel Bartl Replace the placeholder "WicketStuff" author and add @author tags across the module, matching the convention used elsewhere in the repo of crediting the actual contributor. Co-Authored-By: Claude Sonnet 5 --- .../springboot/starter/example/ExampleApplication.java | 2 ++ .../springboot/starter/example/DefaultWebApplicationTest.java | 2 ++ .../springboot/starter/example/ExampleApplicationTest.java | 2 ++ .../springboot/starter/example/GreetingService.java | 3 +++ .../springboot/starter/example/QuickstartHomePage.java | 2 ++ .../springboot/starter/example/QuickstartWebApplication.java | 2 ++ .../starter/example/SpringBeanInjectionQuickstartTest.java | 2 ++ .../SpringBeanInjectionWithCustomFilterRegistrationTest.java | 2 ++ .../springboot/starter/example/StarterSelfSufficiencyTest.java | 2 ++ .../starter/example/WicketAndSpringMvcCoexistenceTest.java | 2 ++ .../starter/example/WicketPropertiesBindingTest.java | 2 ++ .../org/wicketstuff/springboot/starter/DefaultHomePage.java | 2 ++ .../wicketstuff/springboot/starter/DefaultWebApplication.java | 2 ++ .../springboot/starter/WicketAutoConfiguration.java | 2 +- .../org/wicketstuff/springboot/starter/WicketProperties.java | 2 +- .../springboot/starter/DefaultWebApplicationTest.java | 3 +++ .../springboot/starter/WicketAutoConfigurationTest.java | 3 +++ 17 files changed, 35 insertions(+), 2 deletions(-) diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java index c0b1fa48a3..bb5a3818ae 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java @@ -16,6 +16,8 @@ * integration tests in {@code src/test/java}, where they are also verified on every build. See this * module's README for a map of which test shows what. *

+ * + * @author Daniel Bartl */ @SpringBootApplication public class ExampleApplication { diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java index bbd09704fa..7911ac415f 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java @@ -15,6 +15,8 @@ /** * Verifies that the starter auto-configures {@link DefaultWebApplication} * when no custom {@link WebApplication} bean is present in the application context. + * + * @author Daniel Bartl */ @SpringBootTest(classes = DefaultWebApplicationTest.TestConfig.class) public class DefaultWebApplicationTest { diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java index 81739c25bc..b2c7c5557c 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java @@ -9,6 +9,8 @@ /** * Basic Spring Boot context integration test. + * + * @author Daniel Bartl */ @SpringBootTest public class ExampleApplicationTest { diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java index 2bf2609791..13244cf4dd 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java @@ -1,5 +1,8 @@ package org.wicketstuff.springboot.starter.example; +/** + * @author Daniel Bartl + */ interface GreetingService { String greet(); diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java index 5487599696..17b73f3e54 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java @@ -7,6 +7,8 @@ /** * Mirrors the custom {@code HomePage} from the README's Quickstart section: a Wicket page * that has a Spring-managed service injected via {@code @SpringBean}. + * + * @author Daniel Bartl */ public class QuickstartHomePage extends WebPage { private static final long serialVersionUID = 1L; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java index fe137d9ac8..f2c2f32a99 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java @@ -7,6 +7,8 @@ * Mirrors the custom {@code WebApplication} from the README's Quickstart section: a * hand-written subclass that the starter's {@code @ConditionalOnMissingBean} default backs * off for, once it is registered as a Spring bean. + * + * @author Daniel Bartl */ class QuickstartWebApplication extends WebApplication { diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java index 175a3fbff9..eb9ea24d71 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java @@ -17,6 +17,8 @@ * {@link WebApplication} bean makes the starter's {@code @ConditionalOnMissingBean} default * back off, and {@code @SpringBean} injects a Spring-managed service into the page that gets * rendered through a real embedded servlet container. + * + * @author Daniel Bartl */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureTestRestTemplate diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java index 280e90c0f7..4f935751d5 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java @@ -21,6 +21,8 @@ * registration back off. Spring injection must keep working regardless, which is why the * {@code SpringComponentInjector} is bound to the {@link WebApplication} bean rather than to the * filter registration. + * + * @author Daniel Bartl */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureTestRestTemplate diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java index f7a3059add..3f62aa2e3b 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java @@ -29,6 +29,8 @@ * The filter name is overridden because Wicket keys its application registry by it, so two tests * that each start a real container in the same JVM collide on the default name. *

+ * + * @author Daniel Bartl */ @SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java index f7ac41019b..0e67d8718e 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java @@ -18,6 +18,8 @@ * MVC's {@code DispatcherServlet} while Wicket's filter is mapped at {@code /*}. This pins down * that the two coexist: Wicket serves its pages and passes anything it does not handle further * down the filter chain, so {@code @RestController} endpoints stay reachable. + * + * @author Daniel Bartl */ @SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java index 9225a1f323..9becc44638 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java @@ -13,6 +13,8 @@ * Verifies that the {@code wicket.*} properties set in this example's * {@code application.properties} are actually bound and applied to the registered Wicket * filter, rather than the starter's built-in defaults. + * + * @author Daniel Bartl */ @SpringBootTest class WicketPropertiesBindingTest { diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java index 5caea67fc3..c1eb7edfd1 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java @@ -8,6 +8,8 @@ /** * The default home page loaded by the Wicket Spring Boot Starter * when the application provides no custom WebApplication bean. + * + * @author Daniel Bartl */ public class DefaultHomePage extends WebPage { @Serial diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java index c094a29d2b..1e45a2c66d 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java @@ -7,6 +7,8 @@ /** * The default {@link WebApplication} used by the Wicket Spring Boot Starter * when the user does not provide their own custom implementation bean. + * + * @author Daniel Bartl */ public class DefaultWebApplication extends WebApplication { diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index 7ed3861b1d..d970b4c989 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -27,7 +27,7 @@ * Set {@code wicket.enabled=false} to switch the whole autoconfiguration off. *

* - * @author WicketStuff + * @author Daniel Bartl */ @AutoConfiguration @ConditionalOnWebApplication(type = Type.SERVLET) diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java index 782cafc3d8..7d60daf712 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java @@ -10,7 +10,7 @@ * or {@code application.yml}) under the {@code wicket} prefix. *

* - * @author WicketStuff + * @author Daniel Bartl */ @ConfigurationProperties(prefix = "wicket") public class WicketProperties { diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java index aa79a24364..ab9fa685bc 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java @@ -9,6 +9,9 @@ import static org.assertj.core.api.Assertions.assertThat; +/** + * @author Daniel Bartl + */ class DefaultWebApplicationTest { private WicketTester tester; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java index 5d1c24bec3..43a203d709 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java @@ -15,6 +15,9 @@ import static org.assertj.core.api.Assertions.assertThat; +/** + * @author Daniel Bartl + */ class WicketAutoConfigurationTest { private final WebApplicationContextRunner servletContextRunner = new WebApplicationContextRunner() From 5a05dc8de76b2f903633e6d63b3140defe5494a7 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Mon, 28 Sep 2026 22:09:47 +0200 Subject: [PATCH 24/35] Back off the filter registration for any WicketFilter bean @ConditionalOnMissingBean only matched a FilterRegistrationBean, so an application declaring a plain WicketFilter bean got Wicket mapped twice. @ConditionalOnMissingFilterBean covers both forms. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 2 +- .../starter/WicketAutoConfiguration.java | 8 ++++- .../starter/WicketAutoConfigurationTest.java | 34 +++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/wicketstuff-spring-boot-starter-parent/README.md b/wicketstuff-spring-boot-starter-parent/README.md index 4650e437f7..b3d7dd5e20 100644 --- a/wicketstuff-spring-boot-starter-parent/README.md +++ b/wicketstuff-spring-boot-starter-parent/README.md @@ -220,7 +220,7 @@ as much or as little as you need: |---|---|---| | `webApplication` | any `WebApplication` bean exists | use your own Wicket application (the usual case — see the Quickstart) | | `springComponentInjector` | any `SpringComponentInjector` bean exists | control how Spring injection is wired | -| `wicketFilterRegistration` | a `FilterRegistrationBean` bean exists | control the filter registration, e.g. its order relative to other filters | +| `wicketFilterRegistration` | a `FilterRegistrationBean` or a plain `WicketFilter` bean exists | control the filter registration, e.g. its order relative to other filters | Overriding the filter registration does **not** cost you Spring injection: the injector is bound to the `WebApplication` rather than to the filter, so `@SpringBean` keeps working in your pages either diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index d970b4c989..02f5f977c1 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -6,6 +6,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingFilterBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; @@ -75,13 +76,18 @@ public SpringComponentInjector springComponentInjector( /** * Creates and configures the {@link FilterRegistrationBean} for the {@link WicketFilter}. + *

+ * Backs off when the application already registers a {@link WicketFilter}, either wrapped in its + * own {@link FilterRegistrationBean} or declared as a plain filter bean, so that Wicket is never + * mapped twice. + *

* * @param webApplication the auto-discovered Wicket WebApplication subclass bean * @param properties the externalized Wicket properties * @return the configured FilterRegistrationBean for WicketFilter */ @Bean - @ConditionalOnMissingBean + @ConditionalOnMissingFilterBean(WicketFilter.class) public FilterRegistrationBean wicketFilterRegistration( WebApplication webApplication, WicketProperties properties) { diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java index 43a203d709..09588f3191 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java @@ -1,5 +1,6 @@ package org.wicketstuff.springboot.starter; +import jakarta.servlet.Filter; import org.apache.wicket.Page; import org.apache.wicket.RuntimeConfigurationType; import org.apache.wicket.protocol.http.WebApplication; @@ -74,6 +75,21 @@ void backsOffWhenACustomWicketFilterRegistrationIsPresent() { }); } + @Test + void backsOffWhenAPlainWicketFilterBeanIsPresent() { + servletContextRunner.withUserConfiguration(PlainWicketFilterConfig.class).run(context -> { + assertThat(context).doesNotHaveBean(FilterRegistrationBean.class); + assertThat(context).hasSingleBean(WicketFilter.class); + }); + } + + @Test + void keepsRegisteringWicketNextToUnrelatedFilterRegistrations() { + servletContextRunner.withUserConfiguration(UnrelatedFilterRegistrationConfig.class).run(context -> + assertThat(context.getBeansOfType(FilterRegistrationBean.class)) + .containsOnlyKeys("unrelatedFilterRegistration", "wicketFilterRegistration")); + } + @Test void doesNotActivateWhenDisabledByProperty() { servletContextRunner.withPropertyValues("wicket.enabled=false").run(context -> { @@ -112,6 +128,24 @@ FilterRegistrationBean customWicketFilterRegistration() { } } + @Configuration + static class PlainWicketFilterConfig { + + @Bean + WicketFilter wicketFilter() { + return new WicketFilter(new CustomWebApplication()); + } + } + + @Configuration + static class UnrelatedFilterRegistrationConfig { + + @Bean + FilterRegistrationBean unrelatedFilterRegistration() { + return new FilterRegistrationBean<>((request, response, chain) -> chain.doFilter(request, response)); + } + } + static class CustomWebApplication extends WebApplication { @Override From 3d520ca46465fdc01156b6349b60e1958fddb6ba Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Mon, 28 Sep 2026 22:09:47 +0200 Subject: [PATCH 25/35] Verify the starter against Spring Boot's own versions and fix Initializr metadata Add an invoker integration test: a project shaped like one generated by Spring Initializr, inheriting from spring-boot-starter-parent, so it runs against exactly the library versions Spring Boot manages rather than the ones wicketstuff-core pins. -Dspring-boot.version=... checks other Boot lines; it passes on 4.0.8 and 4.1.1. The Initializr metadata in the README used the old versionRange key, an open-ended range and no starter version, which would generate a build that does not resolve. Replace it with a bounded compatibilityRange and a version mapping, and state the verified Boot lines in the compatibility matrix. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 53 +++++++++---------- .../wicketstuff-spring-boot-starter/pom.xml | 47 ++++++++++++++++ .../src/it/boot-managed-versions/pom.xml | 35 ++++++++++++ .../com/example/wicket/DemoApplication.java | 12 +++++ .../example/wicket/DemoWicketApplication.java | 14 +++++ .../com/example/wicket/GreetingService.java | 11 ++++ .../java/com/example/wicket/HomePage.java | 17 ++++++ .../com/example/wicket/PingController.java | 13 +++++ .../com/example/wicket/HomePage.html | 6 +++ .../example/wicket/DemoApplicationTest.java | 47 ++++++++++++++++ .../src/it/settings.xml | 38 +++++++++++++ 11 files changed, 266 insertions(+), 27 deletions(-) create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/pom.xml create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/DemoApplication.java create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/DemoWicketApplication.java create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/GreetingService.java create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/HomePage.java create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/PingController.java create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/resources/com/example/wicket/HomePage.html create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/test/java/com/example/wicket/DemoApplicationTest.java create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/settings.xml diff --git a/wicketstuff-spring-boot-starter-parent/README.md b/wicketstuff-spring-boot-starter-parent/README.md index b3d7dd5e20..e98557ba13 100644 --- a/wicketstuff-spring-boot-starter-parent/README.md +++ b/wicketstuff-spring-boot-starter-parent/README.md @@ -125,7 +125,16 @@ Ensure you match the correct starter version with your Spring Boot and Java envi | WicketStuff / Starter Version | Spring Boot Version | Spring Framework Version | Minimum Java Version | | :--- | :--- | :--- | :--- | -| **`10.x.y`** (Current) | `4.x.y` | `7.x.y` | Java 17 | +| **`10.12.x`** (Current) | `4.0.x`, `4.1.x` | `7.0.x` | Java 17 | + +Every supported Spring Boot line is verified by the integration test under +`wicketstuff-spring-boot-starter/src/it`: a project shaped like one generated by Spring Initializr, +inheriting from `spring-boot-starter-parent` so it runs against exactly the library versions Spring +Boot manages. To check another Spring Boot version, run from the starter module: + +```bash +mvn verify -Dspring-boot.version=4.0.8 +``` --- @@ -289,20 +298,25 @@ filter is never initialised. ## Spring Initializr Metadata Registration -If you are requesting this starter to be listed on `start.spring.io` (or registering it in an internal Initializr instance), configure the dependency metadata as follows. `versionRange` expresses the Spring Boot versions this starter supports (see the Compatibility Matrix above), not the starter's own version. It's left open-ended here (`4.0.0` and any later version) since nothing in the starter's autoconfiguration mechanism is expected to break across future Spring Boot majors — add an explicit upper bound only once a specific incompatibility is found: +To list the starter on `start.spring.io` (or in an internal Initializr instance), the dependency is +added to the Initializr's `application.yml`. Spring Boot's BOM does not manage `org.wicketstuff` +artifacts, so the entry has to say which starter version goes with which Spring Boot line; +otherwise the generated build has no version for the dependency and does not resolve. -### YAML Configuration (e.g. `application.yml`) ```yaml initializr: dependencies: - name: Web content: - - name: Wicket + - name: Apache Wicket id: wicket - description: Apache Wicket component-oriented web application framework integrated with Spring Boot. + description: Build component-oriented, server-side web applications with Apache Wicket. groupId: org.wicketstuff artifactId: wicketstuff-spring-boot-starter - versionRange: "4.0.0" + compatibilityRange: "[4.0.0,4.2.0-M1)" + mappings: + - compatibilityRange: "[4.0.0,4.2.0-M1)" + version: 10.12.0 links: - rel: reference href: https://github.com/wicketstuff/core/tree/master/wicketstuff-spring-boot-starter-parent @@ -310,27 +324,12 @@ initializr: href: https://wicket.apache.org/start/quickstart.html ``` -### JSON Metadata API Representation -```json -{ - "name": "Wicket", - "id": "wicket", - "description": "Apache Wicket component-oriented web application framework integrated with Spring Boot.", - "groupId": "org.wicketstuff", - "artifactId": "wicketstuff-spring-boot-starter", - "versionRange": "4.0.0", - "links": [ - { - "rel": "reference", - "href": "https://github.com/wicketstuff/core/tree/master/wicketstuff-spring-boot-starter-parent" - }, - { - "rel": "guide", - "href": "https://wicket.apache.org/start/quickstart.html" - } - ] -} -``` +- `compatibilityRange` is always bounded above. When a new Spring Boot line appears, it is only + opened up once the integration test above passes against it, so that Initializr never offers a + combination that has not been tested. +- Each `mappings` entry pins the starter release for a Spring Boot range. When a starter release + drops or adds a Spring Boot line, split the range into several mappings. +- `version` must be a release available on Maven Central, never a snapshot. --- diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml index 2fd1d20917..a2a702cfc2 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml @@ -19,6 +19,12 @@ Lightweight auto-configuration and integration starter for Apache Wicket and Spring Boot. + + 3.10.1 + + false + + @@ -96,4 +102,45 @@ test + + + + + + org.apache.maven.plugins + maven-invoker-plugin + ${maven-invoker-plugin.version} + + ${project.build.directory}/it + ${project.build.directory}/local-repo + src/it/settings.xml + + */pom.xml + + + verify + + + + ${spring-boot.version} + + true + ${skipTests} + + + + integration-test + + install + run + + + + + + diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/pom.xml b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/pom.xml new file mode 100644 index 0000000000..a00de2e79b --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/pom.xml @@ -0,0 +1,35 @@ + + + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + @spring-boot.version@ + + + + com.example + boot-managed-versions + 0.0.1-SNAPSHOT + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + + org.springframework.boot + spring-boot-starter-test + test + + + diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/DemoApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/DemoApplication.java new file mode 100644 index 0000000000..1aefff2111 --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/DemoApplication.java @@ -0,0 +1,12 @@ +package com.example.wicket; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } +} diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/DemoWicketApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/DemoWicketApplication.java new file mode 100644 index 0000000000..6f7b84b843 --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/DemoWicketApplication.java @@ -0,0 +1,14 @@ +package com.example.wicket; + +import org.apache.wicket.Page; +import org.apache.wicket.protocol.http.WebApplication; +import org.springframework.stereotype.Component; + +@Component +public class DemoWicketApplication extends WebApplication { + + @Override + public Class getHomePage() { + return HomePage.class; + } +} diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/GreetingService.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/GreetingService.java new file mode 100644 index 0000000000..1873411a94 --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/GreetingService.java @@ -0,0 +1,11 @@ +package com.example.wicket; + +import org.springframework.stereotype.Service; + +@Service +public class GreetingService { + + public String greet() { + return "Hello from a Spring bean"; + } +} diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/HomePage.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/HomePage.java new file mode 100644 index 0000000000..2fe653ff91 --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/HomePage.java @@ -0,0 +1,17 @@ +package com.example.wicket; + +import org.apache.wicket.markup.html.WebPage; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.spring.injection.annot.SpringBean; + +public class HomePage extends WebPage { + + private static final long serialVersionUID = 1L; + + @SpringBean + private GreetingService greetingService; + + public HomePage() { + add(new Label("greeting", greetingService.greet())); + } +} diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/PingController.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/PingController.java new file mode 100644 index 0000000000..5077e3395d --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/java/com/example/wicket/PingController.java @@ -0,0 +1,13 @@ +package com.example.wicket; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class PingController { + + @GetMapping("/api/ping") + public String ping() { + return "pong"; + } +} diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/resources/com/example/wicket/HomePage.html b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/resources/com/example/wicket/HomePage.html new file mode 100644 index 0000000000..f78405b8f6 --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/main/resources/com/example/wicket/HomePage.html @@ -0,0 +1,6 @@ + + + +

+ + diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/test/java/com/example/wicket/DemoApplicationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/test/java/com/example/wicket/DemoApplicationTest.java new file mode 100644 index 0000000000..608d80fb68 --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/boot-managed-versions/src/test/java/com/example/wicket/DemoApplicationTest.java @@ -0,0 +1,47 @@ +package com.example.wicket; + +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.server.LocalServerPort; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Boots the application in a real servlet container, with every library at the version Spring + * Boot manages, and exercises the starter end to end: the user's WebApplication is picked up, + * {@code @SpringBean} injection works in pages, and Spring MVC still answers behind the Wicket + * filter. + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +class DemoApplicationTest { + + @LocalServerPort + private int port; + + @Test + void rendersAWicketPageWithAnInjectedSpringBean() throws Exception { + HttpResponse response = get("/"); + + assertThat(response.statusCode()).isEqualTo(200); + assertThat(response.body()).contains("Hello from a Spring bean"); + } + + @Test + void springMvcAnswersBehindTheWicketFilter() throws Exception { + HttpResponse response = get("/api/ping"); + + assertThat(response.statusCode()).isEqualTo(200); + assertThat(response.body()).isEqualTo("pong"); + } + + private HttpResponse get(String path) throws Exception { + HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build(); + return client.send(HttpRequest.newBuilder(URI.create("http://localhost:" + port + path)).build(), + HttpResponse.BodyHandlers.ofString()); + } +} diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/settings.xml b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/settings.xml new file mode 100644 index 0000000000..54edb774f7 --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/it/settings.xml @@ -0,0 +1,38 @@ + + + + + + it-repo + + + local.central + @localRepositoryUrl@ + + true + + + true + + + + + + local.central + @localRepositoryUrl@ + + true + + + true + + + + + + + it-repo + + From 89da80b6c34375e5e8d71d251db94e5fe8a614d2 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Mon, 28 Sep 2026 22:09:47 +0200 Subject: [PATCH 26/35] Build the starter against the versions Spring Boot ships Versions pinned by wicketstuff-core win over the imported Spring Boot BOM, so the starter was built and tested against e.g. logback 1.6 and jackson-databind 3.2 next to jackson-core 3.1. Override those properties in the starter parent with Spring Boot's values, drop the JUnit/logback-core workaround this made necessary, and add BuildAlignedWithSpringBootTest to fail the build as soon as the overrides drift from the BOM. Also drop the redundant provided jakarta.servlet-api dependency; the embedded Tomcat already supplies the servlet API. Co-Authored-By: Claude Opus 5.5 --- .../pom.xml | 55 ++++++----------- .../wicketstuff-spring-boot-starter/pom.xml | 26 +++++--- .../BuildAlignedWithSpringBootTest.java | 59 +++++++++++++++++++ 3 files changed, 97 insertions(+), 43 deletions(-) create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/BuildAlignedWithSpringBootTest.java diff --git a/wicketstuff-spring-boot-starter-parent/pom.xml b/wicketstuff-spring-boot-starter-parent/pom.xml index f68038524c..b4206d376a 100644 --- a/wicketstuff-spring-boot-starter-parent/pom.xml +++ b/wicketstuff-spring-boot-starter-parent/pom.xml @@ -20,46 +20,29 @@ 4.1.1 + + + 7.0.9 + 3.1.5 + 2.21.5 + 2.0.18 + 1.5.38 + 2.25.5 + 1.3.6 + 6.0.3 - - - org.junit.jupiter - junit-jupiter - ${junit.version} - - - org.junit.jupiter - junit-jupiter-params - ${junit.version} - - - org.junit.platform - junit-platform-commons - ${junit.version} - - - org.junit.platform - junit-platform-engine - ${junit.version} - - - - - ch.qos.logback - logback-core - ${logback.version} - - diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml index a2a702cfc2..ad9dae82d8 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/pom.xml @@ -74,13 +74,6 @@ true - - - jakarta.servlet - jakarta.servlet-api - provided - - org.springframework.boot @@ -105,6 +98,25 @@ + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${settings.localRepository}/org/springframework/boot/spring-boot-dependencies/${spring-boot.version}/spring-boot-dependencies-${spring-boot.version}.pom + ${spring.version} + ${jackson.version} + ${jackson2.version} + ${slf4j.version} + ${logback.version} + ${log4j.version} + ${commons-logging.version} + ${junit.version} + + + + + org.springframework.boot + spring-boot-autoconfigure-processor + true + From 7c82845b23ead3870c853c116d720307b3e283b5 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Mon, 28 Sep 2026 22:35:25 +0200 Subject: [PATCH 29/35] Document switching Wicket to DEPLOYMENT mode for production Co-Authored-By: Claude Opus 5.5 --- .../README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/wicketstuff-spring-boot-starter-parent/README.md b/wicketstuff-spring-boot-starter-parent/README.md index 4205c94ae9..b649a009fd 100644 --- a/wicketstuff-spring-boot-starter-parent/README.md +++ b/wicketstuff-spring-boot-starter-parent/README.md @@ -274,6 +274,25 @@ wicket.filter-name=my-custom-wicket-filter --- +## Going to Production + +Like Wicket itself, the starter runs in `DEVELOPMENT` mode unless told otherwise, and says so with a +banner in the log on every start. That mode is meant for your machine only: it reloads changed +markup, leaves `wicket:id` attributes in the rendered HTML, enables the Ajax debug window, serves +unminified JavaScript and renders exception pages with full stack traces. + +Switch to `DEPLOYMENT` wherever the application actually runs. A Spring profile keeps the setting +next to the rest of your production configuration, in `application-prod.properties`: + +```properties +wicket.configuration=DEPLOYMENT +``` + +activated with `--spring.profiles.active=prod` (or `SPRING_PROFILES_ACTIVE=prod`). Without a +profile, setting the environment variable `WICKET_CONFIGURATION=DEPLOYMENT` does the same. + +--- + ## Testing Wicket keys its application registry by the filter name, and Spring keeps test contexts cached for From 7337c543d58333184da4507639da9fd0c2c9184f Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Mon, 28 Sep 2026 22:49:53 +0200 Subject: [PATCH 30/35] Add license headers, use tabs and stop mounting default page resources at root - Add the Apache 2.0 license header to all sources, markup and CSS. - Indent WicketAutoConfiguration and DefaultHomePage with tabs like the rest. - Link the default page's stylesheet and logo with as package resources instead of mounting them at the application root, where they could shadow an application's own static files. - Show the release version, not a snapshot, in the README's Maven snippet. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 2 +- .../starter/example/ExampleApplication.java | 13 ++ .../example/DefaultWebApplicationTest.java | 13 ++ .../example/ExampleApplicationTest.java | 13 ++ .../starter/example/GreetingService.java | 13 ++ .../starter/example/QuickstartHomePage.java | 13 ++ .../example/QuickstartWebApplication.java | 13 ++ .../SpringBeanInjectionDuringInitTest.java | 13 ++ .../SpringBeanInjectionQuickstartTest.java | 13 ++ ...ctionWithCustomFilterRegistrationTest.java | 13 ++ .../example/StarterSelfSufficiencyTest.java | 13 ++ .../WicketAndSpringMvcCoexistenceTest.java | 13 ++ .../example/WicketPropertiesBindingTest.java | 13 ++ .../starter/example/QuickstartHomePage.html | 13 ++ .../springboot/starter/DefaultHomePage.java | 15 +- .../starter/DefaultWebApplication.java | 23 +-- .../SpringComponentInjectorRegistrar.java | 13 ++ .../starter/WicketAutoConfiguration.java | 157 ++++++++++-------- .../springboot/starter/WicketProperties.java | 13 ++ .../springboot/starter/DefaultHomePage.html | 17 +- .../wicketstuff/springboot/starter/style.css | 13 ++ .../BuildAlignedWithSpringBootTest.java | 13 ++ .../starter/DefaultWebApplicationTest.java | 29 +++- .../starter/WicketAutoConfigurationTest.java | 13 ++ 24 files changed, 389 insertions(+), 88 deletions(-) diff --git a/wicketstuff-spring-boot-starter-parent/README.md b/wicketstuff-spring-boot-starter-parent/README.md index b649a009fd..d4a06c9d78 100644 --- a/wicketstuff-spring-boot-starter-parent/README.md +++ b/wicketstuff-spring-boot-starter-parent/README.md @@ -113,7 +113,7 @@ for the latest released version): org.wicketstuff wicketstuff-spring-boot-starter - 10.12.0-SNAPSHOT + 10.12.0 ``` diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java index bb5a3818ae..2ca10f52bd 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/main/java/org/wicketstuff/springboot/starter/example/ExampleApplication.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.springframework.boot.SpringApplication; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java index 7911ac415f..bd9ec21ce6 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/DefaultWebApplicationTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.apache.wicket.protocol.http.WebApplication; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java index b2c7c5557c..277172b100 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/ExampleApplicationTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.apache.wicket.protocol.http.WebApplication; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java index 13244cf4dd..83ef9d8af3 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/GreetingService.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; /** diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java index 17b73f3e54..ab90ef1fe3 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartHomePage.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.apache.wicket.markup.html.WebPage; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java index f2c2f32a99..10a62e421d 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/QuickstartWebApplication.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.apache.wicket.Page; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionDuringInitTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionDuringInitTest.java index a2f0b9608e..998af058b7 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionDuringInitTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionDuringInitTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.apache.wicket.injection.Injector; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java index eb9ea24d71..06c675c5d5 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionQuickstartTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.apache.wicket.protocol.http.WebApplication; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java index 4f935751d5..9ef1b573c3 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/SpringBeanInjectionWithCustomFilterRegistrationTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.apache.wicket.protocol.http.WebApplication; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java index 3f62aa2e3b..414ec0ba8f 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/StarterSelfSufficiencyTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.junit.jupiter.api.Test; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java index 0e67d8718e..4b321fd7b3 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketAndSpringMvcCoexistenceTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.junit.jupiter.api.Test; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java index 9becc44638..e86ab927f2 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/java/org/wicketstuff/springboot/starter/example/WicketPropertiesBindingTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter.example; import org.apache.wicket.RuntimeConfigurationType; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html index 3b0bf1d76a..d378b97d2b 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/src/test/resources/org/wicketstuff/springboot/starter/example/QuickstartHomePage.html @@ -1,3 +1,16 @@ + placeholder diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java index c1eb7edfd1..5cedd3bda1 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultHomePage.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter; import org.apache.wicket.markup.html.WebPage; @@ -13,7 +26,7 @@ */ public class DefaultHomePage extends WebPage { @Serial - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; public DefaultHomePage() { add(new Label("version", getApplication().getFrameworkSettings().getVersion())); diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java index 1e45a2c66d..18056f5e39 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/DefaultWebApplication.java @@ -1,8 +1,20 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter; import org.apache.wicket.Page; import org.apache.wicket.protocol.http.WebApplication; -import org.apache.wicket.request.resource.PackageResourceReference; /** * The default {@link WebApplication} used by the Wicket Spring Boot Starter @@ -16,13 +28,4 @@ public class DefaultWebApplication extends WebApplication { public Class getHomePage() { return DefaultHomePage.class; } - - @Override - protected void init() { - super.init(); - - // Mount resources to serve style.css and logo.png from the application root path - mountResource("style.css", new PackageResourceReference(DefaultHomePage.class, "style.css")); - mountResource("logo.png", new PackageResourceReference(DefaultHomePage.class, "logo.png")); - } } diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/SpringComponentInjectorRegistrar.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/SpringComponentInjectorRegistrar.java index 14e70465df..b6fbc52051 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/SpringComponentInjectorRegistrar.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/SpringComponentInjectorRegistrar.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter; import org.apache.wicket.protocol.http.WebApplication; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index b5834c3e93..2eb495a98b 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter; import org.apache.wicket.protocol.http.WebApplication; @@ -36,81 +49,81 @@ @EnableConfigurationProperties(WicketProperties.class) public class WicketAutoConfiguration { - /** - * Registers a default {@link WebApplication} bean if the application does not define one. - * This registers the {@link DefaultWebApplication} which serves the starter's {@link DefaultHomePage}. - * - * @return the default WebApplication - */ - @Bean - @ConditionalOnMissingBean(WebApplication.class) - public WebApplication webApplication() { - return new DefaultWebApplication(); - } + /** + * Registers a default {@link WebApplication} bean if the application does not define one. + * This registers the {@link DefaultWebApplication} which serves the starter's {@link DefaultHomePage}. + * + * @return the default WebApplication + */ + @Bean + @ConditionalOnMissingBean(WebApplication.class) + public WebApplication webApplication() { + return new DefaultWebApplication(); + } - /** - * Registers a {@link SpringComponentInjector} on the {@link WebApplication} bean so that Wicket - * pages and components can inject Spring beans via - * {@link org.apache.wicket.spring.injection.annot.SpringBean}. - *

- * The injector is added when the {@link WebApplication} bean is created, not later as a bean of - * its own: the servlet container initialises the Wicket filter, and so runs - * {@link WebApplication#init()}, before ordinary singletons exist. Being bound to the - * {@link WebApplication} rather than to the filter registration also keeps injection working - * for an application that supplies its own {@link FilterRegistrationBean}. - *

- *

- * Backs off when the application defines its own {@link SpringComponentInjector} bean. - *

- * - * @return the post-processor registering the injector on each {@link WebApplication} bean - */ - @Bean - @ConditionalOnMissingBean(SpringComponentInjector.class) - static SpringComponentInjectorRegistrar springComponentInjectorRegistrar() { - return new SpringComponentInjectorRegistrar(); - } + /** + * Registers a {@link SpringComponentInjector} on the {@link WebApplication} bean so that Wicket + * pages and components can inject Spring beans via + * {@link org.apache.wicket.spring.injection.annot.SpringBean}. + *

+ * The injector is added when the {@link WebApplication} bean is created, not later as a bean of + * its own: the servlet container initialises the Wicket filter, and so runs + * {@link WebApplication#init()}, before ordinary singletons exist. Being bound to the + * {@link WebApplication} rather than to the filter registration also keeps injection working + * for an application that supplies its own {@link FilterRegistrationBean}. + *

+ *

+ * Backs off when the application defines its own {@link SpringComponentInjector} bean. + *

+ * + * @return the post-processor registering the injector on each {@link WebApplication} bean + */ + @Bean + @ConditionalOnMissingBean(SpringComponentInjector.class) + static SpringComponentInjectorRegistrar springComponentInjectorRegistrar() { + return new SpringComponentInjectorRegistrar(); + } - /** - * Creates and configures the {@link FilterRegistrationBean} for the {@link WicketFilter}. - *

- * Backs off when the application already registers a {@link WicketFilter}, either wrapped in its - * own {@link FilterRegistrationBean} or declared as a plain filter bean, so that Wicket is never - * mapped twice. - *

- * - * @param webApplication the auto-discovered Wicket WebApplication subclass bean - * @param properties the externalized Wicket properties - * @return the configured FilterRegistrationBean for WicketFilter - */ - @Bean - @ConditionalOnMissingFilterBean(WicketFilter.class) - public FilterRegistrationBean wicketFilterRegistration( - WebApplication webApplication, - WicketProperties properties) { + /** + * Creates and configures the {@link FilterRegistrationBean} for the {@link WicketFilter}. + *

+ * Backs off when the application already registers a {@link WicketFilter}, either wrapped in its + * own {@link FilterRegistrationBean} or declared as a plain filter bean, so that Wicket is never + * mapped twice. + *

+ * + * @param webApplication the auto-discovered Wicket WebApplication subclass bean + * @param properties the externalized Wicket properties + * @return the configured FilterRegistrationBean for WicketFilter + */ + @Bean + @ConditionalOnMissingFilterBean(WicketFilter.class) + public FilterRegistrationBean wicketFilterRegistration( + WebApplication webApplication, + WicketProperties properties) { - return configureWicketFilter(properties, new WicketFilter(webApplication)); - } + return configureWicketFilter(properties, new WicketFilter(webApplication)); + } - /** - * Configures a {@link FilterRegistrationBean} for a given {@link WicketFilter}. - * Sets up the filter mapping path, filter name, and configuration type for Wicket. - * - * @param properties the {@link WicketProperties} containing configuration details such as filter path, - * filter name, and runtime configuration type - * @param filter the {@link WicketFilter} to be configured and registered - * @return a configured {@link FilterRegistrationBean} instance for the provided {@link WicketFilter} - */ - private static FilterRegistrationBean configureWicketFilter( - WicketProperties properties, WicketFilter filter) { - FilterRegistrationBean registration = new FilterRegistrationBean<>(); - registration.setFilter(filter); - registration.addUrlPatterns(properties.getFilterPath()); - registration.setName(properties.getFilterName()); + /** + * Configures a {@link FilterRegistrationBean} for a given {@link WicketFilter}. + * Sets up the filter mapping path, filter name, and configuration type for Wicket. + * + * @param properties the {@link WicketProperties} containing configuration details such as filter path, + * filter name, and runtime configuration type + * @param filter the {@link WicketFilter} to be configured and registered + * @return a configured {@link FilterRegistrationBean} instance for the provided {@link WicketFilter} + */ + private static FilterRegistrationBean configureWicketFilter( + WicketProperties properties, WicketFilter filter) { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + registration.setFilter(filter); + registration.addUrlPatterns(properties.getFilterPath()); + registration.setName(properties.getFilterName()); - // Specify configuration parameter mapping for Wicket - registration.addInitParameter(WicketFilter.FILTER_MAPPING_PARAM, properties.getFilterPath()); - registration.addInitParameter("configuration", properties.getConfiguration().name()); - return registration; - } + // Specify configuration parameter mapping for Wicket + registration.addInitParameter(WicketFilter.FILTER_MAPPING_PARAM, properties.getFilterPath()); + registration.addInitParameter("configuration", properties.getConfiguration().name()); + return registration; + } } diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java index 7d60daf712..2543af2ce8 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter; import org.apache.wicket.RuntimeConfigurationType; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html index 89e17c1c6c..5f1f88064b 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/DefaultHomePage.html @@ -1,14 +1,27 @@ + Wicket Spring Boot Starter - +
diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css index 9829f1e162..b6f4f908f2 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/org/wicketstuff/springboot/starter/style.css @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ body, p, li, a { font-family: georgia, times, serif;font-size:13pt;} h1, h2, h3 { font-family: "Helvetica Neue", helvetica, arial, sans-serif; } body { margin:0;padding:0;} diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/BuildAlignedWithSpringBootTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/BuildAlignedWithSpringBootTest.java index 863febef13..36a7e5bb00 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/BuildAlignedWithSpringBootTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/BuildAlignedWithSpringBootTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter; import java.nio.file.Files; diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java index ab9fa685bc..904b2e4fc7 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DefaultWebApplicationTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter; import org.apache.wicket.markup.html.basic.Label; @@ -40,14 +53,26 @@ void rendersDefaultHomePageWithTheWicketVersionLabel() { } @Test - void servesTheMountedCssResource() { + void linksItsStylesheetAndLogoAsPackageResourcesRatherThanFromTheApplicationRoot() { + tester.startPage(DefaultHomePage.class); + + String markup = tester.getLastResponseAsString(); + assertThat(markup) + .contains("wicket/resource/org.wicketstuff.springboot.starter.DefaultHomePage/style") + .contains("wicket/resource/org.wicketstuff.springboot.starter.DefaultHomePage/logo") + .doesNotContain("href=\"style.css\"") + .doesNotContain("src=\"logo.png\""); + } + + @Test + void servesTheStylesheetAsAPackageResource() { tester.startResourceReference(new PackageResourceReference(DefaultHomePage.class, "style.css")); assertThat(tester.getLastResponse().getStatus()).isEqualTo(200); } @Test - void servesTheMountedPngResource() { + void servesTheLogoAsAPackageResource() { tester.startResourceReference(new PackageResourceReference(DefaultHomePage.class, "logo.png")); assertThat(tester.getLastResponse().getStatus()).isEqualTo(200); diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java index 9d2bac80fb..8971ce28d6 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java @@ -1,3 +1,16 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wicketstuff.springboot.starter; import java.util.ArrayList; From 441c54b330c2f94f5ee9c5e7a06659b2a26cf091 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Mon, 28 Sep 2026 22:54:36 +0200 Subject: [PATCH 31/35] Add wicket.filter-order to position the Wicket filter in the chain Defaults to Ordered.LOWEST_PRECEDENCE, the order the registration already had, so Wicket keeps running after every other filter, including Spring Security's. Changing it no longer requires replacing the whole filter registration. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 8 +++++- .../starter/WicketAutoConfiguration.java | 5 ++-- .../springboot/starter/WicketProperties.java | 28 +++++++++++++++++++ ...itional-spring-configuration-metadata.json | 4 +++ .../starter/WicketAutoConfigurationTest.java | 4 +++ 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/wicketstuff-spring-boot-starter-parent/README.md b/wicketstuff-spring-boot-starter-parent/README.md index d4a06c9d78..825695bf2a 100644 --- a/wicketstuff-spring-boot-starter-parent/README.md +++ b/wicketstuff-spring-boot-starter-parent/README.md @@ -229,7 +229,7 @@ as much or as little as you need: |---|---|---| | `webApplication` | any `WebApplication` bean exists | use your own Wicket application (the usual case — see the Quickstart) | | `springComponentInjectorRegistrar` | any `SpringComponentInjector` bean exists | control how Spring injection is wired | -| `wicketFilterRegistration` | a `FilterRegistrationBean` or a plain `WicketFilter` bean exists | control the filter registration, e.g. its order relative to other filters | +| `wicketFilterRegistration` | a `FilterRegistrationBean` or a plain `WicketFilter` bean exists | control every detail of the filter registration (for path, name and order, the `wicket.filter-*` properties are enough) | Overriding the filter registration does **not** cost you Spring injection: the injector is bound to the `WebApplication` rather than to the filter, so `@SpringBean` keeps working in your pages either @@ -263,6 +263,7 @@ The following properties can be configured in your `application.properties` or ` | `wicket.enabled` | `true` | Set to `false` to switch the auto-configuration off entirely. | | `wicket.filter-path` | `/*` | URL mapping pattern for the Wicket filter. | | `wicket.filter-name` | `wicket-filter` | The name of the registered Wicket servlet filter. | +| `wicket.filter-order` | `Ordered.LOWEST_PRECEDENCE` | Position of the Wicket filter in the servlet filter chain; lower values run earlier. | | `wicket.configuration` | `DEVELOPMENT` | The configuration type: `DEVELOPMENT` or `DEPLOYMENT`. | For example: @@ -272,6 +273,11 @@ wicket.filter-path=/app/* wicket.filter-name=my-custom-wicket-filter ``` +By default the Wicket filter runs last, after every other filter, including Spring Security's +filter chain (order `-100`). That is usually what you want, since security decisions are made before +Wicket renders anything. Set `wicket.filter-order` if another filter of yours has to run after +Wicket instead. + --- ## Going to Production diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java index 2eb495a98b..e10b79537a 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketAutoConfiguration.java @@ -107,10 +107,10 @@ public FilterRegistrationBean wicketFilterRegistration( /** * Configures a {@link FilterRegistrationBean} for a given {@link WicketFilter}. - * Sets up the filter mapping path, filter name, and configuration type for Wicket. + * Sets up the filter mapping path, filter name, filter order and configuration type for Wicket. * * @param properties the {@link WicketProperties} containing configuration details such as filter path, - * filter name, and runtime configuration type + * filter name, filter order and runtime configuration type * @param filter the {@link WicketFilter} to be configured and registered * @return a configured {@link FilterRegistrationBean} instance for the provided {@link WicketFilter} */ @@ -120,6 +120,7 @@ private static FilterRegistrationBean configureWicketFilter( registration.setFilter(filter); registration.addUrlPatterns(properties.getFilterPath()); registration.setName(properties.getFilterName()); + registration.setOrder(properties.getFilterOrder()); // Specify configuration parameter mapping for Wicket registration.addInitParameter(WicketFilter.FILTER_MAPPING_PARAM, properties.getFilterPath()); diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java index 2543af2ce8..cedd918e82 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/java/org/wicketstuff/springboot/starter/WicketProperties.java @@ -15,6 +15,7 @@ import org.apache.wicket.RuntimeConfigurationType; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.core.Ordered; /** * Configuration properties for Apache Wicket integration in Spring Boot. @@ -53,6 +54,15 @@ public class WicketProperties { */ private RuntimeConfigurationType configuration = RuntimeConfigurationType.DEVELOPMENT; + /** + * Order of the Wicket Filter within the servlet filter chain. + *

+ * Lower values run earlier. Default is {@link Ordered#LOWEST_PRECEDENCE}, so Wicket runs after + * every other filter, e.g. after Spring Security's filter chain. + *

+ */ + private int filterOrder = Ordered.LOWEST_PRECEDENCE; + /** * Gets the URL mapping pattern for the Wicket Filter. * @@ -106,4 +116,22 @@ public RuntimeConfigurationType getConfiguration() { public void setConfiguration(RuntimeConfigurationType configuration) { this.configuration = configuration; } + + /** + * Gets the order of the Wicket Filter within the servlet filter chain. + * + * @return the filter order + */ + public int getFilterOrder() { + return filterOrder; + } + + /** + * Sets the order of the Wicket Filter within the servlet filter chain. + * + * @param filterOrder the filter order to set; lower values run earlier + */ + public void setFilterOrder(int filterOrder) { + this.filterOrder = filterOrder; + } } diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 5f4afde051..e53d54f497 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -5,6 +5,10 @@ "type": "java.lang.Boolean", "description": "Whether the Wicket auto-configuration is enabled. When false, no WebApplication, SpringComponentInjector or Wicket filter registration is contributed.", "defaultValue": true + }, + { + "name": "wicket.filter-order", + "defaultValue": 2147483647 } ] } diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java index 8971ce28d6..002539548c 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/WicketAutoConfigurationTest.java @@ -31,6 +31,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; import static org.assertj.core.api.Assertions.assertThat; @@ -53,6 +54,7 @@ void registersDefaultWebApplicationAndFilterWhenNoneProvided() { assertThat(registration.getFilter()).isInstanceOf(WicketFilter.class); assertThat(registration.getUrlPatterns()).containsExactly("/*"); assertThat(registration.getFilterName()).isEqualTo("wicket-filter"); + assertThat(registration.getOrder()).isEqualTo(Ordered.LOWEST_PRECEDENCE); assertThat(registration.getInitParameters()) .containsEntry("configuration", RuntimeConfigurationType.DEVELOPMENT.name()); }); @@ -64,11 +66,13 @@ void bindsCustomWicketPropertiesOntoTheFilterRegistration() { .withPropertyValues( "wicket.filter-path=/app/*", "wicket.filter-name=custom-wicket-filter", + "wicket.filter-order=-50", "wicket.configuration=DEPLOYMENT") .run(context -> { FilterRegistrationBean registration = context.getBean(FilterRegistrationBean.class); assertThat(registration.getUrlPatterns()).containsExactly("/app/*"); assertThat(registration.getFilterName()).isEqualTo("custom-wicket-filter"); + assertThat(registration.getOrder()).isEqualTo(-50); assertThat(registration.getInitParameters()) .containsEntry("configuration", RuntimeConfigurationType.DEPLOYMENT.name()); }); From 1acb1226ce0eb679aa0970a84a427dba3644bb35 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Mon, 28 Sep 2026 23:11:47 +0200 Subject: [PATCH 32/35] Make the starter work with Spring Boot DevTools With DevTools, Wicket's jars and a stale copy of the application classes stay in the base classloader while the application runs in the restart classloader. Restoring a stored page (the back button, or any page after a restart) resolved the page class from the base classloader but rebuilt its @SpringBean proxies for the restart classloader, failing with a ClassCastException. Ship META-INF/spring-devtools.properties to load all Wicket and wicketstuff jars in the restart classloader, guard its patterns with a test against the Wicket jars on the classpath, and document DevTools usage. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 17 ++++ .../META-INF/spring-devtools.properties | 13 +++ .../starter/DevToolsRestartIncludeTest.java | 86 +++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/spring-devtools.properties create mode 100644 wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DevToolsRestartIncludeTest.java diff --git a/wicketstuff-spring-boot-starter-parent/README.md b/wicketstuff-spring-boot-starter-parent/README.md index 825695bf2a..5b3ffd4654 100644 --- a/wicketstuff-spring-boot-starter-parent/README.md +++ b/wicketstuff-spring-boot-starter-parent/README.md @@ -100,6 +100,23 @@ for deploying to an external servlet container works unchanged — set `war` pac A direct declaration wins over the transitive one, so the embedded container is demoted to `provided` and stays out of `WEB-INF/lib` while Wicket and the starter are packaged as normal. +### Using Spring Boot DevTools + +The starter works with `spring-boot-devtools` out of the box. It ships a +`META-INF/spring-devtools.properties` that loads the Wicket and wicketstuff jars in DevTools' +restart classloader, next to your own classes. Without it, Wicket would restore stored pages +(e.g. on the back button) against a stale copy of your classes and fail with a +`ClassCastException` on every `@SpringBean` field. + +On a restart your session survives, but by default the pages in it do not: Wicket keeps them in +the servlet container's temporary directory, and Spring Boot creates a new one for every start of +the embedded Tomcat. Requesting an old page then simply renders it afresh. To keep page state across +restarts as well, give Tomcat a fixed base directory in development: + +```properties +server.tomcat.basedir=target/tomcat +``` + --- ## Dependency Configuration diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/spring-devtools.properties b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/spring-devtools.properties new file mode 100644 index 0000000000..c9c8e021ac --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/main/resources/META-INF/spring-devtools.properties @@ -0,0 +1,13 @@ +# Loads Wicket and wicketstuff jars (including this starter) in Spring Boot DevTools' restart +# classloader instead of its base classloader. +# +# Wicket deserializes pages from its page store with an ObjectInputStream that resolves classes +# through the nearest application classloader on the call stack. With Wicket in the base +# classloader, that resolves the application's page classes from the base classloader too, while +# @SpringBean proxies are rebuilt for the restart classloader's classes: restoring a stored page +# (the back button, or any page after a restart) then fails with a ClassCastException. +# +# Every jar that references Wicket types has to move together, or the two classloaders mismatch +# the other way round. +restart.include.wicket=/wicket-[\\w\\d-\\.]+\\.jar +restart.include.wicketstuff=/wicketstuff-[\\w\\d-\\.]+\\.jar diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DevToolsRestartIncludeTest.java b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DevToolsRestartIncludeTest.java new file mode 100644 index 0000000000..d4f4b8be8c --- /dev/null +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter/src/test/java/org/wicketstuff/springboot/starter/DevToolsRestartIncludeTest.java @@ -0,0 +1,86 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wicketstuff.springboot.starter; + +import java.io.File; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import java.util.regex.Pattern; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Guards {@code META-INF/spring-devtools.properties}, which moves Wicket into Spring Boot + * DevTools' restart classloader. DevTools matches each {@code restart.include.*} pattern against + * the URL of every classpath entry; a jar that references Wicket types but stays in the base + * classloader breaks page deserialization, so every Wicket and wicketstuff jar must match and + * nothing else should. + * + * @author Daniel Bartl + */ +class DevToolsRestartIncludeTest { + + @Test + void restartIncludePatternsMatchExactlyTheWicketJarsOnTheClasspath() throws Exception { + List patterns = restartIncludePatterns(); + List jars = Arrays.stream(System.getProperty("java.class.path").split(File.pathSeparator)) + .map(Path::of) + .filter(path -> path.getFileName().toString().endsWith(".jar")) + .toList(); + + List wicketJars = jars.stream() + .filter(jar -> jar.toString().contains("/org/apache/wicket/")) + .map(DevToolsRestartIncludeTest::url) + .toList(); + List otherJars = jars.stream() + .filter(jar -> !jar.toString().contains("/org/apache/wicket/") + && !jar.toString().contains("/org/wicketstuff/")) + .map(DevToolsRestartIncludeTest::url) + .toList(); + + assertThat(wicketJars).as("Wicket jars on the test classpath").isNotEmpty() + .allSatisfy(url -> assertThat(matchesAny(patterns, url)).as(url).isTrue()); + assertThat(otherJars) + .allSatisfy(url -> assertThat(matchesAny(patterns, url)).as(url).isFalse()); + assertThat(matchesAny(patterns, url(Path.of("/repo/org/wicketstuff/wicketstuff-spring-boot-starter/" + + "10.12.0/wicketstuff-spring-boot-starter-10.12.0.jar")))) + .as("the starter itself").isTrue(); + } + + private static List restartIncludePatterns() throws Exception { + Properties properties = new Properties(); + try (InputStream in = DevToolsRestartIncludeTest.class + .getResourceAsStream("/META-INF/spring-devtools.properties")) { + assertThat(in).as("META-INF/spring-devtools.properties").isNotNull(); + properties.load(in); + } + return properties.stringPropertyNames().stream() + .filter(name -> name.startsWith("restart.include.")) + .map(name -> Pattern.compile(properties.getProperty(name))) + .toList(); + } + + private static boolean matchesAny(List patterns, String url) { + return patterns.stream().anyMatch(pattern -> pattern.matcher(url).find()); + } + + private static String url(Path jar) { + return jar.toUri().toString(); + } +} From 3e3eb6f2bd74614310bb543354298bcec95ab261 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Mon, 28 Sep 2026 23:41:28 +0200 Subject: [PATCH 33/35] Keep the starter examples out of the wicketstuff BOM The examples module is excluded from publishing, so the BOM must not reference it either; its exclusion list is kept in sync with the publishing one. Co-Authored-By: Claude Opus 5.5 --- wicketstuff-bom/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wicketstuff-bom/pom.xml b/wicketstuff-bom/pom.xml index 7f158b872f..24d104473c 100644 --- a/wicketstuff-bom/pom.xml +++ b/wicketstuff-bom/pom.xml @@ -239,6 +239,10 @@ org.wicketstuff wicketstuff-springreference-examples + + org.wicketstuff + wicketstuff-spring-boot-starter-examples + org.wicketstuff jasperreports-examples From d34879698d2609f1b995220b240d0dce2fd70b39 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Mon, 28 Sep 2026 23:41:28 +0200 Subject: [PATCH 34/35] Complete the starter READMEs - Quickstart: define the injected service and show the page's markup and where it goes, so the example actually runs. - List Spring MVC coexistence, DevTools support and the filter order among the features, mention the BOM, and describe accurately what the integration test verifies. - Fix the examples' run command, which failed to resolve the spring-boot plugin prefix, and list SpringBeanInjectionDuringInitTest. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 48 +++++++++++++++---- .../README.md | 6 ++- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/wicketstuff-spring-boot-starter-parent/README.md b/wicketstuff-spring-boot-starter-parent/README.md index 5b3ffd4654..37f8d4b5b8 100644 --- a/wicketstuff-spring-boot-starter-parent/README.md +++ b/wicketstuff-spring-boot-starter-parent/README.md @@ -17,8 +17,7 @@ is ordinary Wicket and ordinary Spring, documented in their own projects. **Staying small is the point, not a limitation.** A deliberately narrow starter is cheap to keep alive: when Wicket or Spring Boot publishes a new major version, there is very little surface to re-verify. It also lives inside `wicketstuff-core` and is released with it, so the version you need -is simply the one matching your Wicket version — there is no separate compatibility matrix to -consult and no second release cycle to wait for. +is simply the one matching your Wicket version, and there is no second release cycle to wait for. ### Is this the right starter for you? @@ -40,8 +39,10 @@ philosophies, and neither is a replacement for the other. - **Auto-Configuration**: Automatically registers Wicket's `WicketFilter` in Spring Boot's embedded servlet container. - **Auto-Discovery**: Detects any subclass of Wicket's `WebApplication` registered as a Spring bean/component and binds it. - **Spring Injection Support**: Automatically adds `SpringComponentInjector` to the application, allowing you to use `@SpringBean` to inject Spring-managed components directly into Wicket Pages and Panels. -- **Externalized Settings**: Configure Wicket's execution mode (`DEVELOPMENT` vs `DEPLOYMENT`), filter paths, and filter names directly from Spring properties. +- **Externalized Settings**: Configure Wicket's execution mode (`DEVELOPMENT` vs `DEPLOYMENT`) and the filter's path, name and order directly from Spring properties. - **IDE Auto-Completion Support**: Ships with built-in configuration metadata, enabling auto-completion and documentation tooltips for Wicket properties in popular IDEs (IntelliJ, Eclipse, VS Code). +- **Spring MVC Coexistence**: Requests Wicket does not handle fall through to Spring MVC, so `@RestController` endpoints work next to Wicket pages. +- **DevTools Support**: Works with `spring-boot-devtools` out of the box: automatic restarts, the back button and restored pages keep working with `@SpringBean` fields. --- @@ -134,6 +135,8 @@ for the latest released version):
``` +If your build already imports the `wicketstuff-bom`, the version can be left out. + --- ## Compatibility Matrix @@ -144,10 +147,10 @@ Ensure you match the correct starter version with your Spring Boot and Java envi | :--- | :--- | :--- | :--- | | **`10.12.x`** (Current) | `4.0.x`, `4.1.x` | `7.0.x` | Java 17 | -Every supported Spring Boot line is verified by the integration test under -`wicketstuff-spring-boot-starter/src/it`: a project shaped like one generated by Spring Initializr, -inheriting from `spring-boot-starter-parent` so it runs against exactly the library versions Spring -Boot manages. To check another Spring Boot version, run from the starter module: +Compatibility is checked by the integration test under `wicketstuff-spring-boot-starter/src/it`: a +project shaped like one generated by Spring Initializr, inheriting from `spring-boot-starter-parent` +so it runs against exactly the library versions Spring Boot manages. Every build runs it against the +Spring Boot version in the parent pom; to check another supported line, run from the starter module: ```bash mvn verify -Dspring-boot.version=4.0.8 @@ -196,7 +199,23 @@ public class WicketApplication extends WebApplication { ``` ### 2. Inject Spring Beans into Pages -Use Wicket's standard `@SpringBean` annotation to inject Spring-managed services: +Any Spring bean can be injected, for example a simple service: + +```java +package com.example; + +import org.springframework.stereotype.Service; + +@Service +public class MySpringService { + + public String sayHello() { + return "Hello from Spring!"; + } +} +``` + +Use Wicket's standard `@SpringBean` annotation to inject it into a page: ```java package com.example; @@ -217,6 +236,19 @@ public class HomePage extends WebPage { } ``` +Every Wicket page needs its markup, in an HTML file named after the class. Put it in +`src/main/resources/com/example/HomePage.html`: Maven only copies resources from +`src/main/resources`, so an HTML file next to the Java source would not end up on the classpath. + +```html + + + +

+ + +``` + ### 3. Bootstrap your Spring Boot App Annotate your entry point with `@SpringBootApplication` and run it: diff --git a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/README.md b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/README.md index ea92ffbe38..524710b7dd 100644 --- a/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/README.md +++ b/wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples/README.md @@ -5,8 +5,11 @@ documented behaviour. ## Running it +From the repository root, install the starter first, then run the example: + ```bash -mvn -pl wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples -am spring-boot:run +mvn -pl wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter -am install -DskipTests +mvn -f wicketstuff-spring-boot-starter-parent/wicketstuff-spring-boot-starter-examples spring-boot:run ``` Then open . @@ -27,6 +30,7 @@ every build rather than drifting out of date as untested sample code: |---|---| | A custom `WebApplication` and a page using `@SpringBean` | `SpringBeanInjectionQuickstartTest` (with `QuickstartWebApplication`, `QuickstartHomePage`, `GreetingService`) | | That `@SpringBean` still works if you supply your own filter registration | `SpringBeanInjectionWithCustomFilterRegistrationTest` | +| That `@SpringBean` already works inside your application's `init()` | `SpringBeanInjectionDuringInitTest` | | REST controllers living alongside Wicket pages | `WicketAndSpringMvcCoexistenceTest` | | `wicket.*` properties actually reaching the filter | `WicketPropertiesBindingTest` | | That the starter alone is enough to boot a web application | `StarterSelfSufficiencyTest` | From 3d43c112d79dadb3b64c3d5c9b74882b40529809 Mon Sep 17 00:00:00 2001 From: Daniel Bartl <630704+danielbartl@users.noreply.github.com> Date: Mon, 28 Sep 2026 23:45:08 +0200 Subject: [PATCH 35/35] Document the plan to list the starter on start.spring.io State the goal in the motivation and outline the steps: merge, release to Maven Central, then request the listing with the prepared Initializr entry. Co-Authored-By: Claude Opus 5.5 --- .../README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/wicketstuff-spring-boot-starter-parent/README.md b/wicketstuff-spring-boot-starter-parent/README.md index 37f8d4b5b8..3b1bca765b 100644 --- a/wicketstuff-spring-boot-starter-parent/README.md +++ b/wicketstuff-spring-boot-starter-parent/README.md @@ -19,6 +19,10 @@ alive: when Wicket or Spring Boot publishes a new major version, there is very l re-verify. It also lives inside `wicketstuff-core` and is released with it, so the version you need is simply the one matching your Wicket version, and there is no second release cycle to wait for. +The goal is also to make Apache Wicket selectable on [start.spring.io](https://start.spring.io), the +way Vaadin already is, so that a new Wicket project is one click away. See +[Road to start.spring.io](#road-to-startspringio) for the plan. + ### Is this the right starter for you? There is an established alternative, [`MarcGiffing/wicket-spring-boot`][giffing] @@ -372,6 +376,21 @@ filter is never initialised. ## Spring Initializr Metadata Registration +### Road to start.spring.io + +Listing the starter on start.spring.io is planned once it has been released, in three steps: + +1. The starter is merged into `wicketstuff-core`. +2. It ships with the next wicketstuff release and is published to Maven Central. The Initializr can + only reference released versions, never snapshots. +3. The listing is requested from the Spring Initializr team with the entry below, and kept up to + date for every new Spring Boot line afterwards. + +Until then, add the dependency to a generated Spring Boot project by hand, as shown in +[Dependency Configuration](#dependency-configuration). + +### The Initializr entry + To list the starter on `start.spring.io` (or in an internal Initializr instance), the dependency is added to the Initializr's `application.yml`. Spring Boot's BOM does not manage `org.wicketstuff` artifacts, so the entry has to say which starter version goes with which Spring Boot line;