Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

June 29, 2011

Jasmine Guard for CoffeeScript rocks on Rails 3

CoffeeScript sure is interesting and I had a very positive experience trying it with Jasmine BDD testing kit. With Guard autocompiling the .js files, it becomes a charm on Rails 3.

Jasmine BDD in CoffeeScript on Vimeo.

This setup guide from pivotallabs.com coupled with this updated gist you will have the infrastructure set up in no time. Any change to the CoffeeScript source or spec files should trigger the Guard to recompile the JavaScript.

To compile "bare" js see this tip to add :bare => true to your Guardfile.

Start guard and jasmine servers and browse to localhost:8888 to run the test suite.
$ guard
$ rake jasmine

Here is a good example of writing a CoffeeScript spec. More spec examples will eventually sprout up, undeniably. And naturally, the Jasmine wiki is a good source of information.

Here's one example: timer.coffee
class Timer
  constructor: (@timer_json) ->
    @start_date = new Date(@timer_json.start_date)
    @end_date = new Date(@timer_json.end_date)
    [@start_hours, @start_minutes] = @timer_json.start_at.split(":")
    [@end_hours, @end_minutes] = @timer_json.end_at.split(":")
And the corresponding test: timer_spec.coffee
describe 'timer-parser', ->

  timer_data = {
    start_date: "2011/06/20", end_date: "2011/06/25",
    start_at: "12:00", end_at: "04:04"
  }

  it 'should parse properly', ->
    timer_json = JSON.parse JSON.stringify timer_data
    timer = new Timer(timer_json)
    expect(timer.start_date).toEqual new Date "2011/06/20"
    expect(timer.end_date).toEqual new Date "2011/06/25"
    expect(timer.start_hours).toEqual "12"
    expect(timer.start_minutes).toEqual "00"
    expect(timer.end_hours).toEqual "04"
    expect(timer.end_minutes).toEqual "04"

June 1, 2011

Writing JavaScript in 2011 - catching up with the latest trends

JavaScript has definitely bloomed during the last few years. I do remember the first time I heard of JavaScript in the late 90s - I wrote a small script that showed a random image (out of a static array) on a static HTML page that I tested in Netscape and IE5-or-so. Today people run JavaScript in top- and mid-range mobile devices, on their web browsers, on servers, on the Gnome3 desktop.

JavaScript is the only language for building an application for all major "smart" mobile devices from within a singular codebase. That, already, interests me enough to give a closer look on some modern JavaScript tools - and write my observations about them.

Foremost, testing JavaScript was something I had completely neglected before. If I was to write serious applications using JavaScript, I'd absolutely needed a way to write unit tests. Secondly, I wanted to have a look at CoffeeScript, which has had a lot of positive attention lately.

I started out by digging into the recent archives of JavaScriptWeekly newsletter. Out of a good number of testing tools, I selected to try out JsTestDriver. It is compact, requiring only a single jar file and a configuration file. The jar contains a small web server that is ran on the source code directory, and exposes a specific url that should be opened in the browsers that will run the JavaScript code to be tested. Cool! If you consider to try out JsTestDriver yourself, I recommend you checkout their SVN repository and compile the jar yourself - the jar file given in the example is outdated and does not contain all the features that the guides may refer to - for example, mocking a piece of HTML that the JavaScript modifies.

Mocking AJAX was out of my scope at this stage, for that you may find this article to be helpful.

For learning to use JsTestDriver, I chose to write a simple slideshow application that uses CSS3 transformations to change the pictures. The required JavaScript for this seemed simple enough, and I wanted to learn some new CSS tricks as well. ;) So, this is "bébé", written in a few days using jQuery-powered CoffeeScript. I started out by getting the basics of CoffeeScript, having it to load the images onto the page, and then wrote tests to see the pictures were actually loaded. Testing the user interface seems to be very difficult, due to differences in how different browsers behave under JsTestDriver. I set the picture position to absolute, since elsehow I could not get the CSS transition to appear smooth (and have the image to disappear without hiding it with JavaScript). CoffeeScript is pretty amazing, and works really well with jQuery. :)

The code for this, along with the JsTestDriver tests, can be found on Github. This seems to work reasonably well in Firefox 4, Chrome, Opera 11, Safari (and Mobile Safari on iOS) and Android browsers. Firefox 3 behaves correctly, it just doesn't show the transition effect. IE fails miserably, never showing anything except the first image. :/

Here are some nice pointers to related articles:

..and now for something different ..
PC emulator in the browser running Linux on JavaScript

January 29, 2011

Recipe of request-response over AMQP with Python and Java

This is a recipe to setup synchronized messaging over AMQP. The recipe source zip file contains an implementation of a Python backend broker. Along comes example Python and Java clients that send messages over AMQP to the running broker(s). The broker load can be balanced over to several processes. RabbitMQ can automagically balance the incoming requests to multiple consumers. This setup has been deployed successfully, achieving decent performance (we have benchmarked only the private implementation, our throughput is approx. 30 msgs/sec. with three backend processes).

Good presentations on concurrent messaging and AMQP are available from:

AMQP can be used as a message bus between various system components in different languages maintained by different teams.

Here are the bare bones of this recipe:

  • create a unique identifier (qid) for the request
  • create a new consumer and bind it to a temporary response queue
  • publish the message into the durable request queue
  • wait for the response on the response queue
  • close response channel
Topic exchange is the only exchange type that honors routing keys, which are essential for pairing request and response together, using the unique identifier in routing key.

Unzip the recipe (or clone the recipe repository from GitHub). Install RabbitMQ (default settings are ok), and install Python modules 'amqplib' and 'carrot' (plus 'jsonrpclib' for the tests).

Launch the RabbitMQ server.

sudo rabbitmq-server

Start the example backend broker:

cd py-src
python example_broker.py
This will launch a daemon that listens for messages on a specific AMQP channel. A "request" is a thin JSON wrapper. If the request includes a request id (qid), the daemon will return the current time over the AMQP. If the request is not identified, the time will be printed instead.

Run the example requests in Python and Java, while the example_broker is running:

cd py-src
python example_request.py
Output:
Response from AMQP: 
{u'msg': u'Sat Jan 29 20:43:36 2011'}
Run the same requests from Java:
cd java-src
java -cp .:build:lib/json.jar:lib/rabbitmq-client-1.8.1.jar:lib/commons-logging.jar:lib/commons-io.jar \
  example.ExampleRequest
Output:
29.1.2011 21:11:01 recipe.amqpbus.AMQPRequestResponseImpl newConnection
INFO: ExampleBroker connected to RabbitMQ @ 127.0.0.1:5672/
29.1.2011 21:11:01 recipe.amqpbus.AMQPPublisher send
INFO: publishing query to ExampleBroker_req with binding key: example.request
{"q":{"q":"hello AMQP backend, I am Java"}}
-----------------------------------------
29.1.2011 21:11:01 recipe.amqpbus.AMQPPublisher send
INFO: publishing query to ExampleBroker_req with binding key: example.request.q538
{"q":{"q":"time can you get me please?"},"qid":"q538"}
29.1.2011 21:11:01 recipe.amqpbus.AMQPConsumer receive
INFO: amq.gen-dyK/PZQn/brNl9jTR/tlAg== received message: 
{"msg": "Sat Jan 29 21:11:01 2011"}
Response from AMQP: {"msg":"Sat Jan 29 21:11:01 2011"}

