Tuesday, May 9, 2017

Send Notification to Mobile device using java



This is mobile era. Most of portal have it's own mobile app. Many time we have situation to access portal data from mobile app using web services. Also need to notify mobile user by notification after processing request successfull. I spend more then a day to find the api and implement to achive this requirement. So here i am sharing how we can send mobile notification from java.


public static Response sendAndroidNotification(String deviceToken,String message,String title) {
       OkHttpClient client = new OkHttpClient();
       MediaType mediaType = MediaType.parse("application/json");
       JSONObject obj = new JSONObject();
       JSONObject msgObject = new JSONObject();
       msgObject.put("body", message);
       msgObject.put("title", title);
      // msgObject.put("icon", ANDROID_NOTIFICATION_ICON);
       msgObject.put("color", "#ff0000");

       obj.put("to", deviceToken);
       obj.put("notification",msgObject);

       RequestBody body = RequestBody.create(mediaType, obj.toString());
       Request request = new Request.Builder().url(FIRE_BASE_SERVER_URL).post(body)
               .addHeader("Content-Type", "application/json")
               .addHeader("Authorization", "key="+SERVER_KEY).build();

       Response response;
try {
response = client.newCall(request).execute();
_log.info( "Response : " + response.body().string());
return response;
} catch (IOException e) {
_log.info(e.getMessage(),e);
}

return null;
}


Note:
FIRE_BASE_SERVER_URL = https://fcm.googleapis.com/fcm/send
SERVER_KEY = Your app server key. you can find it from firebase portal.
deviceToken = Your deviceId is generate when you install app. you can find it from firebase portal.


This is very simple implementation to send notification to mobile device using java.

HTH!!

Thank you,
Ketan Savaliya

Tuesday, April 18, 2017

Liferay7: Changes in search container tag

Hi,

Liferay search container is the very common practice for liferay developer to display list of data. So, here is am writing something interesting for search container in liferay new version called Liferay7 or Liferay DXP.

Earlier or older version, we use or setup search container tag like below....

<liferay-ui:search-container
emptyResultsMessage="no-users-were-found"
iteratorURL="<%= iteratorURL %>"
>
          <liferay-ui:search-container-results
                   results="<%= UserLocalServiceUtil.getUser(themeDisplay.getUserId()), searchContainer.getStart(), searchContainer.getEnd(), searchContainer.getOrderByComparator()) %>"
                     total="<%= UserLocalServiceUtil.getUser(themeDisplay.getUserId()).size() %>"
        />
       ...
       ...
       ...
</liferay-ui:search-container>


result & total attribute are configure in the liferay-ui:search-container-results tag. While in DXP version the total attribute move to the liferay-ui:search-container tag. So, we just have to
setup results attribute into liferay-ui:search-container-results. Below is the example how we use search container in liferay7 or DXP.


<liferay-ui:search-container
emptyResultsMessage="no-users-were-found"
iteratorURL="<%= iteratorURL %>"
 total="<%= UserLocalServiceUtil.getUserCount(themeDisplay.getUserId()) %>"
>
              <liferay-ui:search-container-results
                      results="<%= UserLocalServiceUtil.getUser(themeDisplay.getUserId()), searchContainer.getStart(), searchContainer.getEnd(), searchContainer.getOrderByComparator()) %>"            
             />
       ...
       ...
       ...
</liferay-ui:search-container>


total is moved from liferay-ui:search-container-results to liferay-ui:search-container tag is only change in search container in Liferay7 or DXP.

HTH!!

Regards,
Ketan Savaliya

Tuesday, March 28, 2017

Liferay7 : Removed the liferay-ui:journal-article Tag

 Hi,

In liferay till version 6.2, Very easy way to display journal article using `liferay-ui:journal-article`. The `liferay-ui:journal-article` tag has been removed.  Now, You should use the `liferay-ui:asset-display` tag instead. below is the piece example for how to use it.


**Example**

Old code:

    <liferay-ui:journal-article
        articleId="<%= article.getArticleId() %>"
    />

New code:   

 <liferay-ui:asset-display
            className="<%= JournalArticle.class.getName() %>"
            classPK="<%= journalArticle.getResourcePrimKey() %>"
            template="<%= AssetRenderer.TEMPLATE_FULL_CONTENT %>"
        />

HTH!!

Friday, July 29, 2016

Adding a Plugins Portlet to the Liferay Control Panel

A "Gotcha!" situation came up when you need to add your custom portlet to the control panel section.

Now the important thing is that as a developer you can actually decide which of the items on the left menu are shown. in simple words which section of liferay control panel is display.

Furthermore you can add any custom portlet to the desired place[portal, server, content] in the left menu and make it part of the Control Panel. Custom portlet's  liferay-portlet.xml need some entries to be place your custom portlet at desired place in Control Panel. That is look similar to this:

<control-panel-entry-category>portal</control-panel-entry-category> <control-panel-entry-weight>1.0</control-panel-entry-weight>

