Impressed by the VirtualBox

>> Tuesday, October 12, 2010

Both my personal computers are now powered by Ubuntu and it has been the case for the past 8 months or so. I must say I am very satisfied and do not regret one bit my Windoze days. Ubuntu has given my aging laptop a second life and has rescued me from the hell of Windoze Vista on my desktop. Overall, things run smoother and faster on both my computers and I can find pretty much anything I need as free application software with generally very few hassles when comes the time to install or update software.

However, there are times when it seems you cannot easily do without Windows. For example, when I need to prepare my income tax report with a piece of software only available on Windows. Just recently, a client asked me to do some maintenance/changes on an Eclipse RCP application we had developed for him a few years ago. Actually, the (Java) program runs pretty well on Linux but I really need to test it on the client's target O/S. I never had any luck with Wine (Windows emulator) on Linux so I tinkered with the idea of configuring my computer for dual boot as a solution but that really did not appeal to me.

That is when I remembered about virtualization and my earlier experiments with Sun's VirtualBox on a Windoze host about a year ago. I had not pursued my investigation very far at the time but the technology appeared promising. Turns out that on my Ubuntu/Linux machine, VBox is a winner. Maybe the product has matured or maybe Linux is just a better host for this technology but I now have a full fledged WinXP machine in a window on my Ubuntu desktop and it is actually running everything I throw at it without a glitch and without any negative impact on the host O/S. I can easily share files, build my Windows RCP application with Eclipse on Linux and run it under (now Oracle's) VBox.

In a nutshell, if you use Linux but occasionally (or regularly) need to run software on Windows, then virtualization in general and VBox in particular is the way to go.

Regards,

Laurent

Read more...

Riguor and ethics in software engineering

>> Friday, October 1, 2010

My formal training is in engineering and I am still a member of the provincial engineer's order or corporation. As such, it is my duty to practice my trade in a professional and ethical manner. My first obligation is to take into account the public interest, my second obligation is to cater to the security of people working on projects for which I have a responsibility. Finally, I must put the interests of my clients before my own or those of my employer. Furthermore, I must apply sound engineering principles in all my professional activities and must refuse to do (or approve) things that I know are wrong or contrary to generally recognized rules even if my customer or employer asks me to. Although I am legally bound by these principles, my personal conviction is that this is the way things should be handled by people practising and profession be it engineering, medicine, accounting or IT.

Now, my domain of work is software design and construction and I work mostly with IT professionals. What is often a surprise to me is how often these principles are not observed and not even promoted. Many professional are quite willing to design and build flawed systems just because their client (or boss) asked them to do things in such a way. As IT specialists and experts, it is our duty to do things according to sound engineering principles and the onus is on us to devise solutions that meet the business requirements of our customers while still respecting good practices.

Obviously, what must be done and how it should be done is subject to interpretation and different people can have different viewpoints on this. Some could argue that if you are not using a formal methodology such as RUP you are not applying sound engineering principles. I cannot agree with such a position. Methodologies are known to get replaced every 4 or 5 years by some new fad. What is considered to be the proper approach today may very well be considered nonsense tomorrow and that is OK. It is called evolution and creativity. Applying good and consistent practices in a given project is important and required but we do not always need to follow a very strict and formal methodology. Other things such as basic principles behind entity relationship modelling are much less subject to schools of thought or fads. To me, accepting to design and build a solution that does not follow ER modelling principles is just wrong and IT professionals should put their foot down and refuse to go along when colleagues or clients insist on modelling things in a funky way. It does not serve the interests of the client and can lead to real problems down the road that can cause financial if not physical damage to individuals and organizations.

Sometimes you just have to protect customers against themselves. Physicians, accountants and engineers are generally very sensitive to, and familiar with such situations. Unfortunately, many IT professionals do not seem to realize the importance of such issues.

So long,

Laurent

Read more...

Agile documentation with Eclipse, Maven, Hudson and Docbook

>> Tuesday, September 28, 2010

As a Java software designer and developer, I have fantastic tools at my disposal. Things like Eclipse, Maven, Hudson. These tools help me design, write, manage and deliver software artifacts. However, when it comes to producing and managing documentation, we generally go back to the stone-age and use office productivity (sic!) software that simply does not play well with the principles of structuring, formatting and delivering content.

