How To retrive freeMarkerPortletPreferences in Web content templates Liferay 7.4? - liferay

I am trying to use portletpreference in my nested webcontent in Liferay 7.4. In the 7.4 version, there are two tables [PortletPreferences] and [PortletPreferenceValue] for Preferences.
I am able to set the Preferences values but, having trouble in retrieving it in the template.
I have tried below code in my template for retriving the prefrences. I am not able to find any method which retrives PortletPreferenceValues.
<#assign portletPreferencesService = serviceLocator.findService("com.liferay.portal.kernel.service.PortletPreferencesLocalService") />
<#assign portletPreferncesValueService = serviceLocator.findService("com.liferay.portal.kernel.service.PortletPreferenceValueLocalService") />
<#assign portletKeys = staticUtil["com.liferay.portal.kernel.util.PortletKeys"]>
<#assign ownerId = groupId />
<#assign ownerType = portletKeys.PREFS_OWNER_TYPE_LAYOUT />
<#assign portletId = "com_liferay_journal_content_web_portlet_JournalContentPortlet" />
<#assign plid = 0/>
<#assign portletPreferences = portletPreferencesService.fetchPortletPreferences(ownerId, ownerType, plid, portletId) />
Can someone throw pointers on how to retrieve the same?
Thanks

Related

Liferay Asset Publisher ADT get Image URL

I have created a structure in Liferay 7.2 that has an image selector. When I add the following to the ADT to get the image
<#assign
artImg = saxReaderUtil.createXPath("dynamic-element[#name='Imagean48']")
/>
it doesn't return the URL but instead returns a list.
<img src=" {" classpk":1923313,"groupid":"1912582","name":"spc_desktop_welcome_image3_benefits.jpg","alt":"man="" in="" suit","title":"spc_desktop_welcome_image3_benefits.jpg","type":"document","uuid":"db10a245-881c-d09c-ab64-4aeebc1581f0","fileentryid":"1923313","resourceprimkey":"2474428"}="" "="">
Is it possible to get just the URL of the image?
Evaluate artImg to a hash
<#assign
artImg = saxReaderUtil.createXPath("dynamic-element[#name='Imagean48']")
artImgHash = artImg?eval
/>
Get artImg DLFileEntry and then its URL
<#assign
dlFileEntryLocalService = serviceLocator.findService("com.liferay.document.library.kernel.service.DLFileEntryLocalService")
dlURLHelper = serviceLocator.findService("com.liferay.document.library.util.DLURLHelper")
artImgDLFile = dlFileEntryLocalService.getFileEntryByUuidAndGroupId(artImgHash.uuid, artImgHash.grouId)
artImgURL = dlURLHelper.getImagePreviewURL(artImgDLFile, themeDisplay)
/>
Then you can just use it in your img
<img src="${artImgURL}"/>
Note: I've replicated your artImg = saxReaderUtil.createXPath... line but I don't think it works. The right way would be something like this:
<#assign
journal = entry.getAssetRenderer().getArticle()
rootElement = saxReaderUtil.read(journal.content).getRootElement()
artImg = rootElement.selectSingleNode("dynamic-element[#name='Imagean48']")
/>

Liferay DXP web content field inside structure

Hello I've created a simple structure which only has 1 repeatable web content field. In my template I have the following code:
<#if WebContent75zf.getSiblings()?has_content>
<#list WebContent75zf.getSiblings() as cur_WebContent75zf>
<!-- Web Content Start -->
${cur_WebContent75zf.getData()}
<!-- Web Content End -->
</#list>
</#if>
The desired result would be either to show each web content rendered or at least get their data.
What I'm getting is the following and I'm wondering if I'm doing something wrong...
<!-- Web Content Start -->
{"className":"com.liferay.journal.model.JournalArticle","classPK":"40952"}
<!-- Web Content End -->
<!-- Web Content Start -->
{"className":"com.liferay.journal.model.JournalArticle","classPK":"40971"}
<!-- Web Content End -->
<!-- Web Content Start -->
{"className":"com.liferay.journal.model.JournalArticle","classPK":"40990"}
<!-- Web Content End -->
This: {"className":"com.liferay.journal.model.JournalArticle","classPK":"40971"} is what you need to retrieve the selected Web Content through the JournalArticleLocalService, you have just to get the classPK like this:
<#if WebContent75zf.getSiblings()?has_content>
<#list WebContent75zf.getSiblings() as cur_webContent>
<#assign cur_webContent_map = cur_webContent.getData()?eval>
<#assign cur_webContent_classPK = cur_webContent_map.classPK>
<#assign article = JournalArticleLocalService.getLatestArticle(cur_webContent_classPK?number)>
</#list>
</#if>
This works in Liferay 7.0. Make sure restricted variables are disabled in Liferay settings
<#-- Liferay 7.0 -->
<#-- Make sure restricted variables are disabled in Liferay settings -->
<#assign
serviceContext = staticUtil["com.liferay.portal.kernel.service.ServiceContextThreadLocal"].getServiceContext()
themeDisplay = serviceContext.getThemeDisplay()
group_id = themeDisplay.getScopeGroupId()
JournalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService")
>
<#if WebContent75zf.getSiblings()?has_content>
<#list WebContent75zf.getSiblings() as cur_webContent>
<#assign
cur_webContent_map = cur_webContent.getData()?eval
cur_webContent_classPK = cur_webContent_map.classPK
article = JournalArticleLocalService.getLatestArticle(cur_webContent_classPK?number)
article_id = article.articleId
article_content = JournalArticleLocalService.getArticleContent(group_id, article_id, null, locale, themeDisplay)
>
${article_content}
</#list>
</#if>
Define journalArticleLocalService before use it:
<#assign journalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService") />

