Skip to content

Commit bbe797f

Browse files
garyrussellartembilan
authored andcommitted
Fix DEBUG Logging for Projection
Don't Log Converted Message With Projection `toString()` cannot be invoked on the payload proxy created by the projection factory. Increase memory for builds. * Unlike Kafka, we can't use the converter type to determine if projection was used. * Add null check. # Conflicts: # build.gradle # gradle.properties # spring-amqp/src/main/java/org/springframework/amqp/support/converter/AbstractJackson2MessageConverter.java
1 parent bde294d commit bbe797f

File tree

5 files changed

+76
-29
lines changed

5 files changed

+76
-29
lines changed

build.gradle

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,17 @@ subprojects { subproject ->
217217
compileKotlin.dependsOn updateCopyrights
218218

219219
test {
220+
maxHeapSize = '2g'
221+
jvmArgs '-XX:+HeapDumpOnOutOfMemoryError'
222+
223+
testLogging {
224+
events "skipped", "failed"
225+
showStandardStreams = project.hasProperty("showStandardStreams") ?: false
226+
showExceptions = true
227+
showStackTraces = true
228+
exceptionFormat = 'full'
229+
}
230+
220231
jacoco {
221232
append = false
222233
destinationFile = file("$buildDir/jacoco.exec")

gradle.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
version=2.2.20.BUILD-SNAPSHOT
2-
org.gradle.daemon=true
2+
org.gradle.jvmargs=-Xms512m -Xmx4g -XX:MaxPermSize=1024m -XX:MaxMetaspaceSize=1g
3+
org.gradlee.caching=trueorg.gradle.daemon=true

spring-amqp/src/main/java/org/springframework/amqp/core/MessageProperties.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ public class MessageProperties implements Serializable {
128128

129129
private boolean lastInBatch;
130130

131+
private boolean projectionUsed;
132+
131133
private transient Type inferredArgumentType;
132134

133135
private transient Method targetMethod;
@@ -552,6 +554,26 @@ public void setLastInBatch(boolean lastInBatch) {
552554
this.lastInBatch = lastInBatch;
553555
}
554556

557+
/**
558+
* Get an internal flag used to communicate that conversion used projection; always
559+
* false at the application level.
560+
* @return true if projection was used.
561+
* @since 2.2.20
562+
*/
563+
public boolean isProjectionUsed() {
564+
return this.projectionUsed;
565+
}
566+
567+
/**
568+
* Set an internal flag used to communicate that conversion used projection; always false
569+
* at the application level.
570+
* @param projectionUsed true for projection.
571+
* @since 2.2.20
572+
*/
573+
public void setProjectionUsed(boolean projectionUsed) {
574+
this.projectionUsed = projectionUsed;
575+
}
576+
555577
/**
556578
* Return the x-death header.
557579
* @return the header.

spring-amqp/src/main/java/org/springframework/amqp/support/converter/AbstractJackson2MessageConverter.java

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -290,33 +290,7 @@ private Object doFromMessage(Message message, Object conversionHint, MessageProp
290290

291291
Object content = null;
292292
try {
293-
JavaType inferredType = this.javaTypeMapper.getInferredType(properties);
294-
if (inferredType != null && this.useProjectionForInterfaces && inferredType.isInterface()
295-
&& !inferredType.getRawClass().getPackage().getName().startsWith("java.util")) { // List etc
296-
content = this.projectingConverter.convert(message, inferredType.getRawClass());
297-
}
298-
else if (inferredType != null && this.alwaysConvertToInferredType) {
299-
content = tryConverType(message, encoding, inferredType);
300-
}
301-
if (content == null) {
302-
if (conversionHint instanceof ParameterizedTypeReference) {
303-
content = convertBytesToObject(message.getBody(), encoding,
304-
this.objectMapper.getTypeFactory().constructType(
305-
((ParameterizedTypeReference<?>) conversionHint).getType()));
306-
}
307-
else if (getClassMapper() == null) {
308-
JavaType targetJavaType = getJavaTypeMapper()
309-
.toJavaType(message.getMessageProperties());
310-
content = convertBytesToObject(message.getBody(),
311-
encoding, targetJavaType);
312-
}
313-
else {
314-
Class<?> targetClass = getClassMapper().toClass(// NOSONAR never null
315-
message.getMessageProperties());
316-
content = convertBytesToObject(message.getBody(),
317-
encoding, targetClass);
318-
}
319-
}
293+
content = convertContent(message, conversionHint, properties, encoding);
320294
}
321295
catch (IOException e) {
322296
throw new MessageConversionException(
@@ -325,6 +299,41 @@ else if (getClassMapper() == null) {
325299
return content;
326300
}
327301

302+
private Object convertContent(Message message, Object conversionHint, MessageProperties properties, String encoding)
303+
throws IOException {
304+
305+
Object content = null;
306+
JavaType inferredType = this.javaTypeMapper.getInferredType(properties);
307+
if (inferredType != null && this.useProjectionForInterfaces && inferredType.isInterface()
308+
&& !inferredType.getRawClass().getPackage().getName().startsWith("java.util")) { // List etc
309+
content = this.projectingConverter.convert(message, inferredType.getRawClass());
310+
properties.setProjectionUsed(true);
311+
}
312+
else if (inferredType != null && this.alwaysConvertToInferredType) {
313+
content = tryConverType(message, encoding, inferredType);
314+
}
315+
if (content == null) {
316+
if (conversionHint instanceof ParameterizedTypeReference) {
317+
content = convertBytesToObject(message.getBody(), encoding,
318+
this.objectMapper.getTypeFactory().constructType(
319+
((ParameterizedTypeReference<?>) conversionHint).getType()));
320+
}
321+
else if (getClassMapper() == null) {
322+
JavaType targetJavaType = getJavaTypeMapper()
323+
.toJavaType(message.getMessageProperties());
324+
content = convertBytesToObject(message.getBody(),
325+
encoding, targetJavaType);
326+
}
327+
else {
328+
Class<?> targetClass = getClassMapper().toClass(// NOSONAR never null
329+
message.getMessageProperties());
330+
content = convertBytesToObject(message.getBody(),
331+
encoding, targetClass);
332+
}
333+
}
334+
return content;
335+
}
336+
328337
/*
329338
* Unfortunately, mapper.canDeserialize() always returns true (adds an AbstractDeserializer
330339
* to the cache); so all we can do is try a conversion.

spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/adapter/MessagingMessageListenerAdapter.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,11 @@ private void handleException(org.springframework.amqp.core.Message amqpMessage,
183183
protected void invokeHandlerAndProcessResult(@Nullable org.springframework.amqp.core.Message amqpMessage,
184184
Channel channel, Message<?> message) throws Exception { // NOSONAR
185185

186-
if (logger.isDebugEnabled()) {
186+
boolean projectionUsed = amqpMessage == null ? false : amqpMessage.getMessageProperties().isProjectionUsed();
187+
if (projectionUsed) {
188+
amqpMessage.getMessageProperties().setProjectionUsed(false);
189+
}
190+
if (logger.isDebugEnabled() && !projectionUsed) {
187191
logger.debug("Processing [" + message + "]");
188192
}
189193
InvocationResult result = null;

0 commit comments

Comments
 (0)