Development Environment

Fix Spidermonkey Build issues with Homebrew on Lion

The fix is documented here: https://github.com/mxcl/homebrew/issues/4782

It consists of adding a line in the readline formula file: /usr/local/Library/Formula/readline.rb right before the system command:

    inreplace 'support/shobj-conf', 'darwin[89]*|darwin10*)', 'darwin[89]*|darwin1[01]*)'

MacPorts is out. Say hello to HomeBrew

Today I realized that the MacPorts of both MongDB and CouchDB were (through their dependencies) completely broken. This pushed me to switch to HomeBrew. Which solved the issue. I ended up with a simpler, better structured and more up-to-date package manager to boot.

Uninstall MacPorts and all your ports

 http://guide.macports.org/#installing.macports.uninstalling

PoistGIS on MacOSX Snow Leopard

This is a crude log of the steps I used to get PostGIS 1.4.1 installed on MacOSX Leopard.

Install the database and admin tool

sudo port install postgis
sudo port install pgadmin

Greate a postgis template

Logged in as user ‘postgres’ do:

/opt/local/lib/postgresql84/bin/createdb -E UTF8 template_postgis
/opt/local/lib/postgresql84/bin/createlang -d template_postgis plpgsql

Run init scripts

/opt/local/lib/postgresql84/bin/psql \
-d template_postgis \
-f /opt/local/share/postgresql84/contrib/postgis.sql
 
/opt/local/lib/postgresql84/bin/psql \
-d template_postgis \
-f /opt/local/share/postgresql84/contrib/postgis_comments.sql
 
/opt/local/lib/postgresql84/bin/psql  \
-d template_postgis  \
-f /opt/local/share/postgresql84/contrib/spatial_ref_sys.sql

Set permissions

/opt/local/lib/postgresql84/bin/psql  \
-d template_postgis  \
-c "GRANT ALL ON geometry_columns TO PUBLIC;"
 
/opt/local/lib/postgresql84/bin/psql  \
-d template_postgis  \
-c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"

Now we can create a spatial database from the template

/opt/local/lib/postgresql84/bin/createdb  \
-T template_postgis -U postgres -O postgres locationdb

And finally we start the database

/opt/local/lib/postgresql84/bin/postgres  \
-D /opt/local/var/db/postgresql84/defaultdb

to drop the DB

/opt/local/lib/postgresql84/bin/dropdb locationdb

PoistGIS on MacOSX Leopard

This is a crude log of the steps I used to get PostGIS installed on MacOSX Leopard.

Install the database and admin tool

sudo port install postgis
sudo port install pgadmin

Greate a postgis template

 
/opt/local/lib/postgresql83/bin/createdb -E UTF8 template_postgis
/opt/local/lib/postgresql83/bin/createlang -d template_postgis plpgsql

Run init scripts

/opt/local/lib/postgresql83/bin/psql -d template_postgis -f /opt/local/share/postgis/lwpostgis.sql
/opt/local/lib/postgresql83/bin/psql -d template_postgis -f /opt/local/share/postgis/spatial_ref_sys.sql

Set permissions

/opt/local/lib/postgresql83/bin/psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;"
 
/opt/local/lib/postgresql83/bin/psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"

Now we can create a spatial database from the template

/opt/local/lib/postgresql83/bin/createdb -T template_postgis -U postgres -O locationdb locationdb

And finally we start the database

/opt/local/lib/postgresql83/bin/postgres -D /opt/local/var/db/postgresql83/locationservice

to drop the DB

/opt/local/lib/postgresql83/bin/dropdb locationdb

Running Google Appengine Java apps in Intellij Idea

After having created a standard maven project for the guestbook app as described in this previous post, running the application in Intellij Idea is pretty straight forward.

Create the project

Select File > New Project, and create a new project from External Model, Maven by pointing idea to your pom.xml, just as you would to import any other maven project.

Create a Runner

While we are waiting for someone to write a Intellij Idea server component for Google Appengine Java SDK, we have to create a runner for the server, with the following parameters:

Main Class

com.google.appengine.tools.KickStart

VM Parameters

