如何管理Java DIY插件依赖项

时间:2018-07-16 16:18:38

标签: java maven plugins

不确定标题是否很好。不知道如何更好地描述它。在那里也全力以赴。现在到实际问题。

我正在尝试为自己制作的程序制作插件。我定义了一堆接口和抽象类。这些是在插件中实现的,然后像这样在实际程序中加载

File pluginFolder = new File(PLUGIN_PATH);

        if (!pluginFolder.exists())
            pluginFolder.mkdir();

        File[] files = pluginFolder.listFiles((dir, name) -> name.endsWith(".jar"));
        ArrayList<URL> urls = new ArrayList<>();
        ArrayList<String> classes = new ArrayList<>();

        if (files != null) {
            Arrays.stream(files).forEach(file -> {
                try {
                    JarFile jarFile = new JarFile(file);
                    urls.add(new URL(String.format("jar:file:%s/%s!/", PLUGIN_PATH, file.getName())));
                    jarFile.stream().forEach(jarEntry -> {
                        if (jarEntry.getName().endsWith(".class"))
                            classes.add(jarEntry.getName());
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            URLClassLoader pluginLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]));
            this.apiClientList = new LinkedList<>();
            classes.forEach(curClassString -> {
                try {
                    Class curClass = pluginLoader.loadClass(curClassString.replaceAll("/", ".").replace(".class", ""));

                    if(curClass.getSuperclass() == ApiClient.class) {
                        try {
                            this.apiClientList.add((ApiClient) curClass.getConstructor().newInstance());
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (NoSuchMethodException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }

                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            });
        }

现在,这可以很好地返回虚拟数据(该插件应该与rest API对话,或者实际上返回电影名称,艺术品和描述的任何东西)。不过,一旦我将这3个依赖项添加到插件的maven中,就可以了

<dependency>
   <groupId>org.glassfish.jersey.core</groupId>
   <artifactId>jersey-client</artifactId>
   <version>2.26</version>
   <scope>compile</scope>
</dependency>
<dependency>
   <groupId>org.glassfish.jersey.inject</groupId>
   <artifactId>jersey-hk2</artifactId>
   <version>2.26</version>
   <scope>compile</scope>
</dependency>

<dependency>
   <groupId>javax.activation</groupId>
   <artifactId>activation</artifactId>
   <version>1.1.1</version>
   <scope>compile</scope>
</dependency>

它会使程序崩溃(尽管如果我向其添加主类,则该插件可以作为独立的jar正常工作)。这是我得到的异常(从终端运行带有主类的相同jar时也不例外)。

java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:473)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:372)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:941)
Caused by: java.lang.NoClassDefFoundError: javax/xml/bind/annotation/adapters/XmlAdapter
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1009)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
    at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:545)
    at java.base/java.net.URLClassLoader.access$100(URLClassLoader.java:83)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:453)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:447)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:446)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:566)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
    at pluginapi.PluginLoader.lambda$loadPlugins$3(PluginLoader.java:63)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1378)
    at pluginapi.PluginLoader.loadPlugins(PluginLoader.java:61)
    at pluginapi.PluginLoader.<init>(PluginLoader.java:21)
    at pluginapi.PluginLoader.instanceOf(PluginLoader.java:27)
    at fxui.Main.main(Main.java:47)
    ... 11 more
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.adapters.XmlAdapter
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:466)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:566)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
    ... 28 more
Exception running application fxui.Main

并非所有Maven依赖项都发生这种情况。例如,谷歌gson可以正常工作。我没有使用插件的应用程序中包含任何插件(也没有gson),我绝对不想这样做,因为那样做会破坏整个目的。

除ContractsLibrary(用于定义插件形状的Interfaces和Abstract方法)之外,所有项目都使用Java10(因为我认为jitpack,我以前将其添加为maven依赖项还不能编译Java10)。我觉得这值得一提,因为过去Java8的模块系统有时会有些奇怪。

此行if(curClass.getSuperclass() == ApiClient.class)中引发了异常,在调试时,我发现该类实际上不再等于我正在寻找的类,但是,上一行中的类是{{ 1}}。因此,真正的问题不是平凡,而是上面的线。 我的意思是我猜这很有道理,因为我只是循环抛出了所有.class文件。那只是第一个,它碰巧在第一个.class文件中崩溃,女巫是属于球衣的一些异常。应该更具体一点,然后我可能不再明白了。

编辑:“已解决”(或根据您的看法躲避了项目符号) 我改变了

org.glassfish.jersey.client.AbortException

jarFile.stream().forEach(jarEntry -> {
                        if (jarEntry.getName().endsWith(".class")) {
                            classes.add(jarEntry.getName());
                        }
                    });

现在可以使用了。我的所有课程(现在还是无论如何)都放在一个名为jarFile.stream().forEach(jarEntry -> { if (jarEntry.getName().endsWith(".class") && jarEntry.getName().startsWith("api/")) { classes.add(jarEntry.getName()); } }); 的程序包中,因此仅给我我的课程(现在)。以后我可以做得更好,昨天还是整个晚上都以某种方式使我无法解决这个问题。现在,我可以真正尝试使用它了。 :)

0 个答案:

没有答案