1/29/2011

How to use the Liferay Language Setting in a JSF / ICEFaces Portlet

Problem: JSF or ICEFaces Portlet don´t really seem to care for the language settings of Liferay. They always take the language properties from the browser. That´s ok, but sometimes you want to force a certain language. This is what you can do:

Create a Bean returning the Liferay Language


public class LocaleBean{
    public Locale getLocale() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ThemeDisplay themeDisplay =       
       (ThemeDisplay)facesContext.getExternalContext().
        getRequestMap().get(WebKeys.THEME_DISPLAY);
        return themeDisplay.getLocale();
    }
}


This Bean returns the locale set for the current User.


Initialize your JSF Page 


Now, initialize your JSF page like this:

<f:view  locale="#{localeUtil.locale}">
...
</f:view>



If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.


1/28/2011

Applet - Portlet Communication

From time to time there is the need to send data from a portlet to an applet and back. For example if you want to access a USB - Stick. Here is how you do it:


Sending data from a portlet to an applet


This way is rather easy: You instantiate the applet, you pass the information using applet parameters and read those parameters in the applet.

Here is a snippet showing you how to instantiate your applet:

<applet id="yourApplet"
code="com.test.YourApplet.class"
archive="yourApplet.jar, someHelperJar.jar"
codebase="http://localhost:8080/yourportlet">
<param name="parameter" value="#{bean.parameterValue}" />
</applet>


Explanation:


code: This is your class extending java.applet.Applet, your applet main class.
archive: This is a list of jars that contain your applet (packed as a jar) and all jars your applet might need.
codebase: The path to access your portlet and by having this, to access the 
applet jar.
param: This is the way to send data to your portlet: add applet parameter and 
point them to values in your bean.

You can access those parameters in the init() method of your applet like this:


public void init() {
        final String  inputStr = getParameter("parameter");    
...
}

Sending data from an applet to a portlet

To let the applet communicate with the portlet you can use javascript:


import java.applet.*;
import java.net.*;

public class myApplet extends Applet{
  public void init(){
    long var = 5;
    try {
      getAppletContext().showDocument
        (new URL("javascript:process(\"" + var+"\")"));
      }
    catch (MalformedURLException me) { }
  }
}

This will call a javascript function on your portlet page with the parameter "var". You can use these parameters to set values in (hidden) text fields and then click a (hidden) button. This allows you to return processed data to the portlet and to tell the portlet what to do.

Just for the sake of completeness ... this is how you specify hidden input fields and buttons in ICEFaces:

Hidden InputField:
<ice:inputHidden value="test"></ice:inputHidden>

Hidden Button:

<ice:commandButton visible="false" value="Click Me"></ice:commandButton> 

If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)
If you have any questions, feel free to leave a comment.

1/27/2011

New Features of JSF 2.0 - Part 1

So, time to move to ICEFaces 2.0, isn´t it ? But if you are talking about ICEFaces 2.0, you have to know what JSF 2.0 is doing for you. So here is the first part of my "Fancy things you can expect from JSF 2.0" Series.

One thing first: JSPs are deprecated, so if you plan to migrate your applications, keep that in mind. And keep it in mind when you are reading this series of blog entries, because (for example) Ressource Management won´t work in JSPs.

JSF Resource Management

JSF 2.0 offers something that is called "Resource Management". What does that mean ? It means, that you can declaratively define the ressource you want to access, JSF picks the newest one for you out of your folder and you don´t have to care about folders, slashes or anything else.
What is a Resource ? A Resource may be a javascript file, a css file or a graphic file.

If you wanted to display an image in JSF 1.2 you had to write something like this:

 <h:graphicImage value="/img/myPictures/picture.png" /> 

The same tag would look like this in JSF 2.0:


  <h:graphicImage value="#{resource['myPictures:picture.png']}" /> 

Or simpler :

  <h:graphicImage name="picture.png" library="myPictures" /> 

Looks confusing ? Wait a sec, this is how it works:

Convention over Configuration

