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!!!