3/30/2011

About the E-Mail Listener in Liferay ...

Some weeks ago, I wrote about creating an own email listener:


http://liferay-blogging.blogspot.com/2011/02/how-to-create-e-mail-listener-in.html


If you do this, you need a way to register your email listener. One way could be in a hook or in a portlet that, when being initialized, registers the email listener. But beware: Your listeners are not unregistered, when you redeploy your portlet / hook ! After a redeployment you suddenly have 2 (or more) listeners doing your work. The solution must be to call unregister before registering a new one.


This might be a solution:


EmailListener listener = new EmailListener();
MessageBus messageBus = MessageBusUtil.getMessageBus();
MessageBusUtil.unregisterMessageListener(DestinationNames.MAIL, listener);
MessageBusUtil.registerMessageListener(DestinationNames.MAIL, listener);

This only works if the equals() method of your listener is properly configured and (for example) checks for the className.



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.

3/26/2011

Inter Portlet Communication in Liferay - Part 1

You will always have the requirement for portlets to communicate with each other.  For example: To book a flight you select the country you wish to fly to. When selecting a country in your portlet, the weather portlet also changes to display the current weather situation in your desired holiday location.


This is done by Inter Portlet Communication and in this series I want to show you how it´s done.


Part 1 : IPC Events



IPC Events, as introduced in JSR-286 (Portlets 2.0), work like any other event you might know from J2EE: They react to events being fired and the sender doesn´t need to care whether there is any receiver. 
This loosely coupled approach makes using the Events so much fun :)

In the example we will do right now we will just send a "Hello World" String from one portlet to another.

To choose a portlet as sender or receiver you need to add the configuration for the sender or receiver to the portlet.xml of the chosen portlet.

Sender configuration

To configure a portlet to be available to send events, add the following to your portlet.xml:

First, you have to define the event to send. To do this, you need to specify a namespace and a name for your event. This definition is the event definition that has to go into the portlet.xml of the sender AND of all receivers.
In our case it defines, that an event called "message" for the namespace http:your.private.namespace.com/yourEvent exists which is a String

<event-definition>
<qname xmlns:t="http:your.private.namespace.com/yourEvent">t:message</qname>
<value-type>java.lang.String</value-type>
</event-definition>

To choose your portlet as a sending portlet additionally add the following:

<supported-publishing-event>
   <qname xmlns:u="http:your.private.namespace.com/yourEvent">t:message</qname>
</supported-publishing-event>

This selects your portlet as a sending portlet for the chosen event. This is all for the configuration of the sender portlet. Now let´s take a look at the code to send an event.



public void sendEvent(ActionRequest actionRequest,
ActionResponse actionResponse) {
QName qname = new QName(
"http:your.private.namespace.com/yourEvent",
"message");
actionResponse.setEvent(qname,"Hello World");
return;
}


Believe it or not ... but this is all it takes to send out an event.


Receiver configuration

First add the event definition we created earlier to the portlet.xml of your receiving portlet.

Second, add the following "i am a receiving portlet" definition to the portlet.xml:

<supported-processing-event>
<qname xmlns:u="http:your.private.namespace.com/yourEvent">t:message</qname>
</supported-processing-event>

Now, just a little code to your receiving portlet class, and you can already test it:

@Override
public void processEvent(EventRequest request, EventResponse response) {
Event event = request.getEvent();

if (event.getName().equals("message")) {

//hooray we have our event
String  message = (String) event.getValue();
}
}
That´s it ... IPC with Events based on the JSR 286 Specification


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.

3/24/2011

Using the DynamicQuery API in Liferay with more than one group by

I love the Dynamic Query APi for Liferay ! It allows me to query everything I want from the liferay database without having to write a single line of sql.


And now I know how to specify more than one projection. Just use the ProjectionList !


If you want to group your results, for example, by firstName and lastName, you could do it like this:



ProjectionList projectionList = ProjectionFactoryUtil.projectionList();

projectionList.add(ProjectionFactoryUtil.groupProperty("firstName"));
projectionList.add(ProjectionFactoryUtil.groupProperty("lastName"));
myQuery.setProjection(projectionList);



It also allows you to group by one column and return the count of another:



ProjectionList projectionList = ProjectionFactoryUtil.projectionList();
projectionList.add(ProjectionFactoryUtil.groupProperty("firstName"));
projectionList.add(ProjectionFactoryUtil.count("lastName"));
myQuery.setProjection(projectionList);



