Get Web Content/Journal Article Fields Data Programmatically using SAX Parser


We already see in my previous blog on  Structues and Tempelates  that Liferay Stores Structues in xml format. So if you create a Web Content using Structures and Template and want to get the value of fields programmatically , than you can use SAXReaderUtil Class of Liferay. This class is used to parse xml content.


Ex- I already Created a Structure MOBILE_STRUCTURE which contain 5 fields Brand,Model,Description,Camera and Price.Now i create web contents Sony Xperia C using this structures .This data is save in journalarticle table as:-



Here the Content column store the data in xml as:-

<?xml version="1.0"?>
<root available-locales="en_US" default-locale="en_US">
<dynamic-element name="Brand" index="0" type="text" index-type="keyword">
<dynamic-content language-id="en_US"><![CDATA[Sony]]></dynamic-content>
</dynamic-element>
<dynamic-element name="Model_Number" index="0" type="text" index-type="keyword">
<dynamic-content language-id="en_US"><![CDATA[Experia C]]></dynamic-content>
</dynamic-element>
<dynamic-element name="Description" index="0" type="text" index-type="keyword">
<dynamic-content language-id="en_US"><![CDATA[Contain Front Camera]]></dynamic-content>
</dynamic-element>
<dynamic-element name="Camera" index="0" type="list" index-type="keyword">
<dynamic-content language-id="en_US"><![CDATA[Yes]]></dynamic-content>
</dynamic-element>
<dynamic-element name="Price" index="0" type="text" index-type="keyword">
<dynamic-content language-id="en_US"><![CDATA[12000]]></dynamic-content>
</dynamic-element>
</root>
view raw Xperia.xml hosted with ❤ by GitHub

So What if we want to fetch the fields like Price of Sony Xperia C programmatically. Just use  SAXReaderUtil as:-

Document document = SAXReaderUtil.read(journalArticleObject.getContentByLocale(Locale.ENGLISH.toString()));
Node brandNode = document.selectSingleNode("/root/dynamic-element[@name='Brand']/dynamic-content");
String brand = brandNode.getText();
Node modelNumberNode = document.selectSingleNode("/root/dynamic-element[@name='Model_Number']/dynamic-content");
String modelNumber = modelNumberNode.getText();
Node descriptionNode = document.selectSingleNode("/root/dynamic-element[@name='Description']/dynamic-content");
String description = descriptionNode.getText();
Node cameraNode = document.selectSingleNode("/root/dynamic-element[@name='Camera']/dynamic-content");
String camera = cameraNode.getText();
Node priceNode = document.selectSingleNode("/root/dynamic-element[@name='Price']/dynamic-content");
String price = priceNode.getText();
view raw Data.java hosted with ❤ by GitHub




For getting JournalArticle object you may refer my previous blog on Fetch Web Content Programmatically.

Hope this will Help....

Related Post:-

Fetch/Retrieve Web Content (By Providing Structures and Categories) Programmaticlly in Liferay


Today we will discuss how to Retrieve/Fetch a web content by providing categories and structures in Liferay. Basically we filter Web contents as our Asset Publisher portlet do in Liferay.Before reading this blog you must know how to Create Categories, Structures and Templates. For this you may refer my previous blogs on Web Contents.

For this I already created 3 things:-

1)Categories:- Nokia, Sony and Camera . 
2)Web Contents:- I also created 4 web Contents and associated with Categories as:- 

  • Nokia 1600-->Nokia
  • Nokia Lumia 520--> Nokia and Camera
  • Sony Xperia C --> Sony and Camera
  • Sony Xperia L --> Sony and Camera

3)Structure:- MOBILE_STRUCTURE

So lets start step by step:-





Step 1:-Create Liferay Project and Portlet
Create a Liferay Project in eclipse and then create a portlet in the Project.For theses you may refer Step 1 and Step 2 of my previous blog Here .

Step 2:-Fetch Structure Ids by Structure Names
For filtering on the basis of Structures first we have to find Structure Ids by providing Structure Names as:-

public static long[] getStructureIdByName(List<String> structureNames) {
long[] allStructureIds = new long[structureNames.size()];
try {
List<DDMStructure> ddmStructures = DDMStructureLocalServiceUtil.getDDMStructures(0, DDMStructureLocalServiceUtil.getDDMStructuresCount());
int counter = 0;
for (DDMStructure structure : ddmStructures) {
for (String name : structureNames) {
if (structure.getName(Locale.ENGLISH).equalsIgnoreCase(name)) {
allStructureIds[counter] = structure.getStructureId();
counter++;
continue;
}
}
}
} catch (SystemException e) {
e.printStackTrace();
}
return allStructureIds;
}


