Tuesday, 16 October 2012

Getting started with liftweb framework


Required 
Java
maven2 or sbt
jetty - a Java servlet engine
scala

STEP 1 Install Java and configure PATH
http://www.oracle.com/technetwork/java/javase/downloads/jdk7u9-downloads-1859576.html

STEP 2 Install scala 2.9.2
Download scala from http://www.scala-lang.org/downloads

$ wget  http://www.scala-lang.org/files/archive/scala-2.9.2.tgz

$ sudo mkdir /opt/scala292
Open the dowloaded file (Archive manager - file-roller) and extract to /opt/scala/

Create a sybolic link (future proof the install):
$ ln -s /opt/scala/scala-2.9.2 /opt/scala292/current

Define environment variable SCALA_HOME by editing /etc/profile and adding the line:
export SCALA_HOME=/opt/scala292/current

Add the Scala executables to your path by editing /etc/profile and adding the line:
export PATH=$PATH:$SCALA_HOME/bin

restart computer, and enter command
scala -version
Scala code runner version 2.9.2  -- Copyright 2002-2011, LAMP/EPFL


STEP 3 Install maven
$ sudo apt-get install maven2

OR
Download maven from http://maven.apache.org/download.html and configure PATH.
(mine /etc/profile is)

JAVA_HOME=/usr/java/jdk1.7.0; export JAVA_HOME
PATH=$JAVA_HOME/bin:$PATH; export PATH
export PATH=$PATH:/home/prayag/apache-maven-3.0.4/bin


STEP 4 Install jetty, an HTTP server, HTTP client, and javax.servlet container
$ sudo apt-get install jetty


STEP 5 Create liftweb app with mvn
$ mkdir /home/prayag/workspace_lift
$ cd /home/prayag/workspace_lift

Issue the following maven2 command for a lift project template downloaded from http://scala-tools.org/repo-snapshots :

mvn archetype:generate \
 -DarchetypeGroupId=net.liftweb \
 -DarchetypeArtifactId=lift-archetype-basic_2.9.1 \
 -DarchetypeVersion=2.4-M5 \
 -DarchetypeRepository=http://scala-tools.org/repo-releases \
 -DremoteRepositories=http://scala-tools.org/repo-releases \
 -DgroupId=com.zam.gwitter \
 -DartifactId=gwitter \
 -Dversion=1.0

The architecture of app will be as follows :

5 - A) The dependencies in pom.xml will be as follows :
<repositories>
    <repository>
      <id>scala-tools.releases</id>
      <name>Scala-Tools Dependencies Repository for Releases</name>
      <url>http://scala-tools.org/repo-releases</url>
    </repository>
    <repository>
      <id>java.net.maven2</id>
      <name>java.net Maven2 Repository</name>
      <url>http://download.java.net/maven/2/</url>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>scala-tools.releases</id>
      <name>Scala-Tools Plugins Repository for Releases</name>
      <url>http://scala-tools.org/repo-releases</url>
    </pluginRepository>
  </pluginRepositories>

  <dependencies>
    <dependency>
      <groupId>net.liftweb</groupId>
      <artifactId>lift-mapper_2.9.1</artifactId>
      <version>2.4-M5</version>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>0.9.26</version>
    </dependency>
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <version>1.2.138</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.7</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.scala-tools.testing</groupId>
      <artifactId>specs_2.9.1</artifactId>
      <version>1.6.9</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mortbay.jetty</groupId>
      <artifactId>jetty</artifactId>
      <version>6.1.25</version>
      <scope>test</scope>
    </dependency>
    <!-- for LiftConsole -->
    <dependency>
      <groupId>org.scala-lang</groupId>
      <artifactId>scala-compiler</artifactId>
      <version>${scala.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

5 - B) The gwitter/src/main/webapp/WEB-INF/web.xml file will be as follows :
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<filter>
  <filter-name>LiftFilter</filter-name>
  <display-name>Lift Filter</display-name>
  <description>The Filter that intercepts lift calls</description>
  <filter-class>net.liftweb.http.LiftFilter</filter-class>
</filter>
   

<filter-mapping>
  <filter-name>LiftFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

</web-app>


5 - C) The gwitter/src/main/webapp/index.html will be as follows :
<div class="lift:surround?with=default;at=content">
  <h2>Welcome to your project!</h2>
  <p>
    <div class="lift:helloWorld.howdy">
      Welcome to gwitter at <span id="time">The current time</span>
    </div>
  </p>
</div>



5 - D) The com/zam/gwitter/model/User.scala will be as follows :
package com.zam.gwitter {
package model {

import _root_.net.liftweb.mapper._
import _root_.net.liftweb.util._
import _root_.net.liftweb.common._

/**
 * The singleton that has methods for accessing the database
 */
object User extends User with MetaMegaProtoUser[User] {
  override def dbTableName = "User" // define the DB table name
  override def screenWrap = Full(<lift:surround with="default" at="content">
          <lift:bind /></lift:surround>)
  // define the order fields will appear in forms and output
  override def fieldOrder = List(id, firstName, lastName, email,
  locale, timezone, password, textArea)

  // comment this line out to require email validations
  override def skipEmailValidation = true
}

/**
 * An O-R mapped "User" class that includes first name, last name, password and we add a "Personal Essay" to it
 */
class User extends MegaProtoUser[User] {
  def getSingleton = User // what's the "meta" server

  // define an additional field for a personal essay
  object textArea extends MappedTextarea(this, 2048) {
    override def textareaRows  = 10
    override def textareaCols = 50
    override def displayName = "Personal Essay"
  }
}
}
}

5 - E)  The com/zam/gwitter/snippet/HelloWorld.scala snippet will be as follows:
package com.zam.gwitter {
package snippet {

import _root_.scala.xml.{NodeSeq, Text}
import _root_.net.liftweb.util._
import _root_.net.liftweb.common._
import _root_.java.util.Date
import com.zam.gwitter.lib._
import Helpers._

class HelloWorld {
  lazy val date: Box[Date] = DependencyFactory.inject[Date] // inject the date

  // bind the date into the element with id "time"
  def howdy = "#time *" #> date.map(_.toString)

  /*
   lazy val date: Date = DependencyFactory.time.vend // create the date via factory

   def howdy = "#time *" #> date.toString
   */
}//end of class
}
}