All your images are located in the standard resource folder called "resources". Within this folder are the library folders and within them folders for the resources to be displayed. This is the convention you have to follow from now on. This will help you to keep your files in place. It also helps you to address your resources, because all you have to care about is your library folder and your image name.

#{resource[... always specifies access to a ressource in JSF 2.0. To access a library with a specific resource use the following pattern: ['libraryName:resourceName'].


Versioning

The JSF 2.0 Resource Management allows versioning of files. How does that work? Well, all your files can be updated at runtime, without the need for a deployment and without to overwrite the file. Just add a new version and the next request for a resource will carry out your updated one.


Part 1 - New Library Version

if you want to add a new library version to your web application just add a versionized folder by creating a folder with the name "1_1". Putyour updated file into this folder.
Your folder should now look like this:

\resources\myPictures\picture.png
\resources\myPictures\1_1\picture.png

The upper picture is the unmodified version, that´s still present in your application, Version 1_1 goes into its own folder. Ever other 1_1 versionized picture for the myPictures library would also go into this folder.

Part 2 - New Image Version

If you want to update your image without having to create a new library version, just do the following: Add a new folder, named "picture.png" and place all future versions of your file into this folder like this:

\resources\myPictures\picture.png
\resources\myPictures\1_1\picture.png
\resources\myPictures\1_1\picture.png\1_1
\resources\myPictures\1_1\picture.png\1_2

This example shows how Version 1_2 of the library version 1_1 would be the most actual to be delivered to the browser. All other files would reside untouched on the server.


Part 3 - Updating JARs

A very nice thing is, that this is also affecting resources in JARs, so you may update a javascript library without changing the original source.

Benefits

  • You don´t have to care about how to deploy new versions of your files
  • You don´t have to care about how to access your resources, or a Junoir Programmer always forgetting the "/" at the beginning

If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.

1/25/2011

Little error in ICEFaces TLD description for inputFile (fileNamePattern)

Regarding the fileNamePattern of the ICEFaces inputFile component which is described in the official Tag description here: http://www.icefaces.org/docs/v1_8_2/tld/ice/inputFile.html:


This is the correct call to identify files with an incorrect file type in the backend:


if (inputFile.getFileInfo().getStatus() == InputFile.INVALID_NAME_PATTERN) {...
}


I don´t know why they still show a deprecated method call and an incorrect   constant ...




Update:


If you are looking for a case insensitive fileNamePattern working with the ICEFaces inputFile component, take this one:


<ice:inputFile fileNamePattern=".+\.((?i)png|(?i)jpg|(?i)jpeg|(?i)gif) "actionListener="#{...}"/>



If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.

ICEFaces request scope (and the consequences)

ICEFaces offers its own interpretation of the JSF request scope : the extended request scope.


This request scope lasts longer than the original request scope: It will continue to live when you are using partialSubmit controls and it will continue to live when you are using non-redirect navigation rules.


This means for example, that when you are navigating back and forth within two pages your beans won´t be recreated which then means that you can´t put code into the constructor of your beans because it will only be executed once.


But sometimes you have the need for backing beans to be recreated every time a page is requested. To avoid having to deal with JQuery you have two possibilities:


What to do when you have a simple ICEFaces application

If you have a simple ICEFaces application that is NOT running in a portlet environment, you can just add a redirect to your faces-config navigation rule:


<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
<from-outcome>edit</from-outcome>
<to-view-id>/pages/editPage.iface</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>


This redirects to the specified pages, thus leaving the extended portlet request and therefore recreating your managed beans. 


What to do in a Portal Environment (Liferay)


You can´t use the faces-config redirect mechanism in a portklet environment because you don´t want to see the ICEFaces page but instead the portlet page with the ICEFaces - Portlet in it. To redirect to the portlet page you are just visiting, use the following snippet:



String portalURL = themeDisplay.getPortalURL();
String urlCurrent = themeDisplay.getURLCurrent();
FacesContext.getCurrentInstance().getExternalContext()
.redirect(portalURL + urlCurrent);




This will redirect to the current Page (which is the Page your portlet is running on) using a standard JSF mechanism. 



