Archive for October, 2009

Jackrabbit on the Run

Friday, October 30th, 2009

This post is a brief guide on how to get Apache Jackrabbit and to write an Eclipse plugin that works with it.

Jackrabbit is an open source implementation of the Java Content Repository defined in JSR 170. Current stable version is 1.6.0 and they have alpha builds of 2.0 version that should implement JSR 283, the next revision of the JCR.

Running Jackrabbit is easy: download jar with standalone server jackrabbit-standalone-1.6.0.jar and launch it:

dimzzy@hornet:~ $java -jar jackrabbit-standalone-1.6.0.jar
Welcome to Apache Jackrabbit!
-------------------------------
Using repository directory jackrabbit
Writing log messages to jackrabbit/log
Starting the server...
Apache Jackrabbit is now running at http://localhost:8080/

After this Jackrabbit will create a JCR repository with default workspace and you may connect to it from a web browser at http://localhost:8080/.

The next step is to put in some data. You may do it right within the browser by following the Populate link and harvesting internet for data or by mounting WebDAV directory http://localhost:8080/repository/default/ and copying some files and folders there. Default administrator account is admin/admin.

Accessing Repository

Now launch Eclipse and create a new plugin project. Our client will be a simple repository browser that shows a tree of nodes so add a view part with a TreeViewer. To use JCR API we will also need a jar (jcr-1.0.jar) with all the classes and interfaces which you can download here: JSR 170 downloads.

In order to connect to the running Jackrabbit you will need three more jars:

  • jackrabbit-api-1.6.0.jar
  • jackrabbit-jcr-commons-1.6.0.jar
  • jackrabbit-jcr-rmi-1.5.0.jar

The tricky part is that I was unable to download them directly so I had to download jackrabbit-webapp-1.6.0.war and extract those jars from there.

Here is code that creates the viewer:

public class RabbitViewPart extends ViewPart {

  private TreeViewer viewer;
  private Session session;

  @Override
  public void createPartControl(Composite parent) {
    viewer = new TreeViewer(parent);
    viewer.setContentProvider(new JCRContentProvider());
    viewer.setLabelProvider(new JCRLabelProvider());

    try {
      Repository repository
        = new URLRemoteRepository("http://localhost:8080/rmi");
      session = repository.login(null, null);
      viewer.setInput(session.getRootNode());
    } catch (Exception e) {
      Activator.error(e);
    }
  }

  @Override
  public void dispose() {
    session.logout();
    super.dispose();
  }

  @Override
  public void setFocus() {
    viewer.getControl().setFocus();
  }
}

The code is pretty straightforward: when view part is created we connect to the Jackrabbit instance using URLRemoteRepository and open a session. First null means that we want the default workspace and the second null means that we login anonymously. Running browser looks like this:



You can download complete source code here.

Classes for JavaScript

Thursday, October 29th, 2009

Classic OOP relies on classes that are essentially object blueprints. You define a class by naming it and adding attributes and methods. Objects are created by new operator that allocates memory and initializes it accordingly to the class design. The ultimate purpose of this setup is to create objects that can do appropriate things.

Each object encapsulates data in its attributes, typically hiding them from other objects. Methods defined in class are bound to objects and are used to give access to object data, for reading or writing. This turns object into an abstraction with a particular interface; you think of objects as of entities that can do certain things and don't care how they do it. This is the reason why OOP is so popular: it is a natural implementation of the 'divide and conquer' principle; instead of shuffling primitive numbers and strings you wire more complex entities to communicate and solve your computing problems.

In JavaScript we have objects but no classes. Actually there are some classes, but they are fixed and you can't define your own class. Every custom object you create is a simple dictionary: a bag of name-value pairs that may store numbers, strings, functions and other objects.

Objects are created by the new operator and initially have no properties or methods (except 'system' stuff like the toString() function). You are supposed to initialize objects later, possibly by providing a dedicated function to do it. And you may write this function in a way that will complement the new operator and make objects look as if they were created from the same blueprint. This means that in JavaScript we may substitute class by a constructor function.

Since every function invocation in JavaScript creates a closure we may use it to store object's hidden attributes. This means that objects in JavaScript are split in two parts: the object itself that exposes the behavior and closure with private stuff.

Below is a Java class and JavaScript function that achieve the same effect:

class Order {
  public String article;
  private double price;
  private int quantity = 1;

  public Order(String article, double price) {
    this.article = article;
    this.price = price;
  }

  public double total() {
    return quantity * price;
  }

  private int validQuantity(int value) {
    return value < 1 ? 1 : value;
   }

  public void setQuantity(int value) {
    quantity = validQuantity(value);
  }
}

function Order(article, price) {
  this.article = article;
  var quantity = 1;

  this.total = function() {
    return quantity * price;
  };

  function validQuantity(value) {
    return value < 1 ? 1 : value;
  }

  this.setQuantity = function(value) {
    quantity = validQuantity(value);
  };
}

Here are the rules to convert Java classes to JavaScript constructor functions:

  1. Identify class constructor and translate it to JavaScript.
  2. Constructor parameters automatically become private attributes.
  3. Declare and initialize local variable for each missing private attribute.
  4. You don't have to declare public attributes, they will be represented by object properties. However, you should initialize them.
  5. Translate public methods to JavaScript functions and bind them to object properties.
  6. Translate private methods to JavaScript functions.
  7. All protected attributes and methods become public.

Packages for JavaScript

Thursday, October 29th, 2009

When JavaScript codebase grows you may wish to break it in modules or packages. The solution is to find a way to create a namespace and put appropriate functions (and possibly variables) inside. Here is a list of options:

Plain objects

p1 = {};

Packages may be hierarchical:

p1.p2 = {};
p1.p3 = {};
p1.p3.util = {};

In the beginning of a file with JavaScript code you initialize the package p1.p2 like this:

if (!p1) {
  p1 = {};
}
if (!p1.p2) {
  p1.p2 = {};
}

Placing stuff in package is simple: you just add properties to the package object. For example function kaboom() and var _boomer are defined like this:

p1.p2.kaboom = function(what, who) { what.boom(who); };
p1.p2._boomer = "Gordon Freeman";

And you refer to them accordingly:

p1.p2.kaboom(new Citadel(), p1.p2._boomer);

Common prototype

Same as plain package objects but now there is a function that creates them. The benefit is that you may add meta-functions to packages for introspection. For example you may stick to the policy that packages should contain only functions; you may implement it like this:

function Package() {
};

Package.prototype.validatePackage = function() {
  for (obj in this) {
    if (!$.isFunction(obj)) {
      throw new Error();
    }
  }
};

p1 = new Package();

// add content to p1...

p1.validatePackage();

Package closures

You create them like this:

p1 = function() {
  var cookie = 10;

  this.total = function(price) {
    return price * cookie;
  };
}();

And use as package objects:

var income = p1.total(23);

Package functions

Since functions have names you may use them to represent packages:

function p1() {};
p1.p2 = function() {};
p1.box = [];
p1.p2.add = function(item) {
  p1.box.push(item);
};

And the winner is...

Package functions look strange; I don't see any benefits over package objects (at least for now).

Package closures are nice and allow package-private stuff but limited to a single file. You may add content as object properties from other files but then you have to ensure that these files are loaded after the package is available, you can't access package-private stuff and you can't use only a part of the package content (you should always include the file that creates the closure even if you need only one function from those 'other files'). And you may create closures for shared data without using package:

p1 = {};

function() {
  var counter = 1;
  p1.inc = function() { counter++; };
  p1.dec = function() { counter--; };
}();

So there is no real advantage of package closures over the plain package objects.

Package objects with the same prototype may look better than just plain package objects: they give you the control over all packages without any overhead; but do you really need this control? Actually you have to define the Package() function somewhere and ensure that all packages are created by it, but this is a minor complication.

I think that the plain package objects should be enough to construct package hierarchies. If you have a strong use-case for package introspection though, you could consider creating package objects with the same prototype.