Tuesday, August 11, 2009

Using Json in Liferay

Introduction:
We have 2 Service tiers..

The Local tier - this tier has no permission checks and is simply a clean cut implementation of the business logic of the service.

i.e. you set local-service="true" when you created the entity.

e.g.
UserLocalServiceUtil.updateActive(long userId, boolean active) (re, no permission check is made, use with caution).

The Remote Tier - this tier is designed to include your permission checks and finally calls the underlying Local service to actually perform the service operation. This tier is also the one on which ALL web-service methods are generated. All the HTTP, JSON, and SOAP are backed by the methods found in this tier.

i.e. you set remote-service="true" when you created the entity AND you implemented methods in [Entity]ServiceImpl.java rather than leaving it blank.

e.g.
UserServiceImpl.updateActive(long userId, boolean active) (i.e., makes a permission check internally):
public User updateActive(long userId, boolean active)
throws PortalException, SystemException {

if ((getUserId() == userId) && !active) {
throw new RequiredUserException();
}

UserPermissionUtil.check(
getPermissionChecker(), userId, ActionKeys.DELETE);

return userLocalService.updateActive(userId, active);
}


SO, all webservice methods which call their implementation of "updateActive" on the UserService are backed by this method. Also, this means that the caller must be authenticated in order to be tested for permissions... otherwise the call will fail. So, you need to be authenticated, AND you need to have permission.

How does a JSON method get authenticated when it's called through and ajax call? All our JSON services are passed through an AutoLogin Filter which handles the authentication based on authorization cookies.

Abstraction for using Json in Liferay:

Step 1. generate service layer for your entity with remote-service="true"
eg.


Step 2. In [entity]ServiceImpl write a method which you want to call using Json.
eg. updateName(userName) throws Exception{//your code goes here}.

Step 3. Do ant build-service -Dservice.file=your_service_xml_path from ext/ext-impl

Step 4. Do ant deploy from ext.

Step 5. Check file ext-web/docroot/html/js/liferay/ext_service_unpacked.js is updated with your method or not.

Note: In liferay version 5.2.x onwards this file is "ext_service.js".

Step 6. Include js like this in file in which you want to call json.

Step 7. Call method like this
eg:
function updateName(userName) {
var params = {
userName: userName
};
Liferay.Service.your_entity_namespace.entity_name.updateName(params);
}

14 comments:

DOHUNGTHUAN said...

hi, i'm new user Liferay, i read your post but i don't understand all. you can send full code for me? if you can step by step build portlet with json in liferay, i'm very thanks you. my email: dohungthuan@yahoo.com

kamalkant said...

Are you looking for plugin env portlet or ext env??

James said...

Hi Kamalkant.
My name is Trinh Hoang Nhu and I'm new to liferay too. Can you tutor me step by step creating a liferay portlet with AJAX and JSON support. I don't know how to make an url request. Ex my main portlet class is test.java but i want a jsp page (or servlet) to process AJAX request name testajax.jsp. how can i call testajax.jsp from test_view.jsp (portlet view mode). Do I need to use strut or st...
thank you

Unknown said...

Do you know liferay if yes ??? let me know if u have developed portlet in ext environment. I can teach in ext environment r8 now . You can put ur queries as well.

DOHUNGTHUAN said...

i try write a portlet in ext in eclipse, i want write a portlet can auto refresh data by ajax use webservice and json but not refresh main page. i learning ajax in liferay. do u have idea for my poblem? if u have a example same my poblem, u can send it for me or u can send me your idea.

Nagendra said...

Do i need to do any extra steps if i want to do it in plugin evn?

ashraf said...

Hi kamalkant,
I am able to get the object, but not able parse. How to parse the object from json object to javascript.

Thanks
ashraf

Unknown said...

you can use json.parse e.g
var json = '{"result":true,"count":1}',
obj = JSON.parse(json);

alert(obj.count);

ashraf said...

Thanks kamalkant
sorry i am very new in json and ajax,so i am not able to understand ur reply fully.I send u my code please help me.

function searchSampleAjax() {

var userName=document.getElementById("sstext").value;

var params = {
title: userName
};
var myJSON = new Object();
myJSON =Liferay.Service.CareerPathFinder.CareerPathFinder.getArticle(params);
alert(myJSON );//here i am able to get the object(output [object Object]).The problem is how to get the value from object.

Thanks
Ashraf
ashrafhabibi@gmail.com

Unknown said...

Hi Ashraf,
sorry for late reply. You can use like this.
Liferay.Service.CareerPathFinder.CareerPathFinder.getArticle(params, function(data, status) {
if (status.readyState == 4) { // here data is the json object which contains return values suppose data contains entryId then to get entryId from data use like this data.entryId }
});
hope this helps

Dennis Gearon said...

So the javascript must EVENTUALLY call a url on the site, right? What is this URL and how can it be accessed WITHOUT jscript?

thas said...

i am new in json and ajax. i am using liferay 6.1 . i want email address already exists validation code using onchange (use json) in mvc portlet.
I send u my code please help me.....


function getUserByEmailAddress(companyId, emailAddress) {

<%
String emailAdress = ParamUtil.getString(request, "email");
User userMy = null;

if(Validator.isNotNull(emailAdress)){
userMy = UserLocalServiceUtil.getUserByEmailAddress(themeDisplay.getCompanyId() ,emailAdress);}
%>

var user = Liferay.Service.Portal.User.getUserByEmailAddress({companyId : companyId, emailAddress : emailAddress});
//alert(user);

if(user.emailAddress != null){
alert("This email address already exists");

}

}

Unknown said...

@Dennis Gearon:http:Yes you are right url will be like below for liferay 6.0.
http//[hostname]:[portnumber]/tunnel-web/json?serviceClassName=[serviceName]&serviceMethodName=[serviceMethodName]&[ Appended Parameters]&serviceParameters=[ Service Parameters In same order]

e.g.
http://localhost:8080/tunnel-web/json?serviceClassName=com.test.portlet.book.service.BookServiceUtil&serviceMethodName=updateBook&bookId=2&bookName=java&serviceParameters=[bookId,bookName]

Unknown said...

@thas : Sorry I could not reply since I was busy with my assignments. If you are still looking for answer then use serveResource method