If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.

1/21/2011

How to move file in Liferay document library

Problem: There is no "out of the box" solution to move files in the Liferay 5.2 document library / liferay image gallery. The method got implemented with Liferay 6 so Liferay 5 users have to find another way.


Your first try might be to reset the "parentFolderId" property of the DlFileEntry you want to move and to update the file. Don´t do that ! Liferay maps the folders you store the files in the document library directly to your harddrive (if you are storing them there) and won´t find the files anymore if you manipulate the entries.


The solution is: Read the DlFileEntry and store it as a new file. Afterwards yuo can delete the old file:


// 1: Get the old content

InputStream fileAsStream = DLFileEntryLocalServiceUtil
      .getFileAsStream(entry.getCompanyId(),
       entry.getUserId(), entry.getFolderId(),
       entry.getName(), entry.getVersion());

//2: Add the new file with the old content


DLFileEntry addFileEntry = 
DLFileEntryLocalServiceUtil.addFileEntry(userid, folder1,
        entry.getName(), entry.getTitle(), entry.getDescription(),   
        null,fileAsStream, entry.getSize(), new ServiceContext());


//3: Delete the old file
DLFileEntryLocalServiceUtil.deleteDLFileEntry(entry);




But beware:


This means that you create a NEW file. A real "move " is not possible. So be sure to pass on the new fileEntryId.



If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.

1/14/2011

Adding Order to a DynamicQuery in Liferay

I am always reacting to the fact when people visit my blog with google queries ... so someone was looking for "Adding order to Dynamic Queries". Well ... here is what I know about that:


If you already know a lot about the DynamicQuery in Liferay, just continue reading. If not, please start here:


http://liferay-blogging.blogspot.com/2010/11/dynamicquery-api-in-liferay.html


Adding Order To a DynamicQuery


The first thing to start is to take a look at the "OrderFactoryUtil" class which you can find in Liferays com.liferay.portal.kernel.dao.orm package. The first two methods you have to know something about are:


Order asc(String propertyName);
Order desc(String propertyName);


They simply tell the DynamicQuery you attach them, that the results should be ordered ascending or desceding according to the chosen property name. That´s all for those methods.


The last method offers you to implement your own comparator. You have to implement the OrderByComparator that works pretty much like any other Comparator you would implement in Java. You can find many example of that in the following package:


com.liferay.portlet.journal.util.comparator


rotty3000 added the following:


"The orderbycomparator is designed in such a way that it is translated into SQL instructions and amends the query."


So - go ahead and use the Comparator :)







If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.

How to programatically add images and documents to Liferay

If you want to upload pictures programatically into your image gallery, or documents to the document library you can use the following code snippets.




Images
Images can be uploaded to the document library as well as to the image gallery. Uploading to the Image Gallery is easy, just use this code snippet here:

IGImage addImage = IGImageLocalServiceUtil.addImage(userId, folderId, imageName, description, file, contentType, new ServiceContext());



You have to provide the userId of the User uploading. If you don´t know your userId, you can read here how to get it:



http://liferay-blogging.blogspot.com/2011/01/how-to-get-liferay-user-when-you-are.html

The ID of the Folder you want to add your image to is the next thing you have to know. You can take a look into the database if you want to hard-code it (DLFolder is the table you should take a look in) or you could make it configurable in your portlets preferences.

The Image Name and description is something that relies on your imagination ;) ... the File object is something you have to have. You could use the ICEFaces component ice:inputFile to get it. The contentType is something like "image/jpg" - you can get it based on the file ending.

The last thing is the ServiceContext - and to be honest, I always use a new instance. If you know what exactly this ServiceContext does, drop me a hint, ok ?

There are plenty more methods to add Images to the Image Gallery - just browse the API, which you can fine here:

http://content.liferay.com/4.2/api/portal-service/com/liferay/portlet/imagegallery/service/IGImageLocalServiceUtil.html


Documents


