diff --git a/README.md b/README.md
index 19faeb9..a3327de 100644
--- a/README.md
+++ b/README.md
@@ -7,20 +7,68 @@ This project requires Java 21 compiler.
## Usage
-Include Launchpad to your project:
-
-```xml
-
+- Include Launchpad to your project:
+ ```xml
+
de.focus-shift
launchpad
...
-
+
+ ```
+ - Choose the right version of Launchpad for your Spring Boot version:
+ - 3.x is using spring boot 4.x as a parent
+ - 1.x is using spring boot 3.x as a parent
+ - 0.x is using spring boot 2.x as a parent
+- Configure launchpad apps in your `application.yml`
+ ```yaml
+ launchpad:
+ name-default-locale: de
+ apps[0]:
+ icon: data:image/png;base64,xxxxxxx
+ name:
+ de: name-1-de
+ en: name-1-en
+ url: https://link-1
+ apps[1]:
+ icon: /static/images/app-icon.png
+ name:
+ de: name-2-de
+ en: name-2-en
+ url: https://link-2
+ ```
+- Assign `HasLaunchpad` to all Controllers you want the launchpad to be available
+
+### Advanced
+
+#### Launchpad on Error Pages
+
+Create a custom `ErrorControllerAdvice` and use the `LaunchpadModelAttributeAppender`
+to prepare the required launchpad model attributes.
+
+Example:
+
+```java
+@ControllerAdvice(assignableTypes = ErrorController.class)
+@Conditional(LaunchpadAutoConfiguration.LaunchpadAppsCondition.class)
+class ErrorControllerAdvice {
+
+ private final LaunchpadModelAttributeAppender launchpadModelAttributeAppender;
+
+ ErrorControllerAdvice(LaunchpadModelAttributeAppender launchpadModelAttributeAppender) {
+ this.launchpadModelAttributeAppender = launchpadModelAttributeAppender;
+ }
+
+ @ModelAttribute
+ public void addAttributes(Model model, Locale locale, Authentication authentication) {
+ launchpadModelAttributeAppender.addModelAttribute(model, locale, authentication);
+ }
+}
```
-Choose the right version of Launchpad for your Spring Boot version:
-* 3.x is using spring boot 4.x as a parent
-* 1.x is using spring boot 3.x as a parent
-* 0.x is using spring boot 2.x as a parent
+You can inject `HttpServletRequest` to check the requested URL with
+`request.getAttribute("jakarta.servlet.error.request_uri")` and only call the
+`LaunchpadModelAttributeAppender` if the requested URL matches your condition.
+
## License
diff --git a/src/main/java/de/focus_shift/launchpad/core/LaunchpadAutoConfiguration.java b/src/main/java/de/focus_shift/launchpad/core/LaunchpadAutoConfiguration.java
index 8380210..906ed0b 100644
--- a/src/main/java/de/focus_shift/launchpad/core/LaunchpadAutoConfiguration.java
+++ b/src/main/java/de/focus_shift/launchpad/core/LaunchpadAutoConfiguration.java
@@ -27,8 +27,15 @@ public class LaunchpadAutoConfiguration {
static class LaunchpadConfig {
@Bean
- LaunchpadControllerAdvice launchpadControllerAdvice(LaunchpadService launchpadService) {
- return new LaunchpadControllerAdvice(launchpadService);
+ LaunchpadModelAttributeAppender launchpadModelAttributeAppender(
+ LaunchpadService launchpadService) {
+ return new LaunchpadModelAttributeAppender(launchpadService);
+ }
+
+ @Bean
+ LaunchpadControllerAdvice launchpadControllerAdvice(
+ LaunchpadModelAttributeAppender launchpadModelAttributeAppender) {
+ return new LaunchpadControllerAdvice(launchpadModelAttributeAppender);
}
@Bean
@@ -48,7 +55,7 @@ LaunchpadAppUrlCustomizer appUrlCustomizer() {
/** Checks if 'launchpad.apps' are configured appropriate. */
// copied and adjusted from
// org.springframework.boot.autoconfigure.condition.OnPropertyListCondition
- static class LaunchpadAppsCondition extends SpringBootCondition {
+ public static class LaunchpadAppsCondition extends SpringBootCondition {
private static final Bindable> APP_LIST =
Bindable.listOf(LaunchpadConfigProperties.App.class);
private static final String PROPERTY_NAME = "launchpad.apps";
diff --git a/src/main/java/de/focus_shift/launchpad/core/LaunchpadControllerAdvice.java b/src/main/java/de/focus_shift/launchpad/core/LaunchpadControllerAdvice.java
index f183813..63d3840 100644
--- a/src/main/java/de/focus_shift/launchpad/core/LaunchpadControllerAdvice.java
+++ b/src/main/java/de/focus_shift/launchpad/core/LaunchpadControllerAdvice.java
@@ -1,7 +1,6 @@
package de.focus_shift.launchpad.core;
import de.focus_shift.launchpad.api.HasLaunchpad;
-import java.util.List;
import java.util.Locale;
import org.springframework.security.core.Authentication;
import org.springframework.ui.Model;
@@ -11,27 +10,14 @@
@ControllerAdvice(assignableTypes = {HasLaunchpad.class})
public class LaunchpadControllerAdvice {
- private final LaunchpadService launchpadService;
+ private final LaunchpadModelAttributeAppender modelAttributeAppender;
- LaunchpadControllerAdvice(LaunchpadService launchpadService) {
- this.launchpadService = launchpadService;
+ LaunchpadControllerAdvice(LaunchpadModelAttributeAppender modelAttributeAppender) {
+ this.modelAttributeAppender = modelAttributeAppender;
}
@ModelAttribute
public void addAttributes(Model model, Locale locale, Authentication authentication) {
-
- final Launchpad launchpad = launchpadService.getLaunchpad(authentication);
-
- final List appDtos =
- launchpad.getApps().stream()
- .map(
- app ->
- new AppDto(
- app.getUrl().toString(), app.getAppName().get(locale), app.getIcon()))
- .toList();
-
- if (!appDtos.isEmpty()) {
- model.addAttribute("launchpad", new LaunchpadDto(appDtos));
- }
+ modelAttributeAppender.addModelAttribute(model, locale, authentication);
}
}
diff --git a/src/main/java/de/focus_shift/launchpad/core/LaunchpadModelAttributeAppender.java b/src/main/java/de/focus_shift/launchpad/core/LaunchpadModelAttributeAppender.java
new file mode 100644
index 0000000..23c3906
--- /dev/null
+++ b/src/main/java/de/focus_shift/launchpad/core/LaunchpadModelAttributeAppender.java
@@ -0,0 +1,32 @@
+package de.focus_shift.launchpad.core;
+
+import java.util.List;
+import java.util.Locale;
+import org.springframework.security.core.Authentication;
+import org.springframework.ui.Model;
+
+public class LaunchpadModelAttributeAppender {
+
+ private final LaunchpadService launchpadService;
+
+ LaunchpadModelAttributeAppender(LaunchpadService launchpadService) {
+ this.launchpadService = launchpadService;
+ }
+
+ public void addModelAttribute(Model model, Locale locale, Authentication authentication) {
+
+ final Launchpad launchpad = launchpadService.getLaunchpad(authentication);
+
+ final List appDtos =
+ launchpad.getApps().stream()
+ .map(
+ app ->
+ new AppDto(
+ app.getUrl().toString(), app.getAppName().get(locale), app.getIcon()))
+ .toList();
+
+ if (!appDtos.isEmpty()) {
+ model.addAttribute("launchpad", new LaunchpadDto(appDtos));
+ }
+ }
+}
diff --git a/src/test/java/de/focus_shift/launchpad/core/LaunchpadControllerAdviceIT.java b/src/test/java/de/focus_shift/launchpad/core/LaunchpadControllerAdviceIT.java
index 3b9f180..263857e 100644
--- a/src/test/java/de/focus_shift/launchpad/core/LaunchpadControllerAdviceIT.java
+++ b/src/test/java/de/focus_shift/launchpad/core/LaunchpadControllerAdviceIT.java
@@ -26,7 +26,7 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
-@SpringBootTest(classes = {LaunchpadControllerAdvice.class})
+@SpringBootTest(classes = {LaunchpadControllerAdvice.class, LaunchpadModelAttributeAppender.class})
@ContextConfiguration(classes = {LaunchpadControllerAdviceIT.TestConfig.class})
@AutoConfigureMockMvc
class LaunchpadControllerAdviceIT {