2011-12-12 36 views
7

मैं चाहता हूं कि जेबॉस केवल मेरी युद्ध फ़ाइल में स्थित निर्भरताओं का उपयोग करे। प्रत्येक बार जब मैं इस युद्ध फ़ाइल को तैनात करता हूं, तो जेबॉस अभी भी अपने स्वयं के जार का उपयोग करता है।जेबॉस 5.x पर जेपीए 2 का उपयोग कैसे करें? (या कक्षा लोडिंग अलगाव समस्या को कैसे खत्म करें?)

<?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:

यहाँ jboss-web.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

+0

आप कैसे जानते हैं कि यह अपने स्वयं के जार का उपयोग कर रहा है? – gkamal

+0

@gkamal जब मेरा ऐप चलाया जाता है, तो मुझे 'NoSuchMethod' अपवाद मिला। – Stephan

+0

क्या डब्ल्यूएआर स्वयं पर तैनात है या क्या यह ईएआर का हिस्सा है? – CoolBeans

उत्तर

7

1> सारांश

प्रारंभ में, मैंने जेबॉस 5.1.0.जीए के साथ हाइबरनेट 3.6.4 जार लोड करने के लिए इस क्लास लोडिंग अलगाव की कोशिश की है।

यह निश्चित रूप से संभव नहीं है। हुड के नीचे कुछ जादू है जो आपको जेपीए 2 समर्थन के साथ किसी भी हाइबरनेट संस्करण का उपयोग करने से रोकता है।

मैं वास्तव में को निराश करता हूं कि जेबॉस प्रोजेक्ट ने 5.1.0.जी.ए. पर जेपीए 2 का समर्थन करने के लिए किसी प्रकार का पैच या सर्विस पैक प्रदान नहीं किया था।

2> कारगर युक्तियाँ: "द कर्नेल समाधान"
मैं JBoss 5.1.0.GA साथ JPA2 उपयोग करने के लिए मैं यहां अपने नुस्खा का वर्णन कामयाब रहे। यह अवधारणा का एक सबूत है जिसका उपयोग आप अपना स्वयं का समाधान करने के लिए कर सकते हैं।

सामग्री:

  • 1 युद्ध संग्रह
  • 1 सर्वलेट
  • 1 स्टैंडअलोन जावा आवेदन (J2SE)

पकाने की विधि:

चरण 1: स्टैंडअलोन एप्लिकेशन (एपीपी)

इस एप्लिकेशन को हाइबरनेट का उपयोग करने के लिए सर्वलेट से निर्देश प्राप्त होंगे।

मैं आपको संचार विधि का विकल्प छोड़ देता हूं। जैसा कि एपीपी जेपीए 2 का उपयोग करता है, उसे META-INF फ़ोल्डर में स्थित persistence.xml फ़ाइल की आवश्यकता होगी। जेबॉस 5.x के बाद, जब आप एक युद्ध तैनात करते हैं, तो जेबॉस अंधेरे से persistence.xml फ़ाइलों को ढूंढने और तैनात करने के लिए युद्ध और उसके सभी उप-तैनाती को स्कैन करेगा। उदाहरण के लिए my-persistence.xml में अपनी persistence.xml फ़ाइल का नाम बदलें। जब आप अपना EntityManagerFactory बनाते हैं तो नीचे दिए गए कोड का उपयोग करें (जेबॉस को persistence.xml को तैनात करने से रोकें)।

अद्यतन: यह विधि काम करती है लेकिन कुछ अजीब चेतावनियां हाइबरनेट द्वारा उठाई जाती हैं। उन चेतावनियों को रोकने के लिए, मैंने WAR के बाहर META-INF फ़ोल्डर और दृढ़ता फ़ाइल (अब वापस persistence.xml पर नामित) डालने का निर्णय लिया है। मेरे मामले में, मैंने हार्ड ड्राइव पर एक विशेष कॉन्फ़िगरेशन फ़ोल्डर चुना और इसे क्लासपाथ में जोड़ा। दृढ़ता फ़ाइल लोड करने के लिए कोई और अजीब चेतावनी और कोई कस्टम क्लासलोडर आवश्यक नहीं है।

मैं इसे कस्टम क्लास लोडर का उपयोग करने या दृढ़ता फ़ाइल स्थान बदलने के बीच चुनने के लिए छोड़ देता हूं। दोनों मामलों में, जेबॉस को दृढ़ता फ़ाइल नहीं मिलेगी।


चरण 2: सर्वलेट

सर्वलेट डेटाबेस का उपयोग करने की जरूरत है जब निर्माण, यह ऐप्लिकेशन को लॉन्च और यह बताता है कि क्या करना है।

एपीपी को लॉच करने के लिए, सर्वलेट एक नया जेवीएम बनाने और एपीपी के क्लासपाथ का निर्माण करने के लिए ज़िम्मेदार है। नीचे दिए गए कोड को पढ़ें (एक जेवीएम स्पॉइंग)। classpath के बाद से सभी आवश्यक जार युद्ध संग्रह का /lib निर्देशिका में हो जाएगा आसानी से बनाने योग्य है ...


चरण 3: युद्ध संग्रह

एक युद्ध संग्रह जहां डाल बिल्ड बिल्ड एक जार के रूप में पैक सर्वलेट और स्टैंडअलोन आवेदन। एपीपी युद्ध की निर्भरता होगी।


रोकें 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(); 
    } 
} 
1

मूल विन्यास आप था Spawning की तैनाती (jboss-web.xml और jboss- classloading.xml) ईएपी-5.12 पर मेरे लिए काम करता है।

जाहिर jboss-web.xml के

