มีการยกเว้นสิ่งประดิษฐ์ที่สืบทอดมาจาก POM หลักหรือไม่?


120

อาร์ติแฟกต์จากการอ้างอิงสามารถแยกออกได้โดยการประกาศ<exclusions>องค์ประกอบภายใน<dependency>แต่ในกรณีนี้จำเป็นต้องแยกอาร์ติแฟกต์ที่สืบทอดมาจากโปรเจ็กต์หลัก ข้อความที่ตัดตอนมาของ POM ภายใต้การอภิปรายมีดังนี้:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>jruby</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
    </parent>

    <dependencies>      
        <dependency>
            <groupId>com.liferay.portal</groupId>
            <artifactId>ALL-DEPS</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>

baseสิ่งประดิษฐ์ขึ้นอยู่กับ javax.mail:mail-1.4.jarและALL-DEPSขึ้นอยู่กับเวอร์ชันอื่นของไลบรารีเดียวกัน เนื่องจากความจริงที่ว่าmail.jarจากALL-DEPSที่มีอยู่กับสภาพแวดล้อมในการดำเนินการแม้จะไม่ได้ส่งออก collides กับที่มีอยู่ในผู้ปกครองซึ่งเป็นขอบเขตเป็นmail.jarcompile

วิธีแก้ปัญหาคือการกำจัด mail.jar ออกจาก POM หลัก แต่โปรเจ็กต์ส่วนใหญ่ที่สืบทอดฐานจำเป็นต้องใช้ (เช่นเดียวกับการพึ่งพา transtive สำหรับ log4j) ดังนั้นสิ่งที่ฉันต้องการจะทำคือการแยกไลบรารีของผู้ปกครองออกจากโปรเจ็กต์ลูกเนื่องจากสามารถทำได้หากbaseเป็นการพึ่งพาไม่ใช่ผู้ปกครอง:

...
    <dependency>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
        <type>pom<type>
        <exclusions>
          <exclusion>
             <groupId>javax.mail</groupId>
             <artifactId>mail</artifactId>
          </exclusion>
        </exclusions>
    </dependency>
...

คำตอบ:


49

แนวคิดบางประการ:

  1. บางทีคุณอาจไม่ได้รับมรดกจากผู้ปกครองในกรณีนั้น (และประกาศการพึ่งพาbaseด้วยการยกเว้น) ไม่สะดวกหากคุณมีสิ่งของมากมายในแม่ปอม

  2. สิ่งที่ต้องทดสอบอีกประการหนึ่งคือการประกาศmailสิ่งประดิษฐ์ด้วยเวอร์ชันที่ต้องการโดยALL-DEPSภายใต้dependencyManagementpom หลักเพื่อบังคับให้เกิดการลู่เข้า (แม้ว่าฉันไม่แน่ใจว่าสิ่งนี้จะแก้ปัญหาการกำหนดขอบเขตได้)

<dependencyManagement>
  <dependencies>
    <dependency>    
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
      <version>???</version><!-- put the "right" version here -->
    </dependency>
  </dependencies>
</dependencyManagement>
  1. หรือคุณสามารถยกเว้นการmailอ้างอิงจาก log4j หากคุณไม่ได้ใช้คุณสมบัติที่อาศัยอยู่ (และนี่คือสิ่งที่ฉันจะทำ):
<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.2.15</version>
  <scope>provided</scope>
  <exclusions>
    <exclusion>
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
    </exclusion>
    <exclusion>
      <groupId>javax.jms</groupId>
      <artifactId>jms</artifactId>
    </exclusion>
    <exclusion>
      <groupId>com.sun.jdmk</groupId>
      <artifactId>jmxtools</artifactId>
    </exclusion>
    <exclusion>
      <groupId>com.sun.jmx</groupId>
      <artifactId>jmxri</artifactId>
    </exclusion>
  </exclusions>
</dependency>
  1. หรือคุณสามารถเปลี่ยนกลับไปใช้ log4j เวอร์ชัน 1.2.14 แทนเวอร์ชัน 1.2.15 นอกรีตได้ (ทำไมพวกเขาไม่ทำเครื่องหมายการอ้างอิงข้างต้นเป็นทางเลือก !)