=> The first element determines to which section of the menu will the portlet be added
     This entry value may be very based on liferay version. here i have given control panel category for Liferay 6.1 and 6.2.
 
   1 )  Liferay 6.1 control panel category values of either my, content, portal, server to place the portlet in the area in the control panel.

  2) Liferay 6.2 control panel category values is extended from the previous version. possible value listed below.
      For My Account Section : my
      For Control Panel Section: users, sites, apps, configuration
      For Site Administration Section: site_administration.pages, site_administration.content, site_administration.users, site_administration.configuration
    
=> The second one determines the position. default value is 1.5.

After doing above configuration for your custom portlet, please deploy and check your control panel respected section.

You are done with what all you need to do, Enjoy!!

HTH!!


Thanks,
Ketan Savaliya

Thursday, July 28, 2016

Create liferay service builder portlet using maven tool

Hello LRExpert,


Now a days maven as building tool is common practice during development. Lifeary is also support maven tool for building liferay plugin. this article is for those who just start using maven or use maven first to create portlet.

Here i have given steps to create new liferay portlet using maven tool. Please follow simple 11 steps given below.

1) Install Maven
    Find specific liferay maven package for liferay version. here in my case i am using liferay-portal-     6.2-ce-ga6. so, supported liferay maven package is liferay-portal-maven-6.2-ce-ga6.zip. liferay         maven package is nothing but just a zip file. unzip that maven package whenever you want. Insall     maven plugin followed by below steps...

    - Open CMD windows
    - Go to directory location where you just unzip file (i.e liferay-portal-maven-6.2-ce-ga6.zip )
    - Execute command Ant istall
    - Wait untill it's finished execution.
    - You are done with you Liferay Maven Plugin Installation.

2) Go to location in CMD window where you need to create liferay maven portlet (suppose d:/lrproject/Source)
     
3) Execute command : mvn archetype:generate
    This will display list of maven project which you can create like...
     ...
     ...
    221: remote -> com.liferay.maven.archetypes:liferay-ext-archetype (Provides an archetype to create Liferay extensions.)
222: remote -> com.liferay.maven.archetypes:liferay-hook-archetype (Provides an archetype to create Liferay hooks.)
223: remote -> com.liferay.maven.archetypes:liferay-layouttpl-archetype (Provides an archetype to create Liferay layout templates.)
224: remote -> com.liferay.maven.archetypes:liferay-portlet-archetype (Provides an archetype to create Liferay portlets.)
225: remote -> com.liferay.maven.archetypes:liferay-portlet-icefaces-archetype (Provides an archetype to create Liferay ICEfaces portlets.)
226: remote -> com.liferay.maven.archetypes:liferay-portlet-jsf-archetype (Provides an archetype to create Liferay JSF portlets.)
227: remote -> com.liferay.maven.archetypes:liferay-portlet-liferay-faces-alloy-archetype (Provides an archetype to create Liferay Faces Alloy portlets.)
228: remote -> com.liferay.maven.archetypes:liferay-portlet-primefaces-archetype (Provides an archetype to create Liferay PrimeFaces portlets.)
229: remote -> com.liferay.maven.archetypes:liferay-portlet-richfaces-archetype (Provides an archetype to create Liferay RichFaces portlets.)
230: remote -> com.liferay.maven.archetypes:liferay-portlet-spring-mvc-archetype (Provides an archetype to create Liferay Spring MVC portlets.)
231: remote -> com.liferay.maven.archetypes:liferay-servicebuilder-archetype (Provides an archetype to create Liferay Service Builder portlets.)
232: remote -> com.liferay.maven.archetypes:liferay-theme-archetype (Provides an archetype to create Liferay themes.)
233: remote -> com.liferay.maven.archetypes:liferay-web-archetype (Provides an archetype to create Liferay webs.)
...
...
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 817: 231 + Enter [Find your liferay plugin type number from above list and enter it as input for above step]

4) After Enter above steps, it's display liferay version list like...
Choose com.liferay.maven.archetypes:liferay-servicebuilder-archetype version:
1: 6.1.0
2: 6.1.1
3: 6.1.2
4: 6.1.10
5: 6.1.20
6: 6.1.30
7: 6.1.30.1
8: 6.2.0-B1
9: 6.2.0-B2
10: 6.2.0-B3
11: 6.2.0-M5
12: 6.2.0-M6
13: 6.2.0-RC1
14: 6.2.0-RC2
15: 6.2.0-RC3
16: 6.2.0-RC4
17: 6.2.0-RC5
18: 6.2.0-ga1
19: 6.2.1
20: 6.2.2
21: 6.2.4
22: 6.2.5
23: 6.2.10.4
24: 6.2.10.5
25: 6.2.10.6
26: 6.2.10.7
27: 6.2.10.8
28: 6.2.10.9
29: 6.2.10.10
30: 6.2.10.11
31: 6.2.10.12
32: 6.2.10.13
33: 6.2.10.14
34: 6.2.10.15
35: 7.0.0-m1
36: 7.0.0-m2
Choose a number: 36: 19 + Enter [Select liferay version, here i am using 6.2.1 ]

5) Define value for property 'groupId': : com.liferay.portlet.search 
    [project groupid in pom.xml]

6) Define value for property 'artifactId': : my-search-portlet

