제 사무실에서 Xerces라는 단어 만 언급하면 개발자들의 격렬한 분노를 불러 일으킬 수 있습니다. SO에 대한 다른 Xerces 질문을 간략하게 살펴보면 거의 모든 Maven 사용자 가이 문제로 인해 어느 시점에서 "만져"있는 것으로 나타납니다. 불행히도 문제를 이해하려면 Xerces의 역사에 대한 약간의 지식이 필요합니다 ...
역사
Xerces는 Java 생태계에서 가장 널리 사용되는 XML 파서입니다. Java로 작성된 거의 모든 라이브러리 또는 프레임 워크는 일부 용량 (직접적으로는 아니지만 전 이적으로)에서 Xerces를 사용합니다.
공식 바이너리에 포함 된 Xerces jar 는 현재까지 버전이 없습니다. 예를 들어, Xerces 2.11.0 구현 jar의 이름은
xercesImpl.jar
notxercesImpl-2.11.0.jar
입니다.Xerces 팀 은 Maven을 사용하지 않으므로 Maven Central에 공식 릴리스를 업로드하지 않습니다 .
Xerces 는 단일 jar (
xerces.jar
) 로 출시 되었지만 하나는 API (xml-apis.jar
)를 포함하고 다른 하나는 해당 API (xercesImpl.jar
) 구현을 포함하는 두 개의 jar로 분할되었습니다 . 이전의 많은 Maven POM은 여전히에 대한 종속성을 선언합니다xerces.jar
. 과거 어느 시점에서 Xerces는로 출시되었는데xmlParserAPIs.jar
, 일부 이전 POM도 의존합니다.Jar를 Maven 리포지토리에 배포하는 사람들이 xml-apis 및 xercesImpl jar에 할당 한 버전은 종종 다릅니다. 예를 들어, xml-apis에는 버전 1.3.03이 제공되고 xercesImpl에는 버전 2.8.0이 제공 될 수 있습니다 (둘 다 Xerces 2.8.0의 것임). 사람들은 종종 xml-apis jar에 구현 된 사양의 버전을 태그하기 때문입니다. 여기에는 매우 훌륭하지만 불완전한 분류가 있습니다 .
문제를 복잡하게하기 위해 Xerces는 JRE에 포함 된 JAXP (Java API for XML Processing)의 참조 구현에 사용되는 XML 파서입니다. 구현 클래스는
com.sun.*
네임 스페이스 아래에 다시 패키지되므로 일부 JRE에서 사용하지 못할 수 있으므로 직접 액세스하는 것이 위험합니다. 그러나 모든 Xerces 기능이java.*
andjavax.*
API 를 통해 노출되는 것은 아닙니다 . 예를 들어 Xerces 직렬화를 노출하는 API가 없습니다.혼란스러운 혼란에 더해 거의 모든 서블릿 컨테이너 (JBoss, Jetty, Glassfish, Tomcat 등)는 하나 이상의
/lib
폴더에 Xerces와 함께 제공 됩니다.
문제
갈등 해결
위의 이유 중 일부 또는 전부에 대해 많은 조직에서 POM에 Xerces의 사용자 지정 빌드를 게시하고 사용합니다. 작은 응용 프로그램이 있고 Maven Central 만 사용하는 경우에는 실제로 문제가되지 않지만 Artifactory 또는 Nexus가 여러 저장소 (JBoss, Hibernate 등)를 프록시하는 엔터프라이즈 소프트웨어의 경우 빠르게 문제가됩니다.
예를 들어 조직 A는 다음 xml-apis
과 같이 게시 할 수 있습니다 .
<groupId>org.apache.xerces</groupId>
<artifactId>xml-apis</artifactId>
<version>2.9.1</version>
한편 조직 B는 다음과 같은 내용 jar
을 게시 할 수 있습니다 .
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>
B jar
는 A보다 낮은 버전이지만 jar
Maven은 서로 다른 인공물을 가지고 있기 때문에 동일한 인공물인지 알지 못합니다
groupId
. 따라서 충돌 해결을 수행 할 수 없으며 두 가지 모두
jar
해결 된 종속성으로 포함됩니다.
클래스 로더 지옥
위에서 언급했듯이 JRE는 JAXP RI에서 Xerces와 함께 제공됩니다. 모든 Xerces Maven 종속성을 <exclusion>
s 또는<provided>
에 의존하는 타사 코드는 사용중인 JDK의 JAXP에 제공된 버전에서 작동하거나 작동하지 않을 수 있습니다. 또한, 서블릿 컨테이너에 Xerces 항아리가 포함되어 있습니다. 서블릿 버전을 삭제하고 컨테이너가 JAXP 버전에서 실행되기를 희망합니까? 서블릿 버전을 유지하는 것이 더 좋으며, 애플리케이션 프레임 워크가 서블릿 버전에서 실행되기를 바랍니다. 위에서 설명한 해결되지 않은 충돌 중 하나 또는 두 개가 제품에 쉽게 들어가면 (대규모 조직에서 쉽게 발생), 클래스 로더가 런타임에 어떤 Xerces 버전을 선택하는지 궁금해하고 클래스 로더 지옥에 빠지게됩니다. Windows 및 Linux에서 동일한 jar을 선택합니다 (아마도).
솔루션?
우리는 모든 Xerces에 메이븐 종속성을 표시하려고했습니다 <provided>
또는으로 <exclusion>
,하지만이 유물은 (많은 별칭이 주어진 (특히 큰 팀) 시행하기가 어렵습니다 xml-apis
, xerces
, xercesImpl
, xmlParserAPIs
, 등). 또한 타사의 libs / frameworks는 JAXP 버전 또는 서블릿 컨테이너가 제공하는 버전에서 실행되지 않을 수 있습니다.
Maven으로이 문제를 어떻게 가장 잘 해결할 수 있습니까? 의존성에 대해 세밀한 제어를 수행 한 다음 계층화 된 클래스 로딩에 의존해야합니까? 모든 Xerces 종속성을 전체적으로 제외하고 모든 프레임 워크 / lib가 JAXP 버전을 사용하도록 강제 할 수있는 방법이 있습니까?
업데이트 : Joshua Spiewak는 Xerces 빌드 스크립트의 패치 버전을 XERCESJ-1454 에 업로드하여 Maven Central에 업로드 할 수 있습니다. 이 문제에 투표 / 감시 / 기고하고이 문제를 한 번에 해결하겠습니다.