Aug 21, 2013

[Solved] Task cannot continue because ECJ is not installed — in Eclipse ant

I know this is known error but still I put it here as it could be helpful.
   
Task cannot continue because ECJ is not installed.

ECJ was automatically installed.

Please rerun your task. Total time: 1 second    

If you get above error in your IDE, just follow below steps to resolve it.   

  1. In Eclipse, Go To Window --> Preferences --> Ant -> Runtime
  2. Select "Ant Home Entries (Default)"
  3. Add External JAR (ecj.jar)  from your plugin-sdk->lib folder
  4. Ant should now be able to compile from your build.xml

Jul 23, 2013

Embed portlet in theme

  • Create a portlet with any name you want, EX. "portlet-embedded".
  • Write your code in portlet (view.jsp) to be displayed.
  • After adding your code to the portlet deploy the portlet so it is available for to use in theme.
  • Embedding portlet in theme
    • Open the velocity template file in which you want to embed the portlet.
    • Add below code in velocity template.
Code snippet

<div id="embedded-test-div">
$theme.runtime("headercart_WAR_headercartportlet","queryString", $velocityPortletPreferences.toString())
</div>

  • The Red marked line is for to embed a portlet in to theme
    • name="headercart_WAR_headercartportlet" the name of your portlet to be embedded with.
    • queryString="" give queryString if any other wise blank as it is optional.
    • You can set preferences using velocityPortletPreferences string or give blank this is also optional.
  • You are done now deploy the theme and you will get the porltet embedded with theme.
  • For more information do visit the link

Jul 4, 2013

Example of Embedding a portlet in to a web content portlet


  • Create a portlet with any name you want, EX. "portlet-embedded".
  • Write your code in portlet (view.jsp) to be displayed.
  • After adding your code to the portlet deploy the portlet so it is available for to use in web content.
  • Adding web content on page
    • Go to dock bar and select Add button and click Web Content Display so it's add Web Content Display portlet on to your page.
    • After adding web content to page now add the content to web content display by clicking Add Web Content button of Web Content Display portlet. 
Code snippet

   <div id="test-div">
<div id="testdata">
Lorem Ipsum is simply dummy text of the printing
and typesetting industry. Lorem Ipsum has been the
industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and 
scrambled it to make a type specimen book. 
</div>
<div id="embedded-test-div">
            <runtime-portlet 
name="portletembedded_WAR_portletembeddedportlet" 
instance="" queryString=""/>
</div>
</div>


  • The Red marked line is for to embed a portlet in to web content 
    • name="portletembedded_WAR_portletembeddedportlet" the name of your portlet to be embedded with.
    • instance="" give instance name other wise blank.
    • queryString="" give queryString if any other wise blank.
  • After adding this save the web content with proper name.
  • So it display the web content with your data plus the portlet with their data as shown below. 





Jun 13, 2013

IPC using client side java script


  • Introduction

    The client-side mechanism to communicate portlets is based on events,uses events instead of direct js calls accross portlets is very important
    since it's not possible to know at deployment time which other portlets will be available in a given page.

    By firing/triggering an event one portlet just notifies that something has happened,
    and then one or more of the other portlets in the page might be listening and act accordingly.

    Code snippet:

    Example: Updating a label inside second-portlet using a link provided in the first-portlet.

    snippet-1: insert the below code in to docroot/view.jsp of first-portlet.

    <script>
    jQuery(
            function () {
              jQuery('a.change_label').click(
                function(event) {
                  Liferay.fire('changeLabel');
                  return false;
                });
              jQuery('a.remove_label').click(
                function(event) {
                  Liferay.fire('removeLabel');
                  return false;
                });
           }
    );
    </script>
    <a class="change_label">Click here to fire event</a><br/>
    <a class="remove_label">Remove label on second portlet</a>


    snippet-2: insert the below code in to docroot/view.jsp of second-portlet.

    <script>
            Liferay.on(
               'changeLabel',
               function(event) {
                 jQuery('label.info_label').html('Event fired on first-portlet');
               }
            );
            Liferay.on(
               'removeLabel',
               function(event) {
                 jQuery('label.info_label').html('');
               }
            );
                  
    </script>
    <br/><label class="info_label" />

    Deploy these portlets and check how they work.

    Congratulations !!

    NOTE:

     Liferay.trigger(eventName, data)
     Liferay.bind(eventName, function, [scope])
    These methods have been deprecated in Liferay 6 in favor of
     Liferay.fire(eventName, data)
     Liferay.on(eventName, function, [scope])

     For more Information about this please check this link

     

     

