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¶
Start a new Liferay DXP instance by running
docker run -it -m 8g -p 8080:8080 liferay/dxp:7.4.13-u22
Sign in to Liferay at http://localhost:8080 using the email address test@liferay.com and the password test. When prompted, change the password to learn.
Then, follow these steps:
Download and unzip Completely Custom Configuration.
curl https://learn.liferay.com/dxp/latest/en/building-applications/core-frameworks/configuration-framework/liferay-u2g5.zip -O
unzip liferay-u2g5.zip
From the module root, build and deploy.
./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
Note
This command is the same as copying the deployed jars to /opt/liferay/osgi/modules on the Docker container.
Confirm the deployment in the Liferay Docker container console.
STARTED com.acme.u2g5.web_1.0.0 [1034]
Verify that the example module is working. Open your browser to
https://localhost:8080
.Navigate to Control Panel → Configuration → System Settings → Third Party. Click U2G5 Configuration.
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
.
@ExtendedObjectClassDefinition(
category = "u2g5", generateUI = false,
scope = ExtendedObjectClassDefinition.Scope.SYSTEM
)
@Meta.OCD(
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 {
@Override
public Class<?> getConfigurationBeanClass() {
return U2G5WebConfiguration.class;
}
}
Implement the Configuration Screen¶
Declare the class as an implementation of
ConfigurationScreen
with the@Component
annotation.@Component(service = ConfigurationScreen.class)
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’sLanguage.properties
file.@Override public String getCategoryKey() { return "third-party"; } @Override public String getKey() { return "u2g5-configuration-name"; } @Override public String getName(Locale locale) { return LanguageUtil.get( ResourceBundleUtil.getBundle(locale, U2G5ConfigurationScreen.class), "u2g5-configuration-name"); }
For this example, the configuration scope is set to
system
. To learn more, see Scoping Configurations.@Override public String getScope() { return "system"; }
The
render()
method usesConfigurationProvider
to get the configuration. The servlet context provides access to the request dispatcher, which allows the custom JSP to read the configuration.@Override public void render( HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException { try { RequestDispatcher requestDispatcher = _servletContext.getRequestDispatcher("/u2g5.jsp"); httpServletRequest.setAttribute( U2G5WebConfiguration.class.getName(), _configurationProvider.getSystemConfiguration( U2G5WebConfiguration.class)); requestDispatcher.include(httpServletRequest, httpServletResponse); } catch (Exception exception) { throw new IOException("Unable to render /u2g5.jsp", exception); } }
Make sure to use the
@Reference
annotation to define the module’s symbolic name.@Reference( 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¶
Import the configuration interface to the JSP.
<%@ page import="com.acme.u2g5.web.internal.configuration.U2G5WebConfiguration" %>
Access the configuration values from the request object.
<% U2G5WebConfiguration u2g5WebConfiguration = (U2G5WebConfiguration)request.getAttribute(U2G5WebConfiguration.class.getName()); %>
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.