Step 3:-Fetch Category Ids by Category Names
For filtering on the basis of Categories, we have to find category Ids by providing Category Names as:-

public static long[] getCategoryIdByName(List<String> categoryName) {
long[] allCategoryIds = null;
List<Long> allCategoriesList = new ArrayList<Long>();
try {
List<AssetCategory> assetCategory = AssetCategoryLocalServiceUtil.getAssetCategories(0, AssetCategoryLocalServiceUtil.getAssetCategoriesCount());
for (AssetCategory asset : assetCategory) {
for (String name : categoryName) {
if (asset.getName().equalsIgnoreCase(name)) {
allCategoriesList.add(asset.getCategoryId());
continue;
}
}
}
} catch (SystemException e) {
e.printStackTrace();
}
if ((allCategoriesList != null) && (allCategoriesList.size() > 0)) {
allCategoryIds = new long[allCategoriesList.size()];
for (int i = 0; i < allCategoriesList.size(); i++) {
allCategoryIds[i] = allCategoriesList.get(i);
}
}
return allCategoryIds;
}
view raw Category.java hosted with ❤ by GitHub


Step 4:-Fetch Asset Entries by Creating Query
Now we have Structure Ids(By Step 1) and Category Id(By Step 2) so create a AssetQuery and get List of Asset Entries by providing both:-

public static List<AssetEntry> getSelectedAssetEntry(List<String> categoryName){
List<AssetEntry>assetEntry = new ArrayList<AssetEntry>();
try {
AssetEntryQuery assetEntryQuery = new AssetEntryQuery();
//assetEntryQuery.setAnyCategoryIds(getCategoryIdByName(categoryName));// Represent Any ie OR
assetEntryQuery.setAllCategoryIds(getCategoryIdByName(categoryName)); // Represent Both ie AND
assetEntryQuery.setClassName(JournalArticle.class.getName());
List<String>structureNames = new ArrayList<String>();
structureNames.add("MOBILE_STRUCTURE");
long [] structureIds= getStructureIdByName(structureNames);
assetEntryQuery.setClassTypeIds(structureIds);
assetEntry = AssetEntryServiceUtil.getEntries(assetEntryQuery);
} catch (Exception exc) {
exc.printStackTrace();
}
return assetEntry;
}
view raw AssetEntry.java hosted with ❤ by GitHub

Explanation:-
Here we create a AssetEntryQuery Object which contain many methods to filter out the result.Ex - setAllCategoryIds which represent OR operation between Categories.


Step 5:-Get Web Contents by AssetEnties
In Step 3 we have List of AssetEntries Now we fetch web contents by Providing AssetEntries as:-

public static List<JournalArticle> getSelectedWebContents(List<AssetEntry> assetEntries) {
List<JournalArticle> journalArticles = new ArrayList<JournalArticle>();
JournalArticleResource journalArticleResource = null;
JournalArticle journalArticle = null;
for (AssetEntry entry : assetEntries) {
try {
journalArticleResource = JournalArticleResourceLocalServiceUtil.getJournalArticleResource(entry.getClassPK());
journalArticle = JournalArticleLocalServiceUtil.getLatestArticle(journalArticleResource.getResourcePrimKey());
} catch (Exception e) {
e.printStackTrace();
}
journalArticles.add(journalArticle);
}
return journalArticles;
}
view raw WebContent.java hosted with ❤ by GitHub

Now by Writing all methods .My Controller become:-