I have always assumed that there existed a better way of producing and managing technical documentation. One that could take advantage of the existing (and robust) software development infrastructure namely source control, IDEs, build management, repository management, etc. Well, I decided to bite the bullet and get organized and I must say I am quite happy with the result. In fact, it was relatively painless to get things working. Essentially, I wanted an open-source solution that could leverage my favorite tools: Eclipse or one of its derivatives, an SCM such as CVS or SVN, Maven and Hudson.

Actually, what got me on the right track is looking at several projects that managed extensive and high quality documentation such as Spring or Maven. Their on-line documents are clearly produced with a Docbook based system. I won't get into a long description of Docbook, there is enough out there for any curious individual, but in a nutshell, Docbook is a mature (its been around for quite some time) and comprehensive XML grammar that can be used to produce technical documentation using XSLT. XSL transformations are freely available to transcode Docbook XML into various HTML and PDF formats. That is exactly what I needed and, as I found out, the solution simply works. What more can I ask?

So here is how I use this technology:

  1. I use the standard Eclipse XML editor (backed by the Docbook DTD) to edit my content. I get all the benefits of schema based editing and validation and in fact, the XML editor tells me what I can put where and if I misplaced or omitted anything (try getting the same from MS Word).
  2. I defined a simple Maven project to hold my document(s) and use the com.agilejava.docbkx:docbook-xml plugin to generate the formatted output I need. Through simple POM configurations I am able to use 3 or 4 Maven commands to do the following: format my document, publish it and generate zipped artifacts containing the source and the transformed (formatted) output.
  3. I can release document versions and deposit them in a repository for safekeeping
  4. Since my Eclipse project is under source control and since I have access to a Hudson continuous integration server, whenever I check-in my source, Hudson triggers a Maven  job that generates and publishes the new version to a filesystem so it is available to my user community through HTTP or otherwise.
For those who want details on how it's done, the POM content for a simple project is included below.

Special thanks  to Vineet Monahar. His article on Docbook and Maven was very helpful.



 <?xml version="1.0" encoding="utf-8"?>  
   
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
     <modelVersion>4.0.0</modelVersion>  
     <groupId>ca.qc.hydro.cej</groupId>  
     <artifactId>cej-guide-developpeur</artifactId>  
     <packaging>pom</packaging>  
     <version>0.0.1-SNAPSHOT</version>  
   
     <!--  
         Usage:   
           
         // Generate docbooks   
         mvn   
           
         // Generate and publish:   
         mvn clean process-resources -Dpublish  
     -->  
   
     <properties>  
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>      
     </properties>  
   
     <build>  
         <defaultGoal>process-resources</defaultGoal>  
         <plugins>  
   
             <plugin>  
                 <groupId>com.agilejava.docbkx</groupId>  
                 <artifactId>docbkx-maven-plugin</artifactId>  
                 <dependencies>  
                     <dependency>  
                         <groupId>org.docbook</groupId>  
                         <artifactId>docbook-xml</artifactId>  
   
                         <version>4.4</version>  
                         <scope>runtime</scope>  
                     </dependency>  
                 </dependencies>  
   
                 <configuration>  
                     <highlightSource>1</highlightSource>  
                     <htmlStylesheet>css/stylesheet.css</htmlStylesheet>  
                 </configuration>  
                 <executions>  
                     <execution>  
                         <id>html</id>  
                         <phase>process-resources</phase>  
                         <goals>  
                             <goal>generate-html</goal>  
                         </goals>  
                         <configuration>  
                             <!-- This copies content (images, etc) for the HTML version -->  
                             <preProcess>  
                                 <copy todir="target/docbkx/html/images">  
                                     <fileset dir="src/docbkx/images" />  
                                 </copy>  
   
                                 <copy todir="target/docbkx/html/css">  
                                     <fileset dir="src/docbkx/css" />  
                                 </copy>  
                             </preProcess>  
                             <!-- Any parameters specific to HTML version go here -->  
                         </configuration>  
                     </execution>  
                     <execution>  
                         <id>eclipse</id>  
   
                         <phase>process-resources</phase>  
                         <goals>  
                             <goal>generate-eclipse</goal>  
                         </goals>  
                         <configuration>  
                             <!-- This copies content (images, etc) for the HTML version -->  
                             <preProcess>  
                                 <copy todir="target/docbkx/eclipse/images">  
                                     <fileset dir="src/docbkx/images" />  
                                 </copy>  
                                 <copy todir="target/docbkx/eclipse/css">  
                                     <fileset dir="src/docbkx/css" />  
                                 </copy>                                  
                             </preProcess>  
                             <!-- Any parameters specific to ECLIPSE version go here -->  
   
                         </configuration>  
                     </execution>  
   
                 </executions>  
             </plugin>  
   
            <plugin>  
             <artifactId>maven-assembly-plugin</artifactId>  
             <configuration>  
              <descriptors>  
               <descriptor>src/assembly/src.xml</descriptor>  
   
               <descriptor>src/assembly/transcoded.xml</descriptor>  
              </descriptors>  
             </configuration>  
            </plugin>      
               
         </plugins>  
   
     </build>  
   
     <profiles>  
         <profile>  
   
             <id>publish</id>  
             <activation>  
                 <property>  
                     <name>publish</name>  
                 </property>  
             </activation>  
             <build>  
                 <defaultGoal>process-resources</defaultGoal>  
   
                 <plugins>  
                     <plugin>  
                         <artifactId>maven-antrun-plugin</artifactId>  
                         <executions>  
                             <execution>  
                                 <phase>process-resources</phase>  
                                 <configuration>  
                                     <tasks>  
                                         <copy todir="\\SOME_NETWORK_FOLDER\eBooks\${project.artifactId}">  
                                             <fileset dir="target/docbkx">  
                                             </fileset>  
                                         </copy>  
                                     </tasks>  
                                 </configuration>  
                                 <goals>  
                                     <goal>run</goal>  
                                 </goals>  
                             </execution>  
                         </executions>  
                     </plugin>  
                 </plugins>  
             </build>  
         </profile>  
     </profiles>  
   
 </project>  