May 28, 2013

AUI Carousel using WebContent (Structure/Template)


To Create carousel like above image or as shown on Liferay home page
Follow under Given Steps
  • Create Structure using under given structure.xml code
  • Create Template using under given template.vm code
  • After creating structure and template now just add appropriate parameters and images.
  • And your carousel is ready for you.

There is a nice tutorial on AlloyUI Carousel which describes in detail about it in very simple term.

structure.xml

1234567891011121314151617181920212223242526272829303132333435363738394041424344


<root>
 <dynamic-element name="imageIndex" type="text" index-type="" repeatable="false">
  <meta-data>
   <entry name="displayAsTooltip"><![CDATA[true]]></entry>
   <entry name="required"><![CDATA[false]]></entry>
   <entry name="instructions"><![CDATA[Index of the first visible item of the carousel]]></entry>
   <entry name="label"><![CDATA[Image Index]]></entry>
   <entry name="predefinedValue"><![CDATA[0]]></entry>
  </meta-data>
 </dynamic-element>
 <dynamic-element name="timeInterval" type="text" index-type="" repeatable="false">
  <meta-data>
   <entry name="displayAsTooltip"><![CDATA[true]]></entry>
   <entry name="required"><![CDATA[false]]></entry>
   <entry name="instructions"><![CDATA[Interval time in seconds between an item transition.]]></entry>
   <entry name="label"><![CDATA[Time Interval]]></entry>
   <entry name="predefinedValue"><![CDATA[0.75]]></entry>
  </meta-data>
 </dynamic-element>
 <dynamic-element name="maxImageHeight" type="text" index-type="" repeatable="false">
  <meta-data>
   <entry name="displayAsTooltip"><![CDATA[true]]></entry>
   <entry name="required"><![CDATA[false]]></entry>
   <entry name="instructions"><![CDATA[Provide max height of image element. ex-200]]></entry>
   <entry name="label"><![CDATA[Max Image Height]]></entry>
   <entry name="predefinedValue"><![CDATA[250]]></entry>
  </meta-data>
 </dynamic-element>
 <dynamic-element name="maxImageWidth" type="text" index-type="" repeatable="false">
  <meta-data>
   <entry name="displayAsTooltip"><![CDATA[true]]></entry>
   <entry name="required"><![CDATA[false]]></entry>
   <entry name="instructions"><![CDATA[Provide max width of image element. ex-150]]></entry>
   <entry name="label"><![CDATA[Max Image Width]]></entry>
   <entry name="predefinedValue"><![CDATA[600]]></entry>
  </meta-data>
 </dynamic-element>
 <dynamic-element name="ImageElementSet" type="selection_break" index-type="keyword" repeatable="true">
  <dynamic-element name="image" type="image" index-type="keyword" repeatable="false" />
  <dynamic-element name="linkUrl" type="text" index-type="keyword" repeatable="false"/>
 </dynamic-element>
</root>
Below are the details of some basic parameters that we've defined in structure.xml
  • imageIndex - Index of the first visible item of the carousel
  • timeInterval - Interval time in seconds between an item transition
  • maxImageHeight - Provide max height of image element. ex-200
  • maxImageWidth - Provide max width of image element. ex-150
  • ImageElementSet
    • image - Browse & upload image to be displayed
    • linkUrl - Url of image if you want to make it clickable
     

template.vm

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
#set($imageWidth = $maxImageWidth.Data)
#set($imageHeight = $maxImageHeight.Data)
#set($imageWidthPx = $imageWidth + "px")
#set($imageHeightPx = $imageHeight + "px")
#set($interval = $timeInterval.Data)
#set($activeIndexValue = $imageIndex.Data)
 
<style type="text/css">
        .aui-carousel {
  -moz-user-select: none;
  margin: 20px 0;
 }
 .aui-carousel-item {
  border-radius: 10px 10px 10px 10px;
  text-indent: -9999em;
 }
 .aui-carousel li {
  margin: 0 !important;
 }
</style>
 
