Search code examples
javaslf4jopenjdk-11

How to have same slf4j log with JDK8 and JDK11 (with String.format inside)?


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}"

Solution

  • 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();
            }
        }
    
    }