Ofisimde, Xerces kelimesinden bahsetmek, geliştiricilerin öldürücü öfkesini kışkırtmak için yeterli. SO hakkındaki diğer Xerces sorularına imleçli bir bakış, neredeyse tüm Maven kullanıcılarının bir noktada bu sorundan "etkilendiğini" gösteriyor. Ne yazık ki, sorunu anlamak Xerces'in tarihi hakkında biraz bilgi gerektiriyor ...
Tarih
Xerces, Java ekosisteminde en yaygın kullanılan XML ayrıştırıcısıdır. Java'da yazılmış hemen hemen her kütüphane veya çerçeve Xerces'i belirli bir kapasitede kullanır (doğrudan değilse, geçişli olarak).
Resmi ikili dosyalarda bulunan Xerces kavanozları bugüne kadar versiyonlanmamış. Örneğin, Xerces 2.11.0 uygulama kavanoz adlandırılır
xercesImpl.jar
değilxercesImpl-2.11.0.jar
.Xerces ekibi Maven'i kullanmaz , yani Maven Central'a resmi bir sürüm yüklemezler .
Xerces , tek bir kavanoz (
xerces.jar
) olarak serbest bırakıldı , ancak biri API (xml-apis.jar
) ve diğeri bu API'ların (xercesImpl.jar
) uygulamalarını içeren iki kavanoza bölündü . Birçok eski Maven POM hala bağımlı olduğunu beyan ediyorxerces.jar
. Geçmişte bir noktadaxmlParserAPIs.jar
, bazı eski POM'ların da bağlı olduğu Xerces olarak serbest bırakıldı .Kavanozlarını Maven depolarına dağıtanlar tarafından xml-apis ve xercesImpl kavanozlarına atanan sürümler genellikle farklıdır. Örneğin, her ikisi de Xerces 2.8.0'dan olsa da, xml-apis sürüm 1.3.03 ve xercesImpl sürüm 2.8.0 verilebilir. Bunun nedeni, insanların genellikle xml-apis kavanozunu uyguladığı özelliklerin sürümüyle etiketlemesidir. Burada bunun çok hoş ama eksik bir dökümü var .
Sorunları karmaşıklaştırmak için Xerces, JRE'de bulunan XML İşleme için Java API'sinin (JAXP) referans uygulamasında kullanılan XML ayrıştırıcısıdır. Uygulama sınıfları,
com.sun.*
bazı JRE'lerde bulunmayabileceklerinden, doğrudan erişilmesini tehlikeli hale getiren ad alanı altında yeniden paketlenir . Ancak, Xerces işlevlerinin tümüjava.*
vejavax.*
API'leri tarafından gösterilmez; örneğin, Xerces serileştirmesini gösteren herhangi bir API yoktur.Kafa karıştırıcı karmaşaya ek olarak, neredeyse tüm sunucu uygulamaları kapları (JBoss, Jetty, Glassfish, Tomcat, vb.), Xerces ile
/lib
klasörlerinden bir veya daha fazlasında gönderilir .
sorunlar
Çatışma çözümü
Yukarıdaki nedenlerden bazıları veya belki de tümü için, birçok kuruluş POM'larında özel Xerces yapıları yayınlar ve tüketir. Küçük bir uygulamanız varsa ve yalnızca Maven Central kullanıyorsanız bu gerçekten bir sorun değildir, ancak Artifactory veya Nexus'un birden çok havuzu (JBoss, Hibernate vb.)
Örneğin, A organizasyonu şu şekilde yayınlayabilir xml-apis
:
<groupId>org.apache.xerces</groupId>
<artifactId>xml-apis</artifactId>
<version>2.9.1</version>
Bu arada, B organizasyonu aşağıdakilerle aynı şeyi yayınlayabilir jar
:
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>
B'ler jar
A'dan daha düşük bir sürüm olmasına rağmen jar
, Maven bunların aynı eser olduğunu bilmiyor çünkü farklı s'lere sahipler
groupId
. Bu nedenle, çatışma çözümlemesi yapamaz ve her ikisi
jar
de çözümlenmiş bağımlılıklar olarak dahil edilir:
Classloader Cehennemi
Yukarıda belirtildiği gibi JRE, JAXP RI'de Xerces ile birlikte gönderilir. Tüm Xerces Maven bağımlılıklarını <exclusion>
s veya<provided>
, bağımlı olduğunuz üçüncü taraf kodu, kullandığınız JDK'nın JAXP'sinde sağlanan sürümle çalışabilir veya çalışmayabilir. Buna ek olarak, kontrol etmek için sunucu uygulaması kabınızda Xerces kavanozları gönderilir. Bu size birkaç seçenek sunar: Sunucu uygulaması sürümünü siler misiniz ve kapsayıcınızın JAXP sürümünde çalışmasını umuyor musunuz? Sunucu uygulaması sürümünden ayrılmak ve uygulama çerçevelerinizin sunucu uygulaması sürümünde çalışmasını ummak daha mı iyi? Yukarıda özetlenen çözülmemiş çatışmalardan biri veya ikisi ürününüze kaymayı başarırsa (büyük bir organizasyonda gerçekleşmesi kolay), kendinizi sınıf yükleyici cehenneminde bulursunuz, sınıf yükleyicinin hangi Xerces sürümünün çalışma zamanında seçilip seçilmediğini merak edersiniz. Windows ve Linux'ta aynı kavanozu seçer (muhtemelen değil).
Çözümler?
Biz gibi tüm Xerces Maven bağımlılıkları işaretleme denedim <provided>
veya olarak <exclusion>
, ancak bu eserler (pek çok diğer adları olan göz önüne alındığında (özellikle büyük takımla) uygulamak zordur xml-apis
, xerces
, xercesImpl
, xmlParserAPIs
, vb.) Ayrıca, üçüncü taraf kütüphanelerimiz / çerçevelerimiz JAXP sürümünde veya sunucu uygulaması kapsayıcısı tarafından sağlanan sürümde çalışmayabilir.
Maven ile bu sorunu en iyi nasıl çözebiliriz? Bağımlılıklarımız üzerinde bu kadar hassas bir kontrol yapmalı ve daha sonra kademeli sınıf yüklemesine güvenmeli miyiz? Tüm Xerces bağımlılıklarını global olarak dışlamanın ve tüm çerçevelerimizi / kütüphanelerimizi JAXP sürümünü kullanmaya zorlamanın bir yolu var mı?
GÜNCELLEME : Joshua Spiewak, Xerces derleme sürümlerinin Maven Central'a yüklenmesine izin veren XERCESJ-1454'e yamalı bir sürümünü yükledi . Bu soruna oy verin / izleyin / katkıda bulunun ve bu sorunu bir kez ve herkes için çözelim.