2010-12-14 15 views
5

में किसी पैकेज के एकाधिक संस्करणों तक पहुंचें हमारे पास कई एप्लिकेशन हैं जो HTTP अनुरोध करने के लिए अपाचे HTTP क्लाइंट 3 का उपयोग करते हैं। हाल ही में हमने वेब सेवा क्लाइंट बनाने शुरू कर दिए हैं जो विभिन्न कारणों से HTTPClient 4 का उपयोग करते हैं। अपाचे स्टैंस यह है कि "प्रमुख रिलीज पीछे संगत नहीं हैं"। जबकि मैं संस्करण 4 का उपयोग करने के लिए हमारी सभी परियोजनाओं को अपडेट करना पसंद करूंगा, यह बस संभव नहीं है।जावा

तो, जबकि मेरा मुख्य प्रश्न सामान्य है, मेरा विशेष प्रश्न है। मैं उसी एप्लिकेशन में HTTPClient संस्करण 3 और 4 का उपयोग कैसे कर सकता हूं? हमारे मामले में एक एप्लिकेशन एक वेब, डेस्कटॉप, या कमांड लाइन ऐप हो सकता है।

मैंने SO question for java-dynamically-load-multiple-versions-of-same-class पढ़ा है जो अर्द्ध बंद लगता है लेकिन मुझे गतिशील भाग के बारे में बहुत कुछ परवाह नहीं है। असल में मैं चाहता हूं कि जार को ऐप के साथ भेज दिया जाए (उदाहरण के लिए, वेब ऐप के लिए वेब-आईएनएफ/lib) मैं भी OSGi को इस तरह के प्रश्नों में बहुत कुछ बताता हूं लेकिन ऐसा लगता है कि यह अधिक हो सकता है या शायद अत्यधिक जटिल हो सकता है (शायद एक साधारण उदाहरण अन्यथा साबित हो सकता है)।

अंत में मैं एक टीम जार है कि वे में ड्रॉप कर सकते हैं का एक सेट सौंपने के लिए सक्षम होना चाहते हैं और यह सिर्फ HTTP क्लाइंट 3.

+1

यह एक ऐसा मामला है जहां वास्तुशिल्प शासन एक अच्छा विचार रहा होगा: या तो संस्करण 3 के साथ चिपकने का निर्णय लेना या सबकुछ 4 संस्करण में ले जाना। अब आपको पैचवर्क समाधान के लिए कार्यान्वयन लागत का भुगतान करना होगा, और यह सिर्फ समय के साथ बदतर हो जाओ। – Anon

+1

@ आओन: कोई अपराध नहीं, लेकिन स्थिति को जानने के बिना मैं इस तरह के कंबल बयान देने की सलाह नहीं दूंगा। मैंने ऐसी टिप्पणियों को रोकने के लिए "विभिन्न कारणों से" कहा। –

+0

ओएसजीआई कम से कम काम करता है (आपको यह तय करने की ज़रूरत है कि क्या इसकी ओवरकिल है या नहीं), मुझे लाइब्रेरी के प्रत्येक संस्करण के लिए दो वेब सर्वरों के अलावा ऐसा करने के किसी भी छोटे तरीके से नहीं पता है। –

उत्तर

5

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

समस्या यह है कि यह अनिवार्य रूप से आपके "कक्षा स्थान" को विभाजित करता है, और आपके आवेदन के कुछ हिस्सों से v4 का जिक्र करते हुए आपके आवेदन के कुछ हिस्सों से v3 को संदर्भित करना अभी भी कठिन होगा। आपको अपना आवेदन बहुत सावधानी से विभाजित करना होगा ... तो क्यों न सिर्फ इसे विभाजित करें और दो एप्लिकेशन वितरित करें? अगर आप सेवाओं में कार्यक्षमता को अलग करने में सक्षम हैं

OSGi एक समाधान हो सकता है।लेकिन ओएसजीआई के लिए विरासत आवेदन को परिवर्तित करना कुछ हल्का नहीं है, और यह निश्चित रूप से आपके द्वारा चलाए जा रहे जाल से सस्ता भाग नहीं होगा। मैं इसे ओएसजीआई और एक प्रसिद्ध ओएसजीआई प्रचारक पर एक पुस्तक के लेखक के रूप में कहता हूं। आपके अनुप्रयोगों को ओएसजीआई में परिवर्तित करने का दीर्घकालिक लक्ष्य आपको बहुत लाभ प्रदान करेगा, लेकिन इसमें महत्वपूर्ण आगे की लागत भी शामिल होगी।

