【问题标题】:Closing single quote missing while comparing strings in XML for Logback with Janino在比较 XML 中的 Logback 和 Janino 字符串时缺少单引号
【发布时间】:2017-08-09 18:42:47
【问题描述】:

使用Logback的条件处理比较一个Logback XML配置文件中的两个Strings如下...

<if condition="'test'.equals('test')">
    <then>
        <include resource="logback.local.xml"/>
    </then>
</if>

...导致以下异常。

14:22:08,315 |-ERROR in ch.qos.logback.core.joran.conditional.IfAction - Failed to parse condition ['test'.equals('test')] org.codehaus.commons.compiler.CompileException: Line 1, Column 38: Closing single quote missing
    at org.codehaus.commons.compiler.CompileException: Line 1, Column 38: Closing single quote missing
    at  at org.codehaus.janino.Scanner.scan(Scanner.java:359)
    at  at org.codehaus.janino.Scanner.produce(Scanner.java:267)
    at  at org.codehaus.janino.TokenStreamImpl.produceToken(TokenStreamImpl.java:62)
    at  at org.codehaus.janino.TokenStreamImpl.peek(TokenStreamImpl.java:104)
    at  at org.codehaus.janino.TokenStreamImpl.peek(TokenStreamImpl.java:134)
    at  at org.codehaus.janino.Parser.peek(Parser.java:3145)
    at  at org.codehaus.janino.Parser.parseReturnStatement(Parser.java:2048)
    at  at org.codehaus.janino.Parser.parseStatement(Parser.java:1659)
    at  at org.codehaus.janino.Parser.parseBlockStatement(Parser.java:1512)
    at  at org.codehaus.janino.Parser.parseBlockStatements(Parser.java:1474)
    at  at org.codehaus.janino.Parser.parseMethodDeclarationRest(Parser.java:1313)
    at  at org.codehaus.janino.Parser.parseClassBodyDeclaration(Parser.java:894)
    at  at org.codehaus.janino.ClassBodyEvaluator.cook(ClassBodyEvaluator.java:231)
    at  at org.codehaus.janino.SimpleCompiler.cook(SimpleCompiler.java:200)
    at  at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:76)
    at  at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:71)
    at  at ch.qos.logback.core.joran.conditional.PropertyEvalScriptBuilder.build(PropertyEvalScriptBuilder.java:47)
    at  at ch.qos.logback.core.joran.conditional.IfAction.begin(IfAction.java:65)
    at  at ch.qos.logback.core.joran.spi.Interpreter.callBeginAction(Interpreter.java:269)
    at  at ch.qos.logback.core.joran.spi.Interpreter.startElement(Interpreter.java:145)
    at  at ch.qos.logback.core.joran.spi.Interpreter.startElement(Interpreter.java:128)
    at  at ch.qos.logback.core.joran.spi.EventPlayer.play(EventPlayer.java:50)
    at  at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:155)
    at  at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:142)
    at  at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:103)
    at  at ch.qos.logback.core.joran.GenericConfigurator.doConfigure(GenericConfigurator.java:53)
    at  at ch.qos.logback.classic.util.ContextInitializer.configureByResource(ContextInitializer.java:75)
    at  at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:150)
    at  at org.slf4j.impl.StaticLoggerBinder.init(StaticLoggerBinder.java:84)
    at  at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:55)
    at  at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
    at  at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
    at  at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
    at  at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
    at  at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
    at  at com.labcorp.ncp.provider.abn.service.impl.AbnServiceImpl.<clinit>(AbnServiceImpl.java:34)
    at  at sun.reflect.GeneratedSerializationConstructorAccessor5.newInstance(Unknown Source)
    at  at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at  at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:40)
    at  at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:59)
    at  at org.mockito.internal.creation.jmock.ClassImposterizer.createProxy(ClassImposterizer.java:128)
    at  at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:63)
    at  at org.mockito.internal.creation.jmock.ClassImposterizer.imposterise(ClassImposterizer.java:56)
    at  at org.mockito.internal.creation.CglibMockMaker.createMock(CglibMockMaker.java:23)
    at  at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:26)
    at  at org.mockito.internal.MockitoCore.mock(MockitoCore.java:51)
    at  at org.mockito.Mockito.mock(Mockito.java:1243)
    at  at org.mockito.Mockito.mock(Mockito.java:1120)
    at  at com.labcorp.ncp.provider.abn.service.AbnServiceTest.invalidDxCode(AbnServiceTest.java:61)
    at  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at  at java.lang.reflect.Method.invoke(Method.java:606)
    at  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at  at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at  at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:367)
    at  at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:274)
    at  at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
    at  at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:161)
    at  at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)
    at  at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)
    at  at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121)
14:22:08,316 |-ERROR in ch.qos.logback.core.joran.conditional.IfAction - Failed to determine "if then else" result
14:22:08,316 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
14:22:08,318 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
14:22:08,324 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
14:22:08,365 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.rolling.RollingFileAppender]

【问题讨论】:

    标签: logback janino


    【解决方案1】:

    最终,您定义的条件由 Janino 作为 Groovy 脚本执行。像这样的:

      String script = "public boolean evaluate() { return \"test\".equals(\"test\"); }";
    
      ClassBodyEvaluator classBodyEvaluator = new ClassBodyEvaluator();
      classBodyEvaluator.setImplementedInterfaces(new Class[] { Condition.class });
      classBodyEvaluator.setExtendedClass(PropertyWrapperForScripts.class);
      classBodyEvaluator.setParentClassLoader(ClassBodyEvaluator.class.getClassLoader());
    
      StringReader sr = new StringReader(script);
      classBodyEvaluator.cook(null, sr);
      Class clazz = classBodyEvaluator.getClazz();
      Condition instance = (Condition) clazz.newInstance();
    

    因此,您只需要确保条件的值(被替换到脚本中)具有引用的字符串,即"..."。但由于您在 XML 中定义条件,因此必须转义引号,如下所示:

    <if condition="&quot;test&quot;.equals(&quot;test&quot;)">
    

    这将产生一个脚本:

    public boolean evaluate() { return "test".equals("test"); }
    

    ...由ch.qos.logback.core.joran.conditional.PropertyEvalScriptBuilder执行。

    我已经验证如下...

    <if condition="&quot;test&quot;.equals(&quot;test&quot;)">
        <then>
            <property name="conditionalValue" value="Conditional value is true"/>
        </then>
        <else>
            <property name="conditionalValue" value="Conditional value is false"/>
        </else>
    </if>
    
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                %d|%-5p|%t|${conditionalValue}%n
            </pattern>
        </encoder>
    </appender>
    

    ... 这个 appender 写的日志事件看起来像:

    2017-08-09 09:07:02,699|INFO |main|Conditional value is true
    

    【讨论】:

    • 谢谢。我刚刚检查并验证,pom.xml 中缺少 janino jar
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 2015-10-06
    • 2015-03-18
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多