JNLP classpath precedence 1.4.2 vs 1.6
Hello,
I have a JNLP file that gets it's classpath defined through the order in which jar files are place inside the JNLP. This works fine for JRE 1.4.2 but now with
1.6 it appears the precedence order has changed.
Is this common practice to define the classpath through the jar file orderings in the JNLP?
Does anyone have a similar problem or can help shed some light on the problem?
Thanks
Burt
[443 byte] By [
Burta] at [2007-11-27 1:21:55]

# 1
The order in which resources are added to a classpathshould not matter, the resource will either be found or not.I suspect there is a more fundamental problem.Try validating the JNLP(s), then post them here.Message was edited by: AndrewThompson64
# 2
Sorry I forgot to include some key information.
Two of the jar files have the *same* class file, but we want the class file in first jar to take precedence over the second jar file.
To the best of our knowledge, this works for Java 1.4.2 and webstart, but does not seem to work for Java 1.6.
So for example
Say LookupCheck.class in the main original.jar file is found to have a bug. As an emergency release, we create a new LookupCheck.class with the corrected code and place this class into a custom.jar file. In the jnlp file, we then list the custom.jar before the original.jar in the list of libraries to download. We would expect the code to run the software in the custom.jar file and not the code in the original.jar for the functionality in LookupCheck.class.
I aplogize for leaving the meat of the problem out and thank you kindly for any response.
I am sure this is probably not the best way to fix the problem . But any information you could contribute would be appreciated.
Burt
Burta at 2007-7-12 0:00:05 >

