Woshiadai Dev Notebook

June 26, 2009

Subversion and SSH setup in Netbeans 6.7 RC3 on Mac OS X

Filed under: Java, PHP, Apple, Mac

Netbeans has been making a lot of progress since version 6 and the latest 6.7 RC3 is even better. For those Eclipse fans, I strongly suggest that you check out Netbeans. It feels much faster and consumes less memory. The plugins are more organized and easy to manage (I think the plugin management in Eclipse is really messy).

The PHP plugin for Netbeans is out of beta and it is quite user friendly and versatile. So, I decided to switch from PDT to Netbeans for my PHP development.

Netbeans comes with Subversion support. However, it is not so smooth to set up Subversion over SSH on Mac OS X due to the ssh-askpass problem. This is a Mac OS X issue, not a Netbeans issue.

  1. Download and install Netbeans 6.7 RC3 (as of June 25, 2009).
  2. The subversion that comes with Mac OS X (/usr/bin/svn, 1.4.4 (r25188)) is quite outdated and it has problems working with newer versions of the SVN server, probably due to different format of the metadata. You need to use MacPorts to install a more recent subversion (if you don’t know how to install MacPorts, check out this). Just type this in your terminal: port install subversion, it might take a white. The subversion from MacPorts is installed in /opt/local/bin, so make sure you put /opt/local/bin before /usr/bin in your PATH environment variable.
  3. Add SVNROOT and SVN_SSH environment variables to your .bashrc:

    export SVNROOT=svn+ssh://your_svn_server/
    export export SVN_SSH=/usr/bin/ssh
  4. Launch Netbeans, go to preferences->Miscellaneous->Versioning->Subversion, for “path to SVN executable file”, enter /opt/local/bin
  5. Now, it seems like everything is ready. However, when you try to do update/diff and other operations, you get error: ssh_askpass: exec(/usr/libexec/ssh-askpass): No such file or directory. I did some Yahoo! search and the problem is that Netbeans wants to communicate with SVN server over ssh without asking your password using ssh-askpass, but it is not available. This is a general ssh issue on Mac OS X.

    I found two solutions: solution 1 and solution 2. I only tried solution 2 and it worked perfectly for me. Here are the simple steps:

    a) download script from here (note that I had to add .jpg since blogsome only supports image upload) and save it in /usr/libexec. Change ssh-askpass script to executable:
    wget wget http://woshiadai.blogsome.com/images/sshaskpass.jpg -O ssh-askpass
    sudo cp ssh-askpass /usr/libexec/ssh-askpass
    sudo chmod a+x /usr/libexec/ssh-askpass

    b) add two more environment variables:

    export SSH_ASKPASS=macos-askpass
    export DISPLAY=:0

  6. Finally, you can use subversion actions from inside Netbeans. You will be asked for password for the first time, then it will be remembered for future activities.

    Enjoy the Netbeans! ;-)

May 5, 2008

instanceof OR getClass()

Filed under: Java, Linux

First, wanna share a nice vim/gvim theme called Wombat. Just download it and put it into $HOME/.vim/colors and setcolors wombat in your $HOME/.vimrc and .gvimrc.

I have seen several interview questions asking you to override equals() method for your class. There are two ways to check the classname. Take a Foo class for example:

public class Foo{
private int id;
public boolean equals(Object o){
if (this == o)
return true;
if (!(o instanceof Foo))
return false;
if (o == null)
return false;
Foo other = (Foo)o;
return (this.id == other.id) ? true : false;
}

Another way:

public class Foo{
private int id;
public boolean equals(Object o){
if (this == o)
return true;
if (getClass() != o.getClass())
return false;
if (o == null)
return false;
Foo other = (Foo)o;
return (this.id == other.id) ? true : false;
}

Basically, it is a question of using instanceof or getClass(). Josh Bloch in his Effective Java and his interview with Altima argues that instanceof should be used because of Liskov substitution principle, meaning that one subclass object should be able to replace occurrences of its superclass object without making changes for correctness.

Cay Horstmann does not agree with the use of instanceof and argues that getClass() method should be used instead to enforce the contract of equals method. He presents a superclass-subclass example where reflexive contract for equals method is broken: parent.equals(child) is true, but child.equals(parent) is false if we stick to the instanceof approach.

I think with some special conditional checks on the inheritance structure, you can still use instanceof and satisfy reflexive contract. But getClass() is much simpler.

So, basically, the question is like this: if Eric is a manager, he is represented as an object e of Employee class and an object m of Manager class which extends Employee class. Do you think e equals m (because they are actually representing a same person, using instanceof approach) or do you think they are not equals (because they are of different classes, using getClass() approach)?

May 31, 2007

Some Hibernate Lessons

Filed under: Java

I have started using Hibernate in my project and it turns out to be more difficult for a beginner than I thought, especially when the domain model is a bit complicated. But I guess it is worthwhile to do the learning and fix the problems along the way because it will be even more problematic if I choose to brew a layer like that by myself.

So, here are some of the lessons I learned.

1) Inheritance: I chose the 3rd strategy, subclass per table because it is the most beautiful solution to my problem. The lesson I learned is that I don’t need to add an extra ID to the subclass since it will use the parent class’s ID anyways. But for the database table schema, you should have an ID for the subclass table.

2) One-to-many mapping: it is a bit similar to 1) except that now it is a foreign key reference that you don’t need to put into the many-to-one end POJO definition. For example, we have a parent p and a child c, p contains a set of c and c contains a single p, so this is a bi-directional one-to-many mapping. In the table_c, there should be a column like p_id that references id column in table_p. But you don’t need to have a property called p_id in the c mapping file. Otherwise, you will see duplicated mapping error. You don’t need to have an attribute p_id with getter and setter defined in c POJO either. Otherwise, you will see a null value returned from c.getPId() method.

