我开发了 Jaybird JDBC 驱动程序,今天我遇到了一个问题(JDBC-325,如何使用休眠配置 Jaybird),该问题与 Jaybird 如何加载其某些组件以及如何(在这种情况下)NetBeans 限制类加载有关。
该问题与 Jaybird 使用条目加载自身部分的方式META-INF/services
以及 NetBeans 用于 Hibernate 向导的类加载器显式忽略这些文件有关(请参阅下面的详细信息)。
我可以通过(也)尝试加载作为 Jaybird 实现的一部分的插件的硬编码列表,或者通过将定义移动到不同的位置来解决这个问题。
但是我想知道像 Jaybird 那样用于内部目的是否很奇怪(或错误)META-INF/services
?
我也不明白为什么 NetBeans 会排除加载META-INF/services
? Drew的评论似乎表明 NetBeans 在加载驱动程序时使用它来解决错误(请参阅此问题),尽管我认为用户会更好地解决包括驱动程序的所有依赖项在内的问题。
问题详情
Jaybird 为支持的协议使用插件,例如 Type 4 协议、自定义 Type 4 Open Office 协议、Type 2 嵌入式(本机)协议和 Type 2 本机客户端协议。我还相信第三方曾经使用它来提供将 Oracle 特定语法转换为 Firebird 语法的驱动程序。
所有这些插件都在中列出META-INF/services/org.firebirdsql.gds.impl.GDSFactoryPlugin
并以类似于java.util.ServiceLoader
(当前 2.2.x 驱动程序仍支持 Java 5,因此我们实际上不使用ServiceLoader
)的方式加载。对于即将发布的版本,我还计划将其用于支持的连接编码和(有线)协议定义。这将允许“自定义”编码定义(例如扩展支持的编码,或使用替代编码)或不同的协议实现(例如,用于故障排除、自定义日志记录等)。
现在实际的问题是 Netbeans 向导Hibernate 映射文件和来自数据库的 POJO使用自定义类加载器(org.netbeans.modules.hibernate.util.CustomClassLoader
),并且这个类加载器忽略META-INF/services
. 请注意,只有这个向导有问题,Netbeans 本身可以毫无问题地使用驱动程序。
代码忽略META-INF/services
:
@Override
public URL findResource(String name) {
return name.startsWith("META-INF/services") ? null : super.findResource(name); //NOI18N
}
@Override
public Enumeration<URL> findResources(String name) throws IOException {
if (name.startsWith("META-INF/services")) { //NOI18N
return Collections.enumeration(Collections.<URL>emptyList());
} else {
return super.findResources(name);
}
}
这导致没有插件被发现并且驱动程序没有协议,这导致NullPointerException
内部 Netbeans,因为没有创建连接。