jjzjj

java - 如何在 JBoss 5.x 上使用 JPA2? (或如何消除类加载隔离问题?)

coder 2024-03-11 原文

我希望 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> 解决方法:“内核解决方案”
我已经设法将 JPA2 与 JBoss 5.1.0.GA 一起使用 我在这里描述我的食谱。它更像是一个概念证明,您可以使用它来制定自己的解决方案。

成分:

  • 1 个 WAR 存档
  • 1 个小服务程序
  • 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并告诉它做什么。

为了启动应用程序,servlet 负责生成新的 JVM 并构建应用程序的类路径。阅读下面的代码(生成 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();
   }
}

关于java - 如何在 JBoss 5.x 上使用 JPA2? (或如何消除类加载隔离问题?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8476944/

有关java - 如何在 JBoss 5.x 上使用 JPA2? (或如何消除类加载隔离问题?)的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  8. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  9. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  10. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

随机推荐