We have to pass this parameter for Appengine to accept loading the tools jar from a non-standard location.

-Dappengine.sdk.root="/Users/<your user>/.m2/repository/com/google/appengine-tools/1.2.0/"

Program Parameters

com.google.appengine.tools.development.DevAppServerMain  target/guestbook

Working Directory

/Users/<your user>/dev/google-app-engine/guestbook

Environment Variables

 
SDK_LIB=/Users/<your user>/dev/google-app-engine/appengine-java-sdk/lib;
 
SDK_CONFIG=/Users/<your user>/dev/google-app-engine/appengine-java-sdk/config/sdk

Run the App

You should se the following in the runner console tab:

/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java -Dappengine.sdk.root=/Users/torstenek/.m2/repository/com/google/appengine-tools/1.2.0/ -Dfile.encoding=MacRoman -classpath /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/deploy.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/dt.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/javaws.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/jce.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/management-agent.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/plugin.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/sa-jdi.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/../Classes/charsets.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/../Classes/classes.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/../Classes/dt.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/../Classes/jce.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/../Classes/jconsole.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/../Classes/jsse.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/../Classes/laf.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/../Classes/management-agent.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/../Classes/ui.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/ext/apple_provider.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/ext/dnsns.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/ext/localedata.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/ext/sunjce_provider.jar:/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/lib/ext/sunpkcs11.jar:/Users/torstenek/dev/google-app-engine/guestbook/target/classes:/Users/torstenek/dev/google-app-engine/appengine-java-sdk/lib/appengine-tools-api.jar:/Users/torstenek/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar:/Users/torstenek/.m2/repository/com/google/appengine-tools/1.2.0/appengine-tools-1.2.0.jar:/Users/torstenek/.m2/repository/com/google/appengine-local-runtime-shared/1.2.0/appengine-local-runtime-shared-1.2.0.jar:/Users/torstenek/.m2/repository/com/google/appengine-sdk-1.2.0-api/1.2.0/appengine-sdk-1.2.0-api-1.2.0.jar:/Users/torstenek/.m2/repository/taglibs/standard/1.1.2/standard-1.1.2.jar:/Users/torstenek/.m2/repository/javax/servlet/jstl/1.1.2/jstl-1.1.2.jar:/Users/torstenek/.m2/repository/org/apache/geronimo/specs/geronimo-el_1.0_spec/1.0.1/geronimo-el_1.0_spec-1.0.1.jar:/Users/torstenek/.m2/repository/org/apache/geronimo/specs/geronimo-jsp_2.1_spec/1.0.1/geronimo-jsp_2.1_spec-1.0.1.jar:/Users/torstenek/.m2/repository/org/apache/geronimo/specs/geronimo-servlet_2.5_spec/1.2/geronimo-servlet_2.5_spec-1.2.jar:/Users/torstenek/.m2/repository/org/apache/geronimo/specs/geronimo-jpa_3.0_spec/1.1.1/geronimo-jpa_3.0_spec-1.1.1.jar:/Users/torstenek/.m2/repository/org/apache/geronimo/specs/geronimo-jta_1.1_spec/1.1.1/geronimo-jta_1.1_spec-1.1.1.jar:/Users/torstenek/.m2/repository/org/datanucleus/datanucleus-appengine/1.0.0.final/datanucleus-appengine-1.0.0.final.jar:/Users/torstenek/.m2/repository/javax/jdo/jdo2-api/2.3-SNAPSHOT/jdo2-api-2.3-SNAPSHOT.jar:/Users/torstenek/.m2/repository/org/datanucleus/datanucleus-core/1.1.1/datanucleus-core-1.1.1.jar:/Users/torstenek/.m2/repository/javax/transaction/transaction-api/1.1/transaction-api-1.1.jar:/Users/torstenek/.m2/repository/org/datanucleus/datanucleus-jpa/1.1.1/datanucleus-jpa-1.1.1.jar:/Users/torstenek/.m2/repository/javax/persistence/persistence-api/1.0/persistence-api-1.0.jar com.google.appengine.tools.KickStart com.google.appengine.tools.development.DevAppServerMain target/erpilot2
2009-04-11 12:44:09.504 java[38706:10b] [Java CocoaComponent compatibility mode]: Enabled
2009-04-11 12:44:09.505 java[38706:10b] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
The server is running at http://localhost:8080/