7) Define value for property 'version':  1.0-SNAPSHOT: : SNAPSHOT-1.0.0 
[Optional...Enter your preferred project version. Other wise default 1.0-SNAPSHOT]

8) Define value for property 'package':  com.liferay.project.search: : com.liferay.project.search
[Optional...Enter your preferred package path. Other wise default com.liferay.project.search]

9) Confirm properties configuration:
     groupId: com.liferay.project.search
     artifactId: my-search-portlet
     version: SNAPSHOT-1.0.0
     package: com.liferay.project.search
     Y: : Y [Enter Y for yest, N for no]

10) your cmd screen final output is....
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: liferay-servicebuilder-archetype:6.2.1
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.liferay.project.search
[INFO] Parameter: artifactId, Value: my-search-portlet
[INFO] Parameter: version, Value: SNAPSHOT-1.0.0
[INFO] Parameter: package, Value: com.liferay.project.search
[INFO] Parameter: packageInPathFormat, Value: com/liferay/project/search
[INFO] Parameter: package, Value: com.liferay.project.search
[INFO] Parameter: version, Value: SNAPSHOT-1.0.0
[INFO] Parameter: groupId, Value: com.liferay.project.search
[INFO] Parameter: artifactId, Value: my-search-portlet
[INFO] project created from Archetype in dir: d:\lrproject\Source\my-search-portlet
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 25:01 min
[INFO] Finished at: 2016-07-28T19:29:27+05:30
[INFO] Final Memory: 16M/229M
[INFO] ------------------------------------------------------------------------

11) Enjoy you are Done. [your maven service builder portlet is create @ d:\lrproject\Source\my-search-portlet]


Veryfirst time you looks it's long process, but once you have more practice to create liferay plugin. then it's very easy to create maven project for liferay.

Hope this Help!!

Thanks,
Ketan Savaliya

Get value from Structure Field for Journal Article/Web Content in Liferay.


During your liferay development, many time you need get value from DDM Structure field. So, here i have piece of code which gives you value of structure field for journal article/ web content.

Suppose you have article content field data(from JournalArticle table) something like (Mention only one field for example.)...


<?xml version="1.0"?>

 <root available-locales="en_US" default-locale="en_US">
  <dynamic-element name="country" type="text" index-type="" index="0" instance-id="Page_Title">
  <dynamic-content language-id="en_US"><![CDATA[India]]></dynamic-content>
  </dynamic-element> 
 </root>


Then your code to get value of country field is like...

JournalArticle article = JournalArticleLocalServiceUtil.getArticle(...);

Document document = SAXReaderUtil.read(article.getContent());

Node node = document.selectSingleNode("/root/dynamic-element[@name='country']/dynamic-content");

String country = node.getText();


if you have multiple field then your code looks like...(Suppose your field have two times as repeated field )

1) Access first element value is....

Node node = document.selectSingleNode("/root/dynamic-element[@name='country' and @index='0']/dynamic-content");
String country = node.getText()


2) Access second element value is....

Node node = document.selectSingleNode("/root/dynamic-element[@name='country' and @index='1']/dynamic-content");
String country = node.getText()



HTH...!!!


Thanks,
Ketan Savaliya





Liferay MySQL Error 'option sql_select_limit=default' at line 1

Hello LRDeveloper,

Sometime when you setup your fresh tomcat even you start first time with you mysql db, you got error something like... You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'OPTION SQL_SELECT_LIMIT=DEFAULT' at line 

This is nothing more complex but problem with your tomcat\lib\ext\mysql.jar file. just download update version of mysql connector jar and replace it with old tomcat\lib\ext\mysql.jar. make sure your new file have name like mysql.jar only.

HTH and save you valuable time.

NOTE: above solution is worked for me if i update mysql connector with "mysql-connector-java-5.1.6.jar" version and rename it with mysql.jar. Liferay version i am using 6.1.20.


Thank you!!


Thanks,
Ketan Savaliya

Friday, July 22, 2016

Maven ServiceBuilder stop override portlet-model-hints.xml with lifeary

Hello Liferay Experts,

Here i am sharing some important liferay + maven information. which i got after spending my more then half day, it may help you as well.

This is helpful for those who are working with liferay 6.1 + service builder  + maven build tool. some time you need to change DB field size rather then default size which generate from service builder code.

Obviously liferay expert very well know to change  portlet-model-hints.xml  to increase filed size. if you don't know about that then this is importance for you, you need to change that file. it's famous and well known problem with maven is overriding your portlet-model-hints.xml everytime while you build service. please check MAVEN-37 and LPS-10607 links for reporting @ liferay.

Due to this you want be able to change your filed size because if you change that file and getting that reflect you need service build. as i said earlier service build is again override your changes if you do build service. to overcome/resolve this issue here i come up with workaround and few step to follow....

1.  Your maven portlet parent pom.xml configure the liferay maven plugin for version 6.1.30 like              bellow...
    <build>
<plugins>
<plugin>
                       <groupId>com.liferay.maven.plugins</groupId>
             <artifactId>liferay-maven-plugin</artifactId>
             <version>6.1.30</version>
             .....

        </plugin>
     </plugins>
   </build>

