You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Andrew Willerding <aw...@itsurcom.com> on 2019/10/17 03:24:16 UTC

Cayenne and classpath question and help

Hi,

I have an application that dynamically loads jar files and reloads them 
when they are changed.  Unfortunately I'm have an issue getting Cayenne 
to see the classes inside one of these dynamically loaded jar files. I 
have some test code that looks roughly like this.

import com.dbclientbase.Database.Account;
public class blah

   public testMethod(){

             Account ac = new Account();  // This object instantiates 
without an error so it's visible to app outside of Cayenne

             ObjectContext oc = DBClientBase.getObjectContext(); // This 
method generates the ServerRuntime and fails to get an ObjectContext to 
work with (error below)

  }
}

The error output below seems to suggest that Cayenne cannot access the 
Account class although I can successfully instantiate a non-Cayenne 
object.  What can I do to ensure that Cayenne also has access to the 
contents of a dynamically loaded and reloaded jar file?  I have found 
references to AdhocObjectFactory.getClassLoader()  but I can't find any 
examples on how to use it and I'm quite at a loss on how to even begin 
use it.

Thanks,

Andrew


Exception==>org.apache.cayenne.configuration.server.DataDomainLoadException: 
[v.4.1.B2 May 04 2019 09:30:14] DataDomain startup failed: Invalid 
class: com.dbclientbase.Database$Account
     at 
org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:123)
     at 
org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:60)
     at 
org.apache.cayenne.di.spi.CustomProvidersProvider.get(CustomProvidersProvider.java:39)
     at 
org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:43)
     at 
org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
     at 
org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:139)
     at 
org.apache.cayenne.di.spi.FieldInjectingProvider.value(FieldInjectingProvider.java:103)
     at 
org.apache.cayenne.di.spi.FieldInjectingProvider.injectMember(FieldInjectingProvider.java:68)
     at 
org.apache.cayenne.di.spi.FieldInjectingProvider.injectMembers(FieldInjectingProvider.java:59)
     at 
org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:44)
     at 
org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
     at 
org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:134)
     at 
org.apache.cayenne.configuration.CayenneRuntime.newContext(CayenneRuntime.java:124)
     at 
com.dbclientbase.DBClientBase.getObjectContext(DBClientBase.java:100)
     at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.apache.cayenne.di.DIRuntimeException: Invalid class: 
com.Database$Account
     at 
org.apache.cayenne.di.spi.DefaultAdhocObjectFactory.getJavaClass(DefaultAdhocObjectFactory.java:128)
     at org.apache.cayenne.util.Util.getJavaClass(Util.java:632)
     at org.apache.cayenne.map.ObjEntity.getJavaClass(ObjEntity.java:265)
     at 
org.apache.cayenne.map.EntityResolver.initCallbacks(EntityResolver.java:141)
     at 
org.apache.cayenne.map.EntityResolver.getCallbackRegistry(EntityResolver.java:163)
     at 
org.apache.cayenne.access.DataDomain.addListener(DataDomain.java:791)
     at 
org.apache.cayenne.access.DataDomain.addSyncFilter(DataDomain.java:748)
     at 
org.apache.cayenne.configuration.server.DataDomainProvider.createAndInitDataDomain(DataDomainProvider.java:188)
     at 
org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:117)
     ... 16 more
Caused by: java.lang.ClassNotFoundException: 
com.dbclientbase.Database.Account
     at 
java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
     at 
java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
     at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
     at java.base/java.lang.Class.forName0(Native Method)
     at java.base/java.lang.Class.forName(Class.java:398)
     at 
org.apache.cayenne.di.spi.DefaultAdhocObjectFactory.getJavaClass(DefaultAdhocObjectFactory.java:93)
     ... 24 more


Re: Cayenne and classpath question and help

Posted by Andrew Willerding <aw...@itsurcom.com>.
I'm not a JRebel user...