Here are two links for examples:

1-to-many

subclass per table

May 29, 2005

Using Jakarta Commons CLI

Filed under: Java

Several examples from Jakarta Commons Cookbook by Timothy M. O’Brien, O’Reilly, Nov 2004

Example 1: Parsing a Simple Command Line

import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.CommandLine;

public static void main(String[] args) throws Exception {

    // Create a Parser
    CommandLineParser parser = new BasicParser( );
    Options options = new Options( );
    options.addOption(”h”, “help”, false, “Print this usage information”);
    options.addOption(”v”, “verbose”, false, “Print out VERBOSE information” );
    options.addOption(”f”, “file”, true, “File to save program output to”);

    // Parse the program arguments
    CommandLine commandLine = parser.parse( options, args );

    // Set the appropriate variables based on supplied options
    boolean verbose = false;
    String file = “”;

    if( commandLine.hasOption(’h') ) {
        System.out.println( “Help Message”)
        System.exit(0);
    }

    if( commandLine.hasOption(’v') ) {
        verbose = true;
    }

    if( commandLine.hasOption(’f') ) {
        file = commandLine.getOptionValue(’f');
    }
}

Example 2: Using OptionGroup

import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.CommandLine;

public static void main(String[] args) throws Exception {

    // Create a Parser
    CommandLineParser parser = new BasicParser( );
    Options options = new Options( );
    options.addOption(”h”, “help”, false, “Print this usage information”);
    options.addOption(”v”, “verbose”, false, “Print out VERBOSE information” );

    OptionGroup optionGroup = new OptionGroup( );
    optionGroup.addOption( OptionBuilder.hasArg(true).create(’f') );
    optionGroup.addOption( OptionBuilder.hasArg(true).create(’m') );
    options.addOptionGroup( optionGroup );

    // Parse the program arguments
    CommandLine commandLine = parser.parse( options, args );

    // … do important stuff …
}

Example 3: Print Usage Info

import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;

public class SomeApp {
    private static final String USAGE = “[-h] [-v] [-f <file> | -m <email>]”;
    private static final String HEADER =
        “SomeApp - A fancy and expensive program, Copyright 2010 Blah.”;
    private static final String FOOTER =
        “For more instructions, see our website at: http://www.blah123.org”;

    public static void main(String[] args) throws Exception {

        // Create a Parser
        CommandLineParser parser = new BasicParser( );
        Options options = new Options( );
        options.addOption(”h”, “help”, false, “Print this usage
                                                                      information”);
        options.addOption(”v”, “verbose”, false, “Print out VERBOSE
                                                                         information” );

        OptionGroup optionGroup = new OptionGroup( );
        optionGroup.addOption( OptionBuilder.hasArg(true).withArgName(”file”)
                                            .withLongOpt(”file”).create(’f') );
        optionGroup.addOption( OptionBuilder.hasArg(true).withArgName(”email”)
                                            .withLongOpt(”email”).create(’m') );
        options.addOptionGroup( optionGroup );
           // Parse the program arguments
        try {
            CommandLine commandLine = parser.parse( options, args );

            if( commandLine.hasOption(’h') ) {
                printUsage( options );
                System.exit(0);
            }
   
               // … do important stuff …
        } catch( Exception e ) {
            System.out.println( “You provided bad program arguments!” );
            printUsage( options );
            System.exit(1);
        }
    }

    private static void printUsage(Options options) {
        HelpFormatter helpFormatter = new HelpFormatter( );
        helpFormatter.setWidth( 80 );
        helpFormatter.printHelp( USAGE, HEADER, options, FOOTER );
    }
}






















Get free blog up and running in minutes with Blogsome
Theme designed by Ben de Groot