The example_broker output should print the events when it receives the requests: Output:

  consumer received message: 
  {'exchange': u'TestExchange', 
    'consumer_tag': u'__main__.ExampleBroker-e7175ec0-cd1f-4d2e-973b-1eeb42d4071d', 
    'routing_key': u'example.request.*', 
    'redelivered': False, 
    'delivery_tag': 2, 
    'channel': <amqplib.client_0_8.channel.Channel object at 0x1007bbad0>}
  -------------------
  received request 355:
  what time is it?
  -------------------
  response to TestExchange with routing_key: example.response.355, message: 
  {"msg": "Sat Jan 29 20:47:59 2011"}
  using channel_id: 3
  Channel open
  Closed channel #3

You should be able to pick up the ingredients and integrate them to your codebase as you see fit.

December 5, 2010

Hybrid Qt applications with PySide and Django

This article describes some thoughts and experiments on developing applications targeted for mobile systems, especially MeeGo. I am trying to imagine a secure and agile way to write applications that are robust yet elegant.

About the author – I have worked with Ruby on Rails, Django and Qt. I think that web run-time technologies (HTML5, JavaScript and CSS3 – called WRT in this article) can provide a flexible way to build user interfaces. Many developers are familiar with these technologies, and maximizing WRT percentage in the codebase has potential to better portability for devices from different manufacturers. Personally to me MeeGo is the most interesting mobile operating system target. I am trying not to completely forget about business models, but then again, I have a software libre bias.

I have experimented of "hybridizing" Qt with Django. PySide provides Qt bindings for Python in LGPL licensing. Django is a CMS-oriented web framework written also in Python. Using Python instead of C++ has a drawback in runtime efficiency, but in some cases developer productivity and codebase maintainability is more important. Python has become one of my favourite languages.

This approach interests me because an application from the same codebase can be deployed both on desktop and on (a Nokia) mobile device. Alternatively a desktop/server Django application could serve plain WRT components also for non-Qt clients (but I can't comment how Apple would respond to this sort of application for the App Store). Android Market - well - they probably would not have a problem with it. That's all I have to say about marketing and business politics.

Nokia N900 is a fabulous platform for prototyping, on which I wrote an experimental application for controlling a TV set within the local area network (LAN). Figure 1 displays an event cycle in which the whole application is self-contained on the mobile device.

Fig 1. The software components on N900

Not depicted in figure 1 for clarity, the Python process contains an implementation of a finite-state machine. User actions are sent as events to the backend process handling logical states, while the WRT defines slots that update the UI.

This approach is reminescent of cloud computing, but with an important difference in that the data that moves between the server an the mobile device would not be stored on servers the user does not have control over. The data would never pass to the ISP either. Consider a Windows PC with a media repository was running PySide/Django in the LAN, and an iPhone owner could control the media stream onto a MeeGo TV set? Switch Windows for Linux and iPhone for a MeeGo device and it still would work without a heavy rewrite of the codebase. The PC would serve an ad-hoc "cloud" that could be operated from the hand-held device, acting as a remote controller. That is the core of this vision.

It makes sense to browse local data (from the PC) and "stream" it onto the mobile device. You wouldn't carry the precious data around in your phone, but it still would be reachable from home over a secure network connection. This is a data privacy issue. Photos are a good example. A major concern in any networked application is security and I've foolishly ignored many gaping secury holes in this prototype. As for my defense I can only say I am experimenting the feasibility and hardware performance so far.

 
Fig 2. Cloud computing within the LAN with MeeGo

The prototype application I've written (called MxManager) is a remote controller for Maximum T-8000 personal video recorder (PVR) that runs on embedded Linux. Its prorietary firmware provides a simple HTTP interface that mimics the physical remote controller. This prototype uses that API to set recordings from the EPG and play recordings on the TV. Here is a screenshot of the application (on MacBook desktop) and a blurry video of it running on N900.

Fig 3. MxManager UI


Qt hybrid on N900 on Vimeo. Sorry about the quality. It was shot up close, I guess I would have needed to strap on a macro lens.


The screen and remote control UI are individual QWebView elements and their content is composed by Django views. Events from the UI are triggered in JavaScript and events back from PySide are injected as JavaScript function calls into the page. PySide is running a finite-state machine (using QStateMachine) that holds the internal state of the application. Changes in UI are triggered by state change events. I wrote about this in more detail in a past blog post. The source code is released under the BSD, so you are welcome to have a look and give an opinion.

Initial experiments with QML appeared subjectively much faster, nearing smooth animation along the button press, but in the past I had a problem in sending signals into QML. This seems to have been fixed in PySide 1.0.0. This is a solid direction to experiment - perhaps Django could be used to compose QML for the QDeclarativeView..

Another video of the application in action with the TV set!

While building the web stack on well-proven frameworks, security issues still need to be considered carefully. Web sockets would be better designed for such eventing purpose than Ajax, with a better security model. I do repeat, this is not production-ready code.
If the mobile phone supported QtMobility, it could be possible to use mobile accelerometer and orientation to control playback. Turn the phone upside down to pause, for example. The next video (by perlinet, not me) portrays using QtMobility API in PySide with QML.


PySide is great technology and it's inclusion to MeeGo opens up many ways for developers to bring their applications to the platform. There are definite points to focus on this basis:
  • security implications
  • web sockets
  • QML
  • QtMobility experimentation
Especially intriguing for me would be to hook up digiKam database into a desktop-based Django app for browsing photos on a mobile device / tablet computer.

What's unique here is the merging of the Qt and web frameworks to operate within the same OS process, which makes it easier to separate the presentation and business logic. Personally I feel this technology seems feasible, and perhaps I will continue to investigate it further in 2011. There are web services that operate on a similar business model, and maybe open source software is following the trend.

November 19, 2010

Recipe: handling database communication breakdown in Rails and Django

This recipe is for users who manually handle persistent (shared) database connection, with Oracle, although it's probably easy to adapt for other database backends with small adjustments. I needed to implement this both in Ruby (Rails' ActiveRecord) and Python (django.db) daemons, both working in the same setting. I thought the solution was elegant enough to be cleaned up into a recipe.

Automated database connection pooling for Python (nor Ruby) is not supported with Oracle 10g. Only 11g introduced Database Resident Connection Pooling (DRCP). It probably makes this recipe redundant for Python users with 11g. Oracle has official support for using Python with Oracle Database 11g, using the cx_Oracle driver. I'm not sure but I think Oracle doesn't have any form of official support for Ruby, but the de-facto ruby-oci8 driver works well with ActiveRecord.

Without automated connection pooling you have two decent options. Either open and close a new connection for each request, or save open connections into shared memory. The latter has obvious performance benefits if the expected request rate is high, but exposes a number of other problems this recipe aims to address. A connection can abruptly terminate because of e.g. a network glitch or maintenance downtime, and the sysadmins deploying your software will be happier having to deal with less services to reboot.

The handler should catch exceptions only related to network or database resource failures, whereas in other cases (SQL typo?) the original exception should not be reacted upon. Figuring out the proper ORA error codes to use was an exciting task, I hope I got them right ;). Those guys at Oracle sure love to make things easy. Since I use a regular expression to match the error message string, a multitude of errors can be matched with a single rule. Fortunately, all errors dealing with Transparent Network Substrate are marked by prefix "TNS". In my tests most errors were indeed caught with the single "ORA-.....: TNS" regexp.

Python and Ruby have much in common, both could let me write this very expressively with about the same LOC. There is one small detail I'd like to bring up. These two expressions both compare the codes listed with the exception (error message in variable "message"), and return true if the message matches to one of the given ORA error codes.

Python

# Example message="ORA-03113: end-of-file on communication channel"
any(filter(lambda oracode: re.search('ORA-'+oracode,message), re.split(' *\n *| +(?=\d)',"""
    .....: TNS
    01000 01001 01014 01033 01034 01037 01089 01090
    011.. 015.. 016..
    031..
    28547
    30678
    """)[1:-1]))
Ruby
# Example message="ORA-01034: ORACLE not available"
%w{ .....:\ TNS
    01000 01001 01014 01033 01034 01037 01089 01090
    011.. 015.. 016..
    031..
    28547
    30678
}.select {|oracode| message[/ORA-#{oracode}/]}.any?
Especially take notice of Ruby's %w{multiline string} versus Python's re.split(' *\n *| +(?=\d)',"""multiline string""")[1:-1]. This just for the sake of the visual appearance of input data on the screen. Ruby makes it easier to write aesthetic code. Perhaps Python has an idiom for this, though, it just didn't pass my mind.

example_oci_exception_handler.py

# -*- coding: utf-8 -*-
"""
You may use this file under the terms of the BSD license as follows:

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice, this list of
      conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright notice, this list
      of conditions and the following disclaimer in the documentation and/or other materials
      provided with the distribution.

THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL  OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those of the
authors and should not be interpreted as representing official policies, either expressed
or implied, of copyright holder.
"""
import re
import sys
from time import sleep
from myapp.settings import settings # your django settings module
from django.core.management import setup_environ
setup_environ(settings)
import cx_Oracle
from django.db import connection
from django.db.utils import DatabaseError
from logging import getLogger
log = getLogger(__name__)

class ExampleOCIExceptionHandler():
    """Recipe for handling lost Oracle database connection.
    
    Depends on Django ORM, and that proper settings.py exist and is initialized properly.
    
    Selects the network and connection errors, waits until the server is reachable again,
    and calls the method again during upon which the exception happened.
    
    This is very useful if the connection, for some reason, is shared between requests.
    Oracle 10g does not support connection pooling with cx_Oracle.
    """

    @staticmethod
    def dispatch(message_data):
        """Processes request.

        In case of database connection failure, the waitForOCIConnection() loop is called
        and connection should be re-established. In case of other Oracle errors,
        the error is raised again.
        """
        try:
            # do some database operations...

        except (cx_Oracle.Error, DatabaseError):
            """
            Catch lost database connection.

            Handles all TNS errors:
              ORA-xxxxx: TNS errors

            And all errors from these ranges:
              ORA-011xx: Database file errors
              ORA-015xx: Execution errors
              ORA-016xx: Execution errors
              ORA-031xx: communication errors

            Along with these specific errors:
              ORA-01000: maximum open cursors exceeded
              ORA-01001: invalid cursor
              ORA-01014: ORACLE shutdown in progress
              ORA-01033: ORACLE initialization or shutdown in progress
              ORA-01034: ORACLE not available
              ORA-01037: cannot allocate sort work area cursor; too many cursors
              ORA-01089: immediate shutdown in progress - no operations are permitted
              ORA-01090: shutdown in progress - connection is not permitted
              ORA-28547: connection to server failed, probable Oracle Net admin error
              ORA-30678: too many open connections

            """
            msg = str(sys.exc_info()[1]).rstrip()

            # is the error about broken connection?
            if any(filter(lambda oracode: re.search('ORA-'+oracode,msg), re.split(' *\n *| +(?=\d)',"""
                .....: TNS
                01000 01001 01014 01033 01034 01037 01089 01090
                011.. 015.. 016..
                031..
                28547
                30678
                """)[1:-1]) # ignore outermost items as they are empty strings
            ):
                log.error(msg)
                ExampleOCIExceptionHandler.waitForOCIConnection()
                # enter recursion and call this method again..
                sleep(2)
                return ExampleOCIExceptionHandler.dispatch(message_data)

            else:
                log.debug(msg)
                log.debug("Error seems to be not about lost connection, raising again ..")
                raise

    @staticmethod
    def waitForOCIConnection(time_to_wait=60):
        """Creates a new database connection, loops until one is established."""
        # nullify the connection first, since it can't discover that the socket is gone
        connection.connection = None
        while not connection._valid_connection():
            try:
                log.info("Attempt to establish OCI connection to %s ..." % [
                    settings.DATABASES['default']['NAME']])
                # in django parlance, calling _cursor() opens the database connection
                cursor = connection._cursor()
                sleep(2)
                return connection._valid_connection()

            except (cx_Oracle.Error, DatabaseError):
                exctype, message = sys.exc_info()[:2]
                log.error(str(message).rstrip())
                log.info("Retrying OCI connection in %i seconds" % time_to_wait)
                sleep(time_to_wait)
                return ExampleOCIExceptionHandler.waitForOCIConnection(time_to_wait)


example_oci_exception_handler.rb
# encoding: utf-8
=begin
You may use this file under the terms of the BSD license as follows:

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice, this list of
      conditions and the following disclaimer.

   2. Redistributions in binary form must reproduce the above copyright notice, this list
      of conditions and the following disclaimer in the documentation and/or other materials
      provided with the distribution.

THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL  OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

The views and conclusions contained in the software and documentation are those of the
authors and should not be interpreted as representing official policies, either expressed
or implied, of copyright holder.
=end
require 'rubygems'
require 'active_record'

# Recipe for handling lost Oracle database connection with ActiveRecord.
#
# Depends on RAILS_ROOT and RAILS_ENV variables to be set and RAILS_ROOT/config/database.yml file to exist.
#
# Selects the network and connection errors, waits until the server is reachable again,
# and calls the method again during upon which the exception happened.
#
# This is very useful if the connection, for some reason, is shared between requests.
class ExampleOCIExceptionHandler

  # Processes request.
  #
  # In case of database connection failure, the waitForOCIConnection() loop is called
  # and connection should be re-established. In case of other Oracle errors,
  # the error is raised again.
  def self.dispatch(message_data)
    begin
      # do some database operations...

    # Catch lost database connection.
    #
    # Handles all TNS errors:
    #   ORA-xxxxx: TNS errors
    #
    # And all errors from these ranges:
    #   ORA-011xx: Database file errors
    #   ORA-015xx: Execution errors
    #   ORA-016xx: Execution errors
    #   ORA-031xx: communication errors
    #
    # Along with these specific errors:
    #   ORA-01000: maximum open cursors exceeded
    #   ORA-01001: invalid cursor
    #   ORA-01014: ORACLE shutdown in progress
    #   ORA-01033: ORACLE initialization or shutdown in progress
    #   ORA-01034: ORACLE not available
    #   ORA-01037: cannot allocate sort work area cursor; too many cursors
    #   ORA-01089: immediate shutdown in progress - no operations are permitted
    #   ORA-01090: shutdown in progress - connection is not permitted
    #   ORA-28547: connection to server failed, probable Oracle Net admin error
    #   ORA-30678: too many open connections
    #
    rescue OCIError, ActiveRecord::StatementInvalid
      msg = $!.message
      
      # is the error about broken connection?
      if %w{
        .....: TNS
        01000 01001 01014 01033 01034 01037 01089 01090
        011.. 015.. 016..
        031..
        28547
        30678
      }.select{|oracode| msg[/ORA-#{oracode}/]}.any?
      
        logger.error msg
        waitForOCIConnection()
        # enter recursion and call this method again..
        return dispatch(message_data)

      else
        logger.debug msg
        logger.debug("Error seems to be not about lost connection, raising again ..")
        raise $!
      end
    end
  end


  # Attempts to establish database connection.
  # Loops until ActiveRecord is connected.
  #
  # Set time_to_wait in seconds.
  def self.waitForOCIConnection(time_to_wait=60)
    begin
      database_configuration = YAML.load_file(File.join(RAILS_ROOT,"config","database.yml"))
      ActiveRecord::Base.configurations = database_configuration
      logger.info(
        "Attempt to establish OCI connection to %s ..." % database_configuration[RAILS_ENV]['database'])
      ActiveRecord::Base.establish_connection(database_configuration[RAILS_ENV])
      ActiveRecord::Base.connection # essential to open connection
      return ActiveRecord::Base.connected?

    rescue OCIError, ActiveRecord::StatementInvalid
      logger.error($!.message)
      logger.info("Retrying OCI connection in %i seconds" % time_to_wait)
      sleep time_to_wait
      return waitForOCIConnection(time_to_wait)
    end
  end
end

October 15, 2010

Interacting with legacy Oracle database in Python

I needed to use an Oracle database in Python. It all went rather smoothly with the guides, hints and examples, but I was missing a walkthrough. This memo is about setting up Oracle with Python and how to use legacy database with Django. Better yet, use Django Models without any of the HTTP functionality.

Oracle more or less has official support for cx_Oracle, and it was fairly easy to set up. cx_Oracle needs Oracle headers to compile. From the Oracle download site get, according to your OS and arch, instantclient-basic, instantclient-sqlplus and instantclient-sdk. The Oracle download site requires registration.

Select a working path and extract the Instant Client packages.

$ cd /opt
$ unzip ~/Downloads/instantclient-basic-10.2.0.4.0-macosx-x64.zip
$ unzip ~/Downloads/instantclient-sdk-10.2.0.4.0-macosx-x64.zip
$ unzip ~/Downloads/instantclient-sqlplus-10.2.0.4.0-macosx-x64.zip

It is necessary to set the environment variables ORACLE_HOME, LD_LIBRARY_PATH and DYLD_LIBRARY_PATH. Put these into a convenient file and update the environment.

~/.oraenv

export ORACLE_HOME=/opt/instantclient_10_2
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME
export DYLD_LIBRARY_PATH=$ORACLE_HOME

On OS X, you need to create one symlink for the build to succeed:

$ cd /opt/instantclient_10_2/
$ ln -s libclntsh.dylib.10.1 libclntsh.dylib

Now you are ready to build and install the cx_Oracle driver.

$ cd /opt
$ tar xzf ~/Downloads/cx_Oracle-5.0.4.tar.gz
$ cd cx_Oracle-5.0.4
$ source ~/.oraenv # load environment
$ python setup.py build
$ python setup.py install

Assuming the database is already running somewhere, enter the connection parameters to this python script and test the connection:

test_connection.py

# -*- coding: utf-8 -*-
import cx_Oracle
connection = cx_Oracle.connect(
    "user",
    "pass",
    "127.0.0.1:1524/some.oraservice"
    )
cursor = connection.cursor()
cursor.execute("select  * from v$version")
for column_1 in cursor:
    print "Values:", column_1
You should see something like this:
$ python test_connection.py
Values: ('Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi',)
Values: ('PL/SQL Release 10.2.0.4.0 - Production',)
Values: ('CORE\t10.2.0.4.0\tProduction',)
Values: ('TNS for Linux: Version 10.2.0.4.0 - Production',)
Values: ('NLSRTL Version 10.2.0.4.0 - Production',)
BUT if you get:
cx_Oracle.DatabaseError: ORA-12737: Instant Client Light: unsupported server character set WE8ISO8859P15
You took the BASICLITE package!!! Go back to download the proper package and start from the beginning.

Python can connect to the database with cx_Oracle, and Django models offer a clean way to make use of that connection. If you happen to have schema read privileges to the database, Django can generate models.py from it. Now, this is pretty nice feature when it comes to interacting with legacy database, as we shall see.

myapp/settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': '127.0.0.1:1524/some.oraservice',
        'USER': 'user',
        'PASSWORD': 'pass',
    }
}

myapp/manage.py

from django.core.management import execute_manager
import settings
if __name__ == "__main__":
    execute_manager(settings)

The database SQL shell is useful to have and to test the connection. You can get greeted with the friendly SQL*Plus console by command dbshell:

$ source ~/.oraenv # remember environment!
$ python myapp/manage.py dbshell
SQL*Plus: Release 10.2.0.4.0 - Production on Fri Oct 15 12:56:05 2010

Copyright (c) 1982, 2007, Oracle. All Rights Reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL>

Then you are ready to inspect the schema and generate the Python classes:

$ python myapp/manage.py inspectdb > myapp/models.py
Check the new file and assign "primary_key=True" to a column you choose, for each table you need.

Say your legacy db has a table called OraAbbOy1001 you need to manipulate. You may have a start script bin/start.py (as you don't run this with django-manage) in which you setup Django and do whatever you do to init your program. In myapp/logic.py you import the models and operate with the database.

bin/start.py

# -*- coding: utf-8 -*-
import myapp.settings
from django.core.management import setup_environ
setup_environ(myapp.settings)
# before do something else,
# the three lines above here is your first operation.
You can then operate on the models by finding or creating instances (selecting and inserting rows) through the ORM. It is also possible to mix in raw SQL, like in this example. I had trouble figuring out how to set a custom sequence name (legacy value) so I opted to select it manually.

myapp/logic.py

# -*- coding: utf-8 -*-
import time
from django.db import models, connection
from myapp.models import OraAbbOy1001

id = # comes somewhere
try:
    user = OraAbbOy1001.objects.get(id=id)

except OraAbbOy1001.DoesNotExist:

    # select nextval from ID sequence
    seq_name = 'q1001user'
    cursor = connection.cursor()
    cursor.execute("SELECT %s.NEXTVAL FROM DUAL" % seq_name)
    userid = cursor.fetchone()[0]

    # create new user
    user = OraAbbOy1001.objects.create(
        id=userid,
        name='Vic Video',
        create_date=time.strftime('%Y-%m-%d',time.localtime()),
    )

    log.info("OraAbbOy1001 user id %i (%s) created" % (
        user.id,
        user.name
        )
    )

SQLAlchemy looks very interesting. If you need to have more control over the queries, look up for it.

BTW, I'm not affiliated with O'Reilly, I just like the illustrations. They do have many good books.

September 11, 2010

QML signals on PySide

I studied QML with signal-slot communication across to Python a bit.
If you are looking for examples in source code, see

The latter one use PySide but not QML, and has a preview video elsewhere in this blog. Here are my earlier experiments.

This video shows a very small application, consisting of two files - webview.qml and webview-qml.py.
The first three signals originate from QML and Python opens up a QMessageBox to display them, along by printing to stdout. The third signal will emit a fourth signal from Python to QML, with an url as a parameter, and the url will open inside a WebView.

This app evolves the idea a bit further. The HTML5 canvas demos seen in the video are not by me, they are from the web. There is a state machine working behind the scenes.

April 15, 2010

Testing JavaScript & XHR with Python

I am working on a library for Django - which I'll describe later - and for building this project I need to test the behavior of XHR on the HTML page. That is, I have a page, inject some JavaScript (that may do a request on the server), and see how it changes the document. The Django application the library is designed for creates some parts of the original page and processes some parts of the server-side XHR.

Python is great for this. I've mentioned already in this blog how I like Qt4, and it proves to be very useful again. I could not get PySide running on OS X just yet, so I opted for PyQt4.

Four tests; four evenings working with them – each having an intricate problem to solve ;) Two tests work on the local document, the other two connect to the Portlet test bench, running on localhost. These tests trigger onclick submit actions from the XHR test page, simulating a user clicking a button.

This way it is possible to test the effect of JavaScript injection onto any web page in the wild. At least the WebKit response.. Firefox could be tested by using python-gtkmozembed. QWebKit also has methods for binding Python variables to the page (it is possible for JavaScript to trigger a Python callback function) and render an image snapshot of the page.

If you wish to run the tests, download the file, start up the Rails server with the test bench and run

$ python xhr_tests.py

March 30, 2010

Mobile SDKs

I met a nice guy who has a web page that presents an award-winning grill he's designed. He briefly mentioned the site that runs entirely on Flash and I offered to upgrade it for HTML, CSS and Javascript. I wanted to learn some CSS3 and MooTools on a real-world problem. The design consists of a menu, a large image and a caption. Images are switched either by timing or by user clicking next/back buttons, complete with fade out and fade in. As it came together I tested it on Firefox, Chrome, Opera, Arora, Safari, Konqueror and IEs 6-8. I decided to try out the popular mobile SDKs as well then. Namely, Nokia Maemo 5, Google Android and Apple iPhone. This is an overview and a quick, superficial evaluation of the mobile developer toolkits.

My aim was not to work on any platform-specific code, but to test out how these devices would display the page and the image transitions. I very much appreciate the ease of installation, good documentation and in general getting to the point very quickly with a minimum amount of hassle. Happy developers make better software. Even better when they needn't to fight with the toolchain. :)

Maemo 5 was the first one I picked since being Debian-based it seems to be the most open platform. I remember briefly using a Nokia N770 in 2006 and apparently Nokia thinks it's a product line worth upgrading by N810 and now N900 released in 2009. Unfortunately even with the backing of Nokia and several years of development, the documentation is not quite as organized as I'd like it to be, with all respect. From the main Maemo.org developer page, it takes five clicks through a Nokia site on another host, back to Maemo wiki, and to the cryptic installation notes that remind me of Gentoo manuals. Choosing those five clicks wasn't quite trivial either.

Thankfully some fellow Maemo developers kindly guided me to a hidden Nokia page hosting a prepared Ubuntu virtual image with the SDK and the rest of the tools. Apparently even hosted at nokia.com this is an unofficial image. I let the 1.7 GB image to download overnight and launched it in VirtualBox the next morning without a hitch. It brought up the Ubuntu desktop, with no assistance or an emulator icon around. Here be dragons indeed.. Spells and incantations will apparently be needed. Now, somewhere in the middle of the installation spellbook it says "Xephyr" needs to be started:

$ Xephyr :2 -host-cursor -screen 800x480x16 -dpi 96 -ac -kb &

Mm-hm. This launches up an empty, gray X window. Now, the commands to start the "scratchbox environment" and inside it, the Maemo startup script:

$ setxkbmap fi
$ /scratchbox/login
> export DISPLAY=:2
> af-sb-init.sh start

Success! I still think I shouldn't need to know any of this, but it is running with a fair amount of work. Unfortunately none of the apps were installed and the virtual device seemed quite empty – all there was this Application Manager:

Some extra packages need to be manually installed into the scratchbox environment:

> apt-get install nokia-binaries nokia-apps

Then I had the Maemo browser, which displayed the page correctly. Happiness!

I wonder what Intel does to the SDK now after merging Moblin and Maemo to MeeGo...

Next, testing Google Android. The SDK is a ~20 MB zip file that is a Java GUI which downloads the actual SDK. The size after downloading platforms v1.6 and v2.1 is 343 MB.

Creating an Android virtual device was very easy with the GUI.

And it renders correctly on version 2.1!

Finally, since I work on OS X, I can also try out the iPhone SDK. It required a registration and another overnight download of the whopping 2.8 GB package that comes with bundled Xcode. After downloading, QuickSilver finds the simulator quite nicely and it looks sleek.

I have only a few times used a real iTouch device, but I see the appeal in their design. iPhone with its Safari browser can display my test page correctly.

Overall, considering these mobile SDKs, Apple provides the most elegant solution, Google being in the middle ground and (now-depracated) Maemo the worst experience. While these being developer tools, the user is expected to have some technical knowledge. This is only a very superficial evaluation, just from the perspective of a web developer who wanted to test how his page renders on these platforms. Speaking of the devices, personally I cannot justify their price to their capabilities just yet, but it is nice to evaluate them by their SDKs. Maemo/MeeGo has the Debian sex appeal for the better and the worse. I feel that Nexus One won't be the first really big model even being technologically superior to the iPhone..

March 18, 2010

Python Qt4 soup - quick way to cook up a cross-platform GUI

A friend of mine asked me to do a very quick and dirty throwaway application that parses data off a standard HTML file into an Excel spreadsheet. I chose to do it in Python and spent about an hour to decide which backend libraries to use, and opted for BeautifulSoup and xlwt to do the hard work. The core app – one function to parse input and another function to create the Excel workbook – was written in under two hours. It was only running from the command line – so I cooked him up a GUI:


This friend is a Windows user who dislikes Linux and Mac, and he needs a clean GUI that is dead simple to run and operate. After one sleepless night of furious hacking, he got one. In a Windows exe. Developed on OSX, also running under Linux. This is the power of Python combined with Qt4. The sources are online for those interested to see the details. To emphasize the throwoff nature of the app, all labels are hard-coded to Finnish.

I already had some experience on PyQt4. If you're reading this and decide to look it up, do not pass PySide – it is a newer Python Qt4 bindings library endorsed by Nokia et al. Either one you choose, you can't pass QtDesigner, which is a nice tool to design the UI and comes bundled in the Qt developer packages. In this case all I did was to add a QTableView element with some margin for the tool and status bars.



QtDesigner creates an .ui file (XML) that is translated to Python via pyuic4. With a text editor (XCode) I wrote a subclass of the UI model that extends it with a toolbar with two functions and a status bar for messages. Using file dialogs is easy. The most tricky bit is to make the data from the input file visible in the table view. PyQt4 handles that by a custom subclass of QAbstractTableModel with specific methods the Qt4 API will call to update the table contents.

Quite simple until you get to signals, slots and threading, and it doesn't hurt too much to write and maintain. Overall, about 120 lines of code for the UI, 50 lines for the core.

Now all is left is to test and package it for Windows for my friend to run. I've gotten over my worst fear and loathing of Windows, but I still have a very uneasy feeling every time I boot the OS, even in VirtualBox. Text editor and the console are my friends, and cmd.exe does not quite meet my standards, even on Windows 7. Perhaps I'll look up TCC, but honestly I'd expect a better act on behalf of Microsoft. I had a better time with 4DOS 20 years ago running on MS-DOS 5. Oh, don't even get me started on "edit.com"..



    Si si, I'm a terminal snob.

Seems that py2exe is just what I need. It installed fine via easy_install into XP. Their wiki houses the information how to construct the setup.py for py2exe to build it. Mainly, name of the main script for the executable and which libraries to bundle. It creates a whole number of files, totalling 26 MB. I was unable to generate a single executable file, but this does the trick.


February 14, 2010

Introduction to Haskell and Erlang

I am reading Masterminds of Programming, by O'Reilly. It is a very good book I will get back to in other posts. Reading up on the thoughts of Haskell core language developers made me very interested in the language and functional programming in general. Haskell and Erlang are functional languages, so it takes a while to get into the mindset but seems like it's all worth the while.

I looked up some Haskell resources: http://www.haskell.org/haskellwiki/Haskell_in_5_steps

Then I saw the Haskell "Hello World"

Prelude> "Hello, World!"
"Hello, World!"
And immediately fell in love. Is there a simpler way to say "Hello, World!"?

This Haskell hacking video is also a great source of inspiration :)

There is also a nice guidebook called Learn You a Haskell for Great Good! with cutesy pictures and writing that takes you by the hand. Very nice. Reminds me of the Poignant Guide to Ruby. :) Erlang has got another one named Learn You Some Erlang for Great Good!, and you can't go wrong with one that has got a bearded squid on the cover =D

