From 1e5ec85a9b02ca5fc85808c9967aa388221bbd25 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 8 Apr 2025 11:59:11 -0400 Subject: [PATCH 001/103] Specify version 24.0.0.2 for binary scanner Signed-off-by: Paul Gooderham --- liberty-maven-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/pom.xml b/liberty-maven-plugin/pom.xml index 8619a9a00..5c5c32bd8 100644 --- a/liberty-maven-plugin/pom.xml +++ b/liberty-maven-plugin/pom.xml @@ -88,7 +88,7 @@ io.openliberty.tools ci.common - 1.8.37 + 1.8.38-SNAPSHOT org.apache.commons From 69a9bdc88a6f18d438b1f967fa5179d92b34c17d Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 8 May 2025 18:32:43 -0400 Subject: [PATCH 002/103] Print an error message if Liberty or server directory is missing during feature generation. Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index cefc8be81..fcb63c7b4 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2021, 2024. + * (C) Copyright IBM Corporation 2021, 2025. * * 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 @@ -83,11 +83,15 @@ protected void init() throws MojoExecutionException { // @see io.openliberty.tools.maven.BasicSupport#init() skip server config // setup as generate features does not require the server to be set up install // dir, wlp dir, outputdir, etc. - this.skipServerConfigSetup = true; + // TODO: When using the generateToSrc option make use of this variable. + //this.skipServerConfigSetup = true; super.init(); + // Ensure server dir exists to generate features to the $serverDirectory/configDropins/overrides/generated-features.xml + checkServerHomeExists(); + checkServerDirectoryExists(); } - + @Override public void execute() throws MojoExecutionException { init(); From d82cede48b9f05ca5056136accbf74790d140d2b Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 12 May 2025 18:25:29 -0400 Subject: [PATCH 003/103] Do not add a comment to server.xml when generating features Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 60 +------------------ 1 file changed, 1 insertion(+), 59 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index cefc8be81..69aad2556 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2021, 2024. + * (C) Copyright IBM Corporation 2021, 2025 * * 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 @@ -35,16 +35,13 @@ import org.apache.maven.project.ProjectBuildingException; import org.apache.maven.project.ProjectBuildingResult; import org.w3c.dom.Element; -import org.xml.sax.SAXException; import io.openliberty.tools.common.plugins.config.ServerConfigXmlDocument; -import io.openliberty.tools.common.plugins.config.XmlDocument; import io.openliberty.tools.common.plugins.util.BinaryScannerUtil; import static io.openliberty.tools.common.plugins.util.BinaryScannerUtil.*; import io.openliberty.tools.common.plugins.util.PluginExecutionException; import io.openliberty.tools.common.plugins.util.ServerFeatureUtil; import io.openliberty.tools.common.plugins.util.ServerFeatureUtil.FeaturesPlatforms; -import io.openliberty.tools.maven.ServerFeatureSupport; /** * This mojo generates the features required in the featureManager element in @@ -57,8 +54,6 @@ @Mojo(name = "generate-features", threadSafe = true) public class GenerateFeaturesMojo extends PluginConfigSupport { - public static final String FEATURES_FILE_MESSAGE = "The Liberty Maven Plugin has generated Liberty features necessary for your application in " - + GENERATED_FEATURES_FILE_PATH; public static final String HEADER = "This file was generated by the Liberty Maven Plugin and will be overwritten on subsequent runs of the liberty:generate-features goal." + "\n It is recommended that you do not edit this file and that you commit this file to your version control."; public static final String GENERATED_FEATURES_COMMENT = "The following features were generated based on API usage detected in your application"; @@ -279,10 +274,6 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("Features detected by binary scanner which are not in server.xml" + missingLibertyFeatures); File newServerXmlSrc = new File(configDirectory, GENERATED_FEATURES_FILE_PATH); - File serverXml = findConfigFile("server.xml", serverXmlFile); - ServerConfigXmlDocument doc = getServerXmlDocFromConfig(serverXml); - getLog().debug("Xml document we'll try to update after generate features doc=" + doc + " file=" + serverXml); - try { if (missingLibertyFeatures.size() > 0) { Set existingGeneratedFeatures = getGeneratedFeatures(servUtil, newServerXmlSrc); @@ -300,8 +291,6 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().info("Generated the following features: " + missingLibertyFeatures); configDocument.writeXMLDocument(newServerXmlSrc); getLog().debug("Created file " + newServerXmlSrc); - // Add a reference to this new file in existing server.xml. - addGenerationCommentToConfig(doc, serverXml); } else { getLog().info("Regenerated the following features: " + missingLibertyFeatures); } @@ -375,53 +364,6 @@ private File getBinaryScannerJarFromRepository() throws PluginExecutionException } } - private ServerConfigXmlDocument getServerXmlDocFromConfig(File serverXml) { - if (serverXml == null || !serverXml.exists()) { - return null; - } - try { - return ServerConfigXmlDocument.newInstance(serverXml); - } catch (ParserConfigurationException | SAXException | IOException e) { - getLog().debug("Exception creating server.xml object model", e); - } - return null; - } - - /** - * Remove the comment in server.xml that warns we created another file with features in it. - */ - private void removeGenerationCommentFromConfig(ServerConfigXmlDocument doc, File serverXml) { - if (doc == null) { - return; - } - try { - doc.removeFMComment(FEATURES_FILE_MESSAGE); - doc.writeXMLDocument(serverXml); - } catch (IOException | TransformerException e) { - getLog().debug("Exception removing comment from server.xml", e); - } - return; - } - - /** - * Add a comment to server.xml to warn them we created another file with features in it. - * Only writes the file if the comment does not exist yet. - */ - private void addGenerationCommentToConfig(ServerConfigXmlDocument doc, File serverXml) { - if (doc == null) { - return; - } - try { - if (doc.createFMComment(FEATURES_FILE_MESSAGE)) { - doc.writeXMLDocument(serverXml); - XmlDocument.addNewlineBeforeFirstElement(serverXml); - } - } catch (IOException | TransformerException e) { - getLog().debug("Exception adding comment to server.xml", e); - } - return; - } - // Return a list containing the classes directory of the Maven projects (upstream projects and main project) private Set getClassesDirectories(List mavenProjects) throws MojoExecutionException { Set dirs = new HashSet(); From 6ba422588e942ff641e4ee3d2def5a7d7da96605 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 9 Apr 2025 18:09:46 -0400 Subject: [PATCH 004/103] Generate features into the server directory and not the src Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 42 ++++++++----------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 69aad2556..1c27c4799 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -75,10 +75,9 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { @Override protected void init() throws MojoExecutionException { - // @see io.openliberty.tools.maven.BasicSupport#init() skip server config - // setup as generate features does not require the server to be set up install - // dir, wlp dir, outputdir, etc. - this.skipServerConfigSetup = true; + // @see io.openliberty.tools.maven.BasicSupport#init() + // do not skip server config setup as generate features requires + // the server to be set up: install dir, wlp dir, outputdir, etc. super.init(); } @@ -182,10 +181,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // get existing server features from source directory ServerFeatureUtil servUtil = getServerFeatureUtil(true, null); - Set generatedFiles = new HashSet(); - generatedFiles.add(GENERATED_FEATURES_FILE_NAME); - - Set existingFeatures = getServerFeatures(servUtil, generatedFiles, optimize); + Set existingFeatures = getServerFeatures(servUtil); Set nonCustomFeatures = new HashSet(); // binary scanner only handles actual Liberty features for (String feature : existingFeatures) { // custom features are "usr:feature-1.0" or "myExt:feature-2.0" if (!feature.contains(":")) nonCustomFeatures.add(feature); @@ -214,8 +210,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } catch (BinaryScannerUtil.NoRecommendationException noRecommendation) { throw new MojoExecutionException(String.format(BinaryScannerUtil.BINARY_SCANNER_CONFLICT_MESSAGE3, noRecommendation.getConflicts())); } catch (BinaryScannerUtil.FeatureModifiedException featuresModified) { - Set userFeatures = (optimize) ? existingFeatures : - getServerFeatures(servUtil, generatedFiles, true); // user features excludes generatedFiles + Set userFeatures = (optimize) ? existingFeatures : getServerFeatures(servUtil); Set modifiedSet = featuresModified.getFeatures(); // a set that works after being modified by the scanner if (modifiedSet.containsAll(userFeatures)) { // none of the user features were modified, only features which were generated earlier. @@ -262,8 +257,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx servUtil.setLowerCaseFeatures(false); // get set of user defined features so they can be omitted from the generated // file that will be written - FeaturesPlatforms fp = servUtil.getServerFeatures(configDirectory, serverXmlFile, new HashMap(), - generatedFiles); + FeaturesPlatforms fp = servUtil.getServerFeatures(configDirectory, serverXmlFile, new HashMap(), null); Set userDefinedFeatures = optimize ? existingFeatures : (fp !=null) ? fp.getFeatures(): new HashSet(); getLog().debug("User defined features:" + userDefinedFeatures); servUtil.setLowerCaseFeatures(true); @@ -273,10 +267,10 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } getLog().debug("Features detected by binary scanner which are not in server.xml" + missingLibertyFeatures); - File newServerXmlSrc = new File(configDirectory, GENERATED_FEATURES_FILE_PATH); + File generatedXmlSrc = new File(serverDirectory, GENERATED_FEATURES_FILE_PATH); try { if (missingLibertyFeatures.size() > 0) { - Set existingGeneratedFeatures = getGeneratedFeatures(servUtil, newServerXmlSrc); + Set existingGeneratedFeatures = getGeneratedFeatures(servUtil, generatedXmlSrc); if (!missingLibertyFeatures.equals(existingGeneratedFeatures)) { // Create special XML file to contain generated features. ServerConfigXmlDocument configDocument = ServerConfigXmlDocument.newInstance(); @@ -289,21 +283,21 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } // Generate log message before writing file as the file change event kicks off other dev mode actions getLog().info("Generated the following features: " + missingLibertyFeatures); - configDocument.writeXMLDocument(newServerXmlSrc); - getLog().debug("Created file " + newServerXmlSrc); + configDocument.writeXMLDocument(generatedXmlSrc); + getLog().debug("Created file " + generatedXmlSrc); } else { getLog().info("Regenerated the following features: " + missingLibertyFeatures); } } else { getLog().info("No additional features were generated."); - if (newServerXmlSrc.exists()) { + if (generatedXmlSrc.exists()) { // generated-features.xml exists but no additional features were generated // create empty features list with comment ServerConfigXmlDocument configDocument = ServerConfigXmlDocument.newInstance(); configDocument.createComment(HEADER); Element featureManagerElem = configDocument.createFeatureManager(); configDocument.createComment(featureManagerElem, NO_NEW_FEATURES_COMMENT); - configDocument.writeXMLDocument(newServerXmlSrc); + configDocument.writeXMLDocument(generatedXmlSrc); } } } catch (ParserConfigurationException | TransformerException | IOException e) { @@ -316,13 +310,11 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } } - // Get the features from the server config and optionally exclude the specified config files from the search. - private Set getServerFeatures(ServerFeatureUtil servUtil, Set generatedFiles, boolean excludeGenerated) { + // Get the features from the server config + private Set getServerFeatures(ServerFeatureUtil servUtil) { servUtil.setLowerCaseFeatures(false); - // if optimizing, ignore generated files when passing in existing features to - // binary scanner FeaturesPlatforms fp = servUtil.getServerFeatures(configDirectory, serverXmlFile, - new HashMap(), excludeGenerated ? generatedFiles : null); // pass generatedFiles to exclude them + new HashMap(), null); servUtil.setLowerCaseFeatures(true); if (fp == null) { return new HashSet(); @@ -330,10 +322,10 @@ private Set getServerFeatures(ServerFeatureUtil servUtil, Set ge return fp.getFeatures(); } - // returns the features specified in the generated-features.xml file + // returns the features specified in the generated-features.xml file in the server directory private Set getGeneratedFeatures(ServerFeatureUtil servUtil, File generatedFeaturesFile) { servUtil.setLowerCaseFeatures(false); - FeaturesPlatforms result = servUtil.getServerXmlFeatures(new FeaturesPlatforms(), configDirectory, + FeaturesPlatforms result = servUtil.getServerXmlFeatures(new FeaturesPlatforms(), serverDirectory, generatedFeaturesFile, null, null); servUtil.setLowerCaseFeatures(true); Set features = new HashSet(); From 560cdebaa66432f1db7014482c63f855bf96b619 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 10 Apr 2025 14:25:32 -0400 Subject: [PATCH 005/103] Update the generated-features test Signed-off-by: Paul Gooderham --- .../net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java index f5d2c10bb..a884b06cb 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java @@ -67,7 +67,7 @@ public class BaseGenerateFeaturesTest { static File serverXmlFile; static final String GENERATED_FEATURES_FILE_NAME = "generated-features.xml"; - static final String GENERATED_FEATURES_FILE_PATH = "/src/main/liberty/config/configDropins/overrides/" + GENERATED_FEATURES_FILE_NAME; + static final String GENERATED_FEATURES_FILE_PATH = "/target/liberty/wlp/usr/servers/defaultServer/configDropins/overrides/" + GENERATED_FEATURES_FILE_NAME; protected static void setUpBeforeTest(String projectRoot) throws IOException, InterruptedException { basicProj = new File(projectRoot); From 83504c082e39ad5563e3ba07aed974466f701e21 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 10 Apr 2025 14:48:08 -0400 Subject: [PATCH 006/103] Update copyright Signed-off-by: Paul Gooderham --- .../net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java index a884b06cb..13248564f 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * (c) Copyright IBM Corporation 2022. + * (c) Copyright IBM Corporation 2022, 2025 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 8878a03a530a52d899b3d0c28b97938f73526f18 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 16 May 2025 16:25:23 -0400 Subject: [PATCH 007/103] Rework: getServerFeatures using serverDirectory not configDir Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 1c27c4799..99d44bfbb 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -78,6 +78,7 @@ protected void init() throws MojoExecutionException { // @see io.openliberty.tools.maven.BasicSupport#init() // do not skip server config setup as generate features requires // the server to be set up: install dir, wlp dir, outputdir, etc. + //this.skipServerConfigSetup = true; super.init(); } @@ -181,7 +182,10 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // get existing server features from source directory ServerFeatureUtil servUtil = getServerFeatureUtil(true, null); - Set existingFeatures = getServerFeatures(servUtil); + Set generatedFiles = new HashSet(); + generatedFiles.add(GENERATED_FEATURES_FILE_NAME); + + Set existingFeatures = getServerFeatures(servUtil, generatedFiles, optimize); Set nonCustomFeatures = new HashSet(); // binary scanner only handles actual Liberty features for (String feature : existingFeatures) { // custom features are "usr:feature-1.0" or "myExt:feature-2.0" if (!feature.contains(":")) nonCustomFeatures.add(feature); @@ -210,7 +214,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } catch (BinaryScannerUtil.NoRecommendationException noRecommendation) { throw new MojoExecutionException(String.format(BinaryScannerUtil.BINARY_SCANNER_CONFLICT_MESSAGE3, noRecommendation.getConflicts())); } catch (BinaryScannerUtil.FeatureModifiedException featuresModified) { - Set userFeatures = (optimize) ? existingFeatures : getServerFeatures(servUtil); + Set userFeatures = (optimize) ? existingFeatures : + getServerFeatures(servUtil, generatedFiles, true); // user features excludes generatedFiles Set modifiedSet = featuresModified.getFeatures(); // a set that works after being modified by the scanner if (modifiedSet.containsAll(userFeatures)) { // none of the user features were modified, only features which were generated earlier. @@ -257,7 +262,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx servUtil.setLowerCaseFeatures(false); // get set of user defined features so they can be omitted from the generated // file that will be written - FeaturesPlatforms fp = servUtil.getServerFeatures(configDirectory, serverXmlFile, new HashMap(), null); + FeaturesPlatforms fp = servUtil.getServerFeatures(configDirectory, serverXmlFile, new HashMap(), + generatedFiles); Set userDefinedFeatures = optimize ? existingFeatures : (fp !=null) ? fp.getFeatures(): new HashSet(); getLog().debug("User defined features:" + userDefinedFeatures); servUtil.setLowerCaseFeatures(true); @@ -267,10 +273,10 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } getLog().debug("Features detected by binary scanner which are not in server.xml" + missingLibertyFeatures); - File generatedXmlSrc = new File(serverDirectory, GENERATED_FEATURES_FILE_PATH); + File generatedXmlFile = new File(serverDirectory, GENERATED_FEATURES_FILE_PATH); try { if (missingLibertyFeatures.size() > 0) { - Set existingGeneratedFeatures = getGeneratedFeatures(servUtil, generatedXmlSrc); + Set existingGeneratedFeatures = getGeneratedFeatures(servUtil, generatedXmlFile); if (!missingLibertyFeatures.equals(existingGeneratedFeatures)) { // Create special XML file to contain generated features. ServerConfigXmlDocument configDocument = ServerConfigXmlDocument.newInstance(); @@ -283,21 +289,21 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } // Generate log message before writing file as the file change event kicks off other dev mode actions getLog().info("Generated the following features: " + missingLibertyFeatures); - configDocument.writeXMLDocument(generatedXmlSrc); - getLog().debug("Created file " + generatedXmlSrc); + configDocument.writeXMLDocument(generatedXmlFile); + getLog().debug("Created file " + generatedXmlFile); } else { getLog().info("Regenerated the following features: " + missingLibertyFeatures); } } else { getLog().info("No additional features were generated."); - if (generatedXmlSrc.exists()) { + if (generatedXmlFile.exists()) { // generated-features.xml exists but no additional features were generated // create empty features list with comment ServerConfigXmlDocument configDocument = ServerConfigXmlDocument.newInstance(); configDocument.createComment(HEADER); Element featureManagerElem = configDocument.createFeatureManager(); configDocument.createComment(featureManagerElem, NO_NEW_FEATURES_COMMENT); - configDocument.writeXMLDocument(generatedXmlSrc); + configDocument.writeXMLDocument(generatedXmlFile); } } } catch (ParserConfigurationException | TransformerException | IOException e) { @@ -310,11 +316,13 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } } - // Get the features from the server config - private Set getServerFeatures(ServerFeatureUtil servUtil) { + // Get the features from the server config and optionally exclude the specified config files from the search. + private Set getServerFeatures(ServerFeatureUtil servUtil, Set generatedFiles, boolean excludeGenerated) { servUtil.setLowerCaseFeatures(false); - FeaturesPlatforms fp = servUtil.getServerFeatures(configDirectory, serverXmlFile, - new HashMap(), null); + // if optimizing, ignore generated files when passing in existing features to + // binary scanner + FeaturesPlatforms fp = servUtil.getServerFeatures(serverDirectory, serverXmlFile, + new HashMap(), excludeGenerated ? generatedFiles : null); // pass generatedFiles to exclude them servUtil.setLowerCaseFeatures(true); if (fp == null) { return new HashSet(); From 1c7358355a58313cedeee4202f88eb849086ef3c Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 14 May 2025 16:40:31 -0400 Subject: [PATCH 008/103] Add generateToSrc option to GenerateFeaturesMojo Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 99d44bfbb..66ffd9f94 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -73,6 +73,13 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { @Parameter(property = "optimize", defaultValue = "true") private boolean optimize; + /** + * If generateToSrc is true, then create the file containing new features in the src directory + * Otherwise, place the file in the target directory where the Liberty server is defined. + */ + @Parameter(property = "generateToSrc", defaultValue = "false") + private boolean generateToSrc; + @Override protected void init() throws MojoExecutionException { // @see io.openliberty.tools.maven.BasicSupport#init() @@ -273,7 +280,12 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } getLog().debug("Features detected by binary scanner which are not in server.xml" + missingLibertyFeatures); - File generatedXmlFile = new File(serverDirectory, GENERATED_FEATURES_FILE_PATH); + File generatedXmlFile; + if (generateToSrc) { + generatedXmlFile = new File(configDirectory, GENERATED_FEATURES_FILE_PATH); + } else { + generatedXmlFile = new File(serverDirectory, GENERATED_FEATURES_FILE_PATH); + } try { if (missingLibertyFeatures.size() > 0) { Set existingGeneratedFeatures = getGeneratedFeatures(servUtil, generatedXmlFile); From edf00e222bb2270850ee45105e191772921d483d Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 14 May 2025 18:22:36 -0400 Subject: [PATCH 009/103] Add a test for the generateToSrc option Signed-off-by: Paul Gooderham --- .../wlp/test/dev/it/BaseGenerateFeaturesTest.java | 7 +++++++ .../wlp/test/dev/it/GenerateFeaturesTest.java | 14 +++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java index 13248564f..c9cdff980 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java @@ -63,11 +63,13 @@ public class BaseGenerateFeaturesTest { static File targetDir; static String processOutput = ""; static File newFeatureFile; + static File newFeatureFileSrc; static File pom; static File serverXmlFile; static final String GENERATED_FEATURES_FILE_NAME = "generated-features.xml"; static final String GENERATED_FEATURES_FILE_PATH = "/target/liberty/wlp/usr/servers/defaultServer/configDropins/overrides/" + GENERATED_FEATURES_FILE_NAME; + static final String GENERATED_FEATURES_FILE_PATH_SRC = "/src/main/liberty/config/configDropins/overrides/" + GENERATED_FEATURES_FILE_NAME; protected static void setUpBeforeTest(String projectRoot) throws IOException, InterruptedException { basicProj = new File(projectRoot); @@ -81,6 +83,7 @@ protected static void setUpBeforeTest(String projectRoot) throws IOException, In assertTrue(logFile.createNewFile()); newFeatureFile = new File(tempProj, GENERATED_FEATURES_FILE_PATH); + newFeatureFileSrc = new File(tempProj, GENERATED_FEATURES_FILE_PATH_SRC); pom = new File(tempProj, "pom.xml"); assertTrue(pom.exists()); replaceVersion(tempProj); @@ -226,6 +229,10 @@ protected void runCompileAndGenerateFeatures() throws IOException, InterruptedEx runProcess("compile liberty:generate-features"); } + protected void runCompileAndGenerateFeaturesToSrc() throws IOException, InterruptedException { + runProcess("compile liberty:generate-features -DgenerateToSrc=true"); + } + protected void runGenerateFeaturesGoal() throws IOException, InterruptedException { runProcess("liberty:generate-features"); } diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java index 379a66bba..d8462d514 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * (c) Copyright IBM Corporation 2022. + * (c) Copyright IBM Corporation 2022, 2025 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -79,6 +79,18 @@ public void basicTest() throws Exception { assertEquals(0, features.size()); } + @Test + public void generateToSrcTest() throws Exception { + newFeatureFile.delete(); // delete file if it exists but do not assert + assertFalse(newFeatureFileSrc.exists()); + runCompileAndGenerateFeaturesToSrc(); + + // verify that the generated features file was created + // Assume the contents are correct based on prior testing + assertTrue(formatOutput(processOutput), newFeatureFileSrc.exists()); + assertTrue(newFeatureFileSrc.delete()); + } + @Test public void noClassFiles() throws Exception { // do not compile before running generate-features From 9591269506a6e088491c738c382a99ad0b7a9b23 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 15 May 2025 11:13:32 -0400 Subject: [PATCH 010/103] Update MultiModuleGenerateFeaturesTest for directory change Signed-off-by: Paul Gooderham --- .../wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java index 707420936..95f621cf7 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java @@ -40,6 +40,7 @@ public void setUp() throws Exception { assertTrue(pom.exists()); replaceVersion(new File(tempProj, "pom")); // "pom" module is liberty configuration module newFeatureFile = new File(tempProj, "pom" + GENERATED_FEATURES_FILE_PATH); + newFeatureFileSrc = new File(tempProj, "pom" + GENERATED_FEATURES_FILE_PATH_SRC); serverXmlFile = new File(tempProj, "pom/src/main/liberty/config/server.xml"); targetDir = new File(tempProj, "war/target"); runProcess("install"); From ef244ce6a33ffaaae390cbff8092ccf179896267 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 20 May 2025 16:08:41 -0400 Subject: [PATCH 011/103] Introduce the concept of the directory that is the subject of generate features Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 66ffd9f94..c897c96a6 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -61,6 +61,7 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { public static final String NO_CLASSES_DIR_WARNING = "Could not find classes directory to generate features against. Liberty features will not be generated. " + "Ensure your project has first been compiled."; + // The executable file used to scan binaries for the Liberty features they use. private File binaryScanner; @Parameter(property = "classFiles") @@ -79,6 +80,14 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { */ @Parameter(property = "generateToSrc", defaultValue = "false") private boolean generateToSrc; + /** + * Generating features is performed relative to a certain server. We only generate features + * that are missing from a server config. By default we generate features that are missing + * from the server directory in the Liberty directory. If generateToSrc is specified then + * we generate features which are missing from the Liberty config specified in the src directory + * (src/main/liberty/config). We will select one server config as the subject of this operation. + */ + private File subjectServerDir; @Override protected void init() throws MojoExecutionException { @@ -159,6 +168,13 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } } + // The config dir is in the src directory. Otherwise generate for the target dir. + if (generateToSrc) { + subjectServerDir = configDirectory; + } else { + subjectServerDir = serverDirectory; + } + binaryScanner = getBinaryScannerJarFromRepository(); BinaryScannerHandler binaryScannerHandler = new BinaryScannerHandler(binaryScanner); @@ -269,7 +285,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx servUtil.setLowerCaseFeatures(false); // get set of user defined features so they can be omitted from the generated // file that will be written - FeaturesPlatforms fp = servUtil.getServerFeatures(configDirectory, serverXmlFile, new HashMap(), + FeaturesPlatforms fp = servUtil.getServerFeatures(subjectServerDir, serverXmlFile, new HashMap(), generatedFiles); Set userDefinedFeatures = optimize ? existingFeatures : (fp !=null) ? fp.getFeatures(): new HashSet(); getLog().debug("User defined features:" + userDefinedFeatures); @@ -333,7 +349,7 @@ private Set getServerFeatures(ServerFeatureUtil servUtil, Set ge servUtil.setLowerCaseFeatures(false); // if optimizing, ignore generated files when passing in existing features to // binary scanner - FeaturesPlatforms fp = servUtil.getServerFeatures(serverDirectory, serverXmlFile, + FeaturesPlatforms fp = servUtil.getServerFeatures(subjectServerDir, serverXmlFile, new HashMap(), excludeGenerated ? generatedFiles : null); // pass generatedFiles to exclude them servUtil.setLowerCaseFeatures(true); if (fp == null) { @@ -345,7 +361,7 @@ private Set getServerFeatures(ServerFeatureUtil servUtil, Set ge // returns the features specified in the generated-features.xml file in the server directory private Set getGeneratedFeatures(ServerFeatureUtil servUtil, File generatedFeaturesFile) { servUtil.setLowerCaseFeatures(false); - FeaturesPlatforms result = servUtil.getServerXmlFeatures(new FeaturesPlatforms(), serverDirectory, + FeaturesPlatforms result = servUtil.getServerXmlFeatures(new FeaturesPlatforms(), subjectServerDir, generatedFeaturesFile, null, null); servUtil.setLowerCaseFeatures(true); Set features = new HashSet(); From 98cb17977e28660e1820609306d98caaab5e2f9d Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 21 May 2025 17:53:04 -0400 Subject: [PATCH 012/103] Add generationContextDir and use consistently to generate features Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index c897c96a6..e6072402d 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -83,18 +83,22 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { /** * Generating features is performed relative to a certain server. We only generate features * that are missing from a server config. By default we generate features that are missing - * from the server directory in the Liberty directory. If generateToSrc is specified then - * we generate features which are missing from the Liberty config specified in the src directory - * (src/main/liberty/config). We will select one server config as the subject of this operation. + * from the server directory in target/liberty/wlp/usr/servers/. + * If generateToSrc is specified then we generate features which are missing from the Liberty + * config specified in the src directory src/main/liberty/config. + * We will select one server config as the context of this operation. */ - private File subjectServerDir; + private File generationContextDir; @Override protected void init() throws MojoExecutionException { // @see io.openliberty.tools.maven.BasicSupport#init() - // do not skip server config setup as generate features requires - // the server to be set up: install dir, wlp dir, outputdir, etc. - //this.skipServerConfigSetup = true; + // Skip server directories setup when generate features only requires + // the files in the src config directory. + // The server directories to be set up: install dir, wlp dir, outputdir, etc. + if (generateToSrc) { + this.skipServerConfigSetup = true; + } super.init(); } @@ -115,7 +119,7 @@ public void execute() throws MojoExecutionException { } /** - * Generates features for the application given the API usage detected and + * Generates features for the application given the API usage detected by the binary scanner and * taking any user specified features into account * * @throws MojoExecutionException @@ -168,12 +172,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } } - // The config dir is in the src directory. Otherwise generate for the target dir. - if (generateToSrc) { - subjectServerDir = configDirectory; - } else { - subjectServerDir = serverDirectory; - } + // The config dir is in the src directory. Otherwise generate for the target/liberty dir. + generationContextDir = generateToSrc ? configDirectory : serverDirectory; binaryScanner = getBinaryScannerJarFromRepository(); BinaryScannerHandler binaryScannerHandler = new BinaryScannerHandler(binaryScanner); @@ -181,6 +181,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("--- Generate Features values ---"); getLog().debug("Binary scanner jar: " + binaryScanner.getName()); getLog().debug("optimize generate features: " + optimize); + getLog().debug("generate to src or target: " + generationContextDir); if (classFiles != null && !classFiles.isEmpty()) { getLog().debug("Generate features for the following class files: " + classFiles.toString()); } @@ -202,7 +203,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // getSpecifiedFeatures may not return the features in the correct case // Set featuresToInstall = getSpecifiedFeatures(null); - // get existing server features from source directory + // get existing server features from directory of interest ServerFeatureUtil servUtil = getServerFeatureUtil(true, null); Set generatedFiles = new HashSet(); @@ -285,7 +286,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx servUtil.setLowerCaseFeatures(false); // get set of user defined features so they can be omitted from the generated // file that will be written - FeaturesPlatforms fp = servUtil.getServerFeatures(subjectServerDir, serverXmlFile, new HashMap(), + FeaturesPlatforms fp = servUtil.getServerFeatures(generationContextDir, serverXmlFile, new HashMap(), generatedFiles); Set userDefinedFeatures = optimize ? existingFeatures : (fp !=null) ? fp.getFeatures(): new HashSet(); getLog().debug("User defined features:" + userDefinedFeatures); @@ -349,7 +350,7 @@ private Set getServerFeatures(ServerFeatureUtil servUtil, Set ge servUtil.setLowerCaseFeatures(false); // if optimizing, ignore generated files when passing in existing features to // binary scanner - FeaturesPlatforms fp = servUtil.getServerFeatures(subjectServerDir, serverXmlFile, + FeaturesPlatforms fp = servUtil.getServerFeatures(generationContextDir, serverXmlFile, new HashMap(), excludeGenerated ? generatedFiles : null); // pass generatedFiles to exclude them servUtil.setLowerCaseFeatures(true); if (fp == null) { @@ -361,7 +362,7 @@ private Set getServerFeatures(ServerFeatureUtil servUtil, Set ge // returns the features specified in the generated-features.xml file in the server directory private Set getGeneratedFeatures(ServerFeatureUtil servUtil, File generatedFeaturesFile) { servUtil.setLowerCaseFeatures(false); - FeaturesPlatforms result = servUtil.getServerXmlFeatures(new FeaturesPlatforms(), subjectServerDir, + FeaturesPlatforms result = servUtil.getServerXmlFeatures(new FeaturesPlatforms(), generationContextDir, generatedFeaturesFile, null, null); servUtil.setLowerCaseFeatures(true); Set features = new HashSet(); From e101410c82b5f47f1f56f4e32cbc7809680ce274 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 21 May 2025 18:47:22 -0400 Subject: [PATCH 013/103] Simplify file name of generated xml file Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index e6072402d..41a2b9978 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -297,12 +297,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } getLog().debug("Features detected by binary scanner which are not in server.xml" + missingLibertyFeatures); - File generatedXmlFile; - if (generateToSrc) { - generatedXmlFile = new File(configDirectory, GENERATED_FEATURES_FILE_PATH); - } else { - generatedXmlFile = new File(serverDirectory, GENERATED_FEATURES_FILE_PATH); - } + // generate the new features into an xml file in the correct context directory + File generatedXmlFile = new File(generationContextDir, GENERATED_FEATURES_FILE_PATH); try { if (missingLibertyFeatures.size() > 0) { Set existingGeneratedFeatures = getGeneratedFeatures(servUtil, generatedXmlFile); From b201d6e9d2f84a086093de86500af80ca1a0dc82 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 22 May 2025 14:15:18 -0400 Subject: [PATCH 014/103] generateToSrcTest adds basic feature generation checks Signed-off-by: Paul Gooderham --- .../test/dev/it/BaseGenerateFeaturesTest.java | 8 +++++-- .../wlp/test/dev/it/GenerateFeaturesTest.java | 24 ++++++++++--------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java index c9cdff980..264210e7b 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java @@ -233,8 +233,12 @@ protected void runCompileAndGenerateFeaturesToSrc() throws IOException, Interrup runProcess("compile liberty:generate-features -DgenerateToSrc=true"); } - protected void runGenerateFeaturesGoal() throws IOException, InterruptedException { - runProcess("liberty:generate-features"); + protected void runGenerateFeaturesGoal(String options) throws IOException, InterruptedException { + String parameters = "liberty:generate-features "; + if (options != null) { + parameters += options; + } + runProcess(parameters); } // Format the output to help debug test failures. diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java index d8462d514..31d1928fb 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java @@ -53,14 +53,18 @@ public void cleanUp() throws Exception { @Test public void basicTest() throws Exception { runCompileAndGenerateFeatures(); - // verify that the target directory was created + executeBasicTests(newFeatureFile, ""); + } + + private void executeBasicTests(File featureFile, String options) { + // verify that the target directory was created by compile goal assertTrue(targetDir.exists()); // verify that the generated features file was created - assertTrue(formatOutput(processOutput), newFeatureFile.exists()); + assertTrue(formatOutput(processOutput), featureFile.exists()); // verify that the correct features are in the generated-features.xml - Set features = readFeatures(newFeatureFile); + Set features = readFeatures(featureFile); Set expectedFeatures = getExpectedGeneratedFeaturesSet(); assertEquals(expectedFeatures.size(), features.size()); assertEquals(expectedFeatures, features); @@ -72,23 +76,21 @@ public void basicTest() throws Exception { "\n", serverXmlFile); - runGenerateFeaturesGoal(); + runGenerateFeaturesGoal(options); // no additional features should be generated - assertTrue(newFeatureFile.exists()); - features = readFeatures(newFeatureFile); + assertTrue(featureFile.exists()); + features = readFeatures(featureFile); assertEquals(0, features.size()); } @Test public void generateToSrcTest() throws Exception { newFeatureFile.delete(); // delete file if it exists but do not assert - assertFalse(newFeatureFileSrc.exists()); + assertFalse(newFeatureFileSrc.exists()); // assuming no other test creates this file runCompileAndGenerateFeaturesToSrc(); - // verify that the generated features file was created - // Assume the contents are correct based on prior testing - assertTrue(formatOutput(processOutput), newFeatureFileSrc.exists()); - assertTrue(newFeatureFileSrc.delete()); + executeBasicTests(newFeatureFileSrc, "-DgenerateToSrc=true"); + assertTrue(newFeatureFileSrc.delete()); // clean up the generated file } @Test From 1267a36b99364be6d350f5394a90b294587f2e4b Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 22 May 2025 15:41:28 -0400 Subject: [PATCH 015/103] Fix copyright Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index fcb63c7b4..3f699300c 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2021, 2025. + * (C) Copyright IBM Corporation 2021, 2024. * * 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 From 889ce92aab23a4eb5a5443ed4c43d835513e95c0 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 22 May 2025 15:45:58 -0400 Subject: [PATCH 016/103] Fix bug in GenerateFeaturesTest Signed-off-by: Paul Gooderham --- .../java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java index 31d1928fb..3ba8dccaa 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java @@ -96,7 +96,7 @@ public void generateToSrcTest() throws Exception { @Test public void noClassFiles() throws Exception { // do not compile before running generate-features - runGenerateFeaturesGoal(); + runGenerateFeaturesGoal(""); // verify that generated features file was not created assertFalse(newFeatureFile.exists()); From 8f0023e8a41e624d0d941984bf439e4afc4a7ff2 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 23 May 2025 17:30:20 -0400 Subject: [PATCH 017/103] Display a message specifically for generate features when serverDir is missing Signed-off-by: Paul Gooderham --- .../openliberty/tools/maven/server/GenerateFeaturesMojo.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 3f699300c..258e8cd20 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -88,8 +88,9 @@ protected void init() throws MojoExecutionException { super.init(); // Ensure server dir exists to generate features to the $serverDirectory/configDropins/overrides/generated-features.xml - checkServerHomeExists(); - checkServerDirectoryExists(); + if (!serverDirectory.exists()) { + throw new MojoExecutionException("GenerateFeatures goal requires the Liberty server but unable to find server path " + serverDirectory.getPath() + ". Please execute the goal liberty:create."); + } } @Override From 006feb4c4adeef2da9f8c555dd2a66c950663284 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 26 May 2025 18:17:12 -0400 Subject: [PATCH 018/103] Improve error message Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 258e8cd20..7f57909f5 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -89,7 +89,7 @@ protected void init() throws MojoExecutionException { super.init(); // Ensure server dir exists to generate features to the $serverDirectory/configDropins/overrides/generated-features.xml if (!serverDirectory.exists()) { - throw new MojoExecutionException("GenerateFeatures goal requires the Liberty server but unable to find server path " + serverDirectory.getPath() + ". Please execute the goal liberty:create."); + throw new MojoExecutionException("The 'generate-features' goal requires a Liberty server, but the server configuration was not found at " + serverDirectory.getPath() + ". To resolve this issue, please run the 'liberty:create' goal first to create a server."); } } From 0de255fb7b75ac0ad407f130ebf3a4c7a0012b6a Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 26 May 2025 18:34:03 -0400 Subject: [PATCH 019/103] Clarify comment Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 41a2b9978..faef1d18d 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -355,7 +355,7 @@ private Set getServerFeatures(ServerFeatureUtil servUtil, Set ge return fp.getFeatures(); } - // returns the features specified in the generated-features.xml file in the server directory + // returns the features specified in the generated-features.xml file in the generation context directory private Set getGeneratedFeatures(ServerFeatureUtil servUtil, File generatedFeaturesFile) { servUtil.setLowerCaseFeatures(false); FeaturesPlatforms result = servUtil.getServerXmlFeatures(new FeaturesPlatforms(), generationContextDir, From d91edae1d5ae8f2c26298780d2b378bf5ffcf297 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 11 Jun 2025 18:32:32 -0400 Subject: [PATCH 020/103] Add internal option to support devmode in generate features mojo Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index faef1d18d..57281f604 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -80,6 +80,16 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { */ @Parameter(property = "generateToSrc", defaultValue = "false") private boolean generateToSrc; + + /** + * The internalDevMode parameter is for internal use only. It is not for users. + * The parameter is only used when generateToSrc is false meaning we generate to serverDir. + * When the parameter is true we will write the generated features file to the temp directory. + * This is required because the features must all be installed before writing to server Dir in devmode. + */ + @Parameter(property = "internalDevMode", defaultValue = "false") + private boolean internalDevMode; + /** * Generating features is performed relative to a certain server. We only generate features * that are missing from a server config. By default we generate features that are missing @@ -298,7 +308,14 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("Features detected by binary scanner which are not in server.xml" + missingLibertyFeatures); // generate the new features into an xml file in the correct context directory - File generatedXmlFile = new File(generationContextDir, GENERATED_FEATURES_FILE_PATH); + File generatedXmlFile; + if (internalDevMode) { + // create a temp dir in the target directory for the generated-features.xml in dev mode + // The ServerConfigXmlDocument will create the directories if needed. + generatedXmlFile = new File(project.getBuild().getDirectory(), GENERATED_FEATURES_TEMP_PATH); + } else { + generatedXmlFile = new File(generationContextDir, GENERATED_FEATURES_FILE_PATH); + } try { if (missingLibertyFeatures.size() > 0) { Set existingGeneratedFeatures = getGeneratedFeatures(servUtil, generatedXmlFile); From f5f3cf5249ac41be5836144706f6aeec43c54303 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 28 May 2025 18:26:20 -0400 Subject: [PATCH 021/103] Add generateToSrc option to dev mode Signed-off-by: Paul Gooderham --- .../openliberty/tools/maven/server/DevMojo.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) 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 f46d98a90..f1f35b20a 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 @@ -135,8 +135,15 @@ public class DevMojo extends LooseAppSupport { @Parameter(property = "container", defaultValue = "false") private boolean container; - @Parameter(property = "generateFeatures", defaultValue = "false") - private boolean generateFeatures; + @Parameter(property = "generateFeatures", defaultValue = "false") + private boolean generateFeatures; + + /** + * If generateToSrc is true, then create the file containing new features in the src directory + * Otherwise, place the file in the target directory where the Liberty server is defined. + */ + @Parameter(property = "generateToSrc", defaultValue = "false") + private boolean generateToSrc; /** * Whether to recompile dependencies. Defaults to false for single module @@ -351,7 +358,7 @@ public DevMojoUtil(File installDir, File userDir, File serverDirectory, File sou File testSourceDirectory, File configDirectory, File projectDirectory, File multiModuleProjectDirectory, List resourceDirs, JavaCompilerOptions compilerOptions, String mavenCacheLocation, List upstreamProjects, List upstreamMavenProjects, boolean recompileDeps, - File pom, Map> parentPoms, boolean generateFeatures, boolean skipInstallFeature, + File pom, Map> parentPoms, boolean generateFeatures, boolean generateToSrc, boolean skipInstallFeature, Set compileArtifactPaths, Set testArtifactPaths, List webResourceDirs, File serverOutputDirectory) throws IOException, PluginExecutionException { super(new File(project.getBuild().getDirectory()), serverDirectory, sourceDirectory, testSourceDirectory, configDirectory, projectDirectory, multiModuleProjectDirectory, resourceDirs, changeOnDemandTestsAction, hotTests, skipTests, @@ -359,7 +366,7 @@ public DevMojoUtil(File installDir, File userDir, File serverDirectory, File sou ((long) (compileWait * 1000L)), libertyDebug, false, false, pollingTest, container, containerfile, containerBuildContext, containerRunOpts, containerBuildTimeout, skipDefaultPorts, compilerOptions, keepTempContainerfile, mavenCacheLocation, upstreamProjects, recompileDeps, project.getPackaging(), - pom, parentPoms, generateFeatures, compileArtifactPaths, testArtifactPaths, webResourceDirs, compileMojoError); + pom, parentPoms, generateFeatures, generateToSrc, compileArtifactPaths, testArtifactPaths, webResourceDirs, compileMojoError); this.libertyDirPropertyFiles = LibertyPropFilesUtility.getLibertyDirectoryPropertyFiles(new CommonLogger(getLog()), installDir, userDir, serverDirectory, serverOutputDirectory); @@ -1646,7 +1653,7 @@ private void doDevMode() throws MojoExecutionException { util = new DevMojoUtil(installDirectory, userDirectory, serverDirectory, sourceDirectory, testSourceDirectory, configDirectory, project.getBasedir(), multiModuleProjectDirectory, resourceDirs, compilerOptions, settings.getLocalRepository(), upstreamProjects, upstreamMavenProjects, recompileDeps, pom, parentPoms, - generateFeatures, skipInstallFeature, compileArtifactPaths, testArtifactPaths, webResourceDirs, new File(super.outputDirectory,serverName)); + generateFeatures, generateToSrc, skipInstallFeature, compileArtifactPaths, testArtifactPaths, webResourceDirs, new File(super.outputDirectory,serverName)); } catch (IOException | PluginExecutionException |DependencyResolutionRequiredException e) { throw new MojoExecutionException("Error initializing dev mode.", e); } From 75dbf3e0feca0e009bdcc3f14ea79cb44fdd9bf4 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 2 Jul 2025 17:23:53 -0400 Subject: [PATCH 022/103] Rewrite the error message for missing server directory Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 7f57909f5..cad50db66 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -89,7 +89,7 @@ protected void init() throws MojoExecutionException { super.init(); // Ensure server dir exists to generate features to the $serverDirectory/configDropins/overrides/generated-features.xml if (!serverDirectory.exists()) { - throw new MojoExecutionException("The 'generate-features' goal requires a Liberty server, but the server configuration was not found at " + serverDirectory.getPath() + ". To resolve this issue, please run the 'liberty:create' goal first to create a server."); + throw new MojoExecutionException("The 'generate-features' goal requires an existing Liberty server in directory " + serverDirectory.getPath() + ". Please run the 'liberty:create' goal before 'generate-features'."); } } From f0af8526135f5271e664518322fc77305934c4c1 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 10 Jul 2025 14:21:57 -0400 Subject: [PATCH 023/103] Add test for missing server directory for generate features Signed-off-by: Paul Gooderham --- .../wlp/test/dev/it/BaseGenerateFeaturesTest.java | 1 + .../wasdev/wlp/test/dev/it/GenerateFeaturesTest.java | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java index f5d2c10bb..9ec355fe1 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java @@ -68,6 +68,7 @@ public class BaseGenerateFeaturesTest { static final String GENERATED_FEATURES_FILE_NAME = "generated-features.xml"; static final String GENERATED_FEATURES_FILE_PATH = "/src/main/liberty/config/configDropins/overrides/" + GENERATED_FEATURES_FILE_NAME; + static final String SERVER_MISSING_MESSAGE = "The 'generate-features' goal requires an existing Liberty server"; protected static void setUpBeforeTest(String projectRoot) throws IOException, InterruptedException { basicProj = new File(projectRoot); diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java index 379a66bba..77751db5d 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java @@ -91,6 +91,18 @@ public void noClassFiles() throws Exception { assertTrue(processOutput.contains(GenerateFeaturesMojo.NO_CLASSES_DIR_WARNING)); } + @Test + public void noServer() throws Exception { + // do not create the server before running generate-features + runGenerateFeaturesGoal(); + + // verify that generated features file was not created + assertFalse(newFeatureFile.exists()); + + // verify server not found warning message + assertTrue(processOutput.contains(SERVER_MISSING_MESSAGE)); + } + @Test public void customFeaturesTest() throws Exception { // complete the setup of the test From 9ef2e685e2a4d416ec67ad3aaef51624b019db06 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 2 Jun 2025 18:43:34 -0400 Subject: [PATCH 024/103] Create server before generate features if required Signed-off-by: Paul Gooderham --- .../java/io/openliberty/tools/maven/server/DevMojo.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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 f1f35b20a..01f4ba207 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 @@ -1522,6 +1522,11 @@ private void doDevMode() throws MojoExecutionException { getLog().info("Running boost:package"); runBoostMojo("package"); } else { + // If generate features to serverDir then create server first. + // If generate features is false it does not matter whether create runs here or below. + if (!generateToSrc) { + runLibertyMojoCreate(); + } if (generateFeatures) { // generate features on startup - provide all classes and only user specified // features to binary scanner @@ -1550,7 +1555,9 @@ private void doDevMode() throws MojoExecutionException { } } } - runLibertyMojoCreate(); + if (generateToSrc) { + runLibertyMojoCreate(); + } // If non-container, install features before starting server. Otherwise, user // should have "RUN features.sh" in their Containerfile/Dockerfile if they want features to be // installed. From 09e94543ab1833d15e7d3fe5ab8f052a35a5f084 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 3 Jun 2025 10:23:32 -0400 Subject: [PATCH 025/103] Clarify dev mode startup mojos for generateToSrc Signed-off-by: Paul Gooderham --- .../tools/maven/server/DevMojo.java | 69 ++++++++++--------- 1 file changed, 36 insertions(+), 33 deletions(-) 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 01f4ba207..05bfb4a9b 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 @@ -1522,42 +1522,16 @@ private void doDevMode() throws MojoExecutionException { getLog().info("Running boost:package"); runBoostMojo("package"); } else { - // If generate features to serverDir then create server first. - // If generate features is false it does not matter whether create runs here or below. - if (!generateToSrc) { - runLibertyMojoCreate(); - } + // If generate features to server directory then create server first. if (generateFeatures) { - // generate features on startup - provide all classes and only user specified - // features to binary scanner - try { - String generatedFileCanonicalPath; - try { - generatedFileCanonicalPath = new File(configDirectory, - BinaryScannerUtil.GENERATED_FEATURES_FILE_PATH).getCanonicalPath(); - } catch (IOException e) { - generatedFileCanonicalPath = new File(configDirectory, - BinaryScannerUtil.GENERATED_FEATURES_FILE_PATH).toString(); - } - getLog().warn( - "The source configuration directory will be modified. Features will automatically be generated in a new file: " - + generatedFileCanonicalPath); - runLibertyMojoGenerateFeatures(null, true); - } catch (MojoExecutionException e) { - if (e.getCause() != null && e.getCause() instanceof PluginExecutionException) { - // PluginExecutionException indicates that the binary scanner jar could not be found - getLog().error(e.getMessage() + ".\nDisabling the automatic generation of features."); - generateFeatures = false; - } else { - throw new MojoExecutionException(e.getMessage() - + " To disable the automatic generation of features, start dev mode with -DgenerateFeatures=false.", - e); - } + if (generateToSrc) { + generateFeaturesOnStartup(); + runLibertyMojoCreate(); + } else { + runLibertyMojoCreate(); + generateFeaturesOnStartup(); } } - if (generateToSrc) { - runLibertyMojoCreate(); - } // If non-container, install features before starting server. Otherwise, user // should have "RUN features.sh" in their Containerfile/Dockerfile if they want features to be // installed. @@ -1693,6 +1667,35 @@ private void doDevMode() throws MojoExecutionException { } } + private void generateFeaturesOnStartup() throws MojoExecutionException { + // generate features on startup - provide all classes and only user specified + // features to binary scanner + try { + String generatedFileCanonicalPath; + try { + generatedFileCanonicalPath = new File(configDirectory, + BinaryScannerUtil.GENERATED_FEATURES_FILE_PATH).getCanonicalPath(); + } catch (IOException e) { + generatedFileCanonicalPath = new File(configDirectory, + BinaryScannerUtil.GENERATED_FEATURES_FILE_PATH).toString(); + } + getLog().warn( + "The source configuration directory will be modified. Features will automatically be generated in a new file: " + + generatedFileCanonicalPath); + runLibertyMojoGenerateFeatures(null, true); + } catch (MojoExecutionException e) { + if (e.getCause() != null && e.getCause() instanceof PluginExecutionException) { + // PluginExecutionException indicates that the binary scanner jar could not be found + getLog().error(e.getMessage() + ".\nDisabling the automatic generation of features."); + generateFeatures = false; + } else { + throw new MojoExecutionException(e.getMessage() + + " To disable the automatic generation of features, start dev mode with -DgenerateFeatures=false.", + e); + } + } + } + @Override public void execute() throws MojoExecutionException { init(); From 173d2d66bdbdebbe19ead969ae37da73564b9bbf Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 3 Jun 2025 14:53:38 -0400 Subject: [PATCH 026/103] Fix bug in regular path Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 2 ++ 1 file changed, 2 insertions(+) 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 05bfb4a9b..46d3b402d 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 @@ -1531,6 +1531,8 @@ private void doDevMode() throws MojoExecutionException { runLibertyMojoCreate(); generateFeaturesOnStartup(); } + } else { + runLibertyMojoCreate(); } // If non-container, install features before starting server. Otherwise, user // should have "RUN features.sh" in their Containerfile/Dockerfile if they want features to be From e51dc0937e3d48acdf680a658ca08fbf5d220150 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 16 Jun 2025 10:38:41 -0400 Subject: [PATCH 027/103] Use the internalDevMode option when calling generate-features Signed-off-by: Paul Gooderham --- .../openliberty/tools/maven/server/StartDebugMojoSupport.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 39686c2e6..099fd8285 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 @@ -291,12 +291,13 @@ protected void runLibertyMojoInstallFeature(Element features, File serverDir, St runLibertyMojo("install-feature", config); } - protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize) throws MojoExecutionException { + protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize, boolean useTmpDir) throws MojoExecutionException { Xpp3Dom config = ExecuteMojoUtil.getPluginGoalConfig(getLibertyPlugin(), "generate-features", getLog()); if (classFiles != null) { config = Xpp3Dom.mergeXpp3Dom(configuration(classFiles), config); } config.addChild(element(name("optimize"), Boolean.toString(optimize)).toDom()); + config.addChild(element(name("internalDevMode"), Boolean.toString(useTmpDir)).toDom()); runLibertyMojo("generate-features", config); } From b49ad47a138cb39e3912467647456b477c4f3a3f Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 16 Jun 2025 10:40:42 -0400 Subject: [PATCH 028/103] Use the tmp dir when generating features and then copy to server dir Signed-off-by: Paul Gooderham --- .../tools/maven/server/DevMojo.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) 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 46d3b402d..baf3750f2 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 @@ -446,7 +446,7 @@ public void libertyCreate() throws PluginExecutionException { } @Override - public boolean libertyGenerateFeatures(Collection classes, boolean optimize) { + public boolean libertyGenerateFeatures(Collection classes, boolean optimize, boolean useTmpDir) { try { if (classes != null) { Element[] classesElem = new Element[classes.size()]; @@ -456,11 +456,10 @@ public boolean libertyGenerateFeatures(Collection classes, boolean optim i++; } // generate features for only the classFiles passed - runLibertyMojoGenerateFeatures(element(name("classFiles"), classesElem), optimize); + runLibertyMojoGenerateFeatures(element(name("classFiles"), classesElem), optimize, useTmpDir); } else { - // pass null for classFiles so that features are generated for ALL of the - // classes - runLibertyMojoGenerateFeatures(null, optimize); + // pass null for classFiles so that features are generated for ALL of the classes + runLibertyMojoGenerateFeatures(null, optimize, useTmpDir); } return true; // successfully generated features } catch (MojoExecutionException e) { @@ -778,13 +777,17 @@ public boolean updateArtifactPaths(ProjectModule projectModule, boolean redeploy if (generateFeatures) { getLog().debug("Detected a change in the compile dependencies for " + buildFile + " , regenerating features"); - boolean generateFeaturesSuccess = libertyGenerateFeatures(null, true); + // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install + boolean generateFeaturesSuccess = libertyGenerateFeatures(null, true, !generateToSrc); if (generateFeaturesSuccess) { util.getJavaSourceClassPaths().clear(); } // install new generated features, will not trigger install-feature if the feature list has not changed util.installFeaturesToTempDir(generatedFeaturesFile, configDirectory, null, generateFeaturesSuccess); + if (!generateToSrc) { + util.copyTempFeatureFileToServer(); // finalize the generate-features operation + } } runLibertyMojoDeploy(); } @@ -1102,15 +1105,15 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat if (optimizeGenerateFeatures && generateFeatures) { getLog().debug("Detected a change in the compile dependencies, regenerating features"); // always optimize generate features on dependency change - generateFeaturesSuccess = libertyGenerateFeatures(null, true); + // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install + generateFeaturesSuccess = libertyGenerateFeatures(null, true, !generateToSrc); if (generateFeaturesSuccess) { util.getJavaSourceClassPaths().clear(); } else { installFeature = false; // skip installing features if generate features fails } - } - + // 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 @@ -1157,6 +1160,10 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat runLibertyMojoInstallFeature(null, null, super.getContainerName()); } } + // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install + if (generateFeaturesSuccess && !generateToSrc) { + util.copyTempFeatureFileToServer(); // finalize the generate-features operation + } if (!(reinstallLiberty || restartServer || createServer || redeployApp || installFeature || runBoostPackage)) { // pom.xml is changed but not affecting liberty:dev mode. return true with the // updated project set in the session @@ -1684,7 +1691,7 @@ private void generateFeaturesOnStartup() throws MojoExecutionException { getLog().warn( "The source configuration directory will be modified. Features will automatically be generated in a new file: " + generatedFileCanonicalPath); - runLibertyMojoGenerateFeatures(null, true); + runLibertyMojoGenerateFeatures(null, true, false); } catch (MojoExecutionException e) { if (e.getCause() != null && e.getCause() instanceof PluginExecutionException) { // PluginExecutionException indicates that the binary scanner jar could not be found @@ -2181,7 +2188,7 @@ protected void runLibertyMojoCreate() throws MojoExecutionException { * @throws MojoExecutionException */ @Override - protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize) throws MojoExecutionException { - super.runLibertyMojoGenerateFeatures(classFiles, optimize); + protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize, boolean useTmpDir) throws MojoExecutionException { + super.runLibertyMojoGenerateFeatures(classFiles, optimize, useTmpDir); } } From 89a6d1f6daaba7ac4fe4c6516b7d626298d803e8 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 16 Jun 2025 11:21:31 -0400 Subject: [PATCH 029/103] Fix comment Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 57281f604..7e70500ce 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -85,7 +85,7 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { * The internalDevMode parameter is for internal use only. It is not for users. * The parameter is only used when generateToSrc is false meaning we generate to serverDir. * When the parameter is true we will write the generated features file to the temp directory. - * This is required because the features must all be installed before writing to server Dir in devmode. + * This is required because the features must all be installed before writing to serverDir in devmode. */ @Parameter(property = "internalDevMode", defaultValue = "false") private boolean internalDevMode; From d13c739ab57138ac60beaa444dea3da3b90da4f1 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 16 Jun 2025 19:54:49 -0400 Subject: [PATCH 030/103] Clean up method copyTempFeatureFileToServer Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 baf3750f2..de75fedc9 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 @@ -786,7 +786,7 @@ public boolean updateArtifactPaths(ProjectModule projectModule, boolean redeploy util.installFeaturesToTempDir(generatedFeaturesFile, configDirectory, null, generateFeaturesSuccess); if (!generateToSrc) { - util.copyTempFeatureFileToServer(); // finalize the generate-features operation + util.copyTempFeatureFileToServer(serverDirectory); // finalize the generate-features operation } } runLibertyMojoDeploy(); @@ -1162,7 +1162,7 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat } // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install if (generateFeaturesSuccess && !generateToSrc) { - util.copyTempFeatureFileToServer(); // finalize the generate-features operation + util.copyTempFeatureFileToServer(serverDirectory); // finalize the generate-features operation } if (!(reinstallLiberty || restartServer || createServer || redeployApp || installFeature || runBoostPackage)) { // pom.xml is changed but not affecting liberty:dev mode. return true with the From d9aed3837660da24f743ba894d0e59be36f644ff Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 17 Jun 2025 19:36:43 -0400 Subject: [PATCH 031/103] Fix comments Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 2 +- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 de75fedc9..39e02909b 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 @@ -1153,7 +1153,7 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat runLibertyMojoCreate(); } else if (redeployApp) { util.installFeaturesToTempDir(generatedFeaturesFile, configDirectory, null, - generateFeaturesSuccess); + generateFeaturesSuccess); runLibertyMojoDeploy(); } if (installFeature) { diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 7e70500ce..b88c06fab 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -311,7 +311,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx File generatedXmlFile; if (internalDevMode) { // create a temp dir in the target directory for the generated-features.xml in dev mode - // The ServerConfigXmlDocument will create the directories if needed. + // The ServerConfigXmlDocument class will create the directories if needed. generatedXmlFile = new File(project.getBuild().getDirectory(), GENERATED_FEATURES_TEMP_PATH); } else { generatedXmlFile = new File(generationContextDir, GENERATED_FEATURES_FILE_PATH); From 2d9d7fd0b6a0e4fc9afe4ec7df318adf847f17c3 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 18 Jun 2025 19:05:39 -0400 Subject: [PATCH 032/103] Improve the debug logging Signed-off-by: Paul Gooderham --- .../openliberty/tools/maven/server/GenerateFeaturesMojo.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index b88c06fab..f79e79e94 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -191,7 +191,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("--- Generate Features values ---"); getLog().debug("Binary scanner jar: " + binaryScanner.getName()); getLog().debug("optimize generate features: " + optimize); - getLog().debug("generate to src or target: " + generationContextDir); + getLog().debug("called by dev mode internalDevMode: " + internalDevMode); + getLog().debug("generate to src or target: " + (internalDevMode ? GENERATED_FEATURES_TEMP_PATH : generationContextDir)); if (classFiles != null && !classFiles.isEmpty()) { getLog().debug("Generate features for the following class files: " + classFiles.toString()); } @@ -332,7 +333,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // Generate log message before writing file as the file change event kicks off other dev mode actions getLog().info("Generated the following features: " + missingLibertyFeatures); configDocument.writeXMLDocument(generatedXmlFile); - getLog().debug("Created file " + generatedXmlFile); + getLog().debug("Created file " + generatedXmlFile.getAbsolutePath()); } else { getLog().info("Regenerated the following features: " + missingLibertyFeatures); } From c0be1277067280fa77a5c954e018b9864ccf02cc Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 23 Jun 2025 15:12:14 -0400 Subject: [PATCH 033/103] Add a comment to explain why generateToSrc is not needed Signed-off-by: Paul Gooderham --- .../src/main/java/io/openliberty/tools/maven/server/DevMojo.java | 1 + 1 file changed, 1 insertion(+) 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 39e02909b..01164b1a5 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 @@ -1691,6 +1691,7 @@ private void generateFeaturesOnStartup() throws MojoExecutionException { getLog().warn( "The source configuration directory will be modified. Features will automatically be generated in a new file: " + generatedFileCanonicalPath); + // Only generate to a tmp dir once dev mode has started. runLibertyMojoGenerateFeatures(null, true, false); } catch (MojoExecutionException e) { if (e.getCause() != null && e.getCause() instanceof PluginExecutionException) { From ba9f9ed33fccc2ec36d8ff61c166c536b279b12a Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 23 Jun 2025 17:42:17 -0400 Subject: [PATCH 034/103] Fix debug stmt to show file full path Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index f79e79e94..9188dee18 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -192,7 +192,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("Binary scanner jar: " + binaryScanner.getName()); getLog().debug("optimize generate features: " + optimize); getLog().debug("called by dev mode internalDevMode: " + internalDevMode); - getLog().debug("generate to src or target: " + (internalDevMode ? GENERATED_FEATURES_TEMP_PATH : generationContextDir)); + getLog().debug("generate to src or target: " + (internalDevMode ? GENERATED_FEATURES_TEMP_PATH : generationContextDir.getAbsolutePath())); if (classFiles != null && !classFiles.isEmpty()) { getLog().debug("Generate features for the following class files: " + classFiles.toString()); } From c5e6f2bf33dca34c27bf98c110453fe5587d81a0 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 24 Jun 2025 16:43:25 -0400 Subject: [PATCH 035/103] Update generate features tests Signed-off-by: Paul Gooderham --- .../net/wasdev/wlp/test/dev/it/BaseDevTest.java | 2 +- .../java/net/wasdev/wlp/test/dev/it/DevTest.java | 4 ++-- .../wlp/test/dev/it/GenerateFeaturesTest.java | 14 +++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseDevTest.java b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseDevTest.java index ea3795bab..075281c03 100644 --- a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseDevTest.java +++ b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseDevTest.java @@ -71,7 +71,7 @@ public class BaseDevTest { final static String RUNNING_GENERATE_FEATURES = "Running liberty:generate-features"; final static String REGENERATE_FEATURES = "Regenerated the following features:"; final static String GENERATE_FEATURES = "Generated the following features:"; - final static String SERVER_XML_COMMENT = "Plugin has generated Liberty features"; // the explanation added to server.xml + // final static String SERVER_XML_COMMENT = "Plugin has generated Liberty features"; // the explanation added to server.xml final static String NEW_FILE_INFO_MESSAGE = "This file was generated by the Liberty Maven Plugin and will be overwritten"; // the explanation added to the generated features file final static String SERVER_CONFIG_SUCCESS = "CWWKZ0003I:";// CWWKZ0003I: The application xxx updated in y.yyy seconds. final static String SERVER_UPDATE_COMPLETE = "CWWKF0008I:"; // Feature update completed in 0.649 seconds. diff --git a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java index 54bcae1f1..9fde5da45 100644 --- a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java +++ b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java @@ -293,11 +293,11 @@ public void generateFeatureTest() throws Exception { verifyFileExists(helloBatchObj, 15000); // ... and run the proper mojo. assertTrue(verifyLogMessageExists(RUNNING_GENERATE_FEATURES, 10000, ++runGenerateFeaturesCount)); // mojo ran - assertTrue(verifyFileExists(newFeatureFile, 5000)); // mojo created file + // assertTrue(verifyFileExists(newFeatureFile, 5000)); // mojo created file assertTrue(verifyFileExists(newTargetFeatureFile, 5000)); // dev mode copied file assertTrue(verifyLogMessageExists("batch-1.0", 10000, newFeatureFile)); assertTrue(verifyLogMessageExists(NEW_FILE_INFO_MESSAGE, 10000, newFeatureFile)); - assertTrue(verifyLogMessageExists(SERVER_XML_COMMENT, 10000, serverXmlFile)); + // assertTrue(verifyLogMessageExists(SERVER_XML_COMMENT, 10000, serverXmlFile)); // "CWWKF0012I: The server installed the following features:" assume batch-1.0 is in there // batch-1.0 pulls in other features that can take a long time to download. assertTrue(verifyLogMessageExists(SERVER_INSTALLED_FEATURES, 123000, ++installedFeaturesCount)); diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java index 3ba8dccaa..cd284e28d 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java @@ -56,7 +56,7 @@ public void basicTest() throws Exception { executeBasicTests(newFeatureFile, ""); } - private void executeBasicTests(File featureFile, String options) { + private void executeBasicTests(File featureFile, String options) throws Exception { // verify that the target directory was created by compile goal assertTrue(targetDir.exists()); @@ -129,7 +129,7 @@ public void customFeaturesTest() throws Exception { @Test public void serverXmlCommentNoFMTest() throws Exception { // initially the expected comment is not found in server.xml - assertFalse(verifyLogMessageExists(GenerateFeaturesMojo.FEATURES_FILE_MESSAGE, 10, serverXmlFile)); + // assertFalse(verifyLogMessageExists(GenerateFeaturesMojo.FEATURES_FILE_MESSAGE, 10, serverXmlFile)); // also we wish to test behaviour when there is no element so test that assertFalse(verifyLogMessageExists("", 10, serverXmlFile)); @@ -142,8 +142,8 @@ public void serverXmlCommentNoFMTest() throws Exception { Charset charset = StandardCharsets.UTF_8; String serverXmlContents = new String(Files.readAllBytes(serverXmlFile.toPath()), charset); serverXmlContents = "\n" + serverXmlContents; - assertTrue(serverXmlContents, - verifyLogMessageExists(GenerateFeaturesMojo.FEATURES_FILE_MESSAGE, 100, serverXmlFile)); + // assertTrue(serverXmlContents, + // verifyLogMessageExists(GenerateFeaturesMojo.FEATURES_FILE_MESSAGE, 100, serverXmlFile)); } @Test @@ -156,7 +156,7 @@ public void serverXmlCommentFMTest() throws Exception { serverXmlFile); // initially the expected comment is not found in server.xml - assertFalse(verifyLogMessageExists(GenerateFeaturesMojo.FEATURES_FILE_MESSAGE, 10, serverXmlFile)); + // assertFalse(verifyLogMessageExists(GenerateFeaturesMojo.FEATURES_FILE_MESSAGE, 10, serverXmlFile)); runCompileAndGenerateFeatures(); @@ -167,8 +167,8 @@ public void serverXmlCommentFMTest() throws Exception { Charset charset = StandardCharsets.UTF_8; String serverXmlContents = new String(Files.readAllBytes(serverXmlFile.toPath()), charset); serverXmlContents = "\n" + serverXmlContents; - assertTrue(serverXmlContents, - verifyLogMessageExists(GenerateFeaturesMojo.FEATURES_FILE_MESSAGE, 100, serverXmlFile)); + // assertTrue(serverXmlContents, + // verifyLogMessageExists(GenerateFeaturesMojo.FEATURES_FILE_MESSAGE, 100, serverXmlFile)); } /** From 493f743dce7e429e72cbd212bb23822488faa0a3 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 24 Jun 2025 17:34:07 -0400 Subject: [PATCH 036/103] Fix MultiModuleGenerateFeaturesTest and DevTest Signed-off-by: Paul Gooderham --- .../src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java | 8 ++++---- .../wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java | 7 +++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java index 9fde5da45..c89af093c 100644 --- a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java +++ b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java @@ -276,7 +276,7 @@ public void generateFeatureTest() throws Exception { int runGenerateFeaturesCount = countOccurrences(RUNNING_GENERATE_FEATURES, logFile); int installedFeaturesCount = countOccurrences(SERVER_INSTALLED_FEATURES, logFile); - File newFeatureFile = getGeneratedFeaturesFile(); + // File newFeatureFile = getGeneratedFeaturesFile(); File newTargetFeatureFile = getTargetGeneratedFeaturesFile(); File serverXmlFile = new File(tempProj, "/src/main/liberty/config/server.xml"); assertTrue(serverXmlFile.exists()); @@ -295,8 +295,8 @@ public void generateFeatureTest() throws Exception { assertTrue(verifyLogMessageExists(RUNNING_GENERATE_FEATURES, 10000, ++runGenerateFeaturesCount)); // mojo ran // assertTrue(verifyFileExists(newFeatureFile, 5000)); // mojo created file assertTrue(verifyFileExists(newTargetFeatureFile, 5000)); // dev mode copied file - assertTrue(verifyLogMessageExists("batch-1.0", 10000, newFeatureFile)); - assertTrue(verifyLogMessageExists(NEW_FILE_INFO_MESSAGE, 10000, newFeatureFile)); + assertTrue(verifyLogMessageExists("batch-1.0", 10000, newTargetFeatureFile)); + assertTrue(verifyLogMessageExists(NEW_FILE_INFO_MESSAGE, 10000, newTargetFeatureFile)); // assertTrue(verifyLogMessageExists(SERVER_XML_COMMENT, 10000, serverXmlFile)); // "CWWKF0012I: The server installed the following features:" assume batch-1.0 is in there // batch-1.0 pulls in other features that can take a long time to download. @@ -345,7 +345,7 @@ public void generateFeatureTest() throws Exception { writer.write("o\n"); // on optimize regenerate writer.flush(); assertTrue(verifyLogMessageExists(GENERATE_FEATURES, 10000, logFile, ++generateFeaturesCount)); - assertTrue(verifyLogMessageExists("batch-1.0", 10000, newFeatureFile, 0)); // exist 0 times + assertTrue(verifyLogMessageExists("batch-1.0", 10000, newTargetFeatureFile, 0)); // exist 0 times // Check for server response to newly generated feature list. assertTrue(verifyLogMessageExists(SERVER_UPDATE_COMPLETE, 10000, serverUpdateCount+1)); // Need to ensure server finished updating before the next test starts. diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java index 95f621cf7..9fc9b1a4e 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java @@ -54,9 +54,12 @@ protected void runCompileAndGenerateFeatures() throws IOException, InterruptedEx } @Override - protected void runGenerateFeaturesGoal() throws IOException, InterruptedException { + protected void runGenerateFeaturesGoal(String options) throws IOException, InterruptedException { + if (options == null) { + options = ""; + } runProcess("io.openliberty.tools:liberty-maven-plugin:" + System.getProperty("mavenPluginVersion") - + ":generate-features"); + + ":generate-features " + options); } @Override From 27f2483e072ab04ae3bb755fac6870aa05d0c5c1 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 25 Jun 2025 14:00:59 -0400 Subject: [PATCH 037/103] Update tests to use gen. features file in server dir Signed-off-by: Paul Gooderham --- .../wasdev/wlp/test/dev/it/BaseDevTest.java | 2 +- .../DevGenerateFeaturesDependenciesTest.java | 31 +++++++++++-------- .../net/wasdev/wlp/test/dev/it/DevTest.java | 2 +- .../dev/it/MultiModuleUpdatePomsTest.java | 5 +-- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseDevTest.java b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseDevTest.java index 075281c03..77f85c6d9 100644 --- a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseDevTest.java +++ b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseDevTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * (c) Copyright IBM Corporation 2019, 2023. + * (c) Copyright IBM Corporation 2019, 2025 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevGenerateFeaturesDependenciesTest.java b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevGenerateFeaturesDependenciesTest.java index 4dfc06f2b..c2ef87691 100644 --- a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevGenerateFeaturesDependenciesTest.java +++ b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevGenerateFeaturesDependenciesTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * (c) Copyright IBM Corporation 2022. + * (c) Copyright IBM Corporation 2022, 2025 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,29 +30,30 @@ public class DevGenerateFeaturesDependenciesTest extends BaseDevTest { @BeforeClass - public static void setUpBeforeClass() throws Exception { - setUpBeforeClass(null, "../resources/basic-dev-project-umbrella-deps"); - } + public static void setUpBeforeClass() throws Exception { + setUpBeforeClass(null, "../resources/basic-dev-project-umbrella-deps"); + } @AfterClass public static void cleanUpAfterClass() throws Exception { - BaseDevTest.cleanUpAfterClass(); + BaseDevTest.cleanUpAfterClass(); } @Test public void updateDependencyTest() throws Exception { assertTrue(verifyLogMessageExists("Liberty is running in dev mode.", 10000)); - File generatedFeaturesFile = getGeneratedFeaturesFile(); + //File generatedFeaturesFile = getGeneratedFeaturesFile(); File targetGeneratedFeaturesFile = getTargetGeneratedFeaturesFile(); assertTrue(pom.exists()); - assertTrue(generatedFeaturesFile.exists()); + //assertTrue(generatedFeaturesFile.exists()); assertTrue(targetGeneratedFeaturesFile.exists()); - long lastModified = generatedFeaturesFile.lastModified(); + // long lastModified = generatedFeaturesFile.lastModified(); + long lastModified = targetGeneratedFeaturesFile.lastModified(); waitLongEnough(); // verify mpHealth-2.2 is in generated features file - assertTrue(verifyLogMessageExists("mpHealth-2.2", 10000, generatedFeaturesFile)); + assertTrue(verifyLogMessageExists("mpHealth-2.2", 10000, targetGeneratedFeaturesFile)); assertTrue(verifyLogMessageExists("mpHealth-2.2", 10000)); // should appear in the message "CWWKF0012I: The server installed the following features:" int generateFeaturesCount = countOccurrences("Running liberty:generate-features", logFile); @@ -75,16 +76,20 @@ public void updateDependencyTest() throws Exception { // Dev mode should now run the generate features mojo assertTrue(getLogTail(), verifyLogMessageExists("Generated the following features:", 15000, logFile, ++generateFeaturesCount)); // mojo ran - assertTrue(generatedFeaturesFile.exists()); - assertTrue(getLogTail(), lastModified < generatedFeaturesFile.lastModified()); + // assertTrue(generatedFeaturesFile.exists()); + // assertTrue(getLogTail(), lastModified < generatedFeaturesFile.lastModified()); assertTrue(targetGeneratedFeaturesFile.exists()); + assertTrue(getLogTail(), lastModified < targetGeneratedFeaturesFile.lastModified()); + //assertTrue(targetGeneratedFeaturesFile.exists()); // verify that mpHealth-3.0 is now in the generated features file - assertTrue(getLogTail(), verifyLogMessageExists("mpHealth-3.1", 10000, generatedFeaturesFile)); + // assertTrue(getLogTail(), verifyLogMessageExists("mpHealth-3.1", 10000, generatedFeaturesFile)); + assertTrue(getLogTail(), verifyLogMessageExists("mpHealth-3.1", 10000, targetGeneratedFeaturesFile)); assertTrue(getLogTail(), verifyLogMessageExists("mpHealth-3.1", 10000)); // should appear in the message "CWWKF0012I: The server installed the following features:" // verify that mpHealth-2.2 is no longer in the generated features file - assertFalse(getLogTail(), verifyLogMessageExists("mpHealth-2.2", 10000, generatedFeaturesFile)); + // assertFalse(getLogTail(), verifyLogMessageExists("mpHealth-2.2", 10000, generatedFeaturesFile)); + assertFalse(getLogTail(), verifyLogMessageExists("mpHealth-2.2", 10000, targetGeneratedFeaturesFile)); } } diff --git a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java index c89af093c..ea6247302 100644 --- a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java +++ b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/DevTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * (c) Copyright IBM Corporation 2019, 2022. + * (c) Copyright IBM Corporation 2019, 2025 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleUpdatePomsTest.java b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleUpdatePomsTest.java index be9d05d09..0798ad340 100644 --- a/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleUpdatePomsTest.java +++ b/liberty-maven-plugin/src/it/dev-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleUpdatePomsTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * (c) Copyright IBM Corporation 2022. + * (c) Copyright IBM Corporation 2022, 2025 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,7 +55,8 @@ public void updatePomsTest() throws Exception { int earTestsCount = countOccurrences("guide-maven-multimodules-ear tests compilation was successful.", logFile); // verify that generated-features.xml file exists - File newFeatureFile = getGeneratedFeaturesFile("ear"); + // File newFeatureFile = getGeneratedFeaturesFile("ear"); + File newFeatureFile = getTargetGeneratedFeaturesFile("ear"); assertTrue(getLogTail(), verifyFileExists(newFeatureFile, 1000)); long newFeatureFileLastModified = newFeatureFile.lastModified(); waitLongEnough(); From d52c823c6bbf47486290c6ee48244fe2e4552851 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 2 Jul 2025 17:18:46 -0400 Subject: [PATCH 038/103] Add .vscode to .gitignore Signed-off-by: Paul Gooderham --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2c8892d8f..6d83aa177 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,8 @@ target/ .classpath .factorypath .idea/ +.vscode/ .DS_Store *.versionsBackup /.metadata/ -*.jar \ No newline at end of file +*.jar From dce7751baf38446d443d2c133ea15c0fbcac88f0 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 8 Jul 2025 17:48:38 -0400 Subject: [PATCH 039/103] Update tests for generate features mojo Signed-off-by: Paul Gooderham --- .../test/dev/it/BaseGenerateFeaturesTest.java | 13 +++----- .../wlp/test/dev/it/GenerateFeaturesTest.java | 32 ++++++++++++------- .../it/MultiModuleGenerateFeaturesTest.java | 19 ++++++----- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java index 264210e7b..1fb71cea2 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/BaseGenerateFeaturesTest.java @@ -226,19 +226,16 @@ protected static Set readFeatures(File configurationFile) throws Excepti } protected void runCompileAndGenerateFeatures() throws IOException, InterruptedException { - runProcess("compile liberty:generate-features"); + runProcess("clean compile liberty:create liberty:generate-features"); } protected void runCompileAndGenerateFeaturesToSrc() throws IOException, InterruptedException { - runProcess("compile liberty:generate-features -DgenerateToSrc=true"); + // do not create liberty when generating to src + runProcess("clean compile liberty:generate-features -DgenerateToSrc=true"); } - protected void runGenerateFeaturesGoal(String options) throws IOException, InterruptedException { - String parameters = "liberty:generate-features "; - if (options != null) { - parameters += options; - } - runProcess(parameters); + protected void runGenerateFeaturesGoal() throws IOException, InterruptedException { + runProcess("liberty:generate-features"); } // Format the output to help debug test failures. diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java index cd284e28d..d424d496c 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java @@ -52,11 +52,18 @@ public void cleanUp() throws Exception { @Test public void basicTest() throws Exception { - runCompileAndGenerateFeatures(); - executeBasicTests(newFeatureFile, ""); + executeBasicTests(false); } - private void executeBasicTests(File featureFile, String options) throws Exception { + private void executeBasicTests(boolean generateToSrc) throws Exception { + File featureFile; + if (generateToSrc) { + featureFile = newFeatureFileSrc; + runCompileAndGenerateFeaturesToSrc(); + } else { + featureFile = newFeatureFile; + runCompileAndGenerateFeatures(); + } // verify that the target directory was created by compile goal assertTrue(targetDir.exists()); @@ -76,27 +83,30 @@ private void executeBasicTests(File featureFile, String options) throws Exceptio "\n", serverXmlFile); - runGenerateFeaturesGoal(options); // no additional features should be generated - assertTrue(featureFile.exists()); - features = readFeatures(featureFile); - assertEquals(0, features.size()); + if (generateToSrc) { + runCompileAndGenerateFeaturesToSrc(); + assertTrue(featureFile.exists()); + features = readFeatures(featureFile); + assertEquals(formatOutput(processOutput), 0, features.size()); + } else { + runCompileAndGenerateFeatures(); + assertFalse(featureFile.exists()); // after clean no feature file is created + } } @Test public void generateToSrcTest() throws Exception { newFeatureFile.delete(); // delete file if it exists but do not assert assertFalse(newFeatureFileSrc.exists()); // assuming no other test creates this file - runCompileAndGenerateFeaturesToSrc(); - - executeBasicTests(newFeatureFileSrc, "-DgenerateToSrc=true"); + executeBasicTests(true); assertTrue(newFeatureFileSrc.delete()); // clean up the generated file } @Test public void noClassFiles() throws Exception { // do not compile before running generate-features - runGenerateFeaturesGoal(""); + runGenerateFeaturesGoal(); // verify that generated features file was not created assertFalse(newFeatureFile.exists()); diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java index 9fc9b1a4e..c2ee7eb92 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/MultiModuleGenerateFeaturesTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * (c) Copyright IBM Corporation 2022. + * (c) Copyright IBM Corporation 2022, 2025 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,17 +49,20 @@ public void setUp() throws Exception { @Override protected void runCompileAndGenerateFeatures() throws IOException, InterruptedException { - runProcess("compile io.openliberty.tools:liberty-maven-plugin:" + System.getProperty("mavenPluginVersion") - + ":generate-features"); + String lmp = "io.openliberty.tools:liberty-maven-plugin:" + System.getProperty("mavenPluginVersion"); + runProcess("clean compile " + lmp + ":create " + lmp + ":generate-features"); } @Override - protected void runGenerateFeaturesGoal(String options) throws IOException, InterruptedException { - if (options == null) { - options = ""; - } + protected void runCompileAndGenerateFeaturesToSrc() throws IOException, InterruptedException { + String lmp = "io.openliberty.tools:liberty-maven-plugin:" + System.getProperty("mavenPluginVersion"); + runProcess("clean compile " + lmp + ":generate-features -DgenerateToSrc=true"); + } + + @Override + protected void runGenerateFeaturesGoal() throws IOException, InterruptedException { runProcess("io.openliberty.tools:liberty-maven-plugin:" + System.getProperty("mavenPluginVersion") - + ":generate-features " + options); + + ":generate-features "); } @Override From 5eaf000fdfcc8a3f0956692096a7292da55c9bfb Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 16 Dec 2025 17:15:03 -0500 Subject: [PATCH 040/103] Update name of method used to copy temp features file and add TODO to investigate the copy Signed-off-by: Paul Gooderham --- .../java/io/openliberty/tools/maven/server/DevMojo.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 01164b1a5..cdbd4daef 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 @@ -786,7 +786,8 @@ public boolean updateArtifactPaths(ProjectModule projectModule, boolean redeploy util.installFeaturesToTempDir(generatedFeaturesFile, configDirectory, null, generateFeaturesSuccess); if (!generateToSrc) { - util.copyTempFeatureFileToServer(serverDirectory); // finalize the generate-features operation + // TODO: do we really need to copy this file here or is it copied by the file watcher after we register the generation temp dir? + util.copyGeneratedFeaturesFile(serverDirectory); // finalize the generate-features operation } } runLibertyMojoDeploy(); @@ -1160,9 +1161,10 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat runLibertyMojoInstallFeature(null, null, super.getContainerName()); } } + // TODO: do we really need to copy this file here or is it copied by the file watcher after we register the generation temp dir? // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install if (generateFeaturesSuccess && !generateToSrc) { - util.copyTempFeatureFileToServer(serverDirectory); // finalize the generate-features operation + util.copyGeneratedFeaturesFile(serverDirectory); // finalize the generate-features operation } if (!(reinstallLiberty || restartServer || createServer || redeployApp || installFeature || runBoostPackage)) { // pom.xml is changed but not affecting liberty:dev mode. return true with the From 0ceb21ef2a85162ad673c66ee86d123176d7fe5f Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 16 Dec 2025 17:16:49 -0500 Subject: [PATCH 041/103] Add generationOutputDir field to clarify generation process Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 9188dee18..079e75376 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -100,6 +100,15 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { */ private File generationContextDir; + /** + * Liberty features are generated in the context of a certain server and they are stored in + * an XML file in the configDir, the serverDir or a temporary directory. When using dev + * mode we must write to the tempDir and call install-features before we can use the + * features in the running server. When not using dev mode we can just write the features + * to the configDir or serverDir as indicated by the generateToSrc option. + */ + private File generationOutputDir; + @Override protected void init() throws MojoExecutionException { // @see io.openliberty.tools.maven.BasicSupport#init() @@ -184,6 +193,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // The config dir is in the src directory. Otherwise generate for the target/liberty dir. generationContextDir = generateToSrc ? configDirectory : serverDirectory; + // When using dev mode we always generate to a temporary directory so we can call install before writing to server dir. + generationOutputDir = internalDevMode ? new File(project.getBuild().getDirectory(), GENERATED_FEATURES_TEMP_DIR) : generationContextDir; binaryScanner = getBinaryScannerJarFromRepository(); BinaryScannerHandler binaryScannerHandler = new BinaryScannerHandler(binaryScanner); @@ -191,8 +202,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("--- Generate Features values ---"); getLog().debug("Binary scanner jar: " + binaryScanner.getName()); getLog().debug("optimize generate features: " + optimize); - getLog().debug("called by dev mode internalDevMode: " + internalDevMode); - getLog().debug("generate to src or target: " + (internalDevMode ? GENERATED_FEATURES_TEMP_PATH : generationContextDir.getAbsolutePath())); + getLog().debug("called by dev mode, internalDevMode: " + internalDevMode); + getLog().debug("generate to directory: " + generationOutputDir.getAbsolutePath()); if (classFiles != null && !classFiles.isEmpty()) { getLog().debug("Generate features for the following class files: " + classFiles.toString()); } @@ -309,14 +320,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("Features detected by binary scanner which are not in server.xml" + missingLibertyFeatures); // generate the new features into an xml file in the correct context directory - File generatedXmlFile; - if (internalDevMode) { - // create a temp dir in the target directory for the generated-features.xml in dev mode - // The ServerConfigXmlDocument class will create the directories if needed. - generatedXmlFile = new File(project.getBuild().getDirectory(), GENERATED_FEATURES_TEMP_PATH); - } else { - generatedXmlFile = new File(generationContextDir, GENERATED_FEATURES_FILE_PATH); - } + // The ServerConfigXmlDocument class will create the directories if needed. + File generatedXmlFile = new File(generationOutputDir, GENERATED_FEATURES_FILE_PATH); try { if (missingLibertyFeatures.size() > 0) { Set existingGeneratedFeatures = getGeneratedFeatures(servUtil, generatedXmlFile); From 7b8aa71361a37d456088721c69913dd7a381100f Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 16 Dec 2025 17:22:39 -0500 Subject: [PATCH 042/103] Add comments to explain basic tests Signed-off-by: Paul Gooderham --- .../java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java index d424d496c..22a2a52bc 100644 --- a/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java +++ b/liberty-maven-plugin/src/it/generate-features-it/src/test/java/net/wasdev/wlp/test/dev/it/GenerateFeaturesTest.java @@ -85,11 +85,13 @@ private void executeBasicTests(boolean generateToSrc) throws Exception { // no additional features should be generated if (generateToSrc) { + // In src dir the generated file is preserved and contains no new features runCompileAndGenerateFeaturesToSrc(); assertTrue(featureFile.exists()); features = readFeatures(featureFile); assertEquals(formatOutput(processOutput), 0, features.size()); } else { + // the server dir is in target directory and a mvn clean is performed so it has been removed runCompileAndGenerateFeatures(); assertFalse(featureFile.exists()); // after clean no feature file is created } From aa12835152a0670d5f37770e21a69d8a010fb2c7 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 17 Dec 2025 17:07:30 -0500 Subject: [PATCH 043/103] Update liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java Co-authored-by: Trevor Crawford --- .../openliberty/tools/maven/server/GenerateFeaturesMojo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 079e75376..edf2d4111 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -87,8 +87,8 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { * When the parameter is true we will write the generated features file to the temp directory. * This is required because the features must all be installed before writing to serverDir in devmode. */ - @Parameter(property = "internalDevMode", defaultValue = "false") - private boolean internalDevMode; + @Parameter(property = "useDevModeTempDir", defaultValue = "false") + private boolean useDevModeTempDir; /** * Generating features is performed relative to a certain server. We only generate features From a5f50389aa29f28955241c4131af0d5772e54606 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 17 Dec 2025 17:07:49 -0500 Subject: [PATCH 044/103] Update liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java Co-authored-by: Trevor Crawford --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index edf2d4111..ae2cee2a7 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -82,7 +82,7 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { private boolean generateToSrc; /** - * The internalDevMode parameter is for internal use only. It is not for users. + * The useDevModeTempDir parameter is for internal use only. It is not for users. * The parameter is only used when generateToSrc is false meaning we generate to serverDir. * When the parameter is true we will write the generated features file to the temp directory. * This is required because the features must all be installed before writing to serverDir in devmode. From 592771af5ad132137d06cef066dcd10a2e22c439 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 17 Dec 2025 17:08:02 -0500 Subject: [PATCH 045/103] Update liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java Co-authored-by: Trevor Crawford --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index ae2cee2a7..156df274a 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -194,7 +194,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // The config dir is in the src directory. Otherwise generate for the target/liberty dir. generationContextDir = generateToSrc ? configDirectory : serverDirectory; // When using dev mode we always generate to a temporary directory so we can call install before writing to server dir. - generationOutputDir = internalDevMode ? new File(project.getBuild().getDirectory(), GENERATED_FEATURES_TEMP_DIR) : generationContextDir; + generationOutputDir = useDevModeTempDir ? new File(project.getBuild().getDirectory(), GENERATED_FEATURES_TEMP_DIR) : generationContextDir; binaryScanner = getBinaryScannerJarFromRepository(); BinaryScannerHandler binaryScannerHandler = new BinaryScannerHandler(binaryScanner); From 4f0e025128d2fe3739d0ffc32ddf4e3ae3784755 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 17 Dec 2025 17:08:16 -0500 Subject: [PATCH 046/103] Update liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java Co-authored-by: Trevor Crawford --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 156df274a..e01926ec9 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -202,7 +202,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("--- Generate Features values ---"); getLog().debug("Binary scanner jar: " + binaryScanner.getName()); getLog().debug("optimize generate features: " + optimize); - getLog().debug("called by dev mode, internalDevMode: " + internalDevMode); + getLog().debug("called by dev mode, useDevModeTempDir: " + useDevModeTempDir); getLog().debug("generate to directory: " + generationOutputDir.getAbsolutePath()); if (classFiles != null && !classFiles.isEmpty()) { getLog().debug("Generate features for the following class files: " + classFiles.toString()); From 0fa8e97f84dd539fc0a797a10418c8c051988642 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 25 Jun 2025 14:12:42 -0400 Subject: [PATCH 047/103] Make the generateFeatures option enabled by default in devmode Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f1f35b20a..93efe12bf 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 @@ -135,7 +135,7 @@ public class DevMojo extends LooseAppSupport { @Parameter(property = "container", defaultValue = "false") private boolean container; - @Parameter(property = "generateFeatures", defaultValue = "false") + @Parameter(property = "generateFeatures", defaultValue = "true") private boolean generateFeatures; /** From b4f14dd5ad48669737abc6bc8d0ff3650ef15f4e Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 18 Dec 2025 15:43:41 -0500 Subject: [PATCH 048/103] Use new variable name Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 4022c7eb0..c13f36365 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 @@ -783,7 +783,7 @@ public boolean updateArtifactPaths(ProjectModule projectModule, boolean redeploy util.getJavaSourceClassPaths().clear(); } // install new generated features, will not trigger install-feature if the feature list has not changed - util.installFeaturesToTempDir(generatedFeaturesFile, configDirectory, null, + util.installFeaturesToTempDir(generateFeaturesFile, configDirectory, null, generateFeaturesSuccess); if (!generateToSrc) { // TODO: do we really need to copy this file here or is it copied by the file watcher after we register the generation temp dir? @@ -1153,7 +1153,7 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat } else if (createServer) { runLibertyMojoCreate(); } else if (redeployApp) { - util.installFeaturesToTempDir(generatedFeaturesFile, configDirectory, null, + util.installFeaturesToTempDir(generateFeaturesFile, configDirectory, null, generateFeaturesSuccess); runLibertyMojoDeploy(); } From 415ee3c7f2cc634ecce64376fa48a79d1e735750 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 19 Dec 2025 16:13:17 -0500 Subject: [PATCH 049/103] One more place useDevModeTempDir is needed Signed-off-by: Paul Gooderham --- .../openliberty/tools/maven/server/StartDebugMojoSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 099fd8285..851d31a2b 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 @@ -297,7 +297,7 @@ protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimi config = Xpp3Dom.mergeXpp3Dom(configuration(classFiles), config); } config.addChild(element(name("optimize"), Boolean.toString(optimize)).toDom()); - config.addChild(element(name("internalDevMode"), Boolean.toString(useTmpDir)).toDom()); + config.addChild(element(name("useDevModeTempDir"), Boolean.toString(useTmpDir)).toDom()); runLibertyMojo("generate-features", config); } From 0f7df6574957fbe71a17d9200da8d24b68275f4d Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 21 Jan 2026 15:45:39 -0500 Subject: [PATCH 050/103] Copy config and changed file to temp dir for feature generation Signed-off-by: Paul Gooderham --- .../tools/maven/server/DevMojo.java | 18 +++---- .../maven/server/GenerateFeaturesMojo.java | 47 +++++++++++++++---- .../maven/server/StartDebugMojoSupport.java | 5 +- 3 files changed, 49 insertions(+), 21 deletions(-) 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 c13f36365..da90f08a8 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 @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2019, 2025. + * (C) Copyright IBM Corporation 2019, 2026 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -446,7 +446,7 @@ public void libertyCreate() throws PluginExecutionException { } @Override - public boolean libertyGenerateFeatures(Collection classes, boolean optimize, boolean useTmpDir) { + public boolean libertyGenerateFeatures(Collection classes, boolean optimize, boolean useTmpDirOut, boolean useTmpDirIn) { try { if (classes != null) { Element[] classesElem = new Element[classes.size()]; @@ -456,10 +456,10 @@ public boolean libertyGenerateFeatures(Collection classes, boolean optim i++; } // generate features for only the classFiles passed - runLibertyMojoGenerateFeatures(element(name("classFiles"), classesElem), optimize, useTmpDir); + runLibertyMojoGenerateFeatures(element(name("classFiles"), classesElem), optimize, useTmpDirOut, useTmpDirIn); } else { // pass null for classFiles so that features are generated for ALL of the classes - runLibertyMojoGenerateFeatures(null, optimize, useTmpDir); + runLibertyMojoGenerateFeatures(null, optimize, useTmpDirOut, useTmpDirIn); } return true; // successfully generated features } catch (MojoExecutionException e) { @@ -778,7 +778,7 @@ public boolean updateArtifactPaths(ProjectModule projectModule, boolean redeploy getLog().debug("Detected a change in the compile dependencies for " + buildFile + " , regenerating features"); // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install - boolean generateFeaturesSuccess = libertyGenerateFeatures(null, true, !generateToSrc); + boolean generateFeaturesSuccess = libertyGenerateFeatures(null, true, !generateToSrc, false); if (generateFeaturesSuccess) { util.getJavaSourceClassPaths().clear(); } @@ -1107,7 +1107,7 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat getLog().debug("Detected a change in the compile dependencies, regenerating features"); // always optimize generate features on dependency change // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install - generateFeaturesSuccess = libertyGenerateFeatures(null, true, !generateToSrc); + generateFeaturesSuccess = libertyGenerateFeatures(null, true, !generateToSrc, false); if (generateFeaturesSuccess) { util.getJavaSourceClassPaths().clear(); } else { @@ -1694,7 +1694,7 @@ private void generateFeaturesOnStartup() throws MojoExecutionException { "The source configuration directory will be modified. Features will automatically be generated in a new file: " + generatedFileCanonicalPath); // Only generate to a tmp dir once dev mode has started. - runLibertyMojoGenerateFeatures(null, true, false); + runLibertyMojoGenerateFeatures(null, true, false, false); } catch (MojoExecutionException e) { if (e.getCause() != null && e.getCause() instanceof PluginExecutionException) { // PluginExecutionException indicates that the binary scanner jar could not be found @@ -2191,7 +2191,7 @@ protected void runLibertyMojoCreate() throws MojoExecutionException { * @throws MojoExecutionException */ @Override - protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize, boolean useTmpDir) throws MojoExecutionException { - super.runLibertyMojoGenerateFeatures(classFiles, optimize, useTmpDir); + protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize, boolean useTmpDirOut, boolean useTmpDirIn) throws MojoExecutionException { + super.runLibertyMojoGenerateFeatures(classFiles, optimize, useTmpDirOut, useTmpDirIn); } } diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 37ac01cd9..12ac499f3 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2021, 2025 + * (C) Copyright IBM Corporation 2021, 2026 * * 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 @@ -82,13 +82,28 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { private boolean generateToSrc; /** - * The useDevModeTempDir parameter is for internal use only. It is not for users. + * The useTempDirAsOutput parameter is for internal use only. It is not for users. * The parameter is only used when generateToSrc is false meaning we generate to serverDir. - * When the parameter is true we will write the generated features file to the temp directory. - * This is required because the features must all be installed before writing to serverDir in devmode. + * It is needed in dev mode because the server is running and we need to ensure the features + * that are generated are installed before we update a running server. + * When the parameter is true we will write the generated features file to the special generate-features + * temp directory. */ - @Parameter(property = "useDevModeTempDir", defaultValue = "false") - private boolean useDevModeTempDir; + @Parameter(property = "useTempDirAsOutput", defaultValue = "false") + private boolean useTempDirAsOutput; + + /** + * The useTempDirAsContext parameter is for internal use only. It is not for users. + * It is needed in dev mode when the user updates a server config file which might affect + * the features that will be generated. In such a case we will required the caller to copy the + * serverDir configuration files into the special generate-features temp directory and augment it + * with the file changed by the user. We do not do this all the time because of the performance + * cost of copying all the files. + * When the parameter is true we will use the generate-features temp directory as the context for + * feature generation. + */ + @Parameter(property = "useTempDirAsContext", defaultValue = "false") + private boolean useTempDirAsContext; /** * Generating features is performed relative to a certain server. We only generate features @@ -195,10 +210,15 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } } - // The config dir is in the src directory. Otherwise generate for the target/liberty dir. - generationContextDir = generateToSrc ? configDirectory : serverDirectory; + if (useTempDirAsContext) { + // When this parameter is true it is required that the caller has copied the config into this dir. + generationContextDir = getGeneratedFeaturesTempDir(); + } else { + // The config dir is the one in the src directory. Otherwise generate for the target/liberty/wlp dir. + generationContextDir = generateToSrc ? configDirectory : serverDirectory; + } // When using dev mode we always generate to a temporary directory so we can call install before writing to server dir. - generationOutputDir = useDevModeTempDir ? new File(project.getBuild().getDirectory(), GENERATED_FEATURES_TEMP_DIR) : generationContextDir; + generationOutputDir = useTempDirAsOutput ? getGeneratedFeaturesTempDir() : generationContextDir; binaryScanner = getBinaryScannerJarFromRepository(); BinaryScannerHandler binaryScannerHandler = new BinaryScannerHandler(binaryScanner); @@ -206,8 +226,10 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("--- Generate Features values ---"); getLog().debug("Binary scanner jar: " + binaryScanner.getName()); getLog().debug("optimize generate features: " + optimize); - getLog().debug("called by dev mode, useDevModeTempDir: " + useDevModeTempDir); + getLog().debug("called by dev mode, useTempDirAsOutput: " + useTempDirAsOutput); + getLog().debug("called by dev mode, useTempDirAsContext: " + useTempDirAsContext); getLog().debug("generate to directory: " + generationOutputDir.getAbsolutePath()); + if (classFiles != null && !classFiles.isEmpty()) { getLog().debug("Generate features for the following class files: " + classFiles.toString()); } @@ -395,6 +417,11 @@ private Set getGeneratedFeatures(ServerFeatureUtil servUtil, File genera return features; } + // returns the hidden directory we use for generate-features special purposes + private File getGeneratedFeaturesTempDir() { + return new File(project.getBuild().getDirectory(), GENERATED_FEATURES_TEMP_DIR); + } + /** * Gets the binary scanner jar file from the local cache. * Downloads it first from connected repositories such as Maven Central if a newer release is available than the cached version. 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 851d31a2b..3be176509 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 @@ -291,13 +291,14 @@ protected void runLibertyMojoInstallFeature(Element features, File serverDir, St runLibertyMojo("install-feature", config); } - protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize, boolean useTmpDir) throws MojoExecutionException { + protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize, boolean useTmpDirOut, boolean useTmpDirIn) throws MojoExecutionException { Xpp3Dom config = ExecuteMojoUtil.getPluginGoalConfig(getLibertyPlugin(), "generate-features", getLog()); if (classFiles != null) { config = Xpp3Dom.mergeXpp3Dom(configuration(classFiles), config); } config.addChild(element(name("optimize"), Boolean.toString(optimize)).toDom()); - config.addChild(element(name("useDevModeTempDir"), Boolean.toString(useTmpDir)).toDom()); + config.addChild(element(name("useTempDirAsOutput"), Boolean.toString(useTmpDirOut)).toDom()); + config.addChild(element(name("useTempDirAsContext"), Boolean.toString(useTmpDirIn)).toDom()); runLibertyMojo("generate-features", config); } From 4071e2bb8bbdf22bc4bb59a263916608e7c25af9 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 2 Feb 2026 14:46:32 -0500 Subject: [PATCH 051/103] Update liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java Modify debug stmts Co-authored-by: Trevor Crawford --- .../openliberty/tools/maven/server/GenerateFeaturesMojo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 12ac499f3..dedb0fada 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -226,8 +226,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("--- Generate Features values ---"); getLog().debug("Binary scanner jar: " + binaryScanner.getName()); getLog().debug("optimize generate features: " + optimize); - getLog().debug("called by dev mode, useTempDirAsOutput: " + useTempDirAsOutput); - getLog().debug("called by dev mode, useTempDirAsContext: " + useTempDirAsContext); + getLog().debug("useTempDirAsOutput (dev mode only): " + useTempDirAsOutput); + getLog().debug("useTempDirAsContext (dev mode only): " + useTempDirAsContext); getLog().debug("generate to directory: " + generationOutputDir.getAbsolutePath()); if (classFiles != null && !classFiles.isEmpty()) { From c4e9526df232d22ea99c515e64d3bb89efafa08e Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 2 Feb 2026 20:15:22 -0500 Subject: [PATCH 052/103] Code review: update comment Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 da90f08a8..e23033924 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 @@ -1693,7 +1693,8 @@ private void generateFeaturesOnStartup() throws MojoExecutionException { getLog().warn( "The source configuration directory will be modified. Features will automatically be generated in a new file: " + generatedFileCanonicalPath); - // Only generate to a tmp dir once dev mode has started. + // During dev mode start up the server is not running yet so we will generate features to the correct + // output directory and then install features in the next step. runLibertyMojoGenerateFeatures(null, true, false, false); } catch (MojoExecutionException e) { if (e.getCause() != null && e.getCause() instanceof PluginExecutionException) { From 915c4aa2f04aff415a8124a6736b08c4eae85a05 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 28 Jan 2026 17:25:51 -0500 Subject: [PATCH 053/103] Pass the generateToSrc option when generating features Signed-off-by: Paul Gooderham --- .../openliberty/tools/maven/server/DevMojo.java | 16 ++++++++-------- .../maven/server/StartDebugMojoSupport.java | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) 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 e23033924..26c57e7d4 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 @@ -446,7 +446,7 @@ public void libertyCreate() throws PluginExecutionException { } @Override - public boolean libertyGenerateFeatures(Collection classes, boolean optimize, boolean useTmpDirOut, boolean useTmpDirIn) { + public boolean libertyGenerateFeatures(Collection classes, boolean optimize, boolean genToSrc, boolean useTmpDirOut, boolean useTmpDirIn) { try { if (classes != null) { Element[] classesElem = new Element[classes.size()]; @@ -456,10 +456,10 @@ public boolean libertyGenerateFeatures(Collection classes, boolean optim i++; } // generate features for only the classFiles passed - runLibertyMojoGenerateFeatures(element(name("classFiles"), classesElem), optimize, useTmpDirOut, useTmpDirIn); + runLibertyMojoGenerateFeatures(element(name("classFiles"), classesElem), optimize, genToSrc, useTmpDirOut, useTmpDirIn); } else { // pass null for classFiles so that features are generated for ALL of the classes - runLibertyMojoGenerateFeatures(null, optimize, useTmpDirOut, useTmpDirIn); + runLibertyMojoGenerateFeatures(null, optimize, genToSrc, useTmpDirOut, useTmpDirIn); } return true; // successfully generated features } catch (MojoExecutionException e) { @@ -778,7 +778,7 @@ public boolean updateArtifactPaths(ProjectModule projectModule, boolean redeploy getLog().debug("Detected a change in the compile dependencies for " + buildFile + " , regenerating features"); // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install - boolean generateFeaturesSuccess = libertyGenerateFeatures(null, true, !generateToSrc, false); + boolean generateFeaturesSuccess = libertyGenerateFeatures(null, true, generateToSrc, !generateToSrc, false); if (generateFeaturesSuccess) { util.getJavaSourceClassPaths().clear(); } @@ -1107,7 +1107,7 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat getLog().debug("Detected a change in the compile dependencies, regenerating features"); // always optimize generate features on dependency change // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install - generateFeaturesSuccess = libertyGenerateFeatures(null, true, !generateToSrc, false); + generateFeaturesSuccess = libertyGenerateFeatures(null, true, generateToSrc, !generateToSrc, false); if (generateFeaturesSuccess) { util.getJavaSourceClassPaths().clear(); } else { @@ -1695,7 +1695,7 @@ private void generateFeaturesOnStartup() throws MojoExecutionException { + generatedFileCanonicalPath); // During dev mode start up the server is not running yet so we will generate features to the correct // output directory and then install features in the next step. - runLibertyMojoGenerateFeatures(null, true, false, false); + runLibertyMojoGenerateFeatures(null, true, generateToSrc, false, false); } catch (MojoExecutionException e) { if (e.getCause() != null && e.getCause() instanceof PluginExecutionException) { // PluginExecutionException indicates that the binary scanner jar could not be found @@ -2192,7 +2192,7 @@ protected void runLibertyMojoCreate() throws MojoExecutionException { * @throws MojoExecutionException */ @Override - protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize, boolean useTmpDirOut, boolean useTmpDirIn) throws MojoExecutionException { - super.runLibertyMojoGenerateFeatures(classFiles, optimize, useTmpDirOut, useTmpDirIn); + protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize, boolean genToSrc, boolean useTmpDirOut, boolean useTmpDirIn) throws MojoExecutionException { + super.runLibertyMojoGenerateFeatures(classFiles, optimize, genToSrc, useTmpDirOut, useTmpDirIn); } } 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 3be176509..cec795f8f 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 @@ -291,12 +291,13 @@ protected void runLibertyMojoInstallFeature(Element features, File serverDir, St runLibertyMojo("install-feature", config); } - protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize, boolean useTmpDirOut, boolean useTmpDirIn) throws MojoExecutionException { + protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimize, boolean generateToSrc, boolean useTmpDirOut, boolean useTmpDirIn) throws MojoExecutionException { Xpp3Dom config = ExecuteMojoUtil.getPluginGoalConfig(getLibertyPlugin(), "generate-features", getLog()); if (classFiles != null) { config = Xpp3Dom.mergeXpp3Dom(configuration(classFiles), config); } config.addChild(element(name("optimize"), Boolean.toString(optimize)).toDom()); + config.addChild(element(name("generateToSrc"), Boolean.toString(generateToSrc)).toDom()); config.addChild(element(name("useTempDirAsOutput"), Boolean.toString(useTmpDirOut)).toDom()); config.addChild(element(name("useTempDirAsContext"), Boolean.toString(useTmpDirIn)).toDom()); runLibertyMojo("generate-features", config); From 4bf9e627ea085a6d4cf21151ef6894987d52848e Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 6 Feb 2026 18:33:38 -0500 Subject: [PATCH 054/103] Update the pom to use the correct version of ci.common Signed-off-by: Paul Gooderham --- liberty-maven-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/pom.xml b/liberty-maven-plugin/pom.xml index e3f37d317..a5e47cfcf 100644 --- a/liberty-maven-plugin/pom.xml +++ b/liberty-maven-plugin/pom.xml @@ -89,7 +89,7 @@ io.openliberty.tools ci.common - 1.8.40 + 1.8.41-SNAPSHOT org.apache.commons From 3ba2ec448c1f5a8034ec9b56e381ec4dcf4644aa Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 10 Feb 2026 17:55:07 -0500 Subject: [PATCH 055/103] Switch to optimizeGenerateFeatures() and updateExistingFeatures to avoid installing features in processConfigFileChange() Signed-off-by: Paul Gooderham --- .../tools/maven/server/DevMojo.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) 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 797886e8d..b9866194f 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 @@ -792,24 +792,26 @@ public boolean updateArtifactPaths(ProjectModule projectModule, boolean redeploy // detect compile dependency changes if (!dependencyListsEquals(getCompileDependency(deps), getCompileDependency(oldDeps))) { + boolean generateFeaturesSuccess = false; // optimize generate features if (generateFeatures) { getLog().debug("Detected a change in the compile dependencies for " + buildFile + " , regenerating features"); // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install - boolean generateFeaturesSuccess = libertyGenerateFeatures(null, true, generateToSrc, !generateToSrc, false); - if (generateFeaturesSuccess) { - util.getJavaSourceClassPaths().clear(); - } - // install new generated features, will not trigger install-feature if the feature list has not changed - util.installFeaturesToTempDir(generateFeaturesFile, configDirectory, null, - generateFeaturesSuccess); + generateFeaturesSuccess = optimizeGenerateFeatures(!generateToSrc, false); + // install new generated features because deploy will copy config files to server dir. + // It will not trigger install-feature if the feature list has not changed + util.installFeaturesToTempDir(generateFeaturesFile, configDirectory, null, generateFeaturesSuccess); if (!generateToSrc) { - // TODO: do we really need to copy this file here or is it copied by the file watcher after we register the generation temp dir? + // Copy the file here to be used by updateExistingFeatures() below even though file watcher will also copy it util.copyGeneratedFeaturesFile(serverDirectory); // finalize the generate-features operation } } runLibertyMojoDeploy(); + // Update the features after deploy mojo has copied the config files to server dir + if (generateFeaturesSuccess) { + updateExistingFeatures(); // update the dev mode cache of features in the server + } } } } catch (ProjectBuildingException | DependencyResolutionRequiredException | IOException From 7b92bc35674f68db6e5e26b088dc36faf6927154 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 11 Feb 2026 18:02:28 -0500 Subject: [PATCH 056/103] Use optimizeGenerateFeatures() and call updateExistingFeatures() to avoid installing features twice in recompileBuildFile() Signed-off-by: Paul Gooderham --- .../tools/maven/server/DevMojo.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) 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 b9866194f..58309d79f 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 @@ -1009,6 +1009,7 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat boolean redeployApp = false; boolean runBoostPackage = false; boolean optimizeGenerateFeatures = false; + boolean generateFeaturesSuccess = false; ProjectBuildingResult build; try { @@ -1123,15 +1124,13 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat compileArtifactPaths.addAll(project.getCompileClasspathElements()); testArtifactPaths.addAll(project.getTestClasspathElements()); - boolean generateFeaturesSuccess = false; if (optimizeGenerateFeatures && generateFeatures) { getLog().debug("Detected a change in the compile dependencies, regenerating features"); // always optimize generate features on dependency change - // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install - generateFeaturesSuccess = libertyGenerateFeatures(null, true, generateToSrc, !generateToSrc, false); - if (generateFeaturesSuccess) { - util.getJavaSourceClassPaths().clear(); - } else { + // If generateToSrc is false then we must copy (below) new generated features file from temp dir to server dir + generateFeaturesSuccess = optimizeGenerateFeatures(!generateToSrc, false); + util.installFeaturesToTempDir(generateFeaturesFile, configDirectory, null, generateFeaturesSuccess); + if (!generateFeaturesSuccess) { installFeature = false; // skip installing features if generate features fails } } @@ -1174,19 +1173,21 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat } else if (createServer) { runLibertyMojoCreate(); } else if (redeployApp) { - util.installFeaturesToTempDir(generateFeaturesFile, configDirectory, null, - generateFeaturesSuccess); runLibertyMojoDeploy(); + // Copy the file here to be used by updateExistingFeatures() below even though file watcher will also copy it + // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install + if (generateFeaturesSuccess && !generateToSrc) { + util.copyGeneratedFeaturesFile(serverDirectory); // finalize the generate-features operation + } + // Update the features after deploy mojo has copied the config files to server dir and generated features file added + if (generateFeaturesSuccess) { + updateExistingFeatures(); // update the dev mode cache of features in the server + } } if (installFeature) { runLibertyMojoInstallFeature(null, null, super.getContainerName()); } } - // TODO: do we really need to copy this file here or is it copied by the file watcher after we register the generation temp dir? - // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install - if (generateFeaturesSuccess && !generateToSrc) { - util.copyGeneratedFeaturesFile(serverDirectory); // finalize the generate-features operation - } if (!(reinstallLiberty || restartServer || createServer || redeployApp || installFeature || runBoostPackage)) { // pom.xml is changed but not affecting liberty:dev mode. return true with the // updated project set in the session From be907d5d775df3a14d039d96faedceaf23fe8dd1 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 18 Feb 2026 19:07:06 -0500 Subject: [PATCH 057/103] Add description why we copy generated features file only when not generating to src Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 2 ++ 1 file changed, 2 insertions(+) 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 58309d79f..3748d3ae9 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 @@ -802,6 +802,8 @@ public boolean updateArtifactPaths(ProjectModule projectModule, boolean redeploy // install new generated features because deploy will copy config files to server dir. // It will not trigger install-feature if the feature list has not changed util.installFeaturesToTempDir(generateFeaturesFile, configDirectory, null, generateFeaturesSuccess); + // When generating to the src dir, mojo deploy will copy the files from src to the server. + // When not generating to the src dir, we must copy the generated features file here. if (!generateToSrc) { // Copy the file here to be used by updateExistingFeatures() below even though file watcher will also copy it util.copyGeneratedFeaturesFile(serverDirectory); // finalize the generate-features operation From 4ddcad7bfcf1e10a48875db04831f9fbbc943712 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 20 Feb 2026 16:23:41 -0500 Subject: [PATCH 058/103] Update a comment Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 3748d3ae9..d06b6ab36 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 @@ -805,7 +805,7 @@ public boolean updateArtifactPaths(ProjectModule projectModule, boolean redeploy // When generating to the src dir, mojo deploy will copy the files from src to the server. // When not generating to the src dir, we must copy the generated features file here. if (!generateToSrc) { - // Copy the file here to be used by updateExistingFeatures() below even though file watcher will also copy it + // Copy the file here to be used by updateExistingFeatures() below util.copyGeneratedFeaturesFile(serverDirectory); // finalize the generate-features operation } } From c7c09bbfdf20d7d7f5b5965149be83b7589f93ca Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 20 Feb 2026 16:26:08 -0500 Subject: [PATCH 059/103] Update a different comment Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d06b6ab36..05a89933b 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 @@ -1176,7 +1176,7 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat runLibertyMojoCreate(); } else if (redeployApp) { runLibertyMojoDeploy(); - // Copy the file here to be used by updateExistingFeatures() below even though file watcher will also copy it + // Copy the file here to be used by updateExistingFeatures() below // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install if (generateFeaturesSuccess && !generateToSrc) { util.copyGeneratedFeaturesFile(serverDirectory); // finalize the generate-features operation From 51c5f0bce3d18d4666bf5316e1ef4c7797aa5657 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 20 Feb 2026 17:14:58 -0500 Subject: [PATCH 060/103] Move mojo deploy after copy of gen. features file to serverDir Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 05a89933b..d3b921604 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 @@ -1175,12 +1175,12 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat } else if (createServer) { runLibertyMojoCreate(); } else if (redeployApp) { - runLibertyMojoDeploy(); // Copy the file here to be used by updateExistingFeatures() below // If generateToSrc is false then we must copy new generated features file from temp dir to server dir after install if (generateFeaturesSuccess && !generateToSrc) { util.copyGeneratedFeaturesFile(serverDirectory); // finalize the generate-features operation } + runLibertyMojoDeploy(); // Update the features after deploy mojo has copied the config files to server dir and generated features file added if (generateFeaturesSuccess) { updateExistingFeatures(); // update the dev mode cache of features in the server From bcff0583d53911a22fa250088241c910ce92cdcb Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 30 Mar 2026 18:51:32 -0400 Subject: [PATCH 061/103] Move the check for server dir after the check for multimodules Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index dedb0fada..f7c3bdc5e 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -135,10 +135,6 @@ protected void init() throws MojoExecutionException { } super.init(); - // Ensure server dir exists to generate features to the $serverDirectory/configDropins/overrides/generated-features.xml - if (!generateToSrc && !serverDirectory.exists()) { - throw new MojoExecutionException("The 'generate-features' goal requires an existing Liberty server in directory " + serverDirectory.getPath() + ". Please run the 'liberty:create' goal before 'generate-features'."); - } } @Override @@ -182,7 +178,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().info("\nSkipping module " + project.getArtifactId() + " which is not configured for the generate-features goal.\n"); return; } - + List downstreamProjects = graph.getDownstreamProjects(project, true); if (!downstreamProjects.isEmpty()) { getLog().debug("Downstream projects: " + downstreamProjects); @@ -209,6 +205,10 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx return; } } + // Ensure server dir exists to generate features to the $serverDirectory/configDropins/overrides/generated-features.xml + if (!generateToSrc && !serverDirectory.exists()) { + throw new MojoExecutionException("The 'generate-features' goal requires an existing Liberty server in directory " + serverDirectory.getPath() + ". Please run the 'liberty:create' goal before 'generate-features'."); + } if (useTempDirAsContext) { // When this parameter is true it is required that the caller has copied the config into this dir. From 8d44408734ed4d2f822812150026f67ac83ab170 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 2 Apr 2026 19:12:01 -0400 Subject: [PATCH 062/103] Collect the base feature list file and pass it to the binary scanner Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index dedb0fada..46144883a 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -61,9 +61,6 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { public static final String NO_CLASSES_DIR_WARNING = "Could not find classes directory to generate features against. Liberty features will not be generated. " + "Ensure your project has first been compiled."; - // The executable file used to scan binaries for the Liberty features they use. - private File binaryScanner; - @Parameter(property = "classFiles") private List classFiles; @@ -220,11 +217,12 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // When using dev mode we always generate to a temporary directory so we can call install before writing to server dir. generationOutputDir = useTempDirAsOutput ? getGeneratedFeaturesTempDir() : generationContextDir; - binaryScanner = getBinaryScannerJarFromRepository(); - BinaryScannerHandler binaryScannerHandler = new BinaryScannerHandler(binaryScanner); + // The executable file used to scan binaries for the Liberty features they use. + File binaryScannerJar = getBinaryScannerJarFromRepository(); + BinaryScannerHandler binaryScannerHandler = new BinaryScannerHandler(binaryScannerJar); getLog().debug("--- Generate Features values ---"); - getLog().debug("Binary scanner jar: " + binaryScanner.getName()); + getLog().debug("Binary scanner jar: " + binaryScannerJar.getName()); getLog().debug("optimize generate features: " + optimize); getLog().debug("useTempDirAsOutput (dev mode only): " + useTempDirAsOutput); getLog().debug("useTempDirAsContext (dev mode only): " + useTempDirAsContext); @@ -282,7 +280,10 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx String logLocation = project.getBuild().getDirectory(); String eeVersionArg = composeEEVersion(eeVersion); String mpVersionArg = composeMPVersion(mpVersion); - scannedFeatureList = binaryScannerHandler.runBinaryScanner(nonCustomFeatures, classFiles, directories, logLocation, eeVersionArg, mpVersionArg, optimize); + File baseFeatureListFile = getBaseFeatureListFileFromRepository(); + File coreFeatureListFile = getBaseFeatureListFileFromRepository(); + scannedFeatureList = binaryScannerHandler.runBinaryScanner(nonCustomFeatures, classFiles, directories, logLocation, + eeVersionArg, mpVersionArg, baseFeatureListFile, coreFeatureListFile, optimize); } catch (BinaryScannerUtil.NoRecommendationException noRecommendation) { throw new MojoExecutionException(String.format(BinaryScannerUtil.BINARY_SCANNER_CONFLICT_MESSAGE3, noRecommendation.getConflicts())); } catch (BinaryScannerUtil.FeatureModifiedException featuresModified) { @@ -443,6 +444,32 @@ private File getBinaryScannerJarFromRepository() throws PluginExecutionException } } + /** + * Gets the file containing the Websphere or Open Liberty base feature list from the local cache. + * Downloads it first from connected repositories such as Maven Central if a newer release is available than the cached version. + * Note: Maven updates artifacts daily by default based on the last updated timestamp. Users should use 'mvn -U' to force updates if needed. + * + * @return The File object of the feature list in the local cache. + * @throws PluginExecutionException + */ + private File getBaseFeatureListFileFromRepository() throws PluginExecutionException { + try { + getLog().warn ("retrieve the artifact " + OLBASE_FEATURELIST_GROUP_ID + "." + + OLBASE_FEATURELIST_ARTIFACT_ID + "." + OLBASE_FEATURELIST_TYPE + "." + OLBASE_FEATURELIST_VERSION + + " needed for liberty:generate-features. Ensure you have a connection to Maven Central or another repository that contains the " + + OLBASE_FEATURELIST_GROUP_ID + "." + OLBASE_FEATURELIST_ARTIFACT_ID + + " configured in your pom.xml."); + return getArtifact(OLBASE_FEATURELIST_GROUP_ID, OLBASE_FEATURELIST_ARTIFACT_ID, OLBASE_FEATURELIST_TYPE, OLBASE_FEATURELIST_VERSION).getFile(); + } catch (Exception e) { + getLog().debug("Could not retrieve the artifact " + OLBASE_FEATURELIST_GROUP_ID + "." + + OLBASE_FEATURELIST_ARTIFACT_ID + "." + OLBASE_FEATURELIST_TYPE + "." + OLBASE_FEATURELIST_VERSION + + " needed for liberty:generate-features. Ensure you have a connection to Maven Central or another repository that contains the " + + OLBASE_FEATURELIST_GROUP_ID + "." + OLBASE_FEATURELIST_ARTIFACT_ID + + " configured in your pom.xml."); + return null; + } + } + // Return a list containing the classes directory of the Maven projects (upstream projects and main project) private Set getClassesDirectories(List mavenProjects) throws MojoExecutionException { Set dirs = new HashSet(); From cbaa34344c33330242e9382bb2ab7e07addccd6d Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 6 Apr 2026 11:54:56 -0400 Subject: [PATCH 063/103] Get the Liberty version Co-authored-by-AI: IBM Bob 1.0.0 Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 46144883a..b32fff425 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -26,6 +26,8 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; +import org.apache.maven.Maven; +import org.apache.maven.artifact.Artifact; import org.apache.maven.execution.ProjectDependencyGraph; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.MojoExecutionException; @@ -216,7 +218,9 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } // When using dev mode we always generate to a temporary directory so we can call install before writing to server dir. generationOutputDir = useTempDirAsOutput ? getGeneratedFeaturesTempDir() : generationContextDir; +// +// // The executable file used to scan binaries for the Liberty features they use. File binaryScannerJar = getBinaryScannerJarFromRepository(); BinaryScannerHandler binaryScannerHandler = new BinaryScannerHandler(binaryScannerJar); @@ -470,6 +474,30 @@ private File getBaseFeatureListFileFromRepository() throws PluginExecutionExcept } } + /* + * Gets the file containing the Websphere or Open Liberty base feature list from the local cache. + * Downloads it first from connected repositories such as Maven Central if a newer release is available than the cached version. + * Note: Maven updates artifacts daily by default based on the last updated timestamp. Users should use 'mvn -U' to force updates if needed. + * + * @return The File object of the feature list in the local cache. + */ + private void getFeatureListFiles(File baseFeatureListFile, File coreFeatureListFile) { + String libertyVersion = null; + + // Check if libertyRuntimeVersion property is set (highest priority) + if (libertyRuntimeVersion != null && !libertyRuntimeVersion.isEmpty()) { + libertyVersion = libertyRuntimeVersion; + } else if (assemblyArtifact != null) { + // Resolve the artifact to get its version + Artifact artifact = getResolvedArtifact(assemblyArtifact); + if (artifact != null) { + libertyVersion = artifact.getVersion(); + } + } + getLog().warn ("--- libertyVersion=" + libertyVersion); + + } + // Return a list containing the classes directory of the Maven projects (upstream projects and main project) private Set getClassesDirectories(List mavenProjects) throws MojoExecutionException { Set dirs = new HashSet(); From e388784fd1caa3a57ced6ef076248efb894418ef Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 6 Apr 2026 18:14:30 -0400 Subject: [PATCH 064/103] Get the feature lists from open or closed liberty according to version number Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 115 +++++++++++++----- 1 file changed, 87 insertions(+), 28 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index b32fff425..de7b3cbbc 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -44,6 +44,7 @@ import io.openliberty.tools.common.plugins.util.PluginExecutionException; import io.openliberty.tools.common.plugins.util.ServerFeatureUtil; import io.openliberty.tools.common.plugins.util.ServerFeatureUtil.FeaturesPlatforms; +import io.openliberty.tools.common.plugins.util.VersionUtility; /** * This mojo generates the features required in the featureManager element in @@ -62,6 +63,8 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { public static final String NO_NEW_FEATURES_COMMENT = "No additional features generated"; public static final String NO_CLASSES_DIR_WARNING = "Could not find classes directory to generate features against. Liberty features will not be generated. " + "Ensure your project has first been compiled."; + private static final String OPEN_LIBERTY_PRODUCT_ID = "io.openliberty"; + private static final String CLOSED_LIBERTY_PRODUCT_ID = "com.ibm.websphere.appserver.runtime"; @Parameter(property = "classFiles") private List classFiles; @@ -284,8 +287,18 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx String logLocation = project.getBuild().getDirectory(); String eeVersionArg = composeEEVersion(eeVersion); String mpVersionArg = composeMPVersion(mpVersion); - File baseFeatureListFile = getBaseFeatureListFileFromRepository(); - File coreFeatureListFile = getBaseFeatureListFileFromRepository(); + File baseFeatureListFile = null; + File coreFeatureListFile = null; + String libertyGroupId = getLibertyRuntimeGroupId(); + getLog().debug("Resolve the liberty groupId used to fetch feature lists, getLibertyRuntimeGroupId()="+libertyGroupId); + if (CLOSED_LIBERTY_PRODUCT_ID.equals(libertyGroupId)) { + baseFeatureListFile = getClosedFeatureListFile(FEATURE_LIST_BASE); + coreFeatureListFile = getClosedFeatureListFile(FEATURE_LIST_CORE); + } else if (OPEN_LIBERTY_PRODUCT_ID.equals(libertyGroupId)) { + // For open liberty pass the same file to each parameter + baseFeatureListFile = getOpenFeatureListFile(); + coreFeatureListFile = baseFeatureListFile; + } // else should not happen, just pass null values scannedFeatureList = binaryScannerHandler.runBinaryScanner(nonCustomFeatures, classFiles, directories, logLocation, eeVersionArg, mpVersionArg, baseFeatureListFile, coreFeatureListFile, optimize); } catch (BinaryScannerUtil.NoRecommendationException noRecommendation) { @@ -448,54 +461,100 @@ private File getBinaryScannerJarFromRepository() throws PluginExecutionException } } - /** - * Gets the file containing the Websphere or Open Liberty base feature list from the local cache. + /* + * Gets the file containing the Open Liberty base feature list from the local cache. * Downloads it first from connected repositories such as Maven Central if a newer release is available than the cached version. - * Note: Maven updates artifacts daily by default based on the last updated timestamp. Users should use 'mvn -U' to force updates if needed. + * Note: Maven updates artifacts daily by default based on the last updated timestamp. Users should use 'mvn -U' to force + * updates if needed. * - * @return The File object of the feature list in the local cache. - * @throws PluginExecutionException + * @return The File object of the feature list in the local cache or null if version number not available */ - private File getBaseFeatureListFileFromRepository() throws PluginExecutionException { - try { - getLog().warn ("retrieve the artifact " + OLBASE_FEATURELIST_GROUP_ID + "." - + OLBASE_FEATURELIST_ARTIFACT_ID + "." + OLBASE_FEATURELIST_TYPE + "." + OLBASE_FEATURELIST_VERSION - + " needed for liberty:generate-features. Ensure you have a connection to Maven Central or another repository that contains the " - + OLBASE_FEATURELIST_GROUP_ID + "." + OLBASE_FEATURELIST_ARTIFACT_ID - + " configured in your pom.xml."); - return getArtifact(OLBASE_FEATURELIST_GROUP_ID, OLBASE_FEATURELIST_ARTIFACT_ID, OLBASE_FEATURELIST_TYPE, OLBASE_FEATURELIST_VERSION).getFile(); - } catch (Exception e) { - getLog().debug("Could not retrieve the artifact " + OLBASE_FEATURELIST_GROUP_ID + "." - + OLBASE_FEATURELIST_ARTIFACT_ID + "." + OLBASE_FEATURELIST_TYPE + "." + OLBASE_FEATURELIST_VERSION - + " needed for liberty:generate-features. Ensure you have a connection to Maven Central or another repository that contains the " - + OLBASE_FEATURELIST_GROUP_ID + "." + OLBASE_FEATURELIST_ARTIFACT_ID - + " configured in your pom.xml."); + public static String OPEN_LIBERTY_FEATURE_LIST_START = "25.0.0.7"; + private File getOpenFeatureListFile() throws MojoExecutionException { + String libertyVersion = getLibertyRuntimeVersion(); + if (libertyVersion == null) { return null; } + // Feature lists were first published for 25.0.0.7. For liberty releases prior to this simply use the + // earliest available feature list, 25.0.0.7. + if (VersionUtility.compareArtifactVersion(libertyVersion, OPEN_LIBERTY_FEATURE_LIST_START, true) < 0) { + libertyVersion = OPEN_LIBERTY_FEATURE_LIST_START; + } + libertyVersion = "[" + libertyVersion + "]"; // Maven syntax to specify an exact version, not a range + return getArtifact(OLBASE_FEATURELIST_GROUP_ID, OLBASE_FEATURELIST_ARTIFACT_ID, OLBASE_FEATURELIST_TYPE, libertyVersion).getFile(); } /* * Gets the file containing the Websphere or Open Liberty base feature list from the local cache. * Downloads it first from connected repositories such as Maven Central if a newer release is available than the cached version. - * Note: Maven updates artifacts daily by default based on the last updated timestamp. Users should use 'mvn -U' to force updates if needed. + * Note: Maven updates artifacts daily by default based on the last updated timestamp. Users should use 'mvn -U' to force + * updates if needed. * * @return The File object of the feature list in the local cache. */ - private void getFeatureListFiles(File baseFeatureListFile, File coreFeatureListFile) { - String libertyVersion = null; + private static String CLOSED_LIBERTY_FEATURE_LIST_START1 = "25.0.0.7"; + private static String CLOSED_LIBERTY_FEATURE_LIST_START2 = "25.0.0.10"; + private static String CLOSED_LIBERTY_FEATURE_LIST_END = "25.0.0.12"; + private static String FEATURE_LIST_BASE = "base"; + private static String FEATURE_LIST_CORE = "core"; + private File getClosedFeatureListFile(String featureListVar) throws MojoExecutionException { + // Feature lists are only available for 25.0.0.7 and 25.0.0.10-25.0.0.12. + // For releases earlier than 25.0.0.10 use 25.0.0.7, for releases after 25.0.0.12 use 25.0.0.12. + String libertyGroupId, libertyArtifactId; + String libertyVersion = getLibertyRuntimeVersion(); + if (libertyVersion == null) { + return null; + } + // There is a value for 25.0.0.7 but not for 25.0.0.8 or 25.0.0.9 and none for <25.0.0.7 + // so for any liberty <25.0.0.10 use the 07 values + if (VersionUtility.compareArtifactVersion(libertyVersion, CLOSED_LIBERTY_FEATURE_LIST_START2, true) < 0) { + libertyGroupId = WS1_FEATURELIST_GROUP_ID; + libertyVersion = CLOSED_LIBERTY_FEATURE_LIST_START1; + } else { // 25.0.0.10 and up + libertyGroupId = WS2_FEATURELIST_GROUP_ID; + // if >25.0.0.12 just use 25.0.0.12 + if (VersionUtility.compareArtifactVersion(libertyVersion, CLOSED_LIBERTY_FEATURE_LIST_END, true) > 0) { + libertyVersion = CLOSED_LIBERTY_FEATURE_LIST_END; + } // else liberty version is 25.0.0.10-25.0.0.12 + } + if (featureListVar.equals(FEATURE_LIST_BASE)) { + libertyArtifactId = WSBASE_FEATURELIST_ARTIFACT_ID; + } else { + libertyArtifactId = WSCORE_FEATURELIST_ARTIFACT_ID; + } + libertyVersion = "[" + libertyVersion + "]"; // Maven syntax to specify an exact version, not a range + getLog().debug("Closed liberty feature list coordinates, libertyGroupId="+libertyGroupId+" libertyArtifactId="+libertyArtifactId+" WS_FEATURELIST_TYPE="+WS_FEATURELIST_TYPE+" libertyVersion="+libertyVersion); + return getArtifact(libertyGroupId, libertyArtifactId, WS_FEATURELIST_TYPE, libertyVersion).getFile(); + } + // resolve the Liberty version from one of the sources + private String getLibertyRuntimeVersion() throws MojoExecutionException { // Check if libertyRuntimeVersion property is set (highest priority) if (libertyRuntimeVersion != null && !libertyRuntimeVersion.isEmpty()) { - libertyVersion = libertyRuntimeVersion; + return libertyRuntimeVersion; } else if (assemblyArtifact != null) { // Resolve the artifact to get its version Artifact artifact = getResolvedArtifact(assemblyArtifact); if (artifact != null) { - libertyVersion = artifact.getVersion(); + return artifact.getVersion(); + } + } + return null; + } + + // resolve the Liberty GroupId from one of the sources + private String getLibertyRuntimeGroupId() throws MojoExecutionException { + // Check if libertyRuntimeGroupId property is set (highest priority) + if (libertyRuntimeGroupId != null && !libertyRuntimeGroupId.isEmpty()) { + return libertyRuntimeGroupId; + } else if (assemblyArtifact != null) { + // Resolve the artifact to get its values + Artifact artifact = getResolvedArtifact(assemblyArtifact); + if (artifact != null) { + return artifact.getGroupId(); } } - getLog().warn ("--- libertyVersion=" + libertyVersion); - + return null; } // Return a list containing the classes directory of the Maven projects (upstream projects and main project) From 769a052ec0e6a7c9dd4a0165ad19d0fab37952d2 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 7 Apr 2026 12:01:39 -0400 Subject: [PATCH 065/103] Clean up comments Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index de7b3cbbc..3f3b1be75 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -221,9 +221,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } // When using dev mode we always generate to a temporary directory so we can call install before writing to server dir. generationOutputDir = useTempDirAsOutput ? getGeneratedFeaturesTempDir() : generationContextDir; -// -// // The executable file used to scan binaries for the Liberty features they use. File binaryScannerJar = getBinaryScannerJarFromRepository(); BinaryScannerHandler binaryScannerHandler = new BinaryScannerHandler(binaryScannerJar); From 893b2940882cb27b5dbe31b8eae130042d0a5a08 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 17 Apr 2026 11:51:14 -0400 Subject: [PATCH 066/103] Rework: clarify the name of open liberty Maven coordinates Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 3f3b1be75..f0b69de90 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -479,7 +479,7 @@ private File getOpenFeatureListFile() throws MojoExecutionException { libertyVersion = OPEN_LIBERTY_FEATURE_LIST_START; } libertyVersion = "[" + libertyVersion + "]"; // Maven syntax to specify an exact version, not a range - return getArtifact(OLBASE_FEATURELIST_GROUP_ID, OLBASE_FEATURELIST_ARTIFACT_ID, OLBASE_FEATURELIST_TYPE, libertyVersion).getFile(); + return getArtifact(OL_FEATURELIST_GROUP_ID, OL_FEATURELIST_ARTIFACT_ID, OL_FEATURELIST_TYPE, libertyVersion).getFile(); } /* From ddd2d730a5a3dccee4efd5ad96a80d8b76357ea5 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 17 Apr 2026 12:29:29 -0400 Subject: [PATCH 067/103] Rework to clarify the names of concepts Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index f0b69de90..4dac6e0dc 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -64,7 +64,7 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { public static final String NO_CLASSES_DIR_WARNING = "Could not find classes directory to generate features against. Liberty features will not be generated. " + "Ensure your project has first been compiled."; private static final String OPEN_LIBERTY_PRODUCT_ID = "io.openliberty"; - private static final String CLOSED_LIBERTY_PRODUCT_ID = "com.ibm.websphere.appserver.runtime"; + private static final String WEBSPHERE_LIBERTY_PRODUCT_ID = "com.ibm.websphere.appserver.runtime"; @Parameter(property = "classFiles") private List classFiles; @@ -289,9 +289,9 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx File coreFeatureListFile = null; String libertyGroupId = getLibertyRuntimeGroupId(); getLog().debug("Resolve the liberty groupId used to fetch feature lists, getLibertyRuntimeGroupId()="+libertyGroupId); - if (CLOSED_LIBERTY_PRODUCT_ID.equals(libertyGroupId)) { - baseFeatureListFile = getClosedFeatureListFile(FEATURE_LIST_BASE); - coreFeatureListFile = getClosedFeatureListFile(FEATURE_LIST_CORE); + if (WEBSPHERE_LIBERTY_PRODUCT_ID.equals(libertyGroupId)) { + baseFeatureListFile = getWebSphereFeatureListFile(FEATURE_LIST_BASE); + coreFeatureListFile = getWebSphereFeatureListFile(FEATURE_LIST_CORE); } else if (OPEN_LIBERTY_PRODUCT_ID.equals(libertyGroupId)) { // For open liberty pass the same file to each parameter baseFeatureListFile = getOpenFeatureListFile(); @@ -467,7 +467,7 @@ private File getBinaryScannerJarFromRepository() throws PluginExecutionException * * @return The File object of the feature list in the local cache or null if version number not available */ - public static String OPEN_LIBERTY_FEATURE_LIST_START = "25.0.0.7"; + private static String OPEN_LIBERTY_FEATURE_LIST_START = "25.0.0.7"; private File getOpenFeatureListFile() throws MojoExecutionException { String libertyVersion = getLibertyRuntimeVersion(); if (libertyVersion == null) { @@ -483,19 +483,19 @@ private File getOpenFeatureListFile() throws MojoExecutionException { } /* - * Gets the file containing the Websphere or Open Liberty base feature list from the local cache. + * Gets the file containing the Websphere base feature list from the local cache. * Downloads it first from connected repositories such as Maven Central if a newer release is available than the cached version. * Note: Maven updates artifacts daily by default based on the last updated timestamp. Users should use 'mvn -U' to force * updates if needed. * * @return The File object of the feature list in the local cache. */ - private static String CLOSED_LIBERTY_FEATURE_LIST_START1 = "25.0.0.7"; - private static String CLOSED_LIBERTY_FEATURE_LIST_START2 = "25.0.0.10"; - private static String CLOSED_LIBERTY_FEATURE_LIST_END = "25.0.0.12"; + private static String WEBSPHERE_LIBERTY_FEATURE_LIST_START = "25.0.0.7"; + private static String WEBSPHERE_LIBERTY_FEATURE_LIST_CONTINUE = "25.0.0.10"; + private static String WEBSPHERE_LIBERTY_FEATURE_LIST_END = "25.0.0.12"; private static String FEATURE_LIST_BASE = "base"; private static String FEATURE_LIST_CORE = "core"; - private File getClosedFeatureListFile(String featureListVar) throws MojoExecutionException { + private File getWebSphereFeatureListFile(String featureListVar) throws MojoExecutionException { // Feature lists are only available for 25.0.0.7 and 25.0.0.10-25.0.0.12. // For releases earlier than 25.0.0.10 use 25.0.0.7, for releases after 25.0.0.12 use 25.0.0.12. String libertyGroupId, libertyArtifactId; @@ -505,14 +505,14 @@ private File getClosedFeatureListFile(String featureListVar) throws MojoExecutio } // There is a value for 25.0.0.7 but not for 25.0.0.8 or 25.0.0.9 and none for <25.0.0.7 // so for any liberty <25.0.0.10 use the 07 values - if (VersionUtility.compareArtifactVersion(libertyVersion, CLOSED_LIBERTY_FEATURE_LIST_START2, true) < 0) { + if (VersionUtility.compareArtifactVersion(libertyVersion, WEBSPHERE_LIBERTY_FEATURE_LIST_CONTINUE, true) < 0) { libertyGroupId = WS1_FEATURELIST_GROUP_ID; - libertyVersion = CLOSED_LIBERTY_FEATURE_LIST_START1; + libertyVersion = WEBSPHERE_LIBERTY_FEATURE_LIST_START; } else { // 25.0.0.10 and up libertyGroupId = WS2_FEATURELIST_GROUP_ID; // if >25.0.0.12 just use 25.0.0.12 - if (VersionUtility.compareArtifactVersion(libertyVersion, CLOSED_LIBERTY_FEATURE_LIST_END, true) > 0) { - libertyVersion = CLOSED_LIBERTY_FEATURE_LIST_END; + if (VersionUtility.compareArtifactVersion(libertyVersion, WEBSPHERE_LIBERTY_FEATURE_LIST_END, true) > 0) { + libertyVersion = WEBSPHERE_LIBERTY_FEATURE_LIST_END; } // else liberty version is 25.0.0.10-25.0.0.12 } if (featureListVar.equals(FEATURE_LIST_BASE)) { @@ -521,7 +521,7 @@ private File getClosedFeatureListFile(String featureListVar) throws MojoExecutio libertyArtifactId = WSCORE_FEATURELIST_ARTIFACT_ID; } libertyVersion = "[" + libertyVersion + "]"; // Maven syntax to specify an exact version, not a range - getLog().debug("Closed liberty feature list coordinates, libertyGroupId="+libertyGroupId+" libertyArtifactId="+libertyArtifactId+" WS_FEATURELIST_TYPE="+WS_FEATURELIST_TYPE+" libertyVersion="+libertyVersion); + getLog().debug("WebSphere Liberty feature list coordinates, libertyGroupId="+libertyGroupId+" libertyArtifactId="+libertyArtifactId+" WS_FEATURELIST_TYPE="+WS_FEATURELIST_TYPE+" libertyVersion="+libertyVersion); return getArtifact(libertyGroupId, libertyArtifactId, WS_FEATURELIST_TYPE, libertyVersion).getFile(); } From 892bdc2f9b5695787c40496b7440674bf61b9113 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 17 Apr 2026 12:36:50 -0400 Subject: [PATCH 068/103] Update a comment Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 4dac6e0dc..f51567eeb 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -483,7 +483,7 @@ private File getOpenFeatureListFile() throws MojoExecutionException { } /* - * Gets the file containing the Websphere base feature list from the local cache. + * Gets the file containing the indicated Websphere feature list from the local cache. * Downloads it first from connected repositories such as Maven Central if a newer release is available than the cached version. * Note: Maven updates artifacts daily by default based on the last updated timestamp. Users should use 'mvn -U' to force * updates if needed. From 2b1a78468ba1bb712c0f4ce1f947a5b0b4f73637 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 17 Apr 2026 12:41:04 -0400 Subject: [PATCH 069/103] Update liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java Clarify a comment Co-authored-by: Trevor Crawford --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index f51567eeb..111092eab 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -460,7 +460,7 @@ private File getBinaryScannerJarFromRepository() throws PluginExecutionException } /* - * Gets the file containing the Open Liberty base feature list from the local cache. + * Gets the file containing the Open Liberty feature list from the local cache. * Downloads it first from connected repositories such as Maven Central if a newer release is available than the cached version. * Note: Maven updates artifacts daily by default based on the last updated timestamp. Users should use 'mvn -U' to force * updates if needed. From 45c4fe01153b4d89303a354c92883301bc2f35cb Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 7 Apr 2026 18:29:21 -0400 Subject: [PATCH 070/103] Collect version numbers from all JavaEE umbrella dependencies and return the maximum number Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 56 +++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 69ee0934c..3a15ca885 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -26,8 +26,8 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; -import org.apache.maven.Maven; import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.maven.execution.ProjectDependencyGraph; import org.apache.maven.model.Dependency; import org.apache.maven.plugin.MojoExecutionException; @@ -610,19 +610,11 @@ public String getEEVersion(List mavenProjects) { // umbrella dependency does not exist, do nothing } } - if (!eeVersionsDetected.isEmpty()) { - eeVersion = eeVersionsDetected.iterator().next(); - // if multiple EE versions are found across multiple modules, return the latest version - for (String ver : eeVersionsDetected) { - if (ver.compareTo(eeVersion) > 0) { - eeVersion = ver; - } - } - } + eeVersion = findMaxVersion(eeVersionsDetected); if (eeVersionsDetected.size() > 1) { getLog().debug( - "Multiple Java and/or Jakarta EE versions found across multiple project modules, using the latest version (" - + eeVersion + ") found to generate Liberty features."); + "Multiple Java and/or Jakarta EE versions found across multiple project modules, using the latest version (" + + eeVersion + ") found to generate Liberty features."); } } return eeVersion; @@ -640,19 +632,51 @@ public String getEEVersion(List mavenProjects) { private String getEEVersion(MavenProject project) throws NoUmbrellaDependencyException { if (project != null) { List dependencies = project.getDependencies(); + Set eeVersionsDetected = new HashSet(); for (Dependency d : dependencies) { - if (!d.getScope().equals("provided")) { + String scope = d.getScope(); + String groupId = d.getGroupId(); + String artifactId = d.getArtifactId(); + if (scope == null || groupId == null || artifactId == null) { continue; } - if ((d.getGroupId().equals("javax") && d.getArtifactId().equals("javaee-api")) || - (d.getGroupId().equals("jakarta.platform") && d.getArtifactId().equals("jakarta.jakartaee-api"))) { - return d.getVersion(); + if (!scope.equals("provided") && !scope.equals("compile") && !scope.equals("import")) { + continue; + } + if ((groupId.equals("javax") && artifactId.equals("javaee-api")) || + (groupId.equals("jakarta.platform") && + (artifactId.equals("jakarta.jakartaee-api") || + artifactId.equals("jakarta.jakartaee-web-api") || + artifactId.equals("jakarta.jakartaee-core-api") || + artifactId.equals("jakarta.jakartaee-bom") || + artifactId.equals("jakartaee-api-parent")))) { + eeVersionsDetected.add(d.getVersion()); } } + return findMaxVersion(eeVersionsDetected); } throw new NoUmbrellaDependencyException(); } + // Find the highest version number in the set of strings + private String findMaxVersion(Set eeVersionsDetected) { + String maxVersion = null; + if (!eeVersionsDetected.isEmpty()) { + maxVersion = eeVersionsDetected.iterator().next(); + ComparableVersion cMaxVersion = new ComparableVersion(maxVersion); + // if multiple EE versions are found across multiple modules, return the latest version + for (String ver : eeVersionsDetected) { + ComparableVersion cVer = new ComparableVersion(ver); + getLog().debug("GenerateFeraturesMojo.findMaxVersion, ver=" + ver); + if (cVer.compareTo(cMaxVersion) > 0) { + maxVersion = ver; + cMaxVersion = cVer; + } + } + } + return maxVersion; + } + /** * Returns the MicroProfile version detected for the given MavenProjects * From 643dbbbf97b5291ae2dad145328f94edf694e176 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 17 Apr 2026 16:46:29 -0400 Subject: [PATCH 071/103] Rework: remove complicated exception mechanism, make two messages info level Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 122 ++++++++---------- 1 file changed, 53 insertions(+), 69 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 3a15ca885..1f7d4afb4 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -600,21 +600,16 @@ public String getEEVersion(List mavenProjects) { if (mavenProjects != null) { Set eeVersionsDetected = new HashSet(); for (MavenProject mavenProject : mavenProjects) { - try { - String ver = getEEVersion(mavenProject); - getLog().debug("Java and/or Jakarta EE umbrella dependency found in project: " + mavenProject.getName()); - if (ver != null) { - eeVersionsDetected.add(ver); - } - } catch (NoUmbrellaDependencyException e) { - // umbrella dependency does not exist, do nothing + String ver = getEEVersion(mavenProject); + getLog().debug("Java and/or Jakarta EE umbrella dependency version: " + ver + " found in project: " + mavenProject.getName()); + if (ver != null) { + eeVersionsDetected.add(ver); } } eeVersion = findMaxVersion(eeVersionsDetected); if (eeVersionsDetected.size() > 1) { - getLog().debug( - "Multiple Java and/or Jakarta EE versions found across multiple project modules, using the latest version (" + - eeVersion + ") found to generate Liberty features."); + getLog().info("Multiple Java EE and/or Jakarta EE versions found across multiple project modules, using the latest version (" + + eeVersion + ") found to generate Liberty features."); } } return eeVersion; @@ -627,35 +622,34 @@ public String getEEVersion(List mavenProjects) { * * @param project the MavenProject to search * @return EE major version corresponding to the EE umbrella dependency - * @throws NoUmbrellaDependencyException indicates that the umbrella dependency was not found */ - private String getEEVersion(MavenProject project) throws NoUmbrellaDependencyException { - if (project != null) { - List dependencies = project.getDependencies(); - Set eeVersionsDetected = new HashSet(); - for (Dependency d : dependencies) { - String scope = d.getScope(); - String groupId = d.getGroupId(); - String artifactId = d.getArtifactId(); - if (scope == null || groupId == null || artifactId == null) { - continue; - } - if (!scope.equals("provided") && !scope.equals("compile") && !scope.equals("import")) { - continue; - } - if ((groupId.equals("javax") && artifactId.equals("javaee-api")) || - (groupId.equals("jakarta.platform") && - (artifactId.equals("jakarta.jakartaee-api") || - artifactId.equals("jakarta.jakartaee-web-api") || - artifactId.equals("jakarta.jakartaee-core-api") || - artifactId.equals("jakarta.jakartaee-bom") || - artifactId.equals("jakartaee-api-parent")))) { - eeVersionsDetected.add(d.getVersion()); - } + private String getEEVersion(MavenProject project) { + if (project == null) { + return null; + } + List dependencies = project.getDependencies(); + Set eeVersionsDetected = new HashSet(); + for (Dependency d : dependencies) { + String scope = d.getScope(); + String groupId = d.getGroupId(); + String artifactId = d.getArtifactId(); + if (scope == null || groupId == null || artifactId == null) { + continue; + } + if (!scope.equals("provided") && !scope.equals("compile") && !scope.equals("import")) { + continue; + } + if ((groupId.equals("javax") && artifactId.equals("javaee-api")) || + (groupId.equals("jakarta.platform") && + (artifactId.equals("jakarta.jakartaee-api") || + artifactId.equals("jakarta.jakartaee-web-api") || + artifactId.equals("jakarta.jakartaee-core-api") || + artifactId.equals("jakarta.jakartaee-bom") || + artifactId.equals("jakartaee-api-parent")))) { + eeVersionsDetected.add(d.getVersion()); } - return findMaxVersion(eeVersionsDetected); } - throw new NoUmbrellaDependencyException(); + return findMaxVersion(eeVersionsDetected); } // Find the highest version number in the set of strings @@ -663,6 +657,9 @@ private String findMaxVersion(Set eeVersionsDetected) { String maxVersion = null; if (!eeVersionsDetected.isEmpty()) { maxVersion = eeVersionsDetected.iterator().next(); + if (eeVersionsDetected.size() == 1) { + return maxVersion; + } ComparableVersion cMaxVersion = new ComparableVersion(maxVersion); // if multiple EE versions are found across multiple modules, return the latest version for (String ver : eeVersionsDetected) { @@ -689,14 +686,10 @@ public String getMPVersion(List mavenProjects) { if (mavenProjects != null) { Set mpVersionsDetected = new HashSet(); for (MavenProject mavenProject : mavenProjects) { - try { - String ver = getMPVersion(mavenProject); - getLog().debug("MicroProfile umbrella dependency found in project: " + mavenProject.getName()); - if (ver != null) { - mpVersionsDetected.add(ver); - } - } catch (NoUmbrellaDependencyException e) { - // umbrella dependency does not exist, do nothing + String ver = getMPVersion(mavenProject); + getLog().debug("MicroProfile umbrella dependency version: " + ver + " found in project: " + mavenProject.getName()); + if (ver != null) { + mpVersionsDetected.add(ver); } } if (!mpVersionsDetected.isEmpty()) { @@ -709,9 +702,8 @@ public String getMPVersion(List mavenProjects) { } } if (mpVersionsDetected.size() > 1) { - getLog().debug( - "Multiple MicroProfile versions found across multiple project modules, using the latest version (" - + mpVersion + ") found to generate Liberty features."); + getLog().info("Multiple MicroProfile versions found across multiple project modules, using the latest version (" + + mpVersion + ") found to generate Liberty features."); } } return mpVersion; @@ -724,22 +716,22 @@ public String getMPVersion(List mavenProjects) { * * @param project the MavenProject to search * @return MP exact version code corresponding to the MP umbrella dependency - * @throws NoUmbrellaDependencyException indicates that the umbrella dependency was not found */ - public String getMPVersion(MavenProject project) throws NoUmbrellaDependencyException { // figure out correct level of MP from declared dependencies - if (project != null) { - List dependencies = project.getDependencies(); - for (Dependency d : dependencies) { - if (!d.getScope().equals("provided")) { - continue; - } - if (d.getGroupId().equals("org.eclipse.microprofile") && - d.getArtifactId().equals("microprofile")) { - return d.getVersion(); - } + public String getMPVersion(MavenProject project) { + if (project == null) { + return null; + } + List dependencies = project.getDependencies(); + for (Dependency d : dependencies) { + if (!d.getScope().equals("provided")) { + continue; + } + if (d.getGroupId().equals("org.eclipse.microprofile") && + d.getArtifactId().equals("microprofile")) { + return d.getVersion(); } } - throw new NoUmbrellaDependencyException(); + return null; } // Define the logging functions of the binary scanner handler and make it available in this plugin @@ -779,12 +771,4 @@ private MavenProject getMavenProject(File buildFile) throws ProjectBuildingExcep session.getProjectBuildingRequest().setResolveDependencies(true)); return build.getProject(); } - - /** - * Class to indicate that an umbrella dependency was not found in the build file - */ - public class NoUmbrellaDependencyException extends Exception { - private static final long serialVersionUID = 1L; - } - } From be184c9c31d207842b0a2f97fb84f2ae4bd78fa7 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 17 Apr 2026 16:48:19 -0400 Subject: [PATCH 072/103] Update liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java Update the comment describing return value Co-authored-by: Trevor Crawford --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 1 + 1 file changed, 1 insertion(+) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 1f7d4afb4..3aa4524d0 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -653,6 +653,7 @@ private String getEEVersion(MavenProject project) { } // Find the highest version number in the set of strings + // returns null if the set of strings is empty private String findMaxVersion(Set eeVersionsDetected) { String maxVersion = null; if (!eeVersionsDetected.isEmpty()) { From cd8c2caf8aa22374554c272be40e810b740b99fe Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 17 Apr 2026 16:59:48 -0400 Subject: [PATCH 073/103] Use Maven knowledgable compare method for MP versions Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 1f7d4afb4..99557598e 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -692,15 +692,8 @@ public String getMPVersion(List mavenProjects) { mpVersionsDetected.add(ver); } } - if (!mpVersionsDetected.isEmpty()) { - mpVersion = mpVersionsDetected.iterator().next(); - // if multiple MP versions are found across multiple modules, return the latest version - for (String ver : mpVersionsDetected) { - if (ver.compareTo(mpVersion) > 0) { - mpVersion = ver; - } - } - } + // if multiple MP versions are found across multiple modules, return the latest version + mpVersion = findMaxVersion(mpVersionsDetected); if (mpVersionsDetected.size() > 1) { getLog().info("Multiple MicroProfile versions found across multiple project modules, using the latest version (" + mpVersion + ") found to generate Liberty features."); From 3ecc5a63e20e8e80d79ad6c90c3793a8c5080944 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 17 Apr 2026 18:18:27 -0400 Subject: [PATCH 074/103] Fix up variable name Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 2625d1e5f..a66cc36e1 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -654,16 +654,16 @@ private String getEEVersion(MavenProject project) { // Find the highest version number in the set of strings // returns null if the set of strings is empty - private String findMaxVersion(Set eeVersionsDetected) { + private String findMaxVersion(Set versionsDetected) { String maxVersion = null; - if (!eeVersionsDetected.isEmpty()) { - maxVersion = eeVersionsDetected.iterator().next(); - if (eeVersionsDetected.size() == 1) { + if (!versionsDetected.isEmpty()) { + maxVersion = versionsDetected.iterator().next(); + if (versionsDetected.size() == 1) { return maxVersion; } ComparableVersion cMaxVersion = new ComparableVersion(maxVersion); - // if multiple EE versions are found across multiple modules, return the latest version - for (String ver : eeVersionsDetected) { + // if multiple EE/MP versions are found across multiple modules, return the latest version + for (String ver : versionsDetected) { ComparableVersion cVer = new ComparableVersion(ver); getLog().debug("GenerateFeraturesMojo.findMaxVersion, ver=" + ver); if (cVer.compareTo(cMaxVersion) > 0) { From 35868e4ff1716e183d6fe977454683f9561fabe4 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 8 Apr 2026 17:58:41 -0400 Subject: [PATCH 075/103] Get platforms from server.xml and use to get version number for jakarta and microprofile for use in generate-features Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index a66cc36e1..ffef4336b 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -279,8 +279,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // user specified features getLog().warn(NO_CLASSES_DIR_WARNING); } - eeVersion = getEEVersion(mavenProjects); - mpVersion = getMPVersion(mavenProjects); + eeVersion = getEEVersion(mavenProjects, servUtil); + mpVersion = getMPVersion(mavenProjects, servUtil); String logLocation = project.getBuild().getDirectory(); String eeVersionArg = composeEEVersion(eeVersion); @@ -406,8 +406,15 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } } - // Get the features from the server config and optionally exclude the specified config files from the search. private Set getServerFeatures(ServerFeatureUtil servUtil, Set generatedFiles, boolean excludeGenerated) { + return getServerFeaturesPlatforms(servUtil, generatedFiles, excludeGenerated, true); + } + private Set getServerPlatforms(ServerFeatureUtil servUtil, Set generatedFiles, boolean excludeGenerated) { + return getServerFeaturesPlatforms(servUtil, generatedFiles, excludeGenerated, false); // platforms + } + + // Get the features from the server config and optionally exclude the specified config files from the search. + private Set getServerFeaturesPlatforms(ServerFeatureUtil servUtil, Set generatedFiles, boolean excludeGenerated, boolean features) { servUtil.setLowerCaseFeatures(false); // if optimizing, ignore generated files when passing in existing features to // binary scanner @@ -416,8 +423,10 @@ private Set getServerFeatures(ServerFeatureUtil servUtil, Set ge servUtil.setLowerCaseFeatures(true); if (fp == null) { return new HashSet(); - } - return fp.getFeatures(); + } else if (features) { + return fp.getFeatures(); + } // else + return fp.getPlatforms(); } // returns the features specified in the generated-features.xml file in the generation context directory @@ -595,7 +604,8 @@ private String getClassesDirectory(String outputDir) { * @return the latest version of EE detected across multiple project modules, * null if an EE version is not found or the version number is out of range */ - public String getEEVersion(List mavenProjects) { + private static final String JAKARTA_PLATFORM_NAME="jakartaee-"; // jakartaee-10.0 etc. + public String getEEVersion(List mavenProjects, ServerFeatureUtil servUtil) { String eeVersion = null; if (mavenProjects != null) { Set eeVersionsDetected = new HashSet(); @@ -612,6 +622,9 @@ public String getEEVersion(List mavenProjects) { eeVersion + ") found to generate Liberty features."); } } + if (eeVersion == null) { + eeVersion = getPlatformVersion(JAKARTA_PLATFORM_NAME, servUtil); + } return eeVersion; } @@ -682,7 +695,8 @@ private String findMaxVersion(Set versionsDetected) { * @return the latest version of MP detected across multiple project modules, * null if an MP version is not found or the version number is out of range */ - public String getMPVersion(List mavenProjects) { + private static final String MP_PLATFORM_NAME="microProfile-"; // microProfile-7.0 etc. + public String getMPVersion(List mavenProjects, ServerFeatureUtil servUtil) { String mpVersion = null; if (mavenProjects != null) { Set mpVersionsDetected = new HashSet(); @@ -700,6 +714,9 @@ public String getMPVersion(List mavenProjects) { mpVersion + ") found to generate Liberty features."); } } + if (mpVersion == null) { + mpVersion = getPlatformVersion(MP_PLATFORM_NAME, servUtil); + } return mpVersion; } @@ -728,6 +745,19 @@ public String getMPVersion(MavenProject project) { return null; } + // Retrieve all platforms from the server.xml and related files and look for the platform specified. + // Platforms have the format jakartaee-10.0 or microProfile-7.1. Just return the version number (10.0 or 7.1 in these examples). + private String getPlatformVersion(String platformName, ServerFeatureUtil servUtil) { + Set platforms = getServerPlatforms(servUtil, null, false); + for (String p : platforms) { + getLog().debug("GenerateFeaturesMojo.getPlatformVersion, searching for platform:" + platformName + " platform=" + p); + if (p.startsWith(platformName)) { + return p.substring(platformName.length()); + } + } + return null; + } + // Define the logging functions of the binary scanner handler and make it available in this plugin private class BinaryScannerHandler extends BinaryScannerUtil { BinaryScannerHandler(File scannerFile) { From 732ca70349125d28e7099719abf574c7ce7929f0 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 8 Apr 2026 18:11:11 -0400 Subject: [PATCH 076/103] Add handling for javaee platform in generate-features Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index ffef4336b..1294c9c24 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -605,6 +605,7 @@ private String getClassesDirectory(String outputDir) { * null if an EE version is not found or the version number is out of range */ private static final String JAKARTA_PLATFORM_NAME="jakartaee-"; // jakartaee-10.0 etc. + private static final String JAVAEE_PLATFORM_NAME="javaee-"; // javaee-7.0 etc. public String getEEVersion(List mavenProjects, ServerFeatureUtil servUtil) { String eeVersion = null; if (mavenProjects != null) { @@ -622,9 +623,14 @@ public String getEEVersion(List mavenProjects, ServerFeatureUtil s eeVersion + ") found to generate Liberty features."); } } + // if the dependencies do not indicate the Jakarta version then reference the platform specified in server.xml + // E.g. pom may specify jakarta.persistence:jakarta.persistence-api:2.2.3 to compile but does not specify Jakarta 9.1 if (eeVersion == null) { eeVersion = getPlatformVersion(JAKARTA_PLATFORM_NAME, servUtil); } + if (eeVersion == null) { + eeVersion = getPlatformVersion(JAVAEE_PLATFORM_NAME, servUtil); + } return eeVersion; } From 2b1e03f638062c329342cc795ee56f46c710f154 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 15 Apr 2026 17:50:10 -0400 Subject: [PATCH 077/103] Add isDevMode parameter to generate features mojo Signed-off-by: Paul Gooderham --- .../openliberty/tools/maven/server/StartDebugMojoSupport.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 c61efb58f..948f7b44e 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 @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2014, 2025. + * (C) Copyright IBM Corporation 2014, 2026 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -247,6 +247,7 @@ protected void runLibertyMojoGenerateFeatures(Element classFiles, boolean optimi if (classFiles != null) { config = Xpp3Dom.mergeXpp3Dom(configuration(classFiles), config); } + config.addChild(element(name("isDevMode"), "true").toDom()); config.addChild(element(name("optimize"), Boolean.toString(optimize)).toDom()); config.addChild(element(name("generateToSrc"), Boolean.toString(generateToSrc)).toDom()); config.addChild(element(name("useTempDirAsOutput"), Boolean.toString(useTmpDirOut)).toDom()); From aebe818569601c3e79384eeeafe40b2e85ed1c50 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 15 Apr 2026 18:36:29 -0400 Subject: [PATCH 078/103] Add isDevMode parameter and write generated features file to server dir conditionally Co-authored-by-AI: IBM Bob 1.0.1 Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 65 +++++++++++++++++-- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 1294c9c24..2c07b941c 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -83,6 +83,16 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { @Parameter(property = "generateToSrc", defaultValue = "false") private boolean generateToSrc; + /** + * The isDevMode parameter is for internal use only. It is not for users. + * This parameter must only be set to true when this mojo is called from dev mode and false otherwise. + * This parameter is added to support generateToSrc and to cause writing the generated features file + * to the server directory (if it exists) in stand-alone mode (not dev mode) in order to save the user + * having to copy it manually. + */ + @Parameter(property = "isDevMode", defaultValue = "false") + private boolean isDevMode; + /** * The useTempDirAsOutput parameter is for internal use only. It is not for users. * The parameter is only used when generateToSrc is false meaning we generate to serverDir. @@ -261,6 +271,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx generatedFiles.add(GENERATED_FEATURES_FILE_NAME); Set existingFeatures = getServerFeatures(servUtil, generatedFiles, optimize); + getLog().warn ("existingFeatures = " + existingFeatures); Set nonCustomFeatures = new HashSet(); // binary scanner only handles actual Liberty features for (String feature : existingFeatures) { // custom features are "usr:feature-1.0" or "myExt:feature-2.0" if (!feature.contains(":")) nonCustomFeatures.add(feature); @@ -364,6 +375,20 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // generate the new features into an xml file in the correct context directory // The ServerConfigXmlDocument class will create the directories if needed. File generatedXmlFile = new File(generationOutputDir, GENERATED_FEATURES_FILE_PATH); + + // For standalone goal (not dev mode) with generateToSrc=true, also write to server dir if it exists + boolean shouldWriteToServerDir = !isDevMode && generateToSrc && (serverDirectory != null) && serverDirectory.exists(); + File serverDirXmlFile = null; + if (shouldWriteToServerDir) { + serverDirXmlFile = new File(serverDirectory, GENERATED_FEATURES_FILE_PATH); + } + getLog().warn ("!isDevMode=" + !isDevMode); + getLog().warn ("generateToSrc=" + generateToSrc); + getLog().warn ("serverDirectory=" + serverDirectory); + getLog().warn ("serverDirectory.exists()=" + serverDirectory.exists()); + getLog().warn ("shouldWriteToServerDir=" + shouldWriteToServerDir); + getLog().warn ("serverDirXmlFile=" + serverDirXmlFile); + try { if (missingLibertyFeatures.size() > 0) { Set existingGeneratedFeatures = getGeneratedFeatures(servUtil, generatedXmlFile); @@ -381,6 +406,15 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().info("Generated the following features: " + missingLibertyFeatures); configDocument.writeXMLDocument(generatedXmlFile); getLog().debug("Created file " + generatedXmlFile.getAbsolutePath()); + + // For standalone mode with generateToSrc=true, also write to server directory + if (shouldWriteToServerDir) { + getLog().warn ("Also creating file " + serverDirXmlFile.getAbsolutePath()); + if (writeToServerDir(configDocument, serverDirXmlFile, true)) { + getLog().debug("Also created file " + serverDirXmlFile.getAbsolutePath()); + getLog().warn ("Also created file " + serverDirXmlFile.getAbsolutePath()); + } + } } else { getLog().info("Regenerated the following features: " + missingLibertyFeatures); } @@ -394,16 +428,36 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx Element featureManagerElem = configDocument.createFeatureManager(); configDocument.createComment(featureManagerElem, NO_NEW_FEATURES_COMMENT); configDocument.writeXMLDocument(generatedXmlFile); + + // For standalone mode with generateToSrc=true, also write to server directory + if (shouldWriteToServerDir) { + getLog().warn ("Also maybe rewriting file " + serverDirXmlFile.getAbsolutePath()); + writeToServerDir(configDocument, serverDirXmlFile, serverDirXmlFile.exists()); + } } } } catch (ParserConfigurationException | TransformerException | IOException e) { getLog().debug("Exception creating the server features file", e); - throw new MojoExecutionException( - "Automatic generation of features failed. Error attempting to create the " - + GENERATED_FEATURES_FILE_NAME - + ". Ensure your id has write permission to the server configuration directory.", - e); + throw new MojoExecutionException( + "Automatic generation of features failed. Error attempting to create the " + + GENERATED_FEATURES_FILE_NAME + + ". Ensure your id has write permission to the server configuration directory.", + e); + } + + } + + private boolean writeToServerDir(ServerConfigXmlDocument configDocument, File serverDirXmlFile, boolean exists) { + if (exists) { + try { + configDocument.writeXMLDocument(serverDirXmlFile); + } catch (TransformerException | IOException e) { + getLog().warn("Failed to write generated-features.xml to server directory: " + + serverDirXmlFile.getAbsolutePath() + ". " + e.getMessage()); + return false; + } } + return true; } private Set getServerFeatures(ServerFeatureUtil servUtil, Set generatedFiles, boolean excludeGenerated) { @@ -416,6 +470,7 @@ private Set getServerPlatforms(ServerFeatureUtil servUtil, Set g // Get the features from the server config and optionally exclude the specified config files from the search. private Set getServerFeaturesPlatforms(ServerFeatureUtil servUtil, Set generatedFiles, boolean excludeGenerated, boolean features) { servUtil.setLowerCaseFeatures(false); + getLog().warn (" generatedFiles="+generatedFiles+" exclu="+excludeGenerated); // if optimizing, ignore generated files when passing in existing features to // binary scanner FeaturesPlatforms fp = servUtil.getServerFeatures(generationContextDir, serverXmlFile, From 930518db67372e96b9d5a97b90c6de0227d1ab8e Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 15 Apr 2026 18:52:27 -0400 Subject: [PATCH 079/103] Remove skipServerConfigSetup because it is no longer needed by GenerateFeaturesMojo Signed-off-by: Paul Gooderham --- .../java/io/openliberty/tools/maven/BasicSupport.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/BasicSupport.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/BasicSupport.java index 9a98d5299..1b06fcd14 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/BasicSupport.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/BasicSupport.java @@ -22,9 +22,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Enumeration; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Properties; import java.util.ResourceBundle; import java.util.zip.ZipEntry; @@ -61,8 +59,6 @@ public abstract class BasicSupport extends AbstractLibertySupport { protected boolean defaultOutputDirSet = false; - protected boolean skipServerConfigSetup = false; - /** * Skips the specific goal */ @@ -206,10 +202,6 @@ protected void init() throws MojoExecutionException { super.init(); - if (skipServerConfigSetup) { - return; - } - try { // First check if installDirectory is set, if it is, then we can skip this if (installDirectory != null) { From 548c8830cd1f3729a668de63db5b69240e452204 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Wed, 15 Apr 2026 18:59:29 -0400 Subject: [PATCH 080/103] Remove skipServerConfigSetup so serverDirectory will be available even when generateToSrc=true Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 2c07b941c..7b6d7aeae 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -138,16 +138,8 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { @Override protected void init() throws MojoExecutionException { - // @see io.openliberty.tools.maven.BasicSupport#init() - // Skip server directories setup when generate features only requires - // the files in the src config directory. - // The server directories to be set up: install dir, wlp dir, outputdir, etc. - if (generateToSrc) { - this.skipServerConfigSetup = true; - } - super.init(); - } + } @Override public void execute() throws MojoExecutionException { @@ -271,7 +263,6 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx generatedFiles.add(GENERATED_FEATURES_FILE_NAME); Set existingFeatures = getServerFeatures(servUtil, generatedFiles, optimize); - getLog().warn ("existingFeatures = " + existingFeatures); Set nonCustomFeatures = new HashSet(); // binary scanner only handles actual Liberty features for (String feature : existingFeatures) { // custom features are "usr:feature-1.0" or "myExt:feature-2.0" if (!feature.contains(":")) nonCustomFeatures.add(feature); @@ -382,12 +373,6 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx if (shouldWriteToServerDir) { serverDirXmlFile = new File(serverDirectory, GENERATED_FEATURES_FILE_PATH); } - getLog().warn ("!isDevMode=" + !isDevMode); - getLog().warn ("generateToSrc=" + generateToSrc); - getLog().warn ("serverDirectory=" + serverDirectory); - getLog().warn ("serverDirectory.exists()=" + serverDirectory.exists()); - getLog().warn ("shouldWriteToServerDir=" + shouldWriteToServerDir); - getLog().warn ("serverDirXmlFile=" + serverDirXmlFile); try { if (missingLibertyFeatures.size() > 0) { @@ -409,10 +394,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // For standalone mode with generateToSrc=true, also write to server directory if (shouldWriteToServerDir) { - getLog().warn ("Also creating file " + serverDirXmlFile.getAbsolutePath()); if (writeToServerDir(configDocument, serverDirXmlFile, true)) { getLog().debug("Also created file " + serverDirXmlFile.getAbsolutePath()); - getLog().warn ("Also created file " + serverDirXmlFile.getAbsolutePath()); } } } else { @@ -431,7 +414,6 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // For standalone mode with generateToSrc=true, also write to server directory if (shouldWriteToServerDir) { - getLog().warn ("Also maybe rewriting file " + serverDirXmlFile.getAbsolutePath()); writeToServerDir(configDocument, serverDirXmlFile, serverDirXmlFile.exists()); } } @@ -470,7 +452,6 @@ private Set getServerPlatforms(ServerFeatureUtil servUtil, Set g // Get the features from the server config and optionally exclude the specified config files from the search. private Set getServerFeaturesPlatforms(ServerFeatureUtil servUtil, Set generatedFiles, boolean excludeGenerated, boolean features) { servUtil.setLowerCaseFeatures(false); - getLog().warn (" generatedFiles="+generatedFiles+" exclu="+excludeGenerated); // if optimizing, ignore generated files when passing in existing features to // binary scanner FeaturesPlatforms fp = servUtil.getServerFeatures(generationContextDir, serverXmlFile, From b6bcc3ebf553516b6585546ba7ebd0f5ce7f3525 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 17 Apr 2026 18:12:00 -0400 Subject: [PATCH 081/103] Rework: simplify the code writing the generate-features file to the server dir Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 7b6d7aeae..c98213530 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -394,7 +394,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // For standalone mode with generateToSrc=true, also write to server directory if (shouldWriteToServerDir) { - if (writeToServerDir(configDocument, serverDirXmlFile, true)) { + if (writeToServerDir(configDocument, serverDirXmlFile)) { getLog().debug("Also created file " + serverDirXmlFile.getAbsolutePath()); } } @@ -413,8 +413,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx configDocument.writeXMLDocument(generatedXmlFile); // For standalone mode with generateToSrc=true, also write to server directory - if (shouldWriteToServerDir) { - writeToServerDir(configDocument, serverDirXmlFile, serverDirXmlFile.exists()); + if (shouldWriteToServerDir && serverDirXmlFile.exists()) { + writeToServerDir(configDocument, serverDirXmlFile); } } } @@ -429,15 +429,18 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } - private boolean writeToServerDir(ServerConfigXmlDocument configDocument, File serverDirXmlFile, boolean exists) { - if (exists) { - try { - configDocument.writeXMLDocument(serverDirXmlFile); - } catch (TransformerException | IOException e) { - getLog().warn("Failed to write generated-features.xml to server directory: " - + serverDirXmlFile.getAbsolutePath() + ". " + e.getMessage()); - return false; - } + /* + * This routine writes an xml document to the specififed file and returns false if there is an exception + * while writing or true otherwise. + */ + private boolean writeToServerDir(ServerConfigXmlDocument configDocument, File serverDirXmlFile) { + try { + configDocument.writeXMLDocument(serverDirXmlFile); + } catch (TransformerException | IOException e) { + getLog().warn("Failed to write generated-features.xml to server directory: " + + serverDirXmlFile.getAbsolutePath() + ". Ensure your id has write permission to the server configuration directory. " + + e.getMessage()); + return false; } return true; } From 3b02a142558d91e3786bc20885c72b6d984d95a6 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 20 Apr 2026 12:58:12 -0400 Subject: [PATCH 082/103] Rework: print full path name in error message when generate features throws an exception. Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index c98213530..14e6a51b6 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -422,7 +422,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug("Exception creating the server features file", e); throw new MojoExecutionException( "Automatic generation of features failed. Error attempting to create the " - + GENERATED_FEATURES_FILE_NAME + + generatedXmlFile.getAbsolutePath() + ". Ensure your id has write permission to the server configuration directory.", e); } From eeeef65a6ee86d9eaf58c853f50c47fbba2beb66 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 20 Apr 2026 15:04:40 -0400 Subject: [PATCH 083/103] Update liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java Update message. Co-authored-by: Trevor Crawford --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 14e6a51b6..6aeb81c73 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -423,7 +423,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx throw new MojoExecutionException( "Automatic generation of features failed. Error attempting to create the " + generatedXmlFile.getAbsolutePath() - + ". Ensure your id has write permission to the server configuration directory.", + + ". Ensure your id has write permission to the directory the generated features file will be written to.", e); } From a55dcf51a9fac1c2361054d21889f1d1b9204a07 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 20 Apr 2026 18:18:19 -0400 Subject: [PATCH 084/103] Use the binary scanner API with a Map Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 6aeb81c73..04c96a931 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -21,6 +21,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import javax.xml.parsers.ParserConfigurationException; @@ -287,20 +288,23 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx String logLocation = project.getBuild().getDirectory(); String eeVersionArg = composeEEVersion(eeVersion); String mpVersionArg = composeMPVersion(mpVersion); - File baseFeatureListFile = null; - File coreFeatureListFile = null; + + Map featureListFileMap = new HashMap(); String libertyGroupId = getLibertyRuntimeGroupId(); getLog().debug("Resolve the liberty groupId used to fetch feature lists, getLibertyRuntimeGroupId()="+libertyGroupId); if (WEBSPHERE_LIBERTY_PRODUCT_ID.equals(libertyGroupId)) { - baseFeatureListFile = getWebSphereFeatureListFile(FEATURE_LIST_BASE); - coreFeatureListFile = getWebSphereFeatureListFile(FEATURE_LIST_CORE); + File baseFeatureListFile = getWebSphereFeatureListFile(FEATURE_LIST_BASE); + featureListFileMap.put(WSBASE_FEATURELIST_KEY, baseFeatureListFile); + File coreFeatureListFile = getWebSphereFeatureListFile(FEATURE_LIST_CORE); + featureListFileMap.put(WSCORE_FEATURELIST_KEY, coreFeatureListFile); } else if (OPEN_LIBERTY_PRODUCT_ID.equals(libertyGroupId)) { // For open liberty pass the same file to each parameter - baseFeatureListFile = getOpenFeatureListFile(); - coreFeatureListFile = baseFeatureListFile; - } // else should not happen, just pass null values + File featureListFile = getOpenFeatureListFile(); + featureListFileMap.put(OL_FEATURELIST_KEY, featureListFile); + } // else should not happen, just pass empty map + scannedFeatureList = binaryScannerHandler.runBinaryScanner(nonCustomFeatures, classFiles, directories, logLocation, - eeVersionArg, mpVersionArg, baseFeatureListFile, coreFeatureListFile, optimize); + eeVersionArg, mpVersionArg, featureListFileMap, optimize); } catch (BinaryScannerUtil.NoRecommendationException noRecommendation) { throw new MojoExecutionException(String.format(BinaryScannerUtil.BINARY_SCANNER_CONFLICT_MESSAGE3, noRecommendation.getConflicts())); } catch (BinaryScannerUtil.FeatureModifiedException featuresModified) { From d5f9be8b590fc7a307647cfb27b8685cb9571a8f Mon Sep 17 00:00:00 2001 From: Trevor Crawford Date: Tue, 21 Apr 2026 13:40:34 -0400 Subject: [PATCH 085/103] Updated user facing output (#2002) * Updated user facing output * EE or MP missing message should be info level * Update wording for how to disable feature gen after exception occurs on startup --- .../tools/maven/server/DevMojo.java | 10 ++++---- .../maven/server/GenerateFeaturesMojo.java | 24 +++++++++++++++---- 2 files changed, 25 insertions(+), 9 deletions(-) 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 d3b921604..77dc2ff19 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 @@ -1717,9 +1717,11 @@ private void generateFeaturesOnStartup() throws MojoExecutionException { generatedFileCanonicalPath = new File(configDirectory, BinaryScannerUtil.GENERATED_FEATURES_FILE_PATH).toString(); } - getLog().warn( - "The source configuration directory will be modified. Features will automatically be generated in a new file: " - + generatedFileCanonicalPath); + if (generateToSrc) { + getLog().info( + "The source configuration directory will be modified. Features will automatically be generated in a new file: " + + generatedFileCanonicalPath); + } // During dev mode start up the server is not running yet so we will generate features to the correct // output directory and then install features in the next step. runLibertyMojoGenerateFeatures(null, true, generateToSrc, false, false); @@ -1730,7 +1732,7 @@ private void generateFeaturesOnStartup() throws MojoExecutionException { generateFeatures = false; } else { throw new MojoExecutionException(e.getMessage() - + " To disable the automatic generation of features, start dev mode with -DgenerateFeatures=false.", + + " To disable the automatic generation of features, type 'g' and press 'Enter' once dev mode is running or restart dev mode with -DgenerateFeatures=false.", e); } } diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 6aeb81c73..1034be079 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -58,7 +58,7 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { public static final String HEADER = "This file was generated by the Liberty Maven Plugin and will be overwritten on subsequent runs of the liberty:generate-features goal." - + "\n It is recommended that you do not edit this file and that you commit this file to your version control."; + + "\n It is recommended that you do not edit this file."; public static final String GENERATED_FEATURES_COMMENT = "The following features were generated based on API usage detected in your application"; public static final String NO_NEW_FEATURES_COMMENT = "No additional features generated"; public static final String NO_CLASSES_DIR_WARNING = "Could not find classes directory to generate features against. Liberty features will not be generated. " @@ -387,8 +387,9 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx getLog().debug(String.format("Adding missing feature %s to %s.", missing, GENERATED_FEATURES_FILE_PATH)); configDocument.createFeature(missing); } - // Generate log message before writing file as the file change event kicks off other dev mode actions + // Output log messages before writing file as the file change event kicks off other dev mode actions getLog().info("Generated the following features: " + missingLibertyFeatures); + printCommonMessages(eeVersion, mpVersion, generatedXmlFile); configDocument.writeXMLDocument(generatedXmlFile); getLog().debug("Created file " + generatedXmlFile.getAbsolutePath()); @@ -399,7 +400,8 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } } } else { - getLog().info("Regenerated the following features: " + missingLibertyFeatures); + getLog().info("No change to the generated feature list: " + missingLibertyFeatures); + printCommonMessages(eeVersion, mpVersion, generatedXmlFile); } } else { getLog().info("No additional features were generated."); @@ -423,12 +425,24 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx throw new MojoExecutionException( "Automatic generation of features failed. Error attempting to create the " + generatedXmlFile.getAbsolutePath() - + ". Ensure your id has write permission to the directory the generated features file will be written to.", + + ". Ensure your ID has write permission to the directory the generated features file will be written to.", e); } } + /* + * This method prints the output for both cases when features are generated (i.e., new features were generated or the same set) + */ + private void printCommonMessages(String eeVersion, String mpVersion, File generatedXmlFile) { + getLog().info("The generated feature list has been written to the following file: " + generatedXmlFile.getAbsolutePath()); + if (eeVersion == null && mpVersion == null) { + getLog().info("Verify the generated feature list meets the needs of your application." + + " If you see features missing or features at unexpected versions, please add the expected features to your server configuration" + + (isDevMode ? "." : " and run the generate-features goal again.")); + } + } + /* * This routine writes an xml document to the specififed file and returns false if there is an exception * while writing or true otherwise. @@ -438,7 +452,7 @@ private boolean writeToServerDir(ServerConfigXmlDocument configDocument, File se configDocument.writeXMLDocument(serverDirXmlFile); } catch (TransformerException | IOException e) { getLog().warn("Failed to write generated-features.xml to server directory: " - + serverDirXmlFile.getAbsolutePath() + ". Ensure your id has write permission to the server configuration directory. " + + serverDirXmlFile.getAbsolutePath() + ". Ensure your ID has write permission to the server configuration directory. " + e.getMessage()); return false; } From 4c4f7110c7c470d96d3407f0f181824f1370b55e Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 21 Apr 2026 14:12:25 -0400 Subject: [PATCH 086/103] Rework: remove outdated comment Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 1 - 1 file changed, 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 04c96a931..21611e4f8 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -298,7 +298,6 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx File coreFeatureListFile = getWebSphereFeatureListFile(FEATURE_LIST_CORE); featureListFileMap.put(WSCORE_FEATURELIST_KEY, coreFeatureListFile); } else if (OPEN_LIBERTY_PRODUCT_ID.equals(libertyGroupId)) { - // For open liberty pass the same file to each parameter File featureListFile = getOpenFeatureListFile(); featureListFileMap.put(OL_FEATURELIST_KEY, featureListFile); } // else should not happen, just pass empty map From 75fbeb31399137cc1265269dddfb8588bc7ddba3 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 20 Apr 2026 17:32:59 -0400 Subject: [PATCH 087/103] Gather all platforms of each type and find max version number in gen. features Co-authored-by-AI: IBM Bob 1.0.1 --- .../maven/server/GenerateFeaturesMojo.java | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 1034be079..d13c94f48 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -679,10 +679,16 @@ public String getEEVersion(List mavenProjects, ServerFeatureUtil s // if the dependencies do not indicate the Jakarta version then reference the platform specified in server.xml // E.g. pom may specify jakarta.persistence:jakarta.persistence-api:2.2.3 to compile but does not specify Jakarta 9.1 if (eeVersion == null) { - eeVersion = getPlatformVersion(JAKARTA_PLATFORM_NAME, servUtil); - } - if (eeVersion == null) { - eeVersion = getPlatformVersion(JAVAEE_PLATFORM_NAME, servUtil); + Set platformVersions = new HashSet(); + // Gather all Jakarta EE platform versions + platformVersions.addAll(getAllPlatformVersions(JAKARTA_PLATFORM_NAME, servUtil)); + getLog().warn("platformVersions="+platformVersions); + // Gather all Java EE platform versions + platformVersions.addAll(getAllPlatformVersions(JAVAEE_PLATFORM_NAME, servUtil)); + getLog().warn("platformVersions="+platformVersions); + // Find the maximum version from all platforms + eeVersion = findMaxVersion(platformVersions); + getLog().warn("eeVersion="+eeVersion); } return eeVersion; } @@ -774,7 +780,7 @@ public String getMPVersion(List mavenProjects, ServerFeatureUtil s } } if (mpVersion == null) { - mpVersion = getPlatformVersion(MP_PLATFORM_NAME, servUtil); + mpVersion = findMaxVersion(getAllPlatformVersions(MP_PLATFORM_NAME, servUtil)); } return mpVersion; } @@ -804,19 +810,21 @@ public String getMPVersion(MavenProject project) { return null; } - // Retrieve all platforms from the server.xml and related files and look for the platform specified. - // Platforms have the format jakartaee-10.0 or microProfile-7.1. Just return the version number (10.0 or 7.1 in these examples). - private String getPlatformVersion(String platformName, ServerFeatureUtil servUtil) { + // Retrieve all platforms from the server.xml and related files that match the platform specified. + // Platforms have the format jakartaee-10.0 or microProfile-7.1. Return all version numbers (10.0, 7.1, etc.) that match. + private Set getAllPlatformVersions(String platformName, ServerFeatureUtil servUtil) { + Set platformVersions = new HashSet(); Set platforms = getServerPlatforms(servUtil, null, false); for (String p : platforms) { - getLog().debug("GenerateFeaturesMojo.getPlatformVersion, searching for platform:" + platformName + " platform=" + p); + getLog().debug("GenerateFeaturesMojo.getAllPlatformVersions, searching for platform:" + platformName + " platform=" + p); if (p.startsWith(platformName)) { - return p.substring(platformName.length()); + platformVersions.add(p.substring(platformName.length())); } } - return null; + return platformVersions; } + // Define the logging functions of the binary scanner handler and make it available in this plugin private class BinaryScannerHandler extends BinaryScannerUtil { BinaryScannerHandler(File scannerFile) { From f6e7cf5d90b1b5786ed049badd4778662d64e363 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 21 Apr 2026 15:01:04 -0400 Subject: [PATCH 088/103] Remove debug code Signed-off-by: Paul Gooderham --- .../openliberty/tools/maven/server/GenerateFeaturesMojo.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index d13c94f48..0e4eef3a6 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -682,13 +682,10 @@ public String getEEVersion(List mavenProjects, ServerFeatureUtil s Set platformVersions = new HashSet(); // Gather all Jakarta EE platform versions platformVersions.addAll(getAllPlatformVersions(JAKARTA_PLATFORM_NAME, servUtil)); - getLog().warn("platformVersions="+platformVersions); // Gather all Java EE platform versions platformVersions.addAll(getAllPlatformVersions(JAVAEE_PLATFORM_NAME, servUtil)); - getLog().warn("platformVersions="+platformVersions); // Find the maximum version from all platforms eeVersion = findMaxVersion(platformVersions); - getLog().warn("eeVersion="+eeVersion); } return eeVersion; } From 81162af60e7eb0feabfa23b526ebc92d374a9eb5 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Tue, 21 Apr 2026 16:05:02 -0400 Subject: [PATCH 089/103] Update ci.common version in pom.xml --- liberty-maven-plugin/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/pom.xml b/liberty-maven-plugin/pom.xml index 114a5262d..73f3455a0 100644 --- a/liberty-maven-plugin/pom.xml +++ b/liberty-maven-plugin/pom.xml @@ -100,7 +100,7 @@ io.openliberty.tools ci.common - 1.8.41-SNAPSHOT + 1.8.42-SNAPSHOT org.apache.commons From 66fc67b8b512a9e2393210a2212bb32b86286934 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 23 Apr 2026 16:49:07 -0400 Subject: [PATCH 090/103] When a versionless feature exception is detected then print a message Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index e2d0419b3..6df6d9bd1 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -64,6 +64,15 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { public static final String NO_NEW_FEATURES_COMMENT = "No additional features generated"; public static final String NO_CLASSES_DIR_WARNING = "Could not find classes directory to generate features against. Liberty features will not be generated. " + "Ensure your project has first been compiled."; + public static final String VERSIONLESS_FEATURE_DETECTED_DEVMODE = "If you would like to continue using auto-generation of features, " + + "please remove all versionless features from your server configuration. " + + "If you would like to continue using versionless features, you can turn off auto-generation " + + "of features by using the g hot key to toggle off auto-generation of features."; + public static final String VERSIONLESS_FEATURE_DETECTED = "Versionless features detected in the server configuration. " + + "If you would like to use auto-generation of features, " + + "remove all versionless features from your server configuration. " + + "If you would like to continue using versionless features, you cannot use " + + "the generate-features mojo."; private static final String OPEN_LIBERTY_PRODUCT_ID = "io.openliberty"; private static final String WEBSPHERE_LIBERTY_PRODUCT_ID = "com.ibm.websphere.appserver.runtime"; @@ -338,6 +347,14 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx } catch (BinaryScannerUtil.IllegalTargetException illegalTargets) { String messages = buildInvalidArgExceptionMessage(illegalTargets.getEELevel(), illegalTargets.getMPLevel(), eeVersion, mpVersion); throw new MojoExecutionException(messages); + } catch (BinaryScannerUtil.VersionlessFeatureDetectedException versionless) { + String messages; + if (isDevMode) { + messages = VERSIONLESS_FEATURE_DETECTED_DEVMODE; + } else { + messages = VERSIONLESS_FEATURE_DETECTED; + }; + throw new MojoExecutionException(messages); } catch (PluginExecutionException x) { // throw an error when there is a problem not caught in runBinaryScanner() Object o = x.getCause(); From 5c3d07ed5e24edb5aac0420a95da7990fd8845b2 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 23 Apr 2026 16:52:52 -0400 Subject: [PATCH 091/103] Code clean-up Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 6df6d9bd1..f33d85ee3 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -348,13 +348,7 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx String messages = buildInvalidArgExceptionMessage(illegalTargets.getEELevel(), illegalTargets.getMPLevel(), eeVersion, mpVersion); throw new MojoExecutionException(messages); } catch (BinaryScannerUtil.VersionlessFeatureDetectedException versionless) { - String messages; - if (isDevMode) { - messages = VERSIONLESS_FEATURE_DETECTED_DEVMODE; - } else { - messages = VERSIONLESS_FEATURE_DETECTED; - }; - throw new MojoExecutionException(messages); + throw new MojoExecutionException(isDevMode ? VERSIONLESS_FEATURE_DETECTED_DEVMODE : VERSIONLESS_FEATURE_DETECTED); } catch (PluginExecutionException x) { // throw an error when there is a problem not caught in runBinaryScanner() Object o = x.getCause(); From 0af64f9c89c8225a9e1f2d4fbb94cd6f871bea21 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 23 Apr 2026 16:55:12 -0400 Subject: [PATCH 092/103] Correct message Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index f33d85ee3..65d41935b 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -68,11 +68,9 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { + "please remove all versionless features from your server configuration. " + "If you would like to continue using versionless features, you can turn off auto-generation " + "of features by using the g hot key to toggle off auto-generation of features."; - public static final String VERSIONLESS_FEATURE_DETECTED = "Versionless features detected in the server configuration. " - + "If you would like to use auto-generation of features, " - + "remove all versionless features from your server configuration. " - + "If you would like to continue using versionless features, you cannot use " - + "the generate-features mojo."; + public static final String VERSIONLESS_FEATURE_DETECTED = "Versionless features are detected in the server configuration. " + + "If you would like to use auto-generation of features, remove all versionless features from your server configuration. " + + "If you would like to continue using versionless features, you cannot use the generate-features mojo."; private static final String OPEN_LIBERTY_PRODUCT_ID = "io.openliberty"; private static final String WEBSPHERE_LIBERTY_PRODUCT_ID = "com.ibm.websphere.appserver.runtime"; From e82aeabd49405cec2d784d551cb7bd886331df45 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 30 Apr 2026 12:07:48 -0400 Subject: [PATCH 093/103] Remove the exception message from a warning message Signed-off-by: Paul Gooderham --- .../openliberty/tools/maven/server/GenerateFeaturesMojo.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index e2d0419b3..22b34e514 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -455,8 +455,7 @@ private boolean writeToServerDir(ServerConfigXmlDocument configDocument, File se configDocument.writeXMLDocument(serverDirXmlFile); } catch (TransformerException | IOException e) { getLog().warn("Failed to write generated-features.xml to server directory: " - + serverDirXmlFile.getAbsolutePath() + ". Ensure your ID has write permission to the server configuration directory. " - + e.getMessage()); + + serverDirXmlFile.getAbsolutePath() + ". Ensure your ID has write permission to the server configuration directory. "); return false; } return true; From e06cd58431612a3ef2d715b97920c119563162f8 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 30 Apr 2026 12:10:35 -0400 Subject: [PATCH 094/103] Clean up a warning message Signed-off-by: Paul Gooderham --- .../io/openliberty/tools/maven/server/GenerateFeaturesMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 22b34e514..48a0c56c4 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -455,7 +455,7 @@ private boolean writeToServerDir(ServerConfigXmlDocument configDocument, File se configDocument.writeXMLDocument(serverDirXmlFile); } catch (TransformerException | IOException e) { getLog().warn("Failed to write generated-features.xml to server directory: " - + serverDirXmlFile.getAbsolutePath() + ". Ensure your ID has write permission to the server configuration directory. "); + + serverDirXmlFile.getAbsolutePath() + ". Ensure your ID has write permission to the server configuration directory."); return false; } return true; From e60436bab83b702b28ec35b7979eda03d016ea06 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Thu, 30 Apr 2026 18:42:30 -0400 Subject: [PATCH 095/103] Print a message if generating to server dir and there is a g-f.xml file in src Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index e2d0419b3..a0bd9f6fe 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -214,6 +214,19 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx if (!generateToSrc && !serverDirectory.exists()) { throw new MojoExecutionException("The 'generate-features' goal requires an existing Liberty server in directory " + serverDirectory.getPath() + ". Please run the 'liberty:create' goal before 'generate-features'."); } + // Detect if there is a generate-features.xml file in src already when generating to server dir + if (!generateToSrc && new File(configDirectory, GENERATED_FEATURES_FILE_PATH).exists()) { + if (isDevMode) { // this is serious because dev mode will overwrite the generated file when copying from src + getLog().error("A generated-features.xml file was detected in the configured source Liberty configuration directory. " + + "It will overwrite the file generated at this time. " + + "You must type 's' + Enter to toggle the option to generate features to the src directory or " + + "remove the generated-features.xml file in the Liberty configuration directory if you need to generate to the server directory."); + } else { // command line mojo just a warning that this configuration is not expected + getLog().warn("A generated-features.xml file was detected in the configured source Liberty configuration directory. " + + "You must use the option -DgenerateToSrc=true to update the source Liberty configuration directory or " + + "remove the generated-features.xml file in the source Liberty configuration directory if you intend to update the server directory."); + } + } if (useTempDirAsContext) { // When this parameter is true it is required that the caller has copied the config into this dir. From 71f0dcf853535a5bb781c7650b58458f0ee8c5c2 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 1 May 2026 17:48:56 -0400 Subject: [PATCH 096/103] Pass the correct parent directory to installFeaturesToTempDir Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 77dc2ff19..b543153a1 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 @@ -1131,7 +1131,7 @@ public boolean recompileBuildFile(File buildFile, Set compileArtifactPat // always optimize generate features on dependency change // If generateToSrc is false then we must copy (below) new generated features file from temp dir to server dir generateFeaturesSuccess = optimizeGenerateFeatures(!generateToSrc, false); - util.installFeaturesToTempDir(generateFeaturesFile, configDirectory, null, generateFeaturesSuccess); + util.installFeaturesToTempDir(generateFeaturesFile, generateFeaturesOutputDir, null, generateFeaturesSuccess); if (!generateFeaturesSuccess) { installFeature = false; // skip installing features if generate features fails } From bfeed36cd489e31901f39e36a3402138daf2faea Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 4 May 2026 12:42:06 -0400 Subject: [PATCH 097/103] Rewrite how we download feature lists for Websphere liberty Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index e2d0419b3..12012419e 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -555,35 +555,29 @@ private File getOpenFeatureListFile() throws MojoExecutionException { * * @return The File object of the feature list in the local cache. */ - private static String WEBSPHERE_LIBERTY_FEATURE_LIST_START = "25.0.0.7"; - private static String WEBSPHERE_LIBERTY_FEATURE_LIST_CONTINUE = "25.0.0.10"; - private static String WEBSPHERE_LIBERTY_FEATURE_LIST_END = "25.0.0.12"; private static String FEATURE_LIST_BASE = "base"; private static String FEATURE_LIST_CORE = "core"; private File getWebSphereFeatureListFile(String featureListVar) throws MojoExecutionException { - // Feature lists are only available for 25.0.0.7 and 25.0.0.10-25.0.0.12. - // For releases earlier than 25.0.0.10 use 25.0.0.7, for releases after 25.0.0.12 use 25.0.0.12. + // For releases earlier than 25.0.0.7 use 25.0.0.7 Maven coordinates (cadre1). + // For releases 25.0.0.8 to 25.0.0.12 use cadre 2 coordinates. + // For 26.0.0.1 and later use the third cadre. String libertyGroupId, libertyArtifactId; String libertyVersion = getLibertyRuntimeVersion(); if (libertyVersion == null) { return null; } - // There is a value for 25.0.0.7 but not for 25.0.0.8 or 25.0.0.9 and none for <25.0.0.7 - // so for any liberty <25.0.0.10 use the 07 values - if (VersionUtility.compareArtifactVersion(libertyVersion, WEBSPHERE_LIBERTY_FEATURE_LIST_CONTINUE, true) < 0) { - libertyGroupId = WS1_FEATURELIST_GROUP_ID; - libertyVersion = WEBSPHERE_LIBERTY_FEATURE_LIST_START; - } else { // 25.0.0.10 and up - libertyGroupId = WS2_FEATURELIST_GROUP_ID; - // if >25.0.0.12 just use 25.0.0.12 - if (VersionUtility.compareArtifactVersion(libertyVersion, WEBSPHERE_LIBERTY_FEATURE_LIST_END, true) > 0) { - libertyVersion = WEBSPHERE_LIBERTY_FEATURE_LIST_END; - } // else liberty version is 25.0.0.10-25.0.0.12 - } - if (featureListVar.equals(FEATURE_LIST_BASE)) { - libertyArtifactId = WSBASE_FEATURELIST_ARTIFACT_ID; - } else { - libertyArtifactId = WSCORE_FEATURELIST_ARTIFACT_ID; + // Publishing started with 25.0.0.7 so for any liberty <25.0.0.7 use the 07 values + if (VersionUtility.compareArtifactVersion(libertyVersion, WS_FEATURE_LIST_VERSION_CADRE1, true) <= 0) { + libertyGroupId = WS_FEATURELIST_GROUP_ID_CADRE1; + libertyArtifactId = (featureListVar.equals(FEATURE_LIST_BASE)) ? WS_BASE_FEATURE_LIST_ARTIFACT_ID_CADRE1 : WS_CORE_FEATURE_LIST_ARTIFACT_ID_CADRE1; + libertyVersion = WS_FEATURE_LIST_VERSION_CADRE1; // must set for versions before 07 + } else if (VersionUtility.compareArtifactVersion(libertyVersion, WS_FEATURE_LIST_VERSION_CADRE3, true) < 0) { + // 25.0.0.8 to 25.0.0.12 + libertyGroupId = WS_FEATURELIST_GROUP_ID_CADRE2; + libertyArtifactId = (featureListVar.equals(FEATURE_LIST_BASE)) ? WS_BASE_FEATURE_LIST_ARTIFACT_ID_CADRE2 : WS_CORE_FEATURE_LIST_ARTIFACT_ID_CADRE2; + } else { // 26.0.0.1 and up + libertyGroupId = WS_FEATURELIST_GROUP_ID_CADRE3; + libertyArtifactId = (featureListVar.equals(FEATURE_LIST_BASE)) ? WS_BASE_FEATURE_LIST_ARTIFACT_ID_CADRE3 : WS_CORE_FEATURE_LIST_ARTIFACT_ID_CADRE3; } libertyVersion = "[" + libertyVersion + "]"; // Maven syntax to specify an exact version, not a range getLog().debug("WebSphere Liberty feature list coordinates, libertyGroupId="+libertyGroupId+" libertyArtifactId="+libertyArtifactId+" WS_FEATURELIST_TYPE="+WS_FEATURELIST_TYPE+" libertyVersion="+libertyVersion); From 9e5f424f06734bc9526da8f7b057543666e8a35b Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 4 May 2026 19:04:51 -0400 Subject: [PATCH 098/103] Pass the correct parent directory to installFeaturesToTempDir in updateArtifactPaths also Signed-off-by: Paul Gooderham --- .../main/java/io/openliberty/tools/maven/server/DevMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b543153a1..f9173b59e 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 @@ -801,7 +801,7 @@ public boolean updateArtifactPaths(ProjectModule projectModule, boolean redeploy generateFeaturesSuccess = optimizeGenerateFeatures(!generateToSrc, false); // install new generated features because deploy will copy config files to server dir. // It will not trigger install-feature if the feature list has not changed - util.installFeaturesToTempDir(generateFeaturesFile, configDirectory, null, generateFeaturesSuccess); + util.installFeaturesToTempDir(generateFeaturesFile, generateFeaturesOutputDir, null, generateFeaturesSuccess); // When generating to the src dir, mojo deploy will copy the files from src to the server. // When not generating to the src dir, we must copy the generated features file here. if (!generateToSrc) { From 7ae01aa9f4a78cd2c4d7ecb4e60bb4f90ba1361c Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 8 May 2026 16:18:06 -0400 Subject: [PATCH 099/103] Apply suggestions from code review Co-authored-by: Trevor Crawford --- .../tools/maven/server/GenerateFeaturesMojo.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 65d41935b..19d779095 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -66,11 +66,11 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { + "Ensure your project has first been compiled."; public static final String VERSIONLESS_FEATURE_DETECTED_DEVMODE = "If you would like to continue using auto-generation of features, " + "please remove all versionless features from your server configuration. " - + "If you would like to continue using versionless features, you can turn off auto-generation " - + "of features by using the g hot key to toggle off auto-generation of features."; + + "If you would like to continue using versionless features, you can use the 'g' hot key " + + "to toggle off auto-generation of features."; public static final String VERSIONLESS_FEATURE_DETECTED = "Versionless features are detected in the server configuration. " - + "If you would like to use auto-generation of features, remove all versionless features from your server configuration. " - + "If you would like to continue using versionless features, you cannot use the generate-features mojo."; + + "To use the 'generate-features' goal, remove all versionless features from your server configuration. " + + "If you would like to continue using versionless features, you cannot use the 'generate-features' goal."; private static final String OPEN_LIBERTY_PRODUCT_ID = "io.openliberty"; private static final String WEBSPHERE_LIBERTY_PRODUCT_ID = "com.ibm.websphere.appserver.runtime"; From f0deb208b14f09b572dbd011ade6f57cbd1a4772 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 8 May 2026 16:51:25 -0400 Subject: [PATCH 100/103] Display exception message with descriptive label Signed-off-by: Paul Gooderham --- .../openliberty/tools/maven/server/GenerateFeaturesMojo.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 48a0c56c4..929ac300c 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -455,7 +455,8 @@ private boolean writeToServerDir(ServerConfigXmlDocument configDocument, File se configDocument.writeXMLDocument(serverDirXmlFile); } catch (TransformerException | IOException e) { getLog().warn("Failed to write generated-features.xml to server directory: " - + serverDirXmlFile.getAbsolutePath() + ". Ensure your ID has write permission to the server configuration directory."); + + serverDirXmlFile.getAbsolutePath() + ". Ensure your ID has write permission to the server configuration directory. " + + "Message from the Exception: " + e.getMessage()); return false; } return true; From a63623785a6fefc454c5f1eb4dceae1f18aa1b00 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 8 May 2026 17:12:18 -0400 Subject: [PATCH 101/103] Change the term cadre to batch Signed-off-by: Paul Gooderham --- .../maven/server/GenerateFeaturesMojo.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 12012419e..7e87cc97d 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -558,26 +558,26 @@ private File getOpenFeatureListFile() throws MojoExecutionException { private static String FEATURE_LIST_BASE = "base"; private static String FEATURE_LIST_CORE = "core"; private File getWebSphereFeatureListFile(String featureListVar) throws MojoExecutionException { - // For releases earlier than 25.0.0.7 use 25.0.0.7 Maven coordinates (cadre1). - // For releases 25.0.0.8 to 25.0.0.12 use cadre 2 coordinates. - // For 26.0.0.1 and later use the third cadre. + // For releases earlier than 25.0.0.7 use 25.0.0.7 Maven coordinates (batch 1). + // For releases 25.0.0.8 to 25.0.0.12 use batch 2 coordinates. + // For 26.0.0.1 and later use the third batch. String libertyGroupId, libertyArtifactId; String libertyVersion = getLibertyRuntimeVersion(); if (libertyVersion == null) { return null; } // Publishing started with 25.0.0.7 so for any liberty <25.0.0.7 use the 07 values - if (VersionUtility.compareArtifactVersion(libertyVersion, WS_FEATURE_LIST_VERSION_CADRE1, true) <= 0) { - libertyGroupId = WS_FEATURELIST_GROUP_ID_CADRE1; - libertyArtifactId = (featureListVar.equals(FEATURE_LIST_BASE)) ? WS_BASE_FEATURE_LIST_ARTIFACT_ID_CADRE1 : WS_CORE_FEATURE_LIST_ARTIFACT_ID_CADRE1; - libertyVersion = WS_FEATURE_LIST_VERSION_CADRE1; // must set for versions before 07 - } else if (VersionUtility.compareArtifactVersion(libertyVersion, WS_FEATURE_LIST_VERSION_CADRE3, true) < 0) { + if (VersionUtility.compareArtifactVersion(libertyVersion, WS_FEATURE_LIST_VERSION_BATCH1, true) <= 0) { + libertyGroupId = WS_FEATURELIST_GROUP_ID_BATCH1; + libertyArtifactId = (featureListVar.equals(FEATURE_LIST_BASE)) ? WS_BASE_FEATURE_LIST_ARTIFACT_ID_BATCH1 : WS_CORE_FEATURE_LIST_ARTIFACT_ID_BATCH1; + libertyVersion = WS_FEATURE_LIST_VERSION_BATCH1; // must set for versions before 07 + } else if (VersionUtility.compareArtifactVersion(libertyVersion, WS_FEATURE_LIST_VERSION_BATCH3, true) < 0) { // 25.0.0.8 to 25.0.0.12 - libertyGroupId = WS_FEATURELIST_GROUP_ID_CADRE2; - libertyArtifactId = (featureListVar.equals(FEATURE_LIST_BASE)) ? WS_BASE_FEATURE_LIST_ARTIFACT_ID_CADRE2 : WS_CORE_FEATURE_LIST_ARTIFACT_ID_CADRE2; + libertyGroupId = WS_FEATURELIST_GROUP_ID_BATCH2; + libertyArtifactId = (featureListVar.equals(FEATURE_LIST_BASE)) ? WS_BASE_FEATURE_LIST_ARTIFACT_ID_BATCH2 : WS_CORE_FEATURE_LIST_ARTIFACT_ID_BATCH2; } else { // 26.0.0.1 and up - libertyGroupId = WS_FEATURELIST_GROUP_ID_CADRE3; - libertyArtifactId = (featureListVar.equals(FEATURE_LIST_BASE)) ? WS_BASE_FEATURE_LIST_ARTIFACT_ID_CADRE3 : WS_CORE_FEATURE_LIST_ARTIFACT_ID_CADRE3; + libertyGroupId = WS_FEATURELIST_GROUP_ID_BATCH3; + libertyArtifactId = (featureListVar.equals(FEATURE_LIST_BASE)) ? WS_BASE_FEATURE_LIST_ARTIFACT_ID_BATCH3 : WS_CORE_FEATURE_LIST_ARTIFACT_ID_BATCH3; } libertyVersion = "[" + libertyVersion + "]"; // Maven syntax to specify an exact version, not a range getLog().debug("WebSphere Liberty feature list coordinates, libertyGroupId="+libertyGroupId+" libertyArtifactId="+libertyArtifactId+" WS_FEATURELIST_TYPE="+WS_FEATURELIST_TYPE+" libertyVersion="+libertyVersion); From 2fac8cff47b2208c9412db190a412b6f4cb62fd3 Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Fri, 8 May 2026 18:46:31 -0400 Subject: [PATCH 102/103] Update the versionless feature message for dev mode Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index 19d779095..6b0e80c49 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -64,10 +64,9 @@ public class GenerateFeaturesMojo extends PluginConfigSupport { public static final String NO_NEW_FEATURES_COMMENT = "No additional features generated"; public static final String NO_CLASSES_DIR_WARNING = "Could not find classes directory to generate features against. Liberty features will not be generated. " + "Ensure your project has first been compiled."; - public static final String VERSIONLESS_FEATURE_DETECTED_DEVMODE = "If you would like to continue using auto-generation of features, " - + "please remove all versionless features from your server configuration. " - + "If you would like to continue using versionless features, you can use the 'g' hot key " - + "to toggle off auto-generation of features."; + public static final String VERSIONLESS_FEATURE_DETECTED_DEVMODE = "Versionless features are detected in the server configuration. " + + "If you would like to continue using the automatic generation of features, remove all versionless features from your server configuration. " + + "If you would like to continue using versionless features, you can disable the automatic generation of features."; public static final String VERSIONLESS_FEATURE_DETECTED = "Versionless features are detected in the server configuration. " + "To use the 'generate-features' goal, remove all versionless features from your server configuration. " + "If you would like to continue using versionless features, you cannot use the 'generate-features' goal."; From 8ae42c7a4460e3ce6fe2992e85941b691f2ec97f Mon Sep 17 00:00:00 2001 From: Paul Gooderham Date: Mon, 11 May 2026 17:58:20 -0400 Subject: [PATCH 103/103] Rework: modify the messages when generated-features.xml file is detected Signed-off-by: Paul Gooderham --- .../tools/maven/server/GenerateFeaturesMojo.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java index a0bd9f6fe..4b525cb24 100644 --- a/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java +++ b/liberty-maven-plugin/src/main/java/io/openliberty/tools/maven/server/GenerateFeaturesMojo.java @@ -217,14 +217,16 @@ private void generateFeatures() throws MojoExecutionException, PluginExecutionEx // Detect if there is a generate-features.xml file in src already when generating to server dir if (!generateToSrc && new File(configDirectory, GENERATED_FEATURES_FILE_PATH).exists()) { if (isDevMode) { // this is serious because dev mode will overwrite the generated file when copying from src - getLog().error("A generated-features.xml file was detected in the configured source Liberty configuration directory. " + - "It will overwrite the file generated at this time. " + - "You must type 's' + Enter to toggle the option to generate features to the src directory or " + - "remove the generated-features.xml file in the Liberty configuration directory if you need to generate to the server directory."); + getLog().error("A 'generated-features.xml' file was detected in the source Liberty configuration directory. " + + "It will overwrite the file generated to the server directory by the automatic generation of features. " + + "To continue to generate features to the server directory, you must delete the 'generated-features.xml' file " + + "in the source Liberty configuration directory. To generate features to the source Liberty configuration " + + "directory instead, you can type 's' + Enter."); } else { // command line mojo just a warning that this configuration is not expected - getLog().warn("A generated-features.xml file was detected in the configured source Liberty configuration directory. " + - "You must use the option -DgenerateToSrc=true to update the source Liberty configuration directory or " + - "remove the generated-features.xml file in the source Liberty configuration directory if you intend to update the server directory."); + getLog().warn("A 'generated-features.xml' file was detected in the source Liberty configuration directory. " + + "To generate features to the server directory, it is recommended you delete the 'generated-features.xml' " + + "file in the source Liberty configuration directory. To generate features to the source Liberty " + + "configuration directory, you must use the option -DgenerateToSrc=true."); } }