9

I want to know how jetty handles when multiple dependency paths which can lead to same class.

For example,

Jetty comes pre-packaged with JSTL-1.2, but I added a dependency to load JSTL-1.2.4. At compile time, if I breakpoint test it downloading the source code in eclipse, it breaks at 1.2.4 version.

I want to know which version will be passed to generate byte code of a JSP, when there are two versions of classes, say some base class JstlCoreTlv in dependency (one pre-packaged, that is JSTL 1.2 with jetty and one passed from maven dependency 1.2.4)

In brief, I want to know How jetty is doing it. I want to know how jetty prioritizes pre-packaged vs dependencies added later. Even if the version is older than that of pre-packaged one, will it override and refer to added dependencies?

I couldn't get much in this context from jetty documentation. Help is much appreciated

  • What is the default behavior ? I didn't change anything related to class loading preference. – Karthik Narisetti Jan 05 '17 at 19:23
  • That doesn't tell anything about what happens when different versions of same class exists though – Karthik Narisetti Jan 05 '17 at 20:41
  • I am not sure I understand that. My actual problem is, I want to know which version will be passed to generate byte code of a JSP, when there are two versions of classes in dependency (one pre-packaged, that is JSTL 1.2 with jetty and one passed from maven dependency 1.2.4). – Karthik Narisetti Jan 05 '17 at 21:07
  • How can both of the classes used to generate byte code? It can be either. To be more specific, lets say a class JstlCoreTlv (1.2), also present in 1.2.4, and my JSP class will be generated on either, how can it be generated by both? – Karthik Narisetti Jan 05 '17 at 21:19
  • you meant to say, it might load different versions of JstlCoreTlv on different compilation times of a JSP ? – Karthik Narisetti Jan 05 '17 at 21:37
  • Thanks for all the help @user2004685. – Karthik Narisetti Jan 05 '17 at 21:48
  • I just edited with my question with one of comment to yours @user2004685 , which is more specific about the problem I am facing. I am pretty sure I am elaborative enough, but If you have any concerns please go ahead and edit the question – Karthik Narisetti Jan 05 '17 at 21:51
  • Sure. I will. Thanks! – Karthik Narisetti Jan 05 '17 at 22:00
  • Why don't you add `verbose:class` and see which class is loaded from which jar. `java -verbose:class -cp "a.jar:b.jar:." foo.bar.ClassWithMain` – ares Jan 12 '17 at 07:49
  • @ares: I want to know if with different classes of web app uses compile time with different packages picked by jetty at different times. Not the class that will be picked at one compile time. To make it clear, If I am loading say for example, x1.jsp and it picks the JSTLCoreTlv from 1.2.4 and I want to know, when I load x2.jsp it loads the same. – Karthik Narisetti Jan 12 '17 at 19:16
  • In the lifetime of a JVM one class is loaded only once. So if `JSTLCoreTlv` is loaded from `1.2.4` all the JSPs in the lieftime of that JVM will be compiled by `1.2.4`. Furthremore, if you launch the JVM in same configuration everytime, the classloading policy will not change and hence you get same version of class on every run. – ares Jan 13 '17 at 09:00

2 Answers2

4
  • Assuming you are not planning to change the jstl version of your Jetty installation.
  • Assuming you are only using jstl version 1.2.4 to compile your code, and you are not adding the jar in your war WEB-INF/lib.

If you compile and package with maven against 1.2.4 and deploy the packaged war on Jetty, Jetty will use 1.2 (which is the one on the server classpath and not 1.2.4 (because it is not available for Jetty). This could lead to problems.

The best way to avoid problems is to use exact the same version in your maven project dependencies as the version is used by the Jetty version you will deploy on.

Escay
  • 294
  • 1
  • 10
  • What if I include all my dependencies inside the WAR? What will happen in this case? – user2004685 Jan 13 '17 at 15:47
  • Jetty normally follows the Servlet specification for classloading. See http://www.eclipse.org/jetty/documentation/current/jetty-classloading.html, so in general it should prefer the jar in WEB-INF/lib. But this JSTL is quite core web server stuff, and would probably also need some other dependencies. I would not recommend going this way. If you wanna go this route you can read the Jetty documentation, it describes the used JSTL dependencies. Note: 1.2 versus 1.2.4 should not give problems, I assume the .4 has some bugfixes, but I would not expect API changes leading to classloading problems. – Escay Jan 13 '17 at 15:56
  • Thanks @Escay. I am adding it as a maven dependency. Yes, The reason I am upgrading is to incorporate one of the bug fixes in 1.2.4 JSTL. So the best way to go about it to update jetty which was pre-packaged with 1.2.4 or later? Is there no other way I could tell jetty to pick 1.2.4? – Karthik Narisetti Jan 13 '17 at 16:57
  • Also, referring to this comment, *Assuming you are not planning to change the jstl version of your Jetty installation* is there a way to do that with out upgrading jetty? – Karthik Narisetti Jan 13 '17 at 17:06
  • @KarthikNarisetti You can simply rename the new jar and replace it with the old one in order for Jetty to pick it up. You don't have to upgrade Jetty that way. – user2004685 Jan 13 '17 at 18:06
  • Not manually, but is there a way to tell Jetty to tell to pick the jar and bind it with **start.jar** before picking up? I am using **jetty-maven-plugin**, and personally I didn't find an easy way to do that – Karthik Narisetti Jan 13 '17 at 19:40
  • Also @Escay, Can you point me to some references which made you think that **If you compile and package with maven against 1.2.4 and deploy the packaged war on Jetty, Jetty will use 1.2 (which is the one on the server classpath and not 1.2.4 (because it is not available for Jetty). This could lead to problems**, this would happen? – Karthik Narisetti Jan 13 '17 at 19:50
  • @KarthikNarisetti As I told you before, you can have a look at the Jetty Classloading Priorities and change it appropriately as per your needs. – user2004685 Jan 13 '17 at 19:51
  • About the maven question: this is maven knowledge you need to have, search for 'dependencies default scope versus scope provided' and the consequences for your WEB-INF/lib contents. – Escay Jan 13 '17 at 23:01
  • I checked the latest Jetty version for you. Version 9.4.0.v20161208 contains apache-jstl, the implementation version is 1.2.5: org.apache.taglibs.taglibs-standard-impl-1.2.5, so if you use maven dependency org.apache.taglibs.taglibs-standard-spec-1.2.5.jar you should have no worries. http://search.maven.org/#artifactdetails%7Corg.apache.taglibs%7Ctaglibs-standard-spec%7C1.2.5%7Cbundle I think you should not depend on the implementation: http://search.maven.org/#artifactdetails%7Corg.apache.taglibs%7Ctaglibs-standard-impl%7C1.2.5%7Cbundle because it is already part of Jetty – Escay Jan 13 '17 at 23:24
4

The servlet specification require that:

  • Classes contained within WEB-INF/lib or WEB-INF/classes have priority over classes on the parent classloader (here is jetty's classloader).

From the document of jetty

A WEB-INF class can replace a Server class.

And the server class here is the jetty implementation of j2ee standard (code from jetty source code):

    /** Is the class a Server Class.
     * A Server class is a class that is part of the implementation of 
     * the server and is NIT visible to a webapplication. The web
     * application may provide it's own implementation of the class,
     * to be loaded from WEB-INF/lib or WEB-INF/classes 
     * @param clazz The fully qualified name of the class.
     * @return True if the class is a server class.
     */
    boolean isServerClass(Class<?> clazz);

You can also add control of server class by calling:

Tony
  • 5,972
  • 2
  • 39
  • 58