Erlang indeed looks to be a very nice language. This is an example from the book:

1> Weather = [
  {toronto, rain},
  {montreal, storms},
  {london, fog},
  {paris, sun},
  {boston, fog},
  {vancouver, snow}].

2> FoggyPlaces = [X || {X, fog} <- Weather].
[london,boston]

In fact this is even more compact syntax than in Ruby. Erlang atoms behave much in the same way as Ruby symbols. In which the equivalent would be something like:

>> weather = [
  {'Toronto' => :rain},
  {'Montreal' => :storms},
  {'London' => :fog},
  {'Paris' => :sun},
  {'Boston' => :fog},
  {'Vancouver' => :snow}]

>> foggy_places = weather.collect{|x| x.keys[0] if x.values[0]==:fog }.compact
=> ["London", "Boston"]
Or..
>> foggy_places = weather.select{|x| x.values[0]==:fog }.collect(&:keys).flatten
=> ["London", "Boston"]

Either case, I cannot think of a better way to say this in Ruby and Erlang has a cleaner way.

Joe Armstrong is one of the original Ericsson engineers who designed Erlang and wrote the first implementation. He describes using Erlang to feed data onto the page by web sockets. I am completely astonished. I need dig deeper into this...

January 29, 2010

EJB to Ruby proxying and a little bit on programming languages