5 - F)  The com/zam/gwitter/lib/DependencyFactory.scala will be as follows :
package com.zam.gwitter {
package lib {

import net.liftweb._
import http._
import util._
import common._
import _root_.java.util.Date

/**
 * A factory for generating new instances of Date.  You can create
 * factories for each kind of thing you want to vend in your application.
 * An example is a payment gateway.  You can change the default implementation,
 * or override the default implementation on a session, request or current call
 * stack basis.
 */
object DependencyFactory extends Factory {
  implicit object time extends FactoryMaker(Helpers.now _)

  /**
   * objects in Scala are lazily created.  The init()
   * method creates a List of all the objects.  This
   * results in all the objects getting initialized and
   * registering their types with the dependency injector
   */
  private def init() {
    List(time)
  }
  init()
}

/*
/**
 * Examples of changing the implementation
 */
sealed abstract class Changer {
  def changeDefaultImplementation() {
    DependencyFactory.time.default.set(() => new Date())
  }

  def changeSessionImplementation() {
    DependencyFactory.time.session.set(() => new Date())
  }

  def changeRequestImplementation() {
    DependencyFactory.time.request.set(() => new Date())
  }

  def changeJustForCall(d: Date) {
    DependencyFactory.time.doWith(d) {
      // perform some calculations here
    }
  }
}
*/
}
}


STEP 6 Run a liftweb app
Issue mvn jetty:run and access the web application in your browser via http://localhost:8080

STEP 7 RESULT





REFERENCES
1 - Lift + Scala, Installation + First contact, 11. AUGUST 2010 available at http://tuxpool.blogspot.com/2010/08/lifting-scala-installation-first.html

2 - Using Maven, available at https://www.assembla.com/wiki/show/liftweb/Using_Maven

Monday, 15 October 2012

Configuring Doctrine ORM with PHP

I needed to configure Doctrine ORM with php. Tried first with CI framework some nights , but it felt like pain in the ass. In the end I started up configuring Doctrine ,Gedmo behavioral Extension with core php.

[STEP 1] Download Doctrine from github
After downloading doctrine orm, i put it under TGCore/app/thirdparty package.
(TGCore is the root folder of my app.)

[STEP 2] Creating Model /app/models/Country.php

<?php
namespace models;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
 * @ORM\Entity(repositoryClass="models\repository\CountryRepository")
 * @ORM\Table(name="Country")
 *
 */
class Country{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue
*/
public $id;

/**
* @ORM\Column(type="string", length=255, nullable=false)
*/
public $name;

/**
* @ORM\Column(type="string", length=255)
*/
public $description;

/**
* @var datetime $created
*
* @Gedmo\Timestampable(on="create")
* @ORM\Column(type="datetime")
*/
public $created;

/**
* @ORM\OneToMany(targetEntity="models\City",mappedBy="country")
*/
public $cities;

/**
* @ORM\Column(type="boolean")
*/
public $active;

public function __construct(){
    $this->id_type = new ArrayCollection();
    }
}



[STEP 3] Configuring Doctrine - /app/config/config.php


<?php
use Doctrine\Common\ClassLoader,
Doctrine\ORM\Configuration,
Doctrine\ORM\EntityManager,
Doctrine\Common\Cache\ArrayCache,
Doctrine\Common\Annotations\AnnotationReader,
Doctrine\ORM\Mapping\Driver\AnnotationDriver,
Doctrine\DBAL\Logging\EchoSqlLogger,
Doctrine\DBAL\Event\Listeners\MysqlSessionInit,
Doctrine\ORM\Tools\SchemaTool,
Doctrine\ORM\Tools\Setup,
Doctrine\Common\EventManager,
Gedmo\Timestampable\TimestampableListener,
Gedmo\Sluggable\SluggableListener,
Gedmo\Tree\TreeListener,
Gedmo\SoftDeleteable\SoftDeleteableListener,
Gedmo\Loggable\LoggableListener;

include_once(dirname(__FILE__) . '/database.php');
include_once 'app/thirdparty/Doctrine/Common/ClassLoader.php';
include_once 'app/thirdparty/Doctrine/ORM/Tools/Setup.php';

$APP_NAME = "TG";
if($_SERVER['HTTP_HOST'] == "localhost"){
$_CONFIG['base_url'] = "http://localhost/{$APP_NAME}/";
   $_CONFIG['base_path'] = $_SERVER['DOCUMENT_ROOT'] . "/{$APP_NAME}/";
}else{
$_CONFIG['base_url'] = "http://localhost/{$APP_NAME}/";
   $_CONFIG['base_path'] = $_SERVER['DOCUMENT_ROOT'] . "/{$APP_NAME}/";
}

define('ROOT_HOST', $_CONFIG['base_url']);
define('ROOT_DIR', $_CONFIG['base_path']);

/*********** Define the values *********/
define("HOSTNAME", $db['hostname']);
define("USERNAME", $db['username']);
define("PASSWORD", $db['password']);
define("DATABASE", $db['database']);
define("BASE_URL", ROOT_HOST);


$application_folder = 'app';
define('APPPATH', ROOT_DIR.$application_folder.'/');

define('EXT', '.php');

/**
 *
 * @var Doctrine\ORM\EntityManager
 */
$em = null;

/*bootstrapping doctrine*/
// Set up class loading
$doctrineClassLoader = new ClassLoader('Doctrine',  APPPATH.'thirdparty');
$doctrineClassLoader->register();

// Setting up Gedmo
$classLoader = new ClassLoader('Gedmo', APPPATH.'thirdparty');
$classLoader->register();

// Setting up custom extensions
$zExtensionsLoader = new ClassLoader('zamoon', APPPATH.'thirdparty');
$zExtensionsLoader->register();