Read more...

Portlet Unit Testing with Liferay 6

>> Tuesday, June 8, 2010

My Test Obsession
I must admit, I am a bit obsessed with automated tests. Whenever I approach the development of a new project with a new system, one of my main concerns is how can we implement and run unit tests? So when I tackled the development of a Liferay portlet I assumed that a unit testing framework or practice was a given, Surely someone (if not the Liferay folks) had mastered and documented this aspect of portlet development. Well, Googling and searching for this revealed that no one seemed to have documented a simple and elegant solution to this need. It is easy to test the base Liferay portlets that can be found in the Liferay SDK and source. However, running Unit tests for a portlet in a separate Eclipse project poses a few challenges as mentioned in the following Liferay forum article: http://www.liferay.com/community/forums/-/message_boards/message/3827878.

The solution proposed in that article did not satisfy me and appeared too complex. There had to be a better and simpler way. After some tinkering and reverse engineering using the Eclipse debugger and changing the log4j settings, I can now run a suite of unit tests for my Liferay service including persistence. The following describes how to achieve this and the general approach. You will probably need to adapt the example to your own situation/portlet but the general approach should be applicable. I am still somewhat green when it comes to Liferay and my understanding of the inner workings of the solution is far from complete so there may be better ways of doing this. Please let me know if you find something missing or incorrect so I can improve this documentation.

The main difficulty with portlet unit testing, from what I observed, is due to the fact that portlets are meant to run inside (or alongside) a portal which provides a number of resources and contexts that are not de facto present when running unit tests. Fortunately, Liferay is based on Spring and the Liferay folks did a good job of making it easy for us to extend or override the context in which code is executed.

In the following example, we have a relatively simple portlet in which Java code was essentially generated with the "build-service" Ant script based on a WEB-INF/service.xml file. What we basically need to do to run the unit tests is create a new source folder for the project that will contain the test resources. This folder contains resources such as Java classes, property and Spring context files that are used exclusively for unit testing and must not be included in the WAR bundle to be deployed in the portal container.

My JUnit test class extends com.liferay.portal.service.persistence.BasePersistenceTestCase and implements the following methods:

public abstract void testCreate() throws Exception;
public abstract void testRemove() throws Exception;
public abstract void testUpdateNew() throws Exception;
public abstract void testUpdateExisting() throws Exception;
public abstract void testFindByPrimaryKeyExisting() throws Exception;
public abstract void testFindByPrimaryKeyMissing() throws Exception;
public abstract void testFetchByPrimaryKeyExisting() throws Exception;
public abstract void testFetchByPrimaryKeyMissing() throws Exception;
public abstract void testDynamicQueryByPrimaryKeyExisting()
      throws Exception;
