You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by pk...@apache.org on 2024/06/19 10:11:25 UTC
(logging-log4j2) 01/01: Fix OSGi test failures
This is an automated email from the ASF dual-hosted git repository.
pkarwasz pushed a commit to branch fix/main/osgi-tests
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 09a27b845e6e1c20dda87eef141a1061711a4202
Author: Piotr P. Karwasz <pi...@karwasz.org>
AuthorDate: Tue Jun 18 14:46:48 2024 +0200
Fix OSGi test failures
OSGi tests are failing for multiple reasons:
- the constructor of the activator of `log4j-core`, indirectly made a call to
`ServiceLoader.load` to populate the `InstanceFactory`.
Experimentally it seems that Service Loader Mediator is not ready at
this moment and the instance factory is not initialized correctly.
To fix this we moved the construction of `Log4jProvider` to the
`start()` method.
- the test classpath of `log4j-osgi-test` contains both Felix and
Equinox, which share some classes, but one artifact is signed and the
other is not.
To solve the classpath problem we split tests into two runs
`test-equinox` and `test-felix`.
- the new `logging-parent` stores the `PluginService` for test plugins
in a random package.
This breaks tests, since the `PluginService` must also be declared in
OSGi headers and therefore need to be deterministic.
---
.../apache/logging/log4j/core/LoggerContext.java | 3 ++
.../log4j/core/config/AbstractConfiguration.java | 1 +
.../log4j/core/impl/internal/Activator.java | 26 +++++++--
log4j-osgi-test/pom.xml | 61 +++++++++++++++++++++-
.../logging/log4j/osgi/tests/CoreOsgiTest.java | 2 +-
5 files changed, 86 insertions(+), 7 deletions(-)
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
index 6cb8995056..2eb829db49 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
@@ -18,6 +18,8 @@ package org.apache.logging.log4j.core;
import static org.apache.logging.log4j.core.util.ShutdownCallbackRegistry.SHUTDOWN_HOOK_MARKER;
+import aQute.bnd.annotation.Cardinality;
+import aQute.bnd.annotation.spi.ServiceConsumer;
import java.io.File;
import java.net.URI;
import java.util.ArrayList;
@@ -76,6 +78,7 @@ import org.jspecify.annotations.Nullable;
* applications and a reference to the Configuration. The Configuration will contain the configured loggers, appenders,
* filters, etc. and will be atomically updated whenever a reconfigure occurs.
*/
+@ServiceConsumer(value = ConfigurableInstanceFactoryPostProcessor.class, cardinality = Cardinality.MULTIPLE)
public class LoggerContext extends AbstractLifeCycle
implements org.apache.logging.log4j.spi.LoggerContext,
AutoCloseable,
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index 26d4fd8db2..e6c1f4427c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -92,6 +92,7 @@ import org.jspecify.annotations.Nullable;
*/
@NullMarked
@ServiceConsumer(value = ScriptManagerFactory.class, cardinality = Cardinality.SINGLE, resolution = Resolution.OPTIONAL)
+@ServiceConsumer(value = ConfigurableInstanceFactoryPostProcessor.class, cardinality = Cardinality.MULTIPLE)
public abstract class AbstractConfiguration extends AbstractFilterable implements Configuration {
private static final List<String> EXPECTED_ELEMENTS =
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/internal/Activator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/internal/Activator.java
index 2d12905ce3..30ee8efccc 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/internal/Activator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/internal/Activator.java
@@ -16,15 +16,33 @@
*/
package org.apache.logging.log4j.core.impl.internal;
+import java.util.Hashtable;
import org.apache.logging.log4j.core.impl.Log4jProvider;
-import org.apache.logging.log4j.util.ProviderActivator;
+import org.apache.logging.log4j.spi.Provider;
import org.osgi.annotation.bundle.Header;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
@Header(name = Constants.BUNDLE_ACTIVATOR, value = "${@class}")
@Header(name = Constants.BUNDLE_ACTIVATIONPOLICY, value = Constants.ACTIVATION_LAZY)
-public class Activator extends ProviderActivator {
- public Activator() {
- super(new Log4jProvider());
+public class Activator implements BundleActivator {
+
+ private ServiceRegistration<Provider> providerRegistration = null;
+
+ @Override
+ public void start(final BundleContext context) throws Exception {
+ final Provider provider = new Log4jProvider();
+ final Hashtable<String, String> props = new Hashtable<>();
+ props.put("APIVersion", provider.getVersions());
+ this.providerRegistration = context.registerService(Provider.class, provider, props);
+ }
+
+ @Override
+ public void stop(final BundleContext context) throws Exception {
+ if (this.providerRegistration != null) {
+ this.providerRegistration.unregister();
+ }
}
}
diff --git a/log4j-osgi-test/pom.xml b/log4j-osgi-test/pom.xml
index 48e8f62fbd..45c538d262 100644
--- a/log4j-osgi-test/pom.xml
+++ b/log4j-osgi-test/pom.xml
@@ -27,7 +27,7 @@
</parent>
<artifactId>log4j-osgi-test</artifactId>
- <packaging>jar</packaging>
+
<name>Apache Log4j OSGi tests</name>
<description>The Apache Log4j OSGi tests</description>
@@ -41,6 +41,9 @@
<spotbugs.skip>true</spotbugs.skip>
<spifly.version>1.3.7</spifly.version>
+
+ <!-- Fix the name of the package with `PluginService`, since it is also used in the code -->
+ <log4jPluginPackageForTests>org.apache.logging.log4j.osgi_test</log4jPluginPackageForTests>
</properties>
<dependencies>
@@ -150,6 +153,20 @@
<plugins>
+ <!-- Disable randomisation of the package used by `PluginService`,
+ since it also must be referenced in the test code. -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>3.5.0</version>
+ <executions>
+ <execution>
+ <id>define-log4jPluginPackageForTests</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+
<!--
~ Unban Logback.
-->
@@ -198,16 +215,56 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
- <classpathDependencyExcludes>org.osgi:org.osgi.framework</classpathDependencyExcludes>
+ <classpathDependencyExcludes>
+ <exclude>org.osgi:org.osgi.framework</exclude>
+ </classpathDependencyExcludes>
<systemPropertyVariables>
<!-- PAX logging has a copy of Log4j2 API-->
<pax.exam.logging>false</pax.exam.logging>
<java.protocol.handler.pkgs>org.ops4j.pax.url</java.protocol.handler.pkgs>
+ <!-- Used in `osgi.properties -->
+ <felix.cache.rootdir>${project.build.directory}</felix.cache.rootdir>
</systemPropertyVariables>
<!-- Illegal access is disabled by default in Java 16 due to JEP-396.
We are relaxing it for tests. -->
<argLine>--add-opens java.base/java.net=ALL-UNNAMED</argLine>
</configuration>
+ <executions>
+ <!-- Split the Felix and Equinox tests to prevent classpath conflicts.
+ Both frameworks contain e.g. the `org.apache.felix.resolver` package. -->
+ <execution>
+ <id>default-test</id>
+ <phase>none</phase>
+ </execution>
+ <execution>
+ <id>test-equinox</id>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <classpathDependencyExcludes combine.children="append">
+ <exclude>org.apache.felix:org.apache.felix.framework</exclude>
+ </classpathDependencyExcludes>
+ <excludes>
+ <exclude>org.apache.logging.log4j.osgi.tests.FelixLoadApiBundleTest</exclude>
+ </excludes>
+ </configuration>
+ </execution>
+ <execution>
+ <id>test-felix</id>
+ <goals>
+ <goal>test</goal>
+ </goals>
+ <configuration>
+ <classpathDependencyExcludes combine.children="append">
+ <exclude>org.eclipse.platform:org.eclipse.osgi</exclude>
+ </classpathDependencyExcludes>
+ <excludes>
+ <exclude>org.apache.logging.log4j.osgi.tests.EquinoxLoadApiBundleTest</exclude>
+ </excludes>
+ </configuration>
+ </execution>
+ </executions>
</plugin>
</plugins>
diff --git a/log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/CoreOsgiTest.java b/log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/CoreOsgiTest.java
index 709c3fffa9..b27dfac08d 100644
--- a/log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/CoreOsgiTest.java
+++ b/log4j-osgi-test/src/test/java/org/apache/logging/log4j/osgi/tests/CoreOsgiTest.java
@@ -69,7 +69,7 @@ public class CoreOsgiTest {
builder.setHeader(
Constants.PROVIDE_CAPABILITY,
"osgi.serviceloader;osgi.serviceloader=\"org.apache.logging.log4j.plugins.model.PluginService\";"
- + "register:=\"org.apache.logging.log4j.osgi.tests.plugins.Log4jPlugins\"");
+ + "register:=\"org.apache.logging.log4j.osgi_test.plugins.Log4jPlugins\"");
builder.setHeader(
Constants.REQUIRE_CAPABILITY,
"osgi.extender;filter:=\"(&(osgi.extender=osgi.serviceloader.registrar)(version>=1.0)(!(version>=2.0)))\"");