# 3
...
> I am sure this is probably not the best way to fix the problem .
You have 'hit the nail on the head' with that comment.
The Java Control Panel for Java 6 has a tab
General, with section Temporary Internet Files,
and button Settings. Click that and you get to
Temporary Files Settings, which has an area
Disk Space, which allows the end user (or their
SysAdmin) to specify the compression level for
Jar's, currently mine is set at 'None', though it
ranges through to 'High'.
In a PC in which the setting is High, I expect the
Jar files would be stored as Jars, but at 'None'
I expect it is storing loose class files.
Assuming compression is 'None', it might be that
the second class is overwriting the first.
Since all this depends on settings that the end user
can change, it is pointless to try and second guess
what behaviour can be expected.
The application needs to be redesigned to get
around this fragile use of class loading.
# 4
Before JWS 1.6, when i want to "patch" my web start application, i just export changes in a new jar and append it at the top of the jnlp file. This way, user just have to download only classes that have been updated. When a jar weights 1.3Mo, the download can be an issue if the user is on a dial connection (yes, there are still users using dial connection). With this tricks, my users just have to download a 10ko jar file for minor changes.
When i release a new stable major version, i repack my main jar and users download it. But it's a major version and users can accept to spend several minutes to download the patch. But this is not acceptable for a patch on 3 java classes.
With java 1.6 and new java web start, it seems no more possible to use such tricks. Is there's any way to have such feature ?
BTW, i don't understand why developpers of JWS have changed the way to store jar. The old way was clear and when download issue occurs, it was simple to check if all is ok on client side. Now it's impossible.
# 5
> Before JWS 1.6, when i want to "patch" my web start
> application, i just export changes in a new jar and
> append it at the top of the jnlp file. This way, user
> just have to download only classes that have been
> updated. When a jar weights 1.3Mo,
Break the jar up into separate packages.
That solves the problem.
> With java 1.6 and new java web start, it seems no
> more possible to use such tricks.
AKA 'hacks' - never rely on hacks.
> BTW, i don't understand why developpers of JWS have
> changed the way to store jar.
Read my previous reply re 'user control'.
Note that code that needs ot know where it
is installed is generally very broken, in normal
apps., let alone web start based applications.
Message was edited by:
AndrewThompson64
# 6
A common issue is that multiple jars may include a log4j.properties. I'd like my resource jar to get used first. I just as soon not alter other peoples jars.
# 7
I would suggest calling your logging properties
file something different again, such as..
com.my.log4j.properties
..then (a little Googling later), take this option..
"log4j.configuration=app_config.properties: First call to Category.getRoot() or Category.getInstance(...) method makes Log4j go through an initialization process. (You can watch that happening by setting "log4j.debug=true".) During this process, Log4j looks in the application's classpath for a "log4j.properties" file or the properties file you specify via the this property key. However, you need to set this as a system property, for example by running your program with java -Dlog4j.configuration=app_config.properties .... This is because, if you set it in the configuration file, it is too late. Log4j would have already started to read the log4j.properties file by default, if available! "
..as mentioned here..
http://www.vipan.com/htdocs/log4jhelp.html
# 8
Webstart should support classpath ordering just as if the user launched the application from the console. There are legitimate reasons for needing to order the jars and, for our needs at least, it has generally been due to 3rd party jar files that we have no control over.
A recent example is our migration from Oracle 9 to Oracle 10 and severe performance decreases that are being noticed. Over 600% slower. A likely suspect is the jdbc drivers that are incorporated within weblogic 6.1's weblogic.jar file itself. To update the drivers it is required to place sun's new jar jdbc files with updated drivers first in the classpath. Simple to do for anything but our jnlp deployments.
The other issue is the "user control" feature for 1.6 that someone chose to default compression to "None". The default should have been HIGH to be compatible with previous jnlp releases. With over 500 non-technical users it is impractical for us to rely on them to set the control correctly. Even then a large majority of our users have extremely limited access to features on their pc's. Assuming this option can't be remotely pushed to every client machine system support will need to go to every user machine and configure this option.
Due to this jnlp classpath "flaw" (for lack of a better term) we either need to roll everyone back to a version of jnlp that supports java's classpath ordering or merge the weblogic.jar file with oracles updated jdbc drivers.
# 9
I strongly agree with rkenny's comment.
We are in the same situation, we need to be able to patch the application without recreating the general release jar files.
We also have the same issues with large numbers of users.
Webstart is supposed to help make the version control as transparent as possible, this makes the version control harder to manage.
Turning compression to high did not resolved the issue, they are saved as jar files, even on none.
# 10
When setting up the new JNLPClassLoader (extending URLClassLoader) it was intended that the order be preserved, other than the jar designated as "main" be listed first,
and then all the jars not designated as "lazy", followed by all those designated as "lazy".
If you call:
URLClassLoader cl = (URLClassLoader) Thread.curentThread().getContextClassLoader();
URL [] urls = cl.getURLs();
for (int i=0; i<urls.length; system.out.println(url[i++])); );
does it return the list in the same order as the jnlp file or reversed ?
/Andy>
# 11
Andy,
Thank for the code snippet.
The order is not reversed it's different. I think Web Start is using a new hash or it's loaded the jars into a hash map.
The order is not being determined by the launch.jnlp, it seems to be some new cache logic.
The load order is consistent from test to test, but it's not predicable.
I'll post an example launch.jnlp.
# 12
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.0+" codebase="$$codebase" href="$$name">
<information>
<title>Managed Objects v4 on xxxxx</title>
<vendor>Managed Objects</vendor>
<homepage href="http://www.ManagedObjects.com"/>
<description>Universal Network, Systems, and Enterprise Management Tool</description>
<icon href="/icons/large/formula.gif"/>
<shortcut>
<menu submenu="Managed Objects" />
<desktop />
</shortcut>
</information>
<security>
<all-permissions/>
</security>
<!-- PATCH MANAGEMENT BEGINDO NO MODIFY THIS SECTION. IT IS MACHINE GENERATED -->
<resources>
<jar href="patches/4002222-05-14CR0000client.jar" />
<jar href="patches/4002007-05-16CR00000client.jar" />
<jar href="patches/4002007-04-17CR20210common.jar" />
<jar href="patches/4002007-04-17CR20210client.jar" />
<jar href="patches/4002007-03-08CR19729common.jar" />
<jar href="patches/4002007-03-08CR19729client.jar" />
<jar href="patches/4002007-03-05CR19729common.jar" />
<jar href="patches/4002007-03-05CR19729client.jar" />
<jar href="patches/4002007-01-30CR19449common.jar" />
<jar href="patches/4002007-01-30CR19449client.jar" />
<jar href="patches/4002007-01-15CR19543client.jar" />
<jar href="patches/4002006-12-20CR19304common.jar" />
<jar href="patches/4002006-12-20CR19304client.jar" />
<jar href="patches/4002006-11-13CR19084common.jar" />
<jar href="patches/4002006-11-13CR19084client.jar" />
<jar href="patches/4002006-11-08CR19203client.jar" />
<jar href="patches/4002006-10-31CR19114common.jar" />
<jar href="patches/4002006-10-31CR19114client.jar" />
</resources>
<!-- PATCH MANAGEMENT ENDDO NO MODIFY THIS SECTION. IT IS MACHINE GENERATED -->
<!-- DEPLOY MANAGEMENT BEGINDO NO MODIFY THIS SECTION. IT IS MACHINE GENERATED -->
<resources>
<jar href="deploy/terajdbc4.jar" />
<jar href="deploy/mysql-connector-java-3.1.14-bin.jar" />
</resources>
<!-- DEPLOY MANAGEMENT ENDDO NO MODIFY THIS SECTION. IT IS MACHINE GENERATED -->
<!-- EXTENSION MANAGEMENT BEGINDO NO MODIFY THIS SECTION. IT IS MACHINE GENERATED -->
<!-- EXTENSION MANAGEMENT ENDDO NO MODIFY THIS SECTION. IT IS MACHINE GENERATED -->
<resources>
<j2se version="1.5.0*" java-vm-args="-Xmx256m" href="http://java.sun.com/products/autodl/j2se"/>
<property name="CORBA.properties" value="$$context/classes/CORBA.properties" />
<property name="log4j.defaultInitOverride" value="true" />
<property name="Script.codegenDisabled" value="true" />
<!-- the following flag is required to make single click drag/drop work in JList in JRE 1.5 -->
<property name="sun.swing.enableImprovedDragGesture" value="true" />
<jar href="client.jar" version="4.0.0.59488" main="true" />
<jar href="svglayout.jar" version="4.0.0.59488"/>
<jar href="xmledit.jar" part="xmledit" version="4.0.0.59488" download="lazy" />
<package part="xmledit" name="com.mosol.Formula.Client.xmleditor.*" recursive="true" />
<jar href="xml.jar" part="xml" version="4.0.0.59488" download="lazy" />
<package part="xml" name="org.w3c.dom.*" recursive="true" />
<package part="xml" name="org.xml.sax.*" recursive="true" />
<package part="xml" name="javax.xml.*" recursive="true" />
<package part="xml" name="org.apache.xerces.*" recursive="true" />
<jar href="rse.jar" part="rse" version="4.0.0.59488" download="lazy" />
<package part="rse" name="com.mosol.Formula.Client.RSE.*" recursive="true" />
<jar href="jena.jar" part="jena" version="4.0.0.59488" download="lazy" />
<package part="jena" name="com.hp.hpl.mesa.*" recursive="true" />
<jar href="ide.jar" part="ide" version="4.0.0.59488" download="lazy" />
<package part="ide" name="com.mosol.Formula.Client.ide.*" recursive="true" />
<package part="ide" name="com.mosol.Formula.Client.guix.*" recursive="true" />
<package part="ide" name="com.mosol.Formula.Client.rdf.*" recursive="true" />
<package part="ide" name="org.apache.ecs.*" recursive="true" />
<package part="ide" name="com.inet.*" recursive="true" />
<package part="ide" name="com.sybase.*" recursive="true" />
<package part="ide" name="net.sourceforge.jtds.*" recursive="true" />
<package part="ide" name="com.ibm.db2.*" recursive="true" />
<package part="ide" name="com.ibm.db2os390.*" recursive="true" />
<package part="ide" name="sqlj.*" recursive="true" />
<package part="ide" name="oracle.*" recursive="true" />
<package part="ide" name="isc_*" />
<package part="ide" name="EDU.oswego.*" recursive="true" />
<jar href="hibernate.jar" part="hibernate" version="4.0.0.59488" download="lazy" />
<package part="hibernate" name="org.hibernate.*" recursive="true" />
<package part="hibernate" name="net.sf.cglib.*" recursive="true" />
<package part="hibernate" name="net.sf.ehcache.*" recursive="true" />
<package part="hibernate" name="org.objectweb.asm.*" recursive="true" />
<package part="hibernate" name="org.dom4j.*" recursive="true" />
<package part="hibernate" name="com.mchange.*" recursive="true" />
<package part="hibernate" name="antlr.*" recursive="true" />
<jar href="bemui.jar" part="bemui" version="4.0.0.59488" download="lazy" />
<package part="bemui" name="com.mosol.integration.apm.data.*" recursive="true" />
<package part="bemui" name="com.mosol.integration.apm.ui.*" recursive="true" />
<jar href="bsv.jar" part="bsv" version="4.0.0.59488" download="lazy" />
<package part="bsv" name="com.mosol.Formula.Client.ui.bsv.*" recursive="true" />
<package part="bsv" name="com.mosol.Formula.ViewBuilder.*" recursive="true" />
<package part="bsv" name="edu.umd.cs.piccolo.*" recursive="true" />
<package part="bsv" name="y.*" recursive="true" />
<jar href="jdic.jar" part="jdic" version="4.0.0.59488" download="lazy"/>
<package part="jdic" name="org.jdesktop.jdic.browser.*" recursive="true" />
<package part="jdic" name="org.jdesktop.jdic.desktop.*" recursive="true" />
<!-- Logging options, set to true for debugging -->
<property name="verbose" value="false" />
</resources>
<resources os="Windows">
<jar href="win32/jdic_stub.jar" version="4.0.0.59488" download="lazy"/>
<nativelib href="win32/jdic-native.jar" version="4.0.0.59488"/>
</resources>
<resources os="SunOS" arch="sparc">
<jar href="win32/jdic_stub.jar" version="4.0.0.59488" download="lazy"/>
<nativelib href="solaris_sparc/jdic-native.jar" version="4.0.0.59488"/>
</resources>
<resources os="Linux">
<jar href="win32/jdic_stub.jar" version="4.0.0.59488" download="lazy"/>
<nativelib href="linux/jdic-native.jar" version="4.0.0.59488"/>
</resources>
<application-desc main-class="com.mosol.Formula.Client.Main">
<argument>$$context/download/DownloadServlet?client=true</argument>
</application-desc>
</jnlp>
# 13
Discussing the launch.jnlp above.
Before 1.6 the order would follow the <jar href> tags. Patches, then core jar and extensions.
Now the order looks like this:
http://xxx/client/client.jar
http://xxx/client/patches/4002007-04-17CR20210common.jar
http://xxx/client/patches/4002007-03-08CR19729common.jar
http://xxx/client/patches/4002007-03-05CR19729common.jar
http://xxx/client/patches/4002007-01-30CR19449common.jar
http://xxx/client/patches/4002007-01-15CR19543client.jar
http://xxx/client/patches/4002006-12-20CR19304client.jar
http://xxx/client/patches/4002006-11-13CR19084client.jar
http://xxx/client/patches/4002006-10-31CR19114common.jar
http://xxx/client/deploy/terajdbc4.jar
http://xxx/client/svglayout.jar
http://xxx/client/win32/jdic_stub.jar
http://xxx/client/bsv.jar
The client jar should be loaded after the patches.
This is the core of the behavior change in 1.6
# 14
Figured out part of the issue.
In Webstart 1.6 the main=true flag causing that jar to be loaded first.
<jar href="client.jar" version="4.0.0.59488" main="true" />
This is different than 1.5, which loaded the jar in the order the launch.jnlp presented them.
We have a workaround, but it hasn't been tested throughly. We created a simple jar with minimal classes to boot the application, this jar has the main flag.
As long as those core classes *never* have to be patched then this workaround is good.