1. Create a new liferay project (e.g named.combobox-portlet).
(http://michi-path.blogspot.in/2012/03/create-new-portlet-in-liferay-ide.html)
2. create service.xml (http://michi-path.blogspot.in/2012/03/using-service-builder-very-basic-to.html)
3. Add the following code to your service.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.0.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_0_0.dtd">
<service-builder package-path="me.pd">
<author>priyanka.dhingra</author>
<namespace>COMBOBOX</namespace>
<entity name="Continent" local-service="true" remote-service="true">
<column name="continentCode" type="String" primary="true" />
<column name="continentName" type="String" />
</entity>
<entity name="Country" local-service="true" remote-service="true">
<column name="countryCode" type="String" primary="true" />
<column name="continentCode" type="String" />
<column name="countryName" type="String" />
<column name="fullName" type="String" />
<finder return-type="Collection" name="ContinentCode">
<finder-column name="continentCode" />
</finder>
</entity>
<entity name="States" local-service="true" remote-service="true">
<column name="stateAbbrev" type="String" primary="true" />
<column name="stateName" type="String" />
<column name="countryCode" type="String" />
<finder return-type="Collection" name="CountryCode">
<finder-column name="countryCode" />
</finder>
</entity>
</service-builder>
4. Do ANT build_service and then ANT deploy
5. Populate your tables running the queries from the following:-
(http://michi-path.blogspot.in/2012/03/create-new-portlet-in-liferay-ide.html)
2. create service.xml (http://michi-path.blogspot.in/2012/03/using-service-builder-very-basic-to.html)
3. Add the following code to your service.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.0.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_0_0.dtd">
<service-builder package-path="me.pd">
<author>priyanka.dhingra</author>
<namespace>COMBOBOX</namespace>
<entity name="Continent" local-service="true" remote-service="true">
<column name="continentCode" type="String" primary="true" />
<column name="continentName" type="String" />
</entity>
<entity name="Country" local-service="true" remote-service="true">
<column name="countryCode" type="String" primary="true" />
<column name="continentCode" type="String" />
<column name="countryName" type="String" />
<column name="fullName" type="String" />
<finder return-type="Collection" name="ContinentCode">
<finder-column name="continentCode" />
</finder>
</entity>
<entity name="States" local-service="true" remote-service="true">
<column name="stateAbbrev" type="String" primary="true" />
<column name="stateName" type="String" />
<column name="countryCode" type="String" />
<finder return-type="Collection" name="CountryCode">
<finder-column name="countryCode" />
</finder>
</entity>
</service-builder>
4. Do ANT build_service and then ANT deploy
5. Populate your tables running the queries from the following:-
http://michi-path.blogspot.in/2012/07/sql-queries-for-populating-continent.html
Note: Please edit according to the namespace_tablename. (e.g combobox_states)
6. open your view.jsp (combobox-portlet\docroot\html\comboboxportlet\view.jsp). create a form
<form method="post" action="">
<select id="continent" name="continent"></select>
<select id="country" name="country"></select>
<select id="state" name="state"></select>
<input type="submit" value="save" />
</form>
7. Go to your portlet Class (e.g. ComboboxPortlet.java that extends MVCPortlet).
@override
public void doView(RenderRequest renderRequest,
RenderResponse renderResponse) throws IOException, PortletException {
List <Continent> continentList=null;
try {
continentList = ContinentLocalServiceUtil.findAll();
} catch (SystemException e) {
LOGGER.error("doView() - error listing keys", e);
}
renderRequest.setAttribute("continentList", continentList);
include("/html/comboboxportlet/view.jsp", renderRequest, renderResponse);
}
8. Open me.pd.service.ContinentLocalServiceUtil. Add the following method
public List<Continent> findAll() throws SystemException {
return continentPersistence.findAll();
}
The method we are using in doView has to be declared and defined in this class
9. update your view.jsp with the following code.
<%@page import="com.liferay.portal.kernel.util.Validator"%>
<%@page import="me.pd.model.Continent"%>
<%@page import="java.util.List"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<portlet:defineObjects />
<%
List <Continent> continentListObj = (List <Continent>)request.getAttribute("continentList");
%>
<form method="post" action="">
<select id="continent" name="continent">
<%if(Validator.isNotNull(continentListObj)){
for(Continent con : continentListObj){%>
<option value="<%=con.getContinentCode()%>"><%=con.getContinentName()%></option>
<%}}%>
</select>
<select id="country" name="country"></select>
<select id="state" name="state"></select>
<input type="submit" value="save" />
</form>
Now, you can ANT build-service and deploy the code once and on your browser you'll be able to see the continent values. its great to see first step completed. Now, moving forward to the Country list.
we'll use jquery and ajax call with json feed to get data and serveResource method to fetch the values from the database.
Moving Forward........
10. Update your view,jsp with following code
<%@page import="com.liferay.portal.kernel.util.Validator"%>
<%@page import="me.pd.model.Continent"%>
<%@page import="java.util.List"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<portlet:defineObjects />
<%
List <Continent> continentListObj = (List <Continent>)request.getAttribute("continentList");
%>
<portlet:resourceURL var="fetchValues" ></portlet:resourceURL>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jquery.js"></script>
<script type="text/javascript" >
$(document).ready(function(){
$("#continent").change(function(){
var url="<%=fetchValues%>";
var continentCode=$("#continent").val();
jQuery.getJSON(url+"&continentCode=" +continentCode+"&action=countryValues" , function(data) {
for(i=0;i<data.countryNameCode.length;i++){
countryNameCode = data.countryNameCode[i].split(":");
$("#country").append("<option value='"+ countryNameCode[0] +"'>"+countryNameCode[1]+"</option> " );
}
});
});
$("#country").change(function(){
var url="<%=fetchValues%>";
var countryCode =$("#country").val();
jQuery.getJSON(url+"&countryCode=" +countryCode+"&action=stateValues" , function(data) {
for(i=0;i<data.stateNameCode.length;i++){
stateNameCode = data.stateNameCode[i].split(":");
$("#state").append("<option value='"+ stateNameCode[0] +"'>"+stateNameCode[1]+"</option> " );
}
});
});
});
</script>
<form method="post" action="">
<select id="continent" name="continent">
<%if(Validator.isNotNull(continentListObj)){
for(Continent con : continentListObj){%>
<option value="<%=con.getContinentCode()%>"><%=con.getContinentName()%></option>
<%}}%>
</select>
<select id="country" name="country"></select>
<select id="state" name="state"></select>
<input type="submit" value="save" />
</form>
11. Add serveResource() to your portlet class.
@Override
public void serveResource(ResourceRequest resourceRequest,
ResourceResponse resourceResponse) throws IOException,
PortletException {
JSONObject jsonFeed = JSONFactoryUtil.createJSONObject();
String action = ParamUtil.getString(resourceRequest, "action");
if (action.equalsIgnoreCase("countryValues")) {
String continentCode = ParamUtil.getString(resourceRequest, "continentCode");
JSONArray countryNameCode = JSONFactoryUtil.getJSONFactory()
.createJSONArray();
List<Country> countryList=null;
try {
countryList = CountryLocalServiceUtil
.getByContinentCode(continentCode);
for (Country countryObj : countryList) {
countryNameCode.put( countryObj.getCountryCode() + ":"
+ countryObj.getCountryName());
}
} catch (SystemException e) {
LOGGER.error("SystemException"+e);
}
jsonFeed.put("countryNameCode", countryNameCode );
}
if (action.equalsIgnoreCase("stateValues")) {
String countryCode = ParamUtil.getString(resourceRequest,"countryCode");
JSONArray statesNameCode = JSONFactoryUtil.getJSONFactory()
.createJSONArray();
List<States> statesList=null;
try {
statesList = StatesLocalServiceUtil
.getByCountryCode(countryCode);
for (States countryObj : statesList) {
statesNameCode.put( countryObj.getStateAbbrev()+ ":"
+ countryObj.getStateName());
}
} catch (SystemException e) {
LOGGER.error("SystemException"+e);
}
jsonFeed.put("stateNameCode", statesNameCode );
}
resourceResponse.setContentType("application/json");
resourceResponse.setCharacterEncoding("UTF-8");
resourceResponse.getWriter().write(jsonFeed.toString());
}
13. ANT build-service and deploy
Here it goes, Dependent combo-box is ready...It is always great to see these small functionalities working with just some simple logics...Enjoy!!!
Note: Please edit according to the namespace_tablename. (e.g combobox_states)
6. open your view.jsp (combobox-portlet\docroot\html\comboboxportlet\view.jsp). create a form
<form method="post" action="">
<select id="continent" name="continent"></select>
<select id="country" name="country"></select>
<select id="state" name="state"></select>
<input type="submit" value="save" />
</form>
7. Go to your portlet Class (e.g. ComboboxPortlet.java that extends MVCPortlet).
@override
public void doView(RenderRequest renderRequest,
RenderResponse renderResponse) throws IOException, PortletException {
List <Continent> continentList=null;
try {
continentList = ContinentLocalServiceUtil.findAll();
} catch (SystemException e) {
LOGGER.error("doView() - error listing keys", e);
}
renderRequest.setAttribute("continentList", continentList);
include("/html/comboboxportlet/view.jsp", renderRequest, renderResponse);
}
8. Open me.pd.service.ContinentLocalServiceUtil. Add the following method
public List<Continent> findAll() throws SystemException {
return continentPersistence.findAll();
}
The method we are using in doView has to be declared and defined in this class
9. update your view.jsp with the following code.
<%@page import="com.liferay.portal.kernel.util.Validator"%>
<%@page import="me.pd.model.Continent"%>
<%@page import="java.util.List"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<portlet:defineObjects />
<%
List <Continent> continentListObj = (List <Continent>)request.getAttribute("continentList");
%>
<form method="post" action="">
<select id="continent" name="continent">
<%if(Validator.isNotNull(continentListObj)){
for(Continent con : continentListObj){%>
<option value="<%=con.getContinentCode()%>"><%=con.getContinentName()%></option>
<%}}%>
</select>
<select id="country" name="country"></select>
<select id="state" name="state"></select>
<input type="submit" value="save" />
</form>
Now, you can ANT build-service and deploy the code once and on your browser you'll be able to see the continent values. its great to see first step completed. Now, moving forward to the Country list.
we'll use jquery and ajax call with json feed to get data and serveResource method to fetch the values from the database.
Moving Forward........
10. Update your view,jsp with following code
<%@page import="com.liferay.portal.kernel.util.Validator"%>
<%@page import="me.pd.model.Continent"%>
<%@page import="java.util.List"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<portlet:defineObjects />
<%
List <Continent> continentListObj = (List <Continent>)request.getAttribute("continentList");
%>
<portlet:resourceURL var="fetchValues" ></portlet:resourceURL>
<script type="text/javascript" src="<%=request.getContextPath()%>/js/jquery.js"></script>
<script type="text/javascript" >
$(document).ready(function(){
$("#continent").change(function(){
var url="<%=fetchValues%>";
var continentCode=$("#continent").val();
jQuery.getJSON(url+"&continentCode=" +continentCode+"&action=countryValues" , function(data) {
for(i=0;i<data.countryNameCode.length;i++){
countryNameCode = data.countryNameCode[i].split(":");
$("#country").append("<option value='"+ countryNameCode[0] +"'>"+countryNameCode[1]+"</option> " );
}
});
});
$("#country").change(function(){
var url="<%=fetchValues%>";
var countryCode =$("#country").val();
jQuery.getJSON(url+"&countryCode=" +countryCode+"&action=stateValues" , function(data) {
for(i=0;i<data.stateNameCode.length;i++){
stateNameCode = data.stateNameCode[i].split(":");
$("#state").append("<option value='"+ stateNameCode[0] +"'>"+stateNameCode[1]+"</option> " );
}
});
});
});
</script>
<form method="post" action="">
<select id="continent" name="continent">
<%if(Validator.isNotNull(continentListObj)){
for(Continent con : continentListObj){%>
<option value="<%=con.getContinentCode()%>"><%=con.getContinentName()%></option>
<%}}%>
</select>
<select id="country" name="country"></select>
<select id="state" name="state"></select>
<input type="submit" value="save" />
</form>
11. Add serveResource() to your portlet class.
@Override
public void serveResource(ResourceRequest resourceRequest,
ResourceResponse resourceResponse) throws IOException,
PortletException {
JSONObject jsonFeed = JSONFactoryUtil.createJSONObject();
String action = ParamUtil.getString(resourceRequest, "action");
if (action.equalsIgnoreCase("countryValues")) {
String continentCode = ParamUtil.getString(resourceRequest, "continentCode");
JSONArray countryNameCode = JSONFactoryUtil.getJSONFactory()
.createJSONArray();
List<Country> countryList=null;
try {
countryList = CountryLocalServiceUtil
.getByContinentCode(continentCode);
for (Country countryObj : countryList) {
countryNameCode.put( countryObj.getCountryCode() + ":"
+ countryObj.getCountryName());
}
} catch (SystemException e) {
LOGGER.error("SystemException"+e);
}
jsonFeed.put("countryNameCode", countryNameCode );
}
if (action.equalsIgnoreCase("stateValues")) {
String countryCode = ParamUtil.getString(resourceRequest,"countryCode");
JSONArray statesNameCode = JSONFactoryUtil.getJSONFactory()
.createJSONArray();
List<States> statesList=null;
try {
statesList = StatesLocalServiceUtil
.getByCountryCode(countryCode);
for (States countryObj : statesList) {
statesNameCode.put( countryObj.getStateAbbrev()+ ":"
+ countryObj.getStateName());
}
} catch (SystemException e) {
LOGGER.error("SystemException"+e);
}
jsonFeed.put("stateNameCode", statesNameCode );
}
resourceResponse.setContentType("application/json");
resourceResponse.setCharacterEncoding("UTF-8");
resourceResponse.getWriter().write(jsonFeed.toString());
}
12. Open your CountryLocalServiceImpl class and add the method you used here i.e. CountryLocalServiceUtil.getByContinentCode(continentCode)
public List<Country> getByContinentCode(String continentCode)
throws SystemException {
return countryPersistence.findByContinentCode(continentCode);
}
(Similar is to be done for the states)
StatesLocalServiceUtil.getByCountryCode(countryCode)
public List<States> getByCountryCode(String countryCode)
throws SystemException {
return statesPersistence.findByCountryCode(countryCode);
}
13. ANT build-service and deploy
Here it goes, Dependent combo-box is ready...It is always great to see these small functionalities working with just some simple logics...Enjoy!!!
Nice Example & well explained ever..!!
ReplyDeleteHi,
ReplyDeleteCan we create web service to expose serveResource method? In the serveResource method I am returning a simple json file. This was one of the option I was trying to carry out my task. Other option was to try calling a serveResource method from a standalone java class and it did not work well. Please advice.
Thanks!
Hi Rav,
DeleteThe second option didn't work because you can't call the serveResource method explicitly. It comes in the portlet life cycle.
Regarding first option, it is correct that you can use serveResource method for the webservice because ultimately we have to give and take the data to the view.
Regards,
Ajeet Singh
Hi Ajeet,
Deletecan we call a serverResource() from a liferay portal scheduler? please let me know how to achieve this.
Thanks,
Ravi
Hey Ravi, with a very late reply,
DeleteAs per my knowledge it is not possible to call the serveResource method because it is not possible to get the resourceRequest and resourceResponse objet in the Java class.
Regards,
Ajeet Singh
good example
DeleteHi,
ReplyDeleteNice example but it is working only for first drop down.Can you check and modify how to achieve this.
Regards,
karthik