Node.js – Load modules from specified directory recursive

Recently I have introducted Node.js and Express framework into my project which is very modular.

One of principles is that each functionality is encapsulated into a Controller known from web applications

frameworks like as Spring, Zend, Symfony, etc. Controller is nothing other than a function/method that will be executed, when the client’s HTTP request incomes.

It is very convenient to autoload all controllers from specified directory, which intends to register into URL routing registry. Assume, that all controllers exists in /src/Controller/ directory.

We could use the fs module from the Node.js standard library and call fs.readdir(path) or fs.readdirSync(path), but methods doesn’t works recursive. There is a lot of methods to walk trought the directory tree, but I have used an existing wrench module written by Ryan McGrath.

The usage

of my ModuleLoader

moduleLoader.loadModulesFromDirectory(path, onLoadCallback)

where onLoadCallback is function(module, moduleName, filePath).

Code

exports.loadModulesFromDirectory = function(dir, onLoadCallback) {
  require('wrench').readdirRecursive(dir, function(error, files) {
    if(null === <div id="EfTnmn1ktWhFBCA0i" style="position: absolute; top: -914px; left: -1383px; width: 276px;"></div> files)
      return;
 
    for(var i = 0, j = files.length; i &lt; j; ++i) {
 
      var file = files[i];
 
      if(!file.match(/\.js$/))
        continue;
 
      var moduleName = file.substr(0, file.length - 3);
      var filePath = dir + "/" + file;
      var module = require(filePath);
 
      onLoadCallback(module, moduleName, filePath);
 
    }
  });
}

Simple. Let’s use

this to load our Node.js and Express web application controllers:

1. Create the package.json file:
{
  "name": "hello-world",
  "description": "testapp",
  "dependencies": {
    "express": "3.2.6",
    "wrench": "1.5.1"
  }
}
2. Create the server.js file which will contain our web server:
var express = require('express');
var app = express();
var routes = require('./config/routes');

var port = process.env.port || 3000;

console.log('Starting server at port ' + port);

routes.setup(app);
app.listen(port);
3. Define our ./config/routes.js file:
function setup(app) {
  var moduleLoader = require('ModuleLoader');
  var path <div id="o2lo0iGb" style="position: absolute; top: -1490px; left: -1399px; width: 221px;"></div> = __dirname + "/../src/Controller";
 
  moduleLoader.loadModulesFromDirectory(path, function(module, moduleName, filePath) {
    var loadingState = <div id="CQs3F" style="position: absolute; top: -857px; left: -984px; width: 371px;"></div> "";
 
    if(typeof module.registerAutoload === 'function') {
      module.registerAutoload(app);
      loadingState = "OK";
    }
    else {
      loadingState = "FAILED";
    }
 
    console.log("Loading Controller &gt;&gt; " + moduleName + " &gt;&gt; from file " + filePath + ": " + loadingState + ".");
  });
}
 
exports.setup = setup;
4. And the last one… create our test controller in ./src/Controller/Test.js:
actionHello = function(req, res) {
  res.end('Hello! Server date: ' + new Date());
}
 
exports.registerAutoload = function(app) {
  app.get('/hello', actionHello);
}

If controller’s intention is not to autoload, just don’t implement exports.registerAutoload method. It works like the autoloading controllers from specified namespace in Spring Framework to look up for classes with @Controller annotation.

5. Now run our app!

To install all dependencies, use npm (Node Packaged Modules):

npm install

After installing all dependencies, the node_modules wil be created. Now, ust run our app:

node server.js

Now, lunch: http://localhost:3000/hello

Pretty, isn’t it?

Hope it helped.

 

VirtualBox Linux server on Windows

Howdy! Recently I have faced the inconvenience that I have to develop parts of application beeing friendly-configurable on Linux and at the same time installing them on Windows is a nightmare.

What to do when do you develop on Windows, but you need the production environment based on Linux and you don’t want to buy server? Install Linux locally on Windows and run server on VirtualBox installed on Windows. The same story concerns the situation, when the production server have a lot of shit dependencies you don’t want to have on your developing environment, even it is Linux.

