Adding the UAD Framework
You can manage and delete user data with Liferay’s User Associated Data (UAD) management tool. The tool is available out-of-the-box for many of Liferay’s applications (e.g. Blogs, Documents and Media, Message Boards, etc.). This framework can also be applied to your custom application.
This task is made easier with the use of Service Builder. See the example below to learn how Service Builder automatically generates the necessary code to enable UAD for your application.
Download the Example Code
Start a new Liferay DXP instance by running
docker run -it -m 8g -p 8080:8080 liferay/dxp:2024.q2.11
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 UAD Framework.
curl https://resources.learn.liferay.com/dxp/latest/en/users-and-permissions/developer-guide/liferay-h6d2.zip -O
unzip liferay-h6d2.zip
-
From the module root, build and deploy.
./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
NoteThis 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.h6d2.api_1.0.0 [1433] STARTED com.acme.h6d2.service_1.0.0 [1434] STARTED com.acme.h6d2.uad_1.0.0 [1435] STARTED com.acme.h6d2.web_1.0.0 [1436]
-
Open your browser to
https://localhost:8080
. -
Add the H6D2 Portlet to a page. You can find the example portlet under Sample Widgets.
-
Create a new user for testing.
-
Log in as the new user and add some content on the H6D2 Portlet.
-
Log back in as the administrator and navigate to Control Panel → Users → Users and Organizations.
-
Click the new user’s Actions icon () → Delete Personal Data. Click OK to confirm deactivation of the user.
-
The UAD management tool appears. You can view, anonymize, or delete the data the new user added in the H6D2 Portlet.
Modify the Service Model Definition
This tutorial assumes that you have a working application that you created using Service Builder. To enable UAD, first make the following changes to your entity:
-
Open your
service.xml
file in the-service
folder. -
There are two
entity
parameters to enable UAD:entity
attributesDescription uad-application-name
Specifies the name of the application the entity type belongs to. uad-package-path
Specifies the package path for the generated UAD classes.
<entity local-service="true" name="H6D2Entry" remote-service="false" uad-application-name="H6D2" uad-package-path="com.acme.h6d2" uuid="true">
-
Add the following data fields if you don’t already have them defined:
<!-- Group instance --> <column name="groupId" type="long" /> <!-- Audit fields --> <column name="companyId" type="long" /> <column name="userId" type="long" /> <column name="userName" type="String" /> <column name="createDate" type="Date" /> <column name="modifiedDate" type="Date" />
The UAD Framework requires these fields to track and anonymize user data.
-
Next, specify the data fields to anonymize. This is done with the use of two attributes:
-
The
uad-anonymize-field-name=[fieldName]
attribute indicates a field whose value is replaced by that of the anonymous user in the UAD auto-anonymization process. For example, settinguad-anonymize-field-name=fullName
would replace the value of that field with the full name of the anonymous user. See Configuring the Anonymous User to learn more about the anonymous user. -
The
uad-nonanonymizable="true"
attribute indicates data that is not automatically anonymized but must be reviewed by an administrator.
-
<column name="userName" type="String" uad-anonymize-field-name="fullName" />
Generate the UAD module
-
Navigate out of the
-service
folder and create a new-uad
folder. -
Create a
bnd.bnd
file for the module.
Bundle-Name: Liferay H6D2 UAD
Bundle-SymbolicName: com.acme.h6d2.uad
Bundle-Version: 1.0.0
-dsannotations-options: inherit
Make sure to include the -dsannotations-options: inherit
annotation. OSGi service component classes inherit OSGi declarative services annotations from their class hierarchy.
- Create a
build.gradle
file for the module.
dependencies {
compileOnly group: "com.liferay.portal", name: "release.portal.api"
compileOnly project(":h6d2-api")
}
Make sure to add any dependencies you need, including any -api
module of your project.
-
Navigate back to the module’s
-service
folder and run Service Builder to generate the UAD module.../gradlew buildService
Output:
> Task :h6d2-service:buildService Building H6D2Entry Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/anonymizer/BaseH6D2EntryUADAnonymizer.java Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/exporter/BaseH6D2EntryUADExporter.java Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/anonymizer/H6D2EntryUADAnonymizer.java Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/exporter/H6D2EntryUADExporter.java Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/display/BaseH6D2EntryUADDisplay.java Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/display/H6D2EntryUADDisplay.java Writing src/main/resources/service.properties Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/constants/H6D2UADConstants.java
Modify the Portlet
When you pass the data fields specific to your application from the form, you must also pass the user-related data fields you added in the service.xml
file.
public class H6D2Portlet extends MVCPortlet {
public void addH6D2Entry(
ActionRequest actionRequest, ActionResponse actionResponse)
throws PortalException {
ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
WebKeys.THEME_DISPLAY);
User user = _portal.getUser(actionRequest);
H6D2Entry h6d2Entry = _h6d2EntryLocalService.createH6D2Entry(
_counterLocalService.increment());
h6d2Entry.setCompanyId(user.getCompanyId());
h6d2Entry.setUserId(user.getUserId());
h6d2Entry.setUserName(user.getFullName());
h6d2Entry.setGroupId(themeDisplay.getSiteGroupId());
h6d2Entry.setName(ParamUtil.getString(actionRequest, "name"));
_h6d2EntryLocalService.addH6D2Entry(h6d2Entry);
}
@Reference
private CounterLocalService _counterLocalService;
@Reference
private H6D2EntryLocalService _h6d2EntryLocalService;
@Reference
private Portal _portal;
}
The H6D2 Portlet
has an H6D2EntryLocalService
field called _h6d2EntryLocalService
and an action-handling method called addH6D2Entry
. The addH6D2Entry
method calls H6D2EntryLocalService
’s addH6D2Entry
method, passing the data fields received from the ActionRequest
.
The portlet’s view.jsp
contains a form users can submit in an ActionRequest
to H6D2 Portlet
.
<h5>Add H6D2 Entry</h5>
<portlet:actionURL name="addH6D2Entry" var="addH6D2EntryURL" />
<aui:form action="<%= addH6D2EntryURL %>">
<aui:input name="name" type="text" />
<aui:button type="submit" value="submit" />
</aui:form>
Submitting the ActionRequest
with the actionURL
invokes the portlet’s addH6D2Entry
method.