Now you can point your browser to:
http://localhost:8080

Maven project for Google Appengine Java SDK

Google Appengine ships with an Eclipse plugin which appears to assume a particular project structure. Since some of us don’t use Eclipse, and all of us use maven, we prefer to use the standard maven structure for the project, which works equally well standalone, and with all major IDEs.

Because the jars distributed Google App Engine appear to different from the same version jars available in the maven repositories, this procedure will require you to add pretty much all Google distributed jars to your local repository which is obviously far from ideal.

Download the SDK

Start by downloading the Google Appengine SDK for Java here: http://code.google.com/appengine/downloads.html, and unzip the distribution package, in our case appengine-java-sdk-1.2.0.zip

Publish the library jars to Maven repository

Next publish the appengine libraries to your maven repository so that we can list them as dependencies in your pom.xml file.

mvn install:install-file -Dfile=lib/appengine-tools-api.jar -DgroupId=com.google -DartifactId=appengine-tools -Dversion=1.2.0 -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/user/appengine-api-1.0-sdk-1.2.0.jar -DgroupId=com.google -DartifactId=appengine-sdk-1.2.0-api -Dversion=1.2.0 -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/shared/appengine-local-runtime-shared.jar -DgroupId=com.google -DartifactId=appengine-local-runtime-shared -Dversion=1.2.0 -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/user/orm/datanucleus-appengine-1.0.0.final.jar -DgroupId=org.datanucleus -DartifactId=datanucleus-appengine -Dversion=1.0.0.final -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/user/orm/datanucleus-appengine-1.0.0.final.jar -DgroupId=org.datanucleus -DartifactId=datanucleus-appengine -Dversion=1.0.0.final -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/user/orm/datanucleus-core-1.1.0.jar -DgroupId=org.datanucleus -DartifactId=datanucleus-core -Dversion=1.1.0 -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -Dfile=lib/user/orm/datanucleus-jpa-1.1.0.jar -DgroupId=org.datanucleus -DartifactId=datanucleus-jpa -Dversion=1.1.0 -DgeneratePom=true -Dpackaging=jar

