0

I think I donot understand well the conf feature of ivy even if I have read the tutorial. Think about I have two dependency;

  • guava.jar
  • foeu.jar

I need foeu.jar in compile time only but I need guava.jar not only in compile time but also in runtime. To implement these needs, I have wrote, in ivy.xml;

<configurations defaultconfmapping="runtime->compile">
    <conf   name="default" 
            visibility="public" />

    <conf   name="compile"      
            visibility="private"/>

    <conf   name="runtime"      
            extends="compile"   
            visibility="public"/>
</configurations>

and, dependency as;

<dependencies>          
    <dependency org="Google Guava"  name="guava-17.0"   rev="17.0"  
                conf="runtime->default"/>
    <dependency org="Foeu"  name="foeu" rev="5.5.1" 
                conf="compile->default"/>
</dependencies>

Really, something wrong with conf understanding of mine. What is the problem and what should I do?

UPDATE:

In build.xml, I am using it like;

ivy-initialization;

<target name="init-ivy" description="Initialize ivy requirements">
    <property   name="ivy.dep.file"     value="${script.directory}/ivy/ivy.xml" />

    <ivy:configure  file="${script.directory}/ivy/ivyconf.xml"/>

    <ivy:resolve/>
    <ivy:cachepath  pathid="ivy.compile.path"    conf="compile" />
    <ivy:cachepath  pathid="ivy.runtime.path" conf="runtime" />
</target>

compile;

<target name="compile"  depends="init-ivy"  description="Compiling Java source codes with external libraries">
    <javac  compiler="javac1.7"
            destdir="${class.directory}"
            source="1.7"
            target="1.7"
            failonerror="true"
            includeantruntime="false">

            <src    path="${source.directory}" />
            <classpath  refid="ivy.compile.path" />

    </javac>
</target>

jar

<target name="create-jar"   depends="compile"   description="Creating jar files">
    <jar    destfile="${build.directory}/jar/${ant.project.name}.jar"
        basedir="${class.directory}">

        <manifest>
            <attribute name="Main-Class" value="dataScience.management.Management"/>    
        </manifest>
    </jar>
</target>

run

<target name="runtime"  depends="create-jar"    description="Running Java based application">
        <java   jar="${jar.directory}/${ant.project.name}.jar"
                fork="yes"  
                maxmemory="400m">
                <jvmarg value="-ea"/>
                <classpath  refid="ivy.runtime.path" />
        </java>
</target>
Hevan
  • 157
  • 1
  • 15

1 Answers1

0

Configurations are a tricky concept to understand. My recommendation is to create one for each functional group of dependencies in your build.

The bit you're looking for is the "extends" attribute. It enables membership inheritance. For example:

<configurations>
    <conf name="compile" description="Libraries needed for compilation" />
    <conf name="runtime" extends="compile" description="Libraries needed at runtime"/>
</configurations>

In this way all compile dependencies are automatically part of the runtime configuration.

For more detailed example take a look at the following answer:

Update

This is not an ivy issue. Executable jars require main class and classpath to be present in the manifest file.

Build your jar file as follows:

  <target name="build" depends="compile">
    <ivy:retrieve pattern="${dist.dir}/lib/[artifact].[ext]" conf="runtime"/>

    <manifestclasspath property="jar.classpath" jarfile="${dist.jar}">
      <classpath>
        <fileset dir="${dist.dir}/lib" includes="*.jar"/>
      </classpath>
    </manifestclasspath>

    <jar destfile="${dist.jar}" basedir="${build.dir}/classes">
      <manifest>
        <attribute name="Main-Class" value="${dist.main.class}"/>
        <attribute name="Class-Path" value="${jar.classpath}"/>
      </manifest>
    </jar>
  </target>

The ivy retrieve task populates a local dir with the runtime dependencies. The manifestclasspath task creates a list of relative links to these files and finally the "Class-Path" entry is added to the manifest file. You will then be able to run the jar as follows:

<java jar="${dist.jar}" fork="yes" maxmemory="400m">
        <jvmarg value="-ea"/>
</java>

In conclusion there is basically two ways to run a jar. Specify the classpath and mainclass or create jar with the main class and classpath in the manifest.

Hope this solves your issue.

Community
  • 1
  • 1
Mark O'Connor
  • 76,015
  • 10
  • 139
  • 185
  • Even if I have changed as you said, the ant emits same problem, ` Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/base/Preconditions` while trying to run my project with guava. – Hevan Aug 27 '14 at 13:52
  • Sounds like there is a problem with either the classpath your using (not populated as with the configuration) or the local jar your using is not the version you think it is. Why? The class exists in the Maven Central jar copy. See: http://search.maven.org/#search|ga|1|g%3A%22com.google.guava%22%20AND%20a%3A%22guava%22%20AND%20v%3A%2217.0%22%20AND%20fc%3A%22com.google.common.base.Preconditions%22 Could you give more details on how you are using the configuration in your build.xml? – Mark O'Connor Aug 27 '14 at 14:02
  • Got it... Nothing to do with ivy. Your jar manifest is missing a "Class-Path" entry. I'll update my answer. – Mark O'Connor Aug 27 '14 at 14:15