这个开始让我完全疯了…
我想使用Maven创建一个Glassfish客户端应用程序。
为此,我添加了必需的gf-client依赖项:
<dependency> <groupId>org.glassfish.appclient</groupId> <artifactId>gf-client</artifactId> <version>3.1</version> <type>pom</type> <scope>compile</scope> </dependency>
然后,想要联系运行在相同应用程序上的我的Glassfish服务器,我进行了常规查找:
Properties p = new Properties(); // optional. Defaults to localhost. Only needed if web server is running // on a different host than the appserver p.setProperty("org.omg.CORBA.ORBInitialHost", "localhost"); // optional. Defaults to 3700. Only needed if target orb port is not // 3700. p.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); Context context = new InitialContext(p); // Stores the list of reachable EJBs return context.lookup(interfacesToNames.getProperty(className));
不幸的是,这样做时,我得到的只是
Caused by: javax.naming.NoInitialContextException: Cannot instantiate class: com.sun.enterprise.naming.impl.SerialInitContextFactory [Root exception is java.lang.ClassNotFoundException: com/sun/enterprise/naming/impl/SerialInitContextFactory] at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:674) at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307) at javax.naming.InitialContext.init(InitialContext.java:242) at javax.naming.InitialContext.<init>(InitialContext.java:216) ... 6 more Caused by: java.lang.ClassNotFoundException: com/sun/enterprise/naming/impl/SerialInitContextFactory at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:264) at com.sun.naming.internal.VersionHelper12.loadClass(VersionHelper12.java:63) at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:671) ... 9 more
经过一番检查后,我注意到glassfish- naming-3.1.jar该客户端应用程序的CLASSPATH中存在我的文件夹。并且,根据Eclipse代码查找,应该包含此jar com.sun.enterprise.naming.impl.SerialInitContextFactory。但是,如果处于调试模式,getClass().getClassLoader().getResource("com/sun/enterprise/naming/impl/SerialInitContextFactory")则返回null,这清楚地表明找不到该类。
glassfish- naming-3.1.jar
com.sun.enterprise.naming.impl.SerialInitContextFactory
getClass().getClassLoader().getResource("com/sun/enterprise/naming/impl/SerialInitContextFactory")
有关更多信息,请使用以下插件配置从我的本地Maven存储库复制JAR:
<plugin> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>package output directory</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <prependGroupId>true</prependGroupId> <includeScope>compile</includeScope> <outputDirectory>${dependencies.outputDir}/jars</outputDirectory> <prefix>${dependencies.outputDir}</prefix> </configuration> </execution> </executions> </plugin>
此外,我不得不承认,当使用相同的API运行简单的测试以连接到Glassfish服务器时,绝对没有问题,这使我想到了ClassLoader问题。
运行该客户端时,当前的类加载器为(由表示getClass().getClassLoader().getClass().getName())sun.misc.Launcher$AppClassLoader。不幸的是,哪个与运行单元测试时完全相同。
getClass().getClassLoader().getClass().getName()
sun.misc.Launcher$AppClassLoader
那么,我该怎么做才能解决该错误?
EDIT 类存在于中glassfish-naming-3.1.jar,但似乎无法通过标准类加载器找到。
glassfish-naming-3.1.jar
编辑 一个有趣的发现:
getClass().getClassLoader().getResource("com/sun/enterprise/naming/impl") = jar:file:/C:/Users/pouet/pouet/target/jars/glassfish-naming-3.1.jar!/com/sun/enterprise/naming/impl
而
getClass().getClassLoader().getResource("com/sun/enterprise/naming/impl/SerialInitContextFactory") = null
由于我不完全了解的原因,在应用程序中运行时,有一个配置的Context类加载器。该类加载器似乎使用某种OSGi命名限制。
因此,为避免该错误,我重置了上下文类加载器:
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
而且有效!