This essay goes quite technical at times but the presented idea is pretty simple.

Java and the J2EE stack seem to be used in large-scale enterprise web solutions. Ruby is an odd hippie programming language that is not so often met (yet!) in this enterprise world. Ruby on Rails does not quite have the native equivalent in Java web development toolpack, and there never will be such. One key fundamental difference in Java and Ruby, is their measure of abstractness. Higher abstraction in some cases help to describe and solve the problem in just a few code blocks. Ruby lets you express ideas outside the micromanagement level - right from the beginning of your introduction to the language.

JRuby helps to break a major technical barrier, making possible to leverage the massive amount of Java libraries that now can be used through the Ruby interpreter. This is a description of a real world scenario where Ruby expression describes and solves the problem quite beautifully.

To understand what is happening next you need to know that an EJB is an Enterprise Java Bean. You can imagine that the Bean is an exporter in Brazil. The Java transaction layer RemoteMethodInvocation is built on top TCP/IP infrastructure. Regular citizen Java clients need to contact their national supplier.

It is quite a bureaucratic process. It takes some knowledge of Java to understand how each object should behave. EJB3 makes this a bit easier but to efficiently use the developer tools will take a long time to learn. This is an example of the Java enterprise business model where you develop on elaborate IDEs and large companies have lots of people doing object-oriented chunks of code. After having that much Java your dreams will become XML configurable for a while..