We are also going to need the jdo-api-2.3-SNAPSHOT artifacts and the transactiona-api-1.1.jar (which can be downloaded from http://download.java.net/maven/1/javax.transaction/jars/ ) as they do not appear to be available in the central maven repository.

mvn install:install-file -Dfile=lib/user/orm/jdo2-api-2.3-SNAPSHOT.jar -DgroupId=javax.jdo -DartifactId=jdo2-api -Dversion=2.3-SNAPSHOT -DgeneratePom=true -Dpackaging=jar
 
mvn install:install-file -DgroupId=javax.transaction -DartifactId=transaction-api           -Dversion=1.1 -Dpackaging=jar -Dfile=/Users/torstenek/Desktop/transaction-api-1.1.jar

The enhancer tools from central has a dependency to a different version of datanucleus-core, so we need to create a local artifact for this one as well.

mvn install:install-file -Dfile=lib/tools/orm/datanucleus-enhancer-1.1.0.jar -DgroupId=org.datanucleus -DartifactId=datanucleus-enhancer -Dversion=1.1.0 -DgeneratePom=true -Dpackaging=jar

This project also uses the maven-datanucleus-plugin (see the POM). We had to hack the pom file to ensure that the datanucleus dependencies match point to the versions we just added manually to the repository.

repository/org/datanucleus/maven-datanucleus-plugin/1.1.0/

Create the Maven project structure and pom.xml

The simplest way to create a maven webapp project is to use the maven archetype plugin. Let’s create a maven version of the guestbook demo included in the SDK.

mvn archetype:create -DgroupId=com.google -DartifactId=guestbook -DarchetypeArtifactId=maven-archetype-webapp

Configure your POM

The finished POM for the guestbook project should look something like this

<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>com.google</groupId>
    <artifactId>guestbook</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>guestbook Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.google</groupId>
            <artifactId>appengine-tools</artifactId>
            <version>1.2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google</groupId>
            <artifactId>appengine-local-runtime-shared</artifactId>
            <version>1.2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google</groupId>
            <artifactId>appengine-sdk-1.2.0-api</artifactId>
            <version>1.2.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <artifactId>standard</artifactId>
            <groupId>taglibs</groupId>
            <version>1.1.2</version>
            <type>jar</type>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <artifactId>jstl</artifactId>
            <groupId>javax.servlet</groupId>
            <version>1.1.2</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-el_1.0_spec</artifactId>
            <version>1.0.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jsp_2.1_spec</artifactId>
            <version>1.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-servlet_2.5_spec</artifactId>
            <version>1.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jpa_3.0_spec</artifactId>
            <version>1.1.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.geronimo.specs</groupId>
            <artifactId>geronimo-jta_1.1_spec</artifactId>
            <version>1.1.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-appengine</artifactId>
            <version>1.0.0.final</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>javax.jdo</groupId>
            <artifactId>jdo2-api</artifactId>
            <version>2.3-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-core</artifactId>
            <version>1.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.datanucleus</groupId>
            <artifactId>datanucleus-jpa</artifactId>
            <version>1.1.0</version>
        </dependency>
    </dependencies>
    <repositories>
        <repository>
            <id>DataNucleus_Repos2</id>
            <name>DataNucleus Repository</name>
            <url>http://www.datanucleus.org/downloads/maven2</url>
        </repository>
    </repositories>
    <build>
        <finalName>guestbook</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.datanucleus</groupId>
                <artifactId>maven-datanucleus-plugin</artifactId>
                <version>1.1.0</version>
                <configuration>
                    <mappingIncludes>**/*.class</mappingIncludes>
                    <verbose>true</verbose>
                    <enhancerName>ASM</enhancerName>
                    <api>JPA</api>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>enhance</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

After you execute %mvn package your deployable app will be in the folder target/guestbook. You should be able to deploy it and run it using the standard instructions for the Appengine Java SDK. I’m moving on to make sure I can run it in Intellij Idea. More on that later.

I’m still waiting for my Java account to activate at Google so I haven’t tried uploading the app yet.

MacFusion – a simple GUI for manaing your MacFUSE file systems.

Tired of typing in your MacFuse file system mount commands? Check out MacFusion – a simple GUI for manaing your MacFUSE file systems.

MacFusion - Simple GUI on MacFUSE

MacFusion - Simple GUI on MacFUSE

Developer site: http://www.macfusionapp.org/

sshfs -oreconnect issue

On MacOSX the sshfs mount might sometimes get stale after sleep or hibernation. Trying to cd or ls the mounted filesystem you simply get:

cd: error retrieving current directory: getcwd: cannot access parent directories: Input/output error

To get out of this you must first umount  the filesystem, using hte absolute path to the mount point:

umount -f /Users/salientpoint/sshfsmount/remote1

The mount-point should now be freed-up and you can then re-mount the filesystem. This note pertains to MacFuse 1.9 development and sshfs 2.2.0.

MacFuse and sshfs – keep connected with your servers

Last week, a SalientPoint colleague asked about FUSE support on the Mac. It turns out that Google appears to have sponsored a MacOSX implementation – MacFUSE. MacFUSE seems to be a great solution to the problem of keeping connected to the myriad of development-, test  and production servers that we work on.

Installing MacFUSE is a snap. Just download the 1.5Mbyte disk image and run the installer app. We decided to go with the MacFUSE 1.9 development version.

Since we use ssh extensively today, the most obvious file system to start with is sshfs. We downloaded the statically linked version from http://code.google.com/p/macfuse/wiki/MACFUSE_FS_SSHFS. After installing it, it was time to create mountpoints. It made sense to create a folder

~/sshfsmount

in which to collect all our sshfs mountpoints. The mount command is straight forward enough:

sshfs myuser@castor:/ /Users/myuser/sshfsmount/castor -oreconnect,volname=castor

And voila:

sshfs volume in the finder