[MAGNOLIA-3408] LinkUtil / FreeMarker Error with missing UUID links Created: 25/Nov/10  Updated: 09/Oct/12  Resolved: 22/Dec/10

Status: Closed
Project: Magnolia
Component/s: fckeditor, freemarker, templating
Affects Version/s: 4.3.8
Fix Version/s: 4.4.2, 4.5

Type: Bug Priority: Major
Reporter: Richard Unger Assignee: Federico Grilli
Resolution: Fixed Votes: 0
Labels: fckeditor, freemarker, rendering, uuid-links
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

This issue was observed under Windows 7, Tomcat 5.5.27 - but I don'zt think the environment is relevant


Attachments: PNG File missing-image-fck.png    
Issue Links:
relation
is related to MAGNOLIA-1720 Freemarker : process links (using Lin... Closed
is related to MAGNOLIA-1762 Improve links processing in freemarke... 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
Date of First Response:

 Description   

The current implementation of Link-Conversion cannot handle missing UUID links within rich-text fields.

When rendering paragraphs, the error simply causes the entire content of the rich-text field not to display at all.

When checking for existence (myfield??), an exception thrown by LinkUtil breaks template processing completely, resulting in a blank page.

This is a big problem for anyone using fckeditor...

Expected behaviour: render the link as "#", which will produce a dead link, but at least generate the normal output for the rest of the page.

To reproduce the problem:

Create a template which renders content from an fckEditor input.
Create a new image in DMS.
Create a page with your template, and insert the DMS-image in the FCKEditor content area.
Save the page, everything should display as expected.
Now go to DMS, and delete the image.
Reload the page, and your fckEditor field will not display.
Now insert a test for existence in the template (myeditorfield??).
Reload the page, and nothing will display (blank page).
Check the console or debug log, and you will see the exception.



 Comments   
Comment by Richard Unger [ 25/Nov/10 ]

The following is a stack-trace of the issue (in this case a test for existence with articleText?? ):

info.magnolia.module.templating.RenderException: Can't render template /lmcd/templates/main.ftl: LinkException: can't get node with uuid 00060890-0220-4544-b6a4-320325dcfd86 and repository dms
	at info.magnolia.module.templating.renderers.FreemarkerTemplateRenderer.onRender(FreemarkerTemplateRenderer.java:82)
	at info.magnolia.module.templating.AbstractRenderer.render(AbstractRenderer.java:86)
	at info.magnolia.module.templatingkit.renderers.STKTemplateRenderer.render(STKTemplateRenderer.java:88)
	at info.magnolia.module.templating.renderers.AbstractTemplateRenderer.renderTemplate(AbstractTemplateRenderer.java:77)
	at info.magnolia.module.templating.engine.DefaultRenderingEngine$RenderingHelper$2.render(DefaultRenderingEngine.java:108)
	at info.magnolia.module.templating.engine.DefaultRenderingEngine.render(DefaultRenderingEngine.java:171)
	at info.magnolia.module.templating.engine.DefaultRenderingEngine.render(DefaultRenderingEngine.java:130)
	at info.magnolia.module.templating.engine.DefaultRenderingEngine$$EnhancerByCGLIB$$76076e2d.render(<generated>)
	at info.magnolia.module.templating.RenderingFilter.render(RenderingFilter.java:132)
	at info.magnolia.module.templating.RenderingFilter.doFilter(RenderingFilter.java:92)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.BackwardCompatibilityFilter.doFilter(BackwardCompatibilityFilter.java:73)
	at info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:62)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.InterceptFilter.doFilter(InterceptFilter.java:121)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.AggregatorFilter.doFilter(AggregatorFilter.java:104)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.security.BaseSecurityFilter.doFilter(BaseSecurityFilter.java:64)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.RepositoryMappingFilter.doFilter(RepositoryMappingFilter.java:91)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.CompositeFilter.doFilter(CompositeFilter.java:64)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:76)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.CompositeFilter.doFilter(CompositeFilter.java:64)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.VirtualUriFilter.doFilter(VirtualUriFilter.java:133)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.module.cache.executor.Bypass.processCacheRequest(Bypass.java:57)
	at info.magnolia.module.cache.filter.CacheFilter.doFilter(CacheFilter.java:122)
	at info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:62)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.i18n.I18nContentSupportFilter.doFilter(I18nContentSupportFilter.java:75)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.module.extendedtemplatingkit.filters.MultiSiteFilter.doFilter(MultiSiteFilter.java:94)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.module.cache.filter.GZipFilter.doFilter(GZipFilter.java:83)
	at info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:62)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.security.BaseSecurityFilter.doFilter(BaseSecurityFilter.java:64)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.security.LogoutFilter.doFilter(LogoutFilter.java:88)
	at info.magnolia.cms.filters.OncePerRequestAbstractMgnlFilter.doFilter(OncePerRequestAbstractMgnlFilter.java:62)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.security.auth.login.LoginFilter.doFilter(LoginFilter.java:77)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.enterprise.registration.RegistrationFilter.doFilter(RegistrationFilter.java:51)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:84)
	at info.magnolia.cms.filters.CosMultipartRequestFilter.doFilter(CosMultipartRequestFilter.java:88)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.ContentTypeFilter.doFilter(ContentTypeFilter.java:102)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.ContextFilter.doFilter(ContextFilter.java:117)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlFilterChain.doFilter(MgnlFilterChain.java:82)
	at info.magnolia.cms.filters.CompositeFilter.doFilter(CompositeFilter.java:64)
	at info.magnolia.cms.filters.AbstractMgnlFilter.doFilter(AbstractMgnlFilter.java:70)
	at info.magnolia.cms.filters.MgnlMainFilter.doFilter(MgnlMainFilter.java:96)
	at info.magnolia.cms.filters.MgnlMainFilter.doFilter(MgnlMainFilter.java:199)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:875)
	at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
	at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
	at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.RuntimeException: Failed to parse links in website:/exportinitiative/Branchen--und-Laenderinformationen/TEST_Kategorie_-_NAME/Exportinitiative_oeffnet_Tueren_zu_neuen_Zielmaerkten/artikel/artikelText[String]
	at info.magnolia.freemarker.models.NodeDataModelFactory.create(NodeDataModelFactory.java:84)
	at freemarker.ext.beans.BeansModelCache.create(BeansModelCache.java:45)
	at freemarker.ext.util.ModelCache.getInstance(ModelCache.java:115)
	at freemarker.ext.beans.BeansWrapper.wrap(BeansWrapper.java:468)
	at freemarker.template.DefaultObjectWrapper.handleUnknownType(DefaultObjectWrapper.java:144)
	at freemarker.template.DefaultObjectWrapper.wrap(DefaultObjectWrapper.java:128)
	at info.magnolia.freemarker.models.MagnoliaObjectWrapper.wrap(MagnoliaObjectWrapper.java:88)
	at info.magnolia.freemarker.models.ContentModel.get(ContentModel.java:115)
	at freemarker.core.Dot._getAsTemplateModel(Dot.java:76)
	at freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
	at freemarker.core.ExistsExpression._getAsTemplateModel(ExistsExpression.java:71)
	at freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
	at freemarker.core.Expression.isTrue(Expression.java:138)
	at freemarker.core.AndExpression.isTrue(AndExpression.java:68)
	at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:77)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.MixedContent.accept(MixedContent.java:92)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:79)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.IteratorBlock$Context.runLoop(IteratorBlock.java:179)
	at freemarker.core.Environment.visit(Environment.java:417)
	at freemarker.core.IteratorBlock.accept(IteratorBlock.java:102)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.MixedContent.accept(MixedContent.java:92)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.IfBlock.accept(IfBlock.java:82)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.MixedContent.accept(MixedContent.java:92)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.ConditionalBlock.accept(ConditionalBlock.java:79)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.MixedContent.accept(MixedContent.java:92)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.Environment.include(Environment.java:1483)
	at freemarker.core.Include.accept(Include.java:169)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.MixedContent.accept(MixedContent.java:92)
	at freemarker.core.Environment.visit(Environment.java:210)
	at freemarker.core.Environment.process(Environment.java:190)
	at freemarker.template.Template.process(Template.java:237)
	at info.magnolia.freemarker.FreemarkerHelper.render(FreemarkerHelper.java:148)
	at info.magnolia.module.templating.renderers.FreemarkerTemplateRenderer.onRender(FreemarkerTemplateRenderer.java:75)
	... 100 more
