Problem :
While working with the Liferay projects, you may need to create a configuration from the control panel like custom fields, structures, templates, roles, permissions, and many more in order to make portlet/implementation work properly.
Solution :
You can create the BundleActivator component to create the above configurations programmatically.
Benefits :
- We don’t need remember/prepare steps to create configurations from Control Panel.
- This will remove overhead of creating configurations in all environments (Dev, Test, Production) you have for your project.
Prerequisites
- Java
- Liferay portal 7/7.x
- Basic knowledge of Liferay
Environment Requirements
- JDK 8
- Eclipse
- MySQL
- Liferay Portal
- Gradle
To create BundleActivator for the Liferay project, you need to perform the below steps. In this example, we will explain to you to create custom fields, structure, templates and roles.
1) Create a Liferay module project using the following steps.
- Go to Liferay workspace project → modules → new
- Select other → Liferay → Liferay Module Project and Click on “Next”.
- Enter the project name.
- Select “Project Template Name” as “ MVC-portlet” and Click on “Next”.
- Enter a Package name and click on “Finish”. The necessary file structure for the MVC-portlet automatically gets created as below.
2) Create a package with the name com.ignek.action.
3) Create one class with the name ConfigurationCreator into this package.
4) Enter the following line into the bnd.bnd.
// bnd.bnd
Bundle-Activator: com.ignek.action.ConfigurationCreator.
5) Enter the following lines into the build.gradle.
// build.gradle
compileOnly group: “org.osgi”, name: “org.osgi.core”
compileOnly group: “com.liferay”, name: “com.liferay.dynamic.data.mapping.api”
compileOnly group: “com.liferay”, name: “com.liferay.journal.api”
compileOnly group: “com.liferay”, name: “com.liferay.petra.string”
6) Open ConfigurationCreator.java & add the following lines before the declaration of the class name.
// ConfigurationCreator.java
@Component(immediate = true,
property = {
"key=application.startup.events"
},
service = BundleActivator.class
)
7) Implement the BundleActivator in ConfigurationCreator.
// ConfigurationCreator.java
public class ConfigurationCreator implements BundleActivator
8) Override the following methods inside the class ConfigurationCreator.
// ConfigurationCreator.java
@Override
public void start(BundleContext context) throws Exception {
}
@Override
public void stop(BundleContext context) throws Exception {
}
Note : Start() method will call automatically when a module is deployed or Liferay server is started. We will add our code to create custom fields, structures, templates, and roles in this method.
1) Create custom fields
Write the below code in the start() method to create custom fields.
//ConfigurationCreator.java
/** Create custom fields **/
/** Fetch default company in Liferay **/
Company defaultCompany = CompanyLocalServiceUtil.getCompanyByMx(PropsUtil.get(PropsKeys.COMPANY_DEFAULT_WEB_ID));
long companyId = defaultCompany.getCompanyId();
/** Fetch Administrator role id **/
long roleId = roleService.getRole(companyId, RoleConstants.ADMINISTRATOR).getRoleId();
long userId = userLocalService.getRoleUsers(roleId, 0, 1).get(0).getUserId();
try {
ExpandoBridge expandoBridge = ExpandoBridgeFactoryUtil.getExpandoBridge(companyId,
Group.class.getName(),0 l);
if (Validator.isNotNull(expandoBridge)) {
int inputType = 15;
expandoBridge.addAttribute("Name", inputType, false);
}
} catch (Exception e) {
log.error("Error occurred while creating custom field");
}
ExpandoBridge allows you to add custom fields in Liferay programmatically.
Notes :
1. You can choose different inputType for Custom fields.
For Text and number | int inputType = 15; |
For Selection | int inputType = 16; |
For Map | int inputType = 21; |
For Date | int inputType = 3; |
For true/false (boolean) | int inputType = 1; |
2. You can choose different className to generate custom fields for sites, organizations, roles, users, and several more.
For sites | Group.class.getName() |
For Organization | Organization.class.getName() |
For Role | Role.class.getName() |
3. You can check generated custom fields from control-panel → configuration → custom-fields (refer below image).
2) Create Structure
Perform the below steps to create Structure programmatically.
- Create a folder inside the src/main/resources with name structures.
- Create a file with the name student.json in this folder.
- Add the source of structure into this file (You can copy the source from the Liferay control panel).
Add the following code into the start() method to generate structures.
// ConfigurationCreator.java
/** Create structure in global site **/
long groupId = groupService.getCompanyGroup(companyId).getGroupId();
String journalArticleClassName = JournalArticle.class.getName();
long journalArticleClassNameId = classNameService.getClassNameId(journalArticleClassName);
String structureKey = STUDENT;
String content = getFile("structure/student.json");
DDMForm ddmForm = DDMUtil.getDDMForm(content);
ServiceContext serviceContext = new ServiceContext();
serviceContext.setScopeGroupId(groupId);
serviceContext.setCompanyId(companyId);
serviceContext.setUserId(userId);
DDMStructure studentStructure = null;
try {
studentStructure = structureLocalService.getStructure(groupId,
journalArticleClassNameId, structureKey);
} catch (NoSuchStructureException e) {
log.info("No Structure found Adding new one");
}
if (Validator.isNotNull(studentStructure)) {
try {
studentStructure.setDDMForm(ddmForm);
studentStructure = structureLocalService.updateStructure(userId,
studentStructure.getStructureId(),ddmForm,
DDMUtil.getDefaultDDMFormLayout(ddmForm), serviceContext);
} catch (Exception e) {
log.error("Error while updating structure");
}
} else {
try {
Map nameMap = new HashMap();
nameMap.put(Locale.US, STUDENT);
Map descriptionMap = new HashMap();
descriptionMap.put(Locale.US, STUDENT);
studentStructure = structureLocalService.addStructure(userId, groupId, StringPool.BLANK,
journalArticleClassNameId, structureKey, nameMap, descriptionMap, ddmForm,
DDMUtil.getDefaultDDMFormLayout(ddmForm), StorageType.JSON.toString(),
DDMStructureConstants.TYPE_DEFAULT, serviceContext);
} catch (Exception e) {
log.error("Error while adding new structure");
}
}
Output :
3) Create Template
To generate a template for an existing structure, perform below steps.
- Create one folder in src/main/resources with the name templates.
- Create one file with the name student.ftl in this folder.
- Add the source of the template into this file (You can copy the source from the Liferay admin panel).
- Add the following code into the start() method to create a template.
// ConfigurationCreator.java
/** Create template in global site **/
String templateKey = STUDENT;
String script = getFile("template/student.ftl");
String structureClassName = DDMStructure.class.getName();
long structureClassNameId = classNameService.getClassNameId(structureClassName);
DDMTemplate studentTemplate = null;
try {
studentTemplate = templateService.getTemplate(groupId, structureClassNameId, templateKey);
} catch (Exception e) {
log.info("No template found Adding new one");
}
if (Validator.isNotNull(studentTemplate)) {
try {
studentTemplate.setScript(script);
studentTemplate = templateService.updateDDMTemplate(studentTemplate);
} catch (Exception e) {
log.error("Error while updating template");
}
} else {
try {
Map < Locale, String > nameMap = new HashMap < Locale, String > ();
nameMap.put(Locale.US, STUDENT);
Map < Locale, String > descriptionMap = new HashMap < Locale, String > ();
descriptionMap.put(Locale.US, STUDENT);
studentTemplate = templateService.addTemplate(userId, groupId, structureClassNameId,
studentStructure.getStructureId(), journalArticleClassNameId,
templateKey, nameMap, descriptionMap,
DDMTemplateConstants.TEMPLATE_TYPE_DISPLAY, StringPool.BLANK,
"ftl", script, false, false, StringPool.BLANK, null, serviceContext);
} catch (Exception e) {
log.error("Error while adding a new template");
}
}
Output:
4) Create Roles
Write the below code (Inside the start() method) to generate roles in Liferay.
// ConfigurationCreator.java
/** Creating role **/
try {
Role role = roleService.fetchRole(companyId, "Head of Organization");
Map < Locale, String > nameMap = new HashMap < > ();
nameMap.put(Locale.US, HEAD_OF_ORGANIZATION);
Map < Locale, String > descriptionMap = new HashMap < > ();
descriptionMap.put(Locale.US, "This role is for organization admin");
if (Validator.isNull(role)) {
role = roleService.addRole(userId, Role.class.getName(), 0, HEAD_OF_ORGANIZATION,
nameMap, descriptionMap, 1, null, serviceContext);
}
} catch (Exception e) {
log.error("Error while adding role");
}
As you see, the Head of Organization role is created under control-panel → users → roles.
Now the structure of the Configuration Creator project will look like the structure below.
Now build/deploy this using the following command.
blade gw deploy
You can download the source code from the below link.