On 2019-10-17 7:02 a.m., Michael Gentry wrote:
> Hi Andrew,
>
> Are you using JRebel?  I seem to recall someone posting a solution here
> about using JRebel during development and getting the Cayenne stack to
> reload properly.
>
>
> On Wed, Oct 16, 2019 at 11:24 PM Andrew Willerding <aw...@itsurcom.com>
> wrote:
>
>> Hi,
>>
>> I have an application that dynamically loads jar files and reloads them
>> when they are changed.  Unfortunately I'm have an issue getting Cayenne
>> to see the classes inside one of these dynamically loaded jar files. I
>> have some test code that looks roughly like this.
>>
>> import com.dbclientbase.Database.Account;
>> public class blah
>>
>>     public testMethod(){
>>
>>               Account ac = new Account();  // This object instantiates
>> without an error so it's visible to app outside of Cayenne
>>
>>               ObjectContext oc = DBClientBase.getObjectContext(); // This
>> method generates the ServerRuntime and fails to get an ObjectContext to
>> work with (error below)
>>
>>    }
>> }
>>
>> The error output below seems to suggest that Cayenne cannot access the
>> Account class although I can successfully instantiate a non-Cayenne
>> object.  What can I do to ensure that Cayenne also has access to the
>> contents of a dynamically loaded and reloaded jar file?  I have found
>> references to AdhocObjectFactory.getClassLoader()  but I can't find any
>> examples on how to use it and I'm quite at a loss on how to even begin
>> use it.
>>
>> Thanks,
>>
>> Andrew
>>
>>
>> Exception==>org.apache.cayenne.configuration.server.DataDomainLoadException:
>>
>> [v.4.1.B2 May 04 2019 09:30:14] DataDomain startup failed: Invalid
>> class: com.dbclientbase.Database$Account
>>       at
>>
>> org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:123)
>>       at
>>
>> org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:60)
>>       at
>>
>> org.apache.cayenne.di.spi.CustomProvidersProvider.get(CustomProvidersProvider.java:39)
>>       at
>>
>> org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:43)
>>       at
>>
>> org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
>>       at
>>
>> org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:139)
>>       at
>>
>> org.apache.cayenne.di.spi.FieldInjectingProvider.value(FieldInjectingProvider.java:103)
>>       at
>>
>> org.apache.cayenne.di.spi.FieldInjectingProvider.injectMember(FieldInjectingProvider.java:68)
>>       at
>>
>> org.apache.cayenne.di.spi.FieldInjectingProvider.injectMembers(FieldInjectingProvider.java:59)
>>       at
>>
>> org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:44)
>>       at
>>
>> org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
>>       at
>>
>> org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:134)
>>       at
>>
>> org.apache.cayenne.configuration.CayenneRuntime.newContext(CayenneRuntime.java:124)
>>       at
>> com.dbclientbase.DBClientBase.getObjectContext(DBClientBase.java:100)
>>       at java.base/java.lang.Thread.run(Thread.java:834)
>> Caused by: org.apache.cayenne.di.DIRuntimeException: Invalid class:
>> com.Database$Account
>>       at
>>
>> org.apache.cayenne.di.spi.DefaultAdhocObjectFactory.getJavaClass(DefaultAdhocObjectFactory.java:128)
>>       at org.apache.cayenne.util.Util.getJavaClass(Util.java:632)
>>       at org.apache.cayenne.map.ObjEntity.getJavaClass(ObjEntity.java:265)
>>       at
>>
>> org.apache.cayenne.map.EntityResolver.initCallbacks(EntityResolver.java:141)
>>       at
>>
>> org.apache.cayenne.map.EntityResolver.getCallbackRegistry(EntityResolver.java:163)
>>       at
>> org.apache.cayenne.access.DataDomain.addListener(DataDomain.java:791)
>>       at
>> org.apache.cayenne.access.DataDomain.addSyncFilter(DataDomain.java:748)
>>       at
>>
>> org.apache.cayenne.configuration.server.DataDomainProvider.createAndInitDataDomain(DataDomainProvider.java:188)
>>       at
>>
>> org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:117)
>>       ... 16 more
>> Caused by: java.lang.ClassNotFoundException:
>> com.dbclientbase.Database.Account
>>       at
>>
>> java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
>>       at
>>
>> java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
>>       at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
>>       at java.base/java.lang.Class.forName0(Native Method)
>>       at java.base/java.lang.Class.forName(Class.java:398)
>>       at
>>
>> org.apache.cayenne.di.spi.DefaultAdhocObjectFactory.getJavaClass(DefaultAdhocObjectFactory.java:93)
>>       ... 24 more
>>
>>

Re: Cayenne and classpath question and help

Posted by Michael Gentry <bl...@gmail.com>.
Hi Andrew,