package com.test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portlet.asset.model.AssetCategory;
import com.liferay.portlet.asset.model.AssetEntry;
import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
import com.liferay.portlet.asset.service.AssetEntryServiceUtil;
import com.liferay.portlet.asset.service.persistence.AssetEntryQuery;
import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
import com.liferay.portlet.journal.model.JournalArticle;
import com.liferay.portlet.journal.model.JournalArticleResource;
import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
import com.liferay.portlet.journal.service.JournalArticleResourceLocalServiceUtil;
import com.liferay.util.bridges.mvc.MVCPortlet;
public class Demo extends MVCPortlet {
@Override
public void doView(RenderRequest renderRequest,RenderResponse renderResponse) throws IOException, PortletException {
List<String>categoryList = new ArrayList<String>();
categoryList.add("Nokia");
categoryList.add("Camera");
List<JournalArticle> journalArticles = getSelectedWebContents(getSelectedAssetEntry(categoryList));
for (JournalArticle journalArticle : journalArticles) {
System.out.println("Title=>"+journalArticle.getTitle(Locale.ENGLISH));
}
super.doView(renderRequest, renderResponse);
}
public static List<JournalArticle> getSelectedWebContents(List<AssetEntry> assetEntries) {
List<JournalArticle> journalArticles = new ArrayList<JournalArticle>();
JournalArticleResource journalArticleResource = null;
JournalArticle journalArticle = null;
for (AssetEntry entry : assetEntries) {
try {
journalArticleResource = JournalArticleResourceLocalServiceUtil.getJournalArticleResource(entry.getClassPK());
journalArticle = JournalArticleLocalServiceUtil.getLatestArticle(journalArticleResource.getResourcePrimKey());
} catch (Exception e) {
e.printStackTrace();
}
journalArticles.add(journalArticle);
}
return journalArticles;
}
public static List<AssetEntry> getSelectedAssetEntry(List<String> categoryName){
List<AssetEntry>assetEntry = new ArrayList<AssetEntry>();
try {
AssetEntryQuery assetEntryQuery = new AssetEntryQuery();
//assetEntryQuery.setAnyCategoryIds(getCategoryIdByName(categoryName));// Represent Any ie OR
assetEntryQuery.setAllCategoryIds(getCategoryIdByName(categoryName)); // Represent Both ie AND
assetEntryQuery.setClassName(JournalArticle.class.getName());
List<String>structureNames = new ArrayList<String>();
structureNames.add("MOBILE_STRUCTURE");
long [] structureIds= getStructureIdByName(structureNames);
assetEntryQuery.setClassTypeIds(structureIds);
assetEntry = AssetEntryServiceUtil.getEntries(assetEntryQuery);
} catch (Exception exc) {
exc.printStackTrace();
}
return assetEntry;
}
public static long[] getCategoryIdByName(List<String> categoryName) {
long[] allCategoryIds = null;
List<Long> allCategoriesList = new ArrayList<Long>();
try {
List<AssetCategory> assetCategory = AssetCategoryLocalServiceUtil.getAssetCategories(0, AssetCategoryLocalServiceUtil.getAssetCategoriesCount());
for (AssetCategory asset : assetCategory) {
for (String name : categoryName) {
if (asset.getName().equalsIgnoreCase(name)) {
allCategoriesList.add(asset.getCategoryId());
continue;
}
}
}
} catch (SystemException e) {
e.printStackTrace();
}
if ((allCategoriesList != null) && (allCategoriesList.size() > 0)) {
allCategoryIds = new long[allCategoriesList.size()];
for (int i = 0; i < allCategoriesList.size(); i++) {
allCategoryIds[i] = allCategoriesList.get(i);
}
}
return allCategoryIds;
}
public static long[] getStructureIdByName(List<String> structureNames) {
long[] allStructureIds = new long[structureNames.size()];
try {
List<DDMStructure> ddmStructures = DDMStructureLocalServiceUtil.getDDMStructures(0, DDMStructureLocalServiceUtil.getDDMStructuresCount());
int counter = 0;
for (DDMStructure structure : ddmStructures) {
for (String name : structureNames) {
if (structure.getName(Locale.ENGLISH)
.equalsIgnoreCase(name)) {
allStructureIds[counter] = structure.getStructureId();
counter++;
continue;
}
}
}
} catch (SystemException e) {
e.printStackTrace();
}
return allStructureIds;
}
}
view raw Demo.java hosted with ❤ by GitHub


Step 6:-Output

1)If input is:-
List<String>categoryList = new ArrayList<String>();
categoryList.add("Nokia");
categoryList.add("Camera");
List<JournalArticle> journalArticles = getSelectedWebContents(getSelectedAssetEntry(categoryList));
for (JournalArticle journalArticle : journalArticles) {
System.out.println("Title=>"+journalArticle.getTitle(Locale.ENGLISH));
}
view raw Output1.java hosted with ❤ by GitHub

Then Output is:-
Title=>Nokia Lumia 520

2)If input is:-
List<String>categoryList = new ArrayList<String>();
categoryList.add("Nokia");
List<JournalArticle> journalArticles = getSelectedWebContents(getSelectedAssetEntry(categoryList));
for (JournalArticle journalArticle : journalArticles) {
System.out.println("Title=>"+journalArticle.getTitle(Locale.ENGLISH));
}
view raw Output2.java hosted with ❤ by GitHub