// Setting up models loading
$entitiesClassLoader = new ClassLoader('models', APPPATH);
$entitiesClassLoader->register();

$proxiesClassLoader = new ClassLoader('Proxies', APPPATH.'models/proxies');
$proxiesClassLoader->register();

//print ("ensure standard doctrine annotations are registered<br/>");
Doctrine\Common\Annotations\AnnotationRegistry::registerFile(APPPATH.'thirdparty/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');

// print("Set up caches<br/>");
$ormConfig = new Doctrine\ORM\Configuration;
$arratyCache = new Doctrine\Common\Cache\ArrayCache;

$ormConfig->setMetadataCacheImpl($arratyCache);
$driverImpl = $ormConfig->newDefaultAnnotationDriver(array(APPPATH.'models/'));
$ormConfig->setMetadataDriverImpl($driverImpl);
$ormConfig->setQueryCacheImpl($arratyCache);

$ormConfig->setQueryCacheImpl($arratyCache);

// print("ORM Proxy configuration");
$ormConfig->setProxyDir(APPPATH.'/models/proxies');
$ormConfig->setProxyNamespace('Proxies');
$ormConfig->setAutoGenerateProxyClasses(TRUE); // this can be based on production config.

$evm = new Doctrine\Common\EventManager();

//print("gedmo extension listeners");
// sluggable
$sluggableListener = new Gedmo\Sluggable\SluggableListener;
// you should set the used annotation reader to listener, to avoid creating new one for mapping drivers
$sluggableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($sluggableListener);

//loggable
$loggableListener = new Gedmo\Loggable\LoggableListener;
$loggableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($loggableListener);


// timestampable
$timestampableListener = new Gedmo\Timestampable\TimestampableListener;
$timestampableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($timestampableListener);


//soft delete
$softdeletelistener = new Gedmo\SoftDeleteable\SoftDeleteableListener;
$softdeletelistener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($softdeletelistener);

//setup soft delete filter
$ormConfig->addFilter('soft-deleteable', 'Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter');

// Database connection information
$connectionOptions = array(
        'driver' => 'pdo_mysql',
        'user' =>     "root",
        'password' => "mysql",
        'host' =>     "localhost",
        'dbname' =>   "TG"
);
//central access point to ORM functionality.
$em = EntityManager::create($connectionOptions, $ormConfig, $evm);
//create/drop/update database schemas based on  <tt>ClassMetadata</tt> class descriptors.
$tool = new SchemaTool($em);
if($em){
//ORM metadata descriptor for a class.
$schemas = array(
                                                $em->getClassMetadata('models\Country')
                                             );

}
//Create the databaseschema for the given array of ClassMetadata instances.
$tool->createSchema($this->schemas);
/* End of file config.php */
/* Location: ./app/config/config.php */


ERROR
Fatal error: Uncaught exception 'Doctrine\ORM\Mapping\MappingException' with message 'Class models\Country is not a valid entity or mapped super class.' in /var/www/TGCore/app/thirdparty/Doctrine/ORM/Mapping/MappingException.php:147
Stack trace:
#0 /var/www/TGCore/app/thirdparty/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php(165): Doctrine\ORM\Mapping\MappingException::classIsNotAValidEntityOrMappedSuperClass('models\Country')
#1 /var/www/TGCore/app/thirdparty/Doctrine/ORM/Mapping/ClassMetadataFactory.php(293): Doctrine\ORM\Mapping\Driver\AnnotationDriver->loadMetadataForClass('models\Country', Object(Doctrine\ORM\Mapping\ClassMetadata))
#2 /var/www/TGCore/app/thirdparty/Doctrine/ORM/Mapping/ClassMetadataFactory.php(178): Doctrine\ORM\Mapping\ClassMetadataFactory->loadMetadata('models\Country')
#3 /var/www/TGCore/app/thirdparty/Doctrine/ORM/EntityManager.php(269): Doctrine\ORM\Mapping\ClassMetadataFactory->getMetadataFor('models\Country')
#4 /var/www/TGCore/app/config/deve in /var/www/TGCore/app/thirdparty/Doctrine/ORM/Mapping/MappingException.php on line 147








HACK

1 - Debugging Doctrine/ORM/EntityManager.php#getClassMetadata($className)
   /**
     * Returns the ORM metadata descriptor for a class.
     *
     * The class name must be the fully-qualified class name without a leading backslash
     * (as it is returned by get_class($obj)) or an aliased class name.
     *
     * Examples:
     * TGCore\app\models\Country
     * sales:PriceRequest
     *
     * @return \Doctrine\ORM\Mapping\ClassMetadata
     * @internal Performance-sensitive method.
     */
    public function getClassMetadata($className){
        return $this->metadataFactory->getMetadataFor($className);
    }


2 - Debugging Doctrine/ORM/Mapping/ClassMetadataFactory.php#getMetadataFor($className) - not available in Doctrine2 (I guess)


/**
     * Gets the class metadata descriptor for a class.
     *
     * @param string $className The name of the class.
     * @return \Doctrine\ORM\Mapping\ClassMetadata
     */
    public function getMetadataFor($className){
        if ( ! isset($this->loadedMetadata[$className])) {
            $realClassName = $className;

            // Check for namespace alias
            if (strpos($className, ':') !== false) {
                list($namespaceAlias, $simpleClassName) = explode(':', $className);
                $realClassName = $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName;

                if (isset($this->loadedMetadata[$realClassName])) {
                    // We do not have the alias name in the map, include it
                    $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName];

                    return $this->loadedMetadata[$realClassName];
                }
            }

            if ($this->cacheDriver) {
                if (($cached = $this->cacheDriver->fetch("$realClassName\$CLASSMETADATA")) !== false) {
                    $this->wakeupReflection($cached, $this->getReflectionService());
                    $this->loadedMetadata[$realClassName] = $cached;
                } else {
                    foreach ($this->loadMetadata($realClassName) as $loadedClassName) {
                        $this->cacheDriver->save(
                            "$loadedClassName\$CLASSMETADATA", $this->loadedMetadata[$loadedClassName], null
                        );
                    }
                }
            } else {
                $this->loadMetadata($realClassName);
            }

            if ($className != $realClassName) {
                // We do not have the alias name in the map, include it
                $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName];
            }
        }

        return $this->loadedMetadata[$className];
    }

