This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5791-struts-boot
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 02bcb32741c0e7159ff8cb4dba3fa27439e299ed
Author: Lukasz Lenart <[email protected]>
AuthorDate: Fri Oct 23 12:59:54 2026 +0200

    WW-5791 feat(boot): add boot-hello example app with runnable jar
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 apps/boot-hello/README.md                          | 56 ++++++++++++++
 apps/boot-hello/pom.xml                            | 90 ++++++++++++++++++++++
 .../org/apache/struts2/boot/hello/HelloAction.java | 30 ++++++++
 .../org/apache/struts2/boot/hello/HelloApp.java    | 35 +++++++++
 .../src/main/resources/templates/hello.ftl         | 21 +++++
 .../apache/struts2/boot/hello/HelloAppTest.java    | 45 +++++++++++
 apps/pom.xml                                       |  1 +
 boot/src/test/resources/templates/admin/users.ftl  | 20 +++++
 boot/src/test/resources/templates/hello.ftl        | 20 +++++
 9 files changed, 318 insertions(+)

diff --git a/apps/boot-hello/README.md b/apps/boot-hello/README.md
new file mode 100644
index 000000000..2e36a61cc
--- /dev/null
+++ b/apps/boot-hello/README.md
@@ -0,0 +1,56 @@
+# Struts Boot Hello
+
+The smallest Struts Boot application: one action, one FreeMarker template, no 
`web.xml`, no `struts.xml`.
+
+## Three steps
+
+1. Depend on `org.apache.struts:struts2-boot-starter`.
+2. Implement `StrutsBootApplication` and register actions:
+
+   ```java
+   public class HelloApp implements StrutsBootApplication {
+
+       public static void main(String[] args) {
+           StrutsBoot.run(HelloApp.class, args);
+       }
+
+       @Override
+       public void actions(ActionRegistry actions) {
+           actions.action("hello", HelloAction.class).success("hello.ftl");
+       }
+   }
+   ```
+
+3. Put the view in `src/main/resources/templates/hello.ftl` and run `main()`.
+
+Then open http://localhost:8080/hello.action.
+
+## Running the jar
+
+```
+mvn package -pl apps/boot-hello -am -DskipAssembly -DskipTests
+java -jar apps/boot-hello/target/struts2-boot-hello-<version>.jar 
--struts.boot.port=9090
+```
+
+## Settings
+
+Settings are read from `struts.properties` on the classpath. A `--key=value` 
argument overrides the file.
+
+| Key                        | Default | Meaning                               
     |
+|----------------------------|---------|--------------------------------------------|
+| `struts.boot.port`         | `8080`  | HTTP port; `0` picks a free port      
     |
