[MGNLRES-210] Groovy as resources: Allow groovy in light modules as model classes Created: 08/Sep/15  Updated: 29/Mar/22  Resolved: 01/Mar/22

Status: Closed
Project: Magnolia Resources Module
Component/s: resourceLoaders
Affects Version/s: 2.4.1
Fix Version/s: None

Type: Story Priority: Neutral
Reporter: Christian Ringele Assignee: Unassigned
Resolution: Won't Do Votes: 8
Labels: devwl, pm
Remaining Estimate: 0d
Time Spent: 0.5d
Original Estimate: Not Specified

Attachments: PNG File Groovy-LinkModel.png    
Issue Links:
Relates
relates to MAGNOLIA-6378 Allow yaml based configuration to mak... Closed
relates to MTE-57 Add function library via Light Module Open
dependency
relation
Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Release notes required:
Yes
Documentation update required:
Yes
Date of First Response:
Story Points: 13
Team: Nucleus

 Description   

The new resource loading mechanism provides a lot of templating possibilities for light modules.
But a templater using a light module also get fast to a limit: Using Java for a model class.

The need for a model class is not the same Java scope as "real" back-end adaptions.
Often its not complex code, and mainly its very bound to the component/template itself.

We have a groovy implementation, but:
One needs to add a groovy script into the CMS (groovy script workspace) to be able to use it as a Module.
Which would lead to the need of a real JAr based module.

Suggestion:
1. Allow a groovy script to be directly added to a light module into the resources, see print screen "Groovy-LinkModel.png"
2. Add possibility that it can be defined directly in a Yaml file and can be executed by the system.

modelClass: travel-demo.templates.components.LinkModel

What we gain:
A pure light module template could get much further with this additional possibility.
It would open the door for a mixture that even with a light module you can do some 'back-end' coding.



 Comments   
Comment by Philipp Bärfuss [ 10/Dec/15 ]

It is not ultimately important that the files are loaded by the new resources API. It might be enough to make groovy files loadable for a the resources root path with its own mechanisms.

Comment by Michael Mühlebach [ 17/Dec/15 ]

This would actually be a good first step to migrate the groovy script to the new loading cascade. The issue is less the new API and more loading it from !JCR and the migration would reduce some of the uncertainty in this area.

Comment by Federico Grilli [ 29/Jan/16 ]

As I already tackled other Groovy issues which should eventually culminate in the ability to use Groovy files on the file system for light development, I gave this a try at https://git.magnolia-cms.com/projects/MODULES/repos/groovy/commits/93843e899da6f39158631fcbaca810b5f4fc3ab7
Basically I let info.magnolia.module.groovy.support.classes.MgnlGroovyResourceLoader (which implements groovy.lang.GroovyResourceLoader) do the job by simply adding the ability to load scripts from the FS and respecting the resources loading cascade (first JCR, then FS, finally class path [not sure though if FS should work only in dev mode]).

One problem I stumbled across is how to specify and resolve e.g. modelClasses in yaml files. So far, in JCR config we refer to Groovy scripts as normal Java classes, e.g. foo.bar.MyGroovyClass, that is by their fully-qualified class names.
Furthermore, we enforce scripts in JCR to have a package name reflecting the folder structure in which they reside. This is not only to keep consistency and avoid confusion if you want to replace a Java class with a Groovy counterpart but, most importantly, because without enforcing that package declaration the script would be compiled under the default package and the class loader would never find what we're looking for.

So here are some questions (and some possible answers):

Q1) How do we enforce devs to declare a valid package in their file system scripts?
A1) probably we can't :/

Q2) FS scripts are resolved relative to the magnolia.resources.dir. Say you have a module there called hello-magnolia and your script is under /hello-magnolia/scripts/MyModel.groovy. In order to be resolved correctly that script should declare a package hello-magnolia.scripts. However the hyphen sign - is not valid in a Java class package name and compilation would eventually fail. How can we solve this?
A2.1) In YAML prepend the class name with the module name, e.g. hello-magnolia:scripts/MyModel and ask devs to declare a package scripts? This would work when Map2Bean tries to resolve the class declared in a YAML config file but not when Magnolia tries to instantiate it (and check if a newer version of the class exists) when rendering a page because in that case what we'd get passed is a class binary name, e.g. script.GroovyModel and we'd miss the module name part hello-magnolia in order to resolve the path to the script on the FS.
A2.2) Discourage devs to use hyphenated module names cause in that case scripts would not work?

UPDATE
------------

  • The resolution of packages containing underscores _ instead of dashes - to circumvent Java's limitation in allowed characters for packages works fine.
    • Devs can use hyphenated module names but need to replace hyphens with underscores in their script's package names. MgnlGroovyResourceLoader will resolve the path to the script correctly
  • I tried to use the resource-loader API by injecting ResourceOrigin into MgnlGroovyResourceLoader. At the moment this doesn't work as GroovyClassLoader will start calling MgnlGroovyResourceLoader#loadGroovySource(String filename) at a very early stage during Magnolia startup when ResourceOrigin is not yet ready. Tried also to inject it as a Provider<ResourceOrigin> in c-tor or to use ioC at field and setter method level but to no avail.
Comment by Christopher Zimmermann [ 03/Feb/16 ]

From PM perspective, we can document that groovy loading from file system is only available if the module name has no hyphens. Accordingly we will change our samples/documentation/tutorials to use a convention without hyphens. It becomes the new convention.

Comment by Christopher Zimmermann [ 03/Feb/16 ]

From PM perspective, OK if we are not using the resources API as it appears that the functionality for the end user will be very good. For example if they change the script - those changes will be reflected when pages render (also when the definition which uses it changes) without having to restart the server.

Comment by Christopher Zimmermann [ 03/Feb/16 ]

Removed the 13 story point estimation, as Federico has a working POC with unit tests and feels it will be less work - from 3 to 5 story points.

Comment by Federico Grilli [ 18/Feb/16 ]

Story points take into account what was decided after the second arch meeting on the subject and which is summarised at https://jira.magnolia-cms.com/browse/DEV-124 (see comment section)

Comment by Christopher Zimmermann [ 13/Apr/16 ]

Please include me in review.

Comment by Michael Mühlebach [ 06/Jun/16 ]

btw: I found a good article to solve the one security issue: http://mrhaki.blogspot.ch/2014/04/groovy-goodness-restricting-script.html

I saw as well in the ScriptEngine API that we can have a custom class loader configuration to white and blacklist packages and even have a custom class loader itself.

Comment by Christopher Zimmermann [ 19/Jan/17 ]

Removed from Backlog because of new JS Models module covering similar requirement. I still see this enhancement as desirable, but with a lower urgency.

Generated at Mon Feb 12 06:48:28 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.