ecc
ecc

Reputation: 1510

Java project that uses library throws NoClassDefFoundError when using project that uses the same library

I'm creating a Java library for using in other Java projects. The projects use Repast Symphony and my library does so too (so i'm afraid this error is being caused by some conflict). Everything builds fine, but when I run a the Repast simulation, it throws java.lang.NoClassDefFoundError: repast/simphony/context/Context

I tried exporting my library as a jar, importing the project directly and adding the library to my project's classpath, to no avail. What can I be doing wrong?

This Context class is being used in both my library and my projects. The following is a snippet of it use in two classes:

// MyContextBulder.java
// This file is in my project
// This class is called by Repast first
import repast.simphony.context.Context;
import repast.simphony.dataLoader.ContextBuilder;
import mylibrary.core.DF;
import mylibrary.core.DF.MyContext;

public class MyContextBuilder implements ContextBuilder<Object> {

    @Override
    public Context<Object> build(Context<Object> context) {

        context.setId("test");
        DF.setContext((MyContext) context);

        // Create agent
        new MyAgent();
        // Add the agent to the Repast context.
        // context.add(t);

        return context;
    }
}
// DF.java
// This file is in my library

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.collections15.Predicate;

import repast.simphony.context.Context;
import repast.simphony.context.ContextListener;
import repast.simphony.space.projection.Projection;
import repast.simphony.util.collections.IndexedIterable;
import repast.simphony.valueLayer.ValueLayer;
import mylibrary.Agent;


/**
 * This static class provides the Directory Facilitator Service
 * and is used to send messages to agents
 * and to keep a directory of all agents in the application.
 * Agents use the static method send(ACLMessage) to send a message
 * to one or more agents. The ACLMessage object contains
 * the receiver agent and the sender (so the receiver can reply back).
 * 
 * This class needs to be setup initially before registering new agents.
 * To do that, simply call setContext(...);
 * @author joaolopes
 *
 */
public class DF {

    private static int lastAID = 0; // Just to help generate new identifiers
    private static HashMap<Integer, Agent> agents; // Contains all agents

    /**
     * The Repast context that contains all
     * scheduled Repast objects.
     */
    private static MyContext context = null;

    /**
     * Registers the agent in the directory and returns its
     * AID (freshly generated for it). If the agent is already
     * registered, returns its current AID.
     * @param agent The agent to be registered
     * @return The AID generated for the agent.
     */
    public static int registerAgent(Agent agent) {
        // If this agent is already in the hashMap,
        // just return its key.
        if (getAgents().containsValue(agent)) {
            return agent.getAID();
        }

        // Quick way to find a new ID for this agent
        // that is not in use at the moment.
        while (getAgents().containsKey(lastAID)) {
            lastAID++;
        }

        // The agent must know their own ID.
        agent.setAID(lastAID);
        agents.put(lastAID, agent);
        System.err.println(context.toString());
        context.add(agent);
        return lastAID;
    }

    public static void setContext(MyContext c){
        context = c;
    }
}

Editing to add relevant info from the comments: I don't import the repast JAR directly in my projects as I do in my library. Repast Symphony is installed in Eclipse as a plugin, so I created "Repast Projects" that include all Repast libraries. Therefore, I'm unable to remove the specific JAR that is causing the possible conflict of classes.

Upvotes: 1

Views: 706

Answers (2)

Sri777
Sri777

Reputation: 540

Exactly as you said. This error should be the conflict between the same classes in a jar. If you are using an IDE try to clean the build and rebuild again.

And also I would suggest you to use only one symphony library jar. Multiple class definitions always leads to ambiguity for the JVM class loader.

Try not to use symphony jar in the importing project since you already have it in your exported jar. After importing your lib, there should no errors.

Try this and let me know how it goes.

I suggest that you use an build tool. Something like Maven. Then maven with the right plugin will fix this problem for you. All you need to do, is to tell Maven that you need a particular jar file. Then a magic will occur, and you will have a well working jar-file to distribute

Upvotes: 2

Viggo
Viggo

Reputation: 91

java.lang.NoClassDefFoundError is thrown when the JVM tries to run the application. Typical cases is when you got one jar-file as "interface". Then you got other jar-file that implement that interface.

So what you need to do, is that have the Repast jar inside your jars classpath. So that your program can find the right class you want to use.

Upvotes: 1

Related Questions