Then Output is:-
Title=>Nokia Lumia 520
Title=>Nokia 1600

You Can Check Other Combination also by Download the code.




Hope this will Help....

You can Download Source code from  Fetch Web Content Programmatically.

Related Post:-

Structure and Templates for Web Content in Liferay


Today we will discuss about Structure and Templates for Web Content in Liferay . Lets consider a scenario where we have to create 100 web contents for Mobiles which are almost similar except the names, camera ie small differences. So 100 times you have to write the similar HTML. What if you just create a Template one time and use it again and again.This is the main task of structure and Templates in Liferay.


Here we create a Structure and Template that provide user some Text fields and user just enter the values in those fields and web content create automatically. Before reading this blog it is highly recommended to read my previous blog on Basic web content in liferay

So lets start step by step:-





Step 1:-Create Structure for Web Content
Go to Admin->Content->Web Content->Manage->Structure



Then a new window is open Click on Add. After that fill name and details :-



After that create 4 text fields Brand,Model Number,Description , price and one select box Camera using GUI provided by Liferay . By clicking setting tab you can change the label and required properties of the fields



Then Click save.

Step 2:-Create Template for Structure
In this Step we create Template for the structure that is created in Step 1 ie Mobile_Structure . In Template we create static HTML and provide the dynamic fields to it.

Go to Admin->Content->Web Content->Manage->Templates

Provide Name and Select Structure as Mobile_Structure which is created in Step 1. From language select box select Velocity.





After that you can use your fields in HTML as :-



Now Click Save.

Step 3:-Create Web Content
Go to Admin->Content->Web Content->Add->Mobile_Structure



As soon as you select Mobile_Structure .The Structure and Template are already selected here fill the other values like brand , description etc.



Now Click Publish.

Step 4:-Check Output
Now add web Content Display Portlet to your page and select your web content and see the output.



Step 5:-Database Tables

1)ddmstructure
This table contain the structure in xml format in xsd column




2)ddmtemplate
This table save template in script column in Text format



3)journalarticle
Now this table contain the ids of both 



Note:- I hide the other fields in tables SnapShots.




That's it ,Hope this will Help....

Related Post:-

Categorization in Web Content


Today we will discuss about Categorization in Web Content . Here we create multiple web contents and display them based on categories by using Asset Publisher Portlet. Before reading this blog it is highly recommended to read my previous blog on Basic web content in liferay. I already created 4 web content for this blog.

So lets start step by step:-




Step 1:-Create Web Content
Just create 4 basic web contents as discussed in my previous blog .




Step 2:-Create Vocabulary
Go to Admin->Content->Categories->Add Vocabulary



Then provide name and description and click save




Step 3:-Create Categories inside Vocabulary
Select Vocabulary(Mobile) and click Add Category :-


Then Provide name and description for the categories as:-


Here you can see mobile is already selected  in drop down box. Similarly create two more categories Sony and front camera .


Step 4:-Assign Category to a Web Content
Go to web content you already created in step 1 and select web content here i am selecting Nokia Lumia 520 and click on categorization and then a new window is open .From there you can select the categories you created here i am selection Nokia :-




Now Similarly open other web contents and give categories.for ex -

a)Sony Xperia C has two Categories front camera and Sony.
b)Sony Xperia L has two Categories front camera and Sony.
c)Nokia Lumia 620 has two Categories front camera and Nokia.

Step 5:-Add Asset Publisher Portlet to Page
Go to Add symbol click Application and select Asset Publisher 




As soon as you add asset publisher on page all the assets like images, documents and all web contents are displayed.

Step 6:-Configure Asset Publisher
Now click on wrench icon and select Configuration:-



After that a new window is open, apply the configuration here:-
1)In Asset Type select Web Content Article.
2)In Filters select contains, Any, categories. 



Now Click save and refresh the page for output.

Note:- 

1)The Any and All represent AND and OR operation between Categories.
2)Here i am showing some of the configuration there are many others. 

Step 8:-Check Output

1)Selecting Category Nokia only




2)Selecting Category Nokia and Front Camera(Any)



3)Selecting Category Nokia and Front Camera(All)



Step 9:-Database Tables

1)assetvacabulary
The Vocabulary mobile is saved in assetvocabulary:-



2)assetcategory
The categories Nokia, Sony and Front Camera is stored in assetcategory:-



