Rendering slot contents

Hi

I’m trying to render the contents of a slot that doesn’t exist on the page. I have a homepage with a featured news slot and the same slot on the news and event page. I only want the users to update the homepage and the news and events page will automatically be updated.

I’ve written a macro to do this and all works fine apart from rendering the actual template.

#macro(get_slot_contents_by_ID $id $slotname $header $before $after $footer)

	#set($guid = $user.psoObjectFinder.getGuidById($id,'1'))
	#set($node = $user.psoObjectFinder.getNodeByGuid($guid))
	#set($clone = $sys.assemblyItem.clone())
    $clone.setNode($node)

	#set($results = $user.psoSlotTools.getSlotContents($clone,$slotname,$params))
	#if($tools.math.toInteger($results.size()) > 0)##
		$header##
		#foreach( $relresult in $results )##
			$relresult
		$footer##
		#end
	#end##
#end

The “$relresult” is the correct assembly item but when I use $rx.doc.extractBody to render the template I get the follow error in the console.log file:

2009-06-03 12:53:57,897 ERROR [PSVelocityAssembler] Problem assembling output for item: 1-101-94167 with template: intranetPgNewsEvents
java.lang.NullPointerException
	at java.io.ByteArrayInputStream.<init>(Unknown Source)
	at com.percussion.services.assembly.jexl.PSDocumentUtils.extractBody(Unknown Source)
	at sun.reflect.GeneratedMethodAccessor931.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.apache.velocity.util.introspection.UberspectImpl$VelMethodImpl.invoke(UberspectImpl.java:267)
	at org.apache.velocity.runtime.parser.node.ASTMethod.execute(ASTMethod.java:197)
	at org.apache.velocity.runtime.parser.node.ASTReference.execute(ASTReference.java:175)
	at org.apache.velocity.runtime.parser.node.ASTReference.render(ASTReference.java:220)
	at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:55)
	at org.apache.velocity.runtime.directive.Foreach.render(Foreach.java:166)
	at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:114)
	at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:55)
	at org.apache.velocity.runtime.parser.node.ASTIfStatement.render(ASTIfStatement.java:70)
	at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:230)
	at org.apache.velocity.runtime.directive.VelocimacroProxy.render(VelocimacroProxy.java:172)
	at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:114)
	at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:230)
	at org.apache.velocity.Template.merge(Template.java:256)
	at com.percussion.services.assembly.impl.plugin.PSVelocityAssembler.assembleSingle(Unknown Source)
	at com.percussion.services.assembly.impl.plugin.PSAssemblerBase.doAssembleSingle(Unknown Source)
	at com.percussion.services.assembly.impl.plugin.PSVelocityAssembler.doAssembleSingle(Unknown Source)
	at com.percussion.services.assembly.impl.plugin.PSAssemblerBase$_b.super(Unknown Source)
	at com.percussion.services.assembly.impl.plugin.PSAssemblerBase$_b.call(Unknown Source)
	at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at com.percussion.services.assembly.impl.plugin.PSAssemblerBase.assemble(Unknown Source)
	at com.percussion.services.assembly.impl.PSAssemblyService.assemble(Unknown Source)
	at sun.reflect.GeneratedMethodAccessor240.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:203)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:162)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:209)
	at $Proxy90.assemble(Unknown Source)
	at com.percussion.services.assembly.impl.plugin.PSDispatchAssembler.assembleSingle(Unknown Source)
	at com.percussion.services.assembly.impl.plugin.PSAssemblerBase.doAssembleSingle(Unknown Source)
	at com.percussion.services.assembly.impl.plugin.PSAssemblerBase$_b.super(Unknown Source)
	at com.percussion.services.assembly.impl.plugin.PSAssemblerBase$_b.call(Unknown Source)
	at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at com.percussion.services.assembly.impl.plugin.PSAssemblerBase.assemble(Unknown Source)
	at com.percussion.services.assembly.impl.PSAssemblyService.assemble(Unknown Source)
	at com.percussion.services.assembly.impl.PSAssemblyService.processServletRequest(Unknown Source)
	at sun.reflect.GeneratedMethodAccessor312.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
	at $Proxy90.processServletRequest(Unknown Source)
	at com.percussion.services.assembly.impl.PSAssemblyServlet.service(Unknown Source)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
	at com.percussion.webdav.PSWebDavRequestFilter.doFilter(Unknown Source)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
	at com.percussion.servlets.PSSecurityFilter.doFilter(Unknown Source)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
	at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:81)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
	at org.jboss.web.tomcat.security.CustomPrincipalValve.invoke(CustomPrincipalValve.java:39)
	at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:159)
	at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:59)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
	at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
	at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
	at java.lang.Thread.run(Unknown Source)

