Uploaded image for project: 'PUBLIC - Liferay Portal Community Edition'
  1. PUBLIC - Liferay Portal Community Edition
  2. LPS-79550

Taglib will break after redeploy when used inside freemarker

    Details

      Description

      Steps to reproduce:

      1. Add blogs portlet to the page.

      2. Add a blog entry.

      3. Check the social bookmarks are displayed in the list view.

      4. Open the portlet configuration and change the display template to 'card'.

      5. Redeploy the module 'modules/apps/collaboration/social/social-bookmarks-taglib' ('gradle clean deploy').

      6. Refresh the page.

       

      Expected: Nothing changes and everything is displayed the same way.

      Actual: A Freemarker error appears (see below).

       

      The problem seems to be that the old instance of the social bookmarks tag is still being run, causing a null pointer exception here.

      If you open the gogo shell and stop&start the module 'Liferay Portal Template FreeMarker' the problem goes away. Which seems to be somehow releasing that old instance and using the new one.

      Caused by: java.lang.NullPointerException
      	at com.liferay.social.bookmarks.taglib.internal.servlet.ServletContextUtil.getServletContext(ServletContextUtil.java:31)
      	at com.liferay.social.bookmarks.taglib.servlet.taglib.SocialBookmarksTag.setPageContext(SocialBookmarksTag.java:74)
      	at freemarker.ext.jsp.TagTransformModel.getWriter(TagTransformModel.java:64)
      	... 233 more
      
      
      An error occurred while processing the template.
      Error while invoking the "bookmarks" JSP custom tag; see cause exception
      
      ----
      FTL stack trace ("~" means nesting-related):
      	- Failed at: @liferay_social_bookmarks["bookmarks"...  [in template "20100#20136#36405" at line 189, column 73]
      ----
      1<div class="widget-mode-card row"> 
      2	<#if entries?has_content> 
      3		<#list entries as curBlogEntry> 
      4			<#if curBlogEntry.getCoverImageURL(themeDisplay)??> 
      5				<#assign cardImage = true /> 
      6			<#else> 
      7				<#assign cardImage = false /> 
      8			</#if> 
      9 
      10			<div class="col-lg-4"> 
      11				<div class="card"> 
      12					<#if cardImage> 
      13						<div class="card-header"> 
      14							<div class="aspect-ratio aspect-ratio-8-to-3"> 
      15								<img alt="thumbnail" class="aspect-ratio-item-center-middle aspect-ratio-item-fluid" src="${curBlogEntry.getCoverImageURL(themeDisplay)}"> 
      16							</div> 
      17						</div> 
      18					</#if> 
      19 
      20					<div class="card-body widget-topbar"> 
      21						<div class="autofit-row card-title"> 
      22							<div class="autofit-col autofit-col-expand"> 
      23								<#assign viewEntryPortletURL = renderResponse.createRenderURL() /> 
      24 
      25								${viewEntryPortletURL.setParameter("mvcRenderCommandName", "/blogs/view_entry")} 
      26 
      27								<#if validator.isNotNull(curBlogEntry.getUrlTitle())> 
      28									${viewEntryPortletURL.setParameter("urlTitle", curBlogEntry.getUrlTitle())} 
      29								<#else> 
      30									${viewEntryPortletURL.setParameter("entryId", curBlogEntry.getEntryId()?string)} 
      31								</#if> 
      32 
      33								<a class="title-link" href="${viewEntryPortletURL.toString()}"> 
      34									<h3 class="title">${blogsEntryUtil.getDisplayTitle(resourceBundle, curBlogEntry)}</h3> 
      35								</a> 
      36							</div> 
      37 
      38							<div class="autofit-col visible-interaction"> 
      39								<div class="dropdown dropdown-action"> 
      40									<@liferay_ui["icon-menu"] 
      41										direction="left-side" 
      42										icon="" 
      43										markupView="lexicon" 
      44										message="" 
      45										showWhenSingleIcon=true 
      46									> 
      47										<#if blogsEntryPermission.contains(permissionChecker, curBlogEntry, "UPDATE")> 
      48											<#assign editEntryPortletURL = renderResponse.createRenderURL() /> 
      49 
      50											${editEntryPortletURL.setWindowState(windowStateFactory.getWindowState("MAXIMIZED"))} 
      51											${editEntryPortletURL.setParameter("mvcRenderCommandName", "/blogs/edit_entry")} 
      52											${editEntryPortletURL.setParameter("redirect", currentURL)} 
      53											${editEntryPortletURL.setParameter("entryId", curBlogEntry.getEntryId()?string)} 
      54 
      55											<@liferay_ui["icon"] 
      56												label=true 
      57												message="edit" 
      58												url=editEntryPortletURL.toString() 
      59											/> 
      60										</#if> 
      61										<#if blogsEntryPermission.contains(permissionChecker, curBlogEntry, "PERMISSIONS")> 
      62											<#assign permissionsEntryURL = permissionsURLTag.doTag(null, "com.liferay.blogs.model.BlogsEntry", blogsEntryUtil.getDisplayTitle(resourceBundle, curBlogEntry), curBlogEntry.getGroupId()?string, curBlogEntry.getEntryId()?string, windowStateFactory.getWindowState("POP_UP").toString(), null, request) /> 
      63 
      64											<@liferay_ui["icon"] 
      65												label=true 
      66												message="permissions" 
      67												method="get" 
      68												url=permissionsEntryURL 
      69												useDialog=true 
      70											/> 
      71										</#if> 
      72										<#if blogsEntryPermission.contains(permissionChecker, curBlogEntry, "DELETE")> 
      73											<#assign deleteEntryPortletURL = renderResponse.createActionURL() /> 
      74 
      75											${deleteEntryPortletURL.setParameter("javax.portlet.action", "/blogs/edit_entry")} 
      76 
      77											${deleteEntryPortletURL.setParameter("cmd", trashHelper.isTrashEnabled(themeDisplay.getScopeGroupId())?then("move_to_trash", "delete"))} 
      78											${deleteEntryPortletURL.setParameter("redirect", currentURL)} 
      79											${deleteEntryPortletURL.setParameter("entryId", curBlogEntry.getEntryId()?string)} 
      80 
      81											<@liferay_ui["icon-delete"] 
      82												label=true 
      83												trash=trashHelper.isTrashEnabled(themeDisplay.getScopeGroupId()) 
      84												url=deleteEntryPortletURL.toString() 
      85											/> 
      86										</#if> 
      87									</@> 
      88								</div> 
      89							</div> 
      90						</div> 
      91 
      92						<div class="autofit-row widget-metadata"> 
      93							<div class="autofit-col inline-item-before"> 
      94								<@liferay_ui["user-portrait"] 
      95									userId=curBlogEntry.userId 
      96									userName=curBlogEntry.userName 
      97								/> 
      98							</div> 
      99 
      100							<div class="autofit-col autofit-col-expand"> 
      101								<div class="autofit-row"> 
      102									<div class="autofit-col autofit-col-expand"> 
      103										<#if serviceLocator??> 
      104											<#assign 
      105												userLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.UserLocalService") 
      106 
      107												entryUser = userLocalService.fetchUser(curBlogEntry.getUserId()) 
      108											/> 
      109 
      110											<#if entryUser?? && !entryUser.isDefaultUser()> 
      111												<#assign entryUserURL = entryUser.getDisplayURL(themeDisplay) /> 
      112											</#if> 
      113										</#if> 
      114 
      115										<a href="${(entryUserURL?? && validator.isNotNull(entryUserURL))?then(entryUserURL, "")}" class="username">${curBlogEntry.getUserName()}</a> 
      116 
      117										<div> 
      118											${dateUtil.getDate(curBlogEntry.getStatusDate(), "dd MMM", locale)} 
      119 
      120											<#if serviceLocator??> 
      121												<#assign 
      122													assetEntryLocalService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetEntryLocalService") 
      123 
      124													assetEntry = assetEntryLocalService.getEntry("com.liferay.blogs.model.BlogsEntry", curBlogEntry.getEntryId()) 
      125												/> 
      126 
      127												<#if blogsPortletInstanceConfiguration.enableViewCount()> 
      128													- <@liferay_ui["message"] arguments=assetEntry.getViewCount() key=(assetEntry.getViewCount()==0)?then("x-view", "x-views") /> 
      129												</#if> 
      130											</#if> 
      131										</div> 
      132									</div> 
      133								</div> 
      134							</div> 
      135						</div> 
      136 
      137						<#if cardImage> 
      138							<p class="widget-resume">${stringUtil.shorten(htmlUtil.stripHtml(curBlogEntry.getContent()), 150)}</p> 
      139						<#else> 
      140							<p class="widget-resume">${stringUtil.shorten(htmlUtil.stripHtml(curBlogEntry.getContent()), 400)}</p> 
      141						</#if> 
      142					</div> 
      143 
      144					<div class="card-footer"> 
      145						<div class="card-row"> 
      146							<div class="autofit-row autofit-row-center autofit-float widget-toolbar"> 
      147								<#if blogsPortletInstanceConfiguration.enableComments()> 
      148									<div class="autofit-col"> 
      149										<#assign viewCommentsPortletURL = renderResponse.createRenderURL() /> 
      150 
      151										${viewCommentsPortletURL.setParameter("mvcRenderCommandName", "/blogs/view_entry")} 
      152										${viewCommentsPortletURL.setParameter("scroll", renderResponse.getNamespace() + "discussionContainer")} 
      153 
      154										<#if validator.isNotNull(curBlogEntry.getUrlTitle())> 
      155											${viewCommentsPortletURL.setParameter("urlTitle", curBlogEntry.getUrlTitle())} 
      156										<#else> 
      157											${viewCommentsPortletURL.setParameter("entryId", curBlogEntry.getEntryId()?string)} 
      158										</#if> 
      159 
      160										<a class="btn btn-outline-borderless btn-outline-secondary btn-sm" href="${viewCommentsPortletURL.toString()}"> 
      161											<span class="inline-item inline-item-before"> 
      162												<@clay["icon"] symbol="comments" /> 
      163											</span> ${commentManager.getCommentsCount("com.liferay.blogs.model.BlogsEntry", curBlogEntry.getEntryId())} 
      164										</a> 
      165									</div> 
      166								</#if> 
      167 
      168								<#if blogsPortletInstanceConfiguration.enableRatings()> 
      169									<div class="autofit-col"> 
      170										<@liferay_ui["ratings"] 
      171											className="com.liferay.blogs.model.BlogsEntry" 
      172											classPK=curBlogEntry.getEntryId() 
      173										/> 
      174									</div> 
      175								</#if> 
      176 
      177								<div class="autofit-col autofit-col-end"> 
      178									<#assign bookmarkURL = renderResponse.createRenderURL() /> 
      179 
      180									${bookmarkURL.setWindowState(windowStateFactory.getWindowState("NORMAL"))} 
      181									${bookmarkURL.setParameter("mvcRenderCommandName", "/blogs/view_entry")} 
      182 
      183									<#if validator.isNotNull(curBlogEntry.getUrlTitle())> 
      184										${bookmarkURL.setParameter("urlTitle", curBlogEntry.getUrlTitle())} 
      185									<#else> 
      186										${bookmarkURL.setParameter("entryId", curBlogEntry.getEntryId()?string)} 
      187									</#if> 
      188 
      189									<@liferay_social_bookmarks["bookmarks"] 
      190										className="com.liferay.blogs.model.BlogsEntry" 
      191										classPK=curBlogEntry.getEntryId() 
      192										displayStyle="menu" 
      193										target="_blank" 
      194										title=blogsEntryUtil.getDisplayTitle(resourceBundle, curBlogEntry) 
      195										types=blogsPortletInstanceConfiguration.socialBookmarksTypes() 
      196										url=portalUtil.getCanonicalURL(bookmarkURL.toString(), themeDisplay, themeDisplay.getLayout()) 
      197									/> 
      198								</div> 
      199							</div> 
      200						</div> 
      201					</div> 
      202				</div> 
      203			</div> 
      204		</#list> 
      205	</#if> 
      206</div> 

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Days since last comment:
                  1 year, 34 weeks, 6 days ago

                  Packages

                  Version Package
                  7.0.0 DXP FP63
                  7.0.X
                  7.1.0 Beta 1
                  7.1.X
                  Master