Wednesday, 26 December 2007

I Tried Grails!

I finally tried Grails.  The Groovy based knock off of Ruby on Rails.  I had earlier started reading " JRuby on Rails : Web 2.0 Projects" but just felt that Ruby was too different from Java to get excited about.  I felt like Grails fit in much more seamlessly into the Java ecosystem than JRuby and I didn't feel like I was missing out on the neater features of JRuby.  More importantly, having trusty old Spring and Hibernate right there if I needed them was certainly reassuring. 

 I started out by first by reading "Getting Started With Grails".  After I completed this book I jumped in and wrote a variation of an application I wrote earlier in Tapestry 4 which is a simple application that asks a bunch of categorized yes/no questions and calculates the yes answers in each category and saves them to a database which is retrievable later.  IMHO, I felt doing the project in Tapestry 4 did not have any advantages for a small project like this.  Here's some metrics:

Tapestry 4 Java Code Lines : 575

Grails Code Lines: 255

Grails Code Lines Excluding Auto Generated Configs and tests: 86 (Wow!) 

Things you don't need to deal with in a basic Grails app that you do with Tapestry 4 :Ant build file, Hibernate Config, Tapestry Application Descriptor, Component Specification (jwc), any additional libs except for the database jar.

 I have to level some criticisms at Grails though.  First, it tends to give some strange error messages when the environment isn't configured just right or you do something wrong.  Also, I had some trouble figuring out where to put stuff if I wanted it to be on the classpath.   Lastly the IDE integration is weaker than pure Java so autocomplete was mostly a manual process not assisted by the IDE.  Being able to quickly re-load and see changes compensates for this.

One more note.  As a Java developer I am a little prejudiced against loosely typed languages but Grails alleviates my fears by allowing me to easily interface with regular Java components  via Spring.

 All in All, I think Grails is the next big thing in Java development.  I have completed major projects professionally in Tapestry, Struts, and JSF and I feel like Grails just blows them all out of the water right now, especially for smaller projects.  I am going to try to use Grails on a much larger project to see how it works in that context.  The backend of my larger project is all in Java/Spring and uses some pretty tricky Hibernate stuff but I think that Grails will be great as a quick and agile web tier framework.

Technorati Tags:

Posted by justin at 1:23 AM in Java Programming

Sunday, 23 September 2007

Adding Selenium Support To Appfuse



Selenium is a very nice browser control/automated testing system.  I wanted to integrate it into my Appfuse project so I could use it to do functional testing in lieu of Canoo, which i feel is less capable.  Selenium RC (remote Control) is particularly useful because it lets one automate web testing from inside of Java and hence inside of Junit.  Here's how I did it.


Step 1 - Download Selenium


Go to http://www.openqa.org/selenium-rc/download.action

and download the selenium 0.9.2 release

Unpacked the file in

lib/

underneath your Appfuse root directory. 

Now the files are in

lib/selenium-remote-control-0.9.2

 

 


Step 2 - Setup Library and Paths

edit /lib/lib.properties and add the follwoing:

#
# Selenium RC - http://www.openqa.org/
# selenium.version=0.9.2
selenium.dir=${lib.dir}/selenium-remote-control-${selenium.version}/
selenium-client.jar=${selenium.dir}/selenium-java-client-driver-${selenium.version}/selenium-java-client-driver.jar
selenium-server.jar=${selenium.dir}/selenium-server-${selenium.version}/selenium-server.jar

 In properties.xml setup the selenium build and test environment

     <!-- Selenium Compile Classpath -->
    <path id="selenium.compile.classpath">
        <path refid="web.compile.classpath"/>
        <pathelement location="${selenium-client.jar}"/>        
        <pathelement location="${selenium-server.jar}"/>
    </path>
    <path id="selenium.test.classpath">
        <path refid="web.test.classpath"/>
        <pathelement location="${selenium-client.jar}"/>        
        <pathelement location="${selenium-server.jar}"/>  

 </path>

 
Step 3 - Setup Source Directories and add a Test

Make two source directories

 test/selenium

and

 src/selenium

Put your tests in test/selenium

 

An example Selenium test:


package appfuse.selenium;

import org.openqa.selenium.server.SeleniumServer;

import junit.framework.TestCase;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;

public class SeleniumTest extends TestCase {
        private Selenium selenium;

        public void setUp() throws Exception {
            
            String url = "http://localhost:8080/appfuse";
            selenium = new DefaultSelenium("localhost", SeleniumServer.getDefaultPort(), "*firefox", url);
            selenium.start();
        }