The given key is not present in the dictionary

Hi I am trying to fetch the accounts from CRM 2011. I am fetching the data in the EntityCollection . But when I am trying to read or access data from entityCollection it displayed first record but throwing an error after that record. Kindly have a look to below code and suggest me.
string fetch2 = #"
<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
<entity name='account'>
<attribute name='name' />
<attribute name='address1_city' />
<attribute name='primarycontactid' />
<attribute name='telephone1' />
<attribute name='accountid' />
<order attribute='name' descending='false' />
<filter type='and'>
<condition attribute='accounttype' operator='eq' value='01' />
</filter>
</entity>
</fetch>";
try
{
EntityCollection fxResult = _service.RetrieveMultiple(new FetchExpression(fetch2));
foreach (var e in fxResult.Entities)
{
Console.WriteLine("Id:{0},Name:{1},City:{2}", e.Attributes ["accountid"].ToString(), e.Attributes["name"].ToString(), e.Attributes["address1_city"].ToString());
// Console.WriteLine("Id:{0},Name:{1},City:{2}", e.ToEntity["accountid"]);
}
}
catch (Exception e)
{
Console.WriteLine("Error:==" + e.Message);
}
Before access an attribute you need to ask if it is in the context:
e.Attributes.Contains("address1_city")
If the collection contains the attribute, then you can access it safe.
string accountid = (string)e.Attributes["address1_city"]
The reason the attribute doesn't come in the collection it's because it is null or you are not retrieving it. In this case maybe, one of your attributes is null. Maybe address1_city.
When retrieving attribute values of late-bound Entity objects, the recommended approach is to use method getAttributeValue<T>. When the attribute is not present in the entity's attribute collection, it returns default(T).
The primary key ('id') of the record is always present when it is returned by the OrganizationService.
So your code should look like this:
EntityCollection fxResult = _service.RetrieveMultiple(new FetchExpression(fetch2));
foreach (var e in fxResult.Entities)
{
Console.WriteLine(
"Id:{0},Name:{1},City:{2}",
e.Id,
e.GetAttributeValue<string>("name"),
e.GetAttributeValue<string>("address1_city"));
}
You can safely use the item selector when you need to assign a value to an attribute, regardless if it is already present or not.
E.g. the following code line is valid:
e["name"] = "Demo Accountname";

Incorrect / redundant where clause

I'm not the best a Linq and I have written the below query and it just seems my where clause is redundant and there has to be a better way?
Given the following XML structure:
<Views>
<Fulfillment>
<SecurityRoleName>ABCD</SecurityRoleName>
<SecurityRoleViews>
<RoleView name="A" />
<RoleView name="B" />
<RoleView name="C" />
<RoleView name="D" />
<RoleView name="E" />
<RoleView name="F" />
</SecurityRoleViews>
<PublicRoleViews>
<RoleView name="Z" />
<RoleView name="Y" />
<RoleView name="X" />
<RoleView name="W" />
<RoleView name="V" />
<RoleView name="U" />
</PublicRoleViews>
</Fulfillment>
</Views>
I wrote the following to get a single value (FulfillmentRoleName) and two List (SecuredViews, PublicViews) objects.
FulfillmentRoleName = configParms.Descendants("Fulfillment")
.Where(node => (string)node.Element("SecurityRoleName") == "SecurityRoleName")
.Select(node => node.Value.ToString())
.First();
SecuredViews = configParms.Descendants("SecurityRoleViews")
.Where(node => (string)node.Element("RoleView") == "RoleView")
.Select(node => node.Attribute("name").Value.ToString())
.ToList();
PublicViews = configParms.Descendants("PublicRoleViews")
.Where(node => (string)node.Element("RoleView") == "RoleView")
.Select(node => node.Attribute("name").Value.ToString())
.ToList();
I would want the following values:
FulfillmentRoleName = ABCD
SecuredViews = List of names A,B,C...
PublicViews = List of names Z,Y,X....
It is the where clause that I am unsure of:
.Where(node => (string)node.Element("RoleView") == "RoleView")
Seems there has to be a more elegant way to locate that node?
Thank you for taking the time to help
As per Ahmad Mageed recommendation I am using the more elegant Element("") approach. However I am getting an instantiation error...as if the element collection is not built yet??
However if I use configParms.Root.Value I get my SecurityRoleName value???
I would have thought that views would be the root....or is it the first node that has a value???
You can use the Elements method and provide the name to match. This would allow you to replace the where query with Elements("RoleView").
Some other observations:
You can simplify the first query by grabbing the "Fulfillment" element directly by using the Element method, instead of Descendants.
The Value property returns a string. The ToString() calls are redundant.
Here's an updated version of your queries:
// if configParms is an XDocument use configParms.Root
var securityRoleName = configParms.Element("Fulfillment")
.Element("SecurityRoleName").Value;
var securedViews = configParms.Descendants("SecurityRoleViews")
.Elements("RoleView")
.Select(node => node.Attribute("name").Value)
.ToList();
var publicViews = configParms.Descendants("PublicRoleViews")
.Elements("RoleView")
.Select(node => node.Attribute("name").Value)
.ToList();

