When you try to connect a class with a model using the function defineClass or findClass URLClassLoader (or your own implementation of ClassLoader 'a), an exception occurs. Please help me figure it out. Any other methods load the model but do not allow the class to be overloaded dynamically (at the request of the administrator).

 @Table("accounts") @BelongsToParents({ @BelongsTo(parent = Customer.class, foreignKeyName = "Customer"), @BelongsTo(parent = Currency.class, foreignKeyName = "Currency") }) public class Account extends Document{ public static DocFields prepareDocument(...){ ... fields = new ...(getTableName()); ... } ... } public abstract class Document extends Model{ public static DocFields prepareDocument(Session session){ return null; } ... } public class DynCLoader extends ClassLoader { public DynCLoader(ClassLoader parentClass) { super(parentClass); } @Override public Class<?> loadClass(String className) throws ClassNotFoundException { if(StrFuncs.isEmpty(className)){ throw new ClassNotFoundException("Ошибка в модуле DynCLoader, в функцие loadClass. Детали: className is empty"); } try { ... if(...){ // Загрузка нового, неопределенного класса Class<?> clazz; try{ String url = "file:"+...+".class"; URL myUrl = new URL(url); URLConnection connection = myUrl.openConnection(); InputStream input = connection.getInputStream(); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int data = input.read(); while(data != -1){ buffer.write(data); data = input.read(); } input.close(); byte[] classData = buffer.toByteArray(); clazz = defineClass(className, classData, 0, classData.length); ... return clazz; } catch (FileNotFoundException ex) { clazz = Class.forName(className); ... return clazz; } catch (MalformedURLException ex) { ... return null; } catch (Throwable ex) { try{ clazz = Class.forName(className, true, this); return clazz; } catch(ClassNotFoundException oErr){ ... } ... return null; } } else if(...) // Загрузка системного класса return Class.forName(className); else{ return Class.forName(className, true, this); } } catch (ClassNotFoundException ex) { throw ex; } } } 

Log of work:

 [main] INFO org.javalite.activejdbc.DB - Opened connection: com.mysql.jdbc.JDBC4Connection@49fd9b [main] INFO org.javalite.activejdbc.ConnectionsAccess - Attached connection named: default: to current thread: com.mysql.jdbc.JDBC4Connection@49fd9b. Extra info: jdbc:mysql://127.0.0.1:3306/*** [main] INFO org.javalite.activejdbc.Configuration - Load models from: file:/***/Product/***/Server/target/classes/activejdbc_models.properties [main] INFO org.javalite.activejdbc.Configuration - Load models from: file:/***/Kernel/Server/target/classes/activejdbc_models.properties [main] INFO org.javalite.activejdbc.Registry - Registered model: class kz.mwb.qupris.server.data.model.Account *** [main] INFO org.javalite.activejdbc.Registry - Registered model: class kz.mwb.qupris.server.data.model.User *** [main] INFO org.javalite.activejdbc.Registry - Fetched metadata for table: accounts *** [main] INFO org.javalite.activejdbc.Registry - Fetched metadata for table: usertable *** [main] INFO org.javalite.activejdbc.MetaModel - Association found: Customer ----------< Account, type: has-many [main] INFO org.javalite.activejdbc.MetaModel - Association found: Account >---------- Customer, type: belongs-to *** [main] INFO org.javalite.activejdbc.cache.QueryCache - MISS, "SELECT * FROM *** WHERE *** *** [Thread-20] INFO org.javalite.activejdbc.DB - Opened connection: com.mysql.jdbc.JDBC4Connection@1db686 [Thread-20] INFO org.javalite.activejdbc.ConnectionsAccess - Attached connection named: default: to current thread: com.mysql.jdbc.JDBC4Connection@1db686. Extra info: jdbc:mysql://127.0.0.1:3306/*** [Thread-20] INFO org.javalite.activejdbc.LazyList - Query: "SELECT * FROM *** WHERE ***, took: 5 milliseconds *** 00:42:52 > 34 > UserLib > ERROR > java.lang.reflect.InvocationTargetException 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 kz.mwb.qupris.server.tool.loader.Include.processMethod(Include.java:111) at kz.mwb.qupris.server.userlib.doDoc.initMod(doDoc.java:59) 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 kz.mwb.qupris.server.tool.loader.Include.processMethod(Include.java:111) at kz.mwb.qupris.server.tool.loader.Include.EvalFunction(Include.java:31) at kz.mwb.qupris.server.engine.ModEngine.MProcess(ModEngine.java:133) at kz.mwb.qupris.server.engine.ModEngine.IProcess(ModEngine.java:85) at kz.mwb.qupris.server.engine.ModEngine.XProcess(ModEngine.java:203) at kz.mwb.qupris.server.engine.Task.ProcessRequest(Task.java:396) at kz.mwb.qupris.server.engine.Task.GateWayLine(Task.java:162) at kz.mwb.qupris.server.engine.Task.ConnectToGateWay(Task.java:326) at kz.mwb.qupris.server.engine.Task.run(Task.java:61) at java.lang.Thread.run(Unknown Source) Caused by: org.javalite.activejdbc.DBException: failed to find metamodel for class kz.mwb.qupris.server.data.model.Account. Are you sure that a corresponding table exists in DB? at org.javalite.activejdbc.Registry.getTableName(Registry.java:414) at org.javalite.activejdbc.ModelDelegate.tableNameOf(ModelDelegate.java:326) at kz.mwb.qupris.server.data.model.Account.getTableName(Account.java:2831) at kz.mwb.qupris.server.data.model.Account.prepareDocument(Account.java:23) ... 20 more 
  • provide the minimum working code: model, interaction with database, class loading. It's difficult to say something without them - Artem Konovalov
  • Made changes to the text of the question. - Sergey Khodusov
  • error in the logs that was not found in the database - Are you sure that the corresponding table exists in DB? - Artem Konovalov
  • It's not a DB. The same table opens successfully if I use Class.forName or loadClass of the standard ClassLoader. Other classes written by me and using the database have been working and working for many years, namely <? extends Model> classes do not work. The problem most likely lies somewhere in the ActiveJdbc toolkit, which does not tighten MetaData if the kernel and modules have different environment directories. In my case, KERNEL is JAR, MODULES is a directory with class files. - Sergey Khodusov
  • Added a detailed log with the progress of the process by which it is clear that everything was "good", until the kernel tried to connect the module. - Sergey Khodusov

2 answers 2

Rewrote the getTableName function in MetaModels.java and it all worked!

 String getTableName(Class<? extends Model> modelClass) { MetaModel mm = null; for (Map.Entry<Class<? extends Model>, MetaModel> entry : metaModelsByClass.entrySet()){ if(modelClass.getName().equals(entry.getKey().getName())) mm = entry.getValue(); } return mm == null ? null : mm.getTableName(); } 

Old code:

 String getTableName(Class<? extends Model> modelClass) { MetaModel mm = metaModelsByClass.get(modelClass); return mm == null ? null : mm.getTableName(); } 

I suggest not to use the class as a key or change the logic of choice.

The same question was duplicated in the English version of stackoverflow, where among the respondents is the developer ActiveJdbc. I think the issue will be resolved soon.

    The developer answered (translated from English):

    It was a small bug in the framework associated with loading the model with another ClassLoader. A fix was suggested by the initiator, an issue was created: https://github.com/javalite/activejdbc/issues/570 and already solved.

    You can get the latest snapshot with fix here: http://repo.javalite.io/org/javalite/activejdbc/2.0-SNAPSHOT/