ขอบคุณสำหรับการตอบกลับของคุณ. มีข้อมูลที่เป็นประโยชน์มากมาย เกี่ยวกับ 1) ดังที่คุณสังเกตเห็นจะไม่เหมาะสมเนื่องจากแม่ pom ไม่เพียง แต่มีการอ้างอิงเท่านั้นที่จะได้รับการแก้ไขตามสกรรมกริยาหากฐานถูกทำเครื่องหมายว่าเป็นการพึ่งพา แต่ยังรวมถึงการรายงานทั่วไปการจัดการแหล่งที่มาและสิ่งอื่น ๆ ที่นำมาใช้ซ้ำในทุกโครงการใน บริษัท เกี่ยวกับ 2) ฉันลองแล้ว แต่ยังระบุขอบเขตของอาร์ติแฟกต์ตามที่ให้ไว้และใช้งานได้ :) ตอนแรกฉันคิดว่าเนื่องจากการคอมไพล์มีความสำคัญมากกว่าที่ให้ไว้มันจะไม่ทำงาน แต่โชคดีที่ฉันคิดผิด (POM ลูกจะแทนที่การกำหนดค่าของผู้ปกครอง)
มิเกล

29

คุณสามารถจัดกลุ่มการอ้างอิงของคุณภายในโครงการอื่นด้วยบรรจุภัณฑ์pomตามที่อธิบายโดย Sonatypes Best Practices :

<project>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>base-dependencies</artifactId>
    <groupId>es.uniovi.innova</groupId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <dependencies>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>
    </dependencies>
</project>

และอ้างอิงจากพ่อแม่ของคุณ (ดูการพึ่งพา<type>pom</type>):

<project>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>base</artifactId>
    <groupId>es.uniovi.innova</groupId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <dependencies>
        <dependency>
            <artifactId>base-dependencies</artifactId>
            <groupId>es.uniovi.innova</groupId>
            <version>1.0.0</version>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>

โปรเจ็กต์ลูกของคุณจะสืบทอดพาเรนต์ - ปอมเหมือนเดิม แต่ตอนนี้การพึ่งพาอีเมลสามารถยกเว้นในโปรเจ็กต์ลูกภายในdependencyManagementบล็อก:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>jruby</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <artifactId>base-dependencies</artifactId>
                <groupId>es.uniovi.innova</groupId>
                <version>1.0.0</version>
                <exclusions>
                    <exclusion>
                        <groupId>javax.mail</groupId>
                        <artifactId>mail</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

4
+1 สำหรับสิ่งนี้แม้ว่า pom ลูกควรใช้ส่วน <dependencies> มากกว่า <dependencyManagement> เนื่องจากส่วนหลังมีไว้สำหรับจัดการเวอร์ชันของการอ้างอิงจากภายใน pom แม่
Matthew Wise

1
สิ่งนี้เรียกอีกอย่างว่า BOM หรือที่เรียกว่ารายการวัสดุ :-)
Pim Hazebroek

สิ่งนี้ใช้ได้เฉพาะกับการอ้างอิงสกรรมกริยาหรือไม่ ปอมแม่ของฉันมี log4j และมันทำให้การล็อกแบ็คของปอมทำงานไม่ถูกต้อง
Sridhar Sarnobat

10

อย่าใช้แม่ปอม

สิ่งนี้อาจฟังดูรุนแรง แต่ในทำนองเดียวกัน "นรกมรดก" เป็นเหตุผลที่บางคนหันหลังให้กับ Object Oriented Programming (หรือชอบการจัดองค์ประกอบมากกว่าการสืบทอด ) ลบ<parent>บล็อกที่มีปัญหาออกแล้วคัดลอกและวางสิ่งที่<dependencies>คุณต้องการ (หากทีมของคุณให้ เสรีภาพนี้)

สมมติฐานที่ว่าการแยกลูกปอมเป็นพ่อแม่และลูกเพื่อ "ใช้ซ้ำ" และ "หลีกเลี่ยงการใช้ซ้ำ" ควรละเว้นและคุณควรตอบสนองความต้องการเฉพาะหน้าก่อน (การรักษาจะแย่ที่สุดกว่าโรค) นอกจากนี้ความซ้ำซ้อนยังมีข้อดีคือความเป็นอิสระของการเปลี่ยนแปลงภายนอก (เช่นความเสถียร)

