Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>1> SUMMARY</strong></p> <p>Initially, I have tried this class loading isolation for loading Hibernate 3.6.4 jars with JBoss 5.1.0.GA.</p> <p><em>It's definitively NOT possible.</em> There is some magic under the hood that prevents you from using any Hibernate version with JPA2 support.</p> <p>I'm really <strong>disappointed</strong> that JBoss project didn't provide some kind of patch or service pack for supporting JPA2 on 5.1.0.GA. <br><br></p> <p><strong>2> WORKAROUND</strong> : <strong><em>"The Kernel solution"</em></strong><br> I have managed to use JPA2 with JBoss 5.1.0.GA I describe here my recipe. It's more a proof of concept you can use to make your own solution.</p> <p><em>Ingredients :</em></p> <ul> <li>1 WAR archive</li> <li>1 servlet</li> <li>1 standalone java application (J2SE)</li> </ul> <p><em>Recipe :</em></p> <p><strong>Step 1</strong>: Build the standalone application (APP)</p> <p>This application will receive instructions from the servlet for using Hibernate.</p> <p>I leave you the choice of the communication method. As the APP uses JPA2, it will need a <code>persistence.xml</code> file located in a <code>META-INF</code> folder. Since JBoss 5.x, when you deploy a WAR, JBoss will scan the WAR and all its sub-deployments for finding and deploying blindly <code>persistence.xml</code> files. Rename your <code>persistence.xml</code> file into <code>my-persistence.xml</code> for example. Use the code below when you build your <code>EntityManagerFactory</code> (Prevent JBoss from deploying persistence.xml).</p> <p><strong>UPDATE:</strong> This method does work but some strange warnings are raised by Hibernate. In order to stop those warnings, I have decided to put the <code>META-INF</code> folder and the persistence file (renamed back to <code>persistence.xml</code> now) outside of the WAR. In my case, I choosed a special config folder on the hard drive and added it to the classpath. No more strange warnings and no custom classloader required for loading the persistence file.</p> <p>I leave it up to you to choose between using a custom class loader or changing the persistence file location. In both cases, JBoss won't find the persistence file. <br><br><br> <strong>Step 2</strong>: Build the servlet</p> <p>When the servlet needs to access the database, it launches the APP and tells it what to do.</p> <p>For lauching the APP, the servlet is responsible of spawning a new JVM and build the classpath of the APP. Read the code below for (Spawning a JVM). The classpath is <em>easily</em> buildable since all the required jars will be in the <code>/lib</code> directory of the WAR archive... <br><br><br> <strong>Step 3</strong>: Build the WAR archive</p> <p>Build a WAR archive where you put the servlet and the standalone application packaged as a JAR. The APP will be a dependency of the WAR.</p> <hr> <p><strong>Prevent JBoss from deploying persistence.xml</strong></p> <pre><code>// 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&lt;URL&gt; getResources(String name) throws IOException { ArrayList&lt;URL&gt; resources = new ArrayList&lt;URL&gt;(); 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&lt;?&gt; 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(); } } </code></pre> <p><strong>Spawning a JVM</strong></p> <pre><code>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&lt;String&gt; command = new ArrayList&lt;String&gt;(); 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(); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload