Saturday 12 November 2011

dynamic queries in liferay

This blog is basically for the developers who are new to liferay and they find it difficult to use the dynamic query.
Many a times we may require a data which cannot be accessed by Liferay API.
Liferay provides several ways to define complex queries used in retrieving database data.
The solution is to use the dynamic query.Liferay provides access to Hibernate’s Dynamic Query API.
Advantages of using dynamic query
To perform operation like add,or,max, min,like. etc.
Optimising the query.
Minimal coding.
Accessing the complex data.

A sample queries.
Returning the whole list without restriction.

List results = new ArrayList();
DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(Library.class,PortalClassLoaderUtil.getClassLoader());
results.addAll(LibraryLocalServiceUtil.dynamicQuery(dynamicQuery));
The above query returns list of all Library objects.

Now to add restriction to our dynamic query.
Liferay provides util class called RestrictionsFactoryUtil where in it provides many api to add restictions to our query.
few API are   like, eq, ne , isNull, isNotnull etc.
Restriction is like where attribute what we write in SQL query eg: “select * from library where authorName=’james’;”.
DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(Library.class);
dynamicQuery.add(RestrictionsFactoryUtil.like(“bookName”, “java”));
dynamicQuery.add(RestrictionsFactoryUtil.eq(“author”, “james”));
List results = LibraryLocalServiceUtil.dynamicQuery(dynamicQuery);
The above query returns list of library objects whose author name is james and bookname is like “java”.

By using ProjectionFactoryUtil for dynamic query
The operations that can be performed using ProjectionFactoryUtil are avg,max,min, distinct etc.
DynamicQuery dynamicQuery=DynamicQueryFactoryUtil.forClass(Library.class,PortalClassLoaderUtil.getClassLoader());
dynamicQuery.setProjection(ProjectionFactoryUtil.max(“price”));
List results = LibraryLocalServiceUtil.dynamicQuery(dynamicQuery);

By using DetachedCriteria for the dynamic query.

The operations that can be performed using DetachedCriteria are add,addorder etc.
DetachedCriteria dCriteria = DetachedCriteria.forClass(Library.class);
dCriteria.add(Restrictions.eq(“bookname”, “java”));
dCriteria.addOrder(Order.desc(“price”));
DynamicQuery dynamicQuery = new DynamicQueryImpl(dCriteria);
List results = LibraryLocalServiceUtil.dynamicQuery(dynamicQuery);
The above query returns list of library objects whose bookname is java in a desc order of price.

The packages imports are given below use it appropriately
import com.liferay.portal.kernel.dao.orm.DynamicQuery;
import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil;
import com.liferay.portal.kernel.dao.orm.Projection;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.DetachedCriteria;
import com.liferay.portal.dao.orm.hibernate.DynamicQueryImpl;

Submiting the form with partial page refresh by using alloy-ui

Well i was looking out to submit the form without refreshing the page in Liferay 6. I used Alloy to submit the form
Here is the code that i wrote in jsp file
<portlet:actionURL var=”ajaxURL” windowState=”<%= LiferayWindowState.EXCLUSIVE.toString()%>” />
<aui:script use=”aui-io-request,aui-node” >
Liferay.provide(
window,
‘submitForm’,
function() {
var A = AUI();
A.io.request(‘<%= ajaxURL %>’,{
method: ‘POST’,
form: { id: ‘<portlet:namespace />fm’ },
on: {
success: function(){
alert(“succefully submitted”);
}
}
});
});
</aui:script >
<form action=”<portlet:actionURL/>” method=”POST” id=”<portlet:namespace />fm” name=”<portlet:namespace />fm” >
<input type=”text” name=”<portlet:namespace />companyName”/>
<input type=”submit” value=”submit form”/>

WEB CONTENT FOR EMAIL TEMPLATE

