Skip to content

Fix JsonLayout failures under JPMS #2815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@
package org.apache.logging.log4j.core.jackson;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.core.impl.ContextDataFactory;
import org.apache.logging.log4j.util.StringMap;

Expand All @@ -37,17 +35,16 @@ public class ContextDataAsEntryListDeserializer extends StdDeserializer<StringMa
private static final long serialVersionUID = 1L;

ContextDataAsEntryListDeserializer() {
super(Map.class);
super(StringMap.class);
}

@Override
public StringMap deserialize(final JsonParser jp, final DeserializationContext ctxt)
throws IOException, JsonProcessingException {
public StringMap deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException {
final List<MapEntry> list = jp.readValueAs(
new TypeReference<List<MapEntry>>() {
// empty
});
final StringMap contextData = new ContextDataFactory().createContextData();
final StringMap contextData = ContextDataFactory.createContextData();
for (final MapEntry mapEntry : list) {
contextData.putValue(mapEntry.getKey(), mapEntry.getValue());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.util.Map;
import org.apache.logging.log4j.util.BiConsumer;
import org.apache.logging.log4j.util.ReadOnlyStringMap;

Expand All @@ -35,7 +34,7 @@ public class ContextDataAsEntryListSerializer extends StdSerializer<ReadOnlyStri
private static final long serialVersionUID = 1L;

protected ContextDataAsEntryListSerializer() {
super(Map.class, false);
super(ReadOnlyStringMap.class);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@
package org.apache.logging.log4j.core.jackson;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.util.Map;
import org.apache.logging.log4j.core.impl.ContextDataFactory;
import org.apache.logging.log4j.util.StringMap;

Expand All @@ -36,12 +34,11 @@ public class ContextDataDeserializer extends StdDeserializer<StringMap> {
private static final long serialVersionUID = 1L;

ContextDataDeserializer() {
super(Map.class);
super(StringMap.class);
}

@Override
public StringMap deserialize(final JsonParser jp, final DeserializationContext ctxt)
throws IOException, JsonProcessingException {
public StringMap deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException {

// Sanity check: verify that we got "Json Object":
// JsonToken tok = jp.nextToken();
Expand All @@ -51,7 +48,7 @@ public StringMap deserialize(final JsonParser jp, final DeserializationContext c
final StringMap contextData = ContextDataFactory.createContextData();
// Iterate over object fields:
while (jp.nextToken() != JsonToken.END_OBJECT) {
final String fieldName = jp.getCurrentName();
final String fieldName = jp.currentName();

// move to value
jp.nextToken();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.util.Map;
import org.apache.logging.log4j.util.ReadOnlyStringMap;
import org.apache.logging.log4j.util.TriConsumer;

Expand All @@ -35,7 +34,7 @@ public class ContextDataSerializer extends StdSerializer<ReadOnlyStringMap> {
private static final long serialVersionUID = 1L;

protected ContextDataSerializer() {
super(Map.class, false);
super(ReadOnlyStringMap.class);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@
*/
package org.apache.logging.log4j.core.jackson;

import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;

import com.fasterxml.jackson.databind.Module.SetupContext;
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.module.SimpleSerializers;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.ThreadContext.ContextStack;
Expand All @@ -27,6 +32,7 @@
import org.apache.logging.log4j.core.time.Instant;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.ObjectMessage;
import org.apache.logging.log4j.util.StringMap;

/**
* Initialization utils.
Expand All @@ -36,10 +42,7 @@
*/
class Initializers {

/**
* Used to set up {@link SetupContext} from different {@link SimpleModule}s.
*/
static class SetupContextInitializer {
private abstract static class AbstractInitializer {

void setupModule(
final SetupContext context, final boolean includeStacktrace, final boolean stacktraceAsString) {
Expand All @@ -50,7 +53,7 @@ void setupModule(
context.setMixInAnnotations(Marker.class, MarkerMixIn.class);
context.setMixInAnnotations(Level.class, LevelMixIn.class);
context.setMixInAnnotations(Instant.class, InstantMixIn.class);
context.setMixInAnnotations(LogEvent.class, LogEventWithContextListMixIn.class);
context.setMixInAnnotations(LogEvent.class, LogEventMixIn.class);
// Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
context.setMixInAnnotations(
Expand All @@ -62,33 +65,43 @@ void setupModule(
: ThrowableProxyWithoutStacktraceMixIn.class);
}
}
/**
* Used to set up {@link SetupContext} from different {@link SimpleModule}s.
* <p>
* Serializes the context map as list of objects.
* </p>
*/
static class SetupContextAsEntryListInitializer extends AbstractInitializer {

@Override
void setupModule(
final SetupContext context, final boolean includeStacktrace, final boolean stacktraceAsString) {
super.setupModule(context, includeStacktrace, stacktraceAsString);
// These classes don't have public constructors, so we instantiate them directly.
// See https://github.com/apache/logging-log4j2/issues/2814
context.addSerializers(new SimpleSerializers(singletonList(new ContextDataAsEntryListSerializer())));
context.addDeserializers(
new SimpleDeserializers(singletonMap(StringMap.class, new ContextDataAsEntryListDeserializer())));
}
}

/**
* Used to set up {@link SetupContext} from different {@link SimpleModule}s.
* Differs from SetupContextInitializer by installing {@code LogEventJsonMixIn} for LogEvents,
* not {@code LogEventMixIn}, so it handles ThreadContext serialization differently.
* <p>
* Serializes the context map as object.
* </p>
*/
static class SetupContextJsonInitializer {
static class SetupContextInitializer extends AbstractInitializer {

@Override
void setupModule(
final SetupContext context, final boolean includeStacktrace, final boolean stacktraceAsString) {
// JRE classes: we cannot edit those with Jackson annotations
context.setMixInAnnotations(StackTraceElement.class, StackTraceElementMixIn.class);
// Log4j API classes: we do not want to edit those with Jackson annotations because the API module should
// not depend on Jackson.
context.setMixInAnnotations(Marker.class, MarkerMixIn.class);
context.setMixInAnnotations(Level.class, LevelMixIn.class);
context.setMixInAnnotations(Instant.class, InstantMixIn.class);
context.setMixInAnnotations(LogEvent.class, LogEventJsonMixIn.class); // different ThreadContext handling
// Log4j Core classes: we do not want to bring in Jackson at runtime if we do not have to.
context.setMixInAnnotations(ExtendedStackTraceElement.class, ExtendedStackTraceElementMixIn.class);
context.setMixInAnnotations(
ThrowableProxy.class,
includeStacktrace
? (stacktraceAsString
? ThrowableProxyWithStacktraceAsStringMixIn.class
: ThrowableProxyMixIn.class)
: ThrowableProxyWithoutStacktraceMixIn.class);
super.setupModule(context, includeStacktrace, stacktraceAsString);
// These classes don't have public constructors, so we instantiate them directly.
// See https://github.com/apache/logging-log4j2/issues/2814
context.addSerializers(new SimpleSerializers(singletonList(new ContextDataSerializer())));
context.addDeserializers(
new SimpleDeserializers(singletonMap(StringMap.class, new ContextDataDeserializer())));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,31 @@
*/
package org.apache.logging.log4j.core.jackson;

import aQute.bnd.annotation.baseline.BaselineIgnore;

/**
* Keeps constants separate from any class that may depend on third party jars.
*/
@BaselineIgnore("2.24.0")
public final class JsonConstants {
public static final String ELT_CAUSE = "cause";
public static final String ELT_CONTEXT_MAP = "contextMap";
public static final String ELT_CONTEXT_STACK = "contextStack";
public static final String ELT_END_OF_BATCH = "endOfBatch";
public static final String ELT_LEVEL = "level";
public static final String ELT_LOGGER_FQCN = "loggerFqcn";
public static final String ELT_LOGGER_NAME = "loggerName";
public static final String ELT_MARKER = "marker";
public static final String ELT_PARENTS = "parents";
public static final String ELT_SOURCE = "source";
public static final String ELT_SUPPRESSED = "suppressed";
public static final String ELT_THREAD = "thread";
public static final String ELT_THROWN = "thrown";
public static final String ELT_MESSAGE = "message";
public static final String ELT_EXTENDED_STACK_TRACE = "extendedStackTrace";
public static final String ELT_NANO_TIME = "nanoTime";
public static final String ELT_INSTANT = "instant";
public static final String ELT_TIME_MILLIS = "timeMillis";

private JsonConstants() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.apache.logging.log4j.core.jackson.Initializers.SetupContextAsEntryListInitializer;
import org.apache.logging.log4j.core.jackson.Initializers.SetupContextInitializer;
import org.apache.logging.log4j.core.jackson.Initializers.SetupContextJsonInitializer;
import org.apache.logging.log4j.core.jackson.Initializers.SimpleModuleInitializer;

/**
Expand All @@ -33,7 +33,6 @@ class Log4jJsonModule extends SimpleModule {
private final boolean encodeThreadContextAsList;
private final boolean includeStacktrace;
private final boolean stacktraceAsString;
private final boolean objectMessageAsJsonObject;

Log4jJsonModule(
final boolean encodeThreadContextAsList,
Expand All @@ -44,7 +43,6 @@ class Log4jJsonModule extends SimpleModule {
this.encodeThreadContextAsList = encodeThreadContextAsList;
this.includeStacktrace = includeStacktrace;
this.stacktraceAsString = stacktraceAsString;
this.objectMessageAsJsonObject = objectMessageAsJsonObject;
// MUST init here.
// Calling this from setupModule is too late!
//noinspection ThisEscapedInObjectConstruction
Expand All @@ -56,9 +54,9 @@ public void setupModule(final SetupContext context) {
// Calling super is a MUST!
super.setupModule(context);
if (encodeThreadContextAsList) {
new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
new SetupContextAsEntryListInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
} else {
new SetupContextJsonInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package org.apache.logging.log4j.core.jackson;

import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
import org.apache.logging.log4j.core.jackson.Initializers.SetupContextInitializer;
import org.apache.logging.log4j.core.jackson.Initializers.SetupContextAsEntryListInitializer;
import org.apache.logging.log4j.core.jackson.Initializers.SimpleModuleInitializer;

/**
Expand All @@ -43,6 +43,6 @@ final class Log4jXmlModule extends JacksonXmlModule {
public void setupModule(final SetupContext context) {
// Calling super is a MUST!
super.setupModule(context);
new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
new SetupContextAsEntryListInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.apache.logging.log4j.core.jackson.Initializers.SetupContextAsEntryListInitializer;
import org.apache.logging.log4j.core.jackson.Initializers.SetupContextInitializer;
import org.apache.logging.log4j.core.jackson.Initializers.SetupContextJsonInitializer;
import org.apache.logging.log4j.core.jackson.Initializers.SimpleModuleInitializer;

/**
Expand Down Expand Up @@ -53,9 +53,9 @@ public void setupModule(final SetupContext context) {
// Calling super is a MUST!
super.setupModule(context);
if (encodeThreadContextAsList) {
new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
new SetupContextAsEntryListInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
} else {
new SetupContextJsonInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
new SetupContextInitializer().setupModule(context, includeStacktrace, stacktraceAsString);
}
}
}
Loading