1

उपयोग एकाधिक वर्ग लोडर, प्रत्येक के लिए एक का उपयोग कर अपनी परियोजना के स्वतंत्र काम करता है HTTP क्लाइंट जिसे आप गले लगाने की इच्छा रखते हैं।

URLClassLoader का विस्तार करने का सबसे आसान तरीका है और प्रत्येक संस्करण के लिए अलग-अलग वर्गपथ को हार्डकोड करने के लिए हैक करें। फिर आपको यह सुनिश्चित करने की ज़रूरत है कि शेष कोड जानता है कि HTTP क्लाइंट का कौन सा संस्करण उपयोग करना है (और इसे प्राप्त करने के लिए सही क्लासलोडर तक पहुंचता है)।

+0

यह वेबपैप के लिए कैसे काम करेगा जहां जारों को युद्धों के साथ भेजना होगा? –

+0

आप संदर्भित प्रत्येक पुस्तकालय के सभी संस्करणों को भेजते हैं, लेकिन उन्हें वेब-इंफ/lib के अलावा कहीं और डाल दें। आपका कस्टम क्लास लोडर "कहीं और" स्थान में दिखता है। यह युद्ध कंटेनर को सीधे संदर्भित करने से रोकता है। –

1

आपको v3 और v4 के लिए अलग-अलग वर्ग लोडर का उपयोग करना होगा। अपने एप्लिकेशन क्लासपाथ से परे फ़ोल्डर को अलग करने के लिए v3 और v4 जार रखें। प्रत्येक संस्करण को लोड करने के लिए URLClassLoadedr का उपयोग करें। यूआरएल जो आप क्लास लोडर्स में से प्रत्येक को पास करते हैं, में HTTP क्लाइंट के विशिष्ट संस्करण में यूआरएल होना चाहिए।

लेकिन क्या मैं आपको सलाह दे सकता हूं? पहले जांचें कि शुरू करने से पहले आपको इन सभी की ज़रूरत है। यह सही है कि संस्करण असंगत हो सकते हैं। लेकिन वे एक बड़ा मौका है कि वे हैं।

+1

मुझे लगता है कि आपका मतलब है "वे बड़े मौके हैं * नहीं *" मुझे पता है कि HTTP क्लाइंट v3 और V4 अच्छी तरह से एक साथ नहीं खेलते हैं। –

2

एक आसान लेकिन स्पष्ट समाधान आप HttpClient3 और HttpClient4 के लिए स्रोतों मिल होगा, और जैसे

org.apache.commons.httpclient3 HttpClient3 के लिए और org.apache.commons कुछ करने के लिए पैकेज के नाम refactor टक्कर से बचने के लिए HttpClient4 के लिए .httpclient4। फिर संकलन, पैकेज, किया।

अब दो कार्यान्वयन के बीच स्विच करना आसान है और वे क्लासलोडर में टकराव नहीं करते हैं।

+1

हालांकि यह एक जार के लिए काम करता है, यह हल होने से अधिक मुद्दों को बनाता है। उदाहरण के लिए आपको apache.commons.logging की आवश्यकता हो सकती है, और दोनों संस्करण कॉमन्स लॉगिंग के विभिन्न संस्करणों पर निर्भर होंगे (क्योंकि उन्हें अलग-अलग समय पर रिलीज़ किया गया था)। अब आप उपरोक्त तरीके से लॉगऑन लॉगिंग को दोबारा कर सकते हैं, लेकिन फिर आपको वापस जाना होगा और सही ढंग से संदर्भित करने के लिए रिकॉर्डेड http क्लाइंट्स में सभी स्रोत कोड को मैन्युअल रूप से संपादित करना होगा। जल्द ही ऐसा समाधान एक बड़ी गड़बड़ी बन जाता है। –

+1

क्या वे वास्तव में कॉमन्स-लॉगिंग के विभिन्न संस्करणों पर निर्भर करते हैं? नवीनतम को दोनों के साथ ठीक काम करना चाहिए, नहीं? – Thilo

+2

ध्यान दें कि कॉमन्स-लैंग लोग इस मार्ग पर जा रहे हैं। कॉमन्स लैंग 3 पैकेज नाम org.apache.commons.lang3 का उपयोग करेगा। यदि आपके पास असंगत एपीआई परिवर्तन होने जा रहे हैं, तो शायद एक नया पैकेज नाम सबसे बुरा विचार नहीं है। – Thilo