2. Maven portlet parent pom.xml also have entry in dependency for above liferay maven plugin.

     <dependencies>
<dependency>
   <groupId>com.liferay.maven.plugins</groupId>
   <artifactId>liferay-maven-plugin</artifactId>
   <version>6.1.30</version>
</dependency>
</dependencies>


3. Make sure maven porlet all three pom.xml refer the same configuration version of liferay maven     plugin. suppose you have maven portlet name portlet-test then check below files

    -porlet-test/pom.xml
    -porlet-test/portlet-test-porlet/pom.xml 
    -porlet-test/portlet-test-portlet-service/pom.xml

4. Update portlet-model-hints.xml with your required changes something like

    <field name="message" type="String">
<hint-collection name="TEXTAREA" />
    </field>

5. Rebuild service.xml and deploy porlet then check your DB table wether your changes get reflect or     not. i am sure yes it is.

6. Make smiley face.....


Hope this save someone development time and make them relax...!!

Thank you.

NOTE : 
I am working with maven 6.1.2 and liferay 6.1.2 and above solution is perfectly working fine with mentioned version.


Thanks,
Ketan Savaliya


Sunday, August 2, 2015

Upload file with ajax - Liferay

In developer life, to stuck at any point is routine. here is one of the point i am sharing where many of us stuck and it's take lot more times to come out with solution.


Scenario: upload file with Ajax.
Some time we need to upload(by file) some data and process them. but after finished data process page doesn't refreshed. to achieve this we defiantly use Ajax. so, generally we giving <portlet:resourceURL> in form action. form which include input file object. here in this case, if we submit the form and try to get uploaded file in liferay controller. it's doesn't work because of ajax. your serverResource() of  portlet controller is not able to fetch file object from request. because ajax request generally we are passing String & Number data. but this is File so ajax can not handle this tyep of data. after trying more and giving lot more time to resolve this. i found resolution that what i am going to share here....

Here is what you need to do... 

1) JSP contains input-file (With or Without Form)  

<script type="text/javascript" src="/XYZ-porlet/js/ajaxfileupload.js"></script>

  

<portlet:resourceURL var="fileImportURL" id="fileImport"></portlet:resourceURL>

 

<input id="fileUpload" name="file" type="file"  accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel"/>

 

 <input type="button" name="upload" id="upload" value="Upload" onclick="ajaxFileUpload()" />


2) Write JS for AJAX

function ajaxFileUpload(){

$.ajaxFileUpload
    ({
        secureuri : false,
        fileElementId : 'fileUpload',
        data: {name: 'Ketan'},
        url: '<%=fileImportURL%>',
        success: function (data, status)
        {

                 alert("File upload success")
         },
        error: function (data, status, e) {

            alert("File upload faile");
        }
    })
 

   return false;

}

 

3) serveResource() of Liferay Controller

UploadPortletRequest uploadRequest   =  PortalUtil.getUploadPortletRequest(resourceRequest);
File file = uploadRequest.getFile("
fileUpload");

 

 

That's all enough to do for ajax file upload. Enjoy!!

 

 

Click Here to download required js file. 

 

 

Saturday, September 27, 2014

Liferay Category Import Export Apps on Liferay Market Place

Here i am sharing one more my work experience to liferay community.

I hope this may help to many liferay developer during development. it's about import/export functionality of Category.

Many time we need create long list of categories. Once we create all categories structure to particular community or organization then we want to copy whole structure to another community or another server. Currently we don't have any option doing this easily within few clicks. Again we need rework all categories entry.

So, here i come up with solution. I created App for that which is use to import/export category list from or to liferay community or organization.

Here you can find my liferay apps from Liferay market place Liferay Category Import-Export App

Thursday, October 10, 2013

Solr Configuration With Liferay

Hi Liferay Mastreo,

Solr Configuration with lifeary is so easy. here i describable  the steps which i follow for solr configuration with liferay 6.0.


1) Download Solr let-test version from here...

2) Download Apache let-test tomcat for solr (separate from liferay tomcat) from here...

3) Unzip .tar/.zip file of Solr which you downloaded version(in step 1) on your prefered location (ex. D:/Solr)

4) Unzip .tar/.zip file of Solr tomcat which you downloaded version(in step 2)on your preferred location (ex. D:/tomcat)

Configuration Solr with tomcat instance

5) apache-solr-1.4.0.war : copy this file from solr dist directory (here D:/Solr/dist) and past into /example/solr(here D:/Solr/example/solr) directory.

6) Configure Solr data directory path into solrconfig.xml (D:/Solr/exmple/solr/conf/solrconfig.xml)
  - Create directory called data into /example/solr/ (here D:/Solr/example/solr)
  - find <dataDir> tag update path of data directory  in ${solr.data.dir:DATA_PATH}
    (here DATA_PATH in our case D:/Solr/example/solr/data so ${solr.data.dir:D:/Solr/example/solr/data})

7) Create solr.xml into D:/tomcat/tomcat****/conf/Catalina/localhost with below content...
      <?xml version="1.0" encoding="utf-8"?>
      <Context docBase="SOLR_WAR_PATH" debug="0" crossContext="true">
        <Environment name="solr/home" type="java.lang.String" value="SOLR_HOME_PATH" override="true"/>
      </Context>
     ( here,
      SOLR_WAR_PATH is D:/Solr/example/solr/apache-solr-1.4.0.war
      SOLR_HOME_PATH is D:/Solr/example/solr)
8) Now start Solr tomcat from D:/tomcat/tomcat****/bin
9) After start successful of tomcat open solr server in your browser with this link
    http://localhost:port/solr (ex http://localhost:8081/solr)
    If you seen "Welcome to Solr!" screen with "Solr Admin" link then congratulation solr   configuration is done successfully.

Integration/Configuration of Solr plug-in with liferay

1) Download solr-plugin war file for liferay supported version from here ...

2) Put solr-plugin war file into "$LIFERAY_HOME/deploy" directory

3) Start Liferay tomcat to deploy solr plugin into portal.

4) Once liferay tomcat start successful. then stop both liferay tomcat and solr tomcat instance
      NOTE: Now liferay webapps contain "/solr-web" directory

5) Open solr-spring.xml from the $LIFERAY_HOME/tomcat/webapps/solr-web/WEB-INF/classes/META-INF

6) Find string {class="com.liferay.portal.search.solr.server.BasicAuthSolrServer"} which is in one of <bean> entry.

7) Inside that <bean> chagne the value as "solr_url" in value attribute of <constructor-arg />   e.g. <constructor-arg type=”java.lang.String” value=”http://localhost:8081/solr” /> 

8) Replace solr instance schema.xml copy from $LIFERAY_HOME/tomcat/webapps/solr-web/WEB-INF/conf/schema.xml  and paste into $SOLR_HOME/exmple/solr/conf

Finally you have done with configuration of solr with Liferay.

Now, Let's confirm weather is it correct configuration or wrong?  by follow below steps.
1) Open Solr tomcat instance first then liferay tomcat instance

2) Goto control_panel -> server administartion-> reindex all data from here

3) Look into solr tomcat server log : solr log change during reindexe from liferay server
   if it's change it means solr configuration is perfect.


That's it.
Enjoy with Solr!!

Note: here solr tomcat port is change to 8081 because both server not start at same time with same port number. you can change according to that.

Friday, August 23, 2013

ECJ Error : Task cannot continue because ECJ is not installed.

Hi all,

Many of java developer use ANT build tool for his project build process. many of us we got this kind of error. so, here i the solution to resolve this.

Please follow below steps...
1) Download ecj.jar file from  this link                                                                                                  "http://mvnrepository.com/artifact/org.eclipse.jdt.core.compiler/ecj/3.5.1"
2)  Goto the   Window -> Preferences 
     (this will display popup windos)

3)  Click On Ant  -> Runtime 

4) Click on Classpath tab 

5) Select Ant Home Entries (Default) option

6) Click on Add External JARs.. button

7) Select Downloaded file from directory -> open

8) Click on Ok


Now, build your project again with ant command. i am sure you will not get this error again.

That's it!!
Enjoy the code!!


Thank you,
Ketan Savaliya

Map Iterator/loop in java

Many time some little things goes our of our mind. Same thing happen in developer life also.So, here i am going to write a small piece of java code which is used daily routine.

Here i am talking about Collection framework Iteration of MAP.

When ever developer need Map almost all time they go to google for how to iterate MAP? so, ans for this question i am going to write small blog about MAP iteration. Bellow is the example for the same.

About Map : Map is part of collection framework. Mainly use to store data in key,value manner. Given a key and a value, you can store the value in a Map object. After the value is stored, you can retrieve it by using its key. now we go through step by step how to use MAP.



1) Declaration of MAP
        Map<String,String> stringMap = new HashMap<String, String>();

2) Store data into MAP

        stringMap.put("1","Apple" );
        stringMap.put("2","Ball");
        stringMap.put("3","Cat");

3) Iteration/Loop/Use of MAP

There are so many ways you can iterate MAP in java. but here i am going to simple way to iterate MAP in java as per my knowledge.
       - by Iterator
       - by EnterySet
       - by keySet

Here we use keySet to iterator MAP. this is very simple way as per my development experiance. like...

         for(String key : stringMap.keySet()){
                 System.out.println("Key : " + key + ", Value : " + stringMap.get(key) );
         }


4) Exmaple

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class test {

    public static void main(String[] s){
       
        Map<String,String> stringMap = new HashMap<String, String>();
        stringMap.put("3","Cat");
        stringMap.put("1","Apple" );
        stringMap.put("2","Ball");
       
        for(String key : stringMap.keySet()){
            System.out.println("Key : " + key + ", Value : " + stringMap.get(key) );
        }
 }

}


5) Output

Key : 3, Value : Cat
Key : 2, Value : Ball
Key : 1, Value : Apple

It's simple right? still we have to go googling for every time to iterate map. i ma sure this blog visit help you remember iteration of map.

That's it!!

Enjoy the code!!


Thank you,
 Ketan Savaliya


Tuesday, August 6, 2013

Web content data display in custom-portlet

Many more time during development we need display liferay web-content in our custom-portlet.
Liferay taglib already give tag to display web-content data.

Here is syntax for "<liferay-ui:journal-article/>"

<<liferay-ui:journal-article showTitle="true/false" articleId="longArticleId" groupId="longGroupId" />


Let take an example...

<<liferay-ui:journal-article showTitle="false" articleId="<%= journalArticleId%>"
groupId="<%= themeDisplay.getScopeGroupId() %>" />

here journalArticleId is long var which is articelId of web-content

Monday, July 8, 2013

Sorting (Case insensitive) using Custom Comparator in Liferay

Search Container is widely used taglib in Liferay.
We will follow few steps to implement ordering on container columns
 
1) Write below code in your jsp .
<%
 
String orderByCol = ParamUtil.getString(renderRequest, "orderByCol");
String orderByType = ParamUtil.getString(renderRequest, "orderByType"); 
 
/* Code to set default arrow on particular column while landing on this page */
 
PortalPreferences portalPrefs = PortletPreferencesFactoryUtil.getPortalPreferences(request);
 
if (Validator.isNotNull(orderByCol) && Validator.isNotNull(orderByType)) {
portalPrefs.setValue("DemoName", "DemoName-order-by-col", orderByCol);
portalPrefs.setValue("DemoName", "DemoName-order-by-type", orderByType);
 
} else {
 
orderByCol = portalPrefs.getValue("DemoName", "DemoName-order-by-col", "keyProperty");
orderByType = portalPrefs.getValue("DemoName", "DemoName-order-by-type", "desc");
}
 
/* Code to convert asc in desc after clicking on cloumn */
 
if(orderByCol==null || orderByCol.equals(StringPool.BLANK)) {
renderRequest.setAttribute("orderByCol","keyProperty");
}
if(orderByType==null || orderByType.equals(StringPool.BLANK)) {
orderByType="desc";
renderRequest.setAttribute("orderByType",orderByType);
}
%>
 
2) Pass Custom comparator to your search container results.
 
<liferay-ui:search-container orderByCol="<%=orderByCol %>" orderByType="<%=orderByType %>"  iteratorURL="<%=iteratorURL %>"  delta='10'>
<liferay-ui:search-container-results>
<%
 
List<YourModel> lst = lst; //Fetch List for sorting purpose;
if(lst!=null){
Collections.sort(lst,DemoComparatorUtil.getDemoComparator(orderByType, orderByCol)); //Pass custom comparator for sorting
total = lst.size();
results = ListUtil.subList(lst, searchContainer.getStart(), searchContainer.getEnd());
pageContext.setAttribute("results", results);
pageContext.setAttribute("total", total);
 
}
 
%>
 
</liferay-ui:search-container-results>
.
.
.
</liferay-ui:search-container>
 
3) Now create custom comparator mentioned above "DemoComparator" :
 
public class DemoComparatorUtil {


    public static DemoComparator getDemoComparator(String orderByType,String orderByCol){
        DemoComparator demoComparator;    
        
        if (orderByType.equals("desc")) {
            demoComparator = new DemoComparator(false, false);
        } else {
            demoComparator = new DemoComparator(true, false);
        }
        
        if (orderByCol != null) {
            demoComparator.addOrderBy(orderByCol);
        }        
            return demoComparator;    
    }
}
class DemoComparator implements Comparator<YourModel>, Serializable{


        private boolean asc;
        private boolean caseSensitive;
        private List<DocumentComparatorOrderBy> columns = new ArrayList<DocumentComparatorOrderBy>();


    public DemoComparator(){
        this(true,false);
    }

    public DemoComparator(boolean asc, boolean caseSensitive) {
        this.asc = asc;
        this.caseSensitive = caseSensitive;
    }
    
    public void addOrderBy(String name) {
        addOrderBy(name, asc, caseSensitive);
    }

    public void addOrderBy(String name, boolean asc, boolean caseSensitive) {
    DocumentComparatorOrderBy orderBy = new DocumentComparatorOrderBy(name, asc, caseSensitive);
        columns.add(orderBy);
    }
    
    public int compare(YourModel arg0, YourModel arg1) {
    
        int result=0;
        for (DocumentComparatorOrderBy orderBy : columns) {
            String value1 = "";
            String value2 = "";
            
            if (orderBy.getName().equals("keyProperty")) {
                if (!orderBy.isAsc()) {
                    String temp = value1;
                    value1 = value2;
                    value2 = temp;        
                }
            
                if ((value1 != null) && (value2 != null)) {
                    if (orderBy.isCaseSensitive()) {
                        result = value1.compareTo(value2);
                    } else {
                        result = value1.compareToIgnoreCase(value2);
                    }
                }    
            
            }
        
        
            if (result != 0) {
                return result;
            }
        }
        return 0;
    }

}

You can use this single comparator for all columns in your search container by checking key property in if-else condition only.
Enjoy..!!

IPC (Inter Portlet Communication) - in Liferay.

Hi Liferay Developers,

Liferay have so many good feature. IPC is one of them. let me give basic idea about IPC. Basically
IPC is use for Inter Portlet Communication between portlets.

