Thursday, February 24, 2005

It's the simple things

A phenomena that I've seen occur when trying to find information on the internet, especially regarding Open Source technologies, is that it's very hard to find a concise set of instructions to bootstrap yourself when learning. Simple things you need to know in order to get started are assumed, omitted, or forgotten.

So, today, I've been working on picking Java up where I left off 2 years ago. Back then, I'd taken a class or two, and learned enough to realize what I was talking about. I didn't understand what I was doing entirely, but I accomplished what I needed to in order to get the grade. Today I'm working on understanding.

Specifically, I wanted to work on using Ant to build a java app that I could use for a custom JSP Tag. I decided that I'd first try to compile a program with multiple classes within a package. Now, stop.

This task should be simple enough. In fact it is simple if you know what you're doing. I didn't.

Problem 1. I kept getting compile errors because I didn't have the package defined correctly. How do you use packages when building a java app? The solution was to do the following:

  1. Put the main class' java file in a directory.
  2. Make a directory with the name of the package the main class uses and put it in the same directory as the main class java file.
  3. At the top of the main class file write:
    import packageName.*;
  4. In each of the .java files for the package you're using, write this at the top of the page:
    package packageName;
    import packageName.*;

  5. Put all of the java files for the package in the directory with the package name
  6. Then you can compile the thing with a command prompt and javac:
    prompt$ javac MainClass.java
  7. If it doesn't work, don't blame me ;-)
OK, that worked. But I wanted to use Ant. Fortunately, ant is extremely easy to use. Just read the docs and get it installed correctly.

Problem 2. How do I set up ant to work for my application?

Fortunately the docs are reasonably good for this app. I had good luck simply customizing the existing example build file. When you have that set up, just make sure to customize the project names and directories you want, and put it in a directory with the same directory tha tholds all of your source code (I used a dir called 'src', as the build file uses). This XML build file must be named 'build.xml'. Then, you can take a prompt, cd to that directory where the build.xml file is, and type 'ant' at the prompt. It will do the building for you. Cool!

Problem 3. How do I get the jar file that ant builds to run as an executable?

Even though this doesn't really have to work in order to build a tag for JSP, I wanted to do it anyway, to see if I could do it. Ant is cool because it automates lots of commands that you'd use when building an app, including the generation of a .jar file. Handy! The only thing is, the jar file that it generates doesn't become executable by default. The solution involves the following:

  1. Set up the MANIFEST.MF file in the META-INF dir of the jar so that it knows which class is the main one to call when executing. This means putting a 'Main-Class:' declaration in that file.
  2. Customizing the build.xml file that ant uses
After noodling around, I adjusted the manifest just fine. and that worked. Then I wanted to use ant to make the MANIFEST.MF file for me. To do that put in a couple lines as a child node to the tag:

<target name="dist" depends="compile"
description="generate the distribution" >
<!-- Create the distribution directory -->
<mkdir dir="${dist}/lib"/>



<!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file -->
<jar jarfile="${dist}/lib/FactoryPattern.jar" basedir="${build}">
<!-- set up the MANIFEST -->
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-Class" value="${app}"/>
</manifest>
</jar>
</target>

Here's some handy tips:
  • For what it's worth, a jar file is just a zip file with a different extension
  • jar works much like tar. To create a jar file type:
    jar cf [input directory and input files] [output file].jar
  • If you want to add a mainfest file, you can do the following:
    jar cmf [input directory and input files] [path/to/MANIFEST.MF] [output file].jar
  • To extract a jar file:
    jar xvf [jarfile].jar
  • To run an executable jar file from the command line:
    java -jar [jarfile].jar
I know these are simple things, and I realize that this is the same kind of non-comprehensive set of information that I was complaining about, but, hopefully this will be helpful enough to get'cha started.

[UPDATE]
I had trouble getting the classpath set up correctly at first, but ant handles it quite elegantly. Basically, you set up a path variable in the build.xml file, and then refer to it in the tag when building.


<path id="base.path">
<fileset dir="${tomcat.home}/common/lib/">
<include name="**/*.jar">
</fileset>
</path>

<!-- THEN THE COMPILE TARGET, AND JAVAC, LOOK LIKE THIS -->
<target name="compile" depends="init" description="compile the source " >
<javac srcdir="${src}" destdir="${build}" >
<classpath refid="base.path"/>
</javac>
</target>
The benefit of keeping the classpath info in the build.xml file is that it doen't need to be set in the shell when you're dealing with custom classes and third party stuff

Wednesday, February 02, 2005

How to Create a Singleton in PHP

Using singletons in PHP can have great benefits for an application. A singleton allows a single reference to be maintained during execution of the application. So for example, you could create a singleton that would hold a reference to a database connection. That way, when making multiple database calls, with the chance for easily making multiple connections to the database, you don't have to worry. Only one connection to a database would be created when using a singleton. In addition, it helps when trying to access an Object from multiple places when the data within that object needs to be persistent.

I've read a number of different threads and articles on creating a singleton pattern in PHP. None of them seemed very satisfactory to me. In the classic sense a Singleton should store a static reference of it's own instance. Since PHP only supports static variables within functions, doing this is a little wierd. So, I set out to create a simple pattern for creating singletons in PHP

The goals were as follows:

  1. Make the singleton in such a way that it can be called statically, such as
    $instance = Singleton::getInstance();
  2. Make the singleton a class, not just a function
  3. Make the singleton retrievable from within other arbitrary classes
  4. The Class should store and retrieve an instance of itself


The following code accomplishes these goals:


//THIS IS FOR PHP4
class Singleton
{
function &getInstance() {
static $obj;
if (!isset($obj)) {
// Assign a reference to the static variable
$v = &new Singleton;
$obj = $v;
}
return $obj;
}
}



The singleton requires only a method to retrieve it's instance. No constructor is required. Since the 'normal' way to make a singleton is by using a private constructor, and then an accessor to retrieve an instance of itself, stored statically, we can't make a traditional singleton. The static variable would need to be a member variable.

Instead, we have to use the means of static variables in PHP. Static variables have many idiosyncracies. Of particular note, they can only exist within functions, and they cannot store references (in PHP4). Therefore, we have to play a little bit of a trick to make this work.

First, the static variable to hold the instance needs to reside in the getInstance function. Kind of wierd, but it's the right way to do it.

Second, since static variables cannot hold variables passed by reference, the instance of the singleton class cannot be set on the static variable. To get around this, create an intermediate variable to set the reference to, then set the value of that intermediate variable to the static var. By looking at it, it seems that the reference would be lost, but that's not the case. It sticks. Try it!

Finally, PHP5 seems to solve lots of the above problems and work arounds. The most significant change is that references can be held by static variables. That means that there's no intermediate variable trick that needs to happen. In addition, there are private, protected, and public declarations for functions and variables. So a more true Singleton can be achieved in that regard as well.

A PHP5 singleton would look something like this:



class Singleton
{
function &getInstance() {
static $obj;
if (!isset($obj)) {
$obj =&new Singleton;
}
return $obj;
}
}

How simple can it get?