3 - Doctrine/ORM/Mapping/ClassMetadataFactory.php#loadMetaData($realClassName)

    /**
     * Loads the metadata of the class in question and all it's ancestors whose metadata
     * is still not loaded.
     *
     * @param string $name The name of the class for which the metadata should get loaded.
     * @param array  $tables The metadata collection to which the loaded metadata is added.
     */
    protected function loadMetadata($name){
        if ( ! $this->initialized) {
            $this->initialize();
        }

        $loaded = array();

        $parentClasses = $this->getParentClasses($name);
        $parentClasses[] = $name;

        // Move down the hierarchy of parent classes, starting from the topmost class
        $parent = null;
        $rootEntityFound = false;
        $visited = array();
        foreach ($parentClasses as $className) {
            if (isset($this->loadedMetadata[$className])) {
                $parent = $this->loadedMetadata[$className];
                if ( ! $parent->isMappedSuperclass) {
                    $rootEntityFound = true;
                    array_unshift($visited, $className);
                }
                continue;
            }

            $class = $this->newClassMetadataInstance($className);
            $this->initializeReflection($class, $this->getReflectionService());

            if ($parent) {
                $class->setInheritanceType($parent->inheritanceType);
                $class->setDiscriminatorColumn($parent->discriminatorColumn);
                $class->setIdGeneratorType($parent->generatorType);
                $this->addInheritedFields($class, $parent);
                $this->addInheritedRelations($class, $parent);
                $class->setIdentifier($parent->identifier);
                $class->setVersioned($parent->isVersioned);
                $class->setVersionField($parent->versionField);
                $class->setDiscriminatorMap($parent->discriminatorMap);
                $class->setLifecycleCallbacks($parent->lifecycleCallbacks);
                $class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
                if ($parent->isMappedSuperclass) {
                    $class->setCustomRepositoryClass($parent->customRepositoryClassName);
                }
            }

            // Invoke driver
            try {
                $this->driver->loadMetadataForClass($className, $class);
                //In my case, $class = Doctrine\ORM\Mapping\ClassMetadataInfo@00000000222ef1a300000000bfc98980
            } catch (ReflectionException $e) {
                throw MappingException::reflectionFailure($className, $e);
            }

            // If this class has a parent the id generator strategy is inherited.
            // However this is only true if the hierachy of parents contains the root entity,
            // if it consinsts of mapped superclasses these don't necessarily include the id field.
            if ($parent && $rootEntityFound) {
                if ($parent->isIdGeneratorSequence()) {
                    $class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition);
                } else if ($parent->isIdGeneratorTable()) {
                    $class->getTableGeneratorDefinition($parent->tableGeneratorDefinition);
                }
                if ($parent->generatorType) {
                    $class->setIdGeneratorType($parent->generatorType);
                }
                if ($parent->idGenerator) {
                    $class->setIdGenerator($parent->idGenerator);
                }
            } else {
                $this->completeIdGeneratorMapping($class);
            }

            if ($parent && $parent->isInheritanceTypeSingleTable()) {
                $class->setPrimaryTable($parent->table);
            }

            if ($parent && $parent->containsForeignIdentifier) {
                $class->containsForeignIdentifier = true;
            }

            if ($parent && !empty ($parent->namedQueries)) {
                $this->addInheritedNamedQueries($class, $parent);
            }

            $class->setParentClasses($visited);

            if ($this->evm->hasListeners(Events::loadClassMetadata)) {
                $eventArgs = new \Doctrine\ORM\Event\LoadClassMetadataEventArgs($class, $this->em);
                $this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs);
            }
            $this->wakeupReflection($class, $this->getReflectionService());

            $this->validateRuntimeMetadata($class, $parent);

            $this->loadedMetadata[$className] = $class;

            $parent = $class;

            if ( ! $class->isMappedSuperclass) {
                $rootEntityFound = true;
                array_unshift($visited, $className);
            }

            $loaded[] = $className;
        }

        return $loaded;
    }


4 - Doctrine/ORM/Mapping/Driver/AnnotationDriver.php#loadMetadataForClass($className, ClassMetadataInfo $metadata)

