From eaad93bb28ffb50a8b33915696c61475181de25d Mon Sep 17 00:00:00 2001
From: Thorsten Marx
Date: Wed, 16 Apr 2025 11:28:19 +0200
Subject: [PATCH 1/8] hooks via annotations
---
CHANGELOG.md | 20 +++++
.../com/condation/cms/api/hooks/Action.java | 14 ++-
.../condation/cms/api/hooks/ActionHook.java | 31 +++++++
.../com/condation/cms/api/hooks/Filter.java | 14 ++-
.../condation/cms/api/hooks/FilterHook.java | 31 +++++++
.../condation/cms/api/hooks/HookSystem.java | 90 ++++++++++++++-----
.../cms/api/hooks/HookSystemTest.java | 44 +++++++++
7 files changed, 218 insertions(+), 26 deletions(-)
create mode 100644 cms-api/src/main/java/com/condation/cms/api/hooks/ActionHook.java
create mode 100644 cms-api/src/main/java/com/condation/cms/api/hooks/FilterHook.java
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e14582048..816390241 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,26 @@ see wiki for more information: [wiki](https://github.com/thmarx/cms/wiki)
* **MAINTENANCE** multiple dependencies updated
* **MAINTENANCE** maven wrapper added to project
+### Developer experience
+
+In this release we introduced some features to make life of developers easier.
+
+#### Registering hooks via annotations
+
+```java
+@Filter("test/annotation/filter1")
+public List filter (FilterContext> context) {
+ context.value().remove("2");
+ return context.value();
+}
+@Action("test/annotation/action1")
+public void action1 (ActionContext> context) {
+ // do something
+}
+```
+
+#### HTTP-Controllers
+
## 7.8.0
* **BUG** Namespaces not set when executing content pipeline [#416](https://github.com/CondationCMS/cms-server/pull/416)
diff --git a/cms-api/src/main/java/com/condation/cms/api/hooks/Action.java b/cms-api/src/main/java/com/condation/cms/api/hooks/Action.java
index e1e849a3d..a39b4e0cd 100644
--- a/cms-api/src/main/java/com/condation/cms/api/hooks/Action.java
+++ b/cms-api/src/main/java/com/condation/cms/api/hooks/Action.java
@@ -4,7 +4,7 @@
* #%L
* cms-api
* %%
- * Copyright (C) 2023 - 2024 CondationCMS
+ * Copyright (C) 2023 - 2025 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
@@ -22,10 +22,18 @@
* #L%
*/
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
/**
*
- * @author t.marx
+ * @author thorstenmarx
*/
-public record Action(String name, int priority, ActionFunction function) implements Hook {
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface Action {
+ String value ();
+ int priority () default 10;
}
diff --git a/cms-api/src/main/java/com/condation/cms/api/hooks/ActionHook.java b/cms-api/src/main/java/com/condation/cms/api/hooks/ActionHook.java
new file mode 100644
index 000000000..281d421da
--- /dev/null
+++ b/cms-api/src/main/java/com/condation/cms/api/hooks/ActionHook.java
@@ -0,0 +1,31 @@
+package com.condation.cms.api.hooks;
+
+/*-
+ * #%L
+ * cms-api
+ * %%
+ * Copyright (C) 2023 - 2024 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+
+/**
+ *
+ * @author t.marx
+ */
+record ActionHook(String name, int priority, ActionFunction function) implements Hook {
+}
diff --git a/cms-api/src/main/java/com/condation/cms/api/hooks/Filter.java b/cms-api/src/main/java/com/condation/cms/api/hooks/Filter.java
index 1ae6e0b22..84345a36f 100644
--- a/cms-api/src/main/java/com/condation/cms/api/hooks/Filter.java
+++ b/cms-api/src/main/java/com/condation/cms/api/hooks/Filter.java
@@ -4,7 +4,7 @@
* #%L
* cms-api
* %%
- * Copyright (C) 2023 - 2024 CondationCMS
+ * Copyright (C) 2023 - 2025 CondationCMS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
@@ -22,10 +22,18 @@
* #L%
*/
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
/**
*
- * @author t.marx
+ * @author thorstenmarx
*/
-public record Filter(String name, int priority, FilterFunction function) implements Hook {
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface Filter {
+ String value ();
+ int priority () default 10;
}
diff --git a/cms-api/src/main/java/com/condation/cms/api/hooks/FilterHook.java b/cms-api/src/main/java/com/condation/cms/api/hooks/FilterHook.java
new file mode 100644
index 000000000..2e3a2f3a5
--- /dev/null
+++ b/cms-api/src/main/java/com/condation/cms/api/hooks/FilterHook.java
@@ -0,0 +1,31 @@
+package com.condation.cms.api.hooks;
+
+/*-
+ * #%L
+ * cms-api
+ * %%
+ * Copyright (C) 2023 - 2024 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+
+/**
+ *
+ * @author t.marx
+ */
+record FilterHook(String name, int priority, FilterFunction function) implements Hook {
+}
diff --git a/cms-api/src/main/java/com/condation/cms/api/hooks/HookSystem.java b/cms-api/src/main/java/com/condation/cms/api/hooks/HookSystem.java
index bd714568f..e3e699272 100644
--- a/cms-api/src/main/java/com/condation/cms/api/hooks/HookSystem.java
+++ b/cms-api/src/main/java/com/condation/cms/api/hooks/HookSystem.java
@@ -21,9 +21,9 @@
* .
* #L%
*/
-
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@@ -40,40 +40,90 @@
@RequiredArgsConstructor
public class HookSystem {
- Multimap actions = ArrayListMultimap.create();
-
- Multimap filters = ArrayListMultimap.create();
-
- private HookSystem (HookSystem source) {
+ Multimap actions = ArrayListMultimap.create();
+
+ Multimap filters = ArrayListMultimap.create();
+
+ private HookSystem(HookSystem source) {
this.actions.putAll(source.actions);
this.filters.putAll(source.filters);
}
-
- public HookSystem clone () {
+
+ public HookSystem clone() {
return new HookSystem(this);
}
+ public void register(Object sourceObject) {
+ Class> objectClass = sourceObject.getClass();
+ for (Method method : objectClass.getDeclaredMethods()) {
+ // regsiter actions
+ var actionAnnotation = method.getAnnotation(Action.class);
+ if (actionAnnotation != null) {
+
+ var parameters = method.getParameterTypes();
+ if (parameters.length != 1 || !ActionContext.class.isAssignableFrom(parameters[0])) {
+ log.warn("Method {}.{} ignored: must have exactly one parameter of type ActionContext",
+ objectClass.getSimpleName(), method.getName());
+ } else {
+ if (!method.canAccess(sourceObject)) {
+ method.setAccessible(true);
+ }
+
+ registerAction(actionAnnotation.value(), context -> {
+ try {
+ return method.invoke(sourceObject, context);
+ } catch (Exception e) {
+ log.error("Error invoking action method {}.{}", objectClass.getSimpleName(), method.getName(), e);
+ throw new RuntimeException(e);
+ }
+ }, actionAnnotation.priority());
+ }
+ }
+
+ // register filters
+ var filterAnnotation = method.getAnnotation(Filter.class);
+ if (filterAnnotation != null) {
+ var parameters = method.getParameterTypes();
+ if (parameters.length != 1 || !FilterContext.class.isAssignableFrom(parameters[0])) {
+ log.warn("Method {}.{} ignored for Filter: must have exactly one parameter of type FilterContext",
+ objectClass.getSimpleName(), method.getName());
+ } else {
+ if (!method.canAccess(sourceObject)) {
+ method.setAccessible(true);
+ }
+ registerFilter(filterAnnotation.value(), context -> {
+ try {
+ return method.invoke(sourceObject, context);
+ } catch (Exception e) {
+ log.error("Error invoking filter method {}.{}", objectClass.getSimpleName(), method.getName(), e);
+ throw new RuntimeException(e);
+ }
+ }, filterAnnotation.priority());
+ }
+ }
+ }
+ }
+
public void registerAction(final String name, final ActionFunction hookFunction) {
registerAction(name, hookFunction, 10);
}
public void registerAction(final String name, final ActionFunction hookFunction, int priority) {
- actions.put(name, new Action<>(name, priority, hookFunction));
+ actions.put(name, new ActionHook<>(name, priority, hookFunction));
}
-
+
public void registerFilter(final String name, final FilterFunction hookFunction) {
registerFilter(name, hookFunction, 10);
}
public void registerFilter(final String name, final FilterFunction hookFunction, int priority) {
- filters.put(name, new Filter<>(name, priority, hookFunction));
+ filters.put(name, new FilterHook<>(name, priority, hookFunction));
}
-
+
public ActionContext execute(final String name) {
return execute(name, Map.of());
}
-
-
+
public ActionContext execute(final String name, final Map arguments) {
var context = new ActionContext(new HashMap<>(arguments), new ArrayList<>());
actions.get(name).stream()
@@ -91,15 +141,15 @@ public ActionContext execute(final String name, final Map
* @param name
* @param parameters
- * @return
+ * @return
*/
public FilterContext filter(final String name, final T parameters) {
final FilterContext returnContext = new FilterContext(
@@ -111,7 +161,7 @@ public FilterContext filter(final String name, final T parameters) {
try {
var context = new FilterContext(returnContext.value());
var result = action.function().apply(context);
- returnContext.value((T)result);
+ returnContext.value((T) result);
} catch (Exception e) {
log.error("error on filter", e);
}
diff --git a/cms-api/src/test/java/com/condation/cms/api/hooks/HookSystemTest.java b/cms-api/src/test/java/com/condation/cms/api/hooks/HookSystemTest.java
index ae5081095..670655d8e 100644
--- a/cms-api/src/test/java/com/condation/cms/api/hooks/HookSystemTest.java
+++ b/cms-api/src/test/java/com/condation/cms/api/hooks/HookSystemTest.java
@@ -26,6 +26,7 @@
import com.condation.cms.api.hooks.HookSystem;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -110,4 +111,47 @@ public void test_filter_remove () {
var context = hookSystem.filter("test/list", new ArrayList<>(List.of("1", "2", "3")));
Assertions.assertThat(context.value()).containsExactly("1", "3");
}
+
+ @Test
+ void test_action_annotation () {
+ var actionObject = new MyActions();
+
+ hookSystem.register(actionObject);
+
+ hookSystem.execute("test/annotation/action1");
+
+ Assertions.assertThat(actionObject.counter).hasValue(2);
+ }
+
+ @Test
+ void test_filter_annotations () {
+ var myFilters = new MyFilters();
+
+ hookSystem.register(myFilters);
+
+ var context = hookSystem.filter("test/annotation/filter1", new ArrayList<>(List.of("1", "2", "3")));
+ Assertions.assertThat(context.value()).containsExactly("1", "3");
+ }
+
+ public class MyFilters {
+ @Filter("test/annotation/filter1")
+ public List filter (FilterContext> context) {
+ context.value().remove("2");
+ return context.value();
+ }
+ }
+
+ public class MyActions {
+
+ private AtomicInteger counter = new AtomicInteger(0);
+
+ @Action("test/annotation/action1")
+ public void action1 (ActionContext> context) {
+ counter.incrementAndGet();
+ }
+ @Action("test/annotation/action1")
+ public void action2 (ActionContext> context) {
+ counter.incrementAndGet();
+ }
+ }
}
From d930d3a4fc24bb99446cb36672466e66bb500be9 Mon Sep 17 00:00:00 2001
From: Thorsten Marx
Date: Wed, 16 Apr 2025 15:39:23 +0200
Subject: [PATCH 2/8] register routes via annotations
---
.../cms/api/extensions/HttpHandler.java | 8 ++
.../cms/api/extensions/routes/Route.java | 35 ++++++++
.../routes/RoutesExtensionPoint.java | 34 ++++++++
.../api/extensions/routes/RoutesManager.java | 82 +++++++++++++++++++
.../extensions/routes/RoutesManagerTest.java | 79 ++++++++++++++++++
.../server/handler/http/RoutesHandler.java | 24 +++++-
6 files changed, 260 insertions(+), 2 deletions(-)
create mode 100644 cms-api/src/main/java/com/condation/cms/api/extensions/routes/Route.java
create mode 100644 cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesExtensionPoint.java
create mode 100644 cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesManager.java
create mode 100644 cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/HttpHandler.java b/cms-api/src/main/java/com/condation/cms/api/extensions/HttpHandler.java
index 7916688f1..9006a97bc 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/HttpHandler.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/HttpHandler.java
@@ -33,5 +33,13 @@
*/
public interface HttpHandler {
+ /**
+ *
+ * @param request
+ * @param response
+ * @param callback
+ * @return true if the request is handled by the HttpHandler, otherwise false
+ * @throws Exception
+ */
boolean handle (Request request, Response response, Callback callback) throws Exception;
}
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/routes/Route.java b/cms-api/src/main/java/com/condation/cms/api/extensions/routes/Route.java
new file mode 100644
index 000000000..a2aced9fd
--- /dev/null
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/routes/Route.java
@@ -0,0 +1,35 @@
+package com.condation.cms.api.extensions.routes;
+
+/*-
+ * #%L
+ * cms-api
+ * %%
+ * Copyright (C) 2023 - 2025 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Route {
+ String value();
+ String method() default "GET"; // Optional: GET, POST, PUT, DELETE ...
+}
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesExtensionPoint.java b/cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesExtensionPoint.java
new file mode 100644
index 000000000..90ba32384
--- /dev/null
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesExtensionPoint.java
@@ -0,0 +1,34 @@
+package com.condation.cms.api.extensions.routes;
+
+/*-
+ * #%L
+ * cms-api
+ * %%
+ * Copyright (C) 2023 - 2025 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import com.condation.cms.api.extensions.AbstractExtensionPoint;
+
+/**
+ *
+ * @author thorstenmarx
+ */
+public abstract class RoutesExtensionPoint extends AbstractExtensionPoint {
+
+ abstract public void registerRoutes (RoutesManager routesManager);
+}
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesManager.java b/cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesManager.java
new file mode 100644
index 000000000..b13490523
--- /dev/null
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesManager.java
@@ -0,0 +1,82 @@
+package com.condation.cms.api.extensions.routes;
+
+/*-
+ * #%L
+ * cms-api
+ * %%
+ * Copyright (C) 2023 - 2025 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import com.condation.cms.api.extensions.http.HttpHandler;
+import com.condation.cms.api.extensions.http.PathMapping;
+import org.eclipse.jetty.http.pathmap.PathSpec;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Optional;
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.util.Callback;
+
+@Slf4j
+public class RoutesManager {
+
+ //private final Map handlerMapping = new HashMap<>();
+ private final PathMapping pathMapping = new PathMapping();
+
+ public Optional findFirst (String path, String method) {
+ return pathMapping.getMatchingHandler(path, method);
+ }
+
+ public void register(Object controller) {
+ Class> clazz = controller.getClass();
+
+ for (Method method : clazz.getDeclaredMethods()) {
+ Route route = method.getAnnotation(Route.class);
+ if (route != null && isValidHandlerMethod(method)) {
+ method.setAccessible(true);
+
+ PathSpec pathSpec = PathSpec.from(route.value());
+
+ HttpHandler handler = (request, response, callback) -> {
+ try {
+ return (Boolean) method.invoke(controller, request, response, callback);
+ } catch (Exception e) {
+ log.error("", e);
+ response.setStatus(500);
+ return true;
+ }
+ };
+ pathMapping.add(pathSpec, route.method(), handler);
+ }
+ }
+ }
+
+ private boolean isValidHandlerMethod(Method method) {
+ // Muss "boolean handle(Request, Response, Callback)" sein
+ if (!Modifier.isPublic(method.getModifiers())) return false;
+ if (!method.getReturnType().equals(boolean.class)) return false;
+
+ Class>[] params = method.getParameterTypes();
+ return params.length == 3 &&
+ Request.class.isAssignableFrom(params[0]) &&
+ Response.class.isAssignableFrom(params[1]) &&
+ Callback.class.isAssignableFrom(params[2]);
+ }
+}
diff --git a/cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java b/cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java
new file mode 100644
index 000000000..5ce98603c
--- /dev/null
+++ b/cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java
@@ -0,0 +1,79 @@
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/UnitTests/JUnit5TestClass.java to edit this template
+ */
+package com.condation.cms.api.extensions.routes;
+
+/*-
+ * #%L
+ * cms-api
+ * %%
+ * Copyright (C) 2023 - 2025 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import com.google.common.base.Stopwatch;
+import java.util.concurrent.TimeUnit;
+import org.assertj.core.api.Assertions;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Response;
+import org.eclipse.jetty.util.Callback;
+import org.junit.jupiter.api.Test;
+
+/**
+ *
+ * @author thorstenmarx
+ */
+public class RoutesManagerTest {
+
+ @Test
+ public void testRegister() {
+ Object controller = new MyRoutes();
+ RoutesManager instance = new RoutesManager();
+ instance.register(controller);
+
+ var handler1 = instance.findFirst("/test1", "GET");
+ Assertions.assertThat(handler1).isPresent();
+ var handler2 = instance.findFirst("/test2", "GET");
+ Assertions.assertThat(handler2).isPresent();
+ }
+
+ @Test
+ public void test_no_handler() {
+ Object controller = new MyRoutes();
+ RoutesManager instance = new RoutesManager();
+ instance.register(controller);
+
+ var handler = instance.findFirst("/test3", "GET");
+ Assertions.assertThat(handler).isEmpty();
+ }
+
+ public class MyRoutes {
+
+ @Route("/test1")
+ public boolean handle1 (Request request, Response response, Callback callback) {
+ return true;
+ }
+
+ @Route("/test2")
+ public boolean handle2 (Request request, Response response, Callback callback) {
+ return true;
+ }
+ }
+
+
+}
diff --git a/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java b/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java
index 2171ded65..da442d11e 100644
--- a/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java
+++ b/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java
@@ -24,6 +24,8 @@
import com.condation.cms.api.extensions.HttpRoutesExtensionPoint;
import com.condation.cms.api.extensions.Mapping;
+import com.condation.cms.api.extensions.routes.RoutesExtensionPoint;
+import com.condation.cms.api.extensions.routes.RoutesManager;
import com.condation.cms.api.request.RequestContext;
import com.condation.cms.api.utils.RequestUtil;
import com.condation.cms.extensions.HttpHandlerExtension;
@@ -62,8 +64,8 @@ public boolean handle(Request request, Response response, Callback callback) thr
if (tryModuleRoutes(request, response, callback)) {
return true;
}
-
- return false;
+
+ return tryRoutesManager(request, response, callback);
} catch (Exception e) {
log.error(null, e);
callback.failed(e);
@@ -71,6 +73,24 @@ public boolean handle(Request request, Response response, Callback callback) thr
}
}
+ private boolean tryRoutesManager (Request request, Response response, Callback callback) throws Exception {
+ String route = "/" + RequestUtil.getContentPath(request);
+
+ RoutesManager routesManager = new RoutesManager();
+
+
+ moduleManager.extensions(RoutesExtensionPoint.class)
+ .stream()
+ .forEach(extension -> extension.registerRoutes(routesManager));
+
+ var handler = routesManager.findFirst(route, request.getMethod());
+ if (handler.isPresent()) {
+ return handler.get().handle(request, response, callback);
+ }
+
+ return false;
+ }
+
private boolean tryModuleRoutes(Request request, Response response, Callback callback) throws Exception {
String route = "/" + RequestUtil.getContentPath(request);
From ba040702ec268f0ec31bbb2241685bf4faee64e6 Mon Sep 17 00:00:00 2001
From: Thorsten Marx
Date: Wed, 16 Apr 2025 15:39:58 +0200
Subject: [PATCH 3/8] refactor package
---
.../condation/cms/api/extensions/{ => http}/routes/Route.java | 2 +-
.../extensions/{ => http}/routes/RoutesExtensionPoint.java | 2 +-
.../cms/api/extensions/{ => http}/routes/RoutesManager.java | 2 +-
.../cms/api/extensions/routes/RoutesManagerTest.java | 2 ++
.../com/condation/cms/server/handler/http/RoutesHandler.java | 4 ++--
5 files changed, 7 insertions(+), 5 deletions(-)
rename cms-api/src/main/java/com/condation/cms/api/extensions/{ => http}/routes/Route.java (95%)
rename cms-api/src/main/java/com/condation/cms/api/extensions/{ => http}/routes/RoutesExtensionPoint.java (94%)
rename cms-api/src/main/java/com/condation/cms/api/extensions/{ => http}/routes/RoutesManager.java (98%)
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/routes/Route.java b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/Route.java
similarity index 95%
rename from cms-api/src/main/java/com/condation/cms/api/extensions/routes/Route.java
rename to cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/Route.java
index a2aced9fd..abfac457c 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/routes/Route.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/Route.java
@@ -1,4 +1,4 @@
-package com.condation.cms.api.extensions.routes;
+package com.condation.cms.api.extensions.http.routes;
/*-
* #%L
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesExtensionPoint.java b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesExtensionPoint.java
similarity index 94%
rename from cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesExtensionPoint.java
rename to cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesExtensionPoint.java
index 90ba32384..b795087d0 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesExtensionPoint.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesExtensionPoint.java
@@ -1,4 +1,4 @@
-package com.condation.cms.api.extensions.routes;
+package com.condation.cms.api.extensions.http.routes;
/*-
* #%L
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesManager.java b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java
similarity index 98%
rename from cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesManager.java
rename to cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java
index b13490523..af6dbfbad 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/routes/RoutesManager.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java
@@ -1,4 +1,4 @@
-package com.condation.cms.api.extensions.routes;
+package com.condation.cms.api.extensions.http.routes;
/*-
* #%L
diff --git a/cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java b/cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java
index 5ce98603c..3674e9ff9 100644
--- a/cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java
+++ b/cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java
@@ -26,6 +26,8 @@
* #L%
*/
+import com.condation.cms.api.extensions.http.routes.Route;
+import com.condation.cms.api.extensions.http.routes.RoutesManager;
import com.google.common.base.Stopwatch;
import java.util.concurrent.TimeUnit;
import org.assertj.core.api.Assertions;
diff --git a/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java b/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java
index da442d11e..28d8008e1 100644
--- a/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java
+++ b/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java
@@ -24,8 +24,8 @@
import com.condation.cms.api.extensions.HttpRoutesExtensionPoint;
import com.condation.cms.api.extensions.Mapping;
-import com.condation.cms.api.extensions.routes.RoutesExtensionPoint;
-import com.condation.cms.api.extensions.routes.RoutesManager;
+import com.condation.cms.api.extensions.http.routes.RoutesExtensionPoint;
+import com.condation.cms.api.extensions.http.routes.RoutesManager;
import com.condation.cms.api.request.RequestContext;
import com.condation.cms.api.utils.RequestUtil;
import com.condation.cms.extensions.HttpHandlerExtension;
From 55e2b5cac8f9936e6424c75985c1c3547597a8fb Mon Sep 17 00:00:00 2001
From: Thorsten Marx
Date: Wed, 16 Apr 2025 15:53:12 +0200
Subject: [PATCH 4/8] refactor test, update changelog
---
CHANGELOG.md | 11 +++++++++++
.../{ => http}/routes/RoutesManagerTest.java | 6 +-----
2 files changed, 12 insertions(+), 5 deletions(-)
rename cms-api/src/test/java/com/condation/cms/api/extensions/{ => http}/routes/RoutesManagerTest.java (89%)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 816390241..456cad960 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,8 @@ In this release we introduced some features to make life of developers easier.
#### Registering hooks via annotations
+It is now possible to pass an object with annotated hook definitions to the HookSystem.register method.
+
```java
@Filter("test/annotation/filter1")
public List filter (FilterContext> context) {
@@ -31,6 +33,15 @@ public void action1 (ActionContext> context) {
#### HTTP-Controllers
+The new RoutesExtensionPoint gives developers access to the RoutesManager, which includes a register method for adding routes via annotated methods.
+
+```java
+@Route("/test2")
+public boolean handle2 (Request request, Response response, Callback callback) {
+ return true;
+}
+```
+
## 7.8.0
* **BUG** Namespaces not set when executing content pipeline [#416](https://github.com/CondationCMS/cms-server/pull/416)
diff --git a/cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java b/cms-api/src/test/java/com/condation/cms/api/extensions/http/routes/RoutesManagerTest.java
similarity index 89%
rename from cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java
rename to cms-api/src/test/java/com/condation/cms/api/extensions/http/routes/RoutesManagerTest.java
index 3674e9ff9..1a76be070 100644
--- a/cms-api/src/test/java/com/condation/cms/api/extensions/routes/RoutesManagerTest.java
+++ b/cms-api/src/test/java/com/condation/cms/api/extensions/http/routes/RoutesManagerTest.java
@@ -2,7 +2,7 @@
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/UnitTests/JUnit5TestClass.java to edit this template
*/
-package com.condation.cms.api.extensions.routes;
+package com.condation.cms.api.extensions.http.routes;
/*-
* #%L
@@ -26,10 +26,6 @@
* #L%
*/
-import com.condation.cms.api.extensions.http.routes.Route;
-import com.condation.cms.api.extensions.http.routes.RoutesManager;
-import com.google.common.base.Stopwatch;
-import java.util.concurrent.TimeUnit;
import org.assertj.core.api.Assertions;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
From 3bec077562aee54b275ddfd0d5ca92485515616b Mon Sep 17 00:00:00 2001
From: Thorsten Marx
Date: Thu, 17 Apr 2025 14:35:09 +0200
Subject: [PATCH 5/8] rafactor extensionpoint
---
CHANGELOG.md | 3 ++-
.../api/extensions/http/routes/RoutesExtensionPoint.java | 4 ++--
.../cms/api/extensions/http/routes/RoutesManager.java | 3 +--
.../condation/cms/server/handler/http/RoutesHandler.java | 6 +++++-
4 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 456cad960..3c02338dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,7 +33,8 @@ public void action1 (ActionContext> context) {
#### HTTP-Controllers
-The new RoutesExtensionPoint gives developers access to the RoutesManager, which includes a register method for adding routes via annotated methods.
+The RoutesExtensionPoint is an extension point for defining HTTP routes.
+It allows developers to provide a list of objects whose methods can be registered as routes using annotations.
```java
@Route("/test2")
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesExtensionPoint.java b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesExtensionPoint.java
index b795087d0..496cd7da4 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesExtensionPoint.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesExtensionPoint.java
@@ -23,12 +23,12 @@
*/
import com.condation.cms.api.extensions.AbstractExtensionPoint;
+import java.util.List;
/**
*
* @author thorstenmarx
*/
public abstract class RoutesExtensionPoint extends AbstractExtensionPoint {
-
- abstract public void registerRoutes (RoutesManager routesManager);
+ abstract public List getRouteDefinitions ();
}
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java
index af6dbfbad..d535c7226 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java
@@ -37,8 +37,7 @@
@Slf4j
public class RoutesManager {
- //private final Map handlerMapping = new HashMap<>();
- private final PathMapping pathMapping = new PathMapping();
+ private final PathMapping pathMapping = new PathMapping();
public Optional findFirst (String path, String method) {
return pathMapping.getMatchingHandler(path, method);
diff --git a/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java b/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java
index 28d8008e1..04c52d49f 100644
--- a/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java
+++ b/cms-server/src/main/java/com/condation/cms/server/handler/http/RoutesHandler.java
@@ -34,6 +34,7 @@
import com.condation.cms.server.filter.CreateRequestContextFilter;
import com.condation.modules.api.ModuleManager;
import com.google.inject.Inject;
+import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -81,7 +82,10 @@ private boolean tryRoutesManager (Request request, Response response, Callback c
moduleManager.extensions(RoutesExtensionPoint.class)
.stream()
- .forEach(extension -> extension.registerRoutes(routesManager));
+ .map(RoutesExtensionPoint::getRouteDefinitions)
+ .filter(routeDefinitions -> routeDefinitions != null && !routeDefinitions.isEmpty())
+ .flatMap(List::stream)
+ .forEach(controller -> routesManager.register(controller));
var handler = routesManager.findFirst(route, request.getMethod());
if (handler.isPresent()) {
From 8ea4e6c068fd30217d64c89074a516a09f4a17bd Mon Sep 17 00:00:00 2001
From: Thorsten Marx
Date: Tue, 22 Apr 2025 15:50:40 +0200
Subject: [PATCH 6/8] add annotations for shortcodes and template components
---
.../api/{hooks => annotations}/Action.java | 2 +-
.../api/{hooks => annotations}/Filter.java | 2 +-
.../http/routes => annotations}/Route.java | 2 +-
.../cms/api/annotations/ShortCode.java | 38 ++++++++
.../api/annotations/TemplateComponent.java | 38 ++++++++
.../RegisterShortCodesExtensionPoint.java | 9 +-
...gisterTemplateComponentExtensionPoint.java | 9 +-
.../extensions/http/routes/RoutesManager.java | 1 +
.../condation/cms/api/hooks/HookSystem.java | 2 +
.../http/routes/RoutesManagerTest.java | 1 +
.../cms/api/hooks/HookSystemTest.java | 2 +
.../cms/content/shortcodes/ShortCodes.java | 87 ++++++++++++++++---
.../content/shortcodes/ShortCodesTest.java | 38 ++++++--
.../cms/request/RequestContextFactory.java | 28 +++---
.../cms/templates/DynamicConfiguration.java | 2 +-
.../templates/components/ComponentMap.java | 9 +-
.../components/TemplateComponents.java | 38 +++++++-
.../module/CMSModuleTemplateEngine.java | 14 ++-
.../TemplateEngineComponentTest.java | 22 +++--
.../cms/templates/TemplateFeatureTest.java | 25 +++---
20 files changed, 292 insertions(+), 77 deletions(-)
rename cms-api/src/main/java/com/condation/cms/api/{hooks => annotations}/Action.java (96%)
rename cms-api/src/main/java/com/condation/cms/api/{hooks => annotations}/Filter.java (96%)
rename cms-api/src/main/java/com/condation/cms/api/{extensions/http/routes => annotations}/Route.java (95%)
create mode 100644 cms-api/src/main/java/com/condation/cms/api/annotations/ShortCode.java
create mode 100644 cms-api/src/main/java/com/condation/cms/api/annotations/TemplateComponent.java
diff --git a/cms-api/src/main/java/com/condation/cms/api/hooks/Action.java b/cms-api/src/main/java/com/condation/cms/api/annotations/Action.java
similarity index 96%
rename from cms-api/src/main/java/com/condation/cms/api/hooks/Action.java
rename to cms-api/src/main/java/com/condation/cms/api/annotations/Action.java
index a39b4e0cd..5700ad687 100644
--- a/cms-api/src/main/java/com/condation/cms/api/hooks/Action.java
+++ b/cms-api/src/main/java/com/condation/cms/api/annotations/Action.java
@@ -1,4 +1,4 @@
-package com.condation.cms.api.hooks;
+package com.condation.cms.api.annotations;
/*-
* #%L
diff --git a/cms-api/src/main/java/com/condation/cms/api/hooks/Filter.java b/cms-api/src/main/java/com/condation/cms/api/annotations/Filter.java
similarity index 96%
rename from cms-api/src/main/java/com/condation/cms/api/hooks/Filter.java
rename to cms-api/src/main/java/com/condation/cms/api/annotations/Filter.java
index 84345a36f..f0afee6fe 100644
--- a/cms-api/src/main/java/com/condation/cms/api/hooks/Filter.java
+++ b/cms-api/src/main/java/com/condation/cms/api/annotations/Filter.java
@@ -1,4 +1,4 @@
-package com.condation.cms.api.hooks;
+package com.condation.cms.api.annotations;
/*-
* #%L
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/Route.java b/cms-api/src/main/java/com/condation/cms/api/annotations/Route.java
similarity index 95%
rename from cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/Route.java
rename to cms-api/src/main/java/com/condation/cms/api/annotations/Route.java
index abfac457c..8f82df0d3 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/Route.java
+++ b/cms-api/src/main/java/com/condation/cms/api/annotations/Route.java
@@ -1,4 +1,4 @@
-package com.condation.cms.api.extensions.http.routes;
+package com.condation.cms.api.annotations;
/*-
* #%L
diff --git a/cms-api/src/main/java/com/condation/cms/api/annotations/ShortCode.java b/cms-api/src/main/java/com/condation/cms/api/annotations/ShortCode.java
new file mode 100644
index 000000000..9cef1bf04
--- /dev/null
+++ b/cms-api/src/main/java/com/condation/cms/api/annotations/ShortCode.java
@@ -0,0 +1,38 @@
+package com.condation.cms.api.annotations;
+
+/*-
+ * #%L
+ * cms-api
+ * %%
+ * Copyright (C) 2023 - 2025 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * @author thorstenmarx
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface ShortCode {
+ String value ();
+}
diff --git a/cms-api/src/main/java/com/condation/cms/api/annotations/TemplateComponent.java b/cms-api/src/main/java/com/condation/cms/api/annotations/TemplateComponent.java
new file mode 100644
index 000000000..b7250e70a
--- /dev/null
+++ b/cms-api/src/main/java/com/condation/cms/api/annotations/TemplateComponent.java
@@ -0,0 +1,38 @@
+package com.condation.cms.api.annotations;
+
+/*-
+ * #%L
+ * cms-api
+ * %%
+ * Copyright (C) 2023 - 2025 CondationCMS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * @author thorstenmarx
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface TemplateComponent {
+ String value ();
+}
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterShortCodesExtensionPoint.java b/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterShortCodesExtensionPoint.java
index 1e02a5f53..1b3b907a6 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterShortCodesExtensionPoint.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterShortCodesExtensionPoint.java
@@ -24,6 +24,7 @@
import com.condation.cms.api.model.Parameter;
+import java.util.Collections;
import java.util.Map;
import java.util.function.Function;
@@ -33,5 +34,11 @@
*/
public abstract class RegisterShortCodesExtensionPoint extends AbstractExtensionPoint {
- public abstract Map> shortCodes ();
+ public Map> shortCodes () {
+ return Collections.emptyMap();
+ }
+
+ public Object shortCodeHandler () {
+ return new Object();
+ }
}
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java b/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java
index 21f099930..b4b0bdb1c 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java
@@ -24,6 +24,7 @@
import com.condation.cms.api.model.Parameter;
+import java.util.Collections;
import java.util.Map;
import java.util.function.Function;
@@ -33,5 +34,11 @@
*/
public abstract class RegisterTemplateComponentExtensionPoint extends AbstractExtensionPoint {
- public abstract Map> components ();
+ public Map> components () {
+ return Collections.emptyMap();
+ }
+
+ public Object handler () {
+ return new Object();
+ }
}
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java
index d535c7226..d3ef35d61 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/http/routes/RoutesManager.java
@@ -22,6 +22,7 @@
* #L%
*/
+import com.condation.cms.api.annotations.Route;
import com.condation.cms.api.extensions.http.HttpHandler;
import com.condation.cms.api.extensions.http.PathMapping;
import org.eclipse.jetty.http.pathmap.PathSpec;
diff --git a/cms-api/src/main/java/com/condation/cms/api/hooks/HookSystem.java b/cms-api/src/main/java/com/condation/cms/api/hooks/HookSystem.java
index e3e699272..b173e4d6e 100644
--- a/cms-api/src/main/java/com/condation/cms/api/hooks/HookSystem.java
+++ b/cms-api/src/main/java/com/condation/cms/api/hooks/HookSystem.java
@@ -21,6 +21,8 @@
* .
* #L%
*/
+import com.condation.cms.api.annotations.Filter;
+import com.condation.cms.api.annotations.Action;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.lang.reflect.Method;
diff --git a/cms-api/src/test/java/com/condation/cms/api/extensions/http/routes/RoutesManagerTest.java b/cms-api/src/test/java/com/condation/cms/api/extensions/http/routes/RoutesManagerTest.java
index 1a76be070..9139f8b1f 100644
--- a/cms-api/src/test/java/com/condation/cms/api/extensions/http/routes/RoutesManagerTest.java
+++ b/cms-api/src/test/java/com/condation/cms/api/extensions/http/routes/RoutesManagerTest.java
@@ -26,6 +26,7 @@
* #L%
*/
+import com.condation.cms.api.annotations.Route;
import org.assertj.core.api.Assertions;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
diff --git a/cms-api/src/test/java/com/condation/cms/api/hooks/HookSystemTest.java b/cms-api/src/test/java/com/condation/cms/api/hooks/HookSystemTest.java
index 670655d8e..1f2155166 100644
--- a/cms-api/src/test/java/com/condation/cms/api/hooks/HookSystemTest.java
+++ b/cms-api/src/test/java/com/condation/cms/api/hooks/HookSystemTest.java
@@ -23,6 +23,8 @@
*/
+import com.condation.cms.api.annotations.Filter;
+import com.condation.cms.api.annotations.Action;
import com.condation.cms.api.hooks.HookSystem;
import java.util.ArrayList;
import java.util.List;
diff --git a/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java b/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java
index 047a5e36a..4c03b6e97 100644
--- a/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java
+++ b/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java
@@ -21,11 +21,12 @@
* .
* #L%
*/
-
-
+import com.condation.cms.api.annotations.ShortCode;
import com.condation.cms.api.model.Parameter;
import com.condation.cms.api.request.RequestContext;
+import java.lang.reflect.Method;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
@@ -43,29 +44,29 @@ public class ShortCodes {
private final TagMap tagMap;
private final TagParser parser;
- public ShortCodes (Map> codes, TagParser tagParser) {
+ public ShortCodes(Map> codes, TagParser tagParser) {
this.parser = tagParser;
this.tagMap = new TagMap();
this.tagMap.putAll(codes);
}
-
- public Set getShortCodeNames () {
+
+ public Set getShortCodeNames() {
return tagMap.names();
}
-
- public String replace (final String content) {
+
+ public String replace(final String content) {
return replace(content, Collections.emptyMap(), null);
}
-
- public String replace (final String content, Map contextModel) {
+
+ public String replace(final String content, Map contextModel) {
return replace(content, contextModel, null);
}
-
- public String replace (final String content, Map contextModel, RequestContext requestContext) {
+
+ public String replace(final String content, Map contextModel, RequestContext requestContext) {
return parser.parse(content, tagMap, contextModel, requestContext);
}
-
- public String execute (String name, Map parameters, RequestContext requestContext) {
+
+ public String execute(String name, Map parameters, RequestContext requestContext) {
if (!tagMap.has(name)) {
return "";
}
@@ -78,8 +79,66 @@ public String execute (String name, Map parameters, RequestConte
}
return tagMap.get(name).apply(params);
} catch (Exception e) {
- log.error("",e);
+ log.error("", e);
}
return "";
}
+
+ public static ShortCodes.Builder builder(TagParser tagParser) {
+ return new Builder(tagParser);
+ }
+
+ public static class Builder {
+
+ private final TagParser tagParser;
+
+ private final Map> codes = new HashMap<>();
+
+ private Builder(TagParser tagParser) {
+ this.tagParser = tagParser;
+ }
+
+ public Builder register(String name, Function shortCodeFN) {
+ codes.put(name, shortCodeFN);
+ return this;
+ }
+
+ public Builder register (Map> codes) {
+ this.codes.putAll(codes);
+ return this;
+ }
+
+ public Builder register(Object handler) {
+ if (handler == null) {
+ return this;
+ }
+
+ Class> clazz = handler.getClass();
+ for (Method method : clazz.getDeclaredMethods()) {
+ if (method.isAnnotationPresent(ShortCode.class)) {
+ if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == Parameter.class) {
+ method.setAccessible(true); // falls private
+ ShortCode annotation = method.getAnnotation(ShortCode.class);
+ String key = annotation.value();
+
+ codes.put(key, param -> {
+ try {
+ return (String) method.invoke(handler, param);
+ } catch (Exception e) {
+ throw new RuntimeException("Error calling shortcode: " + key, e);
+ }
+ });
+ } else {
+ log.error("ignore methode" + method.getName() + " – wrong signature.");
+ }
+ }
+ }
+
+ return this;
+ }
+
+ public ShortCodes build() {
+ return new ShortCodes(codes, tagParser);
+ }
+ }
}
diff --git a/cms-content/src/test/java/com/condation/cms/content/shortcodes/ShortCodesTest.java b/cms-content/src/test/java/com/condation/cms/content/shortcodes/ShortCodesTest.java
index 8c0924ba3..618577a5a 100644
--- a/cms-content/src/test/java/com/condation/cms/content/shortcodes/ShortCodesTest.java
+++ b/cms-content/src/test/java/com/condation/cms/content/shortcodes/ShortCodesTest.java
@@ -23,6 +23,7 @@
*/
+import com.condation.cms.api.annotations.ShortCode;
import com.condation.cms.api.model.Parameter;
import com.condation.cms.api.request.RequestContext;
import com.condation.cms.content.ContentBaseTest;
@@ -43,44 +44,47 @@ public class ShortCodesTest extends ContentBaseTest {
@BeforeEach
public void init () {
- Map> tags = new HashMap<>();
- tags.put(
+ var builder = ShortCodes.builder(getTagParser());
+
+ builder.register(
"youtube",
(params) -> " ".formatted(params.getOrDefault("id", "")));
- tags.put(
+ builder.register(
"hello_from",
(params) -> "
%s from %s
".formatted(params.getOrDefault("name", ""), params.getOrDefault("from", "")));
- tags.put(
+ builder.register(
"mark",
params -> "%s ".formatted(params.get("_content"))
);
- tags.put(
+ builder.register(
"mark2",
params -> "%s ".formatted(params.get("class"), params.get("_content"))
);
- tags.put(
+ builder.register(
"exp",
params -> "%s ".formatted(params.get("expression"))
);
- tags.put(
+ builder.register(
"set_var",
params -> {
params.getRequestContext().getVariables().put("myVar", "Hello world!");
return "";
}
);
- tags.put(
+ builder.register(
"get_var",
params -> {
return (String)params.getRequestContext().getVariables().getOrDefault("myVar", "DEFAULT");
}
);
- shortCodes = new ShortCodes(tags, getTagParser());
+ builder.register(new ShortCodesHandler());
+
+ shortCodes = builder.build();
}
@@ -229,4 +233,20 @@ void test_variables() {
Assertions.assertThat(result).isEqualTo("Hello world!");
}
+
+ @Test
+ void test_handler () {
+ RequestContext requestContext = new RequestContext();
+
+ var result = shortCodes.replace("[[printHello name='CondationCMS' /]]", Map.of(), requestContext);
+
+ Assertions.assertThat(result).isEqualTo("hello CondationCMS");
+ }
+
+ public static class ShortCodesHandler {
+ @ShortCode("printHello")
+ public String printHello (Parameter parameter) {
+ return "hello " + parameter.getOrDefault("name", "");
+ }
+ }
}
diff --git a/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java b/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java
index c8fdc93f4..bc1455337 100644
--- a/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java
+++ b/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java
@@ -171,16 +171,22 @@ private HookSystem setupAndGetHookSystem() {
}
private ShortCodes initShortCodes(RequestContext requestContext) {
- Map> codes = new HashMap<>();
+ var parser = injector.getInstance(TagParser.class);
+ var builder = ShortCodes.builder(parser);
+
injector.getInstance(ModuleManager.class).extensions(RegisterShortCodesExtensionPoint.class)
- .forEach(extension -> codes.putAll(extension.shortCodes()));
+ .forEach(extension -> {
+ builder.register(extension.shortCodes());
+ builder.register(extension.shortCodeHandler());
+ });
+ var codes = new HashMap>();
var wrapper = requestContext.get(ContentHooks.class).getShortCodes(codes);
- var parser = injector.getInstance(TagParser.class);
+ builder.register(wrapper.getShortCodes());
- return new ShortCodes(wrapper.getShortCodes(), parser);
+ return builder.build();
}
public RequestContext create() throws IOException {
@@ -219,7 +225,7 @@ public RequestContext create() throws IOException {
RenderContext renderContext = new RenderContext(
markdownRenderer,
- createShortCodes(requestContext),
+ initShortCodes(requestContext),
theme);
requestContext.add(RenderContext.class, renderContext);
requestContext.add(MarkdownRendererFeature.class, new MarkdownRendererFeature(markdownRenderer));
@@ -253,16 +259,4 @@ public RequestContext create(
return requestContext;
}
-
- private ShortCodes createShortCodes(RequestContext requestContext) {
- Map> codes = new HashMap<>();
-
- injector.getInstance(ModuleManager.class).extensions(RegisterShortCodesExtensionPoint.class)
- .forEach(extension -> codes.putAll(extension.shortCodes()));
-
- var wrapper = requestContext.get(ContentHooks.class).getShortCodes(codes);
- var parser = injector.getInstance(TagParser.class);
- return new ShortCodes(wrapper.getShortCodes(), parser);
- }
-
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java b/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java
index bca613a7d..945c62cda 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/DynamicConfiguration.java
@@ -37,7 +37,7 @@
public record DynamicConfiguration(TemplateComponents templateComponents, Map components, RequestContext requestContext) {
public static final DynamicConfiguration EMPTY = new DynamicConfiguration(
- new TemplateComponents(Collections.emptyMap()),
+ new TemplateComponents(),
Collections.emptyMap(),
null
);
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/components/ComponentMap.java b/cms-templates/src/main/java/com/condation/cms/templates/components/ComponentMap.java
index 185fa791d..75223403f 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/components/ComponentMap.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/components/ComponentMap.java
@@ -21,26 +21,27 @@
* .
* #L%
*/
-
import com.condation.cms.api.model.Parameter;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
+import lombok.extern.slf4j.Slf4j;
/**
*
* @author t.marx
*/
+@Slf4j
public class ComponentMap {
private final Map> tags = new HashMap<>();
- public Set names () {
+ public Set names() {
return Collections.unmodifiableSet(tags.keySet());
}
-
+
public void put(String codeName, Function function) {
tags.put(codeName, function);
}
@@ -48,7 +49,7 @@ public void put(String codeName, Function function) {
public void putAll(Map> tags) {
this.tags.putAll(tags);
}
-
+
public boolean has(String codeName) {
return tags.containsKey(codeName);
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java b/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java
index 5055f9764..b592b44f2 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java
@@ -23,8 +23,10 @@
*/
+import com.condation.cms.api.annotations.TemplateComponent;
import com.condation.cms.api.model.Parameter;
import com.condation.cms.api.request.RequestContext;
+import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
@@ -39,11 +41,45 @@ public class TemplateComponents {
private final ComponentMap componentMap;
- public TemplateComponents (Map> components) {
+ public TemplateComponents () {
this.componentMap = new ComponentMap();
+ }
+
+ public void register (String name, Function templateComponentFN) {
+ componentMap.put(name, templateComponentFN);
+ }
+
+ public void register (Map> components) {
this.componentMap.putAll(components);
}
+ public void register(Object handler) {
+ if (handler == null) {
+ return;
+ }
+
+ Class> clazz = handler.getClass();
+ for (Method method : clazz.getDeclaredMethods()) {
+ if (method.isAnnotationPresent(TemplateComponent.class)) {
+ if (method.getParameterCount() == 1 && method.getParameterTypes()[0] == Parameter.class) {
+ method.setAccessible(true);
+ var annotation = method.getAnnotation(TemplateComponent.class);
+ String key = annotation.value();
+
+ componentMap.put(key, param -> {
+ try {
+ return (String) method.invoke(handler, param);
+ } catch (Exception e) {
+ throw new RuntimeException("Error calling component: " + key, e);
+ }
+ });
+ } else {
+ log.error("ignore methode" + method.getName() + " – wrong signature.");
+ }
+ }
+ }
+ }
+
public Set getComponentNames () {
return componentMap.names();
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java b/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java
index 3951e64c1..087d9c587 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java
@@ -129,16 +129,22 @@ private DynamicConfiguration createDynamicConfiguration(Model model) {
}
private TemplateComponents createTemplateComponents(RequestContext requestContext) {
- Map> components = new HashMap<>();
-
var injector = requestContext.get(InjectorFeature.class).injector();
+ var templateComponents = new TemplateComponents();
injector.getInstance(ModuleManager.class)
.extensions(RegisterTemplateComponentExtensionPoint.class)
- .forEach(extension -> components.putAll(extension.components()));
+ .forEach(extension -> {
+ templateComponents.register(extension.components());
+ templateComponents.register(extension.handler());
+ });
+ Map> components = new HashMap<>();
var wrapper = requestContext.get(TemplateHooks.class).getComponents(components);
- return new TemplateComponents(wrapper.getComponents());
+
+ templateComponents.register(wrapper.getComponents());
+
+ return templateComponents;
}
@Override
diff --git a/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java b/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java
index e72981be5..7b205476f 100644
--- a/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java
+++ b/cms-templates/src/test/java/com/condation/cms/templates/TemplateEngineComponentTest.java
@@ -21,8 +21,8 @@
* .
* #L%
*/
-import com.condation.cms.content.shortcodes.ShortCodes;
-import com.condation.cms.content.shortcodes.TagParser;
+import com.condation.cms.api.annotations.TemplateComponent;
+import com.condation.cms.api.model.Parameter;
import com.condation.cms.templates.components.TemplateComponents;
import com.condation.cms.templates.exceptions.ParserException;
import com.condation.cms.templates.exceptions.RenderException;
@@ -44,20 +44,24 @@ public class TemplateEngineComponentTest extends AbstractTemplateEngineTest {
@BeforeAll
public void setupShortCodes() {
- components = new TemplateComponents(
- Map.of(
+ components = new TemplateComponents();
+ components.register(Map.of(
"tag1", (params) -> {
return "Hello";
},
"tag2", (param) -> {
return "Hello " + param.get("name") + "!";
- },
- "tag3", (param) -> {
- return "%s
".formatted(param.get("_content"));
- })
- );
+ }));
+ components.register(new MyComponents());
dynamicConfiguration = new DynamicConfiguration(components, null);
}
+
+ public static class MyComponents {
+ @TemplateComponent("tag3")
+ public String tag3 (Parameter parameter) {
+ return "%s
".formatted(parameter.get("_content"));
+ }
+ }
@Override
public TemplateLoader getLoader() {
diff --git a/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java b/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java
index 998c233a5..4e122296a 100644
--- a/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java
+++ b/cms-templates/src/test/java/com/condation/cms/templates/TemplateFeatureTest.java
@@ -21,7 +21,6 @@
* .
* #L%
*/
-import com.condation.cms.content.shortcodes.TagParser;
import com.condation.cms.templates.components.TemplateComponents;
import com.condation.cms.templates.loaders.StringTemplateLoader;
import com.google.gson.Gson;
@@ -43,7 +42,7 @@
public class TemplateFeatureTest extends AbstractTemplateEngineTest {
private StringTemplateLoader templateLoader = new StringTemplateLoader();
-
+
private Gson gson = new GsonBuilder()
.setStrictness(Strictness.LENIENT)
.create();
@@ -66,7 +65,7 @@ void test_features(String templateFile) throws Exception {
var expectedContent = readContent(templateFile + "_expected.html");
var data = getData(templateFile);
-
+
templateLoader.add(templateFile, templateContent);
var template = SUT.getTemplate(templateFile);
@@ -76,25 +75,25 @@ void test_features(String templateFile) throws Exception {
Assertions.assertThat(rendered).isEqualToIgnoringWhitespace(expectedContent);
}
- private DynamicConfiguration createDynamicConfig () {
- TemplateComponents components = new TemplateComponents(
- Map.of(
- "hello", (params) -> "hello " + params.get("name")
- ));
+ private DynamicConfiguration createDynamicConfig() {
+ TemplateComponents components = new TemplateComponents();
+ components.register(Map.of(
+ "hello", (params) -> "hello " + params.get("name")
+ ));
return new DynamicConfiguration(components, null);
}
-
- private Map getData (String filename) throws IOException {
+
+ private Map getData(String filename) throws IOException {
String dataFile = filename + "_data.json";
if (!exists(dataFile)) {
return Collections.emptyMap();
}
-
+
var dataContent = readContent(dataFile);
-
+
return gson.fromJson(dataContent, HashMap.class);
}
-
+
private boolean exists(String filename) {
var resourcePath = "testdata/" + filename;
var url = TemplateFeatureTest.class.getResource(resourcePath);
From f0de54c4e67800aab9818720b3b8111f8cdee42c Mon Sep 17 00:00:00 2001
From: Thorsten Marx
Date: Wed, 23 Apr 2025 09:50:48 +0200
Subject: [PATCH 7/8] 1. minor refactorings 2. changelog
---
CHANGELOG.md | 31 +++++++++++++++---
.../RegisterShortCodesExtensionPoint.java | 5 +--
...gisterTemplateComponentExtensionPoint.java | 5 +--
.../cms/content/shortcodes/ShortCodes.java | 11 +++++++
.../cms/request/RequestContextFactory.java | 3 +-
.../components/TemplateComponents.java | 32 +++++++++++--------
.../module/CMSModuleTemplateEngine.java | 2 +-
7 files changed, 66 insertions(+), 23 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c02338dd..28fb5b13b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,7 +19,7 @@ In this release we introduced some features to make life of developers easier.
It is now possible to pass an object with annotated hook definitions to the HookSystem.register method.
-```java
+´´´java
@Filter("test/annotation/filter1")
public List filter (FilterContext> context) {
context.value().remove("2");
@@ -29,19 +29,42 @@ public List filter (FilterContext> context) {
public void action1 (ActionContext> context) {
// do something
}
-```
+´´´
#### HTTP-Controllers
The RoutesExtensionPoint is an extension point for defining HTTP routes.
It allows developers to provide a list of objects whose methods can be registered as routes using annotations.
-```java
+´´´java
@Route("/test2")
public boolean handle2 (Request request, Response response, Callback callback) {
return true;
}
-```
+´´´
+
+#### ShortCodes
+
+The RegisterShortCodesExtensionPoint interface now includes a new method, shortCodeDefinitions, which returns a list of objects that contain shortcode definitions provided through annotations.
+
+´´´java
+@ShortCode("printHello")
+public String printHello (Parameter parameter) {
+ return "hello " + parameter.getOrDefault("name", "");
+}
+´´´
+
+#### TemplateComponents
+
+A new method, componentDefinitions, has been added to the RegisterTemplateComponentExtensionPoint interface. It returns a list of objects that define template components using annotations.
+
+´´´java
+@TemplateComponent("tag3")
+public String tag3 (Parameter parameter) {
+ return "%s
".formatted(parameter.get("_content"));
+}
+
+´´´
## 7.8.0
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterShortCodesExtensionPoint.java b/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterShortCodesExtensionPoint.java
index 1b3b907a6..a5adadf36 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterShortCodesExtensionPoint.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterShortCodesExtensionPoint.java
@@ -25,6 +25,7 @@
import com.condation.cms.api.model.Parameter;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -38,7 +39,7 @@ public Map> shortCodes () {
return Collections.emptyMap();
}
- public Object shortCodeHandler () {
- return new Object();
+ public List shortCodeDefinitions () {
+ return Collections.emptyList();
}
}
diff --git a/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java b/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java
index b4b0bdb1c..d980b6175 100644
--- a/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java
+++ b/cms-api/src/main/java/com/condation/cms/api/extensions/RegisterTemplateComponentExtensionPoint.java
@@ -25,6 +25,7 @@
import com.condation.cms.api.model.Parameter;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -38,7 +39,7 @@ public Map> components () {
return Collections.emptyMap();
}
- public Object handler () {
- return new Object();
+ public List componentDefinitions () {
+ return Collections.emptyList();
}
}
diff --git a/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java b/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java
index 4c03b6e97..ba0d1c6a4 100644
--- a/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java
+++ b/cms-content/src/main/java/com/condation/cms/content/shortcodes/ShortCodes.java
@@ -27,6 +27,7 @@
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
@@ -108,6 +109,16 @@ public Builder register (Map> codes) {
return this;
}
+ public Builder register (List handlers) {
+ if (handlers == null || handlers.isEmpty()) {
+ return this;
+ }
+
+ handlers.forEach(this::register);
+
+ return this;
+ }
+
public Builder register(Object handler) {
if (handler == null) {
return this;
diff --git a/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java b/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java
index bc1455337..151485564 100644
--- a/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java
+++ b/cms-server/src/main/java/com/condation/cms/request/RequestContextFactory.java
@@ -178,7 +178,8 @@ private ShortCodes initShortCodes(RequestContext requestContext) {
injector.getInstance(ModuleManager.class).extensions(RegisterShortCodesExtensionPoint.class)
.forEach(extension -> {
builder.register(extension.shortCodes());
- builder.register(extension.shortCodeHandler());
+
+ builder.register(extension.shortCodeDefinitions());
});
var codes = new HashMap>();
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java b/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java
index b592b44f2..93befd56e 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/components/TemplateComponents.java
@@ -21,12 +21,11 @@
* .
* #L%
*/
-
-
import com.condation.cms.api.annotations.TemplateComponent;
import com.condation.cms.api.model.Parameter;
import com.condation.cms.api.request.RequestContext;
import java.lang.reflect.Method;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
@@ -41,18 +40,25 @@ public class TemplateComponents {
private final ComponentMap componentMap;
- public TemplateComponents () {
+ public TemplateComponents() {
this.componentMap = new ComponentMap();
}
-
- public void register (String name, Function templateComponentFN) {
+
+ public void register(String name, Function templateComponentFN) {
componentMap.put(name, templateComponentFN);
}
-
- public void register (Map> components) {
+
+ public void register(Map> components) {
this.componentMap.putAll(components);
}
-
+
+ public void register(List handlers) {
+ if (handlers == null || handlers.isEmpty()) {
+ return;
+ }
+ handlers.forEach(this::register);
+ }
+
public void register(Object handler) {
if (handler == null) {
return;
@@ -79,12 +85,12 @@ public void register(Object handler) {
}
}
}
-
- public Set getComponentNames () {
+
+ public Set getComponentNames() {
return componentMap.names();
}
-
- public String execute (String name, Map parameters, RequestContext requestContext) {
+
+ public String execute(String name, Map parameters, RequestContext requestContext) {
if (!componentMap.has(name)) {
return "";
}
@@ -97,7 +103,7 @@ public String execute (String name, Map parameters, RequestConte
}
return componentMap.get(name).apply(params);
} catch (Exception e) {
- log.error("",e);
+ log.error("", e);
}
return "";
}
diff --git a/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java b/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java
index 087d9c587..9f9ac3ee5 100644
--- a/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java
+++ b/cms-templates/src/main/java/com/condation/cms/templates/module/CMSModuleTemplateEngine.java
@@ -136,7 +136,7 @@ private TemplateComponents createTemplateComponents(RequestContext requestContex
.extensions(RegisterTemplateComponentExtensionPoint.class)
.forEach(extension -> {
templateComponents.register(extension.components());
- templateComponents.register(extension.handler());
+ templateComponents.register(extension.componentDefinitions());
});
Map> components = new HashMap<>();
From 07fbddf9e2980b2751a31721b2e66f4f4cd51e7b Mon Sep 17 00:00:00 2001
From: Thorsten Marx
Date: Wed, 23 Apr 2025 09:52:48 +0200
Subject: [PATCH 8/8] fix changelog code formatting
---
CHANGELOG.md | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 28fb5b13b..bc3f5044c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,7 +19,7 @@ In this release we introduced some features to make life of developers easier.
It is now possible to pass an object with annotated hook definitions to the HookSystem.register method.
-´´´java
+```java
@Filter("test/annotation/filter1")
public List filter (FilterContext> context) {
context.value().remove("2");
@@ -29,42 +29,42 @@ public List filter (FilterContext> context) {
public void action1 (ActionContext> context) {
// do something
}
-´´´
+```
#### HTTP-Controllers
The RoutesExtensionPoint is an extension point for defining HTTP routes.
It allows developers to provide a list of objects whose methods can be registered as routes using annotations.
-´´´java
+```java
@Route("/test2")
public boolean handle2 (Request request, Response response, Callback callback) {
return true;
}
-´´´
+```
#### ShortCodes
The RegisterShortCodesExtensionPoint interface now includes a new method, shortCodeDefinitions, which returns a list of objects that contain shortcode definitions provided through annotations.
-´´´java
+```java
@ShortCode("printHello")
public String printHello (Parameter parameter) {
return "hello " + parameter.getOrDefault("name", "");
}
-´´´
+```
#### TemplateComponents
A new method, componentDefinitions, has been added to the RegisterTemplateComponentExtensionPoint interface. It returns a list of objects that define template components using annotations.
-´´´java
+```java
@TemplateComponent("tag3")
public String tag3 (Parameter parameter) {
return "%s
".formatted(parameter.get("_content"));
}
-´´´
+```
## 7.8.0