Any clues?

Cheers
James

James,

Is there any reason why you are calling getGuidById($id,‘1’) ? You are specifying revision 1. As you know, GUIDs come in 2 forms: revision specific and revision independent.

It seems to me that you want the revision independent one in this case. You obtain this with getGuidById($id) rather than the method you are calling.

Of course, this may not have anything to do with your problem.

Dave

Hi Dave

Thanks for the pointer and you’re right it had nothing to do with the issue :slight_smile:

Cheers
James

A workaround could be to just get the content IDs of the items in the slot, and build a JSR-170 query that searches for anything (FROM nt:base) with those content IDs (WHERE rx:sys_contentid = $relresult.Id.UUID OR rx:sys_contentid = $nextrelresult.Id.UUID OR …)

Have you tried using this macro?

#slotItem($relresult)

It’s a macro that’s in the sys_resources/vm directory

I do something similar in my templates, and this works for me.

Hi, James.

You may have resolved this problem already, but in case you haven’t, I’m going to outline a technique that’s worked well for me when I’ve had content items

on which I’ve wanted to render slot or slots belonging to another content item. The technique is not very efficient or elegant, but it works.

In your case, the slot belongs to the home page, and the rendering context is a news page. I’m assuming that the home page and the news page are different content types with different page templates. For this example, I’ll call their content types home_page and news_page and their templates home_page_P and news_page_P; I’ll call the slot on home_page_P events_slot.

First, create a dummy (placeholder) slot. For this example, the name of the slot will be dummy_slot. Set the content finder to sys_AutoSlotContentFinder and

leave the allowed content field empty.

Create a macro in the User Velocity Macros file (rx_assembly.vm) that renders the item(s) in events_slot. For this example, the name of the macro will be

render_slot_item. Call render_slot_item from home_page_P. The contents of render_slot_item could just be #slot(“events_slot” “” “” “” “” “”).

Next, create a snippet template. For this example, the name of the snippet template will be dummy_template_S. The sole purpose of dummy_template_S is to call the macro render_slot_item. So, the contents of dummy_template_S should just be #render_slot_item(). The allowed content type for dummy_template_S should be home_page.

Now, create another macro (say, render_slot_item_from_node). The code for the macro should be:

#macro(render_slot_item_from_node)
#set($dummy_params = "template=dummy_template_S&max_results=1")
#set($combined_dummy_params = $rx.asmhelper.combine($sys.params,$dummy_params))
#set($combined_dummy_params.query = "select rx:sys_contentid, rx:sys_folderid from home_page where rx:sys_contentid = 'home_page_id'")
#slot("dummy_slot" "" "" "" "" $combined_dummy_params)
#end

Call render_slot_item_from_node from news_page_P. The output should be identical to what the macro render_slot_item produces on home_page_P.

You can make render_slot_item_from_node much more generic if you wish (pass in content IDs, content types, locales, templates, et cetera). For example, the following code finds an item’s parent and renders a template from the context of that parent. Note that dummy_reverse_slot uses PSOReverseSlotContentFinder for its content finder.

#macro(render_slot_item_from_node $slotname $template)
#get_parent_slot($slotname)
#set($node_id = $node.getProperty('rx:sys_contentid').String)
#set($contenttype = "$node.getPrimaryNodeType().getName().substring(3)" )
#set($dummy_params = "template=$template&max_results=1&locale=$locale")
#set($combined_dummy_params = $rx.asmhelper.combine($sys.params,$dummy_params))
#set($combined_dummy_params.query = "select rx:sys_contentid, rx:sys_folderid from $contenttype where rx:sys_contentid = '$node_id'")
#slot("dummy_slot" "" "" "" "" $combined_dummy_params)
#end

#macro(get_parent_slot $slotname)
#set($reverse_params = "template=TitleLink_S&max_results=1&source_slot=$slotname")
#set($reverse_params_query = $rx.asmhelper.combine($sys.params,$reverse_params))
#set($node = $user.psoSlotTools.getSlotContents($sys.assemblyItem,"dummy_reverse_slot",$reverse_params_query).get(0).Node )
#end

One improvement would be for the code to let you skip the creation of dummy_template_S, but I think you can only render templates, not standalone macros, with this technique.

Anyway, post an update here if you can get your macro working, since it’s a more direct approach than what I’ve been using.