Friday, September 13, 2013

Liferay UI Tag liferay-ui:input-move-boxes

Following is the sample code to use liferay-ui:input-move-boxes tag-

1. JSP Code:

<form name=”fm” method=”post” action=”<<actionUrl>>”>
<liferay-ui:input-move-boxes
rightList="<%=rightFields %>"
rightTitle="Right Fields"
rightBoxName="rightFieldsList"
leftList="<%=leftFields%>"
leftTitle="Left Fields"
leftBoxName="leftFieldsList"
leftReorder="true" />
</liferay-ui:panel>
<br />
<liferay-aui:input name="hiddenLeftFields" type="hidden" />
<liferay-aui:input name="hiddenRightFields" type="hidden" />
<input type="button" value="Submit" onclick="<portlet:namespace />submitForm();">
</form>
<liferay-aui:script>
Liferay.provide(
window,
'<portlet:namespace />submitForm',
function() {
document.fm.<portlet:namespace />hiddenLeftFields.value = Liferay.Util.listSelect(document.fm.<portlet:namespace />leftFieldsList);
document.fm.<portlet:namespace />hiddenRightFields.value = Liferay.Util.listSelect(document.fm.<portlet:namespace />rightFieldsList);
document.fm.submit();
}, ['liferay-util-list-fields']
);
</liferay-aui:script>
2. Java Code:
String hiddenLeftFields = ParamUtil.getString(actionRequest, "hiddenLeftFields");
String hiddenRightFields = ParamUtil.getString(actionRequest, "hiddenRightFields");
view raw java-code hosted with ❤ by GitHub

Monday, September 9, 2013

jQuery Autocomplete in Liferay Custom Portlet

In the following post we are going to implement jQuery Autocomplete in our custom portlet.

1. create the service.xml file-

<service-builder package-path="com.sample.harish">
<author>harish.kumar</author>
<namespace>harish</namespace>
<entity name="Student" local-service="true" remote-service="true">
<column name="studentId" type="long" primary="true" />
<column name="studentName" type="String" />
<column name="course" type="String" />
<finder return-type="Collection" name="CourseLike">
<finder-column name="course" comparator="LIKE" />
</finder>
</entity>
</service-builder>
2. Add the finder method in StudentLocalServiceImpl class-

public java.util.List<Student> findByCourseLike(
java.lang.String course)
throws com.liferay.portal.kernel.exception.SystemException {
return StudentUtil.findByCourseLike(course);
}
3. Put the jquery js files in docroot/js folder and add the following entries in liferay-portlet.xml file -

<header-portlet-javascript>/js/jquery.min.js</header-portlet-javascript>
<footer-portlet-javascript>/js/jquery-ui.min.js</footer-portlet-javascript>
4. view.jsp file-

<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css" />
<portlet:defineObjects />
This is the <b>JqueryAutocomplete</b> portlet.
<portlet:resourceURL var="getAutoCompleteData" id="getAutoCompleteData" >
<portlet:param name="action" value="autocompleteCall"/>
</portlet:resourceURL>
<portlet:actionURL name="submitCourse" var="courseUrl" />
<STYLE TYPE="text/css" media="all">
.ui-autocomplete {
position: absolute;
cursor: default;
height: 100px;
overflow-y: scroll;
overflow-x: hidden;
text-align:left;
}
</STYLE>
<script type="text/javascript">
function createAutoComplete(fieldName) {
$('#' + fieldName).autocomplete({
width: 300,
max: 10,
delay: 100,
minLength: 1,
minChars:2,
autoFocus: true,
cacheLength: 1,
scroll: true,
highlight: false,
source: function(request, response) {
$.ajax({
url: "<%= getAutoCompleteData %>" + "&fieldName=" + fieldName,
dataType: "json",
data: request,
success: function(data, textStatus, jqXHR) {
var items = data;
response(items);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log( textStatus);
}
});
}
});
}
$(document).ready(function() {
createAutoComplete("course");
});
</script>
<br/>
<form name="fm" method="post" action="<%=courseUrl%>">
<input type="text" name="course" id="course" value=""/> <br/><br/>
<input type="submit" />
</form>
5. Add the following methods in portlet class-
@Override
public void serveResource(ResourceRequest resourceRequest,
ResourceResponse resourceResponse) throws IOException,
PortletException {
String action = ParamUtil.getString(resourceRequest, "action");
if(action.equals("autocompleteCall"))
{
String fieldName = ParamUtil.getString(resourceRequest, "fieldName");
String term = ParamUtil.getString(resourceRequest, "term");
String res = getAutocompleteListData(fieldName,term);
resourceResponse.getWriter().write(res);
}
}
private String getAutocompleteListData(String fieldName, String term) {
List<String> courseList = new ArrayList<String>();
Gson gson = new Gson();
List<Student> students = null;
try {
students = StudentLocalServiceUtil.findByCourseLike(term + "%");
} catch (SystemException e) {
e.printStackTrace();
}
if (Validator.isNotNull(students)) {
for (Student stud : students) {
courseList.add(stud.getCourse());
}
}
return gson.toJson(courseList);
}
public void submitCourse(ActionRequest request, ActionResponse response)
{
String course = ParamUtil.getString(request, "course");
System.out.println("Process Course: " + course);
}