Are you using JRebel?  I seem to recall someone posting a solution here
about using JRebel during development and getting the Cayenne stack to
reload properly.


On Wed, Oct 16, 2019 at 11:24 PM Andrew Willerding <aw...@itsurcom.com>
wrote:

> Hi,
>
> I have an application that dynamically loads jar files and reloads them
> when they are changed.  Unfortunately I'm have an issue getting Cayenne
> to see the classes inside one of these dynamically loaded jar files. I
> have some test code that looks roughly like this.
>
> import com.dbclientbase.Database.Account;
> public class blah
>
>    public testMethod(){
>
>              Account ac = new Account();  // This object instantiates
> without an error so it's visible to app outside of Cayenne
>
>              ObjectContext oc = DBClientBase.getObjectContext(); // This
> method generates the ServerRuntime and fails to get an ObjectContext to
> work with (error below)
>
>   }
> }
>
> The error output below seems to suggest that Cayenne cannot access the
> Account class although I can successfully instantiate a non-Cayenne
> object.  What can I do to ensure that Cayenne also has access to the
> contents of a dynamically loaded and reloaded jar file?  I have found
> references to AdhocObjectFactory.getClassLoader()  but I can't find any
> examples on how to use it and I'm quite at a loss on how to even begin
> use it.
>
> Thanks,
>
> Andrew
>
>
> Exception==>org.apache.cayenne.configuration.server.DataDomainLoadException:
>
> [v.4.1.B2 May 04 2019 09:30:14] DataDomain startup failed: Invalid
> class: com.dbclientbase.Database$Account
>      at
>
> org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:123)
>      at
>
> org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:60)
>      at
>
> org.apache.cayenne.di.spi.CustomProvidersProvider.get(CustomProvidersProvider.java:39)
>      at
>
> org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:43)
>      at
>
> org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
>      at
>
> org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:139)
>      at
>
> org.apache.cayenne.di.spi.FieldInjectingProvider.value(FieldInjectingProvider.java:103)
>      at
>
> org.apache.cayenne.di.spi.FieldInjectingProvider.injectMember(FieldInjectingProvider.java:68)
>      at
>
> org.apache.cayenne.di.spi.FieldInjectingProvider.injectMembers(FieldInjectingProvider.java:59)
>      at
>
> org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:44)
>      at
>
> org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
>      at
>
> org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:134)
>      at
>
> org.apache.cayenne.configuration.CayenneRuntime.newContext(CayenneRuntime.java:124)
>      at
> com.dbclientbase.DBClientBase.getObjectContext(DBClientBase.java:100)
>      at java.base/java.lang.Thread.run(Thread.java:834)
> Caused by: org.apache.cayenne.di.DIRuntimeException: Invalid class:
> com.Database$Account
>      at
>
> org.apache.cayenne.di.spi.DefaultAdhocObjectFactory.getJavaClass(DefaultAdhocObjectFactory.java:128)
>      at org.apache.cayenne.util.Util.getJavaClass(Util.java:632)
>      at org.apache.cayenne.map.ObjEntity.getJavaClass(ObjEntity.java:265)
>      at
>
> org.apache.cayenne.map.EntityResolver.initCallbacks(EntityResolver.java:141)
>      at
>
> org.apache.cayenne.map.EntityResolver.getCallbackRegistry(EntityResolver.java:163)
>      at
> org.apache.cayenne.access.DataDomain.addListener(DataDomain.java:791)
>      at
> org.apache.cayenne.access.DataDomain.addSyncFilter(DataDomain.java:748)
>      at
>
> org.apache.cayenne.configuration.server.DataDomainProvider.createAndInitDataDomain(DataDomainProvider.java:188)
>      at
>
> org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:117)
>      ... 16 more
> Caused by: java.lang.ClassNotFoundException:
> com.dbclientbase.Database.Account
>      at
>
> java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
>      at
>
> java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
>      at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
>      at java.base/java.lang.Class.forName0(Native Method)
>      at java.base/java.lang.Class.forName(Class.java:398)
>      at
>
> org.apache.cayenne.di.spi.DefaultAdhocObjectFactory.getJavaClass(DefaultAdhocObjectFactory.java:93)
>      ... 24 more
>
>

Re: Cayenne and classpath question and help

Posted by Andrus Adamchik <an...@objectstyle.org>.
I suspect reloaded classes come through their own ClassLoader. So what mechanism are you using for dynamic reloading and what is the structure of class loaders?