3)assetentries_assetcategories
The mapping of which asset is associated with which category is stored in assetentries_assetcategories:-



Note:- I hide the other fields in tables SnapShots.




Thats it Hope this will Help.

Related Post:-

Basic Web Content in Liferay


Today we will discuss about Basic Web Content in Liferay. But before that we must know what is Web Content.

A web content is a simple static content that can be displayed on a web page. 

Liferay provide a simple way to achieve this . Here we don't need to create any Portlet Just simply use WYSIWUG  HTML editor to create a web content and add to our page.


So lets start this Step by Step:-





Step 1:-Create Web Content
For creating web content Go to:-

Admin->Content->Web Content(On LHS)->Add-> Basic Web Content.



Then Provide Title. Now you have to ways to add the Content:-

A)By Using WYSIWUG Editor
Liferay provide What you see is what you get(WYSIWUG) HTML editor. Here you just use the buttons to create the content.You can provide link ,change text size etc using this.


B)By Directly Pasting HTML file
For This Just Click Source Button and use HTML tags:-



Step 2(Optional):-Set Other Properties

A)Expiration and Review Time
You can set expiration time of web content so that the web content automatically expired on that date here i am using Never. For this Click on Schedule :-



B)Description
You can provide description  about your web content by Clicking on Abstract as:-



Step 3:-Display Web Content on Page
Go to your home page(http://localhost:8080/) click on add symbol and add web content display portlet on your page and than click on select web content as:-



After that a window is open Click your web content and than press Save Button thats it refresh the page and you web Content is displayed on the page as:-


Step 4:-Database tables
Here we see database tables where all these things are stored :-

a)assetentry
As usual when ever you create an asset like upload image in liferay ,create folder etc an entry is put in this table which contain creation date, groupId, companyId etc.



b)journalarticle
As usual when ever you create an asset like upload image in liferay.This table contain the main data ie title,description, expiration date, review date ,content etc.



Content is stored in xml format in content column as:-

<?xml version="1.0"?>
<root available-locales="en_US" default-locale="en_US">
<static-content language-id="en_US"><![CDATA[<p><span style="font-size:24px;"><strong>Brand</strong></span><span style="font-size:22px;">:- Nokia</span></p>
<p><span style="font-size:24px;"><strong>Model Number</strong></span><span style="font-size:22px;">:- Lumia 520</span></p>
<p><span style="font-size:24px;"><strong>Description</strong></span><span style="font-size:22px;">:- Windows Phone with 8 Gb of Internal Memory.</span></p>
<p><span style="font-size:24px;"><strong>Price</strong></span><span style="font-size:22px;">:- Rs 10000</span></p>]]></static-content>
</root>
view raw content.xml hosted with ❤ by GitHub

c)journalarticleresource
This table is mapping table between assetentry and journalarticle table as resourceprimkey column in journalarticle table is same as classPk column in assetentry table.



Note:- I hide the other fields in tables SnapShots.





Thats it Hope this will Help.

Related Post:-

Fetch/Retrive a Document with its Metadata Programmatically in Liferay


In my previous blogs we see how to upload a file with metadata. Now its time to fetch all the data Programmatically .Before reading this blog you must know how to create metadata sets and document type for this you can read my previous blog Save Document with Metadata in Liferay

This can be done in 2 parts:-
  • First we have to create indexer Post Processor hook.
  • Secondly we create Portlet for fetching the data.
For this blog i am using liferay 6.1.

Before start just create Resume(metadata sets) and Resume Type(Document Types) as describe in my previous blog Save Document with Metadata in Liferay

So lets start this step by step:-





Step 1:-Create Indexer Hook
For creating indexer post processor hook you may refer my previous blog Indexer Post Processor Hook in Liferay . Here i just created indexer on DLFileEntry Class and apply indexing on experience.

liferay-hook.xml

<?xml version="1.0"?>
<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.1.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd">
<hook>
<indexer-post-processor>
<indexer-class-name>com.liferay.portlet.documentlibrary.model.DLFileEntry</indexer-class-name>
<indexer-post-processor-impl>com.demo.ExperienceIndexer</indexer-post-processor-impl>
</indexer-post-processor>
</hook>

ExperienceIndexer.java

