Archive for June, 2007

Red5 Application Deployment with Capistrano

Monday, June 25th, 2007

Introduction

To deploy the applications for Red5, I found that Rubys Capistrano really fits very nice. This is an abstract on how we did it.

Basic Requirements

Subversion repository with your Red5 Application checked in (the compiled .class files) with the following structure (or adjust the script below):

  • webapps/config
  • webapps/MyRed5Application
  • webapps/red5-default.xml

On the server

  • Installed and configured Red5 server
  • Secure socket shell access to the server
  • Subversion client (svn)

On the client from which to deploy

  • Ruby >1.8.4
  • Gems
  • Capistrano (gem install capistrano)

deploy.rb

The following Capistrano recipe will provide you with the functionality of automatic deployment and rollback (it uses Capistranos out-of-the-box features where possible). Put this file (”deploy.rb”) in a directory called “config”. Be sure to adjust all parameters starting with a “#”.

set :application, “webapps”
set :repository, “#svn-path-to-your-webapps” # i.e. https://server.com/repos/red5apps/webapps
set :svn_username, “#svn_user” # svn user to use for checking out the application
set :svn_password, Proc.new { Capistrano::CLI.password_prompt(’SVN Password: ‘) }
# app roles
role :app, “#example.com” # domain with s.s.h. access to deploy to
set :user, “#user” # user used for login
# directories
red5_dir = “#/etc/red5″ # path on the server to your red5 directory
set :deploy_to, “#/etc/red5/deploy_to_directory” # directory where to check out your svn code
# tasks
task :restart do
run “cd #{red5_dir} ; #{red5_dir}/red5-shutdown.sh >> #{red5_dir}/red5.log”
run “cd #{red5_dir} ; nohup #{red5_dir}/red5.sh >> #{red5_dir}/red5.log &\nsleep 5″
end
# overridden task
desc <<-DESC
Update all servers with the latest release of the source code. All this does
is do a checkout (as defined by the selected scm module).
DESC
task :update_code, :except => { :no_release => true } do
on_rollback { delete release_path, :recursive => true }
source.checkout(self)
set_permissions
# uncache the list of releases, so that the next time it is called it will
# include the newly released path.
@releases = nil
end

Now what

First step is to create the initial directory layout for your application on the server. Run the following command in the terminal/shell in the “webapps” directory:

cap setup

When started, Capistrano will ask for your password to log into the server and create the appropriate directories you specified in the deploy.rb recipe. You can read more about this in the Capistrano manual, but basically it creates subdirectories like “releases”, “shared” where the application is going to be placed. Each deploy will create a new release and the directory “current” will be a symlink to the current release.

Next step on the server is to replace the Red5 “webapps” directory and create a symbolic link:

cd #/etc/red5
rm -rf webapps
ln -s #/etc/red5/deploy_to_directory/current webapps

This makes sure that Red5 will always take the latest deployed release.

The final step is to deploy the application:

cap deploy

This will checkout the latest release to the server, change the “current” symlink to this release (Red5 was configured to use the “current” directory) and will restart the Red5 server to use the latest version. If you’re running Tomcat it should be easy to change the task :restart…

And finally, in case you want to roll back to your previous version, just execute

cap rollback

on your client and Capistrano will take care of it.

Convert Generic Objects into Class Instances using JSON Schema

Saturday, June 9th, 2007

To convert plain old Actionscript objects into Value Objects I’ve created a generator (still in internal pre alpha mode) that will take (what I call) a “JSON Schema definition” file and generate the Actionscript Value Object classes.
In the “JSON Schema definition” (like XML Schema), the data structure is declared (but unlike XSDs, this is lightweight and human readable). In fact, its valid JSON itself (so the parsing code in the generator reduces itself to a simple json.parse(…)).

You can also define nested structures (typed objects containing other typed objects) as well as typed arrays (array containing typed objects).

To proceed with an example, feed the generator the following JSON definition file:

{
  “_class”: “Book”,
  “title”: “String”,
  “author”: “String”,
  “chapters”:
  [
    {
      “_class”: “Chapter”,
      “name”: “String”,
      “pages”: “Int”
    }
  ]
}

And it will generate the following classes (package declarations omitted for readability):

public class Book
{
  public var title:String;
  public var author:String;
  public var chapters:ChapterArray;

  public function Book(o:Object)
  {
    title = o.title;
    author = o.author;
    chapters = new ChapterArray(o.chapters);
  }
}

public class Chapter
{
  public var name:String;
  public var pages:int;

  public function Chapter(o:Object)
  {
    name = o.name;
    pages = o.pages;
  }
}

public dynamic class ChapterArray extends Array
{
  public function ChapterArray(o:Object)
  {
    super();
    for each(var item:Object in o)
    {
      var chapter:Chapter = new Chapter(item);
      this.push(chapter);
    }
  }
}

Now all you have to do when receiving plain old objects (via a webservice, json/http or any other method), all you have to do to convert them to typed objects is to call

var book:Book = new Book(event.result);

And you’ll have all the benefits of having typed objects (like complete IDE support, etc.) as well as having your interface documented!

I’m interested in feedback about this method, so feel invited to comment.

Close
E-mail It
Socialized through Gregarious 42