You can add documents to the document library in the same way as you can add images to the image gallery: By taking the correct XYZLocalServiceUtil.
In this case it´s the DLFileEntryLocalServiceUtil:
DLFileEntry fileENtry= DLFileEntryLocalServiceUtil.addFileEntry(userId, folderId,fileName, fileTitle, "description", "",inputStream, fileLength, new    ServiceContext());

I won´t explain everything in detail here - it works pretty much like the IGImageLocalServiceImpl. The API is available for you at:


http://docs.liferay.com/portal/5.2/javadocs/portal-service/com/liferay/portlet/documentlibrary/service/DLFileEntryLocalServiceUtil.html



If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.

How to get the Liferay - User when you are using ICEFaces

Ok, I had an email of someone who needed to know how to get the userId of the currently logged in User when he is using Liferay together with ICEFaces. Well Brian, here´s your answer...


You have to retrieve the ThemeDisplay, which then allows you to access a lot of the information, Liferay is providing:



FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
PortletRequest request = (PortletRequest) ec.getRequest();
ThemeDisplay display = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);


If you have the ThemeDisplay, you can access the User ... and the real User (no kidding). Because it is possible to run certain Liferay pages as another User, the User you have to retrieve is the real User:


User realUser = display.getRealUser();




That´s all :)





If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.

1/13/2011

Looking for AlloyUI Literature?

Part 1   Part 2   Part 3   Useful Links   Useful Literature

If you seek AlloyUI Literature, seek no longer.

"Liferay User Interface Development" should have most of the answers, you are looking for. It covers the following contents:



  • Theme Development
  • Layout Templates
  • AlloyUI
  • Portlet Development & Styling
  • Velocity Templates
  • UI Taglib
  • JQUery
  • [...]

I ordered my copy today and will surely find some useful hints about all that AlloyUI stuff in there ...

How to create an ICEFaces / JSF dataTable with dynamic columns.

Once in a while I have the need to create an ICEFaces (or JSF) dataTable with dynamic columns. For example if I want an administrator to assign preferences to  certain Users.


This is what you will do to archieve this:


Create the dataTable in your backing bean


Take an icefaces com.icesoft.faces.component.ext.HtmlDataTable and make it accessible via getters and setters in your backing bean.


Create a ListDataModel and assign the entities to it. In my case it would be a List of Users:


ListDataModel dataModel = new ListDataModel(users);


The next step is to configure the dataTable to have as much columns as preferences and as much rows as users. You also assign the variable under which your entries will be accessible - just like you would do it in an xhtml file



dataTable.setColNumber(preferences.size());
dataTable.setRows(users.size());
dataTable.setId("theID");
dataTable.setVar("users");
dataTable.setValue(dataModel);


Create the Columns you need


For every column you want to display, do the following. First, create the column and assign some header information to it:



UIColumn column= new UIColumn();
HtmlOutputText outputText= new HtmlOutputText();
outputText.setValue("Header for my column");
roleColumn.setHeader(outputText);
roleColumn.setId("IdForTheColumn");


Second, create a ValueExpression that will display your data in the dataTable.



HtmlOutputText outputText = new HtmlOutputText();
ValueExpression expression= expressionFactory

.createValueExpression(FacesContext.getCurrentInstance()
.getELContext(), "#{users.firstName}", String.class);

outputText .setValueExpression("value", 
expression);

outputText .setId("firstName");

Add this ValueExpression as child to your column, and you are good to go!


column.getChildren().add(outputText );


By inspecting this little example you immediately see the downside of this example: Your EL is now in your backing bean! This will surely not speed up your development time. Now add the column to your dataTable and repeat the work for all other columns, and your work in the backend is done:


dataTable.getChildren.add(column);


Reference your dataTable from your xhtml file


Now, just reference your dataTable by using binding, and that´s it. You now have a dynamic dataTable.



<ice:dataTable id="myDataTable" binding="#{bean.dataTable}" 
     partialSubmit="true"

 immediate="true">


</ice:dataTable>




If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.

1/10/2011

Liferay Configuration & Preferences ... together with ICEFaces