You can also specify aliases (just look at the ProjectionList outline) ... all in all a very powerful feature which I, from now on will use a little more often!




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.

3/21/2011

Creating a URL for an MVC Portlet

I (sadly) have to work with JSPs at the moment, so I can´t use ICEfaces and I can´t use all the benefits JSF brought into this world. 
When you have to develop with JSPs it´s like going back to the stoneage of web development. But one thing, I just found out, works pretty well. It´s the calling of backing bean methods from a JSP.


If you have created an MVCPortlet (never, ever use the GenericPortlet !!!), then you can create a link, that relates directly to a backing bean method by doing this:


PortletURL url = renderResponse.createActionURL();

url.setParameter("javax.portlet.action","methodName");

url.setParameter("parameter","value");

This relates to a method in your backing bean that looks like this, where you can access your parameters:


public void 
methodName 
(ActionRequest actionRequest, ActionResponse actionResponse) 
throws IOException, PortletException{

String parameter = actionRequest.getParameter("parameter");
System.out.println(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.

3/18/2011

How to prevent bean fields from being overridden in JSF when using a ChangeListener

Maybe you had this problem before:


You have two input fields and a changeListener bound to one of them. If the changeListener fires, you also want to change the content of the second input field. It works, but sadly, JSF overwrites the values you just set with the initial values. 


Here is your solution: Push back the change event to a later phase in the JSF life cycle:



public final void someChangeListener(ValueChangeEvent event) {
PhaseId phaseId = event.getPhaseId();

if (phaseId.equals(PhaseId.ANY_PHASE)) {
event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
event.queue();
} else if (phaseId.equals(PhaseId.UPDATE_MODEL_VALUES)) {
String newValue = (String) event.getNewValue();

setValue(newValue);
}

}

That´s all :)



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.

3/17/2011

Bug in Liferay 6.0.10 ? Accessing a Portlet´s Service from another Portlet

If you want to access a Service that has been defined by Portlet A by Portlet B you would normally do this :


http://liferay-blogging.blogspot.com/2011/03/liferay-portlets-accessing-services-of.html

But what if you get this Exception :

java.lang.NullPointerException
at com.liferay.socialnetworking.service.WallEntryLocalServiceClp.<init>(WallEntryLocalServiceClp.java:598)
at com.liferay.socialnetworking.service.WallEntryLocalServiceUtil.getService(WallEntryLocalServiceUtil.java:290)
at com.liferay.socialnetworking.service.WallEntryLocalServiceUtil.dynamicQuery(WallEntryLocalServiceUtil.java:98)
at ...





Well, then it might be that you have running Liferay 6.0.10, which (to me ) seems to have a bug which results in returning null instead of a classloaderproxy. So - what is to be done ?


1) Migrate to 6.0.11 - The Bug is fixed there or


2) Define all Services you wish to access AGAIN in the accessing portlet. If you use the "table" property, you make sure, the services access the same table. Here is an example to access the table of the chat portlet:


<entity name="Entry"  table="chat_entry"  local-service="true" remote-service="false">...</entity>




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.

3/16/2011

New Features of JSF 2.0 - Part 3

JSF 2.0 : Custom Components - Part 2


In this part of the Tutorial to learn JSF 2.0 we will cover the advanced functions of the custom components. If you want to read the other articles about the new features of JSF 2.0, then take a look here:


Part 1 - JSF Resources || Part 2 - Custom Components I


Now we will cover the advanced usage of custom components. To do so, let´s first take a look at the component we developed the last time:



<h:body>
   <composite:interface>
   </composite:interface>

   <composite:implementation>
   <h1>Hello World</h1>
   </composite:implementation>

</h:body>





As you can see it consists of an interface and an implementation, just as you would expect it in Java: The interface defines the contract, the implementation the concrete behaviour.


Before we add some content, just a note: You don´t need to fill out the interface part - it´s completly optional. But it will help the developer using your component a lot if you put everything in, that you are using in your implementation part.


We won´t cover all aspects of the custom components, but we will get you so far, that you can go the last steps on your own.


so - let´s start with the interface part. Here is an example of what you might add to it:


<composite:interface>
    <composite:attribute name="someLabel" >

</composite:interface>




This defines an attribute that you can use in your implementation. For example as a label:


<composite:implementation>
    <ice:outputLabel value="#{cc.attrs.someLabel}"/>