IPC can be achieved in two ways:

1) Public-render-parameter
2) Event-definition




1) Public Render Parameter - IPC

Adding below property in portlet-ext, we can enable portlets to share render states with other portlets that are on different pages:

Changes in portal-ext.properties:

portlet.public.render.parameter.distribution=ALL_PORTLETS



Changes in Pitcher Portlet

Step 1:

Add below attribute in Pitcher Portlet in portlet.xml

<portlet-app>
   <portlet>
         <supported-public-render-parameter>
          name
          </supported-public-render-parameter>
   </portlet>
   <public-render-parameter>
           <identifier>name</identifier>
           <qname xmlns:x="http://ktn.com/anything">x:param1</qname>
    </public-render-parameter>
</portlet-app>

Note: http://ktn.com/anything is userdefine url which you like. i.e. http://testorganizationcom/name


Step 2:
Set render parameter in the processAction() method from the Pitcher Portlet.

public void processAction(
    ActionRequest request, ActionResponse response)
             throws IOException, PortletException {
        response.setRenderParameter("name", "value");
}



Step 3:
Changes Catcher Portlet in portlet.xml, defines which render parameter is shared in portlet section.

<portlet-app>
     <portlet>
              <supported-public-render-parameter>
              name
                </supported-public-render-parameter>
     </portlet>
     <public-render-parameter>
                <identifier>name</identifier>
                <qname xmlns:x="http://ktn.com/anything">x:param1</qname>
     </public-render-parameter>
</portlet-app>


Step 4:
Portlet can read public render parameter using from the Catcher Portlet:

request.getPublicParameterMap()

or can also be read using

request.getParameter(“name”);



2) Event : IPC

Adding below property in portlet-ext, we can enable portlets to share Even states with other portlets.

Changes in portal-ext.properties:

portlet.event.distribution=ALL_PORTLETS



Changes in Pitcher Portlet

Step 1:

Adding attribute in Pitcher Portlet in portlet.xml

This is defines supported-publishing from the pitcher portlet.

<portlet-app>
     <portlet>
                  <supported-publishing-event>
                           <qname xmlns:t="http://liferay.com/events">t:name</qname>
                  </supported-publishing-event>
      </portlet>
       <event-definition>
                  <qname xmlns:t="http://liferay.com/events">t:name</qname>
                  <value-type>java.lang.String</value-type>
      </event-definition>
</portlet-app>

 
Step 2:


Changes in jsp page to

<portlet:actionURL name="myAction" var="actionURL">
</portlet:actionURL>

<a href="<%=actionURL.toString()%>"> Click here </a>

this code is generate event from jsp to controller class of Pitcher portlet.


Step 3:
By using below code line we can communicate between Pitcher and Catcher Portlet.
This is to how we sending event from Pitcher to Catcher portlet.


public void myAction(ActionRequest actionRequest,ActionResponse actionResponse) {
       QName qname = new QName("http://liferay.com/events","name");
       actionResponse.setEvent(qname,"Hello World");
       return;
}


Changes in Catcher Portlet

Step 4:
Adding below entry in Catcher portlet. This is defines supported-processing from the Catcher portlet.

<portlet-app>
       <portlet>          
          <supported-processing-event>
                        <qname xmlns:t="http://liferay.com/events">t:name</qname>
                </supported-processing-event>
       </portlet>

       <event-definition>
                 <qname xmlns:t="http://liferay.com/events">t:name</qname>
                 <value-type>java.lang.String</value-type>
       </event-definition>
</portlet-app>



 Step 5:

By below code line  capture the event in Catcher Portlet.

@Override

public void processEvent(EventRequest request, EventResponse response)
{
         Event event = request.getEvent();
         String name = (String) event.getValue();
         response.setRenderParameter("name", name);  
}



Step 6:
Now, we get this attribute value in jsp page of Catcher portlet.
In view page of Catcher Portlet, by this line we can get value of parameter from Pitcher Portlet.

<% String name = (String)renderRequest.getParameter("name"); %>



That's It for IPC. Enjoy the feature to communicate between portlet to portlet!!!

Wednesday, December 26, 2012

Template : some important variable in template(.vm)

Hi All,

   Many time we use webcontent OOTB functionality for our solution. for that we also use Structure/Template. here Template is render part of WebContent. so many time developer stuck with how to get value of some important properties like theme-dispaly,scopegroupid,image path, etc. so, here give some instruction for that.

1) to get instance of class (some times we can't get accesss class by serviceLocator.findService())
$portal.getClass().forName("com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil").newInstance()   

2)currentScopegroupid 
    - $getterUtil.getLong($request.get("theme-display").get("scope-group-id"))
    - $request.theme-display.scope-group-id
3) images path in theme
    $request.get("theme-display").path-theme-images
4) themeDispaly
    $request.theme-display
5) globalScopeGroupId
    $groupId

5) find service
 $serviceLocator.findService("com.liferay.portlet.documentlibrary.service.DLFileEntryLocalService")


Enjoy!!!

Wednesday, December 19, 2012

Servidce/Util classes access in template (.vm) file in Liferay