public abstract void testDynamicQueryByPrimaryKeyMissing() throws Exception;

I am a lazy type so I simply copied an existing subclass of BasePersistenceTestCase and changed the implementation so it refers to my own services.

In the root of the source test folder, put a file called portal-test.properties containing the following (substitute $TOKEN$ to reflect your context):

jdbc.default.driverClassName=$DRIVER_CLASS_NAME$
jdbc.default.url=$DB_URL$
jdbc.default.username=$USER_NAME$
jdbc.default.password=$USER_PASSWORD$

# Disable the scheduler for Unit testing
ehcache.portal.cache.manager.jmx.enabled=false

value.object.listener.com.liferay.portal.model.LayoutSet=

resource.repositories.root=$RESOURCE_REPOSITORIES_ROOT$

# Disable the scheduler for Unit testing
scheduler.enabled=false

hibernate.configs=\
META-INF/mail-hbm.xml,\
META-INF/portal-hbm.xml,\
META-INF/ext-hbm.xml,\
META-INF/portlet-hbm.xml

One of the basic principles in Liferay is that you can override base properties and Spring configs with your own. In the above file, we define properties that override the base ones that come from the portal project.

In the same fashion, I created a "ext-spring.xml" file in the META-INF subfolder of the source test folder that overrides the bean definitions found in the portlet or portal spring contexts. As an example, the content of the "ext-spring.xml" file I use is the following (substitute type names to reflect your service/portlet):

<beans default-destroy-method="destroy" default-init-method="afterPropertiesSet"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
 xsi:schemalocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

 <bean
  class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy"
  id="liferayDataSource">
  <property name="targetDataSource">
   <bean class="com.liferay.portal.dao.jdbc.util.DataSourceFactoryBean">
    <property name="propertyPrefix" value="jdbc.default.">
    </property>
   </bean>
  </property>
 </bean>

 <bean class="com.opnworks.portlet.iamhere.service.impl.MyLocalServiceImpl"
  id="com.opnworks.portlet.service.MyLocalService">
  <bean class="com.opnworks.portlet.service.MyLocalServiceUtil" id="com.opnworks.portlet.service.MyLocalServiceUtil">
   <property name="service"
    ref="com.opnworks.portlet.service.GeoCampaignLocalService">
   </property>
  </bean>
  <bean
   class="com.opnworks.portlet.iamhere.service.persistence.MyEntityPersistenceImpl"
   id="com.opnworks.portlet.service.persistence.MyEntityPersistence"
   parent="basePersistence">

   <bean
    class="com.liferay.portal.spring.transaction.TransactionManagerFactory"
    factory-method="createTransactionManager" id="liferayTransactionManager">
    <constructor-arg ref="liferayDataSource">
     <constructor-arg ref="liferayHibernateSessionFactory">
     </constructor-arg>
    </constructor-arg>
   </bean>
   <bean
    class="com.opnworks.portlet.iamhere.service.persistence.PortletHibernateTestConfiguration"
    id="liferayHibernateSessionFactory">
    <property name="dataSource" ref="liferayDataSource">
    </property>
   </bean>
   <bean class="com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil"
    id="com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil">
    <property name="dynamicQueryFactory">
     <bean
      class="com.liferay.portal.dao.orm.hibernate.DynamicQueryFactoryImpl">
     </bean>
    </property>
   </bean>
   <bean class="com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil"
    id="com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil">
    <property name="restrictionsFactory">
     <bean
      class="com.liferay.portal.dao.orm.hibernate.RestrictionsFactoryImpl">
     </bean>
    </property>
   </bean>
   <bean class="com.liferay.portal.kernel.util.InfrastructureUtil"
    id="com.liferay.portal.kernel.util.InfrastructureUtil">
    <property name="dataSource" ref="liferayDataSource">
     <property name="transactionManager" ref="liferayTransactionManager">
     </property>
    </property>
   </bean>
  </bean>
 </bean>
</beans> 
                                                     

In the above file, the main trick that I pulled is to redefine the bean called liferayHibernateSessionFactory and to specify the following class implementation:

import com.liferay.portal.spring.hibernate.PortletHibernateConfiguration;

public class PortletHibernateTestConfiguration extends
  PortletHibernateConfiguration {
 protected ClassLoader getConfigurationClassLoader() {
  return this.getClass().getClassLoader();
 }
}

This was needed because the PortletHibernateConfiguration implementation throws a NPE on the getConfigurationClassLoader() method invocation due to the fact that we are not running inside a container. I also put the above class definition in my test source folder. If anybody can suggest a more elegant solution, I would be delighted to hear about it.

Another useful trick is to put a copy of portal-log4j.xml in the META-INF subfolder of your test source folder. That way, you can change the logging strategy used for unit testing.

If using Eclipse, you can simply run your unit test classes or suite as a JUnit configuration.

Have fun in the Liferay lane...

Read more...

Developing in the Liferay Lane

>> Monday, February 22, 2010

I have been studying the Liferay portal  system in the past few weeks and I must admit I am quite impressed with this JSR-168 implementation. I will have the chance to discuss this solution some other time but for now, I want to share some tips and tricks to setup an environment to develop Liferay "plugins".

In fact, setting up a development environment to work with Liferay can be quite challenging and time consuming. It is very easy to mess up and things can go wrong in many areas. Furthermore, the instructions are not always clear or complete and there a few tricks one can pull when working with Eclipse and Tomcat that will make things  more fluid. After a lot of suffering and trial and error, here is a recipe to setup a development environment with  Eclipse 3.5.x, MySQL, Liferay 5.2.3 and Apache Tomcat 6.0.x. I just hope I did not forget anything since after the fact, we sometimes miss out or omit a step. Let me know if corrections are needed. My system is running Ubuntu 9.1 but the recipe should be easy to adapt to a Windows box. So here we go.

  • Install (if needed) MySQL (I use MySQL 5.1.37).
  • Create a new MySQL database called "lportal" and test the connection parameters.
  • Install Eclipse 3.5 (Galileo) JEE Edition. You will need JEE edition for some of the tricks below.
  • Download and install Apache Tomcat 6.x somewhere and make sure it is setup properly and working (probably best to have a dedicated Tomcat installation).
  • Create a Tomcat server profile in Eclipse (JEE perspective/Servers view/Add server).
  • Download liferay-portal-src-5.2.3.zip and unzip it in the folder of your choice ( you will end up with a liferay-portal-src-5.2.3 subfolder)
  • Import the contents of liferay-portal-src-5.2.3 as an Eclipse project (it already has the ".project "and ".classpath" files). A "portal" project should appear in your list of Eclipse project.
  • Create a "release.[USERNAME].properties" file in the root of the portal project where [USERNAME] is your Windows or Linux user name.
  • Add the following lines to the release.[USERNAME].properties file. Replace [ECLIPSE_PROJECTS_ROOT] and [ECLIPSE_WORKSPACE_ROOT] with the full paths for your setup The first folder is where you want to put the Liferay "ext" Eclipse project content.

    lp.ext.dir=[ECLIPSE_PROJECTS_ROOT]/liferay-ext
    lp.eclipse.dir=[ECLIPSE_WORKSPACE_ROOT]
    lp.eclipse.project.name=ext
  • Open an ANT view in Eclipse and drag the portal/build.xml file onto the view.
  • Launch (doubleclick) the "clean" task in the ANT view (should be optional the first time).
  • Launch the ANT "start" task followed by the ANT "build-ext" task.
  • Import the "ext" project into Eclipse (use "Import existing project" wizard). You should find it in [ECLIPSE_PROJECTS_ROOT]/liferay-ex.
  • In Eclipse, create a new file:  /ext/ext-impl/src/portal-ext.properties
  • Add the following lines to this file and make sure you set the proper paths and values for all the properties.
auto.deploy.dest.dir=${auto.deploy.tomcat.dest.dir}
auto.deploy.tomcat.conf.dir=[TOMCAT_HOME]/conf/Catalina/localhost

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

#
# Mail
#
mail.session.mail.pop3.host=opnworks.com
mail.session.mail.pop3.password=
mail.session.mail.pop3.port=110
mail.session.mail.pop3.user=lgauthier
mail.session.mail.smtp.auth=false
mail.session.mail.smtp.host=relais.videotron.ca
#mail.session.mail.smtp.password=
mail.session.mail.smtp.port=25

