Issue Details (XML | Word | Printable)

Key: TOC-70
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: David Chui
Reporter: Jeff Turner
Votes: 2
Watchers: 2
Operations

If you were logged in you would be able to see more operations.
Confluence Table of Contents Macro

{toc} macro breaks when rendered in PDF export, activity stream plugin

Created: 17/Jul/08 08:49 PM   Updated: 22/Aug/08 01:34 AM
Component/s: {toc-zone}, {toc}
Affects Version/s: 2.4.5
Fix Version/s: 2.4.8

Time Tracking:
Not Specified

File Attachments: None
Image Attachments:

1. brokentoc.png
(13 kB)
Environment: Confluence 2.8.2, toc-plugin-2.4.5.jar (in $home/bundled-plugins)
Issue Links:
Cause
 

Labels:


 Description  « Hide
If I add a page to Confluence containing a {toc} macro, then when this addition is rendered in the activity stream, it breaks with a NullPointerException:

In the logs I get the stacktrace:

Unexpected error formatting macro: toc

java.lang.NullPointerException  at net.customware.confluence.plugin.toc.AbstractTOCMacro.execute(AbstractTOCMacro.java:567)     at
org.randombits.confluence.support.ConfluenceMacro.execute(ConfluenceMacro.java:54)      at
com.atlassian.renderer.v2.macro.ResourceAwareMacroDecorator.execute(ResourceAwareMacroDecorator.java:45)        at
com.atlassian.renderer.v2.components.MacroRendererComponent.executeMacro(MacroRendererComponent.java:297)       at
com.atlassian.renderer.v2.components.MacroRendererComponent.processMacro(MacroRendererComponent.java:255)       at
com.atlassian.renderer.v2.components.MacroRendererComponent.makeMacro(MacroRendererComponent.java:151)  at
com.atlassian.renderer.v2.components.WikiContentRendererHandler.handleMacro(WikiContentRendererHandler.java:18) at
com.atlassian.renderer.v2.WikiMarkupParser.makeMacro(WikiMarkupParser.java:126) at com.atlassian.renderer.v2.WikiMarkupParser.makeMacro(WikiMarkupParser.java:114)      at
com.atlassian.renderer.v2.WikiMarkupParser.handlePotentialMacro(WikiMarkupParser.java:99)       at com.atlassian.renderer.v2.WikiMarkupParser.parse(WikiMarkupParser.java:60)   at
com.atlassian.renderer.v2.components.MacroRendererComponent.render(MacroRendererComponent.java:47)      at com.atlassian.renderer.v2.V2Renderer.render(V2Renderer.java:53)      at
com.atlassian.renderer.v2.plugin.PluggableV2Renderer.render(PluggableV2Renderer.java:30)        at com.atlassian.renderer.v2.V2RendererFacade.convertWikiToXHtml(V2RendererFacade.java:57)
at sun.reflect.GeneratedMethodAccessor321.invoke(Unknown Source)        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)        at
java.lang.reflect.Method.invoke(Method.java:585)        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:296)   at
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:177)       at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)       at
com.atlassian.spring.interceptors.SpringProfilingInterceptor.invoke(SpringProfilingInterceptor.java:20) at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)       at
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)      at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)       at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)        at $Proxy46.convertWikiToXHtml(Unknown Source)  at
com.atlassian.confluence.renderer.DefaultWikiStyleRenderer.convertWikiToXHtml(DefaultWikiStyleRenderer.java:19) at
com.atlassian.studio.feed.RemoteChangeReport.<init>(RemoteChangeReport.java:38) at com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:124)   at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.RemoteChangeReportFactory.addReports(RemoteChangeReportFactory.java:155)      at
com.atlassian.studio.feed.RemoteChangeReportFactory.addChangeReports(RemoteChangeReportFactory.java:58) at
com.atlassian.studio.feed.ActivityFeedDelegator$1.doInTransaction(ActivityFeedDelegator.java:88)        at
org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:127)       at
com.atlassian.studio.feed.ActivityFeedDelegator.getRecentlyUpdatedEntities(ActivityFeedDelegator.java:69)       at
com.atlassian.studio.feed.ActivityFeedServlet.doGet(ActivityFeedServlet.java:26)        at javax.servlet.http.HttpServlet.service(HttpServlet.java:690) at
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)    at com.atlassian.plugin.descriptors.servlet.ServletModuleContainerServlet.service(ServletModuleContainerServlet.java:38)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)    at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)       at com.atlassian.confluence.util.LoggingContextFilter.doFilter(LoggingContextFilter.java:49)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)    at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)       at com.atlassian.seraph.filter.SecurityFilter.doFilter(SecurityFilter.java:192) at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)       at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)       at
....


 All   Comments   Work Log   Change History   FishEye   Crucible   Builds      Sort Order: Ascending order - Click to sort in descending order
Jeff Turner added a comment - 17/Jul/08 09:11 PM
The relevant code is AbstractTOCMacro.java, line 567. Basically the org.randombits.confluence.support.MacroInfo object's getRequestAttributes() method is returning null. Without source or javadocs it's hard to tell what the contract is.

David Peterson added a comment - 17/Jul/08 09:52 PM
Hi there,

The relevant class is in the 'confluence-support' library, in SVN here;

http://svn.atlassian.com/fisheye/browse/public/contrib/confluence/libraries/org.randombits.confluence/confluence-support/trunk

I'm not certain which version TOC is using - it may be somewhat out of date now - but current versions of the library look for the current HttpServletRequest using the ServletAssistant (also in that library). The ServletAssistant lets you register 'providers' which will look for the current Request, by default in two places - XWork's ServletActionContext and DWR's WebContextFactory. You can register other providers with it, so if the activity stream is rendering outside of one of those two locations, I would suggest implementing a 'Provider' and registering it with the ServletAssistant prior to rendering the activity stream.


Jeff Turner added a comment - 17/Jul/08 10:18 PM
Thanks for the source pointer. I see in RequestInfo.java that the javadoc for getRequestAttributes() states "This may be <code>null</code> if the HTTP request is not available in
the current context.". So if AbstractTOCMacro is not handling the null case, isn't that a bug? The toc macro does actually render (eg. see the screenshot) despite the NPE.

The ServletAssistant lets you register 'providers' which will look for the current Request, by default in two places - XWork's ServletActionContext and DWR's WebContextFactory. You can register other providers with it, so if the activity stream is rendering outside of one of those two locations, I would suggest implementing a 'Provider' and registering it with the ServletAssistant prior to rendering the activity stream.

I assume that the activity stream shouldn't have macro-specific code in it, eg. to implement a custom ServletAssistant provider


David Peterson added a comment - 17/Jul/08 10:46 PM
Yes, that's definitely true. TOC should handle the null case. I'm not sure how functional it will be if it doesn't have access to the request attributes, but that's probably a different issue.

Matt Ryall added a comment - 18/Aug/08 08:32 PM - edited
This bug also prevents PDF export with the TOC macro in Confluence 2.8 and later. Please review the priority of this issue accordingly.

http://jira.atlassian.com/browse/CONF-11795