[MGNLUI-3755] Possible StackOverflow when DefinitionCloner tries to clone i18n proxies Created: 23/Nov/15  Updated: 15/Apr/16  Resolved: 25/Jan/16

Status: Closed
Project: Magnolia UI
Component/s: None
Affects Version/s: 5.4.3
Fix Version/s: 5.4.5

Type: Bug Priority: Critical
Reporter: Fabrizio Giustina Assignee: Roman Kovařík
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: 0d
Time Spent: 5h
Original Estimate: Not Specified

Issue Links:
dependency
is depended upon by MAGNOLIA-6234 TranslationService could use new Reso... Closed
supersession
is superseded by MGNLUI-3431 Replace usages of cloner in favor of ... Closed
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)
Bug DoR:
[ ]* Steps to reproduce, expected, and actual results filled
[ ]* Affected version filled
Sprint: Kromeriz 28
Story Points: 2

 Description   

Given the fact that I really wasn't able to realize why this only happens with some specific configured definition and not with others this problem really drived me nuts for a while...

Use case: I simply tried to use the action "move" in a custom content app. I simply configured the OpenMoveDialogAction which uses MoveDialogPresenterImpl. Although the same identical configuration seems to work in existing apps (e.g. works fine in the DAM app) when I tried it in my content app it consistently blowed up with a stack overflow exception with the following stack:

	at com.rits.cloning.Cloner.cloneObject(Cloner.java:463)
	at com.rits.cloning.Cloner.cloneInternal(Cloner.java:439)
	at com.rits.cloning.Cloner.cloneObject(Cloner.java:463)
	at com.rits.cloning.Cloner.cloneInternal(Cloner.java:439)
	at com.rits.cloning.Cloner.cloneObject(Cloner.java:463)
	at com.rits.cloning.Cloner.cloneInternal(Cloner.java:439)
	at com.rits.cloning.Cloner.cloneObject(Cloner.java:463)
	at com.rits.cloning.Cloner.cloneInternal(Cloner.java:439)
	at com.rits.cloning.Cloner.cloneObject(Cloner.java:463)
	at com.rits.cloning.Cloner.cloneInternal(Cloner.java:439)
	at com.rits.cloning.Cloner.cloneObject(Cloner.java:463)
	at com.rits.cloning.Cloner.cloneInternal(Cloner.java:439)
	at com.rits.cloning.Cloner.cloneObject(Cloner.java:463)
	at com.rits.cloning.Cloner.cloneInternal(Cloner.java:439)
	at com.rits.cloning.Cloner.cloneObject(Cloner.java:463)
	at com.rits.cloning.Cloner.cloneInternal(Cloner.java:439)
	at com.rits.cloning.Cloner.cloneObject(Cloner.java:463)
	at com.rits.cloning.Cloner.cloneInternal(Cloner.java:439)
	at com.rits.cloning.Cloner.cloneObject(Cloner.java:463)
        [... tons of identical rows]

even worst, most of the time the whole jvm crashed after this error.

It took a lot to debug it but I finally traced down the source of the problem in the clone done in MoveDialogPresenterImpl:

        ConfiguredWorkbenchDefinition workbenchDefinition = (ConfiguredWorkbenchDefinition) cloner
            .deepClone(subAppDescriptor.getWorkbench());

I double checked I had nothing strange in my workbench definition and I also tried making the configuration identical to the one in working apps but no way, the stack overflow error was always there.
I tried debugging the cloning process and at the end I traced down the problem to be in this part:

> cloning class java.lang.reflect.Method -- public abstract java.lang.Object info.magnolia.i18nsystem.I18nParentable.getI18nContextParent()
> cloning class info.magnolia.i18nsystem.proxytoys.FilteringMethodDecorator -- info.magnolia.i18nsystem.proxytoys.FilteringMethodDecorator@2b79e9a1
> cloning class info.magnolia.i18nsystem.proxytoys.I18nTextMethodDecorator -- info.magnolia.i18nsystem.proxytoys.I18nTextMethodDecorator@ae4a60c
> cloning class info.magnolia.i18nsystem.TranslationServiceImpl -- info.magnolia.i18nsystem.TranslationServiceImpl@225ad7ee
> cloning class info.magnolia.i18nsystem.DefaultMessageBundlesLoader -- info.magnolia.i18nsystem.DefaultMessageBundlesLoader@2f5dfa5d

The definitions configured are proxied by the i18n system so the clone also clones I18nParentable. It goes down to I18nTextMethodDecorator which in turns has references to

    private final TranslationService translationService;
    private final LocaleProvider localeProvider;
    private I18nKeyGenerator keyGenerator;

when those fields are reached the cloner now gets access to all the jackrabbit classes and somewhere to the classloader itself, trying to serialize and clone all the objects in the JVM :o

As said, I didn't understand why this is always happening on some situations and not other, I fear it may be due to the order of modules loaded or something not really predictable. Realized that, it seems that this could be fixed easily by adding:

        cloner.dontCloneInstanceOf(I18nParentable.class);

to info.magnolia.ui.contentapp.DefinitionCloner. I am now living with a patched version of definitionCloner to avoid this problem at all... do you have an opinion in adding this exclusion by default in definitionCloner? Or any other solution that could similarly avoid this kind of situation with i18n proxies?


Generated at Mon Feb 12 09:09:45 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.