Posts

Showing posts from 2015

Liferay Input Move boxes

Image
In Liferay we have one more taglib called input-moveboxes , where we can move the items from left to right viceversa. Which can be look like as below, Here the Code, <%@page import="com.liferay.portal.kernel.util.KeyValuePair"%> <%@page import="java.util.ArrayList"%> <%@page import="java.util.List"%> <%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %> <%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %> <portlet:defineObjects /> <% List<KeyValuePair> leftList = new ArrayList<KeyValuePair>(); leftList.add(new KeyValuePair("1", "Blog")); leftList.add(new KeyValuePair("2", "Asset Publisher")); leftList.add(new KeyValuePair("3", "Wiki")); leftList.add(new KeyValuePair("4", "Message Board")); leftList.add(new KeyValuePair("5", "

Steps to follow to deploy/undeploy the EXT

As we know that EXT is not hot deployable , we need to restart the server whenever it is deployed. At first time we can deploy the EXT without any prob, but when we need to redeploy or undploying the EXT following things need to be followed. 1. Stop the tomcat server 2. Delete the temp and work folder of tomcat server. It will be reside in the <tomcat-home>. Probably it can as  liferay-portal-6.2.10.1-ee-ga1\tomcat-7.0.42\temp and  liferay-portal-6.2.10.1-ee-ga1\tomcat-7.0.42\work. 3. Make sure to delete the JAR files created when EXT is deployed. All the jar files will be created with name prefix as ext . Jar files will be at <tomcat-home>/lib/ext it can  liferay-portal-6.2.10.1-ee-ga1\tomcat-7.0.42\lib\ext.                 ext-*-ext-service.jar Also it can also be at <tomcat-home>/ROOT/WEB-INF/lib/ probably it can be as  liferay-portal-6.2.10.1-ee-ga1\tomcat-7.0.42\webapps\ROOT\WEB-INF\lib                 ext-*-ext-impl.jar                 ext-*-e

UnderStanding the Resource Permission

This article explains about the basic flow of the resources, how they are applied. 1. Create the Portlet with the Name as "TestPermission" 2. Create service.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.2.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_2_0.dtd"> <service-builder package-path="com.service"> <author>Test</author> <namespace>Test</namespace> <entity name="Bus" local-service="true">         <column name="id" type="long" primary="true"></column>         <column name="registration" type="String"></column>         <column name="wheels" type="String"></column>     </entity> </service-builder> Build the services, automatically classes w

Working with Alloy UI Taglibs

Image
We can use readly avalible taglibs in our customportlet , Here are the some 1. If we want user to rate the content we can use "ratings" taglib as, <liferay-ui:ratings classPK="12724" className="<%=BlogsEntry.class.getName() %>"></liferay-ui:ratings> Here classPK is the  primarykey , here i am using the blogsentry so it is blogsentryid className is the classname of the entry, wheather it is "BlogsEntry" , "JournalArticle" etc. 2. If we want to display the rating score <liferay-ui:ratings-score score="2"></liferay-ui:ratings-score> 3. "Discussion" taglib mostly used to display the user comments <liferay-ui:discussion classPK="12724" userId="10201" className="<%=BlogsEntry.class.getName() %>" formAction="fm"></liferay-ui:discussion> Here classPK is the  primarykey , here i am using the blogsentry so it is

Service builder exception : org.dom4j.DocumentException: www.liferay.com Nested exception: www.liferay.com

Today, while building an service i got the following exception. Solution:    Since i don't have the internet connection. while building the services i got the below exception.    So remove the DTD from the service.xml   If still you get this exception remove from the other xml files like liferay-display.xml and liferay-portlet.xml DTD will be at lineno:1 or 2 of the service.xml It will look as below <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.2.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_2_0.dtd"> <service-builder package-path="com.test.sample"> ................ Hope this information helps. com.liferay.portal.kernel.xml.DocumentException: www.liferay.com Nested exception: www.liferay.com at com.liferay.portal.xml.SAXReaderImpl.read(SAXReaderImpl.java:429) at com.liferay.portal.xml.SAXReaderImpl.read(SAXReaderImpl.java:447) at com.liferay.portal.kernel.xml.SAXReaderUtil.

Disabling the Change of password for the user

If we want to disable the change of the password when user is logging into first time, we can follow these 2 steps 1. When the user is creating the my code, i mean if we have written the code for adding the user instead of out of box. then we can set like this . user.setPasswordReset(false); UserLocalServiceUtil.updateUser(user); 2. I think this option we be better, Go to the controlPanel Control Panel -> Password Policies(Portal Section) -> Default Password Policy .-> Change Required (uncheck checkbox). That's it , when user is logging first time, then we cannot get change password screen.

Knowing About the layout

We can Check the page whether it is private or public page using layout object. layout.isPrivateLayout() layout.isPublicLayout() layout is an implict object in liferay By using this "layout" object we can get title , description, theme applied to that page, group, Also we can get the child page and parent page details. Forming the dynamic URL PortalUtil.getPathFriendlyURLPublic() : It retrieves "/web" PortalUtil.getPathFriendlyURLPrivateGroup() : It retrieves "/group" themeDisplay.getScopeGroup().getFriendlyURL(): It retrieves site name(ex: guest) So finally we can write as, If we want Public Page URL: PortalUtil.getPathFriendlyURLPublic()+ themeDisplay.getScopeGroup().getFriendlyURL() +StringPool.SLASH + "home"; It will be as "/web/guest/home. Also If we want Private Page URL: PortalUtil.getPathFriendlyURLPrivateGroup()+ themeDisplay.getScopeGroup().getFriendlyURL() + StringPool.SLASH

Copying array to another array

Sometimes it is required to copy array to another array, how can we do that? Here is the things, In the java.lang.system class we have System.arrayCopy(-,-.....); we can utlize these method to copy the array. Here is the method : System.arraycopy(src, srcPos, dest, destPos, length); Here we have 2 array fields , which we need to copy into the String [] finalfields array. final String [] userField = {"screenName","firstName","lastName","emailAddress","jobTitle"}; final String [] addressFields= {"streetNo","pinCode"}; Calculating the finalfields array size int fieldsSize = userField.length + addressFields.length; String [] finalfields = new String[fieldsSize]; System.arraycopy(userField, 0, finalfields, 0, userField.length); Here we have copied the "userField" array values into the "finalfields" array values. System.arraycopy(addressFields, 0, finalfields, userField.length, addressFie

Getting the Organization name.

We know we can get the Organization details from the OrganizationLocalServiceUtil. Also we have another option to get those details. It is from the GroupLocalServiceUtil. As we know that whenever we create the Organization it will be created in the " Group " table only. Here I am getting the " Test Organization" Organization Getting the Organization name from the group String defaultOrganizationGroupName = "Test Organization"; defaultOrganizationGroupName +=GroupLocalServiceImpl.ORGANIZATION_NAME_SUFFIX; Group group = GroupLocalServiceUtil.getGroup(companyId,defaultOrganizationGroupName);

Getting the Expandovalue

We can use the "ExpandoLocalServiceUtil" to get the Expando or custom field value from the Object. Also we have another option to get expando value, Here we will use the ExpandoBridge to get the value details. Below example , using the user object to get the expando values. String attributeName = "interest"; ExpandoBridge expandoBridge = user.getExpandoBridge(); if(Validator.isNotNull(expandoBridge)) { String attr = (String) expandoBridge.getAttribute(attributeName); } Here we have the customfield name as " interest " and retrieving the value of that attribute. Note : But user should have permission to get the value.

Adding Default Roles, sites and userGroup

If we want add the default "UserGroups" , "Groups" and "Roles" to the users, we can use the following methods to add. This will ensure, when user is creating it will assign these "UserGroups" , "Groups" and "Roles" to the users If we look into this " admin.default.role.names " in the portal.properties , it has User and PowerUser added, So whenever user is created, these 2 roles are assigned. Here for admin.default.user.group.names , we have added as CoffeGroup , so this group will be assigned automatically to the newly created user. Note: Whatever value we assign to the property , this should exists in the Portal. i.e  CoffeGroup (user group)should be exist in the portal, before creation of user. 1. UserGroup     #     # Input a list of default user group names separated by \n characters that     # are associated with newly created users.     #     admin.default.user.group.names=CoffeGroup UserLoca

Executing the BackGround Task

In Liferay we can exceute the background task asynchrously. The Background Task framework allows the developers to create and manage any kind of tasks that need to be run in a separated thread without the need of knowing anything about JAVA threading or concurrency Here the code ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY); Map taskContextMap = null; String taskName = null; String servletContextNames [] = new String[1] ; Portlet portlet = PortletLocalServiceUtil.getPortletById(request.getAttribute(WebKeys.PORTLET_ID).toString()); servletContextNames[0] = portlet.getContextName(); try { BackgroundTaskLocalServiceUtil.addBackgroundTask(themeDisplay.getUserId(), themeDisplay.getScopeGroupId(), taskName, servletContextNames,TestBackgroundTaskExecutor.class, taskContextMap,new ServiceContext()); } catch (PortalException e) { e.printStackTrace(); } catch (SystemException e) { e.printStackTrace(); }

UnSubscribe the user from the comment

  Whenever we write comment to the post(Blog or webcontent etc..) , user will automatically subscribe to the comments and also will be receving the email when ever any user update or add the comment.   If user want to subscribe manually, it is timetaking to check each and every post.   so here the following code which helps to unsubscribe the user from the post. Here we are unsubscribing the "Admin" user  posts of  JournalArticle.   String screenName = "Admin"; String className = JournalArticle.class.getName(); User user = null; ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY); try { user = UserLocalServiceUtil.getUserByScreenName(themeDisplay.getCompanyId(), screenName); } catch (PortalException e) { e.printStackTrace(); } catch (SystemException e) { e.printStackTrace(); } if(user!=null) { List<subscription> subscriptionList = null; try { subscriptionL

Knowing the cluster Node in the server

Sometimes we need to know which server node we are accessing in cluster environment. We know that we can execute the "Groovy" and "BeanShell" script in control panel. So place the following code and execute it, you will be knowing which server we are accessing. Note: Before execution make necessary imports ClusterNode clusterNode =ClusterExecutorUtil.getLocalClusterNode(); if (clusterNode != null) { System.out.println("cluster Node is "+clusterNode.getClusterNodeId()); }

Deleting the cookies

Sometimes it is required to delete the cookies, where we need to set the MaxAge to 0. Here we are retrieving the cookies from the request, and setting the maxAge to "0" to the response , so that it will expire the cookies. Cookie[] cookies = request.getCookies(); for(Cookie cookie : cookies){ System.out.println("cookie Name is "+cookie.getName()); cookie.setMaxAge(0); response.addProperty(cookie); }

Getting the user password

In Liferay, We know that user password stores in Encrypted format in DB but sometime we have want to know the user password. so what to do?? We have utility method portalUtil.getUserPassword(portalRequest); But it gives null value. So how do we get it? Add the following properties in the Portal-ext.properties and restart the server. session.store.password=true session.shared.attributes.excludes= Then use the portalUtil.getPassword to get the userPassword. Thats it!!!  Now we can view the user password.

Extending the session/jsessionId

Image
JSESSIONID is a cookie generated by Servlet container like Tomcat or Jetty and used for session management in J2EE web application for http protocol.  Since HTTP is a stateless protocol there is no way for Web Server to relate two separate requests coming from same client and Session management is the process to track user session using different session management techniques like Cookies and URL Rewriting. If Web server is using cookie for session management it creates and sends JSESSIONID cookie to the client and than client sends it back to server in subsequent http requests. This cookie is valid still the browser session is available. We can view this JSessionId in the chrome as If we want this jsession cookie should  be present certain period of time. How can we do it? In liferay  it can be done just by adding the entry in the web.xml Go to the 1. <liferay-path>/tomcat/webapps/ROOT/WEB-INF/  2. Open the web.xml and add the "cookie-config" Full s

Retrieving/getting the JournalArticle from the Tag

Whenever we create the JournalArticle we add tag. Sometimes it is required to get the "Article" from the tag, so how can we do that. Here is the code, String tagName = "cricket"; AssetTag assetTag = AssetTagLocalServiceUtil.getTag(themeDisplay.getScopeGroupId(),tagName); AssetEntryQuery assetEntryQuery = new AssetEntryQuery(); assetEntryQuery.setAllTagIds(new long []{assetTag.getTagId()}); List<journalarticle> journalArticleList = null; List<assetentry> assetEntryList = AssetEntryLocalServiceUtil.getEntries(assetEntryQuery); for(AssetEntry assetEntry : assetEntryList) { try { JournalArticleResource journalArticleResource = JournalArticleResourceLocalServiceUtil .getJournalArticleResource(assetEntry .getClassPK()); JournalArticle journalArticle = JournalArticleLocalServiceUtil.getArticle(groupId,journalArticleResource.getArticleId()); jou

Applying the theme , layout and setting the portlets for the Page template programmatically

In previous post we have seen adding the site template and page template programatically . If you want to look into those posts again please follow the links below. Creation of Site Template http://liferaytutorial.blogspot.in/2015/03/adding-site-template-programmatically.html Creation of Page Template http://liferaytutorial.blogspot.in/2015/03/adding-page-template-in-liferay.html Sometimes it required to add the portlet to layout and apply theme programatically. So here is the code, Here we are applying the 2 column layout with 1st column as " MessageBoard (19)" and 2nd column as " Search (3)" and " Blog (33)" portlets Also applying the theme "label_WAR_labeltheme. // Updating the column and Portlets for the pagetemplate LayoutPrototype layoutPrototype = LayoutPrototypeLocalServiceUtil.getLayoutProtoType(10011l); Layout layout = layoutPrototype.getLayout(); LayoutTypePortlet layoutTypePortlet =(LayoutTypePortlet)layout.getL

Applying the theme for the site template programmatically

In previous post we have seen adding the site template and page template programatically . If you want to look into those posts again please follow the links below. Creation of Site Template       http://liferaytutorial.blogspot.in/2015/03/adding-site-template-programmatically.html Creation of Page Template         http://liferaytutorial.blogspot.in/2015/03/adding-page-template-in-liferay.html Sometimes it is required to apply the custom theme for the site template. So how we can do that? Here is as follows, I have a theme called label and themeid is label_WAR_labeltheme . As we know that SiteTemplate is stored in the LayoutSetProtoType table. So we can get the template from the layoutsetprototypeutil LayoutSetPrototype layoutSetProtoType = LayoutSetPrototypeUtil.get(----------------); LayoutSetLocalServiceUtil.updateLookAndFeel(layoutSetPrototype.getGroupId(), "label_WAR_labeltheme", "01", "",false); Thats it we have applied the

Adding Page Template in liferay Programmatically

We know that we can create the page template from the control panel, What if we want to create programmatically. So here we go, 1. We are reterving the page template name form the portlet.properties. If you want to know how to create the portlet.properties and retrieve follow the below link. http://liferaytutorial.blogspot.in/2013/03/how-to-read-values-from-properties-file.html So here i am retrieving the page template name as page.template from portlet.properties file. String pageTemplateNames = PortletProps.get("page.template"); In Portlet. properties page.template = Home,Test Before adding the page template we are checking weather page template exists or not by dynamicQuery , because we don't have any finder method to check the page template by name. Here i am checking by descrition beacause name will be storing as JSON format in DB. List<LayoutPrototype> layoutProtoTypeList = null; DynamicQuery dynamicQuery = DynamicQueryFactoryUti

Adding Site Template Programmatically

We know that we can create the site template from the control panel, What if we want to create programmatically. So here we go, 1. We are reterving the site template name form the portlet.properties. If you want to know how to create the portlet.properties and reterive follow the below link. http://liferaytutorial.blogspot.in/2013/03/how-to-read-values-from-properties-file.html So here i am reterving the site name as  site.template from portlet.properties file. String siteTemplateNames = PortletProps.get("site.template"); In portlet.properties site.template = SiteTemplate1 , SiteTemplate2 Before adding the site template we are checking weather site template exists for not by dynamicQuery , because we don't have any finder method to check the site template by name. Here i am checking by descrition beacause name will be storing as JSON format in DB. DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(LayoutSetPrototype.class); dynamicQuery.

Date Picker in liferay

Image
In Liferay it is simple to add the add the DatePicker. Liferay already had datepicker taglib, so here we go . Creating the calendar object, for today date. Calendar cal = CalendarFactoryUtil.getCalendar(timeZone, locale); int startDateValue = cal.get(Calendar.DATE); int startMonthValue = cal.get(Calendar.MONTH); int startYearValue = cal.get(Calendar.YEAR); Implementing the date picker, <aui:fieldset> <aui:field-wrapper label="start-date"> </aui:field-wrapper></aui:fieldset> <div class="field-row"> <liferay-ui:input-date dayparam="schedulerStartDateDay" dayvalue="&lt;%=startDateValue %&gt;" disabled="&lt;%= false %&gt;" monthparam="schedulerStartDateMonth" monthvalue="&lt;%=startMonthValue%&gt;" name="startDate" yearparam="schedulerStartDateYear" yearvalue="&lt;%=startYearValue%&gt;"> </liferay-u

How to know which liferay version we are using

Image
Sometimes we have to know which liferay version we are using, so how can we know? We can know the liferay version in different ways. 1. Liferay has provided some utility methods to know the which liferay version we are using , Here is the utility method ReleaseInfo.getReleaseInfo() It prints this statement " Liferay Portal Community Edition 6.2 CE GA2 (Newton / Build 6201 / March 20, 2014) " as i am using community version it shoes as CE. 2. Also we can also identify by response headers as below screenshot. If your using the chrome, right click on the browser and click inscept element , and navigate to the network  . you will see the URLS , click on the any url. 3. Also we can see during server startup as below statement Liferay Portal Community Edition 6.2 CE GA2 (Newton / Build 6201 / March 20, 2014)

ECJ jar not installed

Image
Today , When I am deploying the new plugin portlet using the ant tool i got a build failed with error stack trace as,                 Task cannot continue because ECJ is not installed.                ECJ was automatically installed. Please rerun your task. As below screenshot as, So what to do ?, how to proceed further? Here it is In Eclipse Go to windows menu, click on the preferences We will see the following screesnshot select the ant and click on the Runtime , by default Classpath tab is selected, click on the Global Entries Then click on the Add External JARS button and select ECJ jar file from the <liferay-tomcat>/tomcat/lib. Click OK button to save the changes. Thats it now we can build the portlet.

Reading the scheduler value from the properties file

In liferay if we want to schedule,then we  write the enries in the liferay-portlet.xml Here we are hard code the value. What if cronValue is retreving the from the portlet.properties Yes we can reterive the value from the propeties , here is the code snippets, liferay-portlet.xml scheduler entry com.sample.scheduler.SchedulerClass cronValue Create the properties file in the /your-portlet/docroot/WEB-INF/src/ Portlet.properties ##cron value ## cronValue = 0/1 1/1 * 1* Here in liferay-portlet.xml we have set the key  " cronValue " in the element of property-key

Export users in liferay

Image
Sometimes it may require to export the users into CSV file to look into the depth of users details. To make life easier, liferay has given such functionality to us, just by clicking the button.  Navigate to the controlPanel and click on the users and Organization , there you will see a button "Export users". Click on the button to export the users. It will download a file called "User.csv" But that csv file contains only 2 columns  1. FullName 2. Email Id But we require more fields to export like(screenName, jobTitle etc) so what to do? Check the following entry in the portal.properties. # # Input a list of user attributes that will be included when exporting users # to a CSV file. You can include custom fields by adding the prefix # "expando:" to the attribute name. # users.export.csv.fields=fullName,emailAddress Add the required entries by comma separated, If you want to know the what are the fields to be added look into the Us

Applying the patches in liferay

We are using EE version of liferay and we found a bug and reported to liferay. They have given patch to solve this issue. This patch will be ZIP file. Copy the ZIP file and paste in patches folder of  this location  "<liferay-tomcat>/tomcat/patching-tool/patches". Sometimes our patching tool will contain the lower version comapared to provided version. So we need to upgrade to latest version. version number can know by using the following command as In Linux ./patching-tool.sh info In Windows patching-tool info After executing this command look into the line of   patching-version  in the  output console. Note : All of these commands should be execute from the "<liferay-tomcat>/tomcat/patching-tool". In Order to install the patch execute the following command In Linux ./patching-tool.sh install In Windows patching-tool install After applying the patch we can see the console installation completed successfully. Sometimes your

Session TimeOut

In Liferay session timeout will be 30 mins by default. If you were idle for 30 mins liferay will expire the session. Sometimes based on the requirement we want to increase the session timeout. So look into the portal.properties  file and search for the "session.timeout"  we can see the  minutes it was set. By default it was 30 minutes. # # Specify the number of minutes before a session expires. This value is # always overridden by the value set in web.xml. # session.timeout=30 Even if we increase this value it would effect because it will be override the entry in the web.xml . so as best option remove the entry in the web.xml Navigate to the tomcat folder as <tomcat>/webapps/ROOT/WEB-INF/web.xml Search for the entry " session-timeout " you can find the following snippets. 30 Remove this entry in the web.xml and increase the value in the portal-ext.properties to your value, suppose if i need to increase the session t

Display server name or node in the cluster configuration

Image
In Cluster configuration if we want to know which cluster server we have accessed it simple. Liferay has provided a property by which we can know which cluster server we have accessed. Add the following property in the portal-ext.properties # # Set this to true to display the server name at the bottom of every page. # This is useful when testing clustering configurations so that you can know # which node you are accessing. # web.server.display.node=true If we see the internally liferay is using to get the computerName. PortalUtil.getComputerName(); Look into the portalImpl class of constructor how liferay is using to get server node name. _computerName = System.getProperty("env.COMPUTERNAME"); if (Validator.isNull(_computerName)) { _computerName = System.getProperty("env.HOST"); } if (Validator.isNull(_computerName)) { _computerName = System.getProperty("env.HOSTNAME"); } After restarting the server we can see the node

Database connection pool C3po configuration in liferay

In Liferay, default connection pool is c3p0 configured using portal-ext.properties. Liferay Portal also supports the database connection pool configuration through the Application Server. Liferay can access the Application Server level data source using JNDI. It is recommended to use the JNDI-based database connection pool configuration. Add the following property in the portal-ext.properties. jdbc.default.jndi.name=jdbc/LiferayPool Open the server.xml in the <liferay-home>/tomcat/conf folder Locate the Resource tag and add the following properties. <Resource auth="Container" description="Portal DB Connection" driverClass="com.mysql.jdbc.Driver" maxPoolSize="75" minPoolSize="10" acquireIncrement="5" name="jdbc/LiferayPool" user="<MySQL Database User Name>" password="<MySQL Password>" factory="org.apache.naming.factory.BeanFactory"

Quartz scheduler configuration in cluster

  Quartz is a very popular open source scheduler engine. Quartz scheduler stores data related to scheduled jobs in the Liferay database. In clustered environment there will be chance of starting the scheduler for all the nodes at same time which causes duplicate entries in the portal. We should  execute only once for all the nodes. Suppose if we have configured 4 nodes, then 4 scheduler will start at same time. But we need execute 1 scheduler for a job. Hence in a clustered environment, it is possible that multiple nodes start the same job at the same time. This can create havoc. To prevent this situation, we need to configure Quartz for the clustered environment. Add the following property in the portal-ext.properties org.quartz.jobStore.isClustered=true  Drop all the tables starting with QUARTZ_. This step is required if Liferay tables are already created. We just added a property to let the Quartz scheduler know that we are running multiple instances of the Q

File Utility methods in liferay

Liferay has many utility method to handle the file like copyDirectory , copyFile , unZip , delete , createTmpfile etc.. In real scenerio to unzip the file we need to write pure java code but liferay has utility method to unzip the file Have a look into the fileUtil class and look into the method unzip(File source, File destination) public static void unzip(File source, File destination) { PortalFilePermission.checkCopy(_getPath(source), _getPath(destination)); getFile().unzip(source, destination); } Also internally if we look into the how liferay is unzip, look into the ExpandTask class and look into the method as public static void expand(File source, File destination) { Expand expand = new Expand(); expand.setDest(destination); expand.setProject(AntUtil.getProject()); expand.setSrc(source); expand.execute(); } Their it is using the Expand class(org.apache.too