8/30/2011

Hiding the Liferay Control Panel

Whenever you set up Liferay for a customer, there will be a requirement to prevent the "normal" user from accessing the control panel. Some administrators fear, the user might do things he´s not supposed to do, others fear, the the user might be confused.

But how do you hide the control panel?

Well, there are several possibilities, and none of them is really nice. There is no portal.properties entry and there is no permission you could set. Either you do it programmatically or by CSS and then you also have the loophole of users entering the control panel URL into the browser:

You, and all of your users can always access the control panel by entering "http://localhost:8080/group/control_panel" into the Browser, no matter what you do. To prevent this, I suspect you have to take a look at ServletFilters and prevent every access to this URL if the User is no administrator.

I will now point out two possibilities how to hide the control panel and I would be very glad if you could describe your own approaches in the comments section.


Hiding the Control Panel programmatically


if you want to hide the control panel for all users, who are no administrators you can overwrite the ServicePreAction class in your ext environment. If you take a look at the servicePre method you will find this:
themeDisplay.setShowControlPanelIcon(signedIn);
So, what ever you do in the .vm files your theme provides: All logged in users will always see the link to the control panel. To remove it, just call the RoleLocalServiceUtil, check whether your user has administrative rights, and change the code above.


Hide the Control Panel using CSS


You could hide the control panel using CSS: You need to apply display:none styles to all elements of the class(es) "control-panel last aui-menu-item".


But how do you make sure, the control panel is hidden from normal users ? To do this, you need to have your own theme. In your theme you need to change the portal_normal.vm and add the following:

#if ($permissionChecker.isCompanyAdmin($company_id))
<style type="text/css"> 
  .control-panel{
    display:none;
  }
</style>
#end


That´s it .. control panel should be hidden!


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.

8/22/2011

Creating New Struts Actions with Liferay 6.1

I just stumbled upon this Liferay Blog Post which I find very interesting:


It would solve one of the problems I right now have:

Liferay 6.1 allows you to add or modify structs actions in a hook plugin. Just a little configuration for your liferay-hook.xml and a little programming and you could easily extend every existing Liferay Portlet. I can`t wait for it to be finished ...


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.

Let Liferay create Roles automatically

If you want to assure that everyone of your developers always works with the same Roles for your Users, you should let liferay create them. It´s very easy, take a look here:


Add the following into your portal-ext.properties:
system.roles = Role1, Role2,Role3
system.role.Role1.description = Role 1
system.role.Role2.description = Role 2
system.role.Role3.description = Role 3
This will automatically create the three roles and also provide a description after you restart your server :)



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.

8/18/2011

Liferay 6.1 Features: Dynamic Data Lists

Overview | Liferay App-Store | Required Categories | Page Customizations | Dynamic Data Lists


Welcome to the next part in my series about the forthcoming and promising Liferay 6.1. Today we will take a look at dynamic data lists and what they offer to you. To summarize it in one sentence, dynamic data lists (DDLs) are a little like Excel Workflows in a portlet.


The administrator has the possibility to create a DDL by first creating a data definition. A data definition is kind of a template that specifies which entities (Integer, Boolean, Date, Text ...) the dynamic data list may hold. The DDL is just an instantiation of this template.


Data Definition Editor
The Data Definition Editor allows to drag and drop all the fields that you want to appear in the Dynamic data List.  If we take a look at the DDL Explorer we can see that we now have the possibility to modify our DDL and to enter into a Spreadsheet View. 


Dynamic Data List Explorer




This Spreadship view allows us to enter some data into the DDL and this is the reason why I call it "Excel for Portlets". You enter enter as much data as you want according to the Data Definition we just created.


Spreadsheet View
The DDL we just created and enriched with some data is exportable by CSV or XML so you may well use it in your Excel to calculate monthly incomes etc.


One thing I am missing are formulars and calculations: Wouldn´t it be nice not having to use Excel at all? It would save some money and make some workflows totally automatic. Maybe they will go for that in Liferay 6.2? Who knows...


To use DDLs in your portlet environment, Liferay has already created a working Dynamic Data List Display Portlet that lets you choose a DDL, decide whether it should be editable and assign it to your Users. This lets your Users remotely create records of data that your financial officer can use to calculate summarized monthly expenses.


Dynamic Data List Display Portlet
Also the asset publisher allows to filter its results for only DDL records. Good idea, if someone needs to have a quick glimpse over all newly created records.


If you take a look at the DDLD Portlet, you will see, that you can also create list and detail templates. Isn´t that great? Now you also have the possibility to customize the view of your DDL! So - without and programming you can create a fully working, customizable remote Excel-light. Of course, the DDLs can also be accessed programatically. The tables you need to know are:

  • DDLRecord (the individual DDL),
  • DDLRecordSet (Data Definition) and 
  • DDLRecordVersion (everything is versioned in liferay).
UPDATE:


I just saw that Liferay also has a blog entry about dynamic data lists. Take a look here:
http://www.liferay.com/de/web/marcellus.tavares/blog/-/blogs/9961174


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.

8/16/2011

How to create a Liferay Action Menu

Just a quick tutorial on how to create those Liferay Action Menus that you can find everywhere in liferay. Here is one example from the Liferay User Menu:

And here is a little tutorial that shows how those so-called icon menus can be created. All you need are URLs (pointing to your portlets class` methods) and icons. That´s it. The example I will show you now will use all the icons you can find under 
\tomcat-6.0.29\webapps\ROOT\html\themes\classic\images\common.