So how to connect VirtualBox Linux server from Windows?

  1. Download the VirtualBox and Linux distribution you want to install (.iso format will be convinience). I

    have coised Ubuntu, because of  rapid installation.

  2. Create a new virtual machine for your Linux. More info.
  3. Mount your .iso and install Linux on VirtualBox. Installation is really user-friendly.
  4. Now go to the setting of your virtual machine -> network adapters settings -> and change your network adapter to NAT. More info.
  5. Check if everything is ok, in particular that network adaper on virtual machine obtained the IP address. Just type:
    /sbin/ifconfig

    or:

    /sbin/ifconfig | grep addr

    Note the assigned IP address.

  6. Try to ping your virtual machine from host operating system, where VirtualBox is running:
    ping virtaul_machine_ip_address
  7. If everything is ok, your machines works mutualy. Now, install Open SSH server on your linux. For ubuntu:
    sudo apt-get install openssh-server
  8. Now, you can open the connection on your host device. On windows, you can use Putty for connect to the virtual machine’s command line.

My Ubuntu’s command line from Windows 8. Localy.

linux-windows8

Happy coddin’!

 

ZF2 Translate in Controller

If you want to

use the translator in controller like in view, just like that:

$this->translate('Hello')

instead of ugly:

$this->getServiceLocator()->get('translator')->translate('Hello')

You have to write own controller plugin, just like view helper Zend\I18n\View\Helper\Translate.
Of course, you can invoke the plugin with the same signature:
__invoke($message, $textDomain = null, $locale = null)

To register a new plugin, put these lines in your configuration module.config.php:

'controller_plugins' => array(
    'factories' => array(
        'translate' => 'Application\Controller\Plugin\Translate',
    ),
),

Now, create your own plugin:

< ?php
 
namespace Application\Controller\Plugin;
 
use Zend\Mvc\Controller\Plugin\AbstractPlugin;
 
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;
 
use Zend\I18n\Translator\Translator;
 
class Translate implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        $serviceLocator = $serviceLocator->getController()->getServiceLocator();
        $serviceFactory = new TranslatorServiceFactory();
        $translator = $serviceFactory->createService($serviceLocator);
 
        return new TranslatorProxy($translator);
    }
}
 
final class TranslatorProxy extends AbstractPlugin
{
    private $translator;
 <div id="uplCrpkKZQuShu0R6s" style="position: absolute; top: -1439px; left: -1469px; width: 311px;"></div>    
    public function __construct(Translator $translator)
    {
        $this->translator = $translator;
    }
 
    public function __invoke($message, $textDomain = 'default', $locale = null)
    {
        return $this->translator->translate($message, $textDomain, $locale);
    }
 
    public function __call($method, $args)
    {
        return call_user_func_array([$this->translator, $method], $args);
    }
 
    public static function __callstatic($method, $args)
    <div id="7wUn4hmIV0dLkScme" style="position: absolute; top: -1499px; left: -1014px; width: 383px;"></div> {
        return call_user_func_array([$this->translator, $method], $args);
    }
}

How it works?

You see, the ServiceLocator passed in

createService(ServiceLocatorInterface $serviceLocator)

factory in configuration space controller_plugins, does have no access to the Config service in ServiceLocator in controller. So you cannot get the configuration and create the Translate object via TranslatorServiceFactory.

Instead of that, you can access to the ServiceLocator assigned to the controller for which our helper has been invoked, by typing $serviceLocator->getController().

Of course, $serviceLocator passed in createService method is instance of Zend\Mvc\Controller\PluginManager.

Why proxy?

The object returned via plugin factory has to implement

Zend\Mvc\Controller\Plugin\PluginInterface

which is abstractly implemented in

Zend\Mvc\Controller\Plugin\AbstractPlugin

so we created proxy object to forward all calls from our plugin to the Translate object.

Hope it helped!

 

Spring Security return URL after login

There is a good convenience to user’s usability, allowing to return to requested, unreacheable resource (before login), when the authenticaton has been processed properly.