Ruby has a similar technique, DRb - Distributed Ruby. It is built into the Ruby core language. It provides a way to share data objects over the wire. As we will see, it takes only a few lines, perfectly writable even from the vi editor.

Now, let's inspect the supply chain.

bean_context =
      {
        'java.naming.factory.initial'      => 'com.evermind.server.rmi.RMIInitialContextFactory',
        'java.naming.security.principal'   => security_principal,
        'java.naming.security.credentials' => security_credentials,
        'java.naming.provider.url'         => provider_url
      }
This is the Brazil Bean exporter who has the brew I like. His contact is found by jndi_name from the @context. Home represents my national office who will be creating me this @stub guy who actually does the delivery of my order.
@context = InitialContext.new(bean_context)
  @home = @context.lookup(jndi_name)
  @stub = @home.create
EJB home is an object that implements the create() method for requesting the remote EJB and returning the stub object that acts as the EJB interface. It acts a bit like a database table model.

Let's say we want to know more of the company..

@stub.companyID
  => "430146"

  @stub.companyName
  => "Brazil Bean Provider"
Mmmh. So let's make an order..
@order = @stub.createOrder(uid,"Coffea arabica, 1 kg sample")
  => #<#:0x62ee558f @java_object=BBPServices stateless session>  
Ah! It returned an object! One important aspect of the dynamic nature of Ruby (and thus JRuby) is that the callable methods need not be specified beforehand. The method call to the Ruby object is dispatched to the EJB, the return value as well and if possible, JRuby casts it to Ruby native.
@order.items
  => ["Coffea arabica, 1 kg sample"]
This could be usable in Rails, but the architecture should allow dynamic translation of method calls so that the solution would have the most leverage and also to stay clean out of implementation details. Ruby has the sort of inner beauty that is capable of this.

method_missing() is a powerful Ruby kernel method, which has its counterpart in Python and Lisp, possibly other dynamic languages are growing into that direction too. Unless you are not familiar with method_missing(), I will explain it so that when Ruby calls a method on the EjbObject's instance (there is this @stub), and the Ruby object does not find the method, it calls method_missing, and here the call is redirected to the @stub, alas the EJB interface and along the network over TCP/IP. In other words, Ruby does not care what kind of EJB it gets.

This is the core of EjbObject class:

class EjbObject
    def context_environment
      {
        'java.naming.factory.initial'      => 'com.evermind.server.rmi.RMIInitialContextFactory',
        'java.naming.security.principal'   => security_principal,
        'java.naming.security.credentials' => security_credentials,
        'java.naming.provider.url'         => provider_url
      }
    end

    def initialize
      @context = InitialContext.new(context_environment)
      @home = @context.lookup(jndi_name)
      @stub = @home.create
    end

    def method_missing(method, *args, &block)
      @stub.send(method, *args, &block)
    end
  end