Hi Developers,

Many times you need to access services/util class in template. 

Below is some importance hits for the same.

=> Access services using findService method in Velocity(vm)

#set ($userLocalService= $serviceLocator.findService("com.liferay.portal.service.UserLocalService"))
=>Access util class using  findUtil Method for inbuilt Util of Liferay
#set ($journalContentUtil = $utiLocator.findUtil("com.liferay.portlet.journalcontent.util.JournalContentUtil"))
=> some times you also need to access util class which is not have access in template file like StorageEngineUtil. for that you can use below approch..

#set ($util = $portal.getClass().forName("com.liferay.portlet.dynamicdatamapping.storage.StorageEngineUtil").newInstance()) 


HTH.. :))

Wednesday, December 12, 2012

Audio play in portlet using flowplayer.....



For mp3 audio file play you need below plugin swf & js file.

flowplayer.controls-3.2.14.swf
flowplayer.audio-3.2.10.swf
flowplayer-3.2.15.swf
flowplayer-3.2.6.min.js

and here is the sample code snippet to play mp3 audio file which in document library....

<< script type="text/javascript" src="/video-portlet/js/flowplayer-3.2.6.min.js"></script>

<< a href="http://localhost:8080/documents/10180/f7804b0c-9001-4f59-a7b2-45dcbceae8ca" style="display:block;width:520px;height:330px" id="unsecure">
            </a>
<< script type="text/javascript">
        $f("unsecure", "/video-portlet/flowplayer-3.2.15.swf",
                {
                    plugins: {
                        controls: {
                            fullscreen: true,
                            height: 30,
                            autoHide: false
                        },
                        audio: {
                            url: '/video-portlet/flowplayer.audio-3.2.10.swf'
                        }
                    },
                    clip:  {
                         provider: "audio"
                    }
                }
       
       
            );

        </script>


NOTE: "http://localhost:8080/documents/10180/f7804b0c-9001-4f59-a7b2-45dcbceae8ca" is a document library file url.

Monday, September 24, 2012

Connect to Another Datasource/Database Schema from Portlet with service

Hi Folks,

Many developer/client's need to separate the liferay database table and custom database table. so, here is the solution to maintain this approach. for that we maintain two data source/schema for liferay and custom database. we can achieve this by trying to  following steps -

1) portal-ext.properties

Add two connection properties for maintain two differance database source/schema. for example

###### MySQL Connection#######
## Liferay default database connection
jdbc.default.driverClassName=com.mysql.jdbc.Driver
jdbc.default.url=jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
jdbc.default.username=root
jdbc.default.password=root

## Your new database connection
jdbc.test.driverClassName=com.mysql.jdbc.Driver
jdbc.test.url=jdbc:mysql://localhost/mytest?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
jdbc.test.username=root
jdbc.test.password=root

2) ext-spring.xml

    create ext-spring.xml in docroot\WEB-INF\src\META-INF\ of you portlet to connect with other database shema default then liferay. copy the below content and paste in newly created file.
   
<<?xml version="1.0"?>
<<beans
    default-destroy-method="destroy"
    default-init-method="afterPropertiesSet"   
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
>

    <<bean id="testDataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
        <<property name="targetDataSource">
            <<bean class="com.liferay.portal.dao.jdbc.util.DataSourceFactoryBean">
                <<property name="propertyPrefix" value="jdbc.test."/>
            <</bean>
        <</property>
    <</bean>
   
   
    <<bean id="testHibernateSessionFactory" class="com.liferay.portal.spring.hibernate.PortletHibernateConfiguration" lazy-init="true">
        <<property name="dataSource" ref="testDataSource" />       
    <</bean>
   

    <<bean id="testSessionFactory" class="com.liferay.portal.dao.orm.hibernate.SessionFactoryImpl" lazy-init="true">       
        <<property name="sessionFactoryImplementor" ref="testHibernateSessionFactory" />
    <</bean>
   
    <<bean id="testTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" lazy-init="true">
        <<property name="dataSource" ref="testDataSource" />
        <<property name="globalRollbackOnParticipationFailure" value="false"/>
        <<property name="sessionFactory" ref="testHibernateSessionFactory" />
    <</bean>

<</beans>

3) service.xml
    create entity with the parameter data-source,session-factory,tx-manager to connect other then default database. for example....
   
    <<entity name="MyTable" local-service="true" remote-service="false" data-source="testDataSource" session-factory="testSessionFactory" tx-manager="testTransactionManager">


4) service.properties

   check the entry of ext-spring.xml in \docroot\WEB-INF\src\service.properties file(some version of liferay have already this entry). if it is not there then append spring.configs properties with the value "WEB-INF/classes/META-INF/ext-spring.xml"
  
  
 At Last......

 After deploying portlet, custom portlet are able to connect with other then default database source/schema .

 NOTE :
 1)This example is  based on Liferay 6.0 and 6.0.29 tomcat bundle. you have to do specific changes in any of file(.xml) if needed based on Liferay version.
 2)While you connect with other then default liferay database source/schema. service-builder can't create automatically table in database. you have to create table manually. then after you can CURD operation for you custom table same as liferay default database.