我希望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>汇总

最初,我尝试使用此类加载隔离功能来使用JBoss 5.1.0.GA加载Hibernate 3.6.4 jar。

绝对不可能。有一些不可思议的因素使您无法使用任何支持JPA2的Hibernate版本。

我真的对感到非常失望,感到JBoss项目没有提供某种补丁或服务包来支持5.1.0.GA上的JPA2。

2>替代方法:“内核解决方案”
我设法在JBoss 5.1.0.GA中使用JPA2
我在这里描述我的食谱。它更多是您可以用来制定自己的解决方案的概念证明。

原料 :

  • 1 WAR存档
  • 1 servlet
  • 1个独立的Java应用程序(J2SE)

  • 食谱 :

    步骤1 :构建独立应用程序(APP)

    该应用程序将从Servlet接收有关使用Hibernate的指令。

    我让您选择沟通方式。
    由于APP使用JPA2,因此需要位于persistence.xml文件夹中的META-INF文件。
    从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目录中,因此可以轻松构建classpath。

    步骤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();
       }
    }
    

    10-07 19:27
    查看更多