สิ่งนี้ง่ายกว่าที่คิดหากคุณสร้าง pom ที่มีประสิทธิภาพ (eclipse จัดเตรียมไว้ให้ แต่คุณสามารถสร้างได้จากบรรทัดคำสั่งด้วยmvn help:effective)

ตัวอย่าง

ฉันต้องการใช้logbackเป็นการรวม slf4j ของฉัน แต่ pom แม่ของฉันมีการlog4jพึ่งพา ฉันไม่ต้องการไปและต้องผลักดันการพึ่งพา log4j ของเด็กคนอื่นลงในpom.xmlไฟล์ของตัวเองเพื่อให้ของฉันไม่มีสิ่งกีดขวาง


1
บันทึกสิ่งนี้ (และขั้นตอนที่คุณปฏิบัติตาม) อย่างระมัดระวังเนื่องจากผู้ดูแลในอนาคตจำเป็นต้องทำซ้ำหากจำเป็นต้องใช้เวอร์ชันที่อัปเดตของแม่ปอม
Thorbjørn Ravn Andersen

แน่นอนคุณหมายถึงอย่าใช้การอ้างอิงในพ่อแม่? แม่ปอมยังคงมีประโยชน์อย่างมากในการจัดการเวอร์ชันอ้างอิงและปลั๊กอินทั่วไป เพียงแค่ใช้มันเพื่อฉีดการพึ่งพาสามารถย้อนกลับได้ - เราใช้มันสำหรับการพึ่งพาที่ต้องมีเท่านั้น (เช่นชุดสปริงบูตที่จำเป็นสำหรับผู้ปกครองสำหรับไมโครเซอร์วิส)
Amit Goldstein

ไม่ฉันไม่ได้บอกว่าใช้พ่อแม่น้ำหนักเบา คนอื่น ๆ ในทีมของคุณไม่อนุญาตให้คุณตัดแต่งปอมแม่เพราะแอปอื่น ๆ ขึ้นอยู่กับขยะในแม่ปอมที่คุณไม่ต้องการ
Sridhar Sarnobat

8

นิยามการพึ่งพา (ในลูกปอม) ใหม่ด้วยscopeระบบชี้ไปที่โถเปล่า:

<dependency>
    <groupId>dependency.coming</groupId>
    <artifactId>from.parent</artifactId>
    <version>0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/empty.jar</systemPath>
</dependency>

jar สามารถมีไฟล์ว่างได้เพียงไฟล์เดียว:

touch empty.txt
jar cvf empty.txt

ขอขอบคุณสำหรับคำตอบของคุณบน Windows 10 ผมต้องวิ่งnotepad empty.classแล้วjar cvf empty.jar empty.classเพื่อสร้างขวดเปล่า
Rov

1
ดูเหมือนการปฏิบัติที่ไม่ดี
Piotr Żak

6

คุณได้ลองประกาศเวอร์ชันของ mail.jar ที่คุณต้องการอย่างชัดเจนแล้วหรือยัง การแก้ปัญหาการพึ่งพาของ Maven ควรใช้สิ่งนี้สำหรับการแก้ไขการอ้างอิงกับเวอร์ชันอื่น ๆ ทั้งหมด

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>jruby</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
    </parent>
    <dependencies>          
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>VERSION-#</version>
            <scope>provided</scope>
        </dependency> 
        <dependency>
            <groupId>com.liferay.portal</groupId>
            <artifactId>ALL-DEPS</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>

1
แนวทางของคุณเนื่องจากวิธีแก้ปัญหาของ Pascal # 2 ก็ใช้ได้เช่นกันในความเป็นจริงคุณต้องพิจารณาด้วยว่าควรประกาศการพึ่งพาอีเมลตามที่ระบุไว้ ขอบคุณ.
มิเกล

ขอบเขตที่ระบุไม่ได้ผลสำหรับฉัน ฉันใช้การทดสอบขอบเขตโปรดตรวจสอบคำตอบของฉัน stackoverflow.com/a/55970293/4587961
Yan Khonski

3

ทางออกที่ดีที่สุดคือการสร้างการอ้างอิงที่คุณไม่ต้องการสืบทอดอกรรมกริยาเสมอไป

