Milen Dyankov

on a mission to help developers build clean, modular, and future-proof software

Recent Posts

  • July 04, 2010

    Liferay Portal 6 Enterprise Intranets review

    A few weeks ago I was asked by Packt publishing to review the new Liferay Portal 6 Enterprise Intranets book. Going through over 650 pages took me some time but finally I'm ready to share my thought about it. 

    By now you are probably scanning the text for something like "In general this is ____ book". Don't bother, I'm not going to generalize in this post. In fact, what you put in place of ____  depends on who you are, what is your Liferay background, and what you expect to learn.

     

  • May 03, 2010

    Writing Liferay portlet to display a file in a way "tail -f" does

    Don't know about you but I can't imagine debugging enterprise class applications without having "tail -f /path/to/log.file" running in dedicated console window. During development and testing phases (assuming work is done "in house") there is usually no problem with this approach as the whole team have access to servers' log files. This is not always the case with staging and production environments though. These days a lot of companies execute strong security policies which sometimes means that application is only accessible via HTTP. In such case, depending on how you SLA looks like, "log files provided on demand via e-mail or FTP" may not be an option. 

    Facing this kind of problem in recent Liferay based project, made me think about creating a portlet capable of displaying log files. Something like WWW based version of "tail -f". This is how Tailgate was born (for those of you looking for solution here is download page). The rest of this post will concentrate on explaining why it was not "a max 2h of coding" as I thought in the begging.

  • April 05, 2010

    Custom global markup portlet

    What would you do if a customer demands to "integrate" his Liferay based corporate portal with Google Analytics, Geminus, ClickTale, Crazy Egg,  and whole bunch of other analytics tools available out there?

    As you probably know, such services typically provide some piece of javascript (code or file) which needs to be added to every page of monitored web site. Each service also provides unique customer code/key (which is either already part of the javascript provided or needs to be placed in specific place). Regardless of whether using all of them at the same time is a smart thing to do, there are a few technical problems to solve:

    • How to add custom code to every portal page
    • How to deal with unique codes/keys through development, testing, staging, production phases
    • How to minimize the impact of changing/removing custom code in production environment

  • October 09, 2009

    Creating Liferay portlet with liferay-maven-sdk

    This post will demonstrate how liferay-maven-sdk can be employed to build a Liferay portlet using Liferay’s Service Builder feature. For this purpose we will create service-builder-portlet which is capable of displaying a list of players and adding a new player to this list. The model, persistence layer and data access services will be generated by Service Builder.

    But first things first. Download and install liferay-maven-sdk if you haven’t done so already (have a look at Download and Install page for instructions). Once liferay-maven-sdk is installed in your local repository, you can create the portlet.

    So enter the folder (or create one) where you keep your portlets and execute mvn archetype:generate you should see a list of available archetypes starting with

    Choose archetype:
    1: local -> liferay-portlet-archetype (Liferay portlet archetype)
    2: local -> liferay-theme-archetype (Liferay theme archetype)
    3: internal -> appfuse-basic-jsf (AppFuse archetype for creating a web application with Hibernate, Spring and JSF)
    4: internal -> appfuse-basic-spring (AppFuse archetype for creating a web application with Hibernate, Spring and Spring MVC)
    ...
    Choose a number: (1/2/3/4/...) :1
    

    Type 1 and press enter to choose liferay-portlet-archetype. Then provide groupId, artifactID, package and version. For example:

    Define value for groupId: : com.commsen.liferay.examples.portlet.servicebuilder
    Define value for artifactId: : service-builder-portlet
    Define value for version: 1.0-SNAPSHOT: : 1.0
    Define value for package: com.commsen.liferay.examples.portlet.servicebuilder: :
    

    Additionally you may execute mvn eclipse:eclipse to setup Eclipse IDE if, that is what you are using! At this time your portlet skeleton is ready and you may compile it and even create WAR, but it of course does nothing special.

    Let’s now add data model and services. Create file service-builder-portlet/src/main/webapp/WEB-INF/service.xml:

    <?xml version="1.0"?>
    <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 5.2.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_5_2_0.dtd">
    <service-builder package-path="com.commsen.liferay.examples.portlet.servicebuilder">
      <namespace>SB</namespace>
      <entity
        name="Player"
        local-service="true"
        remote-service="true">
    
        <!-- PK fields -->
        <column name="playerId" type="long" primary="true" />
    
        <!-- Other fields -->
        <column name="name" type="String" />
        <column name="active" type="boolean" />
        <column name="score" type="int" />
        <column name="birthday" type="Date" />
        <column name="description" type="String" />
    
        <!-- Order -->
        <order by="asc">
          <order-column name="name" />
        </order>
    
        <!-- Finder methods -->
        <finder name="ActivePlayers" return-type="Collection">
          <finder-column name="active" />
        </finder>
      </entity>
    </service-builder>
    
    

    The portlet projects created by liferay-portlet-archetype contain maven profile with lifray-maven-plugin’s build-service goal attached to generate-sources phase. To run ServiceBuilder you need to activate the profile:

    mvn -P build-service package
    

    If you read carefully the messages you will realize that service and persistence classes were generated in service-builder-portlet/src/main/java-service-api/ folder. Also there should be a few implementation files in service-builder-portlet/src/main/java/.

    Now we’ll add custom methods. Open the following file service-builder-portlet/src/main/java/com/commsen/liferay/examples/portlet/servicebuilder/service/impl/PlayerLocalServiceImpl.java and paste this code:

    public void addPlayer(String name, boolean active, int score, Date birthday, String desc) throws PortalException, SystemException {    
      long playerId = CounterLocalServiceUtil.increment();    
      Player player = PlayerUtil.create(playerId);    
      player.setName(name);   
      player.setActive(active);   
      player.setScore(score);   
      player.setBirthday(birthday);   
      player.setDescription(desc);    
      PlayerUtil.update(player, false);  
    }
    public List<Player> getAllPlayers() throws PortalException, SystemException {   
      return PlayerUtil.findAll();  
    }
    

    We added methods to the implementation class. The next time we compile the code we need to activate the build-service profile again in order for Service Builder to react on the change and regenerate the API and interfaces. If you want to try it now simply execute

    mvn -P build-service compile
    

    Now we can start using these services in our portlet. Open service-builder-portlet/src/main/java/com/commsen/liferay/examples/portlet/servicebuilder/JSPPortlet.java and add this method

    @ProcessAction(name = Constants.ADD)  
    public void addPlayer(ActionRequest actionRequest, ActionResponse actionResponse) throws PortletException, IOException {   
      String name = ParamUtil.getString(actionRequest, "name");   
      boolean active = ParamUtil.getBoolean(actionRequest, "active");   
      int score = ParamUtil.getInteger(actionRequest, "score");   
      String description = ParamUtil.getString(actionRequest, "description");   
      int year = ParamUtil.getInteger(actionRequest, "birthday_year");   
      int month = ParamUtil.getInteger(actionRequest, "birthday_month");   
      int day = ParamUtil.getInteger(actionRequest, "birthday_day");    
      Calendar calendar = Calendar.getInstance();   
      calendar.set(Calendar.YEAR, year);   
      calendar.set(Calendar.MONTH, month);   
      calendar.set(Calendar.DAY_OF_MONTH, day);    
      try {    
        PlayerLocalServiceUtil.addPlayer(name, active, score, calendar.getTime(), description);   
      } catch (Exception e) {    
        throw new PortletException("Failed to add player", e);   
      }  
    }
    

    This method handles adding players to database by calling the method we created earlier. To complete the portlet we only need the JSP page which displays the list and render HTML form to add users. The page source code is available here.

    That’s all! We can now create WAR file (mvn package) deploy it and add some players to our database! For more details have a look at portlet’s source code available in examples/service-builder-portlet folder of liferay-maven-sdk.

  • April 26, 2009

    Run GWT application in "hosted mode" from maven

    It seems to get more and more cloudy in the IT world these days . It's a matter of time before the rain (of applications) starts. When this happen one will need the proper tools, to be able to add his/hers own few drops.

    So I though it's about time to start experimenting with Google Web Toolkit. What I like the most about GWT is it's "hosted mode". The fact that Java code changes reflect the GUI right away and one don't have to wait for generate, compile, build, deploy, ... steps to complete is really speeding up the development process.

    Since 99% of my projects use Maven the first thing to look for (after reading GWT tutorials) was a GWT maven plug-in. No surprise here - there is one (http://mojo.codehaus.org/gwt-maven-plugin). The GWT docs and gwt-maven-plugin docs gives a lot of information how to create and build GWT applications.  Unfortunately the released version of  gwt-maven-plugin (1.0 at the time of writing) does not support hosted mode.