Caused by: info.magnolia.link.LinkException: Failed to create link with uuid 00060890-0220-4544-b6a4-320325dcfd86 and repository dms and fallbackhandle 
	at info.magnolia.link.LinkFactory.createLink(LinkFactory.java:192)
	at info.magnolia.link.LinkUtil.convertLinksFromUUIDPattern(LinkUtil.java:156)
	at info.magnolia.link.LinkUtil.convertLinksFromUUIDPattern(LinkUtil.java:169)
	at info.magnolia.freemarker.models.NodeDataModelFactory.create(NodeDataModelFactory.java:81)
	... 142 more
Caused by: info.magnolia.link.LinkException: can't get node with uuid 00060890-0220-4544-b6a4-320325dcfd86 and repository dms
	at info.magnolia.link.LinkFactory.createLink(LinkFactory.java:94)
	at info.magnolia.link.LinkFactory.createLink(LinkFactory.java:183)
	... 145 more
Comment by Richard Unger [ 25/Nov/10 ]

I think this problem is linked with these two issues.

Comment by Philipp Bärfuss [ 17/Dec/10 ]

We definitely have to fix this as a broken link should not affect/fail the rendering.

Comment by Federico Grilli [ 22/Dec/10 ]

I was not able to reproduce the issue on a live Magnolia instance: it seems to have gone with 4.4. This screenshot shows what I get for a missing image referred to in the fckEditor field. It correctly displays a broken image both in the page and in the dialog. Rendering of the page and of the dialog is not broken at all. Looking at the provided stacktrace it seems that somehow you ended up in a situation where eventually this code was called info.magnolia.link.LinkFactory.createLink('00060890-0220-4544-b6a4-320325dcfd86', 'dms', '', null, null, null, null) where the fallbackhandle parameter (the third one) was either null or empty, hence a RepositoryException was caught and rethrown as a LinkException. This seems not to be the case anymore as fallbackhandle was never empty in my tests. If we want to be on the safe side we could just create an undefined info.magnolia.link.Link in the catch block for RepositoryException as it actually happens for the PathNotFoundException.

Comment by Jan Haderka [ 17/Jan/11 ]

Wouldn't it be better to generate invalid link based on the nonexistent handle instead? This would allow to use broken link detection tools to find out such broken links. Generating # links just hides the problem.

Comment by Federico Grilli [ 17/Jan/11 ]

Makes sense. I'm going to change that.

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