/**
     * {@inheritdoc}
     */
    public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
{
        $class = $metadata->getReflectionClass();
        /* it results as follows for me
           /**
             * @ORM\Entity(repositoryClass="models\repository\CountryRepository")
             * @ORM\Table(name="Country")
             *
             */
             Class [  class models\Country ] {
                  @@ /var/www/TGCore/app/models/Country.php 10-46

                      - Constants [0] {}

                      - Static properties [0] {}

                      - Static methods [0] {}

                      - Properties [6] {
                        Property [  private $id ]
                        Property [  private $name ]
                        Property [  private $description ]
                        Property [  private $created ]
                        Property [  private $cities ]
                        Property [  private $active ]
          }
       */
        if (!$class) {
            // this happens when running annotation driver in combination with
            // static reflection services. This is not the nicest fix
            $class = new \ReflectionClass($metadata->name);
        }
        //problem is with _reader (AnnotationReader) i guess
        $classAnnotations = $this->_reader->getClassAnnotations($class);
        //in my case returning Array ( )
        if ($classAnnotations && is_numeric(key($classAnnotations))) {
            foreach ($classAnnotations as $annot) {
                $classAnnotations[get_class($annot)] = $annot;
            }
        }

        // Evaluate Entity annotation
        //this is where my code goes wrong 
        if (isset($classAnnotations['Doctrine\ORM\Mapping\Entity'])) {
            $entityAnnot = $classAnnotations['Doctrine\ORM\Mapping\Entity'];
            if ($entityAnnot->repositoryClass !== null) {
                $metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
            }
            if ($entityAnnot->readOnly) {
                $metadata->markReadOnly();
            }
        } else if (isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'])) {
            $mappedSuperclassAnnot = $classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'];
            $metadata->setCustomRepositoryClass($mappedSuperclassAnnot->repositoryClass);
            $metadata->isMappedSuperclass = true;
        } else {
            throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
        }

        // Evaluate Table annotation
        if (isset($classAnnotations['Doctrine\ORM\Mapping\Table'])) {
            $tableAnnot = $classAnnotations['Doctrine\ORM\Mapping\Table'];
            $primaryTable = array(
                'name' => $tableAnnot->name,
                'schema' => $tableAnnot->schema
            );

            if ($tableAnnot->indexes !== null) {
                foreach ($tableAnnot->indexes as $indexAnnot) {
                    $index = array('columns' => $indexAnnot->columns);

                    if ( ! empty($indexAnnot->name)) {
                        $primaryTable['indexes'][$indexAnnot->name] = $index;
                    } else {
                        $primaryTable['indexes'][] = $index;
                    }
                }
            }

            if ($tableAnnot->uniqueConstraints !== null) {
                foreach ($tableAnnot->uniqueConstraints as $uniqueConstraintAnnot) {
                    $uniqueConstraint = array('columns' => $uniqueConstraintAnnot->columns);

                    if ( ! empty($uniqueConstraintAnnot->name)) {
                        $primaryTable['uniqueConstraints'][$uniqueConstraintAnnot->name] = $uniqueConstraint;
                    } else {
                        $primaryTable['uniqueConstraints'][] = $uniqueConstraint;
                    }
                }
            }

            $metadata->setPrimaryTable($primaryTable);
        }

        // Evaluate NamedQueries annotation
        if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedQueries'])) {
            $namedQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedQueries'];

            if (!is_array($namedQueriesAnnot->value)) {
                throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
            }

            foreach ($namedQueriesAnnot->value as $namedQuery) {
                if (!($namedQuery instanceof \Doctrine\ORM\Mapping\NamedQuery)) {
                    throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
                }
                $metadata->addNamedQuery(array(
                    'name'  => $namedQuery->name,
                    'query' => $namedQuery->query
                ));
            }
        }

        // Evaluate InheritanceType annotation
        if (isset($classAnnotations['Doctrine\ORM\Mapping\InheritanceType'])) {
            $inheritanceTypeAnnot = $classAnnotations['Doctrine\ORM\Mapping\InheritanceType'];
            $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceTypeAnnot->value));

            if ($metadata->inheritanceType != \Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) {
                // Evaluate DiscriminatorColumn annotation
                if (isset($classAnnotations['Doctrine\ORM\Mapping\DiscriminatorColumn'])) {
                    $discrColumnAnnot = $classAnnotations['Doctrine\ORM\Mapping\DiscriminatorColumn'];
                    $metadata->setDiscriminatorColumn(array(
                        'name' => $discrColumnAnnot->name,
                        'type' => $discrColumnAnnot->type,
                        'length' => $discrColumnAnnot->length
                    ));
                } else {
                    $metadata->setDiscriminatorColumn(array('name' => 'dtype', 'type' => 'string', 'length' => 255));
                }

                // Evaluate DiscriminatorMap annotation
                if (isset($classAnnotations['Doctrine\ORM\Mapping\DiscriminatorMap'])) {
                    $discrMapAnnot = $classAnnotations['Doctrine\ORM\Mapping\DiscriminatorMap'];
                    $metadata->setDiscriminatorMap($discrMapAnnot->value);
                }
            }
        }


        // Evaluate DoctrineChangeTrackingPolicy annotation
        if (isset($classAnnotations['Doctrine\ORM\Mapping\ChangeTrackingPolicy'])) {
            $changeTrackingAnnot = $classAnnotations['Doctrine\ORM\Mapping\ChangeTrackingPolicy'];
            $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' . $changeTrackingAnnot->value));
        }

        // Evaluate annotations on properties/fields
        foreach ($class->getProperties() as $property) {
            if ($metadata->isMappedSuperclass && ! $property->isPrivate()
                ||
                $metadata->isInheritedField($property->name)
                ||
                $metadata->isInheritedAssociation($property->name)) {
                continue;
            }

            $mapping = array();
            $mapping['fieldName'] = $property->getName();

            // Check for JoinColummn/JoinColumns annotations
            $joinColumns = array();

            if ($joinColumnAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumn')) {
                $joinColumns[] = array(
                    'name' => $joinColumnAnnot->name,
                    'referencedColumnName' => $joinColumnAnnot->referencedColumnName,
                    'unique' => $joinColumnAnnot->unique,
                    'nullable' => $joinColumnAnnot->nullable,
                    'onDelete' => $joinColumnAnnot->onDelete,
                    'columnDefinition' => $joinColumnAnnot->columnDefinition,
                );
            } else if ($joinColumnsAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumns')) {
                foreach ($joinColumnsAnnot->value as $joinColumn) {
                    $joinColumns[] = array(
                        'name' => $joinColumn->name,
                        'referencedColumnName' => $joinColumn->referencedColumnName,
                        'unique' => $joinColumn->unique,
                        'nullable' => $joinColumn->nullable,
                        'onDelete' => $joinColumn->onDelete,
                        'columnDefinition' => $joinColumn->columnDefinition,
                    );
                }
            }

            // Field can only be annotated with one of:
            // @Column, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany
            if ($columnAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Column')) {
                if ($columnAnnot->type == null) {
                    throw MappingException::propertyTypeIsRequired($className, $property->getName());
                }

                $mapping['type'] = $columnAnnot->type;
                $mapping['length'] = $columnAnnot->length;
                $mapping['precision'] = $columnAnnot->precision;
                $mapping['scale'] = $columnAnnot->scale;
                $mapping['nullable'] = $columnAnnot->nullable;
                $mapping['unique'] = $columnAnnot->unique;
                if ($columnAnnot->options) {
                    $mapping['options'] = $columnAnnot->options;
                }

                if (isset($columnAnnot->name)) {
                    $mapping['columnName'] = $columnAnnot->name;
                }

                if (isset($columnAnnot->columnDefinition)) {
                    $mapping['columnDefinition'] = $columnAnnot->columnDefinition;
                }

                if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
                    $mapping['id'] = true;
                }

                if ($generatedValueAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\GeneratedValue')) {
                    $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAnnot->strategy));
                }

                if ($versionAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Version')) {
                    $metadata->setVersionMapping($mapping);
                }

                $metadata->mapField($mapping);

                // Check for SequenceGenerator/TableGenerator definition
                if ($seqGeneratorAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\SequenceGenerator')) {
                    $metadata->setSequenceGeneratorDefinition(array(
                        'sequenceName' => $seqGeneratorAnnot->sequenceName,
                        'allocationSize' => $seqGeneratorAnnot->allocationSize,
                        'initialValue' => $seqGeneratorAnnot->initialValue
                    ));
                } else if ($tblGeneratorAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\TableGenerator')) {
                    throw MappingException::tableIdGeneratorNotImplemented($className);
                }
            } else if ($oneToOneAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToOne')) {
                if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
                    $mapping['id'] = true;
                }

                $mapping['targetEntity'] = $oneToOneAnnot->targetEntity;
                $mapping['joinColumns'] = $joinColumns;
                $mapping['mappedBy'] = $oneToOneAnnot->mappedBy;
                $mapping['inversedBy'] = $oneToOneAnnot->inversedBy;
                $mapping['cascade'] = $oneToOneAnnot->cascade;
                $mapping['orphanRemoval'] = $oneToOneAnnot->orphanRemoval;
                $mapping['fetch'] = $this->getFetchMode($className, $oneToOneAnnot->fetch);
                $metadata->mapOneToOne($mapping);
            } else if ($oneToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToMany')) {
                $mapping['mappedBy'] = $oneToManyAnnot->mappedBy;
                $mapping['targetEntity'] = $oneToManyAnnot->targetEntity;
                $mapping['cascade'] = $oneToManyAnnot->cascade;
                $mapping['indexBy'] = $oneToManyAnnot->indexBy;
                $mapping['orphanRemoval'] = $oneToManyAnnot->orphanRemoval;
                $mapping['fetch'] = $this->getFetchMode($className, $oneToManyAnnot->fetch);

                if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
                    $mapping['orderBy'] = $orderByAnnot->value;
                }

                $metadata->mapOneToMany($mapping);
            } else if ($manyToOneAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToOne')) {
                if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
                    $mapping['id'] = true;
                }

                $mapping['joinColumns'] = $joinColumns;
                $mapping['cascade'] = $manyToOneAnnot->cascade;
                $mapping['inversedBy'] = $manyToOneAnnot->inversedBy;
                $mapping['targetEntity'] = $manyToOneAnnot->targetEntity;
                $mapping['fetch'] = $this->getFetchMode($className, $manyToOneAnnot->fetch);
                $metadata->mapManyToOne($mapping);
            } else if ($manyToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToMany')) {
                $joinTable = array();

                if ($joinTableAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinTable')) {
                    $joinTable = array(
                        'name' => $joinTableAnnot->name,
                        'schema' => $joinTableAnnot->schema
                    );

                    foreach ($joinTableAnnot->joinColumns as $joinColumn) {
                        $joinTable['joinColumns'][] = array(
                            'name' => $joinColumn->name,
                            'referencedColumnName' => $joinColumn->referencedColumnName,
                            'unique' => $joinColumn->unique,
                            'nullable' => $joinColumn->nullable,
                            'onDelete' => $joinColumn->onDelete,
                            'columnDefinition' => $joinColumn->columnDefinition,
                        );
                    }

                    foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) {
                        $joinTable['inverseJoinColumns'][] = array(
                            'name' => $joinColumn->name,
                            'referencedColumnName' => $joinColumn->referencedColumnName,
                            'unique' => $joinColumn->unique,
                            'nullable' => $joinColumn->nullable,
                            'onDelete' => $joinColumn->onDelete,
                            'columnDefinition' => $joinColumn->columnDefinition,
                        );
                    }
                }

                $mapping['joinTable'] = $joinTable;
                $mapping['targetEntity'] = $manyToManyAnnot->targetEntity;
                $mapping['mappedBy'] = $manyToManyAnnot->mappedBy;
                $mapping['inversedBy'] = $manyToManyAnnot->inversedBy;
                $mapping['cascade'] = $manyToManyAnnot->cascade;
                $mapping['indexBy'] = $manyToManyAnnot->indexBy;
                $mapping['orphanRemoval'] = $manyToManyAnnot->orphanRemoval;
                $mapping['fetch'] = $this->getFetchMode($className, $manyToManyAnnot->fetch);

                if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
                    $mapping['orderBy'] = $orderByAnnot->value;
                }

                $metadata->mapManyToMany($mapping);
            }
        }

        // Evaluate @HasLifecycleCallbacks annotation
        if (isset($classAnnotations['Doctrine\ORM\Mapping\HasLifecycleCallbacks'])) {
            foreach ($class->getMethods() as $method) {
                // filter for the declaring class only, callbacks from parents will already be registered.
                if ($method->isPublic() && $method->getDeclaringClass()->getName() == $class->name) {
                    $annotations = $this->_reader->getMethodAnnotations($method);

                    if ($annotations && is_numeric(key($annotations))) {
                        foreach ($annotations as $annot) {
                            $annotations[get_class($annot)] = $annot;
                        }
                    }

                    if (isset($annotations['Doctrine\ORM\Mapping\PrePersist'])) {
                        $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::prePersist);
                    }

                    if (isset($annotations['Doctrine\ORM\Mapping\PostPersist'])) {
                        $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postPersist);
                    }

                    if (isset($annotations['Doctrine\ORM\Mapping\PreUpdate'])) {
                        $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preUpdate);
                    }

                    if (isset($annotations['Doctrine\ORM\Mapping\PostUpdate'])) {
                        $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postUpdate);
                    }

                    if (isset($annotations['Doctrine\ORM\Mapping\PreRemove'])) {
                        $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preRemove);
                    }

                    if (isset($annotations['Doctrine\ORM\Mapping\PostRemove'])) {
                        $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postRemove);
                    }

                    if (isset($annotations['Doctrine\ORM\Mapping\PostLoad'])) {
                        $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postLoad);
                    }

                    if (isset($annotations['Doctrine\ORM\Mapping\PreFlush'])) {
                        $metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preFlush);
                    }
                }
            }
        }
    }




