Проблема преобразования класса Java, содержащего статический метод фабрики, в Kotlin - PullRequest
0 голосов
/ 26 января 2019

У меня не было успеха, пытаясь преобразовать это в Kotlin и использовать его.

Он работает как Java, но не с моим Kotlin (который я преобразовал с помощью IntelliJ Kotlin Plugin)

проблема заключается в этой части

 @PluginFactory
    public static AnsiConsoleAppender createAppender(

Я пытался добавить @JvmStatic и получаю эту ошибку:

Невозможно вызвать фабричный метод в классе AnsiConsoleAppender для элемента AnsiConsoleAppender: java.lang.IllegalArgumentException: параметр, указанный как ненулевое, имеет значение null: метод AnsiConsoleAppender $ Companion.AnsiConsoleAppender, фильтр параметров java.lang.reflect.InvocationTargetException

import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.appender.AppenderLoggingException;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.layout.PatternLayout;

import java.io.Serializable;

/**
 * <h2>AnsiConsoleAppender</h2>
 *
 * <h3>notes</h3>
 * <li>class name need not match the @Plugin name</li>
 * <h3>more<h3/>
 * <li><a href="https://stackoverflow.com/a/24220688/270143">How to Create a Custom Appender in log4j2?</a></li>
 */
@Plugin(name="AnsiConsoleAppender", category="Core", elementType="appender", printObject=true)
public final class AnsiConsoleAppender extends AbstractAppender {

    protected AnsiConsoleAppender(String name, Filter filter,
                                  Layout<? extends Serializable> layout, final boolean ignoreExceptions) {
        super(name, filter, layout, ignoreExceptions);
    }

    // The append method is where the appender does the work.
    // Given a log event, you are free to do with it what you want.
    // This example demonstrates:
    // 1. Concurrency: this method may be called by multiple threads concurrently
    // 2. How to use layouts
    // 3. Error handling
    //@Override
    public void append(LogEvent event) {
        try {
            final byte[] bytes = getLayout().toByteArray(event);

// output code goes here

        } catch (Exception ex) {
            if (!ignoreExceptions()) throw new AppenderLoggingException(ex);
        }
    }

    // Your custom appender needs to declare a factory method
    // annotated with `@PluginFactory`. Log4j will parse the configuration
    // and call this factory method to construct an appender instance with
    // the configured attributes.
    @PluginFactory
    public static AnsiConsoleAppender createAppender(
            @PluginAttribute("name") String name,
            @PluginElement("Layout") Layout<? extends Serializable> layout,
            @PluginElement("Filter") final Filter filter,
            @PluginAttribute("otherAttribute") String otherAttribute) {
        if (name == null) {
            LOGGER.error("No name provided for AnsiConsoleAppenderImpl");
            return null;
        }
        if (layout == null) {
            layout = PatternLayout.createDefaultLayout();
        }
        return new AnsiConsoleAppender(name, filter, layout, true);
    }
}
import org.apache.logging.log4j.core.AbstractLifeCycle
import org.apache.logging.log4j.core.Filter
import org.apache.logging.log4j.core.Layout
import org.apache.logging.log4j.core.LogEvent
import org.apache.logging.log4j.core.appender.AbstractAppender
import org.apache.logging.log4j.core.appender.AppenderLoggingException
import org.apache.logging.log4j.core.config.plugins.Plugin
import org.apache.logging.log4j.core.config.plugins.PluginAttribute
import org.apache.logging.log4j.core.config.plugins.PluginElement
import org.apache.logging.log4j.core.config.plugins.PluginFactory
import org.apache.logging.log4j.core.layout.PatternLayout

import java.io.Serializable

@Plugin(name = "AnsiConsoleAppender", category = "Core", elementType = "appender", printObject = true)
class AnsiConsoleAppender /*protected*/ constructor(
    name: String, filter: Filter,
    layout: Layout<out Serializable>, ignoreExceptions: Boolean
) : AbstractAppender(name, filter, layout, ignoreExceptions) {

    // The append method is where the appender does the work.
    // Given a log event, you are free to do with it what you want.
    // This example demonstrates:
    // 1. Concurrency: this method may be called by multiple threads concurrently
    // 2. How to use layouts
    // 3. Error handling
    //@Override
    override fun append(event: LogEvent) {
        try {
            val bytes = layout.toByteArray(event)
            //AnsiColor.out(String(bytes), ColorMaps.ASTERIKSY, null, true)
        } catch (ex: Exception) {
            if (!ignoreExceptions()) throw AppenderLoggingException(ex)
        }

    }

    companion object {

        // Your custom appender needs to declare a factory method
        // annotated with `@PluginFactory`. Log4j will parse the configuration
        // and call this factory method to construct an appender instance with
        // the configured attributes.
        @JvmStatic
        @PluginFactory
        fun createAppender(
            @PluginAttribute("name") name: String?,
            @PluginElement("Layout") layout: Layout<out Serializable>?,
            @PluginElement("Filter") filter: Filter,
            @PluginAttribute("otherAttribute") otherAttribute: String
        ): AnsiConsoleAppender? {
            val lay = layout ?: PatternLayout.createDefaultLayout()
            if (name == null) {
                AbstractLifeCycle.LOGGER.error("No name provided for AnsiConsoleAppenderImpl")
                return null
            }
            return AnsiConsoleAppender(name, filter, lay, true)
        }
    }
}

что мне не хватает?

Ответы [ 2 ]

0 голосов
/ 26 января 2019

Исключение говорит о том, что filter равно нулю.

Так что это должен быть тип NULL.

companion object {
    @PluginFactory
    @JvmStatic
    fun createAppender(
            @PluginAttribute("name") name: String,
            @PluginElement("Layout") layout: Layout<out Serializable>,
            @PluginElement("Filter") filter: Filter?,
            @PluginAttribute("otherAttribute") otherAttribute: String?
    ): AnsiConsoleAppender {
0 голосов
/ 26 января 2019

В Kotlin фабричные методы обычно определяются в сопутствующем объекте класса, например ::

class AnsiConsoleAppender : AbstractAppender() {
    companion object {
        // add JvmStatic annotation if you want to call this method from Java file
        @JvmStatic 
        @PluginFactory
        fun createAppender(/*params*/): AnsiConsoleAppender {
            //...
        }
    }
}

Подробнее о сопутствующем объекте

...