Here is an example that creates two icons and links them to actionURLs in the portlet class. Notice how we just have to specify that we want to have the edit or permissions icons without having to specify a path or a filename. That´s what I call convention over configuration!

<liferay-ui:icon-menu>
  <portlet:actionURL name="edit" var="edit"/>
  <liferay-ui:icon image="edit" message="Edit" url="<%=edit.toString() %>" />
  <portlet:actionURL name="permissions" var="permissions"/> 
  <liferay-ui:icon image="permissions" message="Permissions" url="<%= permissions.toString() %>" />
</liferay-ui:icon-menu>
Quick Explanation: the action URLs link to the method in the portlet class that matches the "name" attribute. The icon tag is linked to an icon in the chosen theme, has a message and connect to the action URL. That´s all !! I love it !!!


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.

Creating Liferay Search Container GUIs

Time for some basic knowledge:

What does the liferay-ui tld say about the search container? How is it possible to create nice and functional search container GUIS? Read the following and you know more:

The search container is always rendering a set of rows that contain one or more columns to display search results. You may change the way the search container is rendering the rows but in the end it will always be a set of rows. So what we are going to do now will only affect the rows itself. We won't change the search container to display grids or something similar.


The liferay search container is structured as follows:

<liferay-ui:search-container > 
<liferay-ui:search-container-results>
<!-- Calculate results-->
</liferay-ui:search-container-results>
<liferay-ui:search-container-row>
<!--Create the rows that display the search results-->
</liferay-ui:search-container-row>
</liferay-ui:search-container >


Because we will only care for the rows, we will jump right in and take a look at some of the tags you can use:


search-container-column-text


<liferay-ui:search-container-column-text name="userName" property="userName" />

The column text tag creates a label filled with a header text (name) and a populated value of the search container entity (property). In our case, the property userName would be taken from our entity and displayed.


search-container-column-jsp


<liferay-ui:search-container-column-jsp path="/your.jsp" align="right" />

Very powerful! Allows to create a complete JSP that will be displayed in every row. By using this tag you can create your own forms with AlloyUI or standard HTML / Javascript and let the search container do all the magic.

search-container-column-button


<liferay-ui:search-container-column-button align="right" href="<%= yourUrl %>" name='clickMe' />

Allows to create a button pretty easy and connect it to a URL.


search-container-column-score

<liferay-ui:ratings classPK="<%=user.getUserId()%>" className="<%=User.class.getName() %>" />
Shows the score for the retrieved object.


These tags allow you to create very fast very powerful search container GUIs. I´ve only touched the surface here and there is a lot more of liferay magic that you can discover. Just take a look at the TLD which you can find here: 


http://code.google.com/p/liferay-book/source/browse/trunk/portlets/library-portlet/docroot/WEB-INF/tld/liferay-ui.tld?spec=svn3&r=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.

8/12/2011

Liferay 6.1 Features: Page Customizations

Overview | Liferay App-Store | Required Categories | Page Customizations | Dynamic Data Lists

A rather small but nice feature is the possibility for administrator to lock certain parts of a liferay page for modifications. Depending on the page layout you use you have two or more areas that you can lock or unlock. Simply click on "Manage -> Page Customizations" and you will see the following screen:


As you can see, you can lock or unlock every area in you portlet page by selecting or deselecting it. If you want users only to edit the upper and lower part of your page you would check the according checkboxes and see the following:


Users now have no possibility to move or edit the portlets in the middle areas.

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.

8/11/2011

