其他分享
首页 > 其他分享> > 如何在JBoss 5.x上使用JPA2? (或如何消除类加载隔离问题?)

如何在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