+| `struts.boot.context-path` | `""`    | Context path the application is 
served at  |
+
+## Defaults worth knowing
+
+- Tomcat listens on all interfaces, not only on localhost.
+- `struts.devMode` stays off.
+- Each start uses a fresh temporary base directory (`struts-boot-<uuid>`) that 
is deleted on shutdown.
+- Views are FreeMarker only; a result path such as `hello.ftl` resolves to 
`/templates/hello.ftl` on the classpath.
+
+## Shading and plugins
+
+The jar is built with `maven-shade-plugin`. Every Struts plugin ships its own 
`META-INF/struts-plugin.xml`, and shading
+keeps only one file with that name, so with two or more plugins on the 
classpath all but one would be silently lost.
+This example uses no plugins. If your application needs them, package it 
differently (for example with
+Spring Boot's repackager or a `lib/` directory next to a thin jar) instead of 
shading.
diff --git a/apps/boot-hello/pom.xml b/apps/boot-hello/pom.xml
new file mode 100644
index 000000000..d6b043b6d
--- /dev/null
+++ b/apps/boot-hello/pom.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.struts</groupId>
+        <artifactId>struts2-apps</artifactId>
+        <version>7.5.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>struts2-boot-hello</artifactId>
+    <packaging>jar</packaging>
+    <version>7.5.0-SNAPSHOT</version>
+    <name>Struts 2 Boot Hello</name>
+    <description>Struts Boot example application packaged as a runnable 
jar</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.struts</groupId>
+            <artifactId>struts2-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}-${project.version}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>3.6.0</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            
<createDependencyReducedPom>false</createDependencyReducedPom>
+                            <transformers>
+                                <transformer 
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                    
<mainClass>org.apache.struts2.boot.hello.HelloApp</mainClass>
+                                </transformer>
+                                <transformer 
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+                            </transformers>
+                            <filters>
+                                <filter>
+                                    <artifact>*:*</artifact>
+                                    <excludes>
+                                        <exclude>META-INF/*.SF</exclude>
+                                        <exclude>META-INF/*.DSA</exclude>
+                                        <exclude>META-INF/*.RSA</exclude>
+                                    </excludes>
+                                </filter>
+                            </filters>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git 
a/apps/boot-hello/src/main/java/org/apache/struts2/boot/hello/HelloAction.java 
b/apps/boot-hello/src/main/java/org/apache/struts2/boot/hello/HelloAction.java
new file mode 100644
index 000000000..6dea4336d
--- /dev/null
+++ 
b/apps/boot-hello/src/main/java/org/apache/struts2/boot/hello/HelloAction.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.struts2.boot.hello;
+
+public class HelloAction {
+
+    public String execute() {
+        return "success";
+    }
+
+    public String getMessage() {
+        return "Hello from Struts Boot";
+    }
+}
diff --git 
a/apps/boot-hello/src/main/java/org/apache/struts2/boot/hello/HelloApp.java 
b/apps/boot-hello/src/main/java/org/apache/struts2/boot/hello/HelloApp.java
new file mode 100644
index 000000000..7c47054ae
--- /dev/null
+++ b/apps/boot-hello/src/main/java/org/apache/struts2/boot/hello/HelloApp.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.struts2.boot.hello;
+
+import org.apache.struts2.boot.ActionRegistry;
+import org.apache.struts2.boot.StrutsBoot;
+import org.apache.struts2.boot.StrutsBootApplication;
+
+public class HelloApp implements StrutsBootApplication {
+
+    public static void main(String[] args) {
+        StrutsBoot.run(HelloApp.class, args);
+    }
+
+    @Override
+    public void actions(ActionRegistry actions) {
+        actions.action("hello", HelloAction.class).success("hello.ftl");
+    }
+}
diff --git a/apps/boot-hello/src/main/resources/templates/hello.ftl 
b/apps/boot-hello/src/main/resources/templates/hello.ftl
new file mode 100644
index 000000000..be6490fc2
--- /dev/null
+++ b/apps/boot-hello/src/main/resources/templates/hello.ftl
@@ -0,0 +1,21 @@
+<#--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+-->
+<h1><@s.property value="message"/></h1>
diff --git 
a/apps/boot-hello/src/test/java/org/apache/struts2/boot/hello/HelloAppTest.java 
b/apps/boot-hello/src/test/java/org/apache/struts2/boot/hello/HelloAppTest.java
new file mode 100644
index 000000000..ba9881a2b
--- /dev/null
+++ 
b/apps/boot-hello/src/test/java/org/apache/struts2/boot/hello/HelloAppTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.struts2.boot.hello;
+
+import org.apache.struts2.boot.StrutsBoot;
+import org.apache.struts2.boot.StrutsBootServer;
+import org.junit.Test;
+
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class HelloAppTest {
+
+    @Test
+    public void testHelloPageRenders() throws Exception {
+        try (StrutsBootServer server = StrutsBoot.start(HelloApp.class, 
"--struts.boot.port=0")) {
+            HttpRequest request = 
HttpRequest.newBuilder(URI.create(server.baseUrl() + 
"/hello.action")).GET().build();
+
+            HttpResponse<String> response = 
HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
+
+            assertThat(response.statusCode()).isEqualTo(200);
+            assertThat(response.body()).contains("Hello from Struts Boot");
+        }
+    }
+}
diff --git a/apps/pom.xml b/apps/pom.xml
index 9ff432498..866c4b5ef 100644
--- a/apps/pom.xml
+++ b/apps/pom.xml
@@ -33,6 +33,7 @@
     <modules>
         <module>showcase</module>
         <module>rest-showcase</module>
+        <module>boot-hello</module>
     </modules>
 
     <properties>
diff --git a/boot/src/test/resources/templates/admin/users.ftl 
b/boot/src/test/resources/templates/admin/users.ftl
index e9544fbee..1d2feeff8 100644
--- a/boot/src/test/resources/templates/admin/users.ftl
+++ b/boot/src/test/resources/templates/admin/users.ftl
@@ -1 +1,21 @@
+<#--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+-->
 <h1>users</h1>
diff --git a/boot/src/test/resources/templates/hello.ftl 
b/boot/src/test/resources/templates/hello.ftl
index 102b1e4a4..be6490fc2 100644
--- a/boot/src/test/resources/templates/hello.ftl
+++ b/boot/src/test/resources/templates/hello.ftl
@@ -1 +1,21 @@
+<#--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+-->
 <h1><@s.property value="message"/></h1>

Reply via email to