EjbObject is used by subclassing it:
class MyEJB < EjbObject
    set_provider_url 'rmi://....'
  end

And so, this essentially is the JRuby engine in ejb2rb. The solution wouldn't be complete without the Rails counterpart, ActiveEJB. Conceptually DRb and RMI are very similar.

Ok - even if the code didn't speak to you, think it this way - now JRuby can talk to the remote Java beans, call their methods, and use the return values as other objects that have methods. Some object classes are mapped directly to corresponding Ruby classes, such as Strings, Arrays and Fixnums. The Java-cast beatnik flower child JRuby can talk enterprise jargon. The EJBDispatcher::Instance enables him to open a channel to one EJB for other Ruby VMs that are equally valuable as Ruby implementations but have not developed their Java-fu.

This is how the EJB stub object is shared for DRb clients (the thread is started later by Hydra):

module EJBDispatcher
    class Instance

      self.config = {
        'hostname' => 'localhost',
        'port'     => '9876',
        'class'    => 'MyEJB'
      }

      def initialize
        @uri = "druby://%s:%s" % [config['hostname'],config['port']]
        DRb.start_service(@uri, Kernel.const_get(config['class']).new)
        return DRb.thread
      end
    end
  end
What happens on the Ruby end?
module ActiveEJB
    class Entity < DRb::DRbObject
      def initialize
        uri = 'druby://%s:%i' % [drb_server,drb_port]
        super(nil,uri)
      end
    end
  end
ActiveEJB::Entity is used by subclassing it:
class MyEJB < ActiveEJB::Entity
    include Singleton

    set_drb_server 'localhost'
    set_drb_port   '9876'
  end

So, in the end, you can use this in native MRI Ruby Rails:

profile = MyEJB.getUserProfile(@username, "PDS")

  contacts = MyEJB2.getCountryContacts(profile.getAddress().getCountry())
  
  contacts.each do |contact|
    ...
  end
Or something .. usually more or less involving enterprise business logic.. The actual implementation can handle multiple concurrent EJB instances.

But, in the end, if we look at the power and sheer expressfulness of Ruby, I think this is a fine example of it working to solve a real world problem. The source code is available to help rubyists with the leverage this technology may give them trying to survive under the serviance of J2EE.

Oh, yes, the order:

@order.delivery.weight
  => 1.108

  BrewerEJB.makeCoffee(
    @order.delivery,
    :espresso,
    :milk => true,
    :sugar => false)

January 23, 2010

Mathematical discourse on the web

Consider explaining mathematics on the web for someone. The tools to use are quite nifty. Algebra needs distinguishable symbols, geometry some other control methods. Even simple formulas are not so simple: I have a friend who recommended I should try to mix MathFlow with webMathematica and offered me a developer platform. This post is not so much as on the display of formulas as it is about my personal experience of mathematical expression on the web. Mathematica feels like a nice language. I had help for learning it from an experienced notebook / jsp writer, another friend. With his teaching I could quickly learn the essentials constructs of Mathematica's functional style to do simple experimentation and mix it in jsp. WebMathematica3 is a Java servlet package with the necessary backend kernel connectivity and a taglib for the developer. Worked out-of-the-box on OSX – Linux server requires 1 extra step for Xvnc. The taglib is quite usable, with three basic types of components: Manipulate is not quite as swift as it is in native Mathematica. The image does not follow the slider before the click is released. The network and server would be stressed for serving many concurrent users..

MathFlow is an input mechanism to essentially decrease the learning curve to input mathematical notation into the web. It is a Java applet that seems to work on all major OSes given that the moon is in correct orientation and system Java has not crucially changed. Icedtea6 Java plugin on Ubuntu worked too. MathFlow is proprietary software, this was an evaluation license. To be able to test it on a private server so that clients other than localhost can see it, was possible by recompiling the jar with a custom evaluation license. I could not find any open source alternatives, and this software seems capable of doing the job right now. Ideally, modern-day alternative could be written in JavaScript.. maybe compatible with MathJax..

The output formula is in MathML, and it can be captured to webMathematica input, in JavaScript, using for example the MooTools toolkit to do an XHR and update the page:

var mml = document.SampleSimpleEditorApplet.getMathML();
   params = 'fun='+URLescape(mml);
   var req = new Request.HTML({
     method: 'post',
     url: '_action.jsp?'+params,
     encoding: 'iso8859-15',
     onRequest: function() {},
     update: $('div.output'),
     onComplete: function(response) {}
   }).send();


This would send the contents of the editor applet to _action.jsp in request parameter fun, and the XHR would update the page. This _action.jsp in webMathematica could..
<%@ page contentType="text/xml"%>
<%@ taglib uri="http://www.wolfram.com/msp" prefix="msp" %>

<msp:evaluate>
  MSPFormat[
    MSPToExpression[$$fun],
    TraditionalForm
    ]
</msp:evaluate>
.. generate an image of the formula in traditional mathematical notation. Notice the $$fun variable, which is parsed by the webMathematica backend. In case where the formula has variables, it is possible to parse it in the "delayed" form:
SetDelayed[
    f[x_],
    Evaluate[
      MSPToExpression[
        $$fun,
        MathMLForm
      ]
    ]
  ];
Or plot it, notice the use of MSPBlock ..
MSPBlock[
    {$fun},
    MSPShow[
      Plot[
  
        $fun,
        {x, -2*Pi, 2*Pi},
        ImageSize->{600,500}

      ]]]

So you can build all sorts of elaborate user interfaces on top of these building blocks. This is just an example of plotting the user input formula. He shouldn't need to learn LaTeX or any other new notation to input the mathematics into the computer.

The mathematica magician can work with the Wolfram Workbench to write Mathematica code, and still work in a familiar notebook environment.

The web developer has a similar view to produce the 3D applet, where the MSPLive3D module creates the HTML code for the Java applet.
Needs["Talo3D`"];

...

  MSPLive3D[
    Graphics3D[
     {
      RGBColor[0, 0, 1],
      Thickness[0.005],
      Map[Line, house]
     },
     Boxed -> False
    ]
  ]

This is LiveGraphics3D generated by webMathematica3 on Safari. The house is rotatible. =) The original .nb was cc'd to me by Jyrki Kajala a few years ago. Quite recently he taught me about Mathematica packages, and .m files, and how the notebook can load the package. The package can now be subjected to functional testing and also included to webMathematica JSP. The tools have a certain good feel of dynamicity. Some issues, here and there, but it would be very interesting to build various use scenarios ..

May 7, 2009

.vimrc + Python indentation

I had two separate projects (vcpynet-client and MXManager) which belong together. MXManager is a GUI in PyQt4 for vcpynet-client (which is now renamed to mx-download). That is worth another post. I needed to re-indent the two codes to have the same indentation style. In Ruby I tend to use 2 spaces. In Python it feels a bit more natural to use 4 spaces. These files used both styles which is ok as long as the indentation is strict in each separate file. Re-indenting in Vim should be simple. I defined these in my .vimrc:
set tabstop=4
set softtabstop=4
set shiftwidth=4
set shiftround
set expandtab
set autoindent
set paste
Vim re-indents the file in normal mode by ”gg=G”. Whoops, didn't work on my files. Guess I need to be more strict. I break some lines in a bit unorthodox fashion but Python 2.5 seems to accept it. Vim doesn't. Sed accomplised it, so for the record:
sed -i 's/\ \ /\ \ \ \ /g' 

