0

How to have same slf4j log with JDK8 and JDK11?

My java Slf4j logger:

log.info("---> {} {}", "When", String.format(matcher.group(1).replaceAll("\\{\\S+\\}", "{%s}").replace("(\\?)", ""), invocation.getArguments()));

My trace in java 8 by JDK8:

---> When I update text {bakery.DemoPage-input_text_field} with {Jenkins T5}

My trace in java 8 by JDK11:

---> When "I update text {bakery.DemoPage-input_text_field} with {Jenkins T5}"

EDIT:

I try this but same result:

String message = MessageFormat.format("---> {0} {1}",
                                      stepAnnotation.annotationType().getSimpleName(),
                                      String.format(matcher.group(1).replaceAll("\\{\\S+\\}", "{%s}").replace("(\\?)", ""), invocation.getArguments())
                                     );
log.info(message);

EDIT (if you want a more simple case):

log.info("---> {} {}", "When", String.format("I update text {%s} with {%s}", "bakery.DemoPage-input_text_field", "Jenkins T5"));

EDIT with @M. Deinum proposal but do not work

log.info("---> {} " + matcher.group(1).replaceAll("\\{\\S+\\}", "{}").replace("(\\?)", ""), stepAnnotation.annotationType().getSimpleName(), invocation.getArguments());

---> When "I update text [bakery.DemoPage-input_text_field, Jenkins T5, []] with {}"

EDIT: I try other proposal with external replace:

String mes = String.format(matcher.group(1).replaceAll("\\{\\S+\\}", "{%s}").replace("(\\?)", ""), invocation.getArguments());
log.info("---> {} {}", stepAnnotation.annotationType().getSimpleName(), mes);

---> When "I update text {bakery.DemoPage-input_text_field} with {Jenkins T5}"
Stéphane GRILLON
  • 11,140
  • 10
  • 85
  • 154
  • Please edit your question to include a [mcve]. – Progman Mar 11 '20 at 19:30
  • Just ditch the string format. Use `log.info("---> When I update text {} with {}", "bakery.DemoPage-input_text_field", "Jenkins T5");`. SLF4J will handle the replacement regardless of the JDK used. – M. Deinum Mar 12 '20 at 08:30
  • @Progman, I added a simpler case, but everything was already in the post to reproduce the problem. I hope this will help you reproduce the problem at home. – Stéphane GRILLON Mar 12 '20 at 08:30
  • @M.Deinum, your proposal but do not work, I edit my post with more elements – Stéphane GRILLON Mar 12 '20 at 08:57
  • Don't use replacements. Why are you adding that complexity for a simple thing as logging. Log4j already supports replacements. As I stated put the whole message in there and don't do replacement yourself. – M. Deinum Mar 12 '20 at 09:04
  • My case is not simple. The original String contain a template: `"I update text {string} with {string}(\\?)"` – Stéphane GRILLON Mar 12 '20 at 09:18
  • I found a big track. the problem does not come from `slf4j` but from `java.lang.annotation.Annotation.toString()` different in JDK8 and JDK11: `@io.cucumber.java.en.When(timeout=0, value=I update text {string} with {string}(\?))` and `@io.cucumber.java.en.When(timeout=0, value="@io.cucumber.java.en.When(timeout=0, value="I update text {string} with {string}(\?)")` – Stéphane GRILLON Mar 12 '20 at 09:49
  • here is the continuation of the problem because this one does not come from Slf4j: https://stackoverflow.com/questions/60651653/how-to-read-valus-of-java-annotation-with-jdk8-and-jdk11 – Stéphane GRILLON Mar 12 '20 at 10:04

1 Answers1

1

the problem is not come from Slf4j but from stepAnnotation.toString() different in JDK8 and JDK11)

openjdk11 and oraclejdk11 do not respect javadoc:

/**
 * Returns a string representation of this annotation.  The details
 * of the representation are implementation-dependent, but the following
 * may be regarded as typical:
 * <pre>
 *   &#064;com.acme.util.Name(first=Alfred, middle=E., last=Neuman)
 * </pre>
 *
 * @return a string representation of this annotation
 */
String toString();

Solution:

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.cucumber.java.en.When;

public class Sof {

    private static final Logger log = LoggerFactory.getLogger(Sof.class);

    @When(value = "I update text {string} with {string}(\\?)")
    public static void main(String[] args) {
        Object as[] = { "a", "b" };
        Class c = Sof.class;
        Method[] methods = c.getMethods();
        Method method = null;
        for (Method m : methods) {
            if (m.getName().equals("main")) {
                method = m;
            }
        }
        Annotation stepAnnotation = method.getAnnotation(When.class);
        Class<? extends Annotation> annotationClass = stepAnnotation.annotationType();
        try {
            Method valueMethods = annotationClass.getDeclaredMethod("value");
            if (Modifier.isPublic(valueMethods.getModifiers())) {
                log.info("---> {} " + String.format(valueMethods.invoke(stepAnnotation).toString().replaceAll("\\{\\S+\\}", "{%s}").replace("(\\?)", ""), as),
                        stepAnnotation.annotationType().getSimpleName());
            }
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
            e1.printStackTrace();
        }
    }

}
Stéphane GRILLON
  • 11,140
  • 10
  • 85
  • 154