0

In Liferay 7, how to create a structure from a Java module?
Here is my attempt:

Map<Locale, String> nameMap = new HashMap<Locale, String>();
nameMap.put(Locale.JAPAN, "The name");
Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
descriptionMap.put(Locale.JAPAN, "The description");

DDMForm ddmForm = DDMUtil.getDDMForm("<here goes my real JSON form>");
DDMFormLayout ddmFormLayout = DDMUtil.getDefaultDDMFormLayout(ddmForm);

DDMStructureLocalServiceUtil.addStructure(
    20156, // userId
    33421, // groupId
    DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID, // parentStructureId
    PortalUtil.getPortal().getClassNameId(DDLRecordSet.class), // classNameId
    new Long(CounterLocalServiceUtil.increment()).toString(), // structureKey
    nameMap,
    descriptionMap,
    ddmForm,
    ddmFormLayout,
    StorageType.JSON.toString(),
    0, // type
    new ServiceContext()
);

The structure gets created in the database's DDMStructure table:

enter image description here

Unfortunately, it does not appear in that site's Liferay UI:

enter image description here

How to make it show up?

  • No error appear in Liferay's log during creation nor when loading the UI.
  • When I create a structure manually, it shows up correctly.
  • The solution to this question for Liferay 6, which I tried too, leads to the same problem.
  • I noticed that when creating a structure manually, 3 rows get added to the ResourcePermission table... when creating a structure in Java should I also create these 3 objects?
Nicolas Raoul
  • 58,567
  • 58
  • 222
  • 373

3 Answers3

2

It is a classNameId problem. Replacing DDLRecordSet with JournalArticle solves the problem, making the structure show up correctly in Liferay's Structures UI.

Code that works:

ServiceContext serviceContext = new ServiceContext();
serviceContext.setScopeGroupId(group.getGroupId());
serviceContext.setAddGroupPermissions(true);
serviceContext.setAddGuestPermissions(true);
serviceContext.setWorkflowAction(WorkflowConstants.ACTION_PUBLISH);

Map<Locale, String> nameMap = new HashMap<Locale, String>();
nameMap.put(Locale.JAPAN, "The name");
Map<Locale, String> descriptionMap = new HashMap<Locale, String>();
descriptionMap.put(Locale.JAPAN, "The description");

DDMForm ddmForm = null;
try {
    ddmForm = DDMUtil.getDDMForm(json);
} catch (PortalException e) {
    log.error("Exception when parsing structure JSON", e);
}

DDMFormLayout ddmFormLayout = DDMUtil.getDefaultDDMFormLayout(ddmForm);
long scopeClassNameId = PortalUtil.getPortal().getClassNameId(JournalArticle.class);
long parentStructureId = DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID;
String storageType = StorageType.JSON.toString();
String structureKey = "my structure";

try {
    DDMStructure ddmStructure = DDMStructureLocalServiceUtil.addStructure(
        user.getUserId(), group.getGroupId(), parentStructureId,
        scopeClassNameId, structureKey,
        nameMap, descriptionMap, ddmForm, ddmFormLayout, storageType,
        DDMStructureConstants.TYPE_DEFAULT, serviceContext);
} catch (StructureDuplicateStructureKeyException e) {
    log.info("Skipping creation of structure that already exists");
} catch (PortalException e) {
    log.error("Exception when creating structure: " + structureDefinitionFilePath, e);
}
Nicolas Raoul
  • 58,567
  • 58
  • 222
  • 373
0

You forgot to initialize ServiceContext before call DDMStructureLocalServiceUtil. In the ServiceContext instance you should add default permission:

    ServiceContext context = new ServiceContext();
    context.setAddGroupPermissions(true);
    context.setAddGuestPermissions(true); 

By doing this before, you make sure that you can view the structure later.

atrujillofalcon
  • 1,042
  • 1
  • 11
  • 17
  • Thank you for the tip! I added these 3 lines and used that `serviceContext` in the `addStructure` call. Then I created a new site and deployed/ran the module again. However, the created structure still does not appear in the site's Liferay UI, only `Basic Web Content` is visible. – Nicolas Raoul Jun 05 '17 at 07:06
0

There is a problem with your ServiceContext argument to the DDMStructureLocalServiceUtil.addStructure method. There are 2 ways you can set the context depending on from where you are trying to add the structure:

If you are invoking from the servlet that has access to the portlet request, use the following method:

   ServiceContextFactory.getInstance(className, portletRequest);

This would take care of all the necessary scope and permission.

If you are implementing it from anywhere else, the best way would be instantiate the ServiceContext and set at least the scopeGroupId:

ServiceContext serviceContext = new ServiceContext();
serviceContext.setScopeGroupId(myGroupId);
serviceContext.setAddGroupPermissions(true);
Uday
  • 1,165
  • 9
  • 12
  • Thank you for the tip! I am writing a module (no servlet) so I added the 3 last lines of your answer and used that `serviceContext` in the `addStructure` call. Then I created a new site and deployed/ran the module again. However, the created structure still does not appear in the site's Liferay UI, only `Basic Web Content` is visible. – Nicolas Raoul Jun 05 '17 at 07:05
  • In the addStructure method, the classnameId, shouldn't that be JournalArticle? Also can you try setting the user id in service context? – Uday Jun 06 '17 at 07:00
  • Yes, as seen in my answer, classNameId was the problem. – Nicolas Raoul Jun 06 '17 at 07:19
  • Oops.. I didn't see when I wrote it. Was commenting from mobile. Glad u were able to resolve! – Uday Jun 06 '17 at 11:32
  • Thanks for always doing your best answering Liferay questions! :-) – Nicolas Raoul Jun 08 '17 at 13:38