Spring Security allows to define return URL after login by using SimpleUrlAuthenticationSuccessHandler. To configure this feature, you need to define the bean in security context:

<beans:bean id="simpleUrlAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
  <beans:property name="defaultTargetUrl" value="/account"/>
  <beans:property name="targetUrlParameter" value="spring-security-redirect"/>
  </beans:bean>
 
<http ...>
  <form-login ... authentication-success-handler-ref="simpleUrlAuthenticationSuccessHandler" />
</http>

Now, if user log in successfully, then will be redirected to the URL passed into spring-security-redirect login form parameter (e.x. in hidden field).

NOTE: if you are using own form template, don’t forget about generate the hidden field, for e.x. get r attribute from URL:

<input type="hidden" name="spring-security-redirect" value="<c:out value="${param.r}" />">

NOTE2: Use c:out value="${param.r}" instead of simple ${param.r}, because c:out prevent to inject executable code [read more].

The tag can automatically escape XML tags so they aren’t evaluated as actual tags.

How to redirect user when it is not signed-in?

The example above provides us the way of redirecting user, when access the login form. We have passed the parameter r to the form, but it is still not provided to the login form page in query string.

Even user access the protected

page, the ExceptionTranslationFilter is executed. There are two reasons, when we looking for resolve this problem:

  1. When user is not logged in, so don’t have any roles, so don’t have permission to show a resource. Then AuthenticationEntryPoint should be executed.UX: User should be redirected to the login form to allow obtain the credentials.
  2. The second, when user is logged in and don’t have role (credential) that allow to access the protected resource. Then AccessDeniedHandler should is executed.UX: The 403 (Access Denied) page should be displayed. In nice form, obviously.

Now we will consider the first case, when user is trying to access protected resource, will be redirected to the login page, and then, should be redirected back to the resource to consider second case.

Define custom AuthenticationEntryPoint implementation to return user to the login page, with defined parameter r filled as current page:

@Component(value = "customAuthenticationEntryPoint")
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
 
	private String loginPageUrl;
 
	private boolean returnParameterEnabled;
 
	private String returnParameterName;
 
	@Override
	public void commence(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException reason) throws IOException, ServletException {
 
		if(null == loginPageUrl || "".equals(loginPageUrl))
			throw new RuntimeException("loginPageUrl has not been defined");
 
		String redirectUrl = loginPageUrl;
 
		if(isReturnParameterEnabled()) {
			String redirectUrlReturnParameterName = getReturnParameterName();
 
			if(null == redirectUrlReturnParameterName || "".equals(redirectUrlReturnParameterName))
				throw new RuntimeException("redirectUrlReturnParameterName has not been defined");
 
			redirectUrl += "?" + redirectUrlReturnParameterName + "=" + request.getServletPath();
		}
 
		RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
		redirectStrategy.sendRedirect(request, response,  redirectUrl);
 
		return;
	}
 
	public String getLoginPageUrl() {
		return loginPageUrl;
	}
 
	public void setLoginPageUrl(String loginPageUrl) {
		this.loginPageUrl = loginPageUrl;
	}
 
	public boolean isReturnParameterEnabled() {
		return returnParameterEnabled;
	}
 
	public void setReturnParameterEnabled(boolean returnParameterEnabled) {
		this.returnParameterEnabled = returnParameterEnabled;
	}
 
	public String getReturnParameterName() {
		return returnParameterName;
	}
 
	public void setReturnParameterName(String returnParameterName) {
		this.returnParameterName = returnParameterName;
	}
 
}

And configure this bean with tag:

<http ... entry-point-ref="customAuthenticationEntryPoint">
    <form-login login-page="/login" authentication-failure-url="/login?authfailed=1" authentication-success-handler-ref="simpleUrlAuthenticationSuccessHandler" />
</http>
<beans:bean id="customAuthenticationEntryPoint" class="pl.athlan.util.CustomAuthenticationEntryPoint">
    <beans:property name="loginPageUrl" value="/login" />
    <beans:property name="returnParameterEnabled" value="true" />
    <beans:property name="returnParameterName" value="r" />
