An error occurred while processing the template.
Java method "com.liferay.portal.json.JSONFactoryImpl.createJSONObject(String)" threw an exception when invoked on com.liferay.portal.json.JSONFactoryImpl object "com.liferay.portal.json.JSONFactoryImpl@2ad66ae2"; see cause exception in the Java stack trace.

----
FTL stack trace ("~" means nesting-related):
	- Failed at: navigationJSONObject = jsonFactoryUti...  [in template "17855804202317#32484267#LEARN-ARTICLE-NAV" at line 4, column 9]
----
1<#assign 
2	groupFriendlyURL = themeDisplay.getScopeGroup().getFriendlyURL() 
3	groupPathFriendlyURLPublic = themeDisplay.getPathFriendlyURLPublic() + groupFriendlyURL 
4	navigationJSONObject = jsonFactoryUtil.createJSONObject(navigation.getData()) 
5	navigationMenuItems = 
6
7			"Analytics Cloud": { 
8				"image": "/documents/d${groupFriendlyURL}/analytics_c-svg", 
9				"title": "Analytics Cloud", 
10				"url": "analytics-cloud" 
11			}, 
12			"Commerce": { 
13				"image": "/documents/d${groupFriendlyURL}/commerce_product-svg", 
14				"title": "Commerce", 
15				"url": "commerce" 
16			}, 
17			"DXP": { 
18				"image": "/documents/d${groupFriendlyURL}/dxp_p-svg", 
19				"title": "DXP / Portal", 
20				"url": "dxp" 
21			}, 
22			"Liferay Cloud": { 
23				"image": "/documents/d${groupFriendlyURL}/dxp_c-svg", 
24				"title": "Liferay Cloud", 
25				"url": "liferay-cloud" 
26			}, 
27			"Reference": { 
28				"image": "/documents/d${groupFriendlyURL}/reference-svg", 
29				"title": "Reference", 
30				"url": "reference" 
31
32
33 
34	breadcrumbJSONArray = navigationJSONObject.getJSONArray("breadcrumb") 
35	childrenJSONArray = navigationJSONObject.getJSONArray("children") 
36	parentJSONObject = navigationJSONObject.getJSONObject("parent") 
37	productJSONObject = breadcrumbJSONArray.getJSONObject(breadcrumbJSONArray.length()-1)!navigationJSONObject.getJSONObject("self") 
38	siblingsJSONArray = navigationJSONObject.getJSONArray("siblings") 
39/> 
40 
41<div class="learn-article-nav"> 
42	<#if productJSONObject?has_content && productJSONObject.getString("title")?has_content && navigationMenuItems[productJSONObject.getString("title")]?has_content && navigationMenuItems[productJSONObject.getString("title")].title?has_content> 
43		<div 
44			class="dropdown learn-article-nav-root learn-dropdown" 
45
46			<div class="learn-article-nav-item"> 
47				<div class="d-flex"> 
48					<div class="learn-article-nav-image"> 
49						<img 
50							class="lexicon-icon lexicon-icon-caret-bottom product-icon" 
51							role="presentation" 
52							src='${navigationMenuItems[productJSONObject.getString("title")].image}' 
53							viewBox="0 0 512 512" 
54						/> 
55					</div> 
56 
57					<span class="learn-article-nav-text">${navigationMenuItems[productJSONObject.getString("title")].title}</span> 
58				</div> 
59 
60				<div id="dropdown-icon"> 
61					<svg 
62						class="lexicon-icon lexicon-icon-caret-bottom" 
63						role="presentation" 
64						viewBox="0 0 512 512" 
65
66						<use xlink:href="/o/admin-theme/images/clay/icons.svg#caret-bottom"></use> 
67					</svg> 
68				</div> 
69			</div> 
70 
71			<ul class="dropdown-menu learn-dropdown-menu"> 
72				<#list navigationMenuItems as key, value> 
73					<li> 
74						<a 
75							class="dropdown-item learn-article-nav-item" 
76							href="/w/${navigationMenuItems[key].url}/index" 
77							tabindex="4" 
78
79							<span class="d-flex"> 
80								<span class="learn-article-nav-image"> 
81									<img 
82										class="lexicon-icon lexicon-icon-caret-bottom product-icon mt-0 mr-2" 
83										role="presentation" 
84										src="${value.image}"height: 25px; margin-left: 5px; max-width: none; width: 25px; 
85										viewBox="0 0 512 512" 
86									/> 
87								</span> 
88								<span class="learn-article-nav-text">${value.title}</span> 
89							</span> 
90 
91							<#if navigationMenuItems[productJSONObject.getString("title")].url == value.url> 
92								<span> 
93									<@clay["icon"] symbol="check" /> 
94								</span> 
95							</#if> 
96						</a> 
97					</li> 
98				</#list> 
99			</ul> 
100		</div> 
101	</#if> 
102 
103	<div class="learn-article-nav-content"> 
104		<#if parentJSONObject?has_content && parentJSONObject.getString("url")?has_content> 
105			<div class="learn-article-nav-item learn-article-nav-parent liferay-nav-item p-2"> 
106				<div class="mr-2"> 
107					<a 
108						href='${parentJSONObject.getString("url")}' 
109
110						<svg 
111							class="lexicon-icon lexicon-icon-angle-left" 
112							role="presentation" 
113							viewBox="0 0 512 512" 
114
115							<use xlink:href="/o/admin-theme/images/clay/icons.svg#angle-left"></use> 
116						</svg> 
117					</a> 
118				</div> 
119 
120				<span>${parentJSONObject.getString("title")}</span> 
121			</div> 
122		</#if> 
123 
124		<#if childrenJSONArray.length() gt 0> 
125			<ul class="m-0 p-2"> 
126				<#list 0..childrenJSONArray.length()-1 as i> 
127					<li class="learn-article-nav-item"> 
128						<a 
129							class='liferay-nav-item ${(navigationJSONObject.getJSONObject("self").url == childrenJSONArray.getJSONObject(i).url)?then("selected", "")}' 
130							href="${childrenJSONArray.getJSONObject(i).url}" 
131
132							<span>${childrenJSONArray.getJSONObject(i).getString("title")}</span> 
133						</a> 
134					</li> 
135				</#list> 
136			</ul> 
137		<#elseif siblingsJSONArray.length() gt 0> 
138			<ul class="m-0 p-2"> 
139				<#list 0..siblingsJSONArray.length()-1 as i> 
140					<li class="learn-article-nav-item"> 
141						<a 
142							class='liferay-nav-item ${(navigationJSONObject.getJSONObject("self").url == siblingsJSONArray.getJSONObject(i).url)?then("selected", "")}' 
143							href="${siblingsJSONArray.getJSONObject(i).url}" 
144
145							<span>${siblingsJSONArray.getJSONObject(i).getString("title")}</span> 
146						</a> 
147					</li> 
148				</#list> 
149			</ul> 
150		</#if> 
151	</div> 
152</div> 

Blacklisting Apps

The bundle blacklist is a convenient way to uninstall or reinstall multiple apps, OSGi bundles (modules), and WAR plugins at once. It saves you the trouble of managing app, module, and plugin installations individually with the Application Manager or Gogo shell.

important

The blacklist is an OSGi configuration that DXP uses to uninstall apps. Using it will prevent any apps listed from being installed until they are removed.

You can set the list in the Control Panel or by using an OSGi configuration (.config) file (by exporting it from the Control Panel).

Blacklisting

DXP removes any installed app, module, or plugin on the blacklist. While they’re blacklisted they can’t be installed. The log reports each uninstallation.

note

Blacklisting an LPKG uninstalls all of its internal modules.

Blacklisting via the Control Panel

Follow these steps to blacklist an app, module, and plugin:

  1. In the Control Panel, navigate to ConfigurationSystem SettingsModule Container. The Bundle Blacklist screen appears.

  2. In the Bundle Blacklist screen, add the bundle symbolic names for the apps, LPKG files, module JARs, or WARs to uninstall. For each item, click the Add button (Add) and enter the item’s bundle symbolic name (see the table below). Click the Save button when you’re finished. DXP uninstalls the blacklisted items immediately.

    This blacklist uninstalls the classic-theme plugin WAR, Liferay Collaboration - Liferay Blogs - API module, and com.acme.greeter module.

Blacklisting via a Configuration File

The blacklist can also be exported from the Control Panel to an OSGi configuration (.config) file. Modifying the file and deploying it to DXP has these additional effects:

  • Persists the changes across DXP server startups
  • Propagates the changes from a local cluster node to all the other nodes.

Use these steps to blacklist using a configuration file:

  1. To export the blacklist currently in use, click its Actions button (Actions) and then click Export. The blacklist config file then downloads (com.liferay.portal.bundle.blacklist.internal.BundleBlacklistConfiguration.config). Here are file contents from exporting the example blacklist:

    blacklistBundleSymbolicNames=[ \
      "classic-theme", \
      "Liferay\ Collaboration\ -\ Liferay\ Blogs\ -\ API", \
      "com.acme.greeter", \
    ]
    
  2. Add the bundle symbolic names of any apps, modules, or plugins not already listed that you want to uninstall and prevent from installing in subsequent DXP server startups.

    warning

    Configuration values can’t contain extra spaces. Extra spaces can short-circuit lists or invalidate the configuration entry.

  3. To deploy the configuration file, copy it into the folder [Liferay Home]/osgi/configs. The Liferay Home folder is typically the app server’s parent folder.

Blacklist Bundle Symbolic Names

TypeBundle Symbolic Name
AppApp name displayed in the App Manager
LPKGLPKG file name without the .lpkg extension
Module/Bundle JARBundle-SymbolicName in bnd.bnd or MANIFEST.MF file
WARServlet context name in liferay-plugin-package.properties file or the WAR file name (minus .war), if there is no servlet context name property

Reinstalling Blacklisted Items

To reinstall blacklisted items, follow these steps:

  1. Open the configuration file com.liferay.portal.bundle.blacklist.internal.BundleBlacklistConfiguration.config.

  2. Remove the symbolic names of the LPKGs, module JARs, or WARs from the blacklistBundleSymbolicNames list and save the file.

To reinstall all the blacklisted items execute one of these options:

tip

To temporarily reinstall an item that’s been blacklisted, you can remove its symbolic name from the Bundle Blacklist module in System Settings and click the Update button. If you’re using a blacklist config file (in the [Liferay Home]/osgi/configs folder) and want the item to install on subsequent server startup, make sure to remove the item’s symbolic name from the file.

The log reports each item installation.

Congratulations! Now you can manage multiple app, module, and plugin installations using a simple list.