I think you are right. The ClassLoader is a likely culprit here. There's a simple way to set a ClassLoader for Cayenne runtime:
Thread.currentThread().setContextClassLoader(..); For something more advanced (e.g. to ensure it works across all threads), you might define a custom implementation of ClassLoaderManager DI service [1]. Andrus [1] https://cayenne.apache.org/docs/4.2/cayenne-guide/#customization-strategies > On Mar 29, 2022, at 1:00 AM, Stefan Stegic <stefanste...@gmail.com> wrote: > > I think I may have figured it out! I switched to MongoDB with Morphia ODM and > had the same problem: works when I run it through main, but throws a > ClassNotFound when ran by Spigot. Morphia couldn't locate my entity classes > package via its path and I solved it by supplying the class loader of the > calling class like so: > > MapperOptions mapperOptions = > MapperOptions.builder().classLoader(this.getClass().getClassLoader()).build(); > datastore = Morphia.createDatastore(MongoClients.create(connectionUri), > dbName, mapperOptions); > datastore.getMapper().mapPackage("path.to.my.models.package"); > > Could there be a similar problem with Cayenne? Is there a way to change the > class loader before initialization in a similar matter? > > On Wed, Mar 23, 2022 at 5:53 PM Stefan Stegic <stefanste...@gmail.com > <mailto:stefanste...@gmail.com>> wrote: > Yup, it's in there: > > ################################################################## > # Licensed to the Apache Software Foundation (ASF) under one > # or more contributor license agreements. See the NOTICE file > # distributed with this work for additional information > # regarding copyright ownership. The ASF licenses this file > # to you under the Apache License, Version 2.0 (the > # "License"); you may not use this file except in compliance > # with the License. You may obtain a copy of the License at > # > # http://www.apache.org/licenses/LICENSE-2.0 > <http://www.apache.org/licenses/LICENSE-2.0> > # > # Unless required by applicable law or agreed to in writing, > # software distributed under the License is distributed on an > # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY > # KIND, either express or implied. See the License for the > # specific language governing permissions and limitations > # under the License. > ################################################################## > > org.apache.cayenne.configuration.server.MainCayenneServerModuleProvider > > On Wed, Mar 23, 2022 at 5:47 PM Andrus Adamchik <aadamc...@gmail.com > <mailto:aadamc...@gmail.com>> wrote: > Ok, shading can be tricky. Do you have this file inside the shaded jar: > > >> "META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider" > > And if you do, can you check the contents of it? It is a simple text file, so > once you extract it form the jar, you can check it in any text editor. > > Andrus > > > > > On Mar 23, 2022, at 5:26 PM, Stefan Stegic <stefanste...@gmail.com > > <mailto:stefanste...@gmail.com>> wrote: > > > > Ok, just tried maven-shade-plugin, but no luck - still the same error... It > > seems that the shading is working as expected: when I run maven package, > > the output jar really has cayenne's stuff in there, but DI is still failing > > when I copy the plugin into the server and start it. > > > > Michael, in response to your question: > > > >> Have you tried updating your "java -cp myPlugin.jar path.to.Main" command > >> to have more classpaths? > > > > > > When I run Main, it works, so that's not the problem. The problem arises > > when my plugin is called by Spigot, the custom Minecraft server I'm writing > > the plugin for. > > > > On Wed, Mar 23, 2022 at 5:20 PM Stefan Stegic <stefanste...@gmail.com > > <mailto:stefanste...@gmail.com>> > > wrote: > > > >> Hi Michael, > >> > >> Oh, I wasn't aware, thanks. Here's the screenshot from my last e-mail: > >> https://imgur.com/QJoBGAV <https://imgur.com/QJoBGAV> . > >> Right, I'll give maven-shade-plugin a try now and check if it works that > >> way, thanks. > >> > >> On Wed, Mar 23, 2022 at 5:18 PM Michael Gentry <blackn...@gmail.com > >> <mailto:blackn...@gmail.com>> > >> wrote: > >> > >>> If you aren't using a shaded JAR (which merges all JARs into a single > >>> JAR), > >>> then you'll need more JARs listed on your Java command. > >>> > >>> > >>> On Wed, Mar 23, 2022 at 12:16 PM Stefan Stegic <stefanste...@gmail.com > >>> <mailto:stefanste...@gmail.com>> > >>> wrote: > >>> > >>>> PS: I'm not using maven-shade (just opened the link you sent) > >>>> > >>>> On Wed, Mar 23, 2022 at 5:10 PM Stefan Stegic <stefanste...@gmail.com > >>>> <mailto:stefanste...@gmail.com>> > >>>> wrote: > >>>> > >>>>> My knowledge of Java is not so deep, so excuse stupid questions - if > >>> any. > >>>>> I believe I am using shading because I'm exporting dependencies into my > >>>>> JAR. IntelliJ does this for me in the build process by publishing the > >>> JAR > >>>>> as an artifact. All I did was specify which dependencies I want to > >>> package > >>>>> in there like this: > >>>>> > >>>>> [image: image.png] > >>>>> > >>>>> So, I build the project, grab the published JAR artifact and put the > >>> file > >>>>> in the plugins folder of the Spigot server. I then run the Server and > >>> it > >>>>> tries to load each plugin JAR that's in there. That's when each of the > >>>>> onEnable methods are called, including that of my plugin > >>>>> (FirstSpigotPlugin). The example code that creates the CayenneRuntime > >>> is in > >>>>> my onEnable method. > >>>>> > >>>>> Should I be packaging these dependencies differently then? > >>>>> > >>>>> On Wed, Mar 23, 2022 at 4:56 PM Andrus Adamchik <aadamc...@gmail.com > >>>>> <mailto:aadamc...@gmail.com>> > >>>>> wrote: > >>>>> > >>>>>> This is not a common problem with Cayenne. In fact this is the first > >>>>>> time I see it happen in any environment. So Spigot is special in this > >>>>>> respect. I found this link: > >>>>>> https://bukkit.fandom.com/wiki/Using_External_Libraries_with_Plugins > >>>>>> <https://bukkit.fandom.com/wiki/Using_External_Libraries_with_Plugins> > >>> < > >>>>>> https://bukkit.fandom.com/wiki/Using_External_Libraries_with_Plugins > >>>>>> <https://bukkit.fandom.com/wiki/Using_External_Libraries_with_Plugins>> > >>>>>> It doesn't answer the question, but provides some hints. So how do you > >>>>>> package your own code and third-party dependencies like Cayenne for > >>>>>> Spigot/Bukkit? Do you use "shading"? > >>>>>> > >>>>>> Andrus > >>>>>> > >>>>>>> On Mar 23, 2022, at 4:51 PM, Stefan Stegic <stefanste...@gmail.com > >>>>>>> <mailto:stefanste...@gmail.com>> > >>>>>> wrote: > >>>>>>> > >>>>>>> Hi, > >>>>>>> > >>>>>>> Thanks for your quick responses! I'm using version 4.1.1. > >>>>>>> Right, so you're saying Spigot is somehow blocking the execution of > >>>>>> said > >>>>>>> code, or it's circumventing it somehow so that those steps of > >>>>>>> initialization are never actually executed? Also, you mean that > >>> it's a > >>>>>>> common problem with Cayenne or with Spigot and other jars? > >>>>>>> > >>>>>>> How would we go about understanding how the Spigot classpath works? > >>> It > >>>>>>> might help to know that the plugin API is called Bukkit, so Spigot > >>> is > >>>>>> kind > >>>>>>> of the parent entity (it's a customized Minecraft server, while > >>> Bukkit > >>>>>> is > >>>>>>> the interface for plugins, as I've come to understand). It's source > >>>>>> code > >>>>>>> should be here: > >>>>>>> https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse > >>>>>>> <https://hub.spigotmc.org/stash/projects/SPIGOT/repos/bukkit/browse> > >>> . > >>>>>>> > >>>>>>> On Wed, Mar 23, 2022 at 4:33 PM Andrus Adamchik < > >>> aadamc...@gmail.com <mailto:aadamc...@gmail.com>> > >>>>>> wrote: > >>>>>>> > >>>>>>>> The bootstrap code is as vanilla as it can get: > >>>>>>>> > >>>>>>>>>> ServerRuntime cayenneRuntime = ServerRuntime.builder() > >>>>>>>>>> .addConfig("cayenne-project.xml") > >>>>>>>>>> .build(); > >>>>>>>> > >>>>>>>> Missing ObjectContextFactory means ServerModule is not loaded in > >>> the > >>>>>>>> environment. Since 4.1 (BTW, which version of Cayenne are we > >>> talking > >>>>>>>> about?), ServerModule is loaded by processing > >>>>>>>> > >>>>>> > >>> "META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider" > >>>>>>>> files from the classpath jars. So there's something about Spigot's > >>>>>>>> classpath that prevents this code in ModuleLoader from returning > >>>>>> proper > >>>>>>>> resources: > >>>>>>>> > >>>>>>>> for (ModuleProvider provider : ServiceLoader.load(providerClass)) { > >>>>>> ... } > >>>>>>>> > >>>>>>>> We need to understand how Spigot classpath works. Cursory Googling > >>>>>> shows > >>>>>>>> that this is a common problem, just don't immediately see a > >>> solution. > >>>>>>>> > >>>>>>>> Andrus > >>>>>>>> > >>>>>>>> > >>>>>>>>> On Mar 23, 2022, at 4:03 PM, Andrus Adamchik <aadamc...@gmail.com > >>>>>>>>> <mailto:aadamc...@gmail.com> > >>>> > >>>>>>>> wrote: > >>>>>>>>> > >>>>>>>>> Actually the stack shows that there's already an instance of > >>> Cayenne > >>>>>>>> runtime available to the code, but the runtime is in a bad state > >>> (not > >>>>>> clear > >>>>>>>> why). So thread binding should not be required. > >>>>>>>>> > >>>>>>>>> Andrus > >>>>>>>>> > >>>>>>>>> > >>>>>>>>>> On Mar 23, 2022, at 4:00 PM, John Huss <johnth...@gmail.com > >>>>>>>>>> <mailto:johnth...@gmail.com>> > >>> wrote: > >>>>>>>>>> > >>>>>>>>>> You have to bind the DI injector to the thread (and unbind it > >>>>>> later): > >>>>>>>>>> > >>>>>>>>>> > >>> CayenneRuntime.*bindThreadInjector*(cayenneRuntime.getInjector()); > >>>>>>>>>> > >>>>>>>>>> If you are using servlets, then CayenneFilter will do this for > >>> you. > >>>>>>>>>> Otherwise you can bind it at the start of a request and unbind it > >>>>>> at the > >>>>>>>>>> end. > >>>>>>>>>> > >>>>>>>>>> On Wed, Mar 23, 2022 at 9:10 AM Stefan Stegic < > >>>>>> stefanste...@gmail.com <mailto:stefanste...@gmail.com>> > >>>>>>>>>> wrote: > >>>>>>>>>> > >>>>>>>>>>> Hi Andrus, > >>>>>>>>>>> > >>>>>>>>>>> Of course: > >>>>>>>>>>> > >>>>>>>>>>> org.apache.cayenne.di.DIRuntimeException: DI container has no > >>>>>> binding > >>>>>>>> for > >>>>>>>>>>> key <BindingKey: > >>>>>> org.apache.cayenne.configuration.ObjectContextFactory> > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> org.apache.cayenne.di.spi.DefaultInjector.getProvider(DefaultInjector.java:158) > >>>>>>>>>>> ~[?:?] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> org.apache.cayenne.di.spi.DefaultInjector.getProvider(DefaultInjector.java:144) > >>>>>>>>>>> ~[?:?] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:134) > >>>>>>>>>>> ~[?:?] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> org.apache.cayenne.configuration.CayenneRuntime.newContext(CayenneRuntime.java:124) > >>>>>>>>>>> ~[?:?] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> io.github.phuskus.firstspigotplugin.StatisticsController.reportPlayerConnectionEvent(StatisticsController.java:20) > >>>>>>>>>>> ~[?:?] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> io.github.phuskus.firstspigotplugin.FirstSpigotPlugin.onEnable(FirstSpigotPlugin.java:29) > >>>>>>>>>>> ~[?:?] > >>>>>>>>>>> at > >>>>>>>>>>> > >>> org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:264) > >>>>>>>>>>> ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:342) > >>>>>>>>>>> ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:480) > >>>>>>>>>>> ~[spigot-api-1.18.1-R0.1-SNAPSHOT.jar:?] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> org.bukkit.craftbukkit.v1_18_R1.CraftServer.enablePlugin(CraftServer.java:521) > >>>>>>>>>>> ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3443-Spigot-699290c-2c1e499] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> org.bukkit.craftbukkit.v1_18_R1.CraftServer.enablePlugins(CraftServer.java:435) > >>>>>>>>>>> ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3443-Spigot-699290c-2c1e499] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> net.minecraft.server.MinecraftServer.loadWorld0(MinecraftServer.java:612) > >>>>>>>>>>> ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3443-Spigot-699290c-2c1e499] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> net.minecraft.server.MinecraftServer.loadLevel(MinecraftServer.java:414) > >>>>>>>>>>> ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3443-Spigot-699290c-2c1e499] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>>>> > >>>>>> > >>> net.minecraft.server.dedicated.DedicatedServer.e(DedicatedServer.java:262) > >>>>>>>>>>> ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3443-Spigot-699290c-2c1e499] > >>>>>>>>>>> at > >>>>>>>> net.minecraft.server.MinecraftServer.w(MinecraftServer.java:994) > >>>>>>>>>>> ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3443-Spigot-699290c-2c1e499] > >>>>>>>>>>> at > >>>>>>>>>>> > >>>>>> > >>> net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:304) > >>>>>>>>>>> ~[spigot-1.18.1-R0.1-SNAPSHOT.jar:3443-Spigot-699290c-2c1e499] > >>>>>>>>>>> at java.lang.Thread.run(Thread.java:833) [?:?] > >>>>>>>>>>> > >>>>>>>>>>> On Wed, Mar 23, 2022 at 11:49 AM Andrus Adamchik < > >>>>>> aadamc...@gmail.com <mailto:aadamc...@gmail.com>> > >>>>>>>>>>> wrote: > >>>>>>>>>>> > >>>>>>>>>>>> Hi Stefan, > >>>>>>>>>>>> > >>>>>>>>>>>> Could you include a full stack trace please? > >>>>>>>>>>>> > >>>>>>>>>>>> Thanks, > >>>>>>>>>>>> Andrus > >>>>>>>>>>>> > >>>>>>>>>>>>> On Mar 23, 2022, at 1:04 AM, Stefan Stegic < > >>>>>> stefanste...@gmail.com <mailto:stefanste...@gmail.com>> > >>>>>>>>>>>> wrote: > >>>>>>>>>>>>> > >>>>>>>>>>>>> Hi, > >>>>>>>>>>>>> > >>>>>>>>>>>>> > >>>>>>>>>>>>> First some context: I'm working on a custom Minecraft server > >>>>>> (Spigot) > >>>>>>>>>>>>> plugin. It's just a JAR that you export and place somewhere in > >>>>>> the > >>>>>>>>>>>> server's > >>>>>>>>>>>>> folder structure. > >>>>>>>>>>>>> > >>>>>>>>>>>>> I wrote a simple insert query via Cayenne's API. It works > >>> when I > >>>>>> run > >>>>>>>>>>> the > >>>>>>>>>>>>> example JAR directly via executing Main from the command line > >>>>>> (java > >>>>>>>> -cp > >>>>>>>>>>>>> myPlugin.jar path.to.Main), but it fails with the following > >>> error > >>>>>>>> when > >>>>>>>>>>>>> executed by the server in my plugin's OnEnable lifecycle hook: > >>>>>>>>>>>>> > >>>>>>>>>>>>> org.apache.cayenne.di.DIRuntimeException: DI container has no > >>>>>> binding > >>>>>>>>>>> for > >>>>>>>>>>>>> key <BindingKey: > >>>>>>>> org.apache.cayenne.configuration.ObjectContextFactory> > >>>>>>>>>>>>> > >>>>>>>>>>>>> > >>>>>>>>>>>>> My initial theory was that it's being executed from a > >>> different > >>>>>>>> thread, > >>>>>>>>>>>> so > >>>>>>>>>>>>> the DI system might not have access to that dependency for > >>> some > >>>>>>>> reason, > >>>>>>>>>>>> but > >>>>>>>>>>>>> it seems like the server executes this lifecycle hook from the > >>>>>> main > >>>>>>>>>>>> thread > >>>>>>>>>>>>> as well (though they've named the thread "Server thread", and > >>> I > >>>>>> don't > >>>>>>>>>>>> know > >>>>>>>>>>>>> how to check if it's the main thread for sure). Not sure if > >>> this > >>>>>> is a > >>>>>>>>>>>>> promising direction to pursue, but I got the hunch by looking > >>> at > >>>>>> the > >>>>>>>>>>>>> threadInjector bits of Cayenne's DI container docs. > >>>>>>>>>>>>> > >>>>>>>>>>>>> My example looks like this: > >>>>>>>>>>>>> > >>>>>>>>>>>>> ServerRuntime cayenneRuntime = ServerRuntime.builder() > >>>>>>>>>>>>> .addConfig("cayenne-project.xml") > >>>>>>>>>>>>> .build();ObjectContext ctx = > >>>>>>>>>>> cayenneRuntime.newContext(); > >>>>>>>>>>>>> PlayerConnectionEvent newEvent = > >>>>>>>>>>>>> ctx.newObject(PlayerConnectionEvent.class); > >>>>>>>>>>>>> newEvent.setEventType(eType); > >>>>>>>>>>>>> newEvent.setPlayerName(playerName); > >>>>>>>>>>>>> newEvent.setIpAddress(ipAddress); > >>>>>>>>>>>>> newEvent.setTimestampUnixSeconds(unixSeconds); > >>>>>>>>>>>>> > >>>>>>>>>>>>> ctx.commitChanges(); > >>>>>>>>>>>>> > >>>>>>>>>>>>> Some help would be greatly appreciated, thanks in advance! > >>>>>>>>>>>>> -- > >>>>>>>>>>>>> S poštovanjem, > >>>>>>>>>>>>> *Stefan Stegić* > >>>>>>>>>>>> > >>>>>>>>>>>> > >>>>>>>>>>> > >>>>>>>>>>> -- > >>>>>>>>>>> S poštovanjem, > >>>>>>>>>>> *Stefan Stegić* > >>>>>>>>>>> > >>>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>> > >>>>>>> -- > >>>>>>> S poštovanjem, > >>>>>>> *Stefan Stegić* > >>>>>> > >>>>>> > >>>>> > >>>>> -- > >>>>> S poštovanjem, > >>>>> *Stefan Stegić* > >>>>> > >>>> > >>>> > >>>> -- > >>>> S poštovanjem, > >>>> *Stefan Stegić* > >>>> > >>> > >> > >> > >> -- > >> S poštovanjem, > >> *Stefan Stegić* > >> > > > > > > -- > > S poštovanjem, > > *Stefan Stegić* > > > > -- > S poštovanjem, > Stefan Stegić > > > -- > S poštovanjem, > Stefan Stegić