คุณสามารถทำได้โดยการทำเครื่องหมายไว้ในแม่ปอมพร้อมขอบเขตที่ให้มา

หากคุณยังคงต้องการให้พาเรนต์จัดการเวอร์ชันของเดปเหล่านี้คุณสามารถใช้<dependencyManagement>แท็กเพื่อตั้งค่าเวอร์ชันที่คุณต้องการโดยไม่ต้องสืบทอดอย่างชัดเจนหรือส่งต่อการสืบทอดนั้นไปยังเด็ก ๆ


1

เมื่อคุณเรียกใช้แพ็กเกจ แต่ไม่ต้องการการอ้างอิงบางอย่างคุณสามารถทำสิ่งนี้ได้ (ในกรณีนี้ฉันไม่ต้องการเพิ่ม log4j เก่าเพราะฉันต้องการใช้อันใหม่กว่า):

<dependency>
  <groupId>package</groupId>
  <artifactId>package-pk</artifactId>
  <version>${package-pk.version}</version>

  <exclusions>
    <exclusion>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
    </exclusion>
  </exclusions>
</dependency>

<!-- LOG4J -->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.5</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api</artifactId>
  <version>2.5</version>
</dependency>

สิ่งนี้ใช้ได้กับฉัน ... แต่ฉันค่อนข้างใหม่กับ java / maven ดังนั้นจึงอาจไม่เหมาะสม


ยินดีต้อนรับสู่ Stack Overflow และอย่าปล่อยให้คนหยาบคายที่ฉันถามคำถามตลอดเวลาทำให้คุณไม่สามารถโพสต์ได้
Sridhar Sarnobat

1

ฉันต้องทำเรื่องสกปรกนี้จริงๆ ... นี่คือวิธี

testผมนิยามใหม่ของการพึ่งพาผู้ที่มีขอบเขต ขอบเขตprovidedไม่ได้ผลสำหรับฉัน

เราใช้ปลั๊กอิน Spring Boot เพื่อสร้างโถไขมัน เรามีโมดูลทั่วไปซึ่งกำหนดไลบรารีทั่วไปเช่น Springfox swagger-2 ฉันซุปเปอร์บริการจะต้องมีผู้ปกครองร่วมกัน (มันไม่ต้องการที่จะทำเช่นนั้น แต่ บริษัท กฎแรง!)

พ่อแม่หรือคอมมอนของฉันก็มีปอม

<dependencyManagement>

    <!- I do not need Springfox in one child but in others ->

    <dependencies>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-bean-validators</artifactId>
            <version>${swagger.version}</version>
        </dependency>

       <!- All services need them ->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${apache.poi.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

และปอมบริการสุดยอดของฉัน

<name>super-service</name>
<parent>
    <groupId>com.company</groupId>
    <artifactId>common</artifactId>
    <version>1</version>
</parent>

<dependencies>

    <!- I don't need them ->

    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-bean-validators</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-core</artifactId>
        <version>2.8.0</version>
        <scope>test</scope>
    </dependency>

    <!- Required dependencies ->

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
     <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
    </dependency>
</dependencies>

นี่คือขนาดของสิ่งประดิษฐ์ไขมันขั้นสุดท้าย

82.3 MB (86,351,753 bytes) - redefined dependency with scope test
86.1 MB (90,335,466 bytes) - redefined dependency with scope provided
86.1 MB (90,335,489 bytes) - without exclusion

คำตอบนี้ควรค่าแก่การกล่าวถึง - ฉันอยากทำ แต่ฉันขี้เกียจ ... https://stackoverflow.com/a/48103554/4587961


0

เราสามารถเพิ่ม parent pom เป็นการอ้างอิงกับ type pom และทำการยกเว้นสิ่งนั้น เพราะยังไงก็ตามพ่อแม่ก็ดาวน์โหลดปอม สิ่งนี้ได้ผลสำหรับฉัน

<dependency>
  <groupId>com.abc.boot</groupId>
  <artifactId>abc-boot-starter-parent</artifactId>
  <version>2.1.5.RELEASE</version>
  <type>pom</type>
  <exclusions>
    <exclusion>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
    </exclusion>
  </exclusions>   
</dependency>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.