However, packaging this class in jar file and placing it in runtime/lib isn't
working. Unless I create a new war that packages this jar file also in its
WEB-INF/lib, this ResourceReference isnt getting loaded. So, eachtime there is
a change in the implementation of DBResourceReference, I need to first package
it in jar and then in war, which is a little painful. Moreover, in my opinion
it beats the purpose of ability to deploy one time and continuously just
develop - meaning there is a clear separation of moqui framework and custom
application libraries.
This behaviour is because of
Class rrClass = this.getClass().getClassLoader().loadClass(rrNode."@class")
in ResourceFacadeImpl.groovy. This allows only war file class loader to be
used for loading resource reference implementations, which I think is quite
limiting. Instead if we can use a classloader which is a child of the war
classloader and has the list of jars and classes of each component, then this
limitation is eliminated.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I guess this choice could be a well-thought out decision. I am trying to
understand the rationale behind it, but was not able to find more reasons than
probably security concerns. If the thought process behind this choice is
shared, it would be very helpful.
Thanks
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for commenting on this Vasanth. This was an oversight and related to
another bug recently fixed related to classpath resources accessed through the
ResourceFacade.
This is fixed in the trunk in commit 909a67d.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I downloaded the latest version and verified it to be 909a67d. I ran my test
app against the war built with this version and am still seeing the same
problem cropping up. On investigating a little bit, I noticed that, in
ExecutionContextImpl, initClassLoader() is being called after
ResourceFacadeImpl is created. I am guessing, this is the reason why
ResourceFacadeImpl throws a ClassNotFoundException. To confirm my inference, I
refactored initClassLoader and extracted a method that adds lib and classes to
the classloader. I invoked this method in ExecutionContextImpl just before
instantiating any *FacadeImpl. With this change, my custom
ResourceReferenceImpl is getting loaded without requiring to package in a jar
and then in the war.
As I do not understand fully, the consequences of this change, but suspect it
to be an unintended bug, I am posting my finding.
Thanks
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for testing this Vasanth. I looked into it a little more and I don't
see any reason to delay the ClassLoader init. I originally put it after the
init of the ResourceFacade, but they can (and as you point out should) by
initialized earlier.
Currently they need to be initialized after components are loaded, though for
a few reasons components cannot currently be on the classpath anyway.
This should be fixed as of commit a834fec.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
What is the test case you are using... this isn't happening for me locally.
I see from that code that what you're saying is correct, but I'm wondering
what sort of component configuration you're using and such that causes this to
happen.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I spent a few more minutes testing and working on this, and basically the
ClassLoader setup and ResourceFacade init had to be split up.
As of commit 1d41e91 the code should be much more flexible, and OOTB
everything loads and runs fine again.
The one constraint is that I couldn't figure out a way around is to allow a
component's location to depend on a ResourceReference implementation that is
in another component. Otherwise, ResourceReference, ScriptRunner and
TemplateRenderer implementations can be in components.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
a component's location should not depend on a Resource Reference
implementation in another component
is an acceptable constraint. In my opinion, documenting this limitation and
moving on, should be good enough for now vis-a-vis making class loading more
complex.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have implemented a custom ResourceReference Implementation
(DBResourceReference) and am looking for a painless way of configuring it.
I have added
However, packaging this class in jar file and placing it in runtime/lib isn't
working. Unless I create a new war that packages this jar file also in its
WEB-INF/lib, this ResourceReference isnt getting loaded. So, eachtime there is
a change in the implementation of DBResourceReference, I need to first package
it in jar and then in war, which is a little painful. Moreover, in my opinion
it beats the purpose of ability to deploy one time and continuously just
develop - meaning there is a clear separation of moqui framework and custom
application libraries.
This behaviour is because of
in ResourceFacadeImpl.groovy. This allows only war file class loader to be
used for loading resource reference implementations, which I think is quite
limiting. Instead if we can use a classloader which is a child of the war
classloader and has the list of jars and classes of each component, then this
limitation is eliminated.
I guess this choice could be a well-thought out decision. I am trying to
understand the rationale behind it, but was not able to find more reasons than
probably security concerns. If the thought process behind this choice is
shared, it would be very helpful.
Thanks
Thanks for commenting on this Vasanth. This was an oversight and related to
another bug recently fixed related to classpath resources accessed through the
ResourceFacade.
This is fixed in the trunk in commit 909a67d.
I downloaded the latest version and verified it to be 909a67d. I ran my test
app against the war built with this version and am still seeing the same
problem cropping up. On investigating a little bit, I noticed that, in
ExecutionContextImpl, initClassLoader() is being called after
ResourceFacadeImpl is created. I am guessing, this is the reason why
ResourceFacadeImpl throws a ClassNotFoundException. To confirm my inference, I
refactored initClassLoader and extracted a method that adds lib and classes to
the classloader. I invoked this method in ExecutionContextImpl just before
instantiating any *FacadeImpl. With this change, my custom
ResourceReferenceImpl is getting loaded without requiring to package in a jar
and then in the war.
As I do not understand fully, the consequences of this change, but suspect it
to be an unintended bug, I am posting my finding.
Thanks
Thanks for testing this Vasanth. I looked into it a little more and I don't
see any reason to delay the ClassLoader init. I originally put it after the
init of the ResourceFacade, but they can (and as you point out should) by
initialized earlier.
Currently they need to be initialized after components are loaded, though for
a few reasons components cannot currently be on the classpath anyway.
This should be fixed as of commit a834fec.
Now I get a NullPointerException.
init of ClassLoader uses ResourceFacade (Line No.281)
Due to this, startup fails. I think, this part of Classloader init should be
called only after ResourceFacadeImpl is init_ed_.
Thanks
What is the test case you are using... this isn't happening for me locally.
I see from that code that what you're saying is correct, but I'm wondering
what sort of component configuration you're using and such that causes this to
happen.
Nevermind... it does happen with no changes or add-ons...
I spent a few more minutes testing and working on this, and basically the
ClassLoader setup and ResourceFacade init had to be split up.
As of commit 1d41e91 the code should be much more flexible, and OOTB
everything loads and runs fine again.
The one constraint is that I couldn't figure out a way around is to allow a
component's location to depend on a ResourceReference implementation that is
in another component. Otherwise, ResourceReference, ScriptRunner and
TemplateRenderer implementations can be in components.
It works now.
Also, I think the constraint that
is an acceptable constraint. In my opinion, documenting this limitation and
moving on, should be good enough for now vis-a-vis making class loading more
complex.