package com.demo;
import java.util.List;
import java.util.Locale;
import com.liferay.portal.kernel.search.BaseIndexerPostProcessor;
import com.liferay.portal.kernel.search.BooleanQuery;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portlet.documentlibrary.model.DLFileEntry;
import com.liferay.portlet.documentlibrary.model.DLFileEntryMetadata;
import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
import com.liferay.portlet.documentlibrary.service.DLFileEntryMetadataLocalServiceUtil;
import com.liferay.portlet.documentlibrary.service.DLFileEntryTypeLocalServiceUtil;
import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
import com.liferay.portlet.dynamicdatamapping.storage.Fields;
import com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil;
public class ExperienceIndexer extends BaseIndexerPostProcessor {
public void postProcessDocument(Document document, Object obj) throws Exception {
try {
DLFileEntry dLFileEntry = (DLFileEntry) obj;
try {
long fileEntryTypeId = dLFileEntry.getFileEntryTypeId();
DLFileEntryType dLFileEntryType = DLFileEntryTypeLocalServiceUtil.getDLFileEntryType(fileEntryTypeId);
DDMStructure yourStructure = null;
List<DDMStructure> structures = dLFileEntryType.getDDMStructures();
for (DDMStructure struct : structures) {
if (struct.getName((Locale.ROOT)).equalsIgnoreCase("Resume"))// Pass your meta type here
{
yourStructure = struct;
break;
}
}
//System.out.println("My Structure=>"+yourStructure.getName(Locale.ROOT));// this is structure of Resume
DLFileEntryMetadata dlFileEntryMetadata = DLFileEntryMetadataLocalServiceUtil.getFileEntryMetadata
(yourStructure.getStructureId(), dLFileEntry.getFileVersion().getFileVersionId());
Fields fields = StorageEngineUtil.getFields(dlFileEntryMetadata.getDDMStorageId());
String experience = null;
try {
experience = fields.get("experience").getValue().toString();
} catch (Exception e) {
e.printStackTrace();
}
if (experience != null) {
document.addText("YearOfExperience", experience);
//System.out.println("Year of Exp=>"+experience);
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void postProcessSearchQuery(BooleanQuery fullQuery, SearchContext arg1)throws Exception {
String experience = (String) arg1.getAttribute("YearOfExperience");
// System.out.println("Experience in query=>"+experience);
if(experience!=null){
fullQuery.addRequiredTerm("YearOfExperience", experience);
// System.out.println("Full Query=>"+fullQuery);
}
}
}

Explanation:-


  • In the postProcessDocument method we just fetch the metadata experience and add this as a index with key YearOfExperience.This method is called each time when we add a Resume ie Document Type Resume Type.
  • In postProcessSearchQuery method we create a Boolean query and pass experience as a argument.This method is called by our portlet.


Step 2:-Create Portlet that Call Boolean Query
Just create a Liferay Project with MVC portlet in it.Inside the Jsp file paste this content:-

view.jsp
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<portlet:defineObjects />
<portlet:actionURL var="searchData" name="searchData"></portlet:actionURL>
<br>
<b>Enter Number of Years of Experience</b>
<form action="<%=searchData%>" method="post">
Experience:-<input type="text" name="experience" id="experience"><br>
<input type="Submit" name="Submit">
</form>
view raw view.jsp hosted with ❤ by GitHub

And in your controller paste this content:-

Demo.java
package com.test;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import com.liferay.portal.kernel.search.Document;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.search.Hits;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.search.SearchContextFactory;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portlet.documentlibrary.model.DLFileEntry;
import com.liferay.portlet.documentlibrary.model.DLFileEntryMetadata;
import com.liferay.portlet.documentlibrary.model.DLFileEntryType;
import com.liferay.portlet.documentlibrary.service.DLAppServiceUtil;
import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
import com.liferay.portlet.documentlibrary.service.DLFileEntryMetadataLocalServiceUtil;
import com.liferay.portlet.documentlibrary.service.DLFileEntryTypeLocalServiceUtil;
import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
import com.liferay.portlet.dynamicdatamapping.storage.Fields;
import com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil;
import com.liferay.util.bridges.mvc.MVCPortlet;
public class Demo extends MVCPortlet {
public void searchData(ActionRequest request,ActionResponse response)
{
String experience = ParamUtil.getString(request, "experience");
SearchContext searchContext = SearchContextFactory. getInstance(PortalUtil.getHttpServletRequest(request));
searchContext.setAttribute("YearOfExperience", experience);
try {
Hits hits =DLAppServiceUtil.search(new Long(10179), searchContext);//Repository Id of Resume Folder
List<Document> docList = hits.toList();
for ( Document document : docList ){
Map<String, Field> fieldMap = document.getFields();
//Getting Basic Data
String title = fieldMap.get("title").getValue();
String description = fieldMap.get("description").getValue();
long fileEntryId= GetterUtil.getLong(document.get(Field.ENTRY_CLASS_PK));
DLFileEntry dLFileEntry = DLFileEntryLocalServiceUtil.getDLFileEntry(fileEntryId);
DLFileEntryType dLFileEntryType = DLFileEntryTypeLocalServiceUtil.getFileEntryType(dLFileEntry.getFileEntryTypeId());
DDMStructure yourStructure = null;
List<DDMStructure> structures = dLFileEntryType.getDDMStructures();
for (DDMStructure struct : structures) {
if (struct.getName((Locale.ROOT)).equalsIgnoreCase("Resume")) {
yourStructure = struct;
break;
}
}
DLFileEntryMetadata dlFileEntryMetadata = DLFileEntryMetadataLocalServiceUtil.getFileEntryMetadata (yourStructure.getStructureId(),
dLFileEntry.getFileVersion().getFileVersionId());
Fields fields = StorageEngineUtil.getFields(dlFileEntryMetadata.getDDMStorageId());
//Getting all Metadata
String outputExperience = fields.get("experience").getValue().toString();
String name = fields.get("cname").getValue().toString();// same name which we use when create metadata sets Candidate Name
ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
String url = themeDisplay.getPortalURL() + themeDisplay.getPathContext() + "/documents/" + themeDisplay.getScopeGroupId() + "/" +
dLFileEntry.getFolderId() + "/" +title;
System.out.println("Title=>"+title+" , description=>"+description+", Name=>"+name+" ,Experience=>"+outputExperience);
System.out.println("Url=>"+url);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
view raw Demo.java hosted with ❤ by GitHub

Explanation:-
Here when we create SearchContext Object and set the attribute experience in it.This will automatically call the postProcessSearchQuery method of indexer and get the result on the basis of Experience. 

Step 3:-Check the output
Just create a folder and set the document type as "Resume type" as explained in my previous blog and add some document and provide experience as 4.5 or 3.0 etc.Now deploy your portlet and see the output as:-




When  you hit submit see the console :-








Hope this will Help....

You can Download Source code from  Fetch a Document with Metadata Programmatically in Liferay.


Related Post:-

Save a Document with Metadata Programatically in Liferay


In my previous blog we see how to upload a file with metadata associated with it by using Liferay GUI.Today we will discuss how to upload a file or document with metadata in Document and Media Portlet Programmatically. Before reading this blog you must know how to create metadata sets and document type for this you can read my previous blog Save Document with Metadata in Liferay.

So lets start this step by step:-

Step 1:-Create Liferay Project and Portlet
Create a Liferay Project in eclipse and then create a Generic portlet in the Project.For theses you may refer Step 1 and Step 2 of my previous blog Here .





Step 2:-Create Your Form
Open view.jsp and paste this code:-

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<portlet:defineObjects />
<portlet:actionURL var="uplaodData" name="uploadDocument"></portlet:actionURL>
<b>Please Upload a Document</b>
<form action="<%=uplaodData%>" method="post" enctype="multipart/form-data">
Candidate Name:-<input type="text" name="name" id="name"><br>
Experience:-<input type="text" name="experience" id="experience"><br>
File Title:-<input type="text" name="title" id="title"><br>
<input type="file" name="uploadedFile"><br>
File Description:-<input type="text" name="description" >
<br>
<input type="Submit" name="Submit">
</form>
view raw view.jsp hosted with ❤ by GitHub

Explanation:-
Here we create a simple form that contain 4 fields .Two for metadata and other two for document title and description.Form enctype is multipart/form-data because we also upload a file.

Step 3:-Create portlet.properties
Create a property file in src with name portlet.properties and paste this content:-

fileupload.folder.name=Naukri
metadata.sets.name=Resume


Step 4:-Create Controller Class
Open your java class and paste this content:-

package com.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.upload.UploadPortletRequest;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.service.ServiceContext;
import com.liferay.portal.service.ServiceContextFactory;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portlet.documentlibrary.model.DLFileEntry;
import com.liferay.portlet.documentlibrary.model.DLFolder;
import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
import com.liferay.portlet.documentlibrary.service.DLFolderLocalServiceUtil;
import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
import com.liferay.portlet.dynamicdatamapping.storage.Field;
import com.liferay.portlet.dynamicdatamapping.storage.Fields;
import com.liferay.util.portlet.PortletProps;
public class Demo extends GenericPortlet {
private static long PARENT_FOLDER_ID = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID;
private static String ROOT_FOLDER_NAME = PortletProps.get("fileupload.folder.name");
private static String METADATA_SETS_NAME = PortletProps.get("metadata.sets.name");
public void init() {
viewTemplate = getInitParameter("view-template");
}
public void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException {
include(viewTemplate, renderRequest, renderResponse);
}
@Override
public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException {
ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
UploadPortletRequest uploadPortletRequest = PortalUtil.getUploadPortletRequest(request);
String candidateName =ParamUtil.getString(uploadPortletRequest, "name");
String fileDescription = ParamUtil.getString(uploadPortletRequest, "description");
String fileTitle = ParamUtil.getString(uploadPortletRequest, "title");
String experience = ParamUtil.getString(uploadPortletRequest, "experience");
File file = uploadPortletRequest.getFile("uploadedFile");
String mimeType = uploadPortletRequest.getContentType("uploadedFile");
InputStream is = new FileInputStream( file );
String fileName=uploadPortletRequest.getFileName("uploadedFile");
DLFolder folder = null;
ServiceContext serviceContext=null;
try {
folder = DLFolderLocalServiceUtil.getFolder(themeDisplay.getScopeGroupId(), PARENT_FOLDER_ID, ROOT_FOLDER_NAME);
serviceContext = ServiceContextFactory.getInstance(DLFileEntry.class.getName(), uploadPortletRequest);
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
Map<String, Fields> fieldsMap = new HashMap<String, Fields>();
DDMStructure structure = getDDMStructureByName(themeDisplay);
Fields fields = new Fields();
fields.put(new Field("candidate_name",candidateName ));
fields.put(new Field("experience", experience));
fieldsMap.put(structure.getStructureKey(), fields);
DLFileEntry dlFileEntry=null;
try {
dlFileEntry = DLFileEntryLocalServiceUtil.addFileEntry(themeDisplay.getUserId(), themeDisplay.getScopeGroupId(),
themeDisplay.getScopeGroupId(), folder.getFolderId(),fileName, mimeType, fileName, StringPool.BLANK, StringPool.BLANK,
folder.getDefaultFileEntryTypeId(),fieldsMap, file, null, file.length(), serviceContext);
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
DLFileEntryLocalServiceUtil.updateFileEntry(folder.getUserId(), dlFileEntry.getFileEntryId(), file.getName(), mimeType,
fileTitle, fileDescription, "Draft to save",true, dlFileEntry.getFileEntryTypeId(), fieldsMap, file, is,
file.getTotalSpace(), serviceContext);
}
catch (Exception e) {
e.printStackTrace();
}
}
public DDMStructure getDDMStructureByName(ThemeDisplay themeDisplay)
{
DDMStructure structure = null;
try {
List<DDMStructure> structures = DDMStructureLocalServiceUtil.getStructures(themeDisplay.getScopeGroupId());
for (DDMStructure struct : structures) {
if (struct.getName((Locale.ROOT)).equalsIgnoreCase(METADATA_SETS_NAME)) {
structure = struct;
break;
}
}
} catch (SystemException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
return structure;
}
protected void include(String path, RenderRequest renderRequest, RenderResponse renderResponse) throws IOException,PortletException {
PortletRequestDispatcher portletRequestDispatcher = getPortletContext().getRequestDispatcher(path);
if (portletRequestDispatcher == null) {
_log.error(path + " is not a valid include");
} else {
portletRequestDispatcher.include(renderRequest, renderResponse);
}
}
protected String viewTemplate;
private static Log _log = LogFactoryUtil.getLog(Demo.class);
}
view raw Demo.java hosted with ❤ by GitHub

Explanation:-

  • Here we create a method getDDMStructureByName which give us structue  in which we have to save our document.You just pass the name of metadata set to it and will return structure.
  • From line 75 to 80 we create a we create a Map of Metadata fields and pass to addFileEntry method.The "candidate_name" and "experience" is exactly same name that we are using when we create metadata sets.All other detail of this method i already explained in Folder and File Upload Programmatically .



Step 5:-Check Output
Now deploy your portlet and check output as:-
Now go to Resume folder and check uploaded file 




Project Structure:-






Hope this will Help....

You can Download Source code from Save a Document with Metadata Programmatically in Liferay.


Related Post:-