resource.repositories.root=[HOME]/liferay
  • Add the following file to the Eclipse "ext" project root: app.server.[username].properties. Make sure all the properties have the proper values.
app.server.type=tomcat

app.server.tomcat.version=6.0
app.server.tomcat.dir=[TOMCAT_HOME]
app.server.tomcat.bin.dir=${app.server.tomcat.dir}/bin
app.server.tomcat.classes.global.dir=${app.server.tomcat.dir}/lib
app.server.tomcat.classes.portal.dir=${app.server.tomcat.portal.dir}/WEB-INF/classes
app.server.tomcat.deploy.dir=${app.server.tomcat.dir}/webapps
app.server.tomcat.lib.endorsed.dir=${app.server.tomcat.dir}/lib/ext
app.server.tomcat.lib.global.dir=${app.server.tomcat.dir}/lib/ext
app.server.tomcat.lib.portal.dir=${app.server.tomcat.portal.dir}/WEB-INF/lib
app.server.tomcat.lib.support.dir=${app.server.tomcat.dir}/lib/ext
app.server.tomcat.portal.context=ROOT
app.server.tomcat.portal.dir=${app.server.tomcat.deploy.dir}/${app.server.tomcat.portal.context}
app.server.tomcat.log.dir=${app.server.tomcat.dir}/logs
app.server.tomcat.temp.dir=${app.server.tomcat.dir}/temp
app.server.tomcat.work.dir=${app.server.tomcat.dir}/work
app.server.tomcat.zip.name=liferay-portal-tomcat-6.0-${downloads.version}.zip
app.server.tomcat.zip.url=${sourceforge.mirror}/${app.server.tomcat.zip.name}
  • In Eclipse, add the ext/build.xml file to your ANT view and launch the "deploy" task.
  • In Eclipse, configure a Tomcat server that refers to the Tomcat that you are using for Liferay and make sure it is configured to "Use Tomcat Installation". Also, change the timeouts to give enough time for Liferay to start (I specified 120 secs).
  • Start Tomcat from Eclipse. You should be getting a trace of Liferay starting up and if you look at your MySQL database, you should see the tables appear.
  • If everything goes well, the Liferay home page will automagically appear in your browser.
Creating and deploying a plugin

Now the interesting part for your portlet or theme development.
  • Download and install the Liferay portlet SDK (liferay-plugins-sdk-5.2.3.zip)
  • Follow instruction to create a new portlet or theme.
  • For a theme, lets assume we created a new theme called "jazz-theme". Create a new static web project in Eclipse, name it "jazz-theme" and set the project contents to the [liferay_sdk]/themes/jazz-theme folder created with the SDK.
  • Add a file called "jazz-theme.xml" to root of the "mirasol-theme" Eclipse project and set its content as follows (replace [liferay_sdk] with the full path of the sdk):
[context
antijarlocking="true">
antiResourceLocking="true"
path="jazz-theme"
docBase="[liferay_sdk]/themes/jazz-theme/docroot"
/]
  • Add the following task to the "build.xml" ANT file for the jazz-theme project ([resource.repositories.root]/deploy" is the folder used by liferay for hot deployment) :
[target name="redeploy"]
[copy file="[liferay_sdk]/themes/mirasol-theme/mirasol-theme.xml"
todir="[resource.repositories.root]/deploy"/]
  • Using the ANT view, launch the "redeploy" task for the mirasol-theme project. You should see somehting like this in the Tomcat console:
19:40:40,987 INFO [ThemeHotDeployListener:90] Registering themes for mirasol-theme
19:40:41,020 INFO [ThemeHotDeployListener:114] 1 theme for mirasol-theme is available for use
  • From the Liferay web page, you should be able to access the new theme and is you change an image, CSS or other resource, simply launch the "redeploy" task and liferay will pickup the changes without having to copy all the files since the "docbase" attribute points to the Eclipse project folder.
  • The same idea applies to portlet projects.

Have fun and let me know if this works (or does not work) for you.

Notes
A good part of this "How-to" is based on information from this blog.

Read more...

  © Blogger template Webnolia by Ourblogtemplates.com 2009

Back to TOP