5/30/2011

Only a type can be imported. XYZ resolves to a package

If you receive an error like this while doing a JSP for Liferay:

An error occurred at line: 8 in the generated java file
Only a type can be imported. com.example.XYZClass resolves to a package.

Most of the time it means "your jar file is missing !". So take a look at your servers lib directory, rebuild your hooks and it should work.



If you like this post 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.

5/27/2011

Syntax Highlightening ...

From now on I will use Syntax Highlightening and I am going to convert all older posts one by one. I hope you like it. Big thanks to this tutorial: 
http://heisencoder.net/2009/01/adding-syntax-highlighting-to-blogger.html


Happy weekend !!!


If you like this blog 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.

Inter-Portlet Communication in Liferay with JSF

This little tutorial will show you how to use Inter-Portlet Communication with JSR 286 Events and JSF 2.0.


Some weeks ago I wrote a blog entry about Inter Portlet Communication the way it is meant to be: Events in JSP-based portlets. You can find that post here:


http://liferay-blogging.blogspot.com/2011/03/inter-portlet-communication-in-liferay_26.html

Today, we will use, the same approach for a JSF based portlet.


Sending Portlet


The portlet that wants to send some data to another portlet has to do send the event manually like this (you can do this in a normal action method, whenever you like):

QName qName = new QName("http://your.domain/name","eventname"); 
ExternalContext externalContext = FacesContext.getCurrentInstance() .getExternalContext(); 
ActionResponse actionResponse = (ActionResponse) externalContext .getResponse(); 
actionResponse.setEvent(qName, "This is a test");


Receiving Portlet:


The Portlet that wants to receive the data from the sending portlet has to do the following. First, create a class that subclasses org.portletfaces.bridge.BridgeEventHandler. This class is in the portletfaces bridge, that you need to get JSF 2.0 running in Liferay. When you created the class (we will call it HelloJSFListener), add the following to your portlet.xml:


<init-param>
<name>javax.portlet.faces.bridgeEventHandler</name>
<value>de.test.HelloJSFListener</value>
</init-param>


This will tell our portlet, that whenever an event occurs, that this portlet is subscribed to, notify the HelloJSFListener. Next, add the following configuration line to your portlet.xml:



<supported-processing-event>
<qname xmlns:x="http://your.domain/name">x:eventname </qname>
</supported-processing-event>



Now our listener is ready to do some serious Inter-Portlet Communication! What we need now is to notify our controller class when our listener is called. We can do it like this:

public EventNavigationResult handleEvent(FacesContext facesContext, Event event) { 
EventNavigationResult eventNavigationResult = null; 
String eventQName = event.getQName().toString(); 
if (eventQName.equals("{http://your.domain/name}eventname")) { 
String value = (String) event.getValue(); 
String elExpression = "#{receiver}"; 
ELContext elContext = facesContext.getELContext(); 
ValueExpression valueExpression = facesContext.getApplication().getExpressionFactory()
.createValueExpression(elContext, elExpression,Receiver.class); 
Receiver Receiver = (Receiver) valueExpression.getValue(elContext);
Receiver.setNewValue(value); 
} 
return eventNavigationResult;  }
This piece of code retreives the controller by using standard JSF Expression language. It then sets the received String into a setter using the setNewValue() method. This setNewValue() method in our example does nothing else but set the data. The View will automatically be refreshed - no need to think about that.


One word about AJAX - forget about using Inter-Portlet Communication when you are using the <f:ajax> tag. We need the ActionResponse to fire our event, and when using AJAX, there will be no response.


Download Eclipse Project here: https://rapidshare.com/files/4275130401/JSFIPCPortlet.rar

If you like 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 read GET parameters with JSF in Liferay

I think you all know the problem: You want to pass some parameters from portlet 1 to portlet 2 but unformtunately you can´t use Inter-Portlet Communication because the other portlet is on another portlet page. Simple using http://localhost:8080/web/guest/home?parameter=helloWorld doesn`t really help. Well, here is the solution to your problem:


First, you need to find out your portlets ID. This you need to extend your link. A portlet ID in liferay looks pretty much like this:


p_p_id=3_WAR_yourportletname_INSTANCE_A8sO


You can find out your portlets id by maximizing it and taking a look at the address field of your browser. There you will find the ID. You now need to add the ID as the first parameter to your URL:


http://localhost:8080/web/guest/home?p_p_id=3_WAR_yourportletname_INSTANCE_A8sO&parameter=helloWorld


This makes sure, that your JSF - Portlet has access to the parameters. Now you need to retrieve them from the request by using this code snippet:

RenderRequest renderRequest = (RenderRequest) (FacesContext .getCurrentInstance()
.getExternalContext().getRequestMap() .get("javax.portlet.request")); 
String parameter = renderRequest.getParameter("parameter");



If you like 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.

A generic approach to Liferay Services

Do you sometimes have to know what´s in the liferay databases ? But you can´t always access the database because you need VPN, URL connection strings etc etc etc ? Here is my approach, that you may or may not use. But please talk to your admins and bosses first ;) I implemented a generic approach to query the Liferay database using the Reflection API of Java.

It basically does nothing but to retrieve all objects of a Service, call all getters and display the data. My approach consists of two parts: A java class doing the string generation and a JSP displaying the data.

public String createTable(List<T> o) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {

StringBuilder builder = new StringBuilder();
builder.append("<table><tr>");
Method[] methods = o.get(0).getClass().getMethods();
Object[] myArray = new Object[0];
//WRITE HEADER
for (Method meth : methods) {
  String name = meth.getName();
  Type[] typeParameters = meth.getGenericParameterTypes();
  if ((name.startsWith("get") && (typeParameters.length == 0))) {
  builder.append("<td>" + name.substring(3) + "</td>");
  }
}
builder.append("</tr>");
//WRITE CONTENT
for (Object myObject : o) {
  builder.append("<tr>");
  for (Method meth : methods) {
  String name = meth.getName();
  Type[] typeParameters = meth.getGenericParameterTypes();
  if ((name.startsWith("get") && (typeParameters.length == 0))) {
   builder.append("<td>" + meth.invoke(myObject, myArray)+ "</td>");
  }
}
builder.append("</tr>");

}

builder.append("</tr></table>");
return builder.toString();

}

If you like 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.

5/26/2011

Doing a Post with unchecked checkboxes

If you have to do JSPs you will certainly run into the problem that you have to submit a Form where you can enable or diasble certain form elements. That´s ok for checkboxes, because if they are not checked, they are won´t get submitted. But what about input fields ? They will be submitted all the time, regardless of the checkbox. This will lead to difficulties processing the fields values in the portlet class, because you will have (for example) 2 values for the selected checkbixes and 6 values for all input fields.


The solution is to dynamically disable all input fields that should not be submitted.


You can do it by javascript like this:

function toggleDisable(identifier) {
  document.getElementById(identifier).disabled = 
(document.getElementById(identifier).disabled) ? false : true;
}

This function toggles the desired input field from disabled to enabled and back. And this is the checkbox doing the javascript call:


<input type="checkbox"onclick="toggleDisable('fieldId');" name="CBName" value="CBName" <%=selected %>>

The Input Field itself is very straightforward:


<input id="fieldId" name="field" <%=disabled %>  type="text" value="value" />


By doing this you can make sure, that you will always submit as much checkbox values as input field values.


If you like 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.

5/23/2011

Retrieving Blogs Comments

If you need to retrieve all comments that have been made to blogsentries (com.liferay.portlet.blogs.model.BlogsEntry), you need to know that Liferay stores all comments as message board messages. So you need to do the following to get all comments:


table: mbMessage


Properties:


classNameId: ClassNameId of BlogsEntry
parentMessageId: Not 0
classPK: Primary Key of your BlogsEntry
categoryId: must be -1

DynamicQuery mbMessageQuery = DynamicQueryFactoryUtil.forClass(MBMessage.class, PortalClassLoaderUtil.getClassLoader());

long blogsEntryClassNameId = ClassNameLocalServiceUtil.getClassNameId(BlogsEntry.class.getName());
mbMessageQuery.add(RestrictionsFactoryUtil.eq("classNameId", blogsEntryClassNameId));
mbMessageQuery.add(PropertyFactoryUtil.forName("parentMessageId").ne(0l));
mbMessageQuery.add(PropertyFactoryUtil.forName("classNameId").ne(0l));
mbMessageQuery.add(PropertyFactoryUtil.forName("classPK").ne(0l));
mbMessageQuery.add(PropertyFactoryUtil.forName("categoryId").eq(-1l));
List dynamicQuery = MBMessageLocalServiceUtil.dynamicQuery(mbMessageQuery);