</composite:implementation>



You always access attributes by #{cc.attrs.attributeName}. cc is the top node of the object structure. 


You could use this component like this:

<test:testComponent someLabel="This is a label"/>.


Or if you want to use dynamic values:



<test:testComponent someLabel="#{someBean.value}"/>.

Ok, next step: How to access methods and beans !

<composite:interface>
    <composite:attribute name="buttonLabel" >
    <composite:attribute name="someMethod" method-signature="java.lang.String methodName()">
</composite:interface>

To pass methods into your custom component, you need to specify the method signature by using the method declaration language like this:

RETURN-VALUE someIdentifyingName(Method parameters).

In our case we have a method that has no input parameters and returns a String. This is the perfect signature to use it as an action method for a commandButton !

 <ice:commandButton id="buttonId" value="#{cc.attrs.buttonLabel}"
      action="#{cc.attrs.someMethod}"/>

That´s all you have to do in your composite component. Now you can dynamically create test components that will render a nice button. You could use it like that:


<test:testComponent buttonLabel="Please Click Me !" someMethod="#{someBean.aMethod}"/>.


That´s all for Part 2 of Custom Components ... stay tuned for Part 3 :)







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.

Vaadin or JSF ?

Hello everybody.


I noticed in the last days and weeks that more and more people are talking about Vaadin and how it would make development in general and in Liferay especially a lot more easy. And the developer studio / Liferay IDE in eclipse allows you to create a vaadin portlet with a few clicks.


To me it seems, that there is a new trend coming, and therefore I want to know your opinion: 



  • Do you use vaadin ?
  • Why do you use vaadin ?
  • Do you prefer Vaadin over JSF ? If yes : Why ?



Please leave a comment:)


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.

Liferay: Portlets accessing Services of other portlets

Just a quick tip:


When you develop portlets you will put most of the generated services in your portlets. So you run the Service Builder, develop your business code and deploy it. Everything´s fine.


But what do you do if another portlet wants to access your service ? Say for  example that portlet A allows you to enter data of users and portlet B displays all users. The service is located in Portlet A and you shouldn´t create a new one in Portlet B.


The solution is simple: Generate your service, and put the resulting xx-portlet-service.jar into your application servers lib dir. 


In Tomcat its (for example): \lib.


Be sure to remove the service jar from Portlet Bs WEB-INF/lib directory !!!
Now restart your server and Portlet B should be able to access all service classes from Portlet A, including the XXLocalServiceUtil.




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.

3/15/2011

How to add a portlet to the Liferay Control Panel

If you want your portlet to be available in the liferay control panel, just add the following:



<control-panel-entry-category>portal</control-panel-entry-category>
<control-panel-entry-weight>2</control-panel-entry-weight>
<instanceable>false</instanceable>




control-panel-entry-category defines where the portal will be shown, for example "portal" or "server".




control-panel-entry-weight defines the position of the portlet in the category you defined above.

control-panel-entry-class is optional and is used to define rights (who can see the portlet and who doesn´t).



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.

3/14/2011

AlloyUI Tutorial Part 3 : Basic AUI Controls

Part 1   Part 2   Part 3   Useful Links   Useful Literature


This is the third part in a line oftutorials for AlloyUI. This time we will step back a bit and take a look on how to use basic Alloy UI components to build a standard JSP page - for Liferay 6.


A normal AUI page consists of all the elements you would normally expect to see on a JSP page: A form, some input fields and a submit button. Here is an example in AlloyUI:


Import the AUI Taglib:


<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui"%>

Then create an action URL for the form you are using


<portlet:actionURL var="myUrl">
</portlet:actionURL>


This URL will be used to bind the form to the actual portlet instance (The portlet class).

Now create the form:

<aui:form action="<%= myUrl%>" name="fm">

inside the form, create some input fields:


<aui:input type="text" name="name"></aui:input>
<aui:input type="password" name="pwd"></aui:input>


This will generate a standard name / password dialog with standard styling.


Next, add a submit button and we are done:

<aui:button type="submit"></aui:button>

That´s basically all, and it should render something like this:


If you want to have the full working portlet, you can download it here:


http://rapidshare.com/files/452502717/AUITest-portlet.zip


That´s the basic UI control tutorial ... next time we will build more complicated GUIs ... promised !




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.

Inter - Portlet Communication in Liferay