Liferay 6.1 Features: Required Categories

Overview | Liferay App-Store | Required Categories | Page Customizations | Dynamic Data Lists


I am currently playing with Liferay 6.1 and I am going to report every cool feature I will stumble upon. The first post in this series will be about required categories.


Required categories allow an administrator to define categories for certain asset types (documents, users, comments etc) that HAVE to be set. So it is very easy to extend the user interface liferay provides, say for documents, by a dropdown box that allows to choose the author or the year the manuscript was published. Here is how you use it.


First enter the new categories view in the new control panel:




Add a new vocabulary , give it a name and a description and take a look at the "associated asset types". They allow to link the category to an asset type of your choice. In this case it`s Document Library Document. By selecting an asset, the Vocabulary will only appear on forms for this very special asset. In our case, it won´t be possible to select a color category for a comment or a blog entry.
By deselecting "Allow Multiple Components" we make sure that only ONE category can be selected, by selecting "Required" we make sure that it HAS to be selected.
The next screenshot shows the new Categories section with the selected Color Vocabulary and its enclosed Categories Blue, Green and Red.




If you now add a document, you will see that you have to select a color. In my opinion, this is just great because it will make programmatically changes to the document library less and less possible.




The required categories will speed up development and save you some money. Thumbs up !


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.

Direct Connection to the Liferay Database

In Liferay, if you want to modify or read entities you would normally use dynamic queries. You can find a lot of tutorials here at liferay-blogging about the DynamicQuery API.


Sometimes you need a direct access to the database to use SQL for whatever reason there might be. This is a little tutorial to show you how you can archieve this with Liferay 6 and Tomcat 6.0.29. To access the database directly you need to define a datasource in your tomcat.
Open the file /conf/context.xml and add the following in the <Context> section:

<Resource 
name="jdbc/Liferay" 
auth="Container" 
type="javax.sql.DataSource" 
maxActive="100" 
maxIdle="30" 
maxWait="10000" 
username="root" 
password="root" 
driverClassName="com.mysql.jdbc.Driver" 
url="jdbc:mysql://localhost:3306/lportal"/>

This defines an access point for your database for the database lportal and the user "root" with the password "root". Change it to fit your needs and open the web.xml of the portlet or hook that needs to access the database.

Add the following:
<resource-ref>
    <description>DB Connection</description>
    <res-ref-name>jdbc/Liferay</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

This makes the dataSource accessible in your portlet. To access and use it, trythe following snippet.It should print our all screen names of all registered users:
Context ctx = new InitialContext(); 
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/Liferay"); 
Connection conn = ds.getConnection();
Statement stmt = conn.createStatement(); 
ResultSet set = stmt.executeQuery("select screenname from user_"); 
if(set.next()) {
  System.out.println("Screenname :"+set.getString(1);
 } 
conn.close();

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.

Download Liferay 6.1 Preview

If you like to try our the forthcoming Liferay 6.1, you can download a nightly build here:


http://releases.liferay.com/portal/nightly/


Use it together with the newest version of Liferay IDE which you can find here:


http://sourceforge.net/projects/lportal/files/Liferay%20IDE/1.3.0/


I am downloading it right now and will keep you all informed about what we can expect from the newest version of Liferay.


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.

8/10/2011

How to change the Liferay Login Module / Authentication Pipeline

If you want to change the Login Module, Liferay uses, or you want to add LDAP authentication to your liferay system, you need to use the liferay authentication pipeline.


To configure your pipeline, you have to take a look into your portal.properties. You will find the following properties:



auth.pipeline.enable.liferay.check=false
auth.pipeline.pre=de.test.auth.RefuseAuthenticator



Those configure the authentication pipeline. The first one disables the standard liferay behaviour to authenticate vs. its configured database. The second tells liferay which classes to use to verify name/password combinations. You can enter as much Authenticators as you want and they will be processed sequentially.


Every Authenticator must implement the interface com.liferay.portal.security.auth.Authenticator. If you take a look you will know what you have to do: The methods authenticateByEmailAddress, authenticateByScreenName and authenticateByUserId are self explanatory.


Here is an example of a RefuseAuthenticator that will refuse every user. Not very useful but it shows how an implemented Authenticator may look like:


package de.test.auth;

import java.util.Map;
import com.liferay.portal.security.auth.AuthException;
import com.liferay.portal.security.auth.Authenticator;

public class RefuseAuthenticator implements Authenticator {

public int authenticateByEmailAddress(long arg0, String arg1, String arg2, Map<String, String[]> arg3, Map<String, String[]> arg4) throws AuthException {

    System.out.println("failed by mail");
    return FAILURE;
}

public int authenticateByScreenName(long arg0, String arg1, String arg2, Map<String, String[]> arg3, Map<String, String[]> arg4) throws AuthException {

    System.out.println("failed by screen name");
    return FAILURE;
}

public int authenticateByUserId(long arg0, long arg1, String arg2, Map<String, String[]> arg3, Map<String, String[]> arg4) throws AuthException {

    System.out.println("failed by user id");
    return FAILURE;
}

}




If you add the lines to your portal-ext.properties and provide the class with your ext environment you should not be able to log into liferay anymore.


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.

8/06/2011

Using parameterized method calls in JSF 2.0

One of the very nice features of JSF 2.0 is the ability to call action methods with parameters. 


Why is that important ? It is important because it allows you to call any method with a click without having to use parameter tags. This is conjunction with JSF 2.0 composite components lets you do magical things like creating unlimited ICEfaces popups.


Let me explain further:


If you use ICEfaces or JSF in a business environment you will always try to reuse components: Don´t Repeat Yourself (DRY). By using composite components, developers using JSF 2.0 (and ICEfaces 2.0) have this ability: One team is creating the components, another team is reusing them to create great applications.


If you want to create a component that displays an ICEfaces popup (PanelPopup component) you have to find a way to let the user call and recall the same popup. The user must have the possibility to create, close and create the popup again and again. 


So the questions are: 


1) How do you let the business component developer tell the composite component which popup to open ?


2) How has the composite component to be developed to open and close always the right popup and keep its state ?


This is my solution, if you have any other solution, please let me know.


The composite component


The composite component that is rendering the popups is a popup component like you would develop it if you wouldn´t care about reusability. You need a boolean value to determine whether it is opened or not and a close Button. Of course you will always need more buttons, business logic etc etc but for our little example here we will just open and close the popup:



<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:icecore="http://www.icefaces.org/icefaces/core"
xmlns:ace="http://www.icefaces.org/icefaces/components"
xmlns:ice="http://www.icesoft.com/icefaces/component">

<head>
    <title>A Popup</title>
</head>
<body>
    <cc:interface>
      <cc:attribute name="bean" required="true" />
    </cc:interface>

    <cc:implementation>
      <ice:panelPopup rendered="#{cc.attrs.bean.show}" modal="true">
      <f:facet name="header">
      <ice:outputText value="Confirmation" />
      </f:facet>
      <f:facet name="body">
      <ice:panelGrid columns="1">
      <ice:outputText value="This is a popup" />
      <ice:commandButton value="Close" actionListener="#{cc.attrs.bean.toggleShow}" />
      </ice:panelGrid>
      </ice:panelGrid>
      </f:facet>
      </ice:panelPopup>
</cc:implementation>
</body>
</html>


As you can see ... nothing special about the composite component so far. We have a bean that holds its state and has a method that allows to toggle the state.


The code


Something much more interesting is the code invoking the composite component:
<composite:popup bean="#{popupCreator.createPopup('test')}" />
We invoke the composite component by calling a parameterized method that returns a Bean. The Bean that we are using in our composite component. This is the code:



private Bean createPopup(String id) {

  Bean bean= beanMap.get(id);
  if (bean== null) {
  bean= new Bean();
  beanMap.put(id, confirmationBean);
  }
  return bean;
}


That´s basically all. If you know how to do composite components, you know how to use this code. This is kind of a generic approach to create truly reusable components. I would be interested in your approaches: How did you solve challenges like this ?




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.

8/02/2011

Liferay and Java 7

Java 7 is out ! Hooray !


If you want to know what Java7 can do for you, take a look here: http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html#changes.


It has a lot of interesting features, some of them I am going to describe in detail in the coming weeks. If you are interested in using Applets in your Portlets you might be intersted in a feature that allows you to determine if your applet is ready to make javaScript calls. This might come in very handy.


But beware, you should not use it right away. Give the folks at Oracle some time to fix some of the bugs that are still in the code. Some of them make working with Lucene and Solr impossile which then means, that working with Liferay is impossible (you can use either Lucene or Solr). If you want to know more, you can take a look here:


http://lucene.apache.org/#28+July+2011+-+WARNING%3A+Index+corruption+and+crashes+in+Apache+Lucene+Core+%2F+Apache+Solr+with+Java+7


My suggestion would be to stick with your existing Java 1.6 installation and try again in 6 months.


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.