April 2, 2009

Streaming from webcam

A little while ago I purchased a cheap webcam: Logitech QuickCam E3500. It works in Linux with the in-kernel 'uvcvideo' driver (plug-and-play) and I was interested to tinker with live video stream. It is very simple to view (a) or record (b) a video stream;
(a)  mplayer tv://
 (b)  mencoder -quiet tv:// -tv noaudio -ovc lavc -o "webcam-$(date "+%Y%m%d %H:%M").avi"
Streaming live video to the internet is a bit more complicated. At first I wanted to use FlowPlayer, a neat Flash program that has elaborate JavaScript controls, to view the stream using RTMP stream, which is a proprietary protocol. Setting up a RTMP server on the other hand seemed to be impossoble to setup in the time that I was going to invest. There seemed to be only few options; the Apple Darwin Streaming Server and Red5. In short, Darwin did not compile and Red5 was way too much work to configure. Away with RTMP - behold, VLC to the rescue!
vlc -I dummy --no-audio --no-sout-audio v4l2:///dev/video0:width=320:height=240 \
    --sout='#transcode{venc=ffmpeg,vcodec=x264,vb=256,vt=128}:std{access=mmsh,mux=asfh,dst=:8080/stream.asf}'
MMS, WTF?! A deprecated proprietary protocol and ASF container! Oh well, this was the first (and worst) simple streaming method I came across, and thought it would be worth a try. This seems to be a popular way of doing HTML embedded video. My internet connection is slow so I opted for the x264 codec, which by the way, is not supported by IE or WMP, which kind of cancels out the theoretical advantage of MMS that is works on the regular Windows user. With Firefox + VLC Mozilla plugin this seems to actually work. IE users can display the stream in VLC.
<OBJECT ID="MediaPlayer" WIDTH="640" HEIGHT="480"
    CLASSID="CLSID:22D6f312-B0F6-11D0-94AB-0080C74C7E95"
    STANDBY="Loading Windows Media Player components..."
    TYPE="application/x-oleobject"
    CODEBASE="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,7,1112">
    <PARAM name="autoStart" value="True">
    <PARAM name='showControls' value="False">
    <PARAM name="filename" value="mms://:8080/stream.asf">
    <EMBED TYPE="application/x-mplayer2"
        SRC="mmsh://:8080/stream.asf"
        NAME="MediaPlayer"
        WIDTH=640
        HEIGHT=480>
    </EMBED>
  </OBJECT>

March 25, 2009

Hacking MFserver

The Maximum T-8000 PVR is an interesting device; it is a consumer-grade product and comes with a custom Linux OS. Marusÿs is the proprietor of the server's source code (which I believe they can, as it uses libupnp, which is licensed under BSD), but they offer it for download. The server (version 0.0.1) needed some patching to compile on GCC 4. The fixes were relatively simple. The major problem was that VLC-0.9 does no longer accept EXTVLCOPTS in playlists, and so far MFserver had relied on this. Fortunately VLC has a powerful way to chain up the needed transcode and networking modules from a single command, so I got it working by defining a few class variables and using sprintf() to contruct the VLC command. This means I can open the MFclient on the television screen, browse the server's video collection with the remote, and select a title to play on the TV. The PVR receives MPEG2 TS stream, such as in DVB broadcasts. I had a couple of test videos; a) DVB recordings from the PVR itself (ts) and from Kaffeine (m2t) b) Youtube videos (flv) c) YLE videos (wmv) d) DVD container units (?) (vob) e) random AVIs from the internet Videos that were recorded on the PVR, transferred to a PC, and streamed back without transcoding provided expectedly the best result, in almost no skipping in audio or video. There should be no loss in the video or audio quality. The Youtube videos seem to generally work quite reasonably. Some videos have low bitrates and it is obvious on the TV screen. Some of the random AVIs pulled from the internet worked very well, others did not work at all. I haven't yet got any picture from Kaffeine recordings. After some experimenting I figured the DVB recordings should not be transcoded. FFmpeg does seem to do ”the wrong thing” when it is asked to transcode from MPEG2 to MPEG2, and actually does demux and re-encode! The transcode options should be set by MFserver and be based on the video file suffix. In Ruby this would be as simple as:
transcode = 
    case filename[/\.([^\.]+)$/,1]
    when 'ts'
      ''
    else
      'transcode{vcodec=mp2v,acodec=mpga,.....'
    end
However, MFserver is written in C (although the file suffix is .cpp). I haven't touched C in years. Since then I have learned to do some programming on Java, Bash, Perl, Ruby, JavaScript and Python (in that chronological order). These are high level, (mostly) object oriented languages. Now, I had to face char[], *char and the paradigm shift from higher level abstractions to byte-level processing of an array, trying to remember how pointers work and what happens when I return a local variable and so on. There was an option to switch to C++ and use the String class without including any additional headers but I was intrigued by solving this in C. After three hours of intense reading and experimenting with a simple testing script, I had a function that parsed the suffix from the filename *char.
void VLCMgr::parseSuffix(char *filename)
{
       char _suffix[5] = "";
       int len = strlen(filename);
       int i=0;
       int seek = len-6;
       int dotreached=0;
       // get suffix
       for ( ; seek <= len ; seek++) {
               // separator . not reached
               if ((filename[seek]=='.') && strlen(_suffix)==0) 
               {
                       dotreached=1;
                       _suffix[i] = filename[seek]; // this will be overwritten
               }
               else if ((dotreached==1) && strlen(_suffix)!=0)
               {
                       // then do not add dots
                       if (filename[seek]!='.')
                       {
                               _suffix[i] = filename[seek];
                               i++;
                       }
               }
       }
       filename[i-1]='\0'; // mark the end of suffix string
       strncpy(filename,_suffix,5);
}
That's a lot of work just to get such a simple task done. Remember the Ruby equivalent was
filename[/\.([^\.]+)$/,1]
It makes me even more amazed how people can program whole operating systems and desktop environments with this language. I also dug up example sources of socket communication and merged them in to send remote control commands to VLC's remote control interface that was opened on a TCP socket. This provided to be somewhat tricky but now the commands pause, faster and slower are sent to the VLC socket. However the speeding up function does not seem to work while transcoding. This is an ongoing project and I'll post updates and the patches later, when I get a reasonable set of functionality finished.

October 15, 2008

jdbcpostgres-adapter and the numeric datatype

Vanilla Ruby with the postgres-pr adapter stores the 'numeric' datatype to BigDecimal. Unlike expected, the column has to explicitly define 'precision' and 'scale' when used in JRuby with the JDBC adapter, otherwise the scale is assumed to be 0 and all decimals are dropped. I have a column 'weight' in a table, in the original migration:

t.column :weight, :decimal, :null => false

This was corrected with the migration:
def self.up
  change_column :weights, :weight, :decimal, :null => false, :precision => 4, :scale => 1
end

def self.down
  change_column :weights, :weight, :decimal, :null => false
end