This is something where I am interested in your opinions - how do you handle Liferay Configuration & Preferences together with ICEFaces ? I´ve written down my approach below but if you have any suggestions - feel free to leave a comment.

Liferay Configuration Page

The Liferay Configuration Page itself is not configurable - you have to configure a configuration class which redirects to a jsp holding the view that lets you perform configuration issues.


First add the following to your liferay-portlet.xml file:


<configuration-action-class>
    com.example.ConfigurationActionImpl
</configuration-action-class>


This class extends BaseConfigurationAction and in its "render" method returns the path to your configuration jsp: "/pages/config/configuration.jsp".


Yes - you read it right. It needs to be a JSP.


Liferay Preferences Page


The Liferay Preferences Page is nothing else but the good old edit view from standard portlet development days. You can set it in your portlet.xml by adding this:



<init-param>
<name>com.icesoft.faces.portlet.editPageURL</name>
<value>/pages/preferences.iface</value>
</init-param>

And here you have the full power of ICEFaces - no JSPs needed here. So if you take a look at these two approaches, do you think there will be a way telling liferay to load the configuration page as a facelets file ?  Leave me a comment :)



If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.

How to pass Parameters and Attributes in JSF / ICEFaces and Liferay

Introduction


I had a couple of people visiting my blog just to find out how to pass parameters by commandButton, commandLink, menuItem etc. So I decided to write it down a little. I´m sure I will need it myself sooner or later ;)


The first thing you have to differentiate is whether you want to send parameters or attributes. While Parameters can be accessed by every component, attributes can only be read by the method that receives the enclosing ActionEvent, because the attribute is mapped to the component that fire the event. This means that attributes can only be used together with ActionListeners - not actions.


A parameter, in contrast is not bound to a specific component. It is an http fragment added to specific components. Those components generate an http URL like http://localhost:8080?id=123 where id is the parameter.
There are only two components that will work with parameters f:commandLink and f:outputLink. ICEFaces adds ice:menuItem to this list. For all the other components you will have to use attributes. 


Accessing Parameters (f:param)




Here are some examples on how to use parameters:


ice:menuItem


The ICEFaces menuItem allows to pass parameters either by a standard jsf f:param tag or by a link. But sadly - not both.



<ice:menuItem value="clickMe" actionListener="#{bean.listener}">
<f:param name="id" value="#{entry.id}" />
<f:param name="action" value="createNew" />
</ice:menuItem>


<ice:menuItem value="clickMe"
         link="localhost:8080/servlet?id=#{entry.id}">
</ice:menuItem>



f:commandLink

A commandLink renders an href element that behaves like a form submit button and is able to call actions or actionListeners:


<h:commandLink value="link" action="#{backingBean.myaction}">
        <f:param name="parameter1" value="value1" />                      
        <f:param name="parameter2" value="value2" />                      
</h:commandLink>



f:outputLink

The outputLink Tag renders a standard html href tag that fires a standard GET request to a web ressource. You could use it to call Java Servlets for example.

<h:outputLink value="#{bean.linkToServlet}">
    <h:outputText value="Click me"/>
    <f:param name="parameter" value="parameterValue" />    
</h:outputLink>




Parameter can be programatically accessed in the following way :





public static String getParameter(String parameterName) {


  String parameter = FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap()
.get(parameterName);
  return parameter;
}


Accessing Attributes (f:attribute)


Attributes can be used (for example) with commandLinks or commandButtons. Hint: commandButtons can´t use parameters ! If you have to use parameters (maybe in navigation), add them manually in an action of yours that you call by clicking your button.


The usage is pretty simple:


<ice:commandButton id="myButton" actionListener="#{bean.ac}"> 
    <f:attribute name="name" value="Click Me"></f:attribute> </h:commandButton>

Attributes can be accessed programatically in the following way:

public void ac(ActionEvent e) {


  Map<String, Object> attributes = e.getComponent().getAttributes();
  Object object = attributes.get("name");
  [...]



If you liked this tutorial it would be very nice, if you could click on some of the google ads you see on the right side. It helps me run this block and motivates me ;)

If you have any questions, feel free to leave a comment.