java2ClassLoadingCompliance="false" 

और/या

<loader-repository-config> 
     java2ParentDelegation=false 
    </loader-repository-config> 

Jboss द्वारा नजरअंदाज कर दिया जा रहा है। http://docs.jboss.org/jbossesb/docs/4.10/manuals/html/Getting_Started_Guide/index.html#sect-scoped_deploy देखें जहां इसका उल्लेख किया गया है (सामुदायिक संस्करण, लेकिन स्पष्ट रूप से jboss के धन्य संस्करण के लिए भी मान्य है)

मैं लंबे समय से w/यह संघर्ष कर रहा था। फिर छोड़ दिया। फिर हाल ही में इसे फिर से संशोधित किया और jboss-classloading.xml समाधान पर ठोकर खाई।

इसके बिना

, मैं ClassCastException मिलेगा:

java.lang.ClassCastException: org.hibernate.ejb.HibernatePersistence javax.persistence.spi.PersistenceProvider

में ढाला नहीं जा सकते हैं मैं किसी बाद वाले संस्करण है (3.6.0. फाइनल) जेबॉस द्वारा उपयोग किए जाने वाले युद्ध की तुलना में युद्ध में हाइबरनेट-एंटिनेमैनर।

<dependency> 
    <groupId>org.hibernate</groupId> 
    <artifactId>hibernate-entitymanager</artifactId> 
    <version>3.6.0.Final</version> 
    <type>jar</type> 
    <scope>compile</scope> 
</dependency> 

क्या इस बारे में बहुत अच्छा है, अब है कि यह काम करता है, मैं बिल्ला और jboss पर एक ही युद्ध की तैनाती कर सकता है। (बैकअप समाधान के लिए क्लाउड में टोमकैट, और "ग्राउंड" पर जेबॉस।)

+0

ग्रेट अगर यह आपके लिए जेबॉस ईएपी-5.1.2 पर काम करता है लेकिन शुरुआत में मेरे पास जेबॉस 5.1.0.जीए के साथ काम करने का कोई विकल्प नहीं था;) – Stephan

1

सहमत हुए। हम निम्नलिखित कदम उठाए:

निम्नलिखित जार फ़ाइलों jboss_home/आम/lib निर्देशिका से निकाल दिया जाना चाहिए:

  • EJB3-persistence.jar (हम जेपीए 2.0 के लिए हाइबरनेट के कार्यान्वयन का उपयोग किया जाएगा)
  • हाइबरनेट-annotations.jar
  • (यह अब हाइबरनेट कोर का हिस्सा है) हाइबरनेट-c3p0.jar हाइबरनेट-कॉमन्स-annotations.jar
  • हाइबरनेट-core.jar हाइबरनेट-entitymanager.jar
  • हाइबरनेट-validator.jar

निम्नलिखित उन्नत बनाया जार jboss_home/आम में जोड़े/lib निर्देशिका:

  • हाइबरनेट-c3p0-3.6.10.Final.jar
  • हाइबरनेट-कॉमन्स-annotations- 3.2.0.Final.jar
  • हाइबरनेट कोर-3.6.10.Final.jar
  • हाइबरनेट-entitymanager-3.6.10.Final.jar
  • हाइबरनेट-जेपीए-2.0-api-1.0.1। Final.jar
  • हाइबरनेट-सत्यापनकर्ता-4.2.0.Final.jar
  • मान्यता-api-1.0.0.GA.jar (हाइबरनेट-सत्यापनकर्ता की निर्भरता)

जोड़े फ़ाइल (जैसे) my-war\src\main\webapp\WEB-INF\jboss-classloading.xml

किसी भी जेबॉस क्लाइंट लाइब्रेरी के बदले आपके युद्ध में हाइबरनेट कक्षाओं का उपयोग सुनिश्चित करने के लिए डिफ़ॉल्ट क्लास-लोडिंग नीति को ओवरराइड करें। यह jboss-classloading.xml फ़ाइल को 'my-war/src/main/webapp/WEB-INF' निर्देशिका में जोड़कर किया जा सकता है। नोट करने के लिए आयात लाइन पैरेंट-प्रथम विशेषता को गलत पर सेट कर रही है।

<?xml version="1.0" encoding="UTF-8"?> 
<classloading xmlns="urn:jboss:classloading:1.0" 
    export-all="NON_EMPTY" 
    import-all="true" 
    parent-first="false"> 
</classloading> 

नाम बदलें (जैसे) '/src/main/resources/META-INF/persistence.xml'

JBoss आँख बंद करके किसी भी persistence.xml फ़ाइल है कि एक META-INF निर्देशिका में मौजूद है लोड करने का प्रयास करेंगे कक्षापथ पर। चूंकि जेबॉस के साथ भेजे गए निरंतरता इकाई मेटाडाटा नियोक्ता केवल जेपीए 1.0 का समर्थन करता है, इसलिए हमें इस व्यवहार को अक्षम करने और इसे वसंत में प्रतिनिधि करने की आवश्यकता है। यह persistence.xml को (उदाहरण के लिए) /src/main/resources/META-INF/my-persistence.xml

अद्यतन '/src/main/resources/spring-jpaaccess.xml' का नाम बदलकर आसानी से किया जा सकता है।

स्प्रिंग एप्लिकेशन संदर्भ कॉन्फ़िगरेशन (उदाहरण के लिए) '/src/main/resources/spring-jpaaccess.xml' अपडेट करें और निम्नानुसार persistenceXmlLocation जोड़ें।

<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="persistenceUnitName" value="myPU" /> 
    <property name="persistenceXmlLocation" value="classpath:META-INF/my-persistence.xml" /> 
/bean>