{"id":19317,"date":"2015-05-01T01:48:56","date_gmt":"2015-04-30T20:18:56","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=19317"},"modified":"2016-05-03T12:10:37","modified_gmt":"2016-05-03T06:40:37","slug":"compile-groovyscript-at-runtime-allow-caching-of-compiled-source-to-avoid-recompilation-at-runtime-using-groovyclassloader","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/compile-groovyscript-at-runtime-allow-caching-of-compiled-source-to-avoid-recompilation-at-runtime-using-groovyclassloader\/","title":{"rendered":"Compile GroovyScript at Runtime and allow caching of compiled source to avoid recompilation at Runtime using GroovyClassLoader"},"content":{"rendered":"<p>In some cases we need mechanism to provide compilation of groovy script at runtime. But at the same time we need to make sure it doesn&#8217;t consume the JVM to perform compilation every time when we try to access that script. Hence to perform this we need to do the following task :<\/p>\n<ol>\n<li>Compile Groovy Script at Runtime.<\/li>\n<li>Cache the compiled source to avoid recompilation.<\/li>\n<li>Make sure script get recompiled when any changes are performed over the script.<\/li>\n<\/ol>\n<p>Interestingly GroovyClassLoader provide loading of groovy script and parsing of class and GroovyCodeSource provide caching of source so that we don&#8217;t need to recompile it every time until and unless there are any changes over script from last compilation.<\/p>\n<p><em><strong>Solution for point 1 and 2 :<\/strong><\/em><\/p>\n<div id=\"attachment_19318\" style=\"width: 785px\" class=\"wp-caption alignleft\"><a href=\"\/blog\/wp-ttn-blog\/uploads\/2015\/04\/Screen-Shot-2015-04-30-at-11.28.24-am.png\"><img aria-describedby=\"caption-attachment-19318\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-19318\" src=\"\/blog\/wp-ttn-blog\/uploads\/2015\/04\/Screen-Shot-2015-04-30-at-11.28.24-am.png\" alt=\"Usage of GroovyClassLoader and GroovyCodeSource\" width=\"775\" height=\"197\" \/><\/a><p id=\"caption-attachment-19318\" class=\"wp-caption-text\">getScriptClass method using GroovyClassLoader and GroovyCodeSource for script compilation<\/p><\/div>\n<p>GroovyCodeSource <em>setCachaeble(true)<\/em> led to caching of compiled script, and when class loader parseClass is being called it check for source is set to cacheable or not, if yes then it fetch the source from cache instead of performing recompilation.<br \/>\n<em><br \/>\n<strong>Solution for point 3 :<\/strong><\/em><\/p>\n<p>Important thing to note down : Argument <em>codeSourceName<\/em> in <em>getScriptClass(&#8230;)<\/em> method.<\/p>\n<p>When GroovyClassLoader <em>parseClass<\/em> is being called then it will look for whether resource is cacheable or not, if yes then it will use the codeSourceName to fetch the cached compiled script from cache. Hence here codeSourceName will act as a key for compiled cached script.<\/p>\n<p><code>String codeSourceName = \"_${someKey}\" + \"_${scriptHashCode}\"<\/code><\/p>\n<p>Hence one of the solutions is that you need to generate the hash of GroovyScript and use it as a codeSourceName because whenever there are any changes over the script, the hash got changed for the script which led to recompilation of it, as GroovyClassLoader won&#8217;t able to find the script with that hash over a cache.<\/p>\n<p><em><strong>Edit : 1<\/strong><\/em><\/p>\n<p>In Solution 1, as we are providing example while creating new instance of\u00a0GroovyClassLoader, at that\u00a0time I was doing implementation and I didn&#8217;t dig deep to see the sourceCache was not grails global level cache it was Map maintained over GroovyClassLoader, hence\u00a0it doesn&#8217;t benefit us with\u00a0cache over next call of getScriptClass as it will reinitialize the cache\u00a0due to which\u00a0we changed the implementation and use single bean of GroovyClassLoader.<\/p>\n<p>We have created our CustomGrailsAwareClassLoader singleton bean which extends GrailsAwareClassLoader which further extends GroovyClassLoader. So that we can benefit from\u00a0the cache for the\u00a0script that\u00a0was compiled earlier.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In some cases we need mechanism to provide compilation of groovy script at runtime. But at the same time we need to make sure it doesn&#8217;t consume the JVM to perform compilation every time when we try to access that script. Hence to perform this we need to do the following task : Compile Groovy [&hellip;]<\/p>\n","protected":false},"author":20,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":58},"categories":[7],"tags":[118,1769,4840,9,1770,1771],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/19317"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=19317"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/19317\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=19317"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=19317"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=19317"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}