Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
254 views
in Technique[技术] by (71.8m points)

executable jar - creating an uber jar with spring dependencies

I'm trying to create an application über jar, but running into an issue due to a dependency on the spring framework. In particular, the namespaces for the xml schemas are problematic. You get the infamous NamespaceHandler problem:

Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/c]

For creating (simple) uber jars, Creating a bundle jar with ant, but this doesn't work if you have spring dependencies due to the fact that the spring jars have files such as spring.handlers, spring.schemas and spring.tooling in the META-INF directories of many of their jar files. The namespace resolution is dependent, I believe, on these files.

The über jar seems to somehow contain all necessary files, but I'm guessing the runtime is seeing only one.

For example, a jar -tf of my uber jar shows (in part)

META-INF/spring.handlers
META-INF/spring.schemas
META-INF/spring.tooling
META-INF/license.txt
META-INF/notice.txt
META-INF/spring.factories
META-INF/spring.handlers
META-INF/spring.schemas
META-INF/spring.tooling
META-INF/license.txt
META-INF/notice.txt
META-INF/license.txt
META-INF/notice.txt
META-INF/spring.handlers
META-INF/spring.schemas
META-INF/spring.tooling
META-INF/license.txt
META-INF/notice.txt
META-INF/license.txt

So: question.. is there a way to create an uber-jar that has the spring jars bundled inside? Do I need to merge the META-INF files? Anyone have experience doing file merger with ant builds?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Well.. this was a pain.

<target name="make-bundle" depends="jar">
  <!-- retrieve the dependencies -->
  <ivy:retrieve conf="deploy" pattern="${dist.dir}/dependencies/[artifact].[ext]"/>

  <delete dir="${dist.dir}/dependencies/uber" failonerror="false" />
  <mkdir dir="${dist.dir}/dependencies/uber"/> 
  <!-- iterate over the dependencies -->
  <for param="file">
    <path>
      <fileset dir="${dist.dir}/dependencies"> 
        <include name="**/*.jar"/> 
      </fileset> 
    </path>
    <sequential> 
      <propertyregex override="yes" 
        property="jarname"  input="@{file}" 
        regexp=".*/([^/]*).jar" replace="1"/> 

      <!-- put the spring.* jars into special sub-directories -->
      <mkdir dir="${dist.dir}/dependencies/${jarname}"/> 
      <unzip dest="${dist.dir}/dependencies/${jarname}" src="@{file}">
        <patternset>
          <include name="**/META-INF/spring.*"/>
        </patternset>
      </unzip>
      <!-- put everything else in the 'uber' directory -->
      <unzip dest="${dist.dir}/dependencies/uber" src="@{file}">
        <patternset>
          <exclude name="**/META-INF/spring.*"/>
        </patternset>
        </unzip>
    </sequential>
  </for>

  <!-- build the concatenated spring.* files -->
  <mkdir dir="${dist.dir}/dependencies/META-INF"/> 
  <concat destfile="${dist.dir}/dependencies/META-INF/spring.handlers" fixlastline="true">
    <fileset dir="${dist.dir}/dependencies/" includes="*/*/spring.handlers"/>
  </concat>
  <concat destfile="${dist.dir}/dependencies/META-INF/spring.schemas" fixlastline="true">
    <fileset dir="${dist.dir}/dependencies/" includes="*/*/spring.schemas"/>
  </concat>
  <concat destfile="${dist.dir}/dependencies/META-INF/spring.tooling" fixlastline="true">
    <fileset dir="${dist.dir}/dependencies/" includes="*/*/spring.tooling"/>
  </concat>
  <concat destfile="${dist.dir}/dependencies/META-INF/spring.factories" fixlastline="true">
    <fileset dir="${dist.dir}/dependencies/" includes="*/*/spring.factories"/>
  </concat>

  <!-- build the uber jar! -->
  <delete file="${dist.dir}/myproject-with-dependencies.jar" failonerror="false"/>
  <jar destfile="${dist.dir}/myproject-with-dependencies.jar">
    <!-- all dependency files except spring.* -->
    <fileset dir="${dist.dir}/dependencies/uber"/> 
    <!-- the spring.* files -->
    <fileset dir="${dist.dir}/dependencies/" includes="META-INF/*"/>
    <!-- my project's classes & etc -->
    <zipgroupfileset dir="${dist.dir}" includes="myproject.jar" />
    <manifest>
      <attribute name="Main-Class" value="${main.class}"/>
    </manifest>  
  </jar>
</target>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...