From 6d51fdd2e540e04fbf3a20c4553caec2298b8296 Mon Sep 17 00:00:00 2001 From: Ondro Mihalyi Date: Sun, 5 Oct 2025 08:11:09 +0200 Subject: [PATCH 1/5] Embedded GlassFish reads system properties from domain.xml Properties are not overwritten, if set on command line or by other means before starting the server. --- .../embeddable/GlassFishVariable.java | 4 ++ .../enterprise/v3/server/SystemTasksImpl.java | 46 +++++++++++-------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishVariable.java b/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishVariable.java index c1684a9ba69..5df3baa8349 100644 --- a/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishVariable.java +++ b/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishVariable.java @@ -18,6 +18,7 @@ import java.util.Arrays; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -128,6 +129,9 @@ public String getSystemPropertyName() { return this.sysPropName; } + public Optional getSystemPropertyValue() { + return Optional.ofNullable(System.getProperty(getSystemPropertyName())); + } /** * The map contains pairs of {@link #getEnvName()} and {@link #getSystemPropertyName()}. diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SystemTasksImpl.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SystemTasksImpl.java index 2a80d2719ea..a590d155160 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SystemTasksImpl.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SystemTasksImpl.java @@ -90,12 +90,16 @@ public class SystemTasksImpl implements SystemTasks, PostConstruct { public void postConstruct() { if (env.isEmbedded()) { initEmbeddedSystemOptions(); + boolean overwriteProperties = false; + setSystemPropertiesFromEnv(overwriteProperties); + setSystemPropertiesFromDomainXml(overwriteProperties); LOG.log(INFO, "Loaded embedded server named: {0}", server.getName()); return; } setVersion(); - setSystemPropertiesFromEnv(); - setSystemPropertiesFromDomainXml(); + boolean overwriteProperties = true; + setSystemPropertiesFromEnv(overwriteProperties); + setSystemPropertiesFromDomainXml(overwriteProperties); resolveJavaConfig(); LOG.log(INFO, "Loaded server named: {0}", server.getName()); } @@ -128,22 +132,24 @@ private void setVersion() { setProperty("glassfish.version", Version.getProductIdInfo(), true); } - private void setSystemPropertiesFromEnv() { + private void setSystemPropertiesFromEnv(boolean forceOverwrite) { // adding our version of some system properties. - setProperty(JAVA_ROOT.getSystemPropertyName(), System.getProperty(JAVA_HOME.getSystemPropertyName()), true); - String hostname = "localhost"; - try { - // canonical name checks to make sure host is proper - hostname = NetUtils.getCanonicalHostName(); - } catch (Exception ex) { - LOG.log(Level.SEVERE, KernelLoggerInfo.exceptionHostname, ex); - } - if (hostname != null) { - setProperty(HOST_NAME.getSystemPropertyName(), hostname, false); + setProperty(JAVA_ROOT.getSystemPropertyName(), System.getProperty(JAVA_HOME.getSystemPropertyName()), forceOverwrite); + if (HOST_NAME.getSystemPropertyValue().isEmpty()) { + String hostname = "localhost"; + try { + // canonical name checks to make sure host is proper + hostname = NetUtils.getCanonicalHostName(); + } catch (Exception ex) { + LOG.log(Level.SEVERE, KernelLoggerInfo.exceptionHostname, ex); + } + if (hostname != null) { + setProperty(HOST_NAME.getSystemPropertyName(), hostname, false); + } } } - private void setSystemPropertiesFromDomainXml() { + private void setSystemPropertiesFromDomainXml(boolean forceOverwrite) { // precedence order from high to low // 0. server // 1. cluster @@ -158,14 +164,14 @@ private void setSystemPropertiesFromDomainXml() { final List clusterSPList = cluster == null ? null : cluster.getSystemProperty(); List serverSPList = server.getSystemProperty(); - setSystemProperties(domainSPList); - setSystemProperties(configSPList); + setSystemProperties(domainSPList, forceOverwrite); + setSystemProperties(configSPList, forceOverwrite); if (clusterSPList != null) { - setSystemProperties(clusterSPList); + setSystemProperties(clusterSPList, forceOverwrite); } - setSystemProperties(serverSPList); + setSystemProperties(serverSPList, forceOverwrite); } private List getConfigSystemProperties() { @@ -202,13 +208,13 @@ private void resolveJavaConfig() { } } - private void setSystemProperties(List spList) { + private void setSystemProperties(List spList, boolean forceOverwrite) { for (SystemProperty sp : spList) { String name = sp.getName(); String value = sp.getValue(); if (ok(name)) { - setProperty(name, value, true); + setProperty(name, value, forceOverwrite); } } } From 0ff756f8f652019890c94f52aa1611fe8ac345ad Mon Sep 17 00:00:00 2001 From: Ondro Mihalyi Date: Sun, 5 Oct 2025 22:08:22 +0200 Subject: [PATCH 2/5] Embedded: Tests for setting sys props --- .../runnable/app/SystemPropertyApp.java | 37 ++++ .../embedded/runnable/GfEmbeddedUtils.java | 34 +++- .../embedded/runnable/SystemPropertyTest.java | 129 +++++++++++++ .../resources/SystemPropertyTest/domain.xml | 176 ++++++++++++++++++ 4 files changed, 373 insertions(+), 3 deletions(-) create mode 100644 appserver/tests/embedded/runnable/src/main/java/org/glassfish/tests/embedded/runnable/app/SystemPropertyApp.java create mode 100644 appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java create mode 100644 appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/domain.xml diff --git a/appserver/tests/embedded/runnable/src/main/java/org/glassfish/tests/embedded/runnable/app/SystemPropertyApp.java b/appserver/tests/embedded/runnable/src/main/java/org/glassfish/tests/embedded/runnable/app/SystemPropertyApp.java new file mode 100644 index 00000000000..fad761b6a51 --- /dev/null +++ b/appserver/tests/embedded/runnable/src/main/java/org/glassfish/tests/embedded/runnable/app/SystemPropertyApp.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ +package org.glassfish.tests.embedded.runnable.app; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Initialized; +import jakarta.enterprise.event.Observes; +import jakarta.ws.rs.core.Application; + +import java.util.logging.Logger; + +/** + * @author Ondro Mihalyi + */ +@ApplicationScoped +public class SystemPropertyApp extends Application { + + private static final Logger LOG = Logger.getLogger(SystemPropertyApp.class.getName()); + + public void init(@Observes @Initialized(ApplicationScoped.class) Object event) { + String myName = System.getProperty("my.name"); + LOG.info("System property my.name: " + myName); + } +} diff --git a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/GfEmbeddedUtils.java b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/GfEmbeddedUtils.java index 19f3061332c..9069a587977 100644 --- a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/GfEmbeddedUtils.java +++ b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/GfEmbeddedUtils.java @@ -20,11 +20,14 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Stream; import static java.lang.System.err; +import static java.util.stream.Collectors.joining; /** * @@ -32,15 +35,29 @@ */ public class GfEmbeddedUtils { - public static Process runGlassFishEmbedded(String glassfishEmbeddedJarName, String... additionalArguments) throws IOException { + public static final String DEBUG_PROPERTY_NAME = "glassfish.test.debug.port"; + + public static Process runGlassFishEmbedded(String glassfishEmbeddedJarName, String... additionalArguments) throws +IOException { + return runGlassFishEmbedded(glassfishEmbeddedJarName, List.of(), additionalArguments); + } + + public static Process runGlassFishEmbedded(String glassfishEmbeddedJarName, List jvmOpts, String... additionalArguments) throws IOException { List arguments = new ArrayList<>(); - arguments.addAll(List.of(ProcessHandle.current().info().command().get(), - // "-Xrunjdwp:transport=dt_socket,server=y,suspend=y", // enable debugging on random port + arguments.add(ProcessHandle.current().info().command().get()); + addDebugArgsIfDebugEnabled(arguments); + arguments.addAll(jvmOpts); + arguments.addAll(List.of( "-jar", glassfishEmbeddedJarName, + "--noPort", "--stop")); for (String argument : additionalArguments) { arguments.add(argument); } + System.out.println("\nCurrent directory: " + Paths.get(".").toFile().getAbsolutePath()); + System.out.println("Going to run Embedded GlassFish: " + arguments.stream() + .map(arg -> "'" + arg + "'") + .collect(joining(" ")) + "\n"); return new ProcessBuilder() .redirectOutput(ProcessBuilder.Redirect.INHERIT) .redirectError(ProcessBuilder.Redirect.PIPE) @@ -57,4 +74,15 @@ public static Stream outputToStreamOfLines(Process gfEmbeddedProcess) { .peek(err::println); } + private static void addDebugArgsIfDebugEnabled(List arguments) { + Optional.ofNullable(System.getProperty(DEBUG_PROPERTY_NAME)) + .filter(debugPort -> List.of("none", "disabled", "false").stream() + .allMatch(value -> !value.equalsIgnoreCase(debugPort)) + ) + .ifPresent(debugPort -> { + arguments.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:" + debugPort); + }); + + } + } diff --git a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java new file mode 100644 index 00000000000..f903149c1f5 --- /dev/null +++ b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ +package org.glassfish.tests.embedded.runnable; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +import org.glassfish.tests.embedded.runnable.TestArgumentProviders.GfEmbeddedJarNameProvider; +import org.glassfish.tests.embedded.runnable.app.SystemPropertyApp; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.exporter.ZipExporter; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ArgumentsSource; + +import static org.glassfish.tests.embedded.runnable.GfEmbeddedUtils.outputToStreamOfLines; +import static org.glassfish.tests.embedded.runnable.GfEmbeddedUtils.runGlassFishEmbedded; +import static org.glassfish.tests.embedded.runnable.ShrinkwrapUtils.logArchiveContent; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Ondro Mihalyi + */ +public class SystemPropertyTest { + + private static final Logger LOG = Logger.getLogger(SystemPropertyTest.class.getName()); + + @ParameterizedTest + @ArgumentsSource(GfEmbeddedJarNameProvider.class) + void testSystemPropertyFromJvmOption(String gfEmbeddedJarName) throws Exception { + File warFile = null; + try { + warFile = createSystemPropertyApp(); + Process gfEmbeddedProcess = runGlassFishEmbedded(gfEmbeddedJarName, + List.of("-Dmy.name=GlassFish"), + "--noPort", + warFile.getAbsolutePath() + ); + assertTrue(outputToStreamOfLines(gfEmbeddedProcess) + .anyMatch(line -> line.contains("System property my.name: GlassFish")), + "Application should print the value of the my.name system property."); + gfEmbeddedProcess.waitFor(30, TimeUnit.SECONDS); + } finally { + Optional.ofNullable(warFile).ifPresent(File::delete); + } + } + + @ParameterizedTest + @ArgumentsSource(GfEmbeddedJarNameProvider.class) + void testSystemPropertyFromAdminCommand(String gfEmbeddedJarName) throws Exception { + File warFile = null; + try { + warFile = createSystemPropertyApp(); + Process gfEmbeddedProcess = runGlassFishEmbedded(gfEmbeddedJarName, + "create-system-properties my.name=GlassFish", + warFile.getAbsolutePath() + ); + assertTrue(outputToStreamOfLines(gfEmbeddedProcess) + .anyMatch(line -> line.contains("System property my.name: GlassFish")), + "Application should print the value of the my.name system property."); + gfEmbeddedProcess.waitFor(30, TimeUnit.SECONDS); + } finally { + Optional.ofNullable(warFile).ifPresent(File::delete); + } + } + + @ParameterizedTest + @ArgumentsSource(GfEmbeddedJarNameProvider.class) + void testSystemPropertyFromDomainConfig(String gfEmbeddedJarName, TestInfo testInfo) throws Exception { + File warFile = null; + Path domainConfigFile = prepareDomainConfig(testInfo); + try { + warFile = createSystemPropertyApp(); + Process gfEmbeddedProcess = runGlassFishEmbedded(gfEmbeddedJarName, + "--domainConfigFile=" + domainConfigFile.toFile().getPath(), + warFile.getAbsolutePath() + ); + assertTrue(outputToStreamOfLines(gfEmbeddedProcess) + .anyMatch(line -> line.contains("System property my.name: GlassFish")), + "Application should print the value of the my.name system property."); + gfEmbeddedProcess.waitFor(30, TimeUnit.SECONDS); + } finally { + Optional.ofNullable(warFile).ifPresent(File::delete); + } + } + + private File createSystemPropertyApp() throws Exception { + String warName = "systemPropertyApp.war"; + WebArchive warArchive = ShrinkWrap.create(WebArchive.class, warName) + .addClass(SystemPropertyApp.class); + File warFile = new File(warName); + warArchive.as(ZipExporter.class).exportTo(warFile); + logArchiveContent(warArchive, warName, LOG::info); + return warFile; + } + + private Path prepareDomainConfig(TestInfo testInfo) throws IOException { + String testClassName = testInfo.getTestClass().get().getSimpleName(); + String testMethodName = testInfo.getTestMethod().get().getName(); + Path domainConfigFile = Paths.get(testClassName + "-" + testMethodName + "-" + "domain.xml"); + Files.copy(getClass().getClassLoader().getResourceAsStream(testClassName + "/domain.xml"), + domainConfigFile, + StandardCopyOption.REPLACE_EXISTING); + return domainConfigFile; + } + +} diff --git a/appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/domain.xml b/appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/domain.xml new file mode 100644 index 00000000000..5464692d053 --- /dev/null +++ b/appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/domain.xml @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -Djavax.net.ssl.keyStore=${com.sun.aas.instanceRoot}/config/keystore.jks + -Djavax.net.ssl.trustStore=${com.sun.aas.instanceRoot}/config/cacerts.jks + -Dorg.glassfish.jms.InitializeOnDemand=true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d4968887ce71c56eb2e92fff5f7b97523ebbc295 Mon Sep 17 00:00:00 2001 From: Ondro Mihalyi Date: Mon, 6 Oct 2025 02:09:01 +0200 Subject: [PATCH 3/5] Embedded: Support escaped spaces in admin command arguments --- .../runnable/app/SystemPropertyApp.java | 3 +-- .../embedded/runnable/GfEmbeddedUtils.java | 24 ++++++++++++------- .../embedded/runnable/SystemPropertyTest.java | 13 +++++----- .../runnable/TestArgumentProviders.java | 20 +++++++--------- .../resources/SystemPropertyTest/domain.xml | 2 +- .../org/glassfish/runnablejar/UberMain.java | 5 ++-- 6 files changed, 35 insertions(+), 32 deletions(-) diff --git a/appserver/tests/embedded/runnable/src/main/java/org/glassfish/tests/embedded/runnable/app/SystemPropertyApp.java b/appserver/tests/embedded/runnable/src/main/java/org/glassfish/tests/embedded/runnable/app/SystemPropertyApp.java index fad761b6a51..fd504803dd9 100644 --- a/appserver/tests/embedded/runnable/src/main/java/org/glassfish/tests/embedded/runnable/app/SystemPropertyApp.java +++ b/appserver/tests/embedded/runnable/src/main/java/org/glassfish/tests/embedded/runnable/app/SystemPropertyApp.java @@ -18,7 +18,6 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.Initialized; import jakarta.enterprise.event.Observes; -import jakarta.ws.rs.core.Application; import java.util.logging.Logger; @@ -26,7 +25,7 @@ * @author Ondro Mihalyi */ @ApplicationScoped -public class SystemPropertyApp extends Application { +public class SystemPropertyApp { private static final Logger LOG = Logger.getLogger(SystemPropertyApp.class.getName()); diff --git a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/GfEmbeddedUtils.java b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/GfEmbeddedUtils.java index 9069a587977..3933a45a1b3 100644 --- a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/GfEmbeddedUtils.java +++ b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/GfEmbeddedUtils.java @@ -35,10 +35,21 @@ */ public class GfEmbeddedUtils { - public static final String DEBUG_PROPERTY_NAME = "glassfish.test.debug.port"; + public static final String DEBUG_PROPERTY_NAME = "glassfish.test.debug"; + + public static Optional getDebugArg() { + return Optional.ofNullable(System.getProperty(DEBUG_PROPERTY_NAME)) + .filter(debugPort -> List.of("none", "disabled", "false").stream() + .allMatch(value -> !value.equalsIgnoreCase(debugPort)) + ); + } + + public static boolean isDebugEnabled() { + return getDebugArg().isPresent(); + } public static Process runGlassFishEmbedded(String glassfishEmbeddedJarName, String... additionalArguments) throws -IOException { + IOException { return runGlassFishEmbedded(glassfishEmbeddedJarName, List.of(), additionalArguments); } @@ -75,12 +86,9 @@ public static Stream outputToStreamOfLines(Process gfEmbeddedProcess) { } private static void addDebugArgsIfDebugEnabled(List arguments) { - Optional.ofNullable(System.getProperty(DEBUG_PROPERTY_NAME)) - .filter(debugPort -> List.of("none", "disabled", "false").stream() - .allMatch(value -> !value.equalsIgnoreCase(debugPort)) - ) - .ifPresent(debugPort -> { - arguments.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:" + debugPort); + getDebugArg() + .ifPresent(debugArgs -> { + arguments.add(debugArgs); }); } diff --git a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java index f903149c1f5..cff40ef300b 100644 --- a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java +++ b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java @@ -54,12 +54,11 @@ void testSystemPropertyFromJvmOption(String gfEmbeddedJarName) throws Exception try { warFile = createSystemPropertyApp(); Process gfEmbeddedProcess = runGlassFishEmbedded(gfEmbeddedJarName, - List.of("-Dmy.name=GlassFish"), - "--noPort", + List.of("-Dmy.name=Embedded GlassFish"), warFile.getAbsolutePath() ); assertTrue(outputToStreamOfLines(gfEmbeddedProcess) - .anyMatch(line -> line.contains("System property my.name: GlassFish")), + .anyMatch(line -> line.contains("System property my.name: Embedded GlassFish")), "Application should print the value of the my.name system property."); gfEmbeddedProcess.waitFor(30, TimeUnit.SECONDS); } finally { @@ -74,11 +73,11 @@ void testSystemPropertyFromAdminCommand(String gfEmbeddedJarName) throws Excepti try { warFile = createSystemPropertyApp(); Process gfEmbeddedProcess = runGlassFishEmbedded(gfEmbeddedJarName, - "create-system-properties my.name=GlassFish", + "create-system-properties my.name=Embedded\\ GlassFish", warFile.getAbsolutePath() ); assertTrue(outputToStreamOfLines(gfEmbeddedProcess) - .anyMatch(line -> line.contains("System property my.name: GlassFish")), + .anyMatch(line -> line.contains("System property my.name: Embedded GlassFish")), "Application should print the value of the my.name system property."); gfEmbeddedProcess.waitFor(30, TimeUnit.SECONDS); } finally { @@ -98,7 +97,7 @@ void testSystemPropertyFromDomainConfig(String gfEmbeddedJarName, TestInfo testI warFile.getAbsolutePath() ); assertTrue(outputToStreamOfLines(gfEmbeddedProcess) - .anyMatch(line -> line.contains("System property my.name: GlassFish")), + .anyMatch(line -> line.contains("System property my.name: Embedded GlassFish")), "Application should print the value of the my.name system property."); gfEmbeddedProcess.waitFor(30, TimeUnit.SECONDS); } finally { @@ -111,7 +110,7 @@ private File createSystemPropertyApp() throws Exception { WebArchive warArchive = ShrinkWrap.create(WebArchive.class, warName) .addClass(SystemPropertyApp.class); File warFile = new File(warName); - warArchive.as(ZipExporter.class).exportTo(warFile); + warArchive.as(ZipExporter.class).exportTo(warFile, true); logArchiveContent(warArchive, warName, LOG::info); return warFile; } diff --git a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/TestArgumentProviders.java b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/TestArgumentProviders.java index b8e2b5ccdf4..bedc618cc7a 100644 --- a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/TestArgumentProviders.java +++ b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/TestArgumentProviders.java @@ -15,6 +15,8 @@ */ package org.glassfish.tests.embedded.runnable; +import java.util.ArrayList; +import java.util.List; import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtensionContext; @@ -31,20 +33,14 @@ public static class GfEmbeddedJarNameProvider implements ArgumentsProvider { @Override public Stream provideArguments(ExtensionContext ec) throws Exception { - return Stream.of(Arguments.of("glassfish-embedded-all.jar"), Arguments.of("glassfish-embedded-web.jar")); + List arguments = new ArrayList<>(); + arguments.add(Arguments.of("glassfish-embedded-all.jar")); + if (!GfEmbeddedUtils.isDebugEnabled()) { + arguments.add(Arguments.of("glassfish-embedded-web.jar")); + } + return arguments.stream(); } } - /** - * For testing a single execution when debugging - */ - public static class SingleGfEmbeddedJarNameProvider implements ArgumentsProvider { - - @Override - public Stream provideArguments(ExtensionContext ec) throws Exception { - return Stream.of(Arguments.of("glassfish-embedded-all.jar")); - } - - } } diff --git a/appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/domain.xml b/appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/domain.xml index 5464692d053..5b911930a80 100644 --- a/appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/domain.xml +++ b/appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/domain.xml @@ -46,7 +46,7 @@ - + diff --git a/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/UberMain.java b/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/UberMain.java index 5f956123c3f..f9cac03b59d 100644 --- a/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/UberMain.java +++ b/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/UberMain.java @@ -177,14 +177,15 @@ private void runCommandPromptLoop() throws GlassFishException { private void executeCommandFromString(String stringCommand) { logger.log(FINE, () -> "Executing command: " + stringCommand); - String[] split = stringCommand.split(" "); + // Split according to empty space but not if empty space is escaped by \ + String[] split = stringCommand.split("(? 1) { commandParams = new String[split.length - 1]; for (int i = 1; i < split.length; i++) { commandParams[i - 1] = split[i].trim(); - } + } } try { CommandResult result = commandParams == null From 3dad4ae41ab274c271ab0dbfb71a2e97e6c1db0f Mon Sep 17 00:00:00 2001 From: Ondro Mihalyi Date: Mon, 6 Oct 2025 16:43:42 +0200 Subject: [PATCH 4/5] Improvements after code review --- .../java/org/glassfish/embeddable/GlassFishVariable.java | 5 ----- .../java/com/sun/enterprise/v3/server/SystemTasksImpl.java | 4 ++-- .../src/main/java/org/glassfish/runnablejar/UberMain.java | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishVariable.java b/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishVariable.java index 5df3baa8349..e6c0b54cde5 100644 --- a/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishVariable.java +++ b/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/GlassFishVariable.java @@ -18,7 +18,6 @@ import java.util.Arrays; import java.util.Map; -import java.util.Optional; import java.util.stream.Collectors; /** @@ -129,10 +128,6 @@ public String getSystemPropertyName() { return this.sysPropName; } - public Optional getSystemPropertyValue() { - return Optional.ofNullable(System.getProperty(getSystemPropertyName())); - } - /** * The map contains pairs of {@link #getEnvName()} and {@link #getSystemPropertyName()}. * When the {@link #getEnvName()} returns null, the mapping is not included. diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SystemTasksImpl.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SystemTasksImpl.java index a590d155160..c719775d3eb 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SystemTasksImpl.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/SystemTasksImpl.java @@ -135,7 +135,7 @@ private void setVersion() { private void setSystemPropertiesFromEnv(boolean forceOverwrite) { // adding our version of some system properties. setProperty(JAVA_ROOT.getSystemPropertyName(), System.getProperty(JAVA_HOME.getSystemPropertyName()), forceOverwrite); - if (HOST_NAME.getSystemPropertyValue().isEmpty()) { + if (forceOverwrite || null == System.getProperty(HOST_NAME.getSystemPropertyName())) { String hostname = "localhost"; try { // canonical name checks to make sure host is proper @@ -144,7 +144,7 @@ private void setSystemPropertiesFromEnv(boolean forceOverwrite) { LOG.log(Level.SEVERE, KernelLoggerInfo.exceptionHostname, ex); } if (hostname != null) { - setProperty(HOST_NAME.getSystemPropertyName(), hostname, false); + setProperty(HOST_NAME.getSystemPropertyName(), hostname, true); } } } diff --git a/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/UberMain.java b/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/UberMain.java index f9cac03b59d..7e78ffaf99c 100644 --- a/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/UberMain.java +++ b/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/UberMain.java @@ -185,7 +185,7 @@ private void executeCommandFromString(String stringCommand) { commandParams = new String[split.length - 1]; for (int i = 1; i < split.length; i++) { commandParams[i - 1] = split[i].trim(); - } + } } try { CommandResult result = commandParams == null From ca42dce0b3f106b3544e4c517a891650606271d7 Mon Sep 17 00:00:00 2001 From: Ondro Mihalyi Date: Mon, 6 Oct 2025 17:32:47 +0200 Subject: [PATCH 5/5] Simple system properties in glassfish.properties for runneble Embedded GlassFish --- .../embedded/runnable/SystemPropertyTest.java | 30 +++++++++++++++++++ .../SystemPropertyTest/glassfish.properties | 15 ++++++++++ .../main/asciidoc/embedded-server-guide.adoc | 3 ++ .../embedded/AutoDisposableGlassFish.java | 8 ++++- .../runnablejar/commandline/Option.java | 4 ++- .../commandline/WordWrapperTest.java | 2 +- 6 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/glassfish.properties diff --git a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java index cff40ef300b..7094d8c4f8b 100644 --- a/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java +++ b/appserver/tests/embedded/runnable/src/test/java/org/glassfish/tests/embedded/runnable/SystemPropertyTest.java @@ -85,6 +85,26 @@ void testSystemPropertyFromAdminCommand(String gfEmbeddedJarName) throws Excepti } } + @ParameterizedTest + @ArgumentsSource(GfEmbeddedJarNameProvider.class) + void testSystemPropertyFromPropertyFileDirectly(String gfEmbeddedJarName, TestInfo testInfo) throws Exception { + File warFile = null; + Path propertiesFile = preparePropertiesFile(testInfo); + try { + warFile = createSystemPropertyApp(); + Process gfEmbeddedProcess = runGlassFishEmbedded(gfEmbeddedJarName, + "--properties=" + propertiesFile.toFile().getPath(), + warFile.getAbsolutePath() + ); + assertTrue(outputToStreamOfLines(gfEmbeddedProcess) + .anyMatch(line -> line.contains("System property my.name: Embedded GlassFish")), + "Application should print the value of the my.name system property."); + gfEmbeddedProcess.waitFor(30, TimeUnit.SECONDS); + } finally { + Optional.ofNullable(warFile).ifPresent(File::delete); + } + } + @ParameterizedTest @ArgumentsSource(GfEmbeddedJarNameProvider.class) void testSystemPropertyFromDomainConfig(String gfEmbeddedJarName, TestInfo testInfo) throws Exception { @@ -125,4 +145,14 @@ private Path prepareDomainConfig(TestInfo testInfo) throws IOException { return domainConfigFile; } + private Path preparePropertiesFile(TestInfo testInfo) throws IOException { + String testClassName = testInfo.getTestClass().get().getSimpleName(); + String testMethodName = testInfo.getTestMethod().get().getName(); + Path propertiesFile = Paths.get(testClassName + "-" + testMethodName + "-" + "glassfish.properties"); + Files.copy(getClass().getClassLoader().getResourceAsStream(testClassName + "/glassfish.properties"), + propertiesFile, + StandardCopyOption.REPLACE_EXISTING); + return propertiesFile; + } + } diff --git a/appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/glassfish.properties b/appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/glassfish.properties new file mode 100644 index 00000000000..72b6abb68f4 --- /dev/null +++ b/appserver/tests/embedded/runnable/src/test/resources/SystemPropertyTest/glassfish.properties @@ -0,0 +1,15 @@ +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0, which is available at +# http://www.eclipse.org/legal/epl-2.0. +# +# This Source Code may also be made available under the following Secondary +# Licenses when the conditions for such availability set forth in the +# Eclipse Public License v. 2.0 are satisfied: GNU General Public License, +# version 2 with the GNU Classpath Exception, which is available at +# https://www.gnu.org/software/classpath/license.html. +# +# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +my.name=Embedded GlassFish \ No newline at end of file diff --git a/docs/embedded-server-guide/src/main/asciidoc/embedded-server-guide.adoc b/docs/embedded-server-guide/src/main/asciidoc/embedded-server-guide.adoc index 617c947fa13..f7d9aa57dc7 100644 --- a/docs/embedded-server-guide/src/main/asciidoc/embedded-server-guide.adoc +++ b/docs/embedded-server-guide/src/main/asciidoc/embedded-server-guide.adoc @@ -285,6 +285,9 @@ The value will be treated as a command to execute at startup. - Keys that start with the "deploy." prefix, followed by any text. The value will be treated as an application to deploy at startup, as if it was specified on the command line. + - If a property name doesn't match any already supported patterns and is not +a recognized GlassFish property, it will be set as a system property, if +it's not already defined. For example, the ${productName} domain directory can be specified with the usual Embedded ${productName} property "glassfish.embedded.tmpdir=myDomainDir", as well as with the property diff --git a/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/AutoDisposableGlassFish.java b/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/AutoDisposableGlassFish.java index 0f94f24bfba..bc8b56287ce 100644 --- a/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/AutoDisposableGlassFish.java +++ b/nucleus/core/bootstrap-osgi/src/main/java/org/glassfish/main/boot/embedded/AutoDisposableGlassFish.java @@ -37,6 +37,7 @@ import org.glassfish.embeddable.GlassFishProperties; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.main.boot.impl.GlassFishImpl; +import org.glassfish.main.jdke.props.SystemProperties; import static com.sun.enterprise.glassfish.bootstrap.cfg.BootstrapKeys.AUTO_DELETE; @@ -79,7 +80,12 @@ class AutoDisposableGlassFish extends GlassFishImpl { && resultList.getOutput().contains(propertyPrefix)) { knownPropertyPrefixes.add(propertyPrefix); } else { - // unknown property prefix, skip it + if (!key.startsWith("com.sun.aas.") && !key.startsWith("-")) { + // unknown property, set as system property + LOG.log(Level.INFO, "Setting system property " + key + " from GlassFish properties, it doesn't match any known property"); + SystemProperties.setProperty(key, gfProps.getProperty(key), false); + } + // not a dotted name, doesn't start with a supported prefix, do not set it later continue; } } diff --git a/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/commandline/Option.java b/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/commandline/Option.java index ec73fa32f0b..2061befffcd 100644 --- a/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/commandline/Option.java +++ b/nucleus/core/kernel/src/main/java/org/glassfish/runnablejar/commandline/Option.java @@ -51,7 +51,9 @@ public enum Option { + " - Keys that start with the \"" + Arguments.DEPLOY_KEY_PREFIX + "\" prefix, followed by any text. The value will be" + " treated as an application to deploy at startup, as if it was specified on the command line.\n" - + "For example, the GlassFish domain directory can be specified with the usual GlassFish Embedded" + + " - If a property name doesn't match any already supported patterns and is not" + + " a recognized GlassFish property, it will be set as a system property, if it's not already defined.\n" + + "\nFor example, the GlassFish domain directory can be specified with the usual GlassFish Embedded" + " property \"glassfish.embedded.tmpdir=myDomainDir\", as well as with the property" + " \"domainDir=myDomainDir\" that represents the \"--domainDir=myDomainDir\" command-line option." + " A command to deploy an application can be specified via a property key" diff --git a/nucleus/core/kernel/src/test/java/org/glassfish/runnablejar/commandline/WordWrapperTest.java b/nucleus/core/kernel/src/test/java/org/glassfish/runnablejar/commandline/WordWrapperTest.java index dff418c337b..91056cae89f 100644 --- a/nucleus/core/kernel/src/test/java/org/glassfish/runnablejar/commandline/WordWrapperTest.java +++ b/nucleus/core/kernel/src/test/java/org/glassfish/runnablejar/commandline/WordWrapperTest.java @@ -38,7 +38,7 @@ public void testWrapper() { .map(Option::getHelpText) .collect(wordWrapper); final List linesEndingWithSpace = message.lines() - .filter(line -> line.endsWith(" ")) + .filter(line -> line.endsWith(" ") && !line.isBlank()) .collect(toList()); assertTrue(linesEndingWithSpace.isEmpty(), "Some lines end with a space: " + linesEndingWithSpace);