SOLUTION
Problem was with AnnotationReader which I forgot to set in /config/config.php.
The final /config/config.php is as following 

<?php
use Doctrine\Common\ClassLoader,
Doctrine\ORM\Configuration,
Doctrine\ORM\EntityManager,
Doctrine\Common\Cache\ArrayCache,
Doctrine\Common\Annotations\AnnotationReader,
Doctrine\ORM\Mapping\Driver\AnnotationDriver,
Doctrine\DBAL\Logging\EchoSqlLogger,
Doctrine\DBAL\Event\Listeners\MysqlSessionInit,
Doctrine\ORM\Tools\SchemaTool,
Doctrine\ORM\Tools\Setup,
Doctrine\Common\EventManager,
Gedmo\Timestampable\TimestampableListener,
Gedmo\Sluggable\SluggableListener,
Gedmo\Tree\TreeListener,
Gedmo\SoftDeleteable\SoftDeleteableListener,
Gedmo\Loggable\LoggableListener;

 include_once(dirname(__FILE__) . '/database.php');
 include_once 'app/thirdparty/Doctrine/Common/ClassLoader.php';
 include_once 'app/thirdparty/Doctrine/ORM/Tools/Setup.php';

 $APP_NAME = "TGCore";
 if($_SERVER['HTTP_HOST'] == "localhost"){
  $_CONFIG['base_url']   = "http://localhost/{$APP_NAME}/";
     $_CONFIG['base_path']   = $_SERVER['DOCUMENT_ROOT'] . "/{$APP_NAME}/";
 }else{
  $_CONFIG['base_url']   = "http://localhost/{$APP_NAME}/";
     $_CONFIG['base_path']   = $_SERVER['DOCUMENT_ROOT'] . "/{$APP_NAME}/";
 }

 define('ROOT_HOST', $_CONFIG['base_url']);
 define('ROOT_DIR', $_CONFIG['base_path']);

 /*********** Define the values *********/
 define("HOSTNAME", $db['hostname']);
 define("USERNAME", $db['username']);
 define("PASSWORD", $db['password']);
 define("DATABASE", $db['database']);
 define("BASE_URL", ROOT_HOST);


 $application_folder = 'app';
 define('APPPATH', ROOT_DIR.$application_folder.'/');

 define('EXT', '.php');

 /**
   *
   * @var Doctrine\ORM\EntityManager
   */
 $em = null;
 /*bootstrapping doctrine*/

 // Set up class loading
 $doctrineClassLoader = new ClassLoader('Doctrine',  APPPATH.'thirdparty');
 $doctrineClassLoader->register();

 // Set up Gedmo
 $classLoader = new ClassLoader('Gedmo', APPPATH.'thirdparty');
 $classLoader->register();

 // Set up zamoon extensions
 $zExtensionsLoader = new ClassLoader('z', APPPATH.'thirdparty');
 $zExtensionsLoader->register();

 // Set up models loading
 $entitiesClassLoader = new ClassLoader('models', APPPATH);
 $entitiesClassLoader->register();

 $isDevMode = true;

 $proxiesClassLoader = new ClassLoader('Proxies', APPPATH.'models/proxies');
 $proxiesClassLoader->register();

  $ormConfig = new Doctrine\ORM\Configuration;
  /*************************************** 1 ******************************************/
  //print ("ensure standard doctrine annotations are registered<br/>");
  Doctrine\Common\Annotations\AnnotationRegistry::registerFile(APPPATH.'thirdparty/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');

  /*************************************** 2 ******************************************/
  // print("Set up caches<br/>");
  $arrayCache = new Doctrine\Common\Cache\ArrayCache;
  $annotationReader = new Doctrine\Common\Annotations\AnnotationReader;
     $cachedAnnotationReader = new Doctrine\Common\Annotations\CachedReader(
      $annotationReader, // use reader
      $arrayCache             // and a cacheDriver
     );

      /*************************************** 3 ******************************************/
     // create a driver chain for metadata reading
     $driverChain = new Doctrine\ORM\Mapping\Driver\DriverChain();

     // load superclass metadata mapping only, into driver chain
     // also registers Gedmo annotations.NOTE: you can personalize it
     Gedmo\DoctrineExtensions::registerAbstractMappingIntoDriverChainORM(
      $driverChain,           // our metadata driver chain, to hook into
      $cachedAnnotationReader // our cached annotation reader
     );

      /*************************************** 4 ******************************************/
  // now we want to register our application entities,
  // for that we need another metadata driver used for Entity namespace
  $annotationDriver = new Doctrine\ORM\Mapping\Driver\AnnotationDriver(
     $cachedAnnotationReader, // our cached annotation reader
     array(APPPATH.'models/') // paths to look in
  );

  /*************************************** 5 ******************************************/
  // NOTE: driver for application Entity can be different, Yaml, Xml or whatever
  // register annotation driver for our application Entity namespace
  $driverChain->addDriver($annotationDriver, 'models');

  /*************************************** 6 ******************************************/
  // print("ORM Proxy configuration");
  $ormConfig->setProxyDir(APPPATH.'/models/proxies');
  $ormConfig->setProxyNamespace('Proxies');
  $ormConfig->setAutoGenerateProxyClasses(TRUE); // this can be based on production config.
  // register metadata driver
  $ormConfig->setMetadataDriverImpl($driverChain);
  // use our allready initialized cache driver
  $ormConfig->setMetadataCacheImpl($arrayCache);
  $ormConfig->setQueryCacheImpl($arrayCache);

  //$driverImpl = $ormConfig->newDefaultAnnotationDriver(array(APPPATH.'models/'));


           /*************************************** 7 ******************************************/

  $evm = new Doctrine\Common\EventManager();

  //print("gedmo extension listeners");
  // sluggable
  $sluggableListener = new Gedmo\Sluggable\SluggableListener;
  // you should set the used annotation reader to listener, to avoid creating new one for mapping drivers
  $sluggableListener->setAnnotationReader($cachedAnnotationReader);
  $evm->addEventSubscriber($sluggableListener);

  //loggable
  $loggableListener = new Gedmo\Loggable\LoggableListener;
  $loggableListener->setAnnotationReader($cachedAnnotationReader);
  $evm->addEventSubscriber($loggableListener);


  // timestampable
  $timestampableListener = new Gedmo\Timestampable\TimestampableListener;
  $timestampableListener->setAnnotationReader($cachedAnnotationReader);
  $evm->addEventSubscriber($timestampableListener);



  //soft delete
  $softdeletelistener = new Gedmo\SoftDeleteable\SoftDeleteableListener;
  $softdeletelistener->setAnnotationReader($cachedAnnotationReader);
  $evm->addEventSubscriber($softdeletelistener);

  //setup soft delete filter
  $ormConfig->addFilter('soft-deleteable', 'Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter');

  // Database connection information
  $connectionOptions = array(
        'driver' => 'pdo_mysql',
        'user' =>     "root",
        'password' => "mysql",
        'host' =>     "localhost",
        'dbname' =>   "TG"
  );
 //central access point to ORM functionality.
  $em = EntityManager::create($connectionOptions, $ormConfig, $evm);
  //create/drop/update database schemas based on  <tt>ClassMetadata</tt> class descriptors.
  $tool = new SchemaTool($em);
  if($em){
   //ORM metadata descriptor for a class.
   $schemas = array(   $em->getClassMetadata('models\Country')
                   );

  }
  //Create the databaseschema for the given array of ClassMetadata instances.
  $tool->createSchema($schemas);
 /* End of file config.php */
 /* Location: ./appl/config/config.php */




REFERENCES
1 - Integrating Doctrine 2 with CodeIgniter 2, available at http://wildlyinaccurate.com/integrating-doctrine-2-with-codeigniter-2

2 - Setting up CodeIgniter 2 with Doctrine 2 the right way, available at http://www.joelverhagen.com/blog/2011/05/setting-up-codeigniter-2-with-doctrine-2-the-right-way/

3 - CodeIgniter-2-with-Doctrine-2, available at https://github.com/iPrayag/CodeIgniter-2-with-Doctrine-2/blob/master/application/libraries/Doctrine.php

4 - Using Doctrine with Code Igniter, available https://github.com/EllisLab/CodeIgniter/wiki/Using-Doctrine-with-Code-Igniter

5- Integrating with CodeIgniter, available at http://docs.doctrine-project.org/en/2.1/cookbook/integrating-with-codeigniter.html

6 - CodeIgniter 2 Doctrine 2 Integration, available at http://searchdaily.net/codeigniter-2-doctrine-2-integration/


Wednesday, 3 October 2012

Understanding GWT Code Splitting

Problem Background
In traditional desktop application like Word Processor, there are so many features of that application that we don’t normally use. For instance, the Mail Merge tool within Word Processor is extremely useful when it's needed, but for others it may not be. So the question is how do we load only the functionality that will be used?