How to call facade from the command

In IBM WebSphere Commerce How the facade can be called from the command Instead of calling it from jsp. we call it from jsp like
<wcf:getData type="com.ibm.commerce.catalog.facade.datatypes.CatalogNavigationViewType" var="catalogNavigationView"
expressionBuilder="${navigationView}" varShowVerb="showCatalogNavigationView"
maxItems="${pageSize}" recordSetStartNumber="${WCParam.beginIndex}">
<wcf:param name="searchProfile" value="${searchProfile}" />
<wcf:param name="searchTerm" value="${newSearchTerm}" />
<wcf:param name="intentSearchTerm" value="${intentSearchTerm}" />
<wcf:param name="searchType" value="${searchType}" />
<wcf:param name="searchSource" value="${WCParam.searchSource}" />
<wcf:param name="metaData" value="${WCParam.metaData}" />
<wcf:param name="orderBy" value="${WCParam.orderBy}" />
<c:forEach var="facetValue" items="${param.facet}">
<c:if test="${fn:contains(facetValue , '|')}">
<c:set var="facetValue" value="${fn:replace(facetValue,'|',',')}"/>
</c:if>
<wcf:param name="facet" value="${facetValue}" />
</c:forEach>
<wcf:param name="advancedFacetList" value="${newAdvancedFacetList}"/>
<wcf:param name="categoryId" value="${currentCategoryId}" />
<wcf:param name="filterTerm" value="${newFilterTerm}" />
<wcf:param name="filterType" value="${WCParam.filterType}" />
<wcf:param name="filterFacet" value="${removeFacet}" />
<wcf:param name="manufacturer" value="${newManufacturer}" />
<wcf:param name="minPrice" value="${WCParam.minPrice}" />
<wcf:param name="maxPrice" value="${WCParam.maxPrice}" />
<wcf:contextData name="storeId" data="${WCParam.storeId}" />
<wcf:contextData name="catalogId" data="${WCParam.catalogId}" />
</wcf:getData>
This is how we can call it from jsp but I want to call this facade from the command (from the java code)
Please give me any suggestion
Thanks
Ankit
You can do it like this :
public someMethod(){
....
CatalogFacadeClient catalogFacadeClient = new CatalogFacadeClient(getBusinessContextType(), null);
GetType getVerb = CatalogFacadeClient.createGetVerb("_wcf:XPath", getXPathExpressionString());
ShowCatalogNavigationViewDataAreaType showDataArea = catalogFacadeClient.getCatalogNavigationView(getVerb);
response = showDataArea.getCatalogNavigationView();
....
}
public String getXPathExpressionString() {
StringBuffer expression = new StringBuffer();
expression.append("{_wcf.ap='IBM_Store_CatalogEntrySearch';");
expression.append("_wcf.search.term='" + toto+ "';");
expression.append("_wcf.search.spellcheck='false';");
expression.append("_wcf.search.type='1000';");
expression.append("_wcf.search.source='Q'}");
expression.append("/CatalogNavigationView");
return expression.toString();
}
protected BusinessContextType getBusinessContextType() {
BusinessContextType businessContext = CommerceFoundationFactory.eINSTANCE.createBusinessContextType();
ContextDataType storeId = CommerceFoundationFactory.eINSTANCE.createContextDataType();
storeId.setName("storeId");
storeId.setValue(currentStoreId);
ContextDataType catalogId = CommerceFoundationFactory.eINSTANCE.createContextDataType();
catalogId.setName("catalogId");
catalogId.setValue(currentCatalogId);
ContextDataType langIdContext = CommerceFoundationFactory.eINSTANCE.createContextDataType();
langIdContext.setName("langId");
langIdContext.setValue(langId.toString());
businessContext.getContextData().add(storeId);
businessContext.getContextData().add(catalogId);
businessContext.getContextData().add(langIdContext);
return businessContext;
}
Your code works!! Thank you so much!
Some Remarks about getXPathExpressionString() method:
1.- In order to prepare the expression builder correctly please check get-data-config.xml and get the expression builder by name. Name is the expressionBuilder param in wcf:getData
expressionBuilder="${navigationView}"
<wcf:getData type="com.ibm.commerce.catalog.facade.datatypes.CatalogNavigationViewType" var="catalogNavigationView"
expressionBuilder="${navigationView}" varShowVerb="showCatalogNavigationView"
maxItems="${pageSize}" recordSetStartNumber="${WCParam.beginIndex}">
Value of ${navigationView} is = "getCatalogNavigationView"
Search this value in get-data-config.xml file and look like this:
<expression-builder>
<name>getCatalogNavigationView</name>
<data-type-name>CatalogNavigationView</data-type-name>
<expression-template>{_wcf.ap='$accessProfile$';_wcf.search.profile='$searchProfile$';_wcf.search.facet.field.limit='$facetLimit$';_wcf.search.term='$searchTerm$';_wcf.search.intent.term='$intentSearchTerm$';_wcf.search.originalterm='$originalSearchTerm$';_wcf.search.category='$categoryId$';_wcf.search.type='$searchType$';_wcf.search.exclude.term='$filterTerm$';_wcf.search.exclude.type='$filterType$';_wcf.search.manufacturer='$manufacturer$';_wcf.search.price.minimum='$minPrice$';_wcf.search.price.maximum='$maxPrice$';_wcf.search.facet='$facet$';_wcf.search.advanced.facet='$advancedFacetList$';_wcf.search.exclude.facet='$filterFacet$';_wcf.search.sort='$orderBy$';_wcf.search.meta='$metaData$';_wcf.search.source='$searchSource$';_wcf.search.store='$physicalStoreIds$'}/CatalogNavigationView</expression-template>
<param>
<name>accessProfile</name>
<value>IBM_Store_CatalogEntrySearch</value>
</param>
<param>
<name>searchType</name>
<value>0</value>
</param>
<param>
<name>searchSource</name>
<value>O</value>
</param>
<param>
<name>searchProfile</name>
<value>IBM_findCatalogEntryByNameAndShortDescription</value>
</param>
</expression-builder>
source: http://158.85.49.234/WEB-INF/config/com.ibm.commerce.catalog-fep/get-data-config.xml
So this tag : <expression-template> contains the treasure :), i.e the solr query expression.
2.- With this expression-template we could can create a correct expression:
public String getXPathExpressionString() throws JspException, AbstractBusinessObjectDocumentException {
String expressionTemplate = "{_wcf.ap='$accessProfile$';_wcf.search.profile='$searchProfile$';_wcf.search.category='$categoryId$';_wcf.search.type='$searchType$';_wcf.search.sort='$orderBy$';_wcf.search.source='$searchSource$';_wcf.search.facet='$facet$';_wcf.search.exclude.facet='$filterFacet$';_wcf.search.meta='$metaData$';_wcf.search.price.minimum='$minPrice$';_wcf.search.price.maximum='$maxPrice$'}/CatalogNavigationView";
ExpressionBuilderConfig expressionBuilderConfig = new ExpressionBuilderConfig();
expressionBuilderConfig.setName("getCatalogNavigationView");
expressionBuilderConfig.setDataTypeName("CatalogNavigationView");
expressionBuilderConfig.setExpressionLanguage("_wcf:XPath");
expressionBuilderConfig.setExpressionTemplate(expressionTemplate);
HashMap<String,String[]> parameters = new HashMap<String, String[]>();
parameters.put("accessProfile", new String[]{"IBM_Store_CatalogEntrySearch"});
parameters.put("searchProfile", new String[]{"IBM_findCatalogEntryByNameAndShortDescription"});
parameters.put("searchType", new String[]{"xyz"});
parameters.put("categoryId",new String[]{ "123"});
parameters.put("minPrice",new String[]{"0"});
ExpressionType expressionType = expressionBuilderConfig.buildExpression(parameters);
return expressionType.getValue();
}
-------------------------------*-------------------------------------
This can be used to convert websphere ecommerce in a back-end or service provider. With that we can stop using jsp, scriplets, dojo 1.5 and use whatever in front-end layer like current js frameworks.

Resources