#set($totalCount = 0)
<div id="carousal">
 #foreach($imageElement in $ImageElementSet.getSiblings())
  #if($imageElement.image.getData() != "")
   #if($imageElement.linkUrl.getData() != "")
    <a href="$imageElement.linkUrl.Data">
     <img class="aui-carousel-item" src="$imageElement.image.Data" height="$imageHeightPx" width="$imageWidthPx" />
    </a>
   #else
    <img class="aui-carousel-item" src="$imageElement.image.Data" height="$imageHeightPx" width="$imageWidthPx" />
   #end
   #set($totalCount = $totalCount + 1)
  #end
 #end
</div>
 
#if($totalCount > 0)
 <script>
  AUI().ready('aui-carousel', function(A) 
  { 
   var carousel = new A.Carousel(
   { 
    contentBox: '#carousal', 
    activeIndex: $activeIndexValue,
    intervalTime: $interval, 
    width: $imageWidth, 
    height: $imageHeight 
   }).render(); 
  });
 </script>
#end

May 8, 2013

Liferay auto complete field example




  • Create field for auto complete

          <div id="autoCompleteDiv">
               <aui:input type="text" name="xyz" id="txtAutoComplete" label="Auto Complete Field" />
          </div>

         NOTE :- You can use <span> also insted of <div>

  • Create Resource URL

         <portlet:resourceURL var="autoCompleteName" id="resourceId" />


  • Write AUI script for auto complete field

         <aui:script use="aui-autocomplete, autocomplete-filters, autocomplete-highlighters">
                  var dataSource = new A.DataSource.IO(
                  {
                        source: '<%=autoCompletName.toString()%>'
                  });
                  var autocomplete = new A.AutoComplete(
                  {
                             dataSource: dataSource,
                             matchKey: 'name',
                             schema: {
                             resultListLocator: 'response',
                             resultFields: ['key', 'name']
                  },
                    schemaType:'json',
                    contentBox: '#autoCompleteDiv',
                    input:'#<portlet:namespace />txtAutoComplete',
                    typeAhead: false
                   });
                autocomplete.generateRequest = function(query) {
                         return {
                             request: '&keywords=' + query
                         };
                 }
                 autocomplete.render();
                });
         </aui:script>

  • Write Resource method that serve to resource URL

          @ResourceMapping("resourceId")
   public void serveResource(ResourceRequest request, ResourceResponse response)
          {
               JSONObject json = JSONFactoryUtil.createJSONObject();
              JSONArray results = JSONFactoryUtil.createJSONArray();

             String keyword = ParamUtil.getString(resourceRequest, DisplayTerms.KEYWORDS);

             List filteredEntries = getFilteredEntries(keyword);

            for (Object entries : filteredEntries)
            {
               Object[] entry = (Object[]) entries;

               JSONObject listEntry = JSONFactoryUtil.createJSONObject();

              listEntry.put("key", Long.parseLong("" + entry[0]));
              listEntry.put("name", "" + entry[1]);

              results.put(listEntry);
          }
           json.put("response", results);
           PrintWriter writer = resourceResponse.getWriter();
           writer.print(json.toString());

        }

        private static List getFilteredEntries(String query) throws SystemException
       {
            List entries = null;
            DynamicQuery xzyQuery = DynamicQueryFactoryUtil.forClass(Xyz.class);
            if (Validator.isNotNull(query))
           {
             xzyQuery.add(RestrictionsFactoryUtil.ilike("title", "%" + query + "%"));    
         
             ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
             projectionList.add(ProjectionFactoryUtil.property("xyzId"));
             projectionList.add(ProjectionFactoryUtil.property("title"));
             xzyQuery.setProjection(projectionList);

              entries = XyzLocalServiceUtil.dynamicQuery(xzyQuery);
            }
           return entries;
        }

NOTE :- Here I used "@ResourceMapping("resourceId")" because I used Spring, make appropriate changes as per your requirement to call the " serveResource(...)" method.

May 7, 2013

Liferay Custom Query

 Step by step process of "How to use custom query"

There are four steps to create custom query and use it.
NOTE :- Here I assume that you know about liferay service builder.