Sunday, September 1, 2013

Connecting Liferay with Another Database

In the following post we will connect liferay with some third party database (legacy database):

Method 1:

1. Create Service.xml

<entity name="Teacher" local-service="true" remote-service="true" data-source="myDatasource">
<!-- PK fields -->
<column name="teacherId" type="long" primary="true" />
<!-- Other fields -->
<column name="teacherName" type="String" />
</entity>
2. Create ext-spring.xml file as /WEB-INF/src/META-INF/ext-spring.xml

<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-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/harish?useUnicode=true"/>
<property name="username" value="" />
<property name="password" value="" />
</bean>
<bean id="liferayHibernateSessionFactory" class="com.liferay.portal.spring.hibernate.PortletHibernateConfiguration">
<property name="dataSource" ref="myDatasource" />
</bean>
</beans>
view raw ext-spring-1 hosted with ❤ by GitHub
You wont believe but yes we are done!!


Method 2:

1. Make an entry in portal-ext.properties file for another database:

jdbc.default.url=jdbc:mysql://localhost/lportal?useUnicode=true&characterEncoding=UTF-&useFastDateParsing=false
jdbc.default.driverClassName=com.mysql.jdbc.Driver
jdbc.default.username=
jdbc.default.password=
jdbc.test.driverClassName=com.mysql.jdbc.Driver
jdbc.test.url=jdbc:mysql://localhost/harish?useUnicode=true&characterEncoding=UTF-&useFastDateParsing=false
jdbc.test.username=
jdbc.test.password=
view raw portal-ext-db hosted with ❤ by GitHub
2. create service.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.1.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_1_0.dtd">
<service-builder package-path="com.harish">
<author>harish.kumar</author>
<namespace>sample</namespace>
<entity name="Employee" local-service="true" remote-service="true" data-source="testDataSource" session-factory="testSessionFactory" tx-manager="testTransactionManager">
<!-- PK fields -->
<column name="empId" type="long" primary="true" />
<!-- other fields -->
<column name="name" type="String" />
</entity>
</service-builder>
3. create ext-spring.xml file:

<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<aop:config>
<aop:pointcut id="transactionOperation" expression="bean(*Service.impl)" />
<aop:advisor advice-ref="transactionAdvice" pointcut-ref="transactionOperation" />
</aop:config>
<bean id="basePersistence" abstract="true">
<property name="dataSource" ref="testDataSource" />
<property name="sessionFactory" ref="testSessionFactory" />
</bean>
<bean id="transactionAdvice" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="testTransactionManager" />
<property name="transactionAttributeSource">
<bean class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource">
<constructor-arg>
<bean class="com.liferay.portal.spring.annotation.PortalTransactionAnnotationParser" />
</constructor-arg>
</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>
<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>
</beans>
view raw ext-spring-db-2 hosted with ❤ by GitHub

done!


NOTE: In both the above methods, we have to create the table manually in the database.

Liferay Permission on Custom Portlet

As mentioned on Liferay Dcoumentation we can add permissions to your custom portlets using four easy steps (also known as DRAC):

1. Define all resources and their permissions.
2. Register all defined resources in the permissions system. This is also known as adding resources.
3. Associate the necessary permissions with resources.
4. Check permission before returning resources.

Here we are implementing Liferay Permission for custom portlet named StudentMaster.

1. The first step is to define your resources and the actions that can be defined on them. Create a file named default.xml in /src/resource-actions folder -

<?xml version="1.0"?>
<!DOCTYPE resource-action-mapping PUBLIC "-//Liferay//DTD Resource Action Mapping 6.1.0//EN" "http://www.liferay.com/dtd/liferay-resource-action-mapping_6_1_0.dtd">
<resource-action-mapping>
<portlet-resource>
<portlet-name>StudentMaster</portlet-name>
<permissions>
<supports>
<action-key>ADD_STUDENT</action-key>
<action-key>CONFIGURATION</action-key>
<action-key>VIEW</action-key>
</supports>
<site-member-defaults>
<action-key>VIEW</action-key>
</site-member-defaults>
<guest-defaults>
<action-key>VIEW</action-key>
</guest-defaults>
<guest-unsupported>
<action-key>CONFIGURATION</action-key>
</guest-unsupported>
</permissions>
</portlet-resource>
<model-resource>
<model-name>com.harish.model.Student</model-name>
<portlet-ref>
<portlet-name>StudentMaster</portlet-name>
</portlet-ref>
<permissions>
<supports>
<action-key>EDIT_STUDENT</action-key>
</supports>
<site-member-defaults />
<guest-defaults />
<guest-unsupported>
<action-key>EDIT_STUDENT</action-key>
</guest-unsupported>
</permissions>
</model-resource>
</resource-action-mapping>

2. After defining resource permissions for our custom portlet, we need to refer Liferay to the resource-actions XML file that contains definitions. Create a properties file named portlet.properties that references the the file default.xml. In this portlet properties file, create a property named resource.actions.configs with the relative path to portlet’s resource-action mapping file (e.g.default.xml) as its value. Here’s what this property specification might look like:

resource.actions.configs=resource-actions/default.xml

3. Adding a Resource

After defining resources and actions, it’s time to add resources into the permissions system. Resources are added at the same time entities are added to the database. Each Entity that requires access permission must be added as a resource every time it is stored.

public Student addNewStudent(String studentName, String course, long companyId, long groupId, long userId) throws SystemException
{
long studentId = counterLocalService.increment(Student.class.getName());
Student student = studentPersistence.create(studentId);
student.setStudentName(studentName);
student.setCourse(course);
studentPersistence.update(student, false);
try {
resourceLocalService.addResources(companyId, groupId, userId, Student.class.getName(), studentId, false, true, true);
} catch (PortalException e) {
e.printStackTrace();
}
return student;
}
4. Adding Permission:

On the portlet level, no code needs to be written in order to have the permission system work for custom portlet. If we have defined any custom permissions (supported actions) in configuration file’s portlet-resource tag, they’re automatically added to a list of permissions in Liferay’s permissions UI. What good, however, are permissions that are available but can’t be set by users?
To let a user set permissions on model resources, we must expose the permission interface to the user. Just add these two Liferay UI tags to JSP:
1. : Returns a URL to the permission settings configuration page.
2. : Shows an icon to the user. These are defined in the theme, and one of them (see below) is used for permissions.

<liferay-security:permissionsURL
modelResource="<%= Student.class.getName() %>"
modelResourceDescription="<%= \"Student\" %>"
resourcePrimKey="1"
var="entryURL"
/>
<liferay-ui:icon image="permissions" url="<%= entryURL %>" />
view raw permission-icon hosted with ❤ by GitHub
5. Checking Permission:

<portlet:defineObjects />
<liferay-theme:defineObjects />
<%
long groupId = scopeGroupId;
String name = portletDisplay.getRootPortletId();
String primKey = portletDisplay.getResourcePK();
String actionId = "ADD_STUDENT";
%>
This is the <b>Student Master</b> portlet.
<portlet:actionURL var="addStudentUrl" name="addStudent" />
<br/><br/>
<strong>
<%-- portlet level permission check --%
<c:if test="<%= permissionChecker.hasPermission(groupId, name, primKey, actionId) %>">
<a href="<%=addStudentUrl.toString()%>">Add New Student</a>
</c:if>
</strong>
<br/><br/>
<liferay-ui:search-container delta="5" emptyResultsMessage="No Students were found!!">
<liferay-ui:search-container-results results="<%=ListUtil.subList((List<Student>)request.getAttribute(\"students\"), searchContainer.getStart(), searchContainer.getEnd())%>" total="${students.size()}" />
<liferay-ui:search-container-row className="com.harish.model.Student" keyProperty="studentId" modelVar="student">
<liferay-ui:search-container-column-text name="name" value="${student.studentName}" />
<liferay-ui:search-container-column-text name="subject" value="${student.course}" />
<%-- model level permission check --%
<c:if test="<%= permissionChecker.hasPermission(groupId, Student.class.getName(), student.getStudentId(), \"EDIT_STUDENT\") %>">
<liferay-ui:search-container-column-jsp path="/studentActions.jsp" align="right" />
</c:if>
</liferay-ui:search-container-row>
<liferay-ui:search-iterator />
</liferay-ui:search-container>
view raw permission-jsp hosted with ❤ by GitHub