GWT Solution

The solution of GWT for this important issue is a concept which is called Code Splitting. In general, GWT framework provides a mechanism to split our code into segments in a way that each segment will be downloaded only when needed.

GWT.runAsync(RunAsyncCallback callback) is the method for code splitting, which will create a ‘split point’ in the code, and everything beyond that split point will be downloaded only on demand.


eg
HelloCodeSplitting.java


public class HelloCodeSplitting implements EntryPoint {
   public void onModuleLoad() {
      Button b = new Button("Click me", new ClickHandler() {
      public void onClick(ClickEvent event) {

         RunAsyncCallback callback = new RunAsyncCallback() { //#1 Creates callback
             public void onSuccess () { //#2 Defines success handler
                     Window.alert("Hello, AJAX");
        }
         public void onFailure (Throwable reason) { //#3 Defines error handler
                      Window.alert("Code download failed");
       }
       };
        GWT.runAsync(callback); //#4 Loads and executes
   }//end of onclick
  RootPanel.get().add(b);
  }//end of moduleload
}//end of Class


In GWTP
GWTP takes care of calling GWT.runAsync, whenever the corresponding Presenter is shown. But need to use AsyncProvider in the Ginjector .
So, I can achieve the same thing in gwtp framework as follows :

HelloCodeSplittingGinjector.java

@GinModules({ HelloCodeSplittingModule.class })
public interface HelloCodeSplittingGinjector extends Ginjector {
  PlaceManager getPlaceManager();
  EventBus getEventBus();
  AsyncProvider<HelloCodeSplittingPresenter> getHelloCodeSplittingPresenter();
}


HelloCodeSplittingPresenter.java

  @ProxyCodeSplit
  @NameToken("main")
  public interface HelloCodeSplittingProxy extends ProxyPlace<HelloCodeSplittingPresenter> {
  }





References
1 - http://www.javabeat.net/2011/11/code-splitting-in-gwt/

2 - http://stackoverflow.com/questions/8652534/gwtp-code-splitting

3 - http://www.summa-tech.com/blog/2011/05/03/a-pattern-for-gwt-code-splitting/

4 - https://developers.google.com/web-toolkit/doc/latest/DevGuideCodeSplitting#patterns

5 - http://benbracha.wordpress.com/2012/05/04/gwt-code-splitting/

6 - http://jcheng.wordpress.com/2010/02/16/elegant-code-splitting-with-gwt/

7- Doloto: Code Splitting for Network-Bound Web 2.0 Applications,  http://research.microsoft.com/apps/pubs/default.aspx?id=70518