On 15.09.2014 15:32, rony g. flatscher wrote:
> On 15.09.2014 15:16, Rick Hillegas wrote:
>> On 9/12/14 7:29 AM, Rony G. Flatscher (Apache) wrote:
>>> On 12.09.2014 15:29, Rick Hillegas wrote:
>>>> On 9/12/14 3:37 AM, Rony G. Flatscher (Apache) wrote:
>>>>> Hi there,
>>>>>
>>>>> tried to find this information on the Internet, but also in the derby
>>>>> wiki, but was not
>>>>> successful so far, hence posting this question here where hopefully those
>>>>> in the know can help
>>>>> out.
>>>>>
>>>>> Using derby from Oracle's JDK 7 distribution I encountered a problem and
>>>>> after a loong time of
>>>>> research, testing, trials and errors I came up with a solution, but still
>>>>> do not understand the
>>>>> reason for the problem!
>>>>>
>>>>> Here is the problem:
>>>>>
>>>>> * having a class from a jar that is placed in one of the
>>>>> java.ext.dirs loading the derby JDBC (to be precise:
>>>>> 'org.apache.derby.jdbc.EmbeddedDriver' and then issuing a
>>>>> newInstance()) from the classpath works, but the subsequent
>>>>>
>>>>> java.sql.DriverManager.getConnection('jdbc:derby:derbyDB;create=true',props)
>>>>> where 'props' is a java.util.Properties with "user1/user1" and
>>>>> "password/user1", yields:
>>>>> getCause(): [java.sql.SQLException: No suitable driver found for
>>>>> jdbc:derby:derbyDB;create=true]
>>>>>
>>>>> The same program works without any changes,
>>>>>
>>>>> * if the jar-file loading the derby JDBC is not in java.ext.dirs
>>>>> but on the classpath then it works
>>>>> * if the jar-file and derby.jar are both in java.ext.dirs then it
>>>>> works
>>>>>
>>>>> My question is, why is this so?
>>>>>
>>>>> (It seems to be the case that both, the Java class that loads the derby
>>>>> JDBC driver and the derby
>>>>> JDBC driver, must use the same class loader, either a
>>>>> sun.misc.Launcher$AppClassLoader or a
>>>>> sun.misc.Launcher$ExtClassLoader, which is very strange as I have not
>>>>> encountered a similar
>>>>> requirement/behaviour in any other use case in the past years. The thread
>>>>> context class loader is
>>>>> the application class loader which, if used, would have found derby.jar
>>>>> given on the classpath.)
>>>>>
>>>>> Is there any documentation that leads to an explanation about this
>>>>> behaviour somewhere? Are there
>>>>> other Java infrastructures that have such a restriction that anyone is
>>>>> aware of?
>>>>>
>>>>> ---
>>>>>
>>>>> Background: I am authoring a scripting language binding for Java
>>>>> (BSF4ooRexx) and moving the
>>>>> BSF4ooRexx jar to a Java extension directory makes it available to all
>>>>> Java applications
>>>>> including the JavaPlugins for browsers. All test and sample programs work
>>>>> in this setup, except
>>>>> for the sample program that demonstrates how easy it is to use derby via
>>>>> JDBC! :(
>>>>>
>>>>> ---
>>>>>
>>>>> Thankful for any pointer, hints, links, explanations that shed some light
>>>>> into this corner!
>>>>>
>>>>> ---rony
>>>>>
>>>>>
>>>> Hi Rony,
>>>>
>>>> I have not been through this code recently. Maybe someone who has studied
>>>> it in detail can give
>>>> you more information.
>>>>
>>>> I believe that putting Derby in lib/ext will make it impossible to unload
>>>> the Derby classes when
>>>> you de-register the Derby driver. This is a feature of Derby which allows
>>>> Derby-powered components
>>>> (including their class definitions) to be removed from memory when they
>>>> are not needed. If you put
>>>> Derby in lib/ext, then the Derby class definitions will be loaded by the
>>>> extension class loader.
>>>> Those definitions will remain loaded until the extension class loader is
>>>> garbage collected. I
>>>> don't think there is a way to remove all references to the extension class
>>>> loader and so allow it
>>>> to be garbage collected.
>>>>
>>>> It makes sense that Derby class loading won't work in a situation which
>>>> would prevent components
>>>> from being removed.
>>>>
>>>> Note that the security implications of putting Derby in lib/ext are also
>>>> serious. By default,
>>>> classes loaded by the extension class loader enjoy all permissions. You
>>>> would not want a browser
>>>> plugin to be able to elevate its privileges by using Derby.
>>>>
>>>> Hope this helps,
>>> Hi Rick,
>>>
>>> thank you!
>>>
>>> Actually, what I would be after is the following scenario: have the
>>> scirpting language binding in
>>> lib/ext, but derby on classpath, and everything works.
>>>
>>> Having the scripting language binding and derby.jar on classpath works.
>>>
>>> Having the scripting language binding in lib/ext causes classes from that
>>> jar to load derby.jar,
>>> then, when using DriveManager to get a connection to derby fails in this
>>> scenario, unfortunately.
>>> (It is in this step attempting to get a connection, where the exception is
>>> thrown.) As a result it
>>> is currently not possible to successfully use derby.jar (on classpath) in
>>> this desired scenario.
>>>
>>> I would go any length of miles to become able to do this successfully,
>>> rather then forcing the users
>>> of the script programs to put derby.jar in lib/ext (or have to use
>>> -Djava.ext.dirs="..."), so would
>>> be thankful for any insights and ideas.
>>>
>>> ---rony
>>>
>>> P.S.: Having both, the scripting language binding and derby.jar in lib/ext
>>> works too, but this is
>>> not desired at all.
>>>
>>>
>> Hi Rony,
>>
>> Can the scripting library get its hands on the class which is calling into
>> it? Maybe it could do
>> something like the following to try to get the VM to load Derby with the
>> caller's ClassLoader:
>>
>> Class.forName( "org.apache.derby.jdbc.EmbeddedDriver", true,
>> callingClass.getClassLoader() );
>>
>> Haven't tried this. Might be a waste of your time.
> Thank you for this hint.
>
> The problem is that the scripting library is in java.ext.dirs (to be
> available to all Java apps),
> hence its classes are loaded with the extension class loader. At runtime of
> the scripts the script
> library classes will interface with the JVM (e.g. loading classes, finding
> and invoking methods,
> etc.), hence it is always the case that the calling class is from the script
> library and was loaded
> with the extension class loader.
>
> If the DriverManager would use the current thread's context class loader,
> then it should work, but
> this seems to not be the case. It seems to be the case that it only uses the
> calling class class
> loader“and if that is the case (and not regarded as an error), then one would
> be forced to move
> 'derby.jar' to java.ext.dirs, which for the very reasons you communicated
> would not be desired.
>
> ---rony
In the meantime I experimented with the class
"org.apache.derby.jdbc.EmbeddedDataSource". This
works, i.e. having the script library in java.ext.dirs and derby.jar on
classpath!
Nevertheless, DriverManager should behave the same, so I will try to file a bug
pointing out at the
use case and regarding it a bug that the thread's context class loader seems to
be not invoked in
this setup.
---rony