In Lucee, I am loading a jar file from a path that...
# lucee
j
In Lucee, I am loading a jar file from a path that is defined in Application.cfc (this.javaSettings.loadPaths = ['../build/lib'];)... but that jar file has a dependency (also in the ..build/lib directory) that is a higher version of what's bundled w/Lucee. (Specifically, hslqdb 1.8 is bundled with Lucee and the jar I'm loading requires hsqldb 2.4.1.) I end up getting an error due to the one bundled with Lucee getting referenced, I believe. I'm trying to understand if going the OSGi route helps this scenario since I wouldn't be loading the jar directly - it's referenced by the jar I am loading. Or should I explore JavaLoader?
b
Javaloader will likely work even though I hate to use it. It's not been maintained in like 10 years.
OSGI is the "real" answer to this, but getting OSGI to work in Lucee can be rife with issues
IN theory, if you have an OSGI bundle which requires a specific version of the H2 OSGI bundle and you load both of those in with
this.javaSettings.bundles
then IN THEORY it would work.
m
you can add an array of paths to jars to createObject() in lucee, it might work for your scenario. createObject( "java", "class", ['/path/to/your.jar', '/another/path/to/yourother.jar' ])
b
@Matt Jones That's what he's doing now
but that jar file has a dependency (also in the ..build/lib directory)
m
i pass the dependencies as jars explicitly
b
Just because you load it there, doesn't always mean it will be the version that gets found first by whatever classloader the lib is using
r
@bdw429s Would Lucee break if 1.8 was just replaced with 2.4.1?
b
@risto You don't really have the option to update Lucee's internal H2 version. Lucee loads it as an OSGI bundle via • bundle name • bundle version which is specifically designed to prevent against the ability to just "grab whatever is floating around the classpath" šŸ™‚
Even if you deleted Lucee H2 bundle, it would most likely just re-download it on the fly the next time it needed it.
r
Good to know. I figured it wasn't that easy.
j
i can confirm it just re-downloads 1.8 - that was one of the first things i tried
b
@John Liljegren Another thing you can try is providing the list of jars to the
createObject()
call. In my experience, that will ONLY work for the initial instantiation of those classes however. I've found that once I created a class and then tried to call a method on that class inside my normal CFML code, it would go back to the default classsloader.
j
yeah that didn't seem to make any difference
b
Can you share the error message and full stack trace that you get?
j
i am going to try going the OSGi route, which I wish was easier to do (meaning i wish the libraries were already OSGified)
b
TBH, the "OSGI route" only really works if you control the code in this library and you intend to have it request the classes it needs from an OSGI framework
If the lib just uses
Copy code
new com.foo.java.Class();
then you're at the mercy of the class loader, regardles of whehter or not that code exists in an "OSGI" jar or not
j
Here is the message: "org.hsqldb.DatabaseURL.parseURL(Ljava/lang/String;ZZ)Lorg/hsqldb/persist/HsqlProperties;" and the stacktrace: "lucee.runtime.exp.NativeException: org.hsqldb.DatabaseURL.parseURL(Ljava/lang/String;ZZ)Lorg/hsqldb/persist/HsqlProperties; at org.hsqldb.jdbc.JDBCDriver.getConnection(Unknown Source) at org.hsqldb.jdbc.JDBCDataSource.getConnection(Unknown Source) at org.hsqldb.jdbc.JDBCDataSource.getConnection(Unknown Source) at org.geotools.referencing.factory.epsg.DirectEpsgFactory.getConnection(DirectEpsgFactory.java:3529) at org.geotools.referencing.factory.epsg.ThreadedEpsgFactory.createBackingStore(ThreadedEpsgFactory.java:437) at org.geotools.referencing.factory.DeferredAuthorityFactory.getBackingStore(DeferredAuthorityFactory.java:114) at org.geotools.referencing.factory.BufferedAuthorityFactory.isAvailable(BufferedAuthorityFactory.java:218) at org.geotools.referencing.factory.DeferredAuthorityFactory.isAvailable(DeferredAuthorityFactory.java:100) at org.geotools.util.factory.FactoryRegistry.isAvailable(FactoryRegistry.java:808) at org.geotools.util.factory.FactoryRegistry.isAcceptable(FactoryRegistry.java:631) at org.geotools.util.factory.FactoryRegistry.lambda$getFactories$0(FactoryRegistry.java:300) at java.util.stream.ReferencePipeline$2$1.accept(Unknown Source) at java.util.Spliterators$IteratorSpliterator.tryAdvance(Unknown Source) at java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(Unknown Source) at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(Unknown Source) at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(Unknown Source) at java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(Unknown Source) at java.util.Spliterators$1Adapter.hasNext(Unknown Source) at org.geotools.util.LazySet.isEmpty(LazySet.java:98) at org.geotools.referencing.factory.ManyAuthoritiesFactory.<init>(ManyAuthoritiesFactory.java:115) at org.geotools.referencing.DefaultAuthorityFactory.getBackingFactory(DefaultAuthorityFactory.java:114) at org.geotools.referencing.DefaultAuthorityFactory.<init>(DefaultAuthorityFactory.java:67) at org.geotools.referencing.CRS.getAuthorityFactory(CRS.java:253) at org.geotools.referencing.CRS.decode(CRS.java:533) at org.geotools.referencing.CRS.decode(CRS.java:447) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at lucee.runtime.reflection.pairs.MethodInstance.invoke(MethodInstance.java:56) at lucee.runtime.java.JavaObject.call(JavaObject.java:265) at lucee.runtime.java.JavaObject.call(JavaObject.java:287) at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:787) at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1775) at beans.point_cfc$cf$11.udfCall(/model/beans/Point.cfc:54) at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:112) at lucee.runtime.type.UDFImpl._call(UDFImpl.java:350) at lucee.runtime.type.UDFImpl.call(UDFImpl.java:223) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:696) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:584) at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1931) at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:787) at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1775) at services.persistence.hazardfeature_cfc$cf.udfCall(/model/services/persistence/hazardFeature.cfc:50) at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:112) at lucee.runtime.type.UDFImpl._call(UDFImpl.java:350) at lucee.runtime.type.UDFImpl.call(UDFImpl.java:223) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:696) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:584) at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1931) at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:787) at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1775) at beans.point_cfc$cf$11.udfCall(/model/beans/Point.cfc:66) at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:112) at lucee.runtime.type.UDFImpl._call(UDFImpl.java:350) at lucee.runtime.type.UDFImpl.call(UDFImpl.java:223) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:696) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:584) at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1931) at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:787) at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1775) at models_cfc$cf.udfCall2(/controllers/models.cfc:569) at models_cfc$cf.udfCall(/controllers/models.cfc) at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:112) at lucee.runtime.type.UDFImpl._call(UDFImpl.java:350) at lucee.runtime.type.UDFImpl.callWithNamedValues(UDFImpl.java:213) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:697) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:584) at lucee.runtime.ComponentImpl.callWithNamedValues(ComponentImpl.java:1950) at lucee.runtime.util.VariableUtilImpl.callFunctionWithNamedValues(VariableUtilImpl.java:900) at lucee.runtime.functions.dynamicEvaluation.Invoke.call(Invoke.java:49) at framework.one_cfc$cf.udfCallb(/framework/one.cfc:1635) at framework.one_cfc$cf.udfCall(/framework/one.cfc) at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:112) at lucee.runtime.type.UDFImpl._call(UDFImpl.java:350) at lucee.runtime.type.UDFImpl.call(UDFImpl.java:223) at lucee.runtime.type.scope.UndefinedImpl.call(UndefinedImpl.java:786) at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:787) at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1775) at framework.one_cfc$cf.udfCall6(/framework/one.cfc:896) at framework.one_cfc$cf.udfCall(/framework/one.cfc) at lucee.runtime.type.UDFImpl.implementation(UDFImpl.java:112) at lucee.runtime.type.UDFImpl._call(UDFImpl.java:350) at lucee.runtime.type.UDFImpl.call(UDFImpl.java:223) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:696) at lucee.runtime.ComponentImpl._call(ComponentImpl.java:584) at lucee.runtime.ComponentImpl.call(ComponentImpl.java:1931) at lucee.runtime.listener.ModernAppListener.call(ModernAppListener.java:444) at lucee.runtime.listener.ModernAppListener._onRequest(ModernAppListener.java:218) at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:44) at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2493) at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2478) at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2449) at lucee.runtime.engine.Request.exe(Request.java:45) at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1216) at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:1162) at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:97) at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51) at javax.servlet.http.HttpServlet.service(HttpServlet.java:590) at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74) at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129) at org.cfmlprojects.regexpathinfofilter.RegexPathInfoFilter.doFilter(RegexPathInfoFilter.java:47) at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68) at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117) at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at runwar.Server$1.handleRequest(Server.java:510) at io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:280) at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:79) at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:134) at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:131) at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:260) at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:79) at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:100) at io.undertow.server.Connectors.executeRootHandler(Connectors.java:387) at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852) at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1449) at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280) at java.lang.Thread.run(Unknown Source) Caused by: java.lang.NoSuchMethodError: org.hsqldb.DatabaseURL.parseURL(Ljava/lang/String;ZZ)Lorg/hsqldb/persist/HsqlProperties; ... 138 more"
šŸ‘ 1
sorry i don't know the right way to format that
so you're saying even if i do the OSGi thing, and try to specify the versions in the bundle manifest, it will load whatever is already loaded regardless?
b
Actually, that may work. I guess it's worth a shot to try. In reality, the bundle is wired when it's loaded by the OSGI framework using the manifest.
j
ok yeah that's my hope and understanding. from https://docs.lucee.org/guides/lucee-5/extensions.html#osgi-bundles, it says: "OSGi is the framework Lucee 5 is based on, that allows for the loading and unloading of JAR files on the fly at any time without a server restart being required. *In addition you can have different versions of the same JAR in your environment without causing a conflict.*" i just hope that extends to dependencies
I ended up using Gradle Shadow (https://github.com/johnrengelman/shadow) to create a jar with hsqldb embedded, and relocated the package names to be versioned so it doesn't conflict with the package loaded in Lucee by default. It may not be the best solution in all cases but I couldn't figure out how to get OSGi working right.
šŸ‘ 1
e
@John Liljegren I would love to know if this still works if you do try the OSGi path: https://forgebox.io/view/commandbox-osgi