        protected void tearDown() throws Exception {
            selenium.stop();
        }

        public void testLocal() throws Throwable {
            selenium.open("http://localhost:8080/appfuse"/images/emoticons/mozilla_wink.gif;
            selenium.waitForPageToLoad("30000"/images/emoticons/mozilla_wink.gif;
            assertTrue(selenium.getTitle().equals("Login | AppFuse"/images/emoticons/mozilla_wink.gif);
        }

}


 

 
Step 5 - Setup proper build targets

In build.xml add the following tasks to support running selenium tests: 

<!-- Start Selenium Test Server -->

     <target name="start-selenium-server" depends="init">
        <java fork="true" spawn="true" classname="org.openqa.selenium.server.SeleniumServer">
            <classpath refid="web.compile.classpath"/>
        </java>
    </target>

<!-- Compile Selenium Modules --> 

    <target name="compile-selenium" depends="package-service,stage-web" description="Compile web module">
        <compile module="selenium"/>
    </target>
 

<!-- Use cargo to startup app server and run selenium tests against them --> 

    <target name="test-selenium" if="tomcat.home" depends="war,check-debug,start-selenium-server,compile-selenium"
        description="Runs Canoo WebTests using Cargo">
        
        <taskdef resource="cargo.tasks">
            <classpath>
                <fileset dir="${cargo.dir}" includes="*.jar"/>
            </classpath>
        </taskdef>

        <echo>running canoo tests at:
              http://${tomcat.server}:${http.port}/${webapp.name}</echo>

        <if>
            <isset property="tomcat5"/>
            <then><property name="cargoId" value="tomcat5x"/></then>
            <else><property name="cargoId" value="tomcat4x"/></else>
        </if>
       
        <echo message="Starting ${cargoId}..."/>
        <cargo containerId="${cargoId}" id="${cargoId}" home="${tomcat.home}" action="start"
            output="${test.dir}/cargo.log" wait="false">
            <configuration home="${test.dir}/${cargoId}">
                <property name="cargo.logging" value="high"/>
                <property name="cargo.servlet.port" value="${http.port}"/>
                <!--<property name="cargo.jvmargs" value="${run.brainReboot.test.debugargline}"/>-->
                <deployable type="war" file="${webapp.dist}/${webapp.war}"/>
            </configuration>  
        </cargo>

        <test-module module="selenium"/>

        <cargo refid="${cargoId}" action="stop"/>
    </target>

Step 6 - Run Tests

Now run

ant test-selenium ;

 

and you will see tomcat startup and the selenium Firefox instance pop open and try and complete any tests you've setup.

Technorati Tags:

Posted by justin at 9:02 PM in Java Programming

Monday, 14 May 2007

Swing/NetBeans development impressions

 

I've never been a big desktop app developer.  I had heard from a number of people at JavaOne that Swing had become much easier to work with lately.  I had a friend who wanted me to port a simple C# desktop app to Java so I immediately jumped in to get a feel for desktop app programming again.

 

I had heard from a number of people that the Netbeans Matisse swing builder was a really good tool. I was not disappointed at all. I was able to whip up a quick copy of the application UI I was porting in Matisse and get it functioning and doing things rather quickly.

NetBeans as an IDE could use a bit of work though. Some things I found that weren't so great:

  • Quick fix support is much more primitive than in Eclipse.
  • The recompilation and error hilighting is not as fast as Eclipse.
  • Sometimes auto-complete would fail mysteriously.
  • The debugger doesn't let you change your code while your program is running.
On the other hand there were some things I liked about NetBeans:
  • Matisse is a great tool for making Swing apps.
  • I didn't have to download any plug-ins to get started.
  • The XML editor is pretty decent.
  • The build system is built in and a no brainer. You don't have to hack your own.
  • Performance and stability were better in NetBeans.
  • No need for perspective switching.
Overall it seems that Eclipse is a little Frankensteinish at times with so many plug-ins all trying to work together.  On the other hand, the base Eclipse Java Development Platform is exceptional.  I'm going to have to stick with Eclipse for now.  
Posted by justin at 10:39 PM in Java Programming

Saturday, 12 May 2007

Blojsom + Jetty + Postgres

Blojsom is a great java based blogging webapp that I got up and running today. 

Here's my guide as to how to set it up:

Setting up Blojsom 3.2 on Postgres/Jetty

  • Download Blojsom Quickstar Bundle

    http://sourceforge.net/project/showfiles.php?group_id=72754&package_id=125988

  • Download Jetty 6

    http://dist.codehaus.org/jetty/jetty-6.1.3.zip

  • If Postgresql has not been installed you can get it from:

    http://www.postgresql.org/

    if you are on Debian or Ubuntu simply run

    apt-get install postgresql
Now on to the install
  • from your home directory - assuming your site is called xclu.com:
    mkdir xclu.com 

    unzip jetty-6.1.3.zip

    declare -x JETTY_HOME=~/xclu.com/jetty-6.1.3/

    cd $JETTY_HOME

    Get the appropriate Postgresql driver from

    http://jdbc.postgresql.org/download.html

    to get your version

    psql --version

    copy it to $JETTY_HOME/lib/ext/

    cd webapps

    mkdir blojsom

    cd blojsom

    jar -xvf ~/xclu.com/blojsom.war

    edit $JETTY_HOME/webapps/blojsom/WEB-INF/classes/blojsom-helper-beans-include.xml

    Replace the datasource with an appropriate postgresql configuration. You probably want to use a better password than 'blojsom'.:



    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="org.postgresql.Driver"/>
    <property name="url" value="jdbc:postgresql://localhost/blojsom"/>
    <property name="username" value="blojsom"/>
    <property name="password" value="blojsom"/>
    </bean>

    Modify the dialect

    <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>

    Edit $JETTY_HOME/webapps/blojsom/WEB-INF/classes/blojsom.xml

    Modify the dbloader


    <bean id="dbloader" class="org.blojsom.util.database.DatabaseLoader" init-method="init">
    <property name="sessionFactory">
    <ref bean="hibernateSessionFactory"/>
    </property>
    <property name="dbScript" value="/WEB-INF/classes/blojsom-full-initial-data-postgresql.sql"/>
    <property name="upgrading" value="false"/>
    <property name="servletConfig">
    <ref bean="servletConfigFactoryBean"/>
    </property>
    <property name="detectBlojsomSQL">
    <value>select relname from pg_stat_user_tables where relname = 'blog';</value>
    </property>
    </bean>

    Create the blojsom database (may need to be done as postgres user account if you haven't created a postgres superuser account for yourself)

    createuser blojsom

    Answer no to whether the user should be allowed to create databases or other users

    createdb -O blojsom blojsom

    psql blojsom
    blojsom=# alter user blojsom with password 'blojsom';
    blojsom=# \q

    To allow local acess to your database edit pg_hba.conf and add the following line right underneath the IPv4 comment.

    # All IPv4 connections from localhost
    host blojsom blojsom 127.0.0.1 255.255.255.255 md5

    Restart postgresql

    Test the configuration

    psql -h 127.0.0.1 -U blojsom -W blojsom

    login with password "blojsom"

    You should get the follow prompt

    blojsom=>

    exit the psql client

    blojsom=> \q

    Set the hostname and port in $JETTY_HOME/etc/jetty.xml properly

        <Call name="addConnector">
    <Arg>
    <New class="org.mortbay.jetty.nio.SelectChannelConnector">
    <Set name="port"><SystemProperty name="jetty.port" default="8080"/></Set>
    <Set name="maxIdleTime">30000</Set>
    <Set name="host">www.xclu.com</Set>
    <Set name="Acceptors">1</Set>
    <Set name="statsOn">false</Set>
    <Set name="confidentialPort">8443</Set>
    <Set name="lowResourcesConnections">1000</Set>
    <Set name="lowResourcesMaxIdleTime">500</Set>
    </New>
    </Arg>
    </Call>

    Replace localhost:8080 with whatever your actual hostname is. In this case my hostname is 'www.xclu.com'

    Change the jetty sql scripts so they initialize the database with the right hostname

    perl -pi -e 's/localhost:8080/www.xclu.com/g' $JETTY_HOME/webapps/blojsom/WEB-INF/classes/*.sql

    Run Jetty!

    cd $JETTY_HOME
    ./bin/jetty.sh start

    Now go to

    • You may now access your blog at http://your-blojsom-install-site/blojsom/blog/default/
    • You may access the administration console at http://your-blojsom-install-site/blojsom/blog/default/?flavor=admin
    • The default user and password is default/default. Be sure to change the password immediately after logging in. You can change this under Weblog Settings | Users.

Technorati Tags:

Posted by justin at 11:51 PM in Java Programming
« July »
SunMonTueWedThuFriSat
  12345
6789101112
13141516171819
20212223242526
2728293031