If you like this post 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.

Java Reflection API in Liferay

I am currently experimenting with the Java Reflection API in combination with Liferay and the Dynamic Query API. I want to see if I can build some more generic accessor classes for the Dynamic Query API. So I started today and I came across this Exception:

Exception in thread "main" java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)


This happens, when you (like me) try to invoke a method without providing an actual instance of the class the method should be invoked on. So don´t use


Method method = instanze.getClass().getMethod("getTest", (Class[]) null);
Object[] myArray = new T1[0];
method.invoke(myArray);


Use instead

method.invoke(instanze,myArray);


If you like this post 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.

5/22/2011

Beginners Guide to Liferay Web Contents (Web CMS)

When you are using Liferay as a Web Content Management System, you can´t  get around creating Web Contents. This post shows you how to create them, and how to use Structures & Templates. It surely is a beginners guide to this field and I intend to add additional posts when I have the time.

What are Web Contents ?

Web Contents are pieces of content that can consist of HTML markus, javascript and CSS. So basically, a Web Content is a small HTML page. The internal description of Web Content is JournalArticle, that´s why (if you are a programmer) you will find all WebContents in the dataTable "journalarticle" and you have to use JournalArticleLocalServiceUtil to access the table. Web Contents, in contrast to portlets, can be created and administrated by end users, marketing departments or secretaries. 

How to create a simple Web Content

To create a Web Content, you need to have the right to enter the Liferay Control Panel. Open It, and on the right side, you´ll see the "Web Content".

Web Content Selection in Liferay Control Panel
The important parts on this page are "Web Content", "Structures" and "Templates". Structures define a data structure that will hold the data types (Strings, boolean values, images, link) that your Web Content will consist of. Templates take the data structure created in Structures and use it to create a web page. Web Contents specify the actual content that is used by the Template to build the displayed entity. This allows us to re-use Templates to create Web Contents that always will look and behave the same.

To start creating a first Web Content, select the "Structures" tab and click on "Add Structure". 


Creating a Structure
At the beginning, our structure is empty. Click on "Autogenerate ID" to let Liferay handling the ID creation. Enter "Hello World" as name and "Hello World Description" as our description. We will now create a simple Web Content that will have a headline, a picture and some content. To do so, click on "Add Row" three times. This will create three rows for our three data types. Give the three rows the names "headline", "pic" and "content". Next, select the type in the dropdown box next to the name field. For "headline" it's "Text", for pic it´s "Image Gallery" and for content it´s "Text Box (HTML)". This allows the editor later to enter a headline text, to select an image from the image gallery and to enter an html-formatted text. Even with javascript.

At the end, your structure will look like this:

Your structure

If you did this, click on "Save" and we are done with our Structure. Next, click on "Templates" and "Add Template". We need a template to transform our structure into something viewable. Let Liferay generate the ID, enter a name and a description and click on "Structure". By selecting our "Hello World" Structure, we link our template to it. 
The next thing, you have to do, is to write the template. This is done in velocity, and velocity itself is worth a couple of books. What we will do here is to write a little velocity script that will do nothing but to display our data. Here are the basics:



  • You can use HTML.
  • You can use Javascript.
  • To access a structures data (for example the value we will later enter into "headline") use $structurename.data.

Add the following HTML snippet into your Template Editor:


<p>
    <h1>$headline.data</h1></br>
    <img src="$pic.data"/></br>
    $content.data
</p>