Webcontent for Email Template
This blog will give you an understanding how the journalcontent can be used as a body of the
Email that you want to send as a Notification.
Follow this Steps
step 1:Create a journal Content as per your own requirement.(This article name I'm assuming as Email_Template)
step 2: Specify the name of the JournalArticle in portlet.properties file.So that any point of time you can change the name of the Journal as per your requirement
journal.Emailtemplate=Email_Template
Step 3: Use the following method to invoke the mail trigger which will send an Email with Journal Article
as the body of the email template.
/****** Method to get Journal content as template ******/
public static String getEmailTemplate(long groupId){
String emailTemplate=”";
JournalArticle jae = null;
try{
jae =JournalArticleLocalServiceUtil.getArticleByUrlTitle(groupId,GetterUtil.getString(PortletProps.get(“journal.Emailtemplate”)));
}catch(Exception e){ }
if(Validator.isNotNull(jae)) emailTemplate = jae.getContent();
}
/**************This method should be invoked with appropriate parameters specified  which will send email****/
public void sendMail(String toAddress,long groupId ){
String emailTemplate =”";
String fromAddress = “satya@gmail.com”;
String fromName =”satyam”;
String subject = “Invitaion for my group”;
emailTemplate  = getEmailTemplate(groupId);
try{
InternetAddress from=new InternetAddress(fromAddress,fromName);
InternetAddress to=new InternetAddress(toAddress,”unknown”);
MailMessage message = new MailMessage(from, to, subject, emailTemplate, true);
MailServiceUtil.sendEmail(message);
}
catch(Exception e){
e.printStackTrace();
}
}
Use the appropriate imports for the above piece of code.
import javax.mail.internet.InternetAddress;
import com.liferay.mail.service.MailServiceUtil;
import com.liferay.portal.kernel.mail.MailMessage;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portlet.journal.model.JournalArticle;
import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
import com.liferay.util.portlet.PortletProps;

Connect to different database through service.xml. Liferay6

Suppose you want to access datas from another database using liferay service.ml.
Then you can do this by the following steps.
  1. Create Service.xml
  2. Create ext-spring.xml file path /WEB-INF/src/META-INF/ext-spring.xml
Service.xml entry looks like this
<service-builder package-path=”com.test”>
    <author>satya</author>
<namespace>test</namespace>
<entity name=”competency” local-service=”true” table=”competency” remote-service=”true” data-source=”myDatasource”>
<column name=”userId” type=”long” primary=”true”></column>
<column name=”firstName” type=”String”></column>
<column name=”lastName” type=”String”></column>
</entity></service-builder>
Run Build-service
Here we are telling the service.xml that this entity will use the userdefined datasource “myDatasource” instead of pointing it into liferay defaultdatasource.
this entry has to be created in the ext-spring.xml file
<?xml version=”1.0″?>
<beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” default-destroy-method=”destroy” default-init-method=”afterPropertiesSet” xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd”>
<bean id=”myDatasource” lazy-init=”true”  class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
<property name=”driverClassName” value=”com.mysql.jdbc.Driver” />
<property name=”url” value=”jdbc:mysql://localhost/training?useUnicode=true”/>
<property name=”username” value=”root” />
<property name=”password” value=”root” />
</bean>
<bean id=”liferayHibernateSessionFactory”   class=”com.liferay.portal.spring.hibernate.PortletHibernateConfiguration”>
<property name=”dataSource” ref=”myDatasource” />
</bean>
</beans>
Deploy the portlet
Now your portlet will fetch datas from different database table through the liferay service API.

liferay 6.x Database migration

Here, We are liferay data migrating from HSQLDB to ORACLE DB.


Data migration

In addition, you may plan to move data from Database to database. You can do it by following these steps:
1.       Add ojdbc<VERSION>.jar  in lib/ext (based our target database. Here we are using oracle database().)
2.       Goto Control Panel : Server Administration under the category Server of Control Panel.
2. Click on the tab: Data Migration.
Enter the valid details
JDBC Driver Class Name : oracle.jdbc.driver.OracleDriver ( Enter  your Driver class name)
JDBC URL: jdbc:oracle :thin:@10.10.10.00:0000:ORCL (Enter URL of your driver)
JDBC User Name:test (Enter database user name)
JDBC Password :secret (Enter database  password)
  1. Click on the Execute button to convert existed database to Oracle database. After clicked we will get the below screen shot.

  1. Open tomcat console of the server and check the console messages.  Application it will take backup of all existed table’s data.
  2. Wait until get the below mentioned messages at the end of the tomcat console:
12:04:14,593 DEBUG [MaintenanceUtil:64] Please change your JDBC settings before restarting server

12:04:14,593 INFO  [ConvertProcess:47] Finished conversion for com.liferay.portal.convert.ConvertDatabase in 15359 ms
  1. Shut down the server (Goto D:\iSolutions\Application\tomcat-6.0.29\bin folder and double click on the shutdown.bat)
  2. Open context.xml file(available in D:\iSolutions\Application\tomcat-6.0.29\conf folder) add another resource entry :
<Resource auth="Container" driverClassName="oracle.jdbc.driver.OracleDriver" maxActive="100" maxIdle="30" maxWait="10000" name="jdbc/application" password="secret" type="javax.sql.DataSource" url="jdbc:oracle:thin:@10.16.10.81:1521:ORCL" username="test "/>

Syntax :
 for name=”jdbc/SCHEMA_NAME” . Here we are assuming you created new schema with ‘application’.
For url=”jdbc:oracle:thin:@<DB_SERVER_IP>:<DB_PORT>:DB_SID”



  1. Open portal-ext.properties file(available in D:\iSolutions\Application  folder) and add the below entry :
   jdbc.default.jndi.name=jdbc/application
(Here application is your schema name)




  1. Start server(Goto D:\iSolutions\Application\tomcat-6.0.29\bin folder and double click on the startup.bat) and verify server identify oracle dialect or not. (identified from the tomcat console.)
Sample msg:
 12:38:31,171 INFO  [DialectDetector:69] Determining dialect for Oracle 10
12:38:31,593 INFO  [DialectDetector:49] Using dialect org.hibernate.dialect.Oracle10gDialect



Tuesday 8 November 2011

Get community level role in Themes

You can write the following code in init_custom.vm

#* Check for Community role for logged in user. *#
#set ($blogEditorCummunityRole = 'Blog Editor')
#set ($userHasBlogEditorRole = 'false')
#* Get Role Local Service *#
#set ($roleLocalService = $serviceLocator.findService("com.liferay.portal.service.RoleLocalService"))
#* Get All community Level Role for current community and Current Logged In User *#
#set ($communityRolesforUser = $roleLocalService.getUserGroupRoles($user_id,$group_id))
#* Iterate through the list of roles and Compare the Blog Editor Role *#
#foreach ($communityRoleforUser in $communityRolesforUser)
         #if ($communityRoleforUser.getName() == $blogEditorCummunityRole)
               #set ($userHasBlogEditorRole= 'true')
          #end
#end

Get community info in theme

#set($currentGroup = $layout.getGroup())
 #set($currentGroupName = $currentGroup.getName())
 #set($currentGroupURL = $currentGroup.getFriendlyURL())

ASSET PUBLISHER FULL CONTENT DISPLAY IN OTHER PAGE


However, it _seems like there is a mechanism in the asset publisher that should handle the situation but may not be implemented fully. In the portlet "Look and Feel" configuration, you can specify an alternate page to send links to. Furthermore, in the asset publisher configuration, the option for "Asset Link Behaviour" shows us "show in a specific portlet".

Now, if these two settings are working together then a user should be able to select a _specific portlet from the page where the look and feel settings are saying to send the links.

Regardless, we did find a workaround using only the UI but it was a bit odd.

1) We created a sub-page of the page that had the asset publisher with the list of abstracts and when that page was created, we made sure to "copy" the parent page. This set us up with a second page that had an asset publisher on it but more importantly, the instanceID of that assets publisher was the same instance ID of the parent page.
2) We reconfigured the asset publisher on the sub page to have "Display style" set to "Full Content"
3) We then set the "Look and Feel" properties of the parent page asset publisher to point the links to the sub page
4) We set the properties of the asset publisher configuration on the parent page to "show in a specific portlet" and viola, it all worked. You can see the result here: