diff --git a/docs/dev.md b/docs/dev.md
index a15515e63..045eea7c8 100644
--- a/docs/dev.md
+++ b/docs/dev.md
@@ -6,7 +6,8 @@ Start a Liberty instance in dev mode. This goal also invokes the `create`, `inst
Starting in version 3.6.1, dev mode invokes the `generate-features` goal when the `generateFeatures` configuration parameter is set to `true`. **This goal modifies the source configuration directory of your application.** See [generate-features](generate-features.md) for details. The default value for the `generateFeatures` parameter is `false`. When auto-generation of features is turned on, dev mode has a runtime dependency on IBM WebSphere Application Server Migration Toolkit for Application Binaries, which is separately licensed under IBM License Agreement for Non-Warranted Programs. For more information, see the [license](https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/wasdev/license/wamt).
-Additionally, starting in 3.5.2-SNAPSHOT, [resource variable filtering](https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html) and [WAR overlays](https://maven.apache.org/plugins/maven-war-plugin/overlays.html) are supported for loose WAR applications. This is done by automatically detecting appropriate Maven WAR plugin configuration and calling the WAR plugin's `exploded` goal and the Maven Resource plugin's `resource` goal when appropriate. Behavior for updating/deleting resources is delegated via the Maven WAR plugin configuration, including the `outdatedCheckPath` parameter enhanced in plugin version 3.3.2.
+Additionally, starting in version 3.5.2, [resource variable filtering](https://maven.apache.org/plugins/maven-resources-plugin/examples/filter.html) and [WAR overlays](https://maven.apache.org/plugins/maven-war-plugin/overlays.html) are supported for loose WAR applications. This is done by automatically detecting appropriate Maven WAR plugin configuration and calling the WAR plugin's [`exploded`](https://maven.apache.org/plugins/maven-war-plugin/exploded-mojo.html) goal and the Maven Resource plugin's [`resource`](https://maven.apache.org/plugins/maven-resources-plugin/resources-mojo.html) goal when appropriate. Behavior for updating/deleting resources can be configured via the [`outdatedCheckPath`](https://maven.apache.org/plugins/maven-war-plugin/exploded-mojo.html#outdatedCheckPath) parameter introduced and then enhanced in maven-war-plugin versions 3.3.1, 3.3.2.
+
To start the server in a container, see the [devc](#devc-container-mode) section below.
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/META-INF/MANIFEST.MF b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..8836a83e2
--- /dev/null
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Created-By: 17.0.3 (IBM Corporation)
+
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/invoker.properties b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/invoker.properties
new file mode 100644
index 000000000..baf93bcbf
--- /dev/null
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/invoker.properties
@@ -0,0 +1,4 @@
+invoker.goals.1 = -Poverlay clean compile liberty:create liberty:install-feature liberty:deploy verify
+invoker.goals.2 = -Pnon-exploded clean compile liberty:create liberty:install-feature liberty:deploy verify
+invoker.goals.3 = -Pfiltered-web-resource clean compile liberty:create liberty:install-feature liberty:deploy verify
+invoker.goals.4 = -Pfiltered-dd clean compile liberty:create liberty:install-feature liberty:deploy verify
diff --git a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/pom.xml b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/pom.xml
old mode 100755
new mode 100644
similarity index 51%
rename from liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/pom.xml
rename to liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/pom.xml
index 4654d6c19..8db7438b8
--- a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/pom.xml
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/pom.xml
@@ -1,13 +1,16 @@
-
+
-
4.0.0
- dev-it-tests
- exploded-war-proj
- 1.0-SNAPSHOT
+
+ io.openliberty.tools.it
+ tests
+ 1.0-SNAPSHOT
+
+
+ deploy-loose-config-exploded-it
war
@@ -15,58 +18,14 @@
UTF-8
1.7
1.7
- LibertyProject
-
- 9080
- 9443
-
- usr
-
-
-
-
- io.openliberty.features
- features-bom
- RUNTIME_VERSION
- pom
- import
-
-
-
-
-
-
- io.openliberty.features
- jaxrs-2.1
- esa
- provided
-
-
- io.openliberty.features
- jsonp-1.1
- esa
- provided
-
-
- io.openliberty.features
- cdi-2.0
- esa
- provided
-
-
- io.openliberty.features
- mpConfig-1.3
- esa
- provided
-
-
- io.openliberty.features
- mpRestClient-1.2
- esa
- provided
-
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ provided
+
junit
@@ -131,21 +90,22 @@
1.2.3
runtime
-
-
-
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.1.2
+
+
+ **/*.java
+
+
+
org.apache.maven.plugins
maven-war-plugin
@@ -153,65 +113,27 @@
false
pom.xml
-
-
-
-
+
+
+
+ ${project.basedir}/src/main/resource1
+ false
+
+
false
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 3.1.2
-
-
- test
- default-test
-
-
- **/it/**
-
- ${project.build.directory}/test-reports/unit
-
-
-
-
+
io.openliberty.tools
liberty-maven-plugin
- SUB_VERSION
+ @pom.version@
-
- io.openliberty
- openliberty-kernel
- RUNTIME_VERSION
- zip
-
- ${app.name}
- ${packaging.type}
-
- ${testServerHttpPort}
- ${testServerHttpsPort}
- json
-
-
+ true
-
+
org.apache.maven.plugins
maven-failsafe-plugin
@@ -223,16 +145,6 @@
integration-test
-
-
- **/it/**/*.java
-
-
-
- ${testServerHttpPort}
-
-
-
verify-results
@@ -242,10 +154,121 @@
- ${project.build.directory}/test-reports/it/failsafe-summary.xml
+
+ ${project.build.directory}/test-reports/it/failsafe-summary.xml
${project.build.directory}/test-reports/it
+
+
+ non-exploded
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ **/NonExplodedTest.java
+
+
+ **/ExplodedTest.java
+
+
+
+
+
+
+
+
+ overlay
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ **/ExplodedTest.java
+
+
+ **/ExplodedFilteredDDTest.java
+ **/NonExplodedTest.java
+
+
+
+
+
+
+
+ filtered-web-resource
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+
+ ${project.basedir}/src/main/resource2
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ **/ExplodedTest.java
+
+
+ **/ExplodedFilteredDDTest.java
+ **/NonExplodedTest.java
+
+
+
+
+
+
+
+ filtered-dd
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+true
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ **/ExplodedFilteredDDTest.java
+
+
+ **/ExplodedTest.java
+ **/NonExplodedTest.java
+
+
+
+
+
+
+
diff --git a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/java/com/demo/HelloServlet.java b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/java/mypkg/HelloServlet.java
similarity index 71%
rename from liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/java/com/demo/HelloServlet.java
rename to liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/java/mypkg/HelloServlet.java
index 01cc44f09..7bb82878b 100644
--- a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/java/com/demo/HelloServlet.java
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/java/mypkg/HelloServlet.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * (c) Copyright IBM Corporation 2021.
+ * (c) Copyright IBM Corporation 2019.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,13 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
-package com.demo;
+package mypkg;
import java.io.IOException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
@@ -30,10 +27,18 @@
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
- private static final Logger log = LoggerFactory.getLogger(HelloLogger.class);
-
+ /**
+ * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
+ */
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- log.info("SLF4J Logger is ready for messages.");
- response.getWriter().append("hello world");
+ String msg = "greeting";
+ response.getWriter().append(msg);
+ }
+
+ /**
+ * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
+ */
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ doGet(request, response);
}
-}
\ No newline at end of file
+}
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/liberty/config/server.xml b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/liberty/config/server.xml
new file mode 100644
index 000000000..6050da10a
--- /dev/null
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/liberty/config/server.xml
@@ -0,0 +1,22 @@
+
+
+
+ jsp-2.3
+
+
+
+
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/resource1/keepalive.txt b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/resource1/keepalive.txt
new file mode 100644
index 000000000..f7d55cf9a
--- /dev/null
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/resource1/keepalive.txt
@@ -0,0 +1 @@
+r1
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/resource2/keepalive.txt b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/resource2/keepalive.txt
new file mode 100644
index 000000000..9a6c8d12d
--- /dev/null
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/resource2/keepalive.txt
@@ -0,0 +1 @@
+r2
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/webapp/WEB-INF/web.xml b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..baddd26c0
--- /dev/null
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,10 @@
+
+
+ Hello Servlet
+
+
+ index.html
+
+
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/webapp/index.html b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/webapp/index.html
new file mode 100644
index 000000000..06dbf4635
Binary files /dev/null and b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/main/webapp/index.html differ
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/ExplodedFilteredDDTest.java b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/ExplodedFilteredDDTest.java
new file mode 100644
index 000000000..43aeabd0b
--- /dev/null
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/ExplodedFilteredDDTest.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * (c) Copyright IBM Corporation 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package mypkg;
+
+import static mypkg.utils.LooseConfigUtils.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Web application test case
+ */
+public class ExplodedFilteredDDTest {
+
+ @Test
+ public void testExplodedLooseAppFormat() throws Exception {
+ File in = new File("target/liberty/wlp/usr/servers/defaultServer/dropins/deploy-loose-config-exploded-it.war.xml");
+ FileInputStream input = new FileInputStream(in);
+
+ // get input XML Document
+ DocumentBuilderFactory inputBuilderFactory = DocumentBuilderFactory.newInstance();
+ inputBuilderFactory.setIgnoringComments(true);
+ inputBuilderFactory.setCoalescing(true);
+ inputBuilderFactory.setIgnoringElementContentWhitespace(true);
+ inputBuilderFactory.setValidating(false);
+ DocumentBuilder inputBuilder = inputBuilderFactory.newDocumentBuilder();
+ Document inputDoc=inputBuilder.parse(input);
+
+ // parse input XML Document
+ XPath xPath = XPathFactory.newInstance().newXPath();
+
+ String expression = "/archive//*";
+ NodeList nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
+ Assert.assertEquals("Number of archive elements ==>", 4, nodes.getLength());
+
+ expression = "/archive/dir";
+ nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
+ Assert.assertEquals("Number of
element ==>", 3, nodes.getLength());
+
+ // 1. validate:
+ //
+ validateSrcResourceRoot(nodes.item(0), "src" + File.separator + "main" + File.separator + "resource1");
+
+ // 2. validate:
+ //
+ validateTargetClasses(nodes.item(1));
+
+ // 3. validate:
+ //
+ validateWebAppDirRoot(nodes.item(2), "deploy-loose-config-exploded-it-1.0-SNAPSHOT");
+ }
+}
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/ExplodedTest.java b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/ExplodedTest.java
new file mode 100644
index 000000000..5fa493ad1
--- /dev/null
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/ExplodedTest.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * (c) Copyright IBM Corporation 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package mypkg;
+
+import static mypkg.utils.LooseConfigUtils.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+/**
+ * Web application test case
+ */
+public class ExplodedTest {
+
+ @Test
+ public void testExplodedLooseAppFormat() throws Exception {
+ File in = new File("target/liberty/wlp/usr/servers/defaultServer/dropins/deploy-loose-config-exploded-it.war.xml");
+ FileInputStream input = new FileInputStream(in);
+
+ // get input XML Document
+ DocumentBuilderFactory inputBuilderFactory = DocumentBuilderFactory.newInstance();
+ inputBuilderFactory.setIgnoringComments(true);
+ inputBuilderFactory.setCoalescing(true);
+ inputBuilderFactory.setIgnoringElementContentWhitespace(true);
+ inputBuilderFactory.setValidating(false);
+ DocumentBuilder inputBuilder = inputBuilderFactory.newDocumentBuilder();
+ Document inputDoc=inputBuilder.parse(input);
+
+ // parse input XML Document
+ XPath xPath = XPathFactory.newInstance().newXPath();
+
+ String expression = "/archive//*";
+ NodeList nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
+ Assert.assertEquals("Number of archive elements ==>", 5, nodes.getLength());
+
+ expression = "/archive/dir";
+ nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
+ Assert.assertEquals("Number of element ==>", 4, nodes.getLength());
+
+ // 1. validate:
+ //
+ validateSrcMainWebAppRoot(nodes.item(0));
+
+ // 2. validate:
+ //
+ validateSrcResourceRoot(nodes.item(1), "src" + File.separator + "main" + File.separator + "resource1");
+
+ // 3. validate:
+ //
+ validateTargetClasses(nodes.item(2));
+
+ // 4. validate:
+ //
+ validateWebAppDirRoot(nodes.item(3), "deploy-loose-config-exploded-it-1.0-SNAPSHOT");
+ }
+
+}
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/NonExplodedTest.java b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/NonExplodedTest.java
new file mode 100644
index 000000000..867a9671e
--- /dev/null
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/NonExplodedTest.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * (c) Copyright IBM Corporation 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package mypkg;
+
+import static mypkg.utils.LooseConfigUtils.validateSrcMainWebAppRoot;
+import static mypkg.utils.LooseConfigUtils.validateTargetClasses;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Web application test case
+ */
+public class NonExplodedTest {
+
+ @Test
+ public void testNonExplodedLooseAppFormat() throws Exception {
+ File in = new File("target/liberty/wlp/usr/servers/defaultServer/dropins/deploy-loose-config-exploded-it.war.xml");
+ FileInputStream input = new FileInputStream(in);
+
+ // get input XML Document
+ DocumentBuilderFactory inputBuilderFactory = DocumentBuilderFactory.newInstance();
+ inputBuilderFactory.setIgnoringComments(true);
+ inputBuilderFactory.setCoalescing(true);
+ inputBuilderFactory.setIgnoringElementContentWhitespace(true);
+ inputBuilderFactory.setValidating(false);
+ DocumentBuilder inputBuilder = inputBuilderFactory.newDocumentBuilder();
+ Document inputDoc=inputBuilder.parse(input);
+
+ // parse input XML Document
+ XPath xPath = XPathFactory.newInstance().newXPath();
+
+ String expression = "/archive//*";
+ NodeList nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
+ Assert.assertEquals("Number of archive elements ==>", 13, nodes.getLength());
+
+ expression = "/archive/dir";
+ nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
+ Assert.assertEquals("Number of element ==>", 3, nodes.getLength());
+
+ // validate:
+ //
+ validateSrcMainWebAppRoot(nodes.item(0));
+
+ // validate:
+ //
+ validateTargetClasses(nodes.item(1));
+
+ expression = "/archive/file";
+ nodes = (NodeList) xPath.compile(expression).evaluate(inputDoc, XPathConstants.NODESET);
+
+ // validate:
+ //
+ String commonsLangBaseName = "commons-lang3-3.0.jar";
+ boolean foundCommonsLangJar = false;
+ for (int i = 0; i < nodes.getLength() && !foundCommonsLangJar; i++) {
+ Node node = nodes.item(i);
+ String srcVal = node.getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
+ String targetVal = node.getAttributes().getNamedItem("targetInArchive").getNodeValue();
+ if (srcVal.endsWith(commonsLangBaseName) && targetVal.endsWith(commonsLangBaseName)) {
+ foundCommonsLangJar = true;
+ }
+ }
+ Assert.assertTrue("Didn't find commons lang JAR in loose app XML ending with: " + commonsLangBaseName, foundCommonsLangJar);
+ }
+
+}
diff --git a/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/utils/LooseConfigUtils.java b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/utils/LooseConfigUtils.java
new file mode 100644
index 000000000..8efc190cd
--- /dev/null
+++ b/liberty-maven-plugin/src/it/deploy-loose-config-exploded-it/src/test/java/mypkg/utils/LooseConfigUtils.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * (c) Copyright IBM Corporation 2023.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *******************************************************************************/
+package mypkg.utils;
+
+import java.io.File;
+
+import org.junit.Assert;
+import org.w3c.dom.Node;
+
+public class LooseConfigUtils {
+
+ public static void validateSrcMainWebAppRoot(Node archiveElem) {
+ // validate:
+ //
+ String s1 = archiveElem.getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
+ Assert.assertTrue("Bad node: " + s1, s1.endsWith("src" + File.separator + "main" + File.separator + "webapp"));
+ String t1 = archiveElem.getAttributes().getNamedItem("targetInArchive").getNodeValue();
+ Assert.assertEquals("Bad node: " + t1, "/", t1);
+ }
+
+ public static void validateSrcResourceRoot(Node archiveElem, String resourcePath) {
+
+ // validate:
+ //
+ String s1 = archiveElem.getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
+ Assert.assertTrue("Bad node: " + s1, s1.endsWith(resourcePath));
+ String t1 = archiveElem.getAttributes().getNamedItem("targetInArchive").getNodeValue();
+ Assert.assertEquals("Bad node: " + t1, "/", t1);
+ }
+
+ public static void validateWebAppDirRoot(Node archiveElem, String webAppName) {
+
+ // validate:
+ //
+ String s1 = archiveElem.getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
+ Assert.assertTrue("Bad node: " + s1, s1.endsWith(webAppName));
+ String t1 = archiveElem.getAttributes().getNamedItem("targetInArchive").getNodeValue();
+ Assert.assertEquals("Bad node: " + t1, "/", t1);
+ }
+
+ // validate:
+ //
+ public static void validateTargetClasses(Node archiveElem) {
+ String s1 = archiveElem.getAttributes().getNamedItem("sourceOnDisk").getNodeValue();
+ Assert.assertTrue("Bad node: " + s1, s1.endsWith("target" + File.separator + "classes"));
+ String t1 = archiveElem.getAttributes().getNamedItem("targetInArchive").getNodeValue();
+ Assert.assertEquals("Bad node: " + t1, "/WEB-INF/classes", t1);
+ }
+}
diff --git a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/java/com/demo/HelloLogger.java b/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/java/com/demo/HelloLogger.java
deleted file mode 100755
index d717d81a5..000000000
--- a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/java/com/demo/HelloLogger.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * (c) Copyright IBM Corporation 2021.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *******************************************************************************/
-package com.demo;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-
-import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
-
-@Path("/show-log")
-public class HelloLogger {
- private static final Logger log = LoggerFactory.getLogger(HelloLogger.class);
-
- @GET
- @Produces(TEXT_PLAIN)
- public String showLog() {
- log.info("Here is the Log");
- return "Log has been shown";
- }
-}
diff --git a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/java/com/demo/HelloWorld.java b/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/java/com/demo/HelloWorld.java
deleted file mode 100755
index 937240b5c..000000000
--- a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/java/com/demo/HelloWorld.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*******************************************************************************
- * (c) Copyright IBM Corporation 2021.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *******************************************************************************/
-package com.demo;
-
-public class HelloWorld {
-
- public String helloWorld() {
- return "helloWorld";
- }
-}
diff --git a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/liberty/config/server.xml b/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/liberty/config/server.xml
deleted file mode 100755
index fdad620d8..000000000
--- a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/liberty/config/server.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
- jaxrs-2.1
-
-
-
-
diff --git a/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/resources/placeHolder.txt b/liberty-maven-plugin/src/it/dev-it/resources/exploded-war-project/src/main/resources/placeHolder.txt
deleted file mode 100644
index e69de29bb..000000000
diff --git a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/ExplodedLooseWarAppTest.java b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/ExplodedLooseWarAppTest.java
deleted file mode 100644
index dbe139af8..000000000
--- a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/ExplodedLooseWarAppTest.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*******************************************************************************
- * (c) Copyright IBM Corporation 2021.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *******************************************************************************/
-package net.wasdev.wlp.test.dev.it;
-
-import static org.junit.Assert.*;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.nio.file.Files;
-import java.util.Scanner;
-
-import org.apache.commons.io.FileUtils;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-
-public class ExplodedLooseWarAppTest extends BaseDevTest {
- private final String projectArtifact = "exploded-war-proj-1.0-SNAPSHOT";
- private final String appsDir = "target/liberty/wlp/usr/servers/defaultServer/dropins/";
-
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- setUpBeforeClass(null, "../resources/exploded-war-project");
- }
-
- @AfterClass
- public static void cleanUpAfterClass() throws Exception {
- BaseDevTest.cleanUpAfterClass();
- }
-
- @Ignore // TODO enable this test
- @Test
- public void configureWebXmlFiltering() throws Exception {
- int appDeployedCount = countOccurrences("Running liberty:deploy", logFile);
- // Add deployment descriptor filtering config to pom war plugin
- replaceString("false",
- "true", pom);
-
- // Verify exploded goal running and redeploy
- assertTrue(getLogTail(), verifyLogMessageExists("Running liberty:deploy", 4000, logFile, ++appDeployedCount));
- assertTrue(getLogTail(), verifyLogMessageExists("Running maven-war-plugin:exploded", 2000));
-
- // Verify loose app xml is correct
- verifyExplodedLooseApp();
-
- // Remove filtering config
- replaceString("true",
- "false", pom);
-
- // Verify redeploy
- assertTrue(getLogTail(), verifyLogMessageExists("Running liberty:deploy", 2000));
-
- // Verify loose app xml is back to how it was
- verifyNonExplodedLooseApp();
- }
-
- @Ignore // TODO enable this test
- @Test
- public void configureFilteredResource() throws Exception {
- // Add filtering config to pom war plugin (directory)
- replaceString("", pom);
-
- replaceString("Filtered directory end -->",
- "", pom);
-
- // Verify exploded goal running and redeploy
- assertTrue(getLogTail(), verifyLogMessageExists("Running liberty:deploy", 2000));
- assertTrue(getLogTail(), verifyLogMessageExists("Running maven-war-plugin:exploded", 2000));
-
- // Verify loose app xml is correct
- verifyExplodedLooseApp();
-
- // Remove filtering config
- replaceString("",
- "",
- "Filtered directory end -->", pom);
-
- // Verify redeploy
- assertTrue(getLogTail(), verifyLogMessageExists("Running liberty:deploy", 2000));
-
- // Verify loose app xml is back to how it was
- verifyNonExplodedLooseApp();
- }
-
- @Ignore // TODO enable this test
- @Test
- public void configureWarOverlay() throws Exception {
- // Add filtering config to pom war plugin (directory)
- replaceString("", pom);
-
- replaceString("Overlay configuration end -->",
- "", pom);
-
- // Verify exploded goal running and redeploy
- assertTrue(getLogTail(), verifyLogMessageExists("Running liberty:deploy", 2000));
- assertTrue(getLogTail(), verifyLogMessageExists("Running maven-war-plugin:exploded", 2000));
-
- // Verify loose app xml is correct
- verifyExplodedLooseApp();
-
- // Remove filtering config
- replaceString("",
- "",
- "Overlay configuration end -->", pom);
-
- // Verify redeploy
- assertTrue(getLogTail(), verifyLogMessageExists("Running liberty:deploy", 2000));
-
- // Verify loose app xml is back to how it was
- verifyNonExplodedLooseApp();
- }
-
- private void verifyExplodedLooseApp() throws Exception {
- String looseAppXml = tempProj.getAbsolutePath() + "/" + appsDir + projectArtifact + ".war.xml";
-
- // Verify the target/ entry
- String explodedWar = basicDevProj.getAbsolutePath() + "/target/" + projectArtifact;
- assertTrue(getLogTail(), verifyFileExists(new File(looseAppXml), 3000));
- assertTrue(getLogTail(), verifyLogMessageExists("", 3000, new File(looseAppXml)));
- }
-
- private void verifyNonExplodedLooseApp() throws Exception {
- String looseAppXml = tempProj.getAbsolutePath() + "/" + appsDir + projectArtifact + ".war.xml";
-
- // Verify the src/main/webapp entry
- String srcMain = basicDevProj.getAbsolutePath() + "/src/main/webapp";
- assertTrue(getLogTail(), verifyLogMessageExists("", 3000, new File(looseAppXml)));
-
- // Verify the target/classes entry
- String targetClasses = basicDevProj.getAbsolutePath() + "/target/classes";
- assertTrue(getLogTail(), verifyLogMessageExists("", 3000, new File(looseAppXml)));
- }
-}
diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojoSupport.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojoSupport.java
index b8a0b4bc0..e1df929ed 100644
--- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojoSupport.java
+++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/DeployMojoSupport.java
@@ -146,27 +146,42 @@ protected void installLooseConfigWar(MavenProject proj, LooseConfigData config,
// Validate maven-war-plugin version
Plugin warPlugin = getPlugin("org.apache.maven.plugins", "maven-war-plugin");
- if (!validatePluginVersion(warPlugin.getVersion(), "3.3.1")) {
- getLog().warn("Exploded WAR functionality is enabled. Please use maven-war-plugin version 3.3.1 or greater for best results.");
+ if (!validatePluginVersion(warPlugin.getVersion(), "3.3.2")) {
+ getLog().warn(
+ "Exploded WAR functionality is enabled. Please use maven-war-plugin version 3.3.2 or greater for best results.");
}
- // If I'm filtering web.xml, etc., I want to monitor from the exploded dir, not via a source dir
- if (!looseWar.isFilteringDeploymentDescriptors()) {
- looseWar.addSourceDir();
- }
-
- // Add source paths for non-filtered web resources.
- // We'll already have the runtime application monitor watching for file changes, and we
- // don't want to set up the more expensive dev mode type of watching.
- looseWar.addNonFilteredWebResourcesConfigurationPaths();
-
// Don't especially need to run it exactly here, but in debugger we can see what we have
runExplodedMojo();
+ ////////////////////////////////////
+ // The order matters and establishes a well-defined precedence as documented: https://www.ibm.com/docs/en/was-liberty/base?topic=liberty-loose-applications
+ //
+ // ".. If you have two files with the same target location in the loose archive, the first occurrence of the file is used.
+ // The first occurrence is based on a top-down approach to reading the elements of the loose application configuration file..."
+ //
+ // Because the flow is so complicated we may have cases where we are applying filtering where one location contains a filtered
+ // version of a file and another potentially has an unfiltered one, and in such cases we need to make sure the filtered version takes
+ // precedence.
+ //
+ // In certain cases, like step 1. below we avoid writing a location into the loose app XML because we don't want an unfiltered
+ // to take precedence and prevent the filtered value from taking effect.
+ //
+ ////////////////////////////////////
+
+ // 1. Add source paths for the source dir and non-filtered web resources. Since there could be overlap, i.e. the source dir
+ // could also be configured as a web resource, we combine these into a single step.
+ //
+ // We'll already have the runtime application monitor watching for file changes, and we don't want to set up the more expensive
+ // dev mode type of watching.
+ looseWar.addNonFilteredSourceAndWebResourcesPaths();
+
+ // 2. target classes - this allows non-deploy mode cases (e.g. non-deploy cases such as `mvn compile` or m2e update in Eclipse)
+ // to pick up Java class updates upon compilation.
+ looseWar.addOutputDir(looseWar.getDocumentRoot(), new File(proj.getBuild().getOutputDirectory()), "/WEB-INF/classes");
+
//////////////////////////
- // Per doc: https://www.ibm.com/docs/en/was-liberty/base?topic=liberty-loose-applications
- // ".. If you have two files with the same target location in the loose archive, the first occurrence of the file is used.
- // The first occurrence is based on a top-down approach to reading the elements of the loose application configuration file..."
+ // 3. Finally add the exploded dir
//
// In order to dynamically reflect changes in non-filtered web app source, this needs to go AFTER the unfiltered source entries above, since
// changes in these un-monitored directories will NOT cause a new 'exploded' goal execution, so the updated content in the unmonitored source will
@@ -181,14 +196,20 @@ protected void installLooseConfigWar(MavenProject proj, LooseConfigData config,
} else {
+ // 1.
looseWar.addSourceDir();
+ // 2.
looseWar.addOutputDir(looseWar.getDocumentRoot(), new File(proj.getBuild().getOutputDirectory()),
"/WEB-INF/classes");
- // retrieve the directories defined as resources in the maven war plugin
+ // 3. retrieve the directories defined as resources in the maven war plugin
+ //
+ // TODO - It would be cleaner to avoid duplicating the source dir in the case it also appears as a web resource, like we do in the exploded case.
+ // If this ever became an issue we could combine this with step 1. above. However at the moment it doesn't seem worth the risk of making a change
+ // in such a key area.
looseWar.addAllWebResourcesConfigurationPaths();
- // retrieves dependent library jar files
+ // 4. retrieves dependent library jar files
addEmbeddedLib(looseWar.getDocumentRoot(), proj, looseWar, "/WEB-INF/lib/");
}
diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/LooseWarApplication.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/LooseWarApplication.java
index a4b9a95f3..910d1a4c4 100644
--- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/LooseWarApplication.java
+++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/applications/LooseWarApplication.java
@@ -36,42 +36,34 @@
public class LooseWarApplication extends LooseApplication {
protected final MavenProject project;
+
+ protected final Path warSourceDirectory;
protected final Log log;
public LooseWarApplication(MavenProject project, LooseConfigData config, Log log) {
super(project.getBuild().getDirectory(), config);
this.project = project;
+ this.warSourceDirectory = getWarSourceDirectory(project);
this.log = log;
}
public static boolean isExploded(MavenProject project) {
- boolean isExplodedWar = false;
-
- // Check if filtering is enabled
- List dynamicWebResources = getFilteredWebSourceDirectories(project);
-
- if (!dynamicWebResources.isEmpty() || isUsingOverlays(project)) {
- isExplodedWar = true;
- }
-
- // TODO: Check additional filtering options (properties?)
-
- return isExplodedWar;
+ if (isUsingOverlays(project)) {
+ return true;
+ } else if (!getWebSourceDirectoriesToMonitor(project).isEmpty()) {
+ return true;
+ } else {
+ return false;
+ }
}
-
public boolean isExploded() {
return isExploded(project);
}
public void addSourceDir() throws IOException {
- Path warSourceDir = getWarSourceDirectory();
- config.addDir(warSourceDir.toFile(), "/");
- }
-
- public Path getWarSourceDirectory() {
- return getWarSourceDirectory(project);
+ config.addDir(warSourceDirectory.toFile(), "/");
}
private static Path getWarSourceDirectory(MavenProject project) {
@@ -102,10 +94,36 @@ private Path getWebAppDirectory(MavenProject project) {
}
}
- public static List getFilteredWebSourceDirectories(MavenProject project) {
+ /**
+ * @param project
+ *
+ * @return A list of directory Path(s) including each web source directory that has filtering applied, including the war source
+ * directory (if so configured) or webResources entries
+ */
+ public static List getWebSourceDirectoriesToMonitor(MavenProject project) {
+
+ Set filteredWebResources = getFilteredWebResourcesConfigurations(project);
- List retVal = new ArrayList();
+ List retVal = new ArrayList(filteredWebResources);
+ Path warSourceDir = getWarSourceDirectory(project);
+
+ // Need to add warSourceDir if DD filtering enabled, unless it's already in the list having its own webResources config
+ if (!filteredWebResources.contains(warSourceDir) && isFilteringDeploymentDescriptors(project)) {
+ retVal.add(warSourceDir);
+ }
+
+ return retVal;
+ }
+
+ /**
+ * @param project
+ *
+ * @return List of webResources/resource configurations with filtering enabled, whether they happen to be the war source directory
+ * or not
+ */
+ private static Set getFilteredWebResourcesConfigurations(MavenProject project) {
+ Set retVal = new HashSet();
Path baseDirPath = Paths.get(project.getBasedir().getAbsolutePath());
for (Xpp3Dom resource : getWebResourcesConfigurations(project)) {
@@ -119,18 +137,11 @@ public static List getFilteredWebSourceDirectories(MavenProject project) {
}
}
- // Now add warSourceDir
- if (isFilteringDeploymentDescriptors(project)) {
- retVal.add(getWarSourceDirectory(project));
- }
-
return retVal;
}
-
- public List getFilteredWebSourceDirectories() {
- return getFilteredWebSourceDirectories(project);
- }
-
+
+
+
private static boolean isFilteringDeploymentDescriptors(MavenProject project) {
Boolean retVal = false;
Xpp3Dom dom = project.getGoalConfiguration("org.apache.maven.plugins", "maven-war-plugin", null, null);
@@ -232,7 +243,14 @@ public static List getWebResourcesConfigurations(MavenProject project)
return retVal;
}
- private void addWebResourcesConfigurationPaths(boolean onlyUnfiltered) throws DOMException, IOException {
+ /*
+ * Add loose app XML elements for each directory within a maven-war-plugin configuration/webResources/resource/directory element
+ *
+ * @return
+ * @throws IOException
+ * @throws DOMException
+ */
+ public void addAllWebResourcesConfigurationPaths() throws DOMException, IOException {
Set handled = new HashSet();
Path baseDirPath = Paths.get(project.getBasedir().getAbsolutePath());
@@ -240,37 +258,62 @@ private void addWebResourcesConfigurationPaths(boolean onlyUnfiltered) throws DO
for (Xpp3Dom resource : getWebResourcesConfigurations(project)) {
Xpp3Dom dir = resource.getChild("directory");
Xpp3Dom target = resource.getChild("targetPath");
- Xpp3Dom filtering = resource.getChild("filtering");
Path resolvedDir = baseDirPath.resolve(dir.getValue());
if (handled.contains(resolvedDir)) {
log.warn("Ignoring webResources dir: " + dir.getValue() + ", already have entry for path: " + resolvedDir);
} else {
- if (onlyUnfiltered && filtering != null && Boolean.parseBoolean(filtering.getValue())) {
- continue;
- } else {
- String targetPath = "/";
- if (target != null) {
- targetPath = "/" + target.getValue();
- }
- addOutputDir(getDocumentRoot(), resolvedDir.toFile(), targetPath);
- handled.add(resolvedDir);
- }
+ String targetPath = "/";
+ if (target != null) {
+ targetPath = "/" + target.getValue();
+ }
+ addOutputDir(getDocumentRoot(), resolvedDir.toFile(), targetPath);
+ handled.add(resolvedDir);
}
}
}
/*
+ * Add loose app XML elements for the WAR source directory, as long as it is not filtered, and for each non-filtered
+ * maven-war-plugin configuration/webResources/resource/directory element
+ *
* @return
* @throws IOException
* @throws DOMException
*/
+ public void addNonFilteredSourceAndWebResourcesPaths() throws DOMException, IOException {
- public void addAllWebResourcesConfigurationPaths() throws DOMException, IOException {
- addWebResourcesConfigurationPaths(false);
- }
+ // Write the source dir first, out of tradition/precedence
+ if (!isFilteringDeploymentDescriptors() && !getFilteredWebResourcesConfigurations(project).contains(warSourceDirectory)) {
+ addSourceDir();
+ }
+
+ Path baseDirPath = Paths.get(project.getBasedir().getAbsolutePath());
- public void addNonFilteredWebResourcesConfigurationPaths() throws DOMException, IOException {
- addWebResourcesConfigurationPaths(true);
+ Set handled = new HashSet(); // Use to warn for duplicate entries
+ for (Xpp3Dom resource : getWebResourcesConfigurations(project)) {
+ Xpp3Dom dir = resource.getChild("directory");
+ Xpp3Dom target = resource.getChild("targetPath");
+ Xpp3Dom filtering = resource.getChild("filtering");
+ Path resolvedDir = baseDirPath.resolve(dir.getValue());
+ if (resolvedDir.equals(warSourceDirectory)) {
+ // We have already decided to write the source dir or not above
+ continue;
+ }
+ if (filtering != null && Boolean.parseBoolean(filtering.getValue())) {
+ continue;
+ } else {
+ if (handled.contains(resolvedDir)) {
+ log.warn("Ignoring webResources dir: " + dir.getValue() + ", already have entry for path: " + resolvedDir);
+ } else {
+ String targetPath = "/";
+ if (target != null) {
+ targetPath = "/" + target.getValue();
+ }
+ addOutputDir(getDocumentRoot(), resolvedDir.toFile(), targetPath);
+ handled.add(resolvedDir);
+ }
+ }
+ }
}
public Path getWebAppDirectory() {
diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/DevMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/DevMojo.java
index d0559beb9..5466ecfe0 100644
--- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/DevMojo.java
+++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/DevMojo.java
@@ -25,6 +25,7 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
@@ -783,8 +784,9 @@ protected void updateLooseApp() throws PluginExecutionException {
// Validate maven-war-plugin version
Plugin warPlugin = getPlugin("org.apache.maven.plugins", "maven-war-plugin");
- if (!validatePluginVersion(warPlugin.getVersion(), "3.3.1")) {
- getLog().warn("Exploded WAR functionality is enabled. Please use maven-war-plugin version 3.3.1 or greater for best results.");
+ if (!validatePluginVersion(warPlugin.getVersion(), "3.3.2")) {
+ getLog().warn(
+ "Exploded WAR functionality is enabled. Please use maven-war-plugin version 3.3.2 or greater for best results.");
}
redeployApp();
@@ -821,20 +823,30 @@ protected void resourceDirectoryCreated() throws IOException {
@Override
protected void resourceModifiedOrCreated(File fileChanged, File resourceParent, File outputDirectory) throws IOException {
- if (project.getPackaging().equals("war") && LooseWarApplication.isExploded(project)) {
- try {
- runMojo("org.apache.maven.plugins", "maven-resources-plugin", "resources");
- runExplodedMojo();
- } catch (MojoExecutionException e) {
- getLog().error("Failed to run goal(s)", e);
- }
- } else {
- copyFile(fileChanged, resourceParent, outputDirectory, null);
+ /**
+ * There is an asymmetry here that we take advantage of in the exploded case. For multi-mod, this would be a copyFile, which
+ * does not apply Maven filters.
+ */
+ try {
+ runMojo("org.apache.maven.plugins", "maven-resources-plugin", "resources");
+ } catch (MojoExecutionException e) {
+ getLog().error("Failed to run goal(s)", e);
}
}
@Override
protected void resourceDeleted(File fileChanged, File resourceParent, File outputDirectory) throws IOException {
+
+ /**
+ * Why is this so asymmetric compared to resourceModifiedOrCreated() above? For two reasons: 1. The resources:resources plugin
+ * goal doesn't update the target/output directory with deletions, so we have to use our own custom deleteFile() method 2. In
+ * the case of the exploded loose app format, even having deleted the file from the outputDirectory ('target/classes'), the
+ * resource would typically also have been collected into the exploded 'webapp' directory. Even though it would take precedence
+ * in 'target/classes' when it ends up in both locations, it will still be present in the 'webapp' directory. So we re-run the
+ * exploded goal to force an "outdated" update cleaning this file from this location. Another approach might have been to do a
+ * delteFile() in the 'webapp' directory.
+ */
+
deleteFile(fileChanged, resourceParent, outputDirectory, null);
if (project.getPackaging().equals("war") && LooseWarApplication.isExploded(project)) {
try {
@@ -871,10 +883,12 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat
// set the updated project in current session;
Plugin backupLibertyPlugin = getLibertyPlugin();
+ Plugin backupWarPlugin = getPluginForProject("org.apache.maven.plugins", "maven-war-plugin", project);
MavenProject backupProject = project;
project = build.getProject();
session.setCurrentProject(project);
Plugin libertyPlugin = getLibertyPlugin();
+ Plugin warPlugin = getPluginForProject("org.apache.maven.plugins", "maven-war-plugin", project);
try {
// TODO rebuild the corresponding module if the compiler options have changed
@@ -916,6 +930,11 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat
if (!Objects.equals(config, oldConfig)) {
redeployApp = true;
}
+ config = ExecuteMojoUtil.getPluginGoalConfig(warPlugin, "exploded", getLog());
+ oldConfig = ExecuteMojoUtil.getPluginGoalConfig(backupWarPlugin, "exploded", getLog());
+ if (!Objects.equals(config, oldConfig) || !warPlugin.getVersion().equals(backupWarPlugin.getVersion())) {
+ redeployApp = true;
+ }
config = ExecuteMojoUtil.getPluginGoalConfig(libertyPlugin, "generate-features", getLog());
oldConfig = ExecuteMojoUtil.getPluginGoalConfig(backupLibertyPlugin, "generate-features", getLog());
if (!Objects.equals(config, oldConfig)) {
@@ -967,6 +986,25 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat
}
}
+
+ // We don't currently have the ability to dynamically add new directories to be watched
+ // There is so much that we are dynamically able to do that this could be surprising.
+ // For now issue a warning
+ Set oldMonitoredWebResourceDirs = new HashSet(this.monitoredWebResourceDirs);
+ Set newMonitoredWebResourceDirs = new HashSet(LooseWarApplication.getWebSourceDirectoriesToMonitor(project));
+ if (!oldMonitoredWebResourceDirs.equals(newMonitoredWebResourceDirs)) {
+ getLog().warn("Change detected in the set of filtered web resource directories, since dev mode was first launched. Adding/deleting a web resource directory has no change on the set of directories monitored by dev mode. Changing the watch list will require a dev mode restart");
+ }
+
+ // convert to Path, which seems to offer more reliable cross-platform, relative path comparison, then compare
+ Set oldResourceDirs = new HashSet();
+ this.resourceDirs.forEach(r -> oldResourceDirs.add(r.toPath()));
+ Set newResourceDirs = new HashSet();
+ project.getResources().forEach(r -> newResourceDirs.add(Paths.get(r.getDirectory())));
+ if (!oldResourceDirs.equals(newResourceDirs)) {
+ getLog().warn("Change detected in the set of resource directories, since dev mode was first launched. Adding/deleting a resource directory has no change on the set of directories monitored by dev mode. Changing the watch list will require a dev mode restart");
+ }
+
if (restartServer) {
// - stop Server
// - create server or runBoostMojo
@@ -1359,7 +1397,7 @@ private void doDevMode() throws MojoExecutionException {
// resource directories
List resourceDirs = getResourceDirectories(project, outputDirectory);
- List webResourceDirs = LooseWarApplication.getFilteredWebSourceDirectories(project);
+ List webResourceDirs = LooseWarApplication.getWebSourceDirectoriesToMonitor(project);
JavaCompilerOptions compilerOptions = getMavenCompilerOptions(project);
diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/StartDebugMojoSupport.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/StartDebugMojoSupport.java
index 4199d251f..c8fdce107 100644
--- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/StartDebugMojoSupport.java
+++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/StartDebugMojoSupport.java
@@ -207,9 +207,14 @@ protected void runExplodedMojo() throws MojoExecutionException {
Plugin warPlugin = getPlugin("org.apache.maven.plugins", "maven-war-plugin");
Xpp3Dom explodedConfig = ExecuteMojoUtil.getPluginGoalConfig(warPlugin, "exploded", getLog());
- if (validatePluginVersion(warPlugin.getVersion(), "3.3.1")) {
- explodedConfig.addChild(element(name("outdatedCheckPath"), "WEB-INF").toDom());
+ if (explodedConfig.getChild("outdatedCheckPath") == null) {
+ if (validatePluginVersion(warPlugin.getVersion(), "3.3.2")) {
+ explodedConfig.addChild(element(name("outdatedCheckPath"), "/").toDom());
+ } else if (validatePluginVersion(warPlugin.getVersion(), "3.3.1")) {
+ explodedConfig.addChild(element(name("outdatedCheckPath"), "WEB-INF").toDom());
+ }
}
+
getLog().info("Running maven-war-plugin:exploded");
getLog().debug("configuration:\n" + explodedConfig);
session.getRequest().setStartTime(new Date());
diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/ExecuteMojoUtil.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/ExecuteMojoUtil.java
index 2627503b3..bb6560d2c 100644
--- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/ExecuteMojoUtil.java
+++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/utils/ExecuteMojoUtil.java
@@ -139,9 +139,17 @@ public class ExecuteMojoUtil {
private static final ArrayList FAILSAFE_REPORT_ONLY_PARAMS = REPORT_ONLY_PARAMS;
// https://maven.apache.org/plugins/maven-war-plugin/exploded-mojo.html
+ // as of Version: 3.4.1-SNAPSHOT, 2023-06-11
private static final ArrayList EXPLODED_PARAMS = new ArrayList<>(Arrays.asList(
- "filteringDeploymentDescriptors", "warSourceDirectory", "webappDirectory", "workDirectory", "filters",
- "overlays", "webResources"
+ // Required
+ "warSourceDirectory", "webappDirectory", "workDirectory",
+ // Optional - skip archive* options which may not make sense with our loose app approach
+ "containerConfigXML", "delimiters", "dependentWarExcludes",
+ "dependentWarIncludes", "escapedBackslashesInFilePath", "escapeString", "failOnMissingWebXml",
+ "filteringDeploymentDescriptors", "filters", "includeEmptyDirectories", "nonFilteredFileExtensions",
+ "outdatedCheckPath", "outputFileNameMapping", "outputTimestamp", "overlays", "propertiesEncoding", "recompressZippedFiles",
+ "resourceEncoding", "supportMultiLineFiltering", "useDefaultDelimiters", "useJvmChmod", "warSourceExcludes", "warSourceIncludes",
+ "webResources", "webXml"
));
// https://maven.apache.org/plugins/maven-ear-plugin/ear-mojo.html