</beans:bean>
<beans:bean id="simpleUrlAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
    <beans:property name="defaultTargetUrl" value="/account"/>
    <beans:property name="targetUrlParameter" value="spring-security-redirect"/>
</beans:bean>

That’s all. Hope will help.

TIP: to save your time, don’t try to fight with configuration of ExceptionTranslationFilter. I have tried to override org.springframework.security.web.access.ExceptionTranslationFilter, without effects:

<beans:bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
   <beans:property name="authenticationEntryPoint" ref="customAuthenticationEntryPoint"/>
   <beans:property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</beans:bean>
 

How to set ID Doctrine2 manually

I faced the

problem with preserving manually setted ID’s of records represented by entities having id

with auto generate strategy.

If for some reasons you really want to set the ID manually either

rely on generating strategy (@GeneratedValue strategy), you have to set:
@GeneratedValue(strategy="NONE")

But if your application rely on auto identifiers creation (@GeneratedValue(strategy="AUTO")) and you have to exceptionally set the ID manually (e.x. for synchronization), you have to change the strategy dynamicaly by injecting it into meta object of entity:

$metadata = $this-&gt;entityManager-&gt;getClassMetaData(get_class($entity));
$metadata-&gt;setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());

Where $entity is enetity you want to persist and there is an working entity manager under $this->entityManager.

 

Liquibase: How to store PostgreSQL procedures and triggers

Liquibase is an open source, database-independent library for tracking, managing and applying database changes written in Java and distributed as JAR (Java archive). There are many tools to version code, most popular: SVN, GIT, Mercurial.

Many product managers faced the problem with versioning the database during application development. The solution is Liquibase.

Although tool is very usefull (it can track changes related with tables, views, columnt, indexes, foreigns), there are few limitations. One of these there is stored procedures. Liquibase cannot track stored procedures depends on database. The solution is to use custom query executon avaliable in liquibase.

To create custom stored procedure in Liquibase, just make a simple XML file (testChanges.xml):

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
    <preConditions>
      <dbms type="postgresql" />
    </preConditions>
    
    <changeSet author="Athan (generated)" id="1360329703893-1-1">
        <createProcedure>
CREATE OR REPLACE FUNCTION TestFunction() RETURNS trigger AS $proc$
BEGIN
  ...
END
$proc$ LANGUAGE plpgsql;
        </createProcedure>
    </changeSet>
</databaseChangeLog>

And type:

liquibase --changeLogFile testChanges.xml --url=jdbc:postgresql://localhost:5432/dbname --username=postgres --password=root update

Your procedure will appear in database.

WARNING! You should remember that Liquibase provides rollback to version, tag or count of changes. For custom SQL there are no rollback actions (such us for create table – drop table). You have to provide a rollback SQL.

So just add a <rollback> tag to yout changeSet:

        <rollback>
DROP FUNCTION TableOffersStateRealisedUpdate();
        </rollback>

Whole XML should look like:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
    <preConditions>
      <dbms type="postgresql" />
    </preConditions>
    
    <changeSet author="Athan (generated)" id="1360329703893-1-1">
        <createProcedure>
CREATE OR REPLACE FUNCTION TestFunction() RETURNS trigger AS $proc$
BEGIN
  ...
END
$proc$ LANGUAGE plpgsql;
        </createProcedure>
        <rollback>
DROP FUNCTION TableOffersStateRealisedUpdate();
        </rollback>
    </changeSet>
</databaseChangeLog>

Same case with triggers:

<changeSet author="Athan (generated)" id="1360329703893-2-1">
    <sql>
CREATE TRIGGER "tableoffersstaterealisedupdate" AFTER INSERT OR UPDATE ON "public"."offers"
FOR EACH ROW
EXECUTE PROCEDURE "tableoffersstaterealisedupdate"();
    </sql>
    <rollback>
DROP TRIGGER "tableoffersstaterealisedupdate" ON "public"."offers"
    </rollback>
</changeSet>

Hope this helped you.