Идея избежать того, чтобы spring.handlers / spring.schemas перезаписывались при объединении нескольких зависимостей Spring в одном банке - PullRequest
35 голосов
/ 07 апреля 2011

Я получил ошибку Unable to locate NamespaceHandler when using context:annotation-config при запуске (java -jar) файла jar, собранного модулем maven-assembly-plugin и содержащего мой проект и все его зависимости.

Как другие люди правильно заметили на форуме.springsource.org thread (message # 7/8) проблема возникает из-за того, что файлы META-INF/spring.handlers и META-INF/spring.schemas, присутствующие в разных jar-файлах, перезаписываются, когда подключаемый модуль maven-assembly-plugin переупаковывает jar-файлы водин файл.

Глядя на содержимое двух файлов spring - *. jar, вы можете видеть, что файлы расположены в одном и том же положении относительно пути к классам

$ jar tf spring-oxm-3.0.3.RELEASE.jar
META-INF/spring.handlers
META-INF/spring.schemas
org/springframework/oxm/GenericMarshaller.class
...

$ jar tf spring-context-3.0.3.RELEASE.jar
META-INF/spring.handlers
META-INF/spring.schemas
org/springframework/context/ApplicationContext.class

Разве это не так?Можно ли поместить папку META-INF в конкретный пакет?Если да, то идея, которую я предлагаю (надеюсь, что это применимо), заключается в том, чтобы поместить файлы META-INF/spring.shemas и META-INF/spring.handlers в пакет, к которому они относятся.

$ jar tf spring-oxm-3.0.3.RELEASE.jar
org/springframework/oxm/META-INF/spring.schemas
org/springframework/oxm/META-INF/spring.handlers
org/springframework/oxm/GenericMarshaller.class
...

$ jar tf spring-context-3.0.3.RELEASE.jar
org/springframework/context/META-INF/spring.handlers
org/springframework/context/META-INF/spring.schemas
org/springframework/context/ApplicationContext.class

Таким образом, они не будут конфликтовать, когдаслил в одну банку.Что вы думаете об этом?

Ответы [ 2 ]

85 голосов
/ 21 апреля 2011

Мне удалось избавиться от ошибки, используя плагин шейдера вместо (глючного) плагина ассемблера:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>at.seresunit.lecturemanager_connector.App</mainClass>
                            </transformer>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.handlers</resource>
                            </transformer>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.schemas</resource>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>

Я думаю, что нашел решение на форумах springsource .. это было довольно многовремя с тех пор, как я его посмотрел .. не могу вспомнить автора.Слава ему в любом случае: р

ура

2 голосов
/ 06 июня 2014

с муравьем.

<!--define couple of properties to identify spring jar files-->
<property name="spring-beans-jar" value="spring-beans-4.0.5.RELEASE.jar"/>
<property name="spring-context-jar" value="spring-context-4.0.5.RELEASE.jar"/>

<!--other properties-->


<target name="dist" depends="compile" description="Prepare distribution">
    <!--dump spring-context into build classes (or some place else)-->
    <unjar src="${lib.dir}/${spring-context-jar}" dest="${build.classes.dir}"/>

    <!--dump spring-beans on top of it overwriting META-INF/spring.* files-->
    <unjar src="${lib.dir}/${spring-beans-jar}" dest="${build.classes.dir}"/>

    <!--get overwritten META-INF/spring.* files of spring-context to some other place-->
    <unjar src="${lib.dir}/${spring-context-jar}" dest="${build.tmp.dir}">
        <patternset>
            <include name="META-INF/spring.handlers"/>
            <include name="META-INF/spring.schemas"/>
            <include name="META-INF/spring.tooling"/>
        </patternset>
    </unjar>

    <!--skipped spring-beans/META-INF/spring.factories as its not present in spring-context-->
    <!--handled only spring-context and spring-beans as that's what I needed at this point-->

    <!--append content from spring-context/META-INF/spring.* files-->
    <concat destfile="${build.classes.dir}/META-INF/spring.handlers" append="true">
        <filelist dir="${build.tmp.dir}" files="META-INF/spring.handlers"/>
    </concat>
    <concat destfile="${build.classes.dir}/META-INF/spring.schemas" append="true">
        <filelist dir="${build.tmp.dir}" files="META-INF/spring.schemas"/>
    </concat>
    <concat destfile="${build.classes.dir}/META-INF/spring.tooling" append="true">
        <filelist dir="${build.tmp.dir}" files="META-INF/spring.tooling"/>
    </concat>

    <jar destfile="${build.dist.dir}/application.jar">
        <fileset dir="${build.classes.dir}"/>

        <!--include all .jar files except already extracted ones-->
        <zipgroupfileset dir="${lib.dir}" includes="*.jar"
                         excludes="${spring-beans-jar}, ${spring-context-jar}"/>
        <manifest>
            <attribute name="Main-Class" value="${main-class}"/>
        </manifest>
    </jar>
</target>
...