You can control CL behavior via ClassLoaderManager which is an injectable service in Cayenne. By default it is implemented via DefaultClassLoaderManager, that looks up a CL like this:

  ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  if (classLoader == null) {
    classLoader = DefaultClassLoaderManager.class.getClassLoader();
  }

If you can figure out CLs structure in your app, you can either implement your own ClassLoaderManager, or set a proper thread class loader.

Andrus


> On Oct 16, 2019, at 11:24 PM, Andrew Willerding <aw...@itsurcom.com> wrote:
> 
> Hi,
> 
> I have an application that dynamically loads jar files and reloads them when they are changed.  Unfortunately I'm have an issue getting Cayenne to see the classes inside one of these dynamically loaded jar files. I have some test code that looks roughly like this.
> 
> import com.dbclientbase.Database.Account;
> public class blah
> 
>   public testMethod(){
> 
>             Account ac = new Account();  // This object instantiates without an error so it's visible to app outside of Cayenne
> 
>             ObjectContext oc = DBClientBase.getObjectContext(); // This method generates the ServerRuntime and fails to get an ObjectContext to work with (error below)
> 
>  }
> }
> 
> The error output below seems to suggest that Cayenne cannot access the Account class although I can successfully instantiate a non-Cayenne object.  What can I do to ensure that Cayenne also has access to the contents of a dynamically loaded and reloaded jar file?  I have found references to AdhocObjectFactory.getClassLoader()  but I can't find any examples on how to use it and I'm quite at a loss on how to even begin use it.
> 
> Thanks,
> 
> Andrew
> 
> 
> Exception==>org.apache.cayenne.configuration.server.DataDomainLoadException: [v.4.1.B2 May 04 2019 09:30:14] DataDomain startup failed: Invalid class: com.dbclientbase.Database$Account
>     at org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:123)
>     at org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:60)
>     at org.apache.cayenne.di.spi.CustomProvidersProvider.get(CustomProvidersProvider.java:39)
>     at org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:43)
>     at org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
>     at org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:139)
>     at org.apache.cayenne.di.spi.FieldInjectingProvider.value(FieldInjectingProvider.java:103)
>     at org.apache.cayenne.di.spi.FieldInjectingProvider.injectMember(FieldInjectingProvider.java:68)
>     at org.apache.cayenne.di.spi.FieldInjectingProvider.injectMembers(FieldInjectingProvider.java:59)
>     at org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:44)
>     at org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
>     at org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:134)
>     at org.apache.cayenne.configuration.CayenneRuntime.newContext(CayenneRuntime.java:124)
>     at com.dbclientbase.DBClientBase.getObjectContext(DBClientBase.java:100)
>     at java.base/java.lang.Thread.run(Thread.java:834)
> Caused by: org.apache.cayenne.di.DIRuntimeException: Invalid class: com.Database$Account
>     at org.apache.cayenne.di.spi.DefaultAdhocObjectFactory.getJavaClass(DefaultAdhocObjectFactory.java:128)
>     at org.apache.cayenne.util.Util.getJavaClass(Util.java:632)
>     at org.apache.cayenne.map.ObjEntity.getJavaClass(ObjEntity.java:265)
>     at org.apache.cayenne.map.EntityResolver.initCallbacks(EntityResolver.java:141)
>     at org.apache.cayenne.map.EntityResolver.getCallbackRegistry(EntityResolver.java:163)
>     at org.apache.cayenne.access.DataDomain.addListener(DataDomain.java:791)
>     at org.apache.cayenne.access.DataDomain.addSyncFilter(DataDomain.java:748)
>     at org.apache.cayenne.configuration.server.DataDomainProvider.createAndInitDataDomain(DataDomainProvider.java:188)
>     at org.apache.cayenne.configuration.server.DataDomainProvider.get(DataDomainProvider.java:117)
>     ... 16 more
> Caused by: java.lang.ClassNotFoundException: com.dbclientbase.Database.Account
>     at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
>     at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
>     at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
>     at java.base/java.lang.Class.forName0(Native Method)
>     at java.base/java.lang.Class.forName(Class.java:398)
>     at org.apache.cayenne.di.spi.DefaultAdhocObjectFactory.getJavaClass(DefaultAdhocObjectFactory.java:93)
>     ... 24 more
>