step 1:- custom-sql folder


  • Create custom-sql folder in docroot/WEB-INF/src package
  • Add new default.xml file in above created folder.
  • The content of default.xml is as under
                <?xml version="1.0" encoding="UTF-8"?>
               <custom-sql>
                  <sql file="custom-sql/query.xml" />
                  <sql file="custom-sql/anotherquery.xml" />
              </custom-sql>
  • You can add multiple sql file in above content.
  • Now create query.xml in same folder
  • Write your sql-query in query.xml as under.
               <?xml version="1.0" encoding="UTF-8"?>
               <custom-sql>
                    <sql id="com.test.services.xyz.service.persistence.uniqueId">


  <![CDATA[
select * from xyz x where x.userId=? AND x.name=?;
  ]]>
  </sql>
           </custom-sql > 
  • The sql id is unique so use the package name of service persistence class and then (xyz) uniqueId.
    • Like "com.test.services.xyz.service.persistence.uniqueId"
    • Here "com.test.services.xyz.service.persistence" is package path of "xyz" service.
    • "Xyz" is the entity name.
    • Here "xyz" is the service created for means table name which we created using service builder.

step 2:- creating service finder impl


  • Create "XyzFinderImpl.java" in "com.test.services.xyz.service.persistence" package of service.
  • NOTE:- Give the name of finder impl related to the service name
    • Here in our case the service is "XYZ" so we create "XyzFinderImpl.java"
  • The content of finder impl is as under
          package com.test.services.xyz.service.persistence;

          import com.liferay.portal.kernel.dao.orm.QueryPos;
          import com.liferay.portal.kernel.dao.orm.SQLQuery;
          import com.liferay.portal.kernel.dao.orm.Session;
          import com.liferay.portal.kernel.exception.SystemException;
          import com.liferay.portal.kernel.util.StringUtil;
          import com.liferay.portal.kernel.util.Validator;
          import com.liferay.portal.service.persistence.impl.BasePersistenceImpl;
          import com.liferay.util.dao.orm.CustomSQLUtil;

          public class XyzFinderImpl extends BasePersistenceImpl<xyz> implements XyzFinder
          {
             public static String CUSTOM_SQL = "com.test.services.xyz.service.persistence.uniqueId";
   
              public List getXYZ(Long userId, String name) throws SystemException
              {
                  Session session = null;
                  String sql = null;
                  try
                  {
                      session = openSession();
                      if (Validator.isNotNull(userId))
                      {
                          sql = CustomSQLUtil.get(CUSTOM_SQL);
                      } 
                      SQLQuery query = session.createSQLQuery(sql);
                      QueryPos qPos = QueryPos.getInstance(query);
                      qPos.add(userId);
                      qPos.add(name);

           //           query.executeUpdate();
                     return (List) query.list();
                  } catch (Exception e)
                  {
                      e.printStackTrace();
                  }
              }

          }

  • Right now "XyzFinder" interface is not available so no need to worry for that.
  • After doing this much build the service again so it's create appropriate classes and interfaces for you.

step 3:-Define method in service Impl


  • Open XyzLocalServiceImpl generated while first time you build service for that.
  • Define method that call the finder method of "XyzFinderImple.java" class as below.
                    public List getUser(Long userId, String name) throws SystemException
                   {
                      return  XyzFinderUtil.getXYZ(userId, name);
                    }
    • Now build service again and after that you are ready to use the custom query.

    step 4:- use of custom-query


    • Call the method as below in your class.
                 List users = XyzLocalServiceUtil.getUser(12345,"test");





    Apr 26, 2013

    Private page as default landing page after login in to Liferay


    1.  Create one public page for login name it (Login) and give friendly url as (/home) or other then login because login is reserved key word of liferay, also do not create other page here(public).

    2.  Now create first private page called (welcome) and give friendly url as(/welcome) or other as per              requirement.

    3.  Create other pages as per requirement on private pages.

    4.  Open control panel-->go to portal settings-->and give default landing page as ("/group/guest/welcome")  the (/welcome) is what we defined on step no 2.

    5.  Also have to give membership to the user.

      5.1   So for that go to control panel-->portal settings-->select tab(Default User Associations)

      5.2  Write the site name(liferay.com) in Sites text field in new line because liferay consider per line user     association.

    And Save it

    That's it you are done.

    NOTE:- You can also set Default Logout Page using step no 4 and set Default Logout Page as (/home) .