IPC (Inter - Portlet Communication) ist wichtig um Beispielsweise mehrere Portlets einer Seite gleichzeitig auf sich verändernde Daten reagieren zu lassen.

Diese Blog - Serie soll nacheinander die einzelnen Möglichkeiten  beleuchten solch eine Kommunikation herzustellen. Teil I wird sich um den Liferay - JavaScript Mechanismus drehen:


Teil I : Liferay JavaScript Event System

Liferay bietet ab Version 5.1 ein eigenes JavaScript - Event - System, um IPC zu ermöglichen.
Die Folgenden 2 Methoden können (out of the box !) sofort genutzt werden, um diese Kommunikation zu ermöglichen:

  • Liferay.trigger(eventName, data) 
  • Liferay.bind(eventName, function, scope)

Hierbei wird ein System, ähnlich dem Observer Pattern genutzt: Zuerst muss sich das empfangende Portlet registrieren (binden), danach kann das sendende Portlet Daten senden (das Event triggern). Dies birgt natürlich das Problem, daß das empfangene Portlet auf jeden Fall vor dem sendenden Portlet sich binden muss. In diesem Fall empfehle ich JQuery, welches bis Liferay 5.x unterstützt wird.

Hier ein Beispiel, welches man einfach so direkt in einem Portlet nutzen kann:

jQuery(document).ready(function(){ 

Liferay.bind('event',
 function(event, data){
  var daten = data.daten;
  //process data ...
  });

});

Fehlt nur noch die sendende Seite (aufzurufen aus dem 2. Portlet):
Liferay.trigger('event', {daten: '1,2,3,4'});

Vorteile dieser Technik:
  • Schnell und unkompliziert aufzusetzen,
  • läuft out-of the box
Nachteile :
  • Wenn man die Daten im Backend braucht, muss man noch entsprechende Komponenten bereitstellen, die die Daten ins Backend bringen, dies erhöht das Coupling
  • Generell sehr starkes Coupling : Backend - Daten im ersten Portlet, Javascript in beiden Portlets und Backend im 2. Portlet müssen übereinstimmen
All das (und noch viel mehr) kann man auch sehr gut hier nachlesen:
http://www.liferay.com/web/guest/community/wiki/-/wiki/1071674/Client-side+Inter-Portlet+Communication
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.

3/11/2011

New Features of JSF 2.0 - Part 2

One thing that was annoying for me since I started working with JSF / ICEFaces was that it is really hard to write reusable components. Especially for firms writing a lot of ICEFaces portlets or applications such a mechanism would save a lot of money.


But, thanks to JSF 2.0, those reusable components will be possible.


JSF 2.0 : Custom Components - Part 1


Custom Components allow you to create truly reusable components in JSF. Those components are that reusable that they will work with any kind of bean you put into them. This means that you can use your components in different projects with different beans.


How to create your first "Hello World" Custom Component


First decide for a namespace. In our case we will use "helloWorld". In this namespace we will create our first component : the testComponent. Create an empty xhtml file. Because all custom components are placed in the standard JSF 2.0 resources folder, we will now have the following structure:

\resources\helloWorld\testComponent.xhtml

We will now create the content for our component. The first component we create will do nothing but to print out "Hello World":


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   <html xmlns="http://www.w3.org/1999/xhtml"
         xmlns:h="http://java.sun.com/jsf/html"
         xmlns:composite="http://java.sun.com/jsf/composite">
   <h:head>
<title>Hello World</title>
   </h:head>


   <h:body>
   <composite:interface>
   </composite:interface>


   <composite:implementation>
   <h1>Hello World</h1>
   </composite:implementation>


   </h:body>
   </html>


The component is created, now we will use it. Create a file called "index.xhtml" and configure it to use our first component. Therefore you import the namespace we just created, prefixed by "http://java.sun.com/jsf/composite/":


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   <html xmlns="http://www.w3.org/1999/xhtml"
         xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core"
         xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:test="http://java.sun.com/jsf/composite/helloWorld">
   <h:head>
<title>Hello World Usage</title>
   </h:head>


   <h:body>
     <f:outputText value="I just wanted to say"/>  
     <test:testComponent/>
   </h:body>
</html>


You can use the component simply by adding this to your file: <test:testComponent/>.


The example we created above works, but of course is a little simple. It gets really interesting, when we start passing parameters into our component. This will be done in Part 3.



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.