Overriding Inline Content Using JSPs

Some Liferay DXP core content, such as tag library tags, can only be overridden using JSPs ending in .readme. The suffix .readme facilitates finding them. The code from these JSPs is now inlined (brought into Liferay DXP Java source files) to improve performance. Liferay DXP ignores JSP files with the .readme suffix. If you add code to a JSP .readme file and remove the .readme suffix, Liferay DXP uses that JSP instead of the core inline content. This tutorial shows you how to make these customizations.

Here’s how to override inline content using JSPs:

  1. Create a Custom JSP Bag for deploying your JSP. Note the module folder you’re storing the JSPs in: the default folder is [your module]/src/main/resources/META-INF/jsps/

  2. Download the Liferay DXP source code or browse the source code on GitHub (Liferay Portal CE).

  3. Search the source code for a .jsp.readme file that overrides the tag you’re customizing.

  4. Copy the .jsp.readme file into your project and drop the .readme suffix. Use the same relative file path Liferay DXP uses for the .jsp.readme file. For example, if the file in Liferay DXP is


    use file path

    [your module]/src/main/resources/META-INF/jsps/html/taglib/aui/fieldset/start.jsp
  5. Familiarize yourself with the current UI content and logic, so you can override it appropriately. Tag library tag content logic, for example, is in the respective *Tag.java file under util-taglib/src/com/liferay/taglib/[tag library]/.

  6. Develop your new logic, keeping in mind the current inline logic you’re replacing.

  7. Deploy your JSP.

Liferay DXP uses your JSP in place of the current inline logic. If you want to walk through an example override, continue with this tutorial. Otherwise, congratulations on a modified .jsp.readme file to override core inline content!

Example: Overriding the fieldset Taglib Tag

This example demonstrates changing the liferay:aui tag library’s fieldset tag. Browsing the Liferay DXP web application or the source code at portal-web/docroot/html/taglib/aui/fieldset reveals these files:

  • start.jsp.readme
  • end.jsp.readme

They can override the logic that creates the start and end of the fieldset tag. The FieldsetTag.java class’s processStart and processEnd methods implement the current inline content. Here’s the processStart method:

protected int processStartTag() throws Exception {
	JspWriter jspWriter = pageContext.getOut();

	jspWriter.write("<fieldset class=\"fieldset ");
	jspWriter.write("\" ");

	String id = getId();

	if (id != null) {
		jspWriter.write("\" ");



	String lable = getLabel();

	if (lable != null) {
			"<legend class=\"fieldset-legend\"><span class=\"legend\">");

		MessageTag messageTag = new MessageTag();



		String helpMessage = getHelpMessage();

		if (helpMessage != null) {
			IconHelpTag iconHelpTag = new IconHelpTag();




	if (getColumn()) {
		jspWriter.write("<div class=\"row\">");
	else {
		jspWriter.write("<div class=\"\">");


The code above does this:

  1. Write <fieldset class=\"fieldsetstarting tag.

  2. Write the CSS class name attribute.

  3. If the tag has an ID, add the id as an attribute.

  4. Write the tag’s dynamic attribute (map).

  5. Close the starting fieldset tag.

  6. Get the tag’s label attribute.

  7. Write the starting legend element.

  8. Use getLocalizeLabel() to add the localized label in the legend.

  9. If there’s a help message (retrieved from getHelpMessage()), write it in an icon-help-tag.

  10. Write the closing legend tag.

  11. If there’s a column attribute, write <div class=\"row\">; else write <div class=\"\">.

Replicating the current logic in your custom JSP helps you set up the tag properly for customizing. The init.jsp for fieldset initializes all the variables required to create the starting tag. You can use the variables in the start.jsp. The logic from FieldsetTag’s processStart method converted to JSP code for start.jsp (renamed from start.jsp.readme) would look like this:

<%@ include file="/html/taglib/aui/fieldset/init.jsp" %>

<fieldset class="fieldset <%= cssClass %>" <%= Validator.isNotNull(id) ? "id=\"" + id + "\"" : StringPool.BLANK %> <%= InlineUtil.buildDynamicAttributes(dynamicAttributes) %>>
	<c:if test="<%= Validator.isNotNull(label) %>">
		<legend class="fieldset-legend">
			<span class="legend">
				<liferay-ui:message key="<%= label %>" localizeKey="<%= localizeLabel %>" />

				<c:if test="<%= Validator.isNotNull(helpMessage) %>">
					<liferay-ui:icon-help message="<%= helpMessage %>" />

	<div class="<%= column ? "row" : StringPool.BLANK %>">

On deploying the start.jsp, the fieldset tags render the same as they did before. This is expected because it uses the same logic as FieldsetTag’s processStart method.

Figure 1: Liferay DXPs home pages search and sign in components are in a fieldset.

Figure 1: Liferay DXP's home page's search and sign in components are in a `fieldset`.

The fieldset starting logic is ready for customization. To test that this works, you’ll print the word test surrounded by asterisks before the end of the fieldset tag’s starting logic. Insert this line before the start.jsp’s last div tag:

<c:out value="**********test**********"/>

Redeploy the JSP and refresh the page to see the text printed above the fieldset’s fields.

Figure 2: Before the fieldsets nested fields, it prints test surrounded by asterisks.

Figure 2: Before the `fieldset`'s nested fields, it prints *test* surrounded by asterisks.

You know how to override specific Liferay DXP core inline content using Liferay’s .jsp.readme files.

Customizing JSPs with Dynamic Includes

JSP Overrides Using Portlet Filters

« JSP Overrides Using Custom JSP BagOverriding Liferay Services (Service Wrappers) »