如何在JBoss 5.x上使用JPA2? (或如何消除类加载隔离问题?)
作者:互联网
我希望JBoss只使用我的war文件中的依赖项.
每次我部署这个war文件时,JBoss仍然使用自己的jar.
这是我使用的jboss-web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<class-loading java2ClassLoadingCompliance="false">
<loader-repository>
my.package:loader=my-app.war
<loader-repository-config>
java2ParentDelegation=false
</loader-repository-config>
</loader-repository>
</class-loading>
</jboss-web>
和jboss-classloading.xml:
<?xml version="1.0" encoding="UTF-8"?>
<classloading
xmlns="urn:jboss:classloading:1.0"
export-all="NON_EMPTY"
import-all="true"
parent-first="false"/>
JBoss 5.1.0.GA
解决方法:
1 GT;摘要
最初,我尝试过这个类加载隔离,用于加载带有JBoss 5.1.0.GA的Hibernate 3.6.4 jar.
这绝对不可能.引擎盖下有一些魔法阻止你使用任何支持JPA2的Hibernate版本.
我真的很失望JBoss项目没有提供某种补丁或服务包来支持5.1.0.GA上的JPA2.
2 – ;解决方法:“内核解决方案”
我已经设法使用JPA2和JBoss 5.1.0.GA
我在这里描述我的食谱.它更像是您可以用来制作自己的解决方案的概念证明.
配料 :
> 1 WAR档案
> 1个servlet
> 1个独立的java应用程序(J2SE)
食谱 :
第1步:构建独立应用程序(APP)
此应用程序将从servlet接收有关使用Hibernate的指令.
我给你留下了沟通方法的选择.
由于APP使用JPA2,因此需要一个位于META-INF文件夹中的persistence.xml文件.
从JBoss 5.x开始,当您部署WAR时,JBoss将扫描WAR及其所有子部署,以便盲目查找和部署persistence.xml文件.例如,将persistence.xml文件重命名为my-persistence.xml.在构建EntityManagerFactory时使用以下代码(防止JBoss部署persistence.xml).
更新:
这种方法确实有效,但Hibernate引发了一些奇怪的警告.为了阻止这些警告,我决定将META-INF文件夹和持久性文件(现在重命名为persistence.xml)放在WAR之外.在我的例子中,我在硬盘驱动器上选择了一个特殊的配置文件夹,并将其添加到类路径中.没有更奇怪的警告,也没有加载持久性文件所需的自定义类加载器.
我让您可以选择使用自定义类加载器还是更改持久性文件位置.在这两种情况下,JBoss都找不到持久性文件.
第2步:构建servlet
当servlet需要访问数据库时,它会启动APP并告诉它该做什么.
为了推动APP,servlet负责生成新的JVM并构建APP的类路径.阅读下面的代码(生成JVM).类路径很容易构建,因为所有必需的jar都将在WAR存档的/ lib目录中…
第3步:构建WAR归档文件
构建一个WAR归档文件,将servlet和独立应用程序打包为JAR. APP将是WAR的依赖.
阻止JBoss部署persistence.xml
// Install a proxy class loader for adding renamed persistence.xml file
Thread t = Thread.currentThread();
ClassLoader clOriginal = t.getContextClassLoader();
t.setContextClassLoader(new SpecialClassLoader(clOriginal, "META-INF/my-persistence.xml"));
// Build EntityManagerFactory
EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);
// Restore original class loader
t.setContextClassLoader(clOriginal);
//...
private class ProxyClassLoader extends ClassLoader {
private ClassLoader realClassLoader;
private String hiddenFromJBossPersistenceFile;
public ProxyClassLoader(ClassLoader realClassLoader, String hiddenFromJBossPersistenceFile) {
this.realClassLoader = realClassLoader;
this.hiddenFromJBossPersistenceFile = hiddenFromJBossPersistenceFile;
}
public void clearAssertionStatus() {
realClassLoader.clearAssertionStatus();
}
public boolean equals(Object obj) {
return realClassLoader.equals(obj);
}
public URL getResource(String name) {
return realClassLoader.getResource(name);
}
public InputStream getResourceAsStream(String name) {
return realClassLoader.getResourceAsStream(name);
}
public Enumeration<URL> getResources(String name) throws IOException {
ArrayList<URL> resources = new ArrayList<URL>();
if (name.equalsIgnoreCase("META-INF/persistence.xml")) {
resources.add(getResource(this.hiddenFromJBossPersistenceFile));
}
resources.addAll(Collections.list(realClassLoader.getResources(name)));
return Collections.enumeration(resources);
}
public int hashCode() {
return realClassLoader.hashCode();
}
public Class<?> loadClass(String name) throws ClassNotFoundException {
return realClassLoader.loadClass(name);
}
public void setClassAssertionStatus(String className, boolean enabled) {
realClassLoader.setClassAssertionStatus(className, enabled);
}
public void setDefaultAssertionStatus(boolean enabled) {
realClassLoader.setDefaultAssertionStatus(enabled);
}
public void setPackageAssertionStatus(String packageName, boolean enabled) {
realClassLoader.setPackageAssertionStatus(packageName, enabled);
}
public String toString() {
return realClassLoader.toString();
}
}
产生JVM
public static Process createProcess(final String optionsAsString, final String workingDir, final String mainClass, final String[] arguments) throws IOException {
String jvm = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
String[] options = optionsAsString.split(" ");
List<String> command = new ArrayList<String>();
command.add(jvm);
command.addAll(Arrays.asList(options));
command.add(mainClass);
command.addAll(Arrays.asList(arguments));
//System.out.println(command);
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(new File(workingDir));
return processBuilder.start();
}
public static void makeItRun() {
try {
// Start JVM
String classPath = buildClassPath();
String workingDir = getSuitableWorkingDir();//or just "."
Process java = createProcess("-cp \"" + classPath + "\"", workingDir, my.package.APP.class.getCanonicalName(), "-the -options -of -my -APP");
// Communicate with your APP here ...
// Stop JVM
java.destroy();
} catch(Throwable t) {
t.printStackTrace();
}
}
标签:jboss5-x,java,war,classloader 来源: https://codeday.me/bug/20190929/1829973.html