Excluir todas as dependências transitivas de uma única dependência

221

No Maven2, para excluir uma única dependência transitiva, eu tenho que fazer algo assim:

<dependency>
  <groupId>sample.group</groupId>
  <artifactId>sample-artifactB</artifactId>
  <version>1</version>
   <exclusions>
     <exclusion>
       <groupId>sample.group</groupId>
       <artifactId>sample-artifactAB</artifactId>
     </exclusion>
   </exclusions>
</dependency>

O problema com essa abordagem é que eu tenho que fazer isso para todas as dependências transitivas contribuídas por sample-artifactB.

Existe uma maneira de usar algum tipo de curinga para excluir todas as dependências transitivas de uma só vez, em vez de uma por uma?

pbreault
fonte
Às vezes, é necessário usar uma versão mais recente da biblioteca, como o Spring 2.5.6, mas algumas outras dependências incluem a versão mais antiga, por exemplo, struts2-spring-plugin (2.1.6) inclui o Spring 2.5.3. Nesses cenários, há um requisito para exclusão ou substituição da versão.
Vinod Singh
1
Use Ivy. Só brincando.
Jake Toronto

Respostas:

54

Para o maven2, não há como fazer o que você descreve. Para o maven 3, existe. Se você estiver usando o maven 3, consulte outra resposta para esta pergunta

Para o maven 2, eu recomendo criar seu próprio pom personalizado para a dependência que tem suas <exclusões>. Para projetos que precisam usar essa dependência, configure a dependência para seu pom personalizado em vez do artefato típico. Embora isso não permita necessariamente excluir todas as dependências transitivas com uma única <exclusão>, permite que você precise gravar sua dependência apenas uma vez e todos os seus projetos não precisem manter listas de exclusão longas e desnecessárias.

baleia
fonte
12
Eu recomendaria não fazer seu próprio pom para solucionar exclusões. Isso torna sua compilação muito menos portátil e reduz a compreensão.
Brian Fox
1
No caso de você não olhar o passado anwser aceita: jira.codehaus.org/browse/MNG-3832
Jakub Bochenski
@JakubBochenski, a resposta que eu dei é específica para o maven 2, que é o que esta pergunta está marcada (no momento em que escrevi este comentário). Seu link é relevante apenas para o maven 3. Independentemente disso, editei minha resposta para vincular à resposta mais votada.
Whaley
306

O que funcionou para mim (pode ser um recurso mais recente do Maven) é apenas fazer curingas no elemento de exclusão.

Eu tenho um projeto de vários módulos que contém um módulo "app" que é referenciado em dois módulos empacotados em WAR. Um desses módulos empacotados com WAR realmente precisa apenas das classes de domínio (e ainda não as separei do módulo de aplicativo). Eu achei que isso funcionava:

<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>app</artifactId>
    <version>${project.version}</version>
    <exclusions>
        <exclusion>
            <groupId>*</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

O curinga em groupId e artifactId exclui todas as dependências que normalmente seriam propagadas para o módulo usando essa dependência.

enricopulatzo
fonte
9
O curinga * para o grupo e artifiact parece estar funcionando em Maven 3
nkr1pt
22
Não sei como você conseguiu encontrar esse trabalho, pois o Maven 3 adverte explicitamente sobre o uso do asterisco: [AVISO] 'dependencies.dependency.exclusions.exclusion.groupId' para <artifcat_id> com o valor "*" não corresponde a um padrão de identificação válido. [AVISO] É altamente recomendável corrigir esses problemas porque eles ameaçam a estabilidade da sua compilação. [AVISO] Por esse motivo, as versões futuras do Maven podem não suportar mais a criação de projetos malformados. Você gostaria de fornecer alguma evidência de que ele é suportado e pode ser usado? Caso contrário, eu consideraria seu comentário extremamente enganador.
25511
7
Funcionou lindamente com o Maven 3.0.4. Graças muito !
Evgeny Goldin
1
maven 3.0.4 -> não funcionou bem para mim. O jar resultante é muito diferente quando eu uso o asterix ou quando excluo explicitamente todas as dependências diretas. pode ter a ver com o fato de eu estar usando o maven-assembly-plugin para criar um frasco de gordura. neste caso, o sulotion sugerido não funciona!
gilad hoch
31
Este método é válido. Eles fixaram o aviso de que os outros estão relatando em maven 3.2.1: issues.apache.org/jira/browse/MNG-3832
Ryan
32

Uma coisa que achei útil:

Se você colocar a dependência com as exclusões na seção dependencyManagement do POM pai do seu projeto ou em um POM importável de gerenciamento de dependências, não será necessário repetir a exclusão (ou a versão).

Por exemplo, se o POM pai tiver:

<dependencyManagement>
    <dependencies>
    ...         
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
     ....
  </dependencies>
</dependencyManagement>

Em seguida, os módulos em seu projeto podem simplesmente declarar a dependência como:

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
        </dependency>

O POM pai especificará a versão e as exclusões. Eu uso essa técnica para quase todos os nossos projetos e elimina muita repetição.

Joshua Davis
fonte
23

Há três anos, eu recomendei o uso da versão 99 não existe, mas agora descobri uma maneira melhor, principalmente porque a versão 99 está offline:

No POM pai do seu projeto, use o maven-enforcer-plugin para falhar na compilação se a dependência indesejada se infiltrar na compilação. Isso pode ser feito usando a regra de dependências banidas do plug-in :

<plugin>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.0.1</version>
    <executions>
        <execution>
            <id>only-junit-dep-is-used</id>
            <goals>
                <goal>enforce</goal>
            </goals>
            <configuration>
                <rules>
                    <bannedDependencies>
                        <excludes>
                            <exclude>junit:junit</exclude>
                        </excludes>
                    </bannedDependencies>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

Então, quando isso alertar sobre uma dependência indesejada, exclua-a na <dependencyManagement>seção do POM pai :

<dependency>
    <groupId>org.springframework.batch</groupId>
    <artifactId>spring-batch-test</artifactId>
    <version>2.1.8.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Dessa forma, a dependência indesejada não será exibida acidentalmente (ao contrário de uma <exclusion>que é fácil de esquecer), ela não estará disponível mesmo durante o tempo de compilação (ao contrário do providedescopo), não haverá dependências falsas (ao contrário da versão 99) e será ' funcionará sem um repositório personalizado (diferente da versão 99). Essa abordagem funcionará mesmo com a versão do artefato, classificadores, escopo ou um groupId inteiro - consulte a documentação para obter detalhes.

Esko Luontola
fonte
Observe que pelo menos no Maven 3.1, o <configuration>é ignorado ao executar a meta na linha de comando e deve ser movido diretamente para cima <plugin>.
10134 David Harkness
Acabei de encontrar o que parece ser um bug desagradável do Maven - versão 3.5.2. Eu tenho um projeto com submódulos em que excluo uma dependência na <dependencyManagement>seção dos pais . A execução de um mvn dependency:treenesse projeto específico não terá a dependência excluída. Mas todos os projetos que importam essa dependência não honrarão o <exclusions>pom do outro pai do projeto - o excluído entrará em cena !!! Eu tive que mudar <exclusions>para cada módulo pom diretamente.
cbaldan 25/06
11

Eu uso a seguinte solução alternativa: em vez de tentar excluir o artefato em todas as dependências apropriadas, desenho a dependência como "fornecida" no nível superior. Por exemplo, para evitar o envio de xml-apis "seja qual for a versão":

    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>[1.0,]</version>
        <scope>provided</scope>
    </dependency>
Michael Zilbermann
fonte
9

Atualmente, não há como excluir mais de uma dependência transitiva por vez, mas há uma solicitação de recurso para isso no site do Maven JIRA:

https://issues.apache.org/jira/browse/MNG-2315

Peter
fonte
6

Existe uma solução alternativa para isso, se você definir o escopo de uma dependência como tempo de execução , as dependências transitivas serão excluídas. Embora esteja ciente, isso significa que você precisará adicionar processamento adicional se desejar compactar a dependência do tempo de execução.

Para incluir a dependência de tempo de execução em qualquer pacote, é possível usar a meta de cópia do plug-in maven-dependency-plugin para um artefato específico .

Vendedor rico
fonte
1
Isso me ajudou a solucionar problemas com o compilador Android Dalvik, que não conseguia lidar com algumas inclusões transitivas de dois níveis - mas eu precisava usar em <scope>provided</scope>vez disso <scope>runtime</scope>.
Garret Wilson
6

se você precisar excluir todas as dependências transitivas de um artefato de dependência que você incluirá em um assembly, poderá especificar isso no descritor do assembly-plugin:

<assembly>
    <id>myApp</id>
    <formats>
        <format>zip</format>
    </formats>
    <dependencySets>
        <dependencySet>
            <useTransitiveDependencies>false</useTransitiveDependencies>
            <includes><include>*:struts2-spring-plugin:jar:2.1.6</include></includes>
        </dependencySet>
    </dependencySets>
</assembly>
Superole
fonte
3

Se você desenvolver no Eclipse, poderá, no gráfico de dependência do Editor POM (guias avançadas ativadas), procurar a dependência que deseja excluir do seu projeto e, em seguida:

clique com o botão direito do mouse -> "Excluir artefato Maven ..." e o Eclipse fará a exclusão para você sem a necessidade de descobrir em qual dependência a biblioteca está vinculada.

Tib
fonte
Observe que isso só funciona se você estiver usando o plug
#
2

Qual é o seu motivo para excluir todas as dependências transitivas?

Se houver um artefato específico (como log comum) que você precise excluir de todas as dependências, a abordagem Versão 99 Não Existe pode ajudar.


Atualização 2012: não use essa abordagem. Use o maven-enforcer-plugin e exclusões . A versão 99 produz dependências falsas e o repositório da versão 99 está offline (existem espelhos semelhantes, mas você também não pode confiar neles para ficar online para sempre; é melhor usar apenas o Maven Central).

Esko Luontola
fonte
1

Em uma questão semelhante, tive a dependência desejada declarada com o escopo fornecido. Com essa abordagem, as dependências transitivas são buscadas, mas NÃO são incluídas na fase do pacote, que é o que você deseja. Também gosto desta solução em termos de manutenção, porque não há pom, nem pom personalizado como na solução da whaley, necessária para manter; você só precisa fornecer a dependência específica no contêiner e ser feito

nkr1pt
fonte
-2

Use o último maven no seu caminho de classe. Ele removerá os artefatos duplicados e manterá o último artefato.

Samraj
fonte