facebook

LinkageError

  1. MyEclipse Archived
  2.  > 
  3. Application Servers and Deployment
Viewing 8 posts - 1 through 8 (of 8 total)
  • Author
    Posts
  • #273908 Reply

    Robert W
    Member

    Sorry if this is covered somewhere but I was unable to locate an answer. Please feel free to refer me to the relevant material if this is already covered.

    I have an enterprise application (ear) project that has an EJB module, a Web module and a Common module. The Common module contains Common classes that both the EJB and Web module use and pass back and forth to each other.

    For the web module I have “Smart Deployment” set. The classes in Common wind up deployed into the classes directory of the web module. I believe that this is what lets me run in debug mode and make changes to Common classes without restarting.

    For the EJB project I have “Merge into EJB Project output folder” turned on. The classes on “Common” wind up deployed into the EJB project as well. I think I also need this for the “no restart” reloading for the EJB module.

    The classes also wind up in a jar file at the root of the ear.

    I turned on verbose class loading and this is what happens.

    The class “User” is first loaded at the same time as the EJB module. It loaded as part of the verification of the EJB’s. The copy that loads is the one inside the EJB module.

    The Web application needs access to the “User” class and loads it. This loads the copy that deployed into the Web classes directory.

    The Web module tries to make a call to the EJB module using the “User” object. A java.lang.Linkage error “loader constraints violated when linking (class name)” is generated.

    Obviously the problem here is that there are two different copies of this class loaded by two different classloaders and when they try to pass an instance of this object around things get sticky.

    If I turn off the option that deploys the Common classes into the EJB and web modules then things run fine. The output from verbose class loading reports that the “User” class loads from the common.jar file sitting at the root of the ear and only loads once.

    Is there a solution to this? Obviously the ability to make changes to code and then have them reflected without doing a restart is a huge advantage and one of the main reasons that I am interested in bringing my whole development team on board with MyEclipse, I would hate to give this feature up.

    I am deploying to jboss 4.0.5 GA. I am running MyEclipse 6.0.0 M1.

    #273928 Reply

    Loyal Water
    Member

    You are adding the Common module as a reference to your EAR project ? Im a little confused as to how you are handling the Common Module. You should be adding the common module as a reference to the EAR project and then set your deployment policy for this dependent project by going to Windows > Pref > MyEclipse > Java Enterprise Project > EAR Project.

    #273967 Reply

    Robert W
    Member

    Thanks for the response.

    I went into Window/Preferences/MyEclipse/Java Enterprise Projects. I went through all the option panels in this section and set them back to their defaults. I went into the options for each individual project and set them to follow the workspace defaults. I went into the ear project and made sure that the Web, Common and EJB projects were set as project references.

    I selected “New Module Manifests” for the ear project. I deleted my deploy and re-deployed. There were no jar files deployed to the root of the ear. The common classes were deployed in the classes directory of the Web app but nowhere else. The EJB’s failed verification and would not deploy because the Common module contains exceptions and value objects that are passed back and forth between layers. Since the common classes appear in the method signatures it looks like the EJB verification process is trying to load them.

    Now I’m a little confused about where to go from here. If I tell the IDE to jar the dependent projects it will place them at the root of the ear and change the classpath of the EJB project to reference them. The EJB’s will verify OK as they are able to load the Common classes from the jar. Don’t I then go back to the same LinkageError problem I had before? When the Web project tries to load a Common class it will load a copy from it’s classes folder and I’ll get the LinkageError when I try to pass the same Common object loaded from two different places between the Web and EJB modules.

    I can also tell the Web module not to deploy the Common module’s classes into it’s classes folder and then all the common classes will load from the jar. No more linkage error, but then I have to reboot every time make a change to a Common class which will invalidate the coolest feature of MyEclipse, the ability to have a change reflected without waiting for a restart.

    I’m new to MyEclipse so perhaps I’m going about it in the wrong way. Let me know if I should be using a different approach.

    #273971 Reply

    Robert W
    Member

    I verified the problem, if you have the classes from the Common project deployed into both the EJB and Web projects the classes are being loaded by two different classloaders. The Common object in EJB is being loaded by org.jboss.mx.loading.UnifiedClassLoader and the classloader in the Web app is called WebappClassLoader with a parent classloader of java.net.FactoryURLClassLoader.

    The JVM does not look at these two classes as being the same, if you call getClass() on the objects and then equals it returns false.

    #274002 Reply

    Riyad Kalla
    Member

    riwright,
    I read through your initial post and for common classes that are shared by 1 or more modules, what you want to do is make that Java Project a reference of the EAR project. And you want to turn *off* the deployment rules for those types of projects from the EJB and Web Projects, so the only copy of the Common Java Project is to the EAR. The class loader heriarchy for Java EE apps will allow all modules to share/load that code.

    #274026 Reply

    Robert W
    Member

    So you are saying that I should not have the IDE deploy the Common classes into the EAR or Web modules, but have it jar them up and put that one jar on the classpath for the modules?

    That would certainly solve the classloader issue as there is only one copy of the class, but then don’t I lose hot deploy for these Common classes? Correct me if I’m wrong but it seems that what I would have to do when I change a common class is stop the server, select “manage deployments” redeploy and then restart. Correct?

    It’s cumbersome for me, we plan on having two Web modules that share a lot of functions and most of the code has been pulled out into the Common classes. It’s not just value objects.

    I don’t see a way to have common classes deployed into an exploded directory of their own, which would solve all of this I think. It looks like you have to either merge them into the module or jar them up. It seems like this would be a really good feature to have. I do the deploys that way, only third party stuff is deployed in jar form, everything else is exploded.

    Thanks for your help.

    #274029 Reply

    Robert W
    Member

    I think I found a solution for it.

    Have the Common classes deployed both into the EJB project and the Web Project. Don’t have the IDE jar them up and put them into the root of the ear.

    Go into this file:

    {server_root}\server\{server_name}\deploy\jbossweb-tomcat55.sar\META-INF\jboss-service.xml

    Modify the class loading behavior by changing the following lines to a value of “true”

    <!– Get the flag indicating if the normal Java2 parent first class
    loading model should be used over the servlet 2.3 web container first
    model.
    –>
    <attribute name=”Java2ClassLoadingCompliance”>true</attribute>
    <!– A flag indicating if the JBoss Loader should be used. This loader
    uses a unified class loader as the class loader rather than the tomcat
    specific class loader.
    The default is false to ensure that wars have isolated class loading
    for duplicate jars and jsp files.
    –>

    <attribute name=”UseJBossWebLoader”>true</attribute>

    The problem is caused by the fact that jboss is using a separate class loader for the web app. This config change forces jboss to use the same class loader for the entire application.

    This won’t work for all circumstances. If for instance you have one version of a class sitting in the EJB project and a different version sitting in the Web project then this will cause a conflict between the two classes, whichever one gets loaded first is the one that will be used by both. Sometimes you need that isolation. We don’t need the isolation.

    The dynamic reloading of the shared classes works fine. The classloader picks them up and since there is only one classloader to deal with it doesn’t matter whether the class file was picked up from the EJB or the Web project.

    We won’t use this method for a production deploy, for that we’ll go with fully exploded directories for all of our own classes and only one copy of each class.

    #274058 Reply

    Riyad Kalla
    Member

    Interesting find, thank you for posting it. I wasn’t aware of that JBoss config option.

Viewing 8 posts - 1 through 8 (of 8 total)
Reply To: LinkageError

You must be logged in to post in the forum log in