Completely Custom Configuration

A configuration UI is generated automatically when you create a configuration interface. But in some cases you want a completely custom UI for your configuration. For example, you plan to handle the configuration programmatically instead of using Liferay’s Configuration Admin. Or maybe you want the flexibility of creating a completely custom UI. Here’s how to do it.

See the Example Project

  1. Start Liferay DXP. If you don’t already have a docker container, use

    docker run -it -m 8g -p 8080:8080 liferay/dxp:7.4.13-ga1

    If you’re running a different Liferay Portal version or Liferay DXP, adjust the above command accordingly.

  2. Download and unzip Completely Custom Configuration.

    curl -O
  3. From the module root, build and deploy.

    ./gradlew deploy$(docker ps -lq)


    This command is the same as copying the deployed jars to /opt/liferay/osgi/modules on the Docker container.

  4. Confirm the deployment in the Liferay Docker container console.

    STARTED com.acme.u2g5.web_1.0.0 [1034]
  5. Verify that the example module is working. Open your browser to https://localhost:8080.

  6. Navigate to Control PanelConfigurationSystem SettingsThird Party. Click U2G5 Configuration.

    Navigate to U2G5 configuration in system settings.

    Note that this view is delivered by a custom JSP file.

Create the Configuration Interface

Define the configurable attributes in the configuration interface. The sample project has three configurable attributes: fontColor, fontFamily, and fontSize.

	category = "u2g5", generateUI = false,
	scope = ExtendedObjectClassDefinition.Scope.SYSTEM
	id = "com.acme.u2g5.web.internal.configuration.U2G5WebConfiguration",
	localization = "content/Language", name = "u2g5-configuration-name"
public interface U2G5WebConfiguration {

	@Meta.AD(deflt = "blue", required = false)
	public String fontColor();

	@Meta.AD(deflt = "serif", required = false)
	public String fontFamily();

	@Meta.AD(deflt = "16", required = false)
	public int fontSize();

Note that under the @ExtendedObjectClassDefinition annotation, generateUI is set to false. This excludes the configuration UI from being auto-generated.

Add the Configuration Bean Declaration

Register the configuration class with a ConfigurationBeanDeclaration. This enables the system to keep track of configuration changes as they happen.

@Component(service = ConfigurationBeanDeclaration.class)
public class U2G5WebConfigurationBeanDeclaration
	implements ConfigurationBeanDeclaration {

	public Class<?> getConfigurationBeanClass() {
		return U2G5WebConfiguration.class;


Implement the Configuration Screen

  1. Declare the class as an implementation of ConfigurationScreen with the @Component annotation.

    @Component(service = ConfigurationScreen.class)
  2. Set the category key, the configuration entry’s key, and its localized name. In the sample project, the category key is set to third-party in System Settings. The string value for the configuration’s name is set by the language key in the bundle’s file.

    public String getCategoryKey() {
    	return "third-party";
    public String getKey() {
    	return "u2g5-configuration-name";
    public String getName(Locale locale) {
    	return LanguageUtil.get(
    		ResourceBundleUtil.getBundle(locale, U2G5ConfigurationScreen.class),
  3. For this example, the configuration scope is set to system. To learn more, see Scoping Configurations.

    public String getScope() {
    	return "system";
  4. The render() method uses ConfigurationProvider to get the configuration. The servlet context provides access to the request dispatcher, which allows the custom JSP to read the configuration.

    public void render(
    		HttpServletRequest httpServletRequest,
    		HttpServletResponse httpServletResponse)
    	throws IOException {
    	try {
    		RequestDispatcher requestDispatcher =
    		requestDispatcher.include(httpServletRequest, httpServletResponse);
    	catch (Exception exception) {
    		throw new IOException("Unable to render /u2g5.jsp", exception);
  5. Make sure to use the @Reference annotation to define the module’s symbolic name.

    	target = "(osgi.web.symbolicname=com.acme.u2g5.web)"

Add the Web-ContextPath

Specify your bundle’s Web-ContextPath in the bnd.bnd file. For example, the sample project has Web-ContextPath: /u2g5-web in the Bnd file. This is what registers the ServletContext object in the Configuration Screen file. Note that a servlet context is created automatically for portlets, but since this sample doesn’t have a portlet, you must add this line to the Bnd file.

Create a Custom JSP

  1. Import the configuration interface to the JSP.

    <%@ page import="com.acme.u2g5.web.internal.configuration.U2G5WebConfiguration" %>
  2. Access the configuration values from the request object.

    U2G5WebConfiguration u2g5WebConfiguration = (U2G5WebConfiguration)request.getAttribute(U2G5WebConfiguration.class.getName());
  3. The attributes fontColor(), fontFamily(), fontSize() can now be used in the JSP.

This sample project demonstrates a basic example of how to use ConfigurationScreen to read and display configuration values in a custom JSP. In your application, write your own code and create a completely custom configuration UI to meet your needs.