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> 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> 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>
>> 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>
>>> 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>
>>>> 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ć*
>>> 
> 

Reply via email to