This will create a simple headline followed by an image and our content. 
Now it`s time to put it all together. Upload an image of your choice to the Image Gallery, enter the "Web Content" section and click on "Create WebContent". Now - on the right side, select the template we just added, You will notice, that the structure is selected automatically.
You will also notice, that you now have some more fields to fill out - for the headline, the picture and the content. Enter some data and your screen should look like this:




This will be the editing screen all the people that don´t really care for data structures, velocity and all that stuff. Click on "Publish" when you finished and leave the control center.


Go to any page you want to display the Web Content and click on "Add" and then "Web Content Display":




Now, click on "Select Web Content" and you should see the Select Web Content View:




Click on "Save" and close the window and you are done. You should now see your Web Content:




If you want, you can change the headline. Click on the Portlet Menu, select "Look and Feel", click on "Use Custom Title" and enter a fancy name. If you don´t want any header (no title) deselect "Show Borders".


Read Part 2 here.



If you like 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.

5/06/2011

Querying Liferay Entities

If you need information on how to use Dynamic Queries with Liferay Entities you need to know which attributes you can query for. The place where to look is the "portal-hbm.xml" file which you can find in portal-impl/src/META-INF.


This file encapsulates all information about the standard liferay entities: Address, User, Role, Group etc etc etc.


If you need information about how to use Dynamic Queries, take a look here:
http://liferay-blogging.blogspot.com/search/label/DynamicQuery

Happy Weekend !!!




If you like this post 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.

Developing JSF 2.0 Portlets with Liferay in Eclipse

A lot of visitors come to my blog to find out the easiest way to develop JSF 2.0 portlets with Eclipse. Here is just a note from me: Although Liferay IDE allows you to select "create JSF 2.0" portlet, it can´t do that right now. You will need Liferay 6.1 / plugins-sdk 6.1 to do that. There is nothing else for you but to create a portlet on your own.

Or ... you could use this link to download a JSF 2.0 portlet that you can unzip into your plugins-sdk/portlets folder: https://rapidshare.com/files/460901106/HelloJSF2World-portlet.zip


It works with Liferay 6.05 CE and already has a standard Liferay build script. What you have to do before that is to deploy the following libs to your servers lib directory (You can get them from portletfaces.org):




  • alloyfaces-1.0.1.0.jar
  • commons-fileupload-1.2.2.jar
  • commons-io-1.3.2.jar
  • jboss-el-2.0.0.GA.jar
  • jsf-api-2.1.1-b03.jar
  • jsf-impl-2.1.1-b03.jar
  • portletfaces-bridge-2.0.0.jar

That should be all to have your very own JSF 2.0 Portlet in Liferay.



If you like 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.

5/03/2011

JSR 303: Validation in JSF 2.0 - Part 1

This post is about the JSR 303 validation that JSF 2.0 applications may use. We will create a first "Hello World" example and won´t go that much into detail. First, download the reference implementation of JSR 303:


http://www.hibernate.org/subprojects/validator.html




1) Create a new JSF 2.0 Dynamic Web Project 




As you can see, I created a ManageBean called "MyBean". Then I added all hibernate jars from the downloaded jar file to the WEB-INF\lib dir. This is just to keep the functionality in the web application. If you want, you can add them to your servers lib dir. Then I created a blank "index.xhtml" which we will use to reference the bean.





















2) Create the Bean Class






Here is the snippet of the ManagedBean I created for this example. Annotate the bean with "@ManagedBean", then create a simple String that will hold our input.
Annotate it with the hibernate annotation"@NotEmpty". This will prevent the user from submitting a form where entries are missing.






3) Create the view




Create a simple JSF 2.0 application: Add an input field and a commandButton: That´s it ! 


You can test the validation by entering nothing into the input field and clicking the submit button.






If you like 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.

5/02/2011

How to set the database, liferay uses

Ok, most of you people already know, but I wanted to have a place for myself where I can look it look. This is how you configure the database that liferay uses:


Locate the file "portal-ext.properties". It should be in your applications server deploy directory under ROOT\WEB-INF\classes. If it doesn´t exist - create it.


Add the following:

jdbc.default.driverClassName=com.mysql.jdbc.Driver 
jdbc.default.url=jdbc:mysql://localhost/lportal?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false 
jdbc.default.username= username
jdbc.default.password=password


Replace the database name, username and password and you are done :).


If you like this post 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.

5/01/2011

Task cannot continue because ECJ is not installed.

If you ever encounter this while building a liferay portlet in eclipse:

BUILD FAILED


...plugins-sdk\build-common.xml:88: .


Task cannot continue because ECJ is not installed.
ECJ was automatically installed. Please rerun your task.



Then you should just add the jar "ecj.jar" to the ant classpath in eclipse.
To do so click on "window -> preferences -> ant -> Runtime".




Select "Ant Home Entries" and add the jar. You will either find it in your plugins-sdk or in your ant directory on your harddrive.




If you like 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.