템플렛을 가공하고 있는 동안 과실은 일어났다.
The following has evaluated to null or missing:
==> portletPreferencesXML  [in template "20116#20152#511011" at line 136, column 18]

----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: #if portletPreferencesXML.selectSingl...  [in template "20116#20152#511011" at line 136, column 13]
----
1<#-- 
2Application display templates can be used to modify the look of a 
3specific application. 
4 
5Please use the left panel to quickly add commonly used variables. 
6Autocomplete is also available and can be invoked by typing "${". 
7--> 
8 
9<#assign JournalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService")> 
10<#assign LayoutLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.LayoutLocalService")> 
11<#assign PortletPreferencesLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.PortletPreferencesLocalService")/> 
12<#assign PropertyFactoryUtil = serviceLocator.findService("com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil") /> 
13<#assign DynamicQueryFactoryUtil = serviceLocator.findService("com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil") /> 
14 
15<#assign GroupLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.GroupLocalService")> 
16<#assign virtualHostLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.VirtualHostLocalService") /> 
17 
18<#assign portletId = themeDisplay.getPortletDisplay().getId()> 
19<#assign PortletPreferencesLocalService = serviceLocator.findService("com.liferay.portal.kernel.service.PortletPreferencesLocalService")/> 
20 
21<#-- 
227.4 Upgrade Start - portlet perferences would not be stored as xml, see https://github.com/liferay/liferay-portal/blob/master/readme/BREAKING_CHANGES.markdown#what-changed-11 
23<#assign portletPreferencesXML = saxReaderUtil.read((PortletPreferencesLocalService.getPortletPreferences(themeDisplay.getPlid(), portletId)?first).getPreferences())> 
24--> 
25 
26<#assign plid = themeDisplay.getPlid()> 
27 
28<#assign portletPreferences = PortletPreferencesLocalService.getPortletPreferences(plid, portletId)?first /> 
29 
30<#assign preferences = PortletPreferencesLocalService.fetchPreferences(portletPreferences.getCompanyId(), portletPreferences.getOwnerId(), portletPreferences.getOwnerType(), plid, portletId) /> 
31 
32<#-- 
337.4 Upgrade end 
34--> 
35 
36<#assign TemplateCustomService = serviceLocator.findService("template.custom.services.TemplateCustomService") /> 
37 
38<#-- Macro used to get specific field text from an Asset Entry --> 
39<#function entryNode article field> 
40	<#assign document = saxReaderUtil.read(article.getContent())> 
41	<#if document.selectSingleNode("/root/dynamic-element[@name='"+field+"']/dynamic-content")??> 
42	    <#return document.selectSingleNode("/root/dynamic-element[@name='"+field+"']/dynamic-content").getText()> 
43	<#else> 
44		<#return ""> 
45	</#if> 
46</#function> 
47 
48<#-- Macro used to get specific portlet preference --> 
49<#macro preference prefKey defaultValue> 
50	<#if portletPreferencesXML.selectSingleNode("/portlet-preferences/preference[name='"+prefKey+"']/value")??> 
51    "${portletPreferencesXML.selectSingleNode("/portlet-preferences/preference[name='"+prefKey+"']/value").getText()?js_string}"<#return> 
52	<#else> 
53    "${defaultValue?js_string}"<#return> 
54	</#if> 
55</#macro> 
56 
57<div id="bioGrid_${portletId}" class="atk-container"> 
58 
59<#if entries?has_content> 
60 
61<!-- update name here if change asset library name --> 
62<#assign assetLibGroup = GroupLocalService.getGroup(themeDisplay.getCompanyId(), "Kearney Global Asset Library") /> 
63 
64<div class="atk-row bio-grid-row"> 
65 
66	<#if entries?size <= 2>     
67		<#list entries as curEntry> 
68 
69			<#assign jArt = JournalArticleLocalService.getLatestArticle(curEntry.getClassPK())> 
70			<#assign articleGroup = GroupLocalService.getGroup(jArt.getGroupId()) 
71				guestGroup = GroupLocalService.getFriendlyURLGroup(articleGroup.getCompanyId(), "/guest") /> 
72			<#assign document = saxReaderUtil.read(jArt.getContentByLocale(themeDisplay.getLocale()))> 
73			<#assign friendlyURL = TemplateCustomService.getArticleViewURL(jArt.getArticleId(),assetLibGroup,jArt.getGroupId(),themeDisplay,guestGroup.getGroupId())/>	 
74 
75            <#assign headshot = TemplateCustomService.getDocumentURL(document,"CutoutHeadshot",themeDisplay)/> 
76            <#assign fullName = entryNode(jArt, "FullName") 
77                title = entryNode(jArt, "Title") /> 
78 
79            <#assign usePositionOverTitle = preferences.getValue("usePositionOverTitle", "false")> 
80            <#if usePositionOverTitle == "true"> 
81                <#assign title = entryNode(jArt, "Position") /> 
82            </#if>             
83 
84            <#if headshot != "" && fullName != "" && title != ""> 
85                <div class="d-6-col t-4-col p-6-col after-30-px-phone normalize-partial-width"> 
86                    <a href="${friendlyURL}"> 
87                        <div class="atk-row article-square-bio"> 
88                            <div class="d-2-col t-2-col p-2-col" style="overflow-y:hidden"> 
89                                <img class="bioGridPhoto" style="width:100%;" src="${headshot}" /> 
90                            </div> 
91                            <div class="d-4-col t-2-col p-4-col"> 
92                                <div class="heading4 bold-text after-10-px black-text">${fullName}</div> 
93                                <div class="body regular-text black-text after-0-px">${title}</div> 
94                            </div> 
95                        </div> 
96                    </a> 
97                </div> 
98            </#if> 
99 
100		</#list> 
101         
102 
103	<#else> 
104 
105		<#assign index = 1> 
106 
107		<#list entries as curEntry> 
108 
109			<#assign jArt = JournalArticleLocalService.getLatestArticle(curEntry.getClassPK())> 
110			<#assign document = saxReaderUtil.read(jArt.getContentByLocale(themeDisplay.getLocale()))> 
111			<#assign articleGroup = GroupLocalService.getGroup(jArt.getGroupId()) 
112				guestGroup = GroupLocalService.getFriendlyURLGroup(articleGroup.getCompanyId(), "/guest") /> 
113			<#assign friendlyURL = TemplateCustomService.getArticleViewURL(jArt.getArticleId(),assetLibGroup,jArt.getGroupId(),themeDisplay,guestGroup.getGroupId())/>	 
114					 
115			<#assign bioContainerClass = "d-3-col t-4-col p-6-col normalize-partial-width"> 
116 
117            <#if index != entries?size> 
118                <#assign bioContainerClass = bioContainerClass + " after-30-px-phone"> 
119            </#if> 
120 
121            <#if 2 <= entries?size - index> 
122                <#assign bioContainerClass = bioContainerClass + " after-30-px-tablet"> 
123            </#if> 
124 
125			<#if index % 4 == 0 && entries?size != 5> 
126				<#assign bioContainerClass = bioContainerClass + " d-nrp"> 
127			</#if> 
128 
129			<#if index % 2 == 0> 
130				<#assign bioContainerClass = bioContainerClass + " t-nrp"> 
131			</#if> 
132            <#assign headshot = TemplateCustomService.getDocumentURL(document,"CutoutHeadshot",themeDisplay)/> 
133            <#assign fullName = entryNode(jArt, "FullName") 
134                title = entryNode(jArt, "Title") /> 
135 
136            <#if portletPreferencesXML.selectSingleNode("/portlet-preferences/preference[name='usePositionOverTitle']/value")?? && 
137            portletPreferencesXML.selectSingleNode("/portlet-preferences/preference[name='usePositionOverTitle']/value").getText() == "true"> 
138                <#assign title = entryNode(jArt, "Position") /> 
139            </#if> 
140 
141            <#if headshot != "" && fullName != "" && title != ""> 
142                <div class="${bioContainerClass}"> 
143                    <a href="${friendlyURL}"> 
144                        <div class="atk-row"> 
145                            <div class="d-2-col t-2-col p-2-col" style="overflow-y:hidden"> 
146                                <img class="bioGridPhoto" style="width:100%;" src="${headshot}" /> 
147                            </div> 
148                            <div class="d-hidden t-2-col p-4-col"> 
149                                <div class="heading4 bold-text after-5-px black-text">${fullName}</div> 
150                                <div class="body regular-text black-text">${title}</div> 
151                            </div> 
152                        </div> 
153 
154                        <div class="atk-row tp-hidden"> 
155                            <div class="heading4 bold-text black-text fullNameHalfHighlight" style="margin-top:20px;margin-bottom: -15px" id="${curEntry.getClassPK()}"></div> 
156 
157                        </div> 
158                        <div class="atk-row tp-hidden"> 
159                            <div class="body regular-text black-text">${title}</div> 
160                        </div> 
161                    </a> 
162                </div> 
163 
164                <script> 
165                    ATK.React.Component.YellowHalfHighlight('${curEntry.getClassPK()}', 'heading4', '', '${friendlyURL}', '${fullName}'); 
166                </script> 
167 
168                <#if (index % 4 == 0 && entries?size != 5 && entries?size != 4) || (entries?size == 5 && index == 3)> 
169                    </div><div class="atk-row" style="padding-top:30px"> 
170                </#if> 
171                <#assign index = index + 1> 
172            </#if> 
173 
174		</#list> 
175 
176	</#if> 
177</div> 
178</#if> 
179 
180</div> 
181 
182<script> 
183 
184 
185 
186    var sizePhotos = function() { 
187        $('.bioGridPhoto').each(function() { 
188            if ($(this)[0].clientWidth < $(this)[0].clientHeight) { 
189                $(this).css('margin-top', (($(this)[0].clientWidth - $(this)[0].clientHeight) / 2) + 'px') 
190                        .css('margin-bottom', (($(this)[0].clientWidth - $(this)[0].clientHeight) / 2) + 'px'); 
191
192        }); 
193
194 
195    sizePhotos(); 
196 
197    window.addEventListener('resize', function () { 
198        if (window.innerWidth < 1024) { 
199            sizePhotos(); 
200
201    }); 
202 
203</script>