Monday, 18 August 2008

Rails: Work Around to Run Tests While Having Full-Text Index

While working in a Rails project, I was having some field in the DB in Text data type and I need to create a full-text index on this column. So, I created a migration that have the following line:

execute "ALTER TABLE transcriptions ADD FULLTEXT text_index (text)"

After running this migration, the full-text index is created and the application runs with no problems, but!

When I tried to run the unit tests, I got the following error:

Mysql::Error: #42000BLOB/TEXT column 'text' used in key specification without a key length: CREATE INDEX `text_index` ON 'transcriptions' ('text')


That is because when you run db:migrate, a schema file is created from the DB called schema.rb. This file contains the complete DB schema including the indices. The problem is that creating index in the schema.rb file is written using add_index method which is used for creating regular indices only, not the full-text index.

In this case when you are trying to run the unit tests, Rails try to prepare the test DB using this schema.rb file and fail due to it can't create index on text type column.

If we take a look on what test rake task do, we can see the following trace:


** Invoke test:units (first_time)
** Invoke db:test:prepare (first_time)
** Invoke environment (first_time)
** Execute environment
** Invoke db:abort_if_pending_migrations (first_time)
** Invoke environment
** Execute db:abort_if_pending_migrations
** Execute db:test:prepare
** Invoke db:test:clone (first_time)
** Invoke db:schema:dump (first_time)
** Invoke environment
** Execute db:schema:dump
** Invoke db:test:purge (first_time)
** Invoke environment
** Execute db:test:purge
** Execute db:test:clone
** Invoke db:schema:load (first_time)
** Invoke environment
** Execute db:schema:load


And the problem fall in the line "Execute db:schema:load" which creates the test DB using the schema.rb file. To work around this issue, we can replace this rake sub-task (thanks for Matthew Bass’s blog post) by test:clone_structure against the development environment. This will clone the development DB schema into the test DB schema without using the corrupted schema.rb file.

To replace this rake task by the clone one, open the Rakefile file in your project and write the following lines:

require 'tasks/rails'

Rake::TaskManager.class_eval do

def remove_task(task_name)

@tasks.delete(task_name.to_s)
end

end

def remove_task(task_name)
Rake.application.remove_task(task_name)

end

remove_task 'db:schema:load'
namespace :db do

namespace :schema do
task :load do
RAILS_ENV = 'development'
Rake::Task['db:test:clone_structure'].invoke
RAILS_ENV = 'test'

end
end

end


Then when you run the test rake task you will get different trace contains the db:test:clone_structure instead of db:schema:load and everything will go as expected.

Wednesday, 16 July 2008

Ruby: Run Code Blocks at Specific Time Intervals

While working in Rails project, some of my business logic parts need to run at specific time intervals. First, I created a rake tasks for my code blocks and use "cron" jobs to run those rake tasks at the required time intervals. But, as You know , every rake task loads the whole Rails application into the memory to run and this is costly specially if my rake tasks run at high frequency (every ~1 min).

So, I decided to load the tasks into the memory and make them sleep and run at specific time intervals. One of the great Rails gems that helps me doing this job is EventMachine. It is event processing library for Ruby applications. Using it you can define specific code blocks to run at specific time and also define a periodic timer for code blocks that will run periodically.

So, what I did is creating one rake task contains the event machine running and defined some periodic timers to run code blocks at the required time intervals. In this case my rake task will be loaded into the memory and will be sleep (using the event machine) and run my code blocks at the defined time intervals.

  • To install this gem:

    gem install eventmachine

    and then choose the required gem version from the given list.

  • If you need some code block to run periodically every 10 secs, create a periodic timer:

    EventMachine.run {
    @periodic_job = EventMachine::PeriodicTimer.new(10){
    # code block to run every 10 secs
    }
    }
  • You can cancel the periodic job at any time by calling:

    @periodic_job.cancel
  • Note Do not forget to stop the event machine at the end of your periodic job, e.g. if you need your periodic job to run just 10 times:

    x = 0
    EventMachine.run {
    EventMachine::PeriodicTimer.new(0.1){
    x += 1

    # your code go here

    EventMachine.stop if x == 10
    }
    }

Checkout the full documentation of EventMachine.

Sunday, 22 June 2008

Centralized Static Authorization Using Just a Hash

Deciding how your site authorization will be implemented is not a simple part. You can implement centralized authorization, distribute it over the controllers or let each model exposes its authorized resources. Of course that depends on how your authorization process will be (static, dynamic, roles appear at run time, etc).

Using centralized authorization:

  1. Define one entry point for authorization. So, you can easly disable/enable it.
  2. You will maintain only one scope of code without touching the other business logic code.
  3. If code failure happened, you can easily isolate it from the application process without dropping down the whole logic.
  4. Other business logic is independent and don't aware of the authorization. So, you can easily upgrade your authorization process if you need without touching other application parts.

In RoR, if your authorization will be static over a predefined list of roles, then you can easily implement your authorization check based on user/controller/action triple using the magic word "hash". This will done by creating a nested hash of the following levels:

  • Level one: Users Roles (Admin, Client, etc)
  • Level two: Controllers (Users, Products, Items, etc)
  • Level Three: Actions (Index, Create, Update, Destroy, etc)

Now, you need to catch the request, extract the request entities (requesting user role, controller and action) and then hash these keys to see whither this request is authorized or not.

Lets see small example. If you have two user roles in your application; Admin and User. And you have two controllers; Products and Users. Your hash will be as following:


@roles = {:Admin => {
:Users => :all,
:Products => :all
}
:User => {
:Users => {:update => :all}
:Products => {:index => :all, :show => :all}
}
}

The above hash gives the "Admin" user role the whole access to the both controllers and the whole controller actions. But, for "User" role, he can request "update" action in "Users" controller and "index" or "show" actions in the "Products" controller only.

Note I am using the value ":all" as the end of my roles permissions tree. So, it means "full access" either on the whole controller's actions or specific action.

The next step is putting this roles and the checking code into small module, include it in your ApplicationController then call the "authorize" method using before_filter.

module Authorization

@roles = {:Admin => {
:Users => :all,
:Products => :all
}
:User => {
:Users => {:update => :all}
:Products => {:index => :all, :show => :all}
}
}

def authorize
# check controllers list for the requested user
@controllers_list = @roles[@user.class.to_s.to_sym]
if (@controllers_list.nil?)
# no controllers permitted for this user role
render :text => "", :status => :unauthorized
return false
else
# check actions list inside the controller
@actions_list = @controllers_list[controller_name.to_sym]
if (@actions_list.nil?)
# the requested controller is not permitted
render :text => "", :status => :unauthorized
return false
elsif (@actions_list == :all)
return true
else
# check the called action
@called_action = @actions_list[action_name.to_sym]
if (@called_action.nil?)
render :text => "", :status => :unauthorized
return false
elsif (@called_action == :all)
return true
else
render :text => "", :status => :unauthorized
return false
end
end
end
end

end

class ApplicationController <>

include Authorization

before_filter :authorize

..............

end

You can enlarge or shrink the hash as you need (add/remove roles, controllers, etc) but the "authorize" method code will not change.

Freshbooks Ruby Gem and Its Patch

For who does not know freshbooks, it is an online service for sending invoices and tracking time. You can access this service either through its web-interface or through its exposed APIs. It is not free, but you can create a test account and try it. I used it while working in project at eSpace company.

To access your freshbooks account through the APIs, you need first to enable its APIs and use the given URL and authentication token in your API connection. You will notice that freshbooks APIs have different versions and they distinguish between them using the API access URL, e.g. for API version 2.1 (latest one at post time), your URL will be "https://espacetest.freshbooks.com/api/2.1/xml-in"

You can access freshbooks APIs from inside Ruby on Rails project either directly through http connections or using a Ruby wrapper freshbooks.rb. To install it:

gem install freshbooks

The latest version of this gem (at post time) is freshbooks-2.2. This version contains a small issue regarding API version number. When using this library, you need to pass both your freshbooks account simple URL (espacetest.freshbooks.com) and authentication token.

FreshBooks.setup(@freshbooks_url, @freshbooks_token)

Then, library code concatenates the rest of the URL. Look at this code lines taken from freshbooks.rb:

Line 35: VERSION = '2.2' # Only works with 2.1

Line 37: SERVICE_URL = "/api/#{VERSION}/xml-in"


You will notice that the version number is "2.2" and this variable "VERSION" is used in the API url. But, no API version 2.2 yet!!
So, if you used this gem as it you will get error from freshbooks API saying "Invalid API version.". All you need to do is replacing this value with "2.1"

Line 35: VERSION = '2.1' # Only works with 2.1:

Line 37: SERVICE_URL = "/api/#{VERSION}/xml-in"

Now, enjoy accessing great online invoices service through simplified Ruby wrapper ( after patching :) ).

Wednesday, 18 June 2008

PayPal Sandbox

While working in a project in eSpace contains e-commerce handling, I wanted to test my code against PayPal payment gateway. I found that PayPal have a test server called PayPal Sandbox. Using this test server you can simulate all the transactions you want to do over the actual PayPal account.

PayPal Sandbox contains the following features:

  1. Simulate actual transactions (authorize, purchase, credit, etc).
  2. You can create test accounts for sellers/buyers as many as you want.
  3. Every created test account will have its own credit card (fake one). You can use it to test you transactions and its balance will reflect your applied transactions.
  4. You can use any of your seller/buyer test accounts to enter the paypal test site and trace its transactions, create reports, etc.
  5. You can access this test sandbox from your code through PayPal APIs.

But, it contains some drawbacks:

  1. The given test credit cards does not contain verification code (CVV code), but you can use "000" instead of it in your tests.
  2. When you enable the API in your Paypal account, you will get API user name, API password and either a signature string or certificate file. Using Sandbox you will get only the signature string.

Monday, 16 June 2008

Ruby and RSA Encryption

One of the greatest security schemes in e-commerce is RSA Encryption. It depends on one published key for encryption and secured private key for decryption. Private key can also be used in signing a content.

Ruby contains a standard library for SSL (Secure Socket Layer) that helps you finding all required schemes for implementing your secure communication channel over the Internet.

If you want to use RSA schema for encrypting/decrypting your content, follow the following steps:

  1. First, you need to generate the private key and store it in secure store, let us generate one with length 1024:

    @private_key = OpenSSL::PKey::RSA.new(1024)


  2. Now, you can use this key to generate the public key as following:

    @public_key = @private_key.public_key

    To get the string representation of this key:

    @public_key.to_pem


  3. After you publish your public key, your clients can encrypt content as following:

    @encrypted_msg = @public_key.public_encrypt("text to encrypt")


  4. Now, to decrypt the incoming encrypted content, use your secured private key:

    @decrypted_msg = @private_key.private_decrypt(@encrypted_msg)

    You can also use this pair to sign your content with your signature. That can be done by encrypting your content using your secret private key and your clients can check the content authority by decrypting this content using your published public key.

Note: Don't forget that private key, public key and also the encrypted content may contains unprintable characters. To store or print them, you need to encrypt them first using Base64 encoding.

This library also contains other security protocols, check the full documentation.

Sunday, 15 June 2008

Forwarding Email as Attachment Using ActionMailer

Using the default TMail::Mail.create_forward for forwarding emails will not help you using email templates for designing the message structure.

If you have an email message and you want to forward it using ActionMailer email templates all you need to do is attach the email content into your email template with content type 'message/rfc822' and file name with extension 'eml' (message.eml).

Lets see some code do that:

  1. Create your email template view file, lets called it "forward_email.rhtml" and fill it with your required content/design.
  2. In your ActionMailer model, create a method with the same name "forward_email" that accepts string argument contain the email content you need to forward:

    def forward_email(forward_email_content)
    recipients "test@espace.com.eg"
    from "info@espace.com.eg"
    subject "Testing forward email content as attachment"
    attachment "message/rfc822" do |a|
    a.filename = 'email.eml'
    a.body = forward_email_content
    a.transfer_encoding = '7bit'
    a.content_disposition = 'inline'
    end
    end

In this way, you can forward the email content as usual but inside your designed email template.

Wednesday, 11 June 2008

Rails Access Different Payment Gatways Using ActiveMerchant

One of my Ruby on Rails projects in eSpace contains e-commerce process for charging the clients using their credit-card information. As there are many payment gateways (PayPal, Authorize.net, etc), then you just need a simple plugin/gem that helps you access those gateways. Ruby on Rails contains many plugins/gems that give you access to different payment gateways. One of the great plugins is ActiveMerchant. It gives Rails a unified API for accessing different payment gateways with very simple way.
Using ActiveMerchant you will get:

  1. Support for too many payment gateways

  2. Bogus gateway for testing all payment functions that can done on actual gateways (except recurring).

  3. Validates credit card format

The following steps shows you how to install ActiveMerchant, create a credit card object and validates it, then use the bogus gateway for processing e-commerce actions.

  1. You can install ActiveMerchant as gem:

    gem install activemerchant


    or as plugin

    ruby script/plugin install http://activemerchant.googlecode.com/svn/trunk/active_merchant


  2. Create a credit card object:

    credit_card = ActiveMerchant::Billing::CreditCard.new({
    :number => 5105105105105100,
    :month => 9,
    :year => Time.now.year + 1,
    :first_name => 'test',
    :last_name => 'account',
    :verification_value => '123',
    :type => 'visa'
    })

    You can check if the given credit card information is valid or not:

    puts credit_card.errors.to_json if !credit_card.valid?


  3. Create a bogus gateway instance:

    @gateway = ActiveMerchant::Billing::BogusGateway.new(
    :login => 'bogus',
    :password => 'bogus'
    )


  4. Now, you can use the bogus gateway instance to process any e-commerce request you want (authorize, purchase, credit, etc)

    response = @gateway.authorize(1000, @creditcard, @options)

    response = @gateway.purchase(1000, @creditcard, @options)


    Note: 1000 = 10$ (credit values in cents)

  5. If your application uses default currency different than the default currency in the targeted payment gateway, you need to initialize ActiveMerchant with your required currency. To do that, add the default currency in your environment configuration file:

    ActiveMerchant::Billing::PaypalExpressGateway.default_currency = 'GBP'


    or you can pass the currency in each interaction with the gateway:

    :currency => 'GBP'


Using the bogus gateway in your test will not help you in testing all credit card types (master card, visa, etc). Bogus gateway support only one card type "bogus" :).
Check the full documentation for ActiveMerchant.

Tuesday, 10 June 2008

Forwarding TMail::Mail Objects

Ruby contains an email handler called TMail. Rails use TMail as default email handler in ActionMailer. You can use it to manipulate email content/headers. Accessing TMail object done via TMail::Mail class, check the documentation

In the most cases, you use ActionMailer to design and deliver your emails. But what if you already have an email and need to forward it as is?

In this case you can use the TMail::Mail object directly and with simple code you can forward the email content without doing any content manipulation. The following steps shows how you can forward an email content.

  1. If you have the email content as string, you can ask TMail to parse this string into TMail::Mail object:

    @email = TMail::Mail.parse(email_content)


  2. Using the parsed TMail::Mail object, you can create a forward copy of the email using one line of code:

    @forward_email = @email.create_forward()


  3. Now, you have a prepared forward email content, you can change any field you want according to your requirements:

    @forward_email.to = 'my_friend@domain.com'
    @forward_email.from = 'me@domain.com'


    Note: don't change the forward email body, it contains the actual email content you need to forward.

  4. Next, lets deliver this forwarded email using our ActionMailer model. You need to write two lines of code to do that:

    @forward_email.write_back
    YourMailerHanlder.deliver(@forward_email)


    The first line flattens the TMail::Mail object into a MIME message ready for sending.
    The second line asks the ActionMailer to deliver the given email.

This technique will not help you in adding any new content into the forwarded email, you just forward it into an empty email as is. I did that while working in RoR project in eSpace.

Wednesday, 4 June 2008

ActionMailer: Receiving Emails Contain Attachments

Web applications may be forced to receive emails and process its content, either its body or contained attachments. ActionMailer can be used to receive emails and give you access to its content. ActionMailer functionality based on receiving TMail object of your email content and give you access on all its parts (from, to, attachments, etc).

All you need to do is add the following method to your action mailer model:

def receive(email)
...
end


"email" argument is an object of type TMail::Mail. You can use it to read email metadata:

@to = email.to
@from = email.from
@body = email.body


The nice part is accessing the email attachments (if exist) through simple code. The following code checks if the email have attachments and read each attachment file name, content type and its content:

def receive(email)
if email.has_attachments?
email.attachments.each do |attachment|
@file_name = attachment.original_filename
@content_type = attachment.content_type
@content = attachment.read
end
end

end


Using ActionMailer for receiving emails contains two magical parts:

  1. Some email bodys encoded using Base64 encoding, also the attachments. The magical part in TMail is that it handles decoding the attachment content using Base64 decoder for you. So, you access the attachment content directly without decoding it.

  2. If you read the incoming email from a system file and need to feed it to your ActionMailer.receive method, all you need to do is reading the file content and give it directly to your ActionMailer.receive method without converting it into TMail object and ActionMailer will do the rest:

    file = open("my_email")
    email_content = file.read
    file.close
    MailerAgent.receive(email_content)

The missing part in this process is that ActionMailer will not listen at the email server for catching the new emails. I used one solution for this part; you can configure your email server to catch all incoming emails, save them inside a specific folder (file per email). Then you create a rake task that run periodically, reads the folder files and send each file content to your ActionMailer.receive method. But you need to filter the spam emails in this case.

Tuesday, 3 June 2008

Rails Basic HTTP Authentication

Some web applications require authentication for accessing some or all resources. The simple case in authentication is depending on http protocol and its authentication mechanism.

There are deferent types for http authentication, the simplest one is Basic Access Authentication. It depends on encoding the user name and password using Base64 encoding and put it in the http authorization header.

Rails helps you in using http basic authentication, or as they say in its documentation "Makes it dead easy to do HTTP Basic authentication". All you need to do is very simple:


  1. Create a separated module, may be called "Authentication"

    module Authentication

    end

  2. Create a method inside the module that will do your authentication

    def authenticate

       authenticate_or_request_with_http_basic do |username, password|

       end

    end

    Note that I put a call to authenticate_or_request_with_http_basic method in ActionController::HttpAuthentication::Basic Module that will provide you with the sent user name and password after decoding them using Base64 decoder.

  3. Now, you need to call the authentication method before every call to your controllers. That will done by putting a "before_filter" call in your ApplicationController class:

    class ApplicationController < ActionController::Base

       include Authentication

       before_filter :authenticate

    .....

    end


  4. If you need to skip some controllers from authentication chain, put in this controller a call to skip_before_filter:

    skip_before_filter :authenticate


  5. The last step is filling your authentication method with the code that will do the authentication check using the given user name and password.


Monday, 31 March 2008

Creating Tab Activity in Adnoird

While developing your application, you may need a window that contains tabs, e.g. wizard window or settings window.

Android supports this kind of views, tabs one. Android gives you TabHost, TabWidget and TabSpec classes for building your tabbed activity.

To create your tabbed activity, you will build your layout xml file contains TabHost tag have two elements:

  • TabWidget that will hold the navigation tabs title and icon
  • FrameLayout that will hold LinearLayout for each tab content

Then, in your activity code you will build the tabs content, assign a title and icon for each tab and then add the tabs to your tab host object.

The following are steps for creating activity have two tabs in its view:

  1. Create the activity layout that contains TabHost, TabWidget and two linear layouts inside frame layout for your two tabs:
  2. <LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TabHost android:id="@+id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <TabWidget
    android:id="@android:id/tabs"
    android:layout_width="fill_parent"
    android:layout_height="65px" />

    <FrameLayout
    android:id="@android:id/tabcontent"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:paddingTop="70px">

    <LinearLayout
    android:id="@+id/tab1"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    </linearlayout>

    <LinearLayout
    android:id="@+id/tab2"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    </linearlayout>
    </framelayout>
    </tabhost>
    </linearlayout>
  3. Inside your activity onCreate method, you will init the tabs view as following:
    1. Acquire the tab host object and call setup() function for starting the setup
    2. tabs = (TabHost) findViewById(R.id.tabhost);
      tabs.setup();

    3. Create your first tab by building TabSpec object and pass its layout content:
    4. TabSpec tab1 = tabs.newTabSpec("tab1");
      tab1.setContent(R.id.tab1);

    5. Set the tab title and icon:
    6. tab1. setIndicator(“my tab one”, drawable_object);

    7. Then, add this tab to the tab host object
    8. tabs.addTab(tab1);

    9. Repeat steps (2), (3) and (4) for the second tab.
  4. To set current tab, call setCurrentTab method in tab host object with the required tab index
  5. tabs.setCurrentTab(0);

Attached is a complete activity code and layout xml file for two tabs activity.

Monday, 24 March 2008

Rendering Web Pages inside Android Activity

While you create Android activities, you supply the activity view content either through XML or dynamically through the code. But, sometimes the content in the view, specially the static content (content will not change with different runs) may be a web page; e.g. “Help” Activity or “Terms and Conditions” Activity of your application.

These contents can be done as web pages, and that will help you in changing the content without affecting the client side application binary. However, sometimes you need to open those pages inside your application as activity, not through web-browser, e.g. open “Terms and Conditions” web page for the user to accept or reject through button actions.

Android have a great widget for this usage, it is “WebView” component. It accepts either plain text as you use in Text View component or a URL to a web page to render inside your activity.

The following example show a layout for a sample activity contains web view to show eSpace site home page:
  • You first create the layout XML file contains your component as following:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <WebView
    android:id="@+id/myWebView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    />

    </LinearLayout>
  • And then supply the URL to the web view through your activity “onCreate” method code:

    WebView webView = (WebView) findViewById(R.id.myWebView);
    webView.loadUrl(“http://www.espace.com.eg”);

  • Now, the given URL is rendered inside the web view widget and you can deal with the opened web page with all functionality available from Android web-kit (scroll, zoom in, zoom out, etc).

Monday, 17 March 2008

Maven Plugins for Manipulating Databases

Some projects have database in their infrastructure, and deploying these projects involves building database schema and initializing some tables with default data.

Using Maven, you can get great help in this point. Maven can help you in building and manipulating your project database through its POM file configuration and in your defined order of execution.

Maven built on plugins. You add plugins configuration into your POM file as your build script needs. Maven has a great set of database manipulation plugins, for example:
  1. Mojo, SQL Maven Plugin

  2. Torque, Maven2-plugin

I recommend the first one for simple usage, Mojo SQL Maven Plugin. It is great and simple plugin for basic database manipulation. You can create your SQL script file(s) and define an execution configuration inside the plugin tag and configure it to run after specific maven lifecycle phase.

You can have more than one execution, everyone have its own lifecycle phase to run after and have its SQL script files set to run against the configured DB.

For example, the next configuration will run after the “package” phase and execute the given SQL script file against the given mysql DB configuration:


<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sql-maven-plugin</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
</dependency>
</dependencies>
<configuration>
<driver>com.mysql.jdbc.Driver</driver>
<autocommit>true</autocommit>
</configuration>
<executions>
<execution>
<id>deploy-schema-data</id>
<phase>package</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<url>jdbc:mysql://localhost/test-db</url>
<username>root</username>
<password>root</password>
<srcFiles>
<srcFile>
src/main/resources/sql/init-data.sql
</srcFile>
</srcFiles>
</configuration>
</execution>
</executions>
</plugin>

Sunday, 9 March 2008

Java Annotations and Aspect Oriented Programming

Starting from Java5, Java starts a trend of annotation-based development. Java gives you ability to build your custom annotations as required and build your configuration through annotations.

In one of my old projects I created custom transaction manager using custom Java annotations and Aspects. I used AspectJ library together with Spring Framework for creating Aspects that run over custom annotations defined as point-cuts.

Next, we will iterate on how we can create aspects run over custom annotations using AspectJ and Spring Framework. This will be a simple example of creating custom transaction manager for starting, committing and rollback.

  1. To create custom annotation, you will create annotation interface and define its target (METHOD, FIELD, PARAMETER, TYPE, etc). The next one is MyTransaction annotation that will be used to annotate transactional methods.

  2. @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface MyTransaction {
    }

    To use it, just add annotation “@MyTransaction” before any method you want to be handled using your transaction manager:

    @MyTransaction
    Public void doCode(){
    }

  3. Creating aspect using AspectJ and Spring Framework is based also on annotations. You have annotation called “@Aspect” used to annotate classes that will be waved as aspects using AspectJ Weaver. You will have aspect for your Transaction Manager as following :

  4. @Aspect
    public class MyTransactionManager {
    }

  5. This aspect will have point-cuts over your custom annotation. This will be done as following:

  6. @Pointcut("execution(@MyTransaction * *(..))")
    private void myTransactionMethod() {
    //No code needed here, just empty method
    }

    The last method defines point-cut over all methods have annotation “MyTransaction”. You can imagine this point-cut as place holder at specific parts of your code.

  7. After creating your point-cut, you need to create your aspect advice(s). Each advice is just a method that will run at specific point-cut at some time (before, after or around).
    1. The following advice will run at point cut “myTransactionMethod” and before running the method have this point-cut (the methods annotated with “MyTransaction”). As you see from its name it will start new transaction.

    2. @Before("myTransactionMethod()")
      public void doStartTransaction() {
      //code for starting transaction
      }

    3. This advice will run after returning from the point-cut. As you see from its name its code will commit the last opened transaction.

    4. @AfterReturning(pointcut = "myTransactionMethod()")
      public void doCommitTransaction() {
      //code for committing transaction
      }

    5. Well, your transactional method may fail and need to rollback. Then, you will need to have advice run after throwing exception at your point-cut.

    6. @AfterThrowing(pointcut = "myTransactionMethod()")
      public void doRollbackTransaction() {
      //rollback transactional code
      }

The last example is just starting point for you to know how you can use Java Custom Annotations together with Aspect Oriented Programming to create a great concern separated components like the one we do.

I attached the two example classes, MyTransaction.java annotation and MyTransactionManager.java aspect to this post.

Attachment File

Sunday, 10 February 2008

Spring Framework; pooling target sources

Spring Framework gives you ability to create beans for any POJOs and use them in IoC as your application needs.
Spring Framework supports more than one scope for its bean:
  1. Singleton: Scopes a single bean definition to a single object instance per Spring IoC container.

  2. Prototype: Scopes a single bean definition to any number of object instances.

And other three scopes if you work with Spring Framework version 2.5.
You must take care while dealing with some of these scopes, specially the prototype/request ones that creates new bean instance for every request. That can harm your web application server as your requests increase and consumes your server memory and resources.

Resource pooling is the best handling for this situation. It is general concept of having a pool or resources with fixed size (can be configurable) and have your resource handler pool out one resource from this pool for every resource request and returns it again in the pool after the request finished. If your pool is empty, then the requested entity will queue until one resource is available for its request in the pool.

By that way you can tune your resources usage based on their types. Some of resource types have more requests to them; you can increase their pool size. Others have less usage; you can decrease their pool size to the proper value.

Spring Framework gives you this ability of resource pooling while creating your POJOs beans. Spring pooling can be applied to any POJO. Spring provides out-of-the-box support for Jakarta Commons Pool, which provides a fairly efficient pooling implementation. You'll need the commons-pool Jar on your application's classpath to use this feature.

Sample configuration is shown below:

... properties omitted
</bean>

<bean id="poolTargetSource"
class="org.springframework.aop.target.CommonsPoolTargetSource">
<property name="targetBeanName" value="businessObjectTarget"/>
<property name="maxSize" value="25"/>
</bean>

<bean id="businessObject"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref="poolTargetSource"/>
</bean>


Note that the target object--"businessObjectTarget" in the example--must be a prototype. This allows the PoolingTargetSource implementation to create new instances of the target to grow the pool as necessary.

Reference:
Spring Framework Documentation, Chapter 7, section 7.10.2

Wednesday, 6 February 2008

Restlet framework integration with Spring

While I am working in my project (Android/weNear), we decided to expose our server side functionality using web-service interface such that we can easily build web-based consol for weNear beside the Android handset client one.

After our eSpace sessions for the REST architecture, I see that REST architecture is more lighter and flexible in use than SOAP one for web-services (check small comparison Giving SOAP a REST). Just to remember, REST architecture is based on http protocol and commands only. No extra data or handling needed to call your REST web-service (as in SOAP protocol). Just use http connection and enjoy dealing with any data formats you want as supported by the REST server (XML, JSON, etc).

Restlet framework is one from a lot of REST web-service frameworks. It is great and lightweight REST framework for java. The problem is that it lakes of documentation.

The good point is that it has extension for integration with Spring framework (the one we are using in weNear server). Next I will elaborate how you can integrate RESTlet framework with Spring framework.

  1. Add the following libs to your application classpath:
    org.restlet-<VERSION>.jar
    org.restlet.ext.spring-<VERSION>.jar
    com.noelios.restlet-<VERSION>.jar
    com.noelios.restlet.ext.servlet-<VERSION>.jar

  2. You need to create two basic java classes (I attached them to the post)

    1. final class RestApplication extends org.restlet.Application
      This is the main starting point for RESTlet framework to be loaded with your web-application. You will override the method “createRoot()” that starts to load your spring context and initialize your REST manager bean with basic router (refer to RESTlet documentation).

    2. final class RestManager
      This classes will contain your resource mapping. Every map entry will contain resource URL as key and Restlet implementation class as value for this key. This Retlet implementation class is the one who will handle the call to this resource URL.


  3. You need to add some configuration in your web.xml for your RESTlet framework to start.

    • Your restlet application context parameter :

      <context-param>
      <param-name>org.restlet.application</param-name>
      <param-value>
      <RESTLET_APPLICATION_CLASS_PATH>
      </param-value>
      </context-param>

    • Your Restlet servlet and its mapping :

      <servlet>
      <servlet-name>RestServlet</servlet-name>
      <servlet-class>
      com.noelios.restlet.ext.servlet.ServerServlet
      </servlet-class>
      </servlet>

      <servlet-mapping>
      <servlet-name>RestServlet</servlet-name>
      <url-pattern>/rest/*</url-pattern>
      </servlet-mapping>


  4. The final point is creating your Restlet manager bean that will hold your resource/restlet mapping. In your applicationContext.xml you will create the next bean:

    <bean id="manager" class="<RESTLET_MANAGER_CLASS_PATH>">
    <property name="resourceMappings">
    <bean class="java.util.HashMap">
    <constructor-arg>
    <map>
    <entry key="<RESOURCE_URL>">
    <ref local="<RESTLET_BEAN>"/>
    </entry>
    </map>
    </constructor-arg>
    </bean>
    </property>
    </bean>
    Notice that
    <RESOURCE_URL> is your resource URL that will be requested by the client to invoke <RESTLET_BEAN> class, e.g. “/user/1”
    <RESTLET_BEAN> is spring bean for the class that extends org.restlet.Restlet and will handle the call for the given RESOURCE_URL.

Now, you have Restlet framework integrated with Spring. All you need to do for adding more rest resources is creating bean for your restlet implementation and create entry in your RestletManager bean that maps your resource URL to your Restlet implementation bean.

Attachments:
RESTlet and Spring

Tuesday, 5 February 2008

Locate Me Using GSM Information and Yahoo Services

Some mobile devices contains GPS (Global Positioning System) hardware using it you can acquire your location on earth in the form of longitude and latitude.

Additionally, most GSM cell towers have fixed locations (some of the towers are mobile ones) and have its own longitude and latitude location defined on it. So, depending on GSM network for acquiring handset location (longitude/latitude) is obvious solution instead of GPS hardware.

Yahoo provides two services API using them you can get GPS location (latitude and longitude) and use it in any maps service (google, yahoo, etc) from GSM network information.

1) ZoneTag. The cell location web service allows you to access the ZoneTag Location Services and get the best known location (address) for a given GSM cell tower ID.
All you need to do is requesting this service API by sending your GSM information in its URL as parameters. Response will be location address for the given cell information. ZoneTag learns about real world cell locations from users.
The required GSM information for the service API is; cell id, mcc (Mobile Country Code), mnc (Mobile Network Code) and lac (Location Area Code).

2) Geocoding API. The Geocoding Web Service allows you to find the specific latitude and longitude for an address. All you need is sending your address (country, city, state, street and zip code) in the request URL and then you will get XML response contains the GPS information.

Example:
Given the following cell information: cell id=48627, lac=201, mnc=15, mcc=234, request URL is:
http://zonetag.research.yahooapis.com/services/rest/V1/cellLookup.php?ap...
Response XML will be :


<rsp stat="ok">
<Location>
<Country cell="current" source="user">United Kingdom
</Location>
<Location>
<Country cell="current" source="generic">United Kingdom
<City cell="current" source="generic">Hammersmith
</Location>
<Location>
<Country cell="current" source="GPS">United Kingdom
<City cell="current" source="GPS">London
<Zipcode cell="current" source="GPS">W6 8
</Location>
</rsp>

From the given address you can request Geocoding service API to get GPS location:
http://local.yahooapis.com/MapsService/V1/geocode?appid=YahooDemo&countr...
Response XML will be:

<ResultSet xsi:schemaLocation="urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd">
<Result precision="zip">
<Latitude>51.506325
<Longitude>-0.127144
<Address/>
<City>London
<State>United Kingdom
<Zip/>
<Country>GB
</Result>
</ResultSet>
http://local.yahooapis.com/MapsService/V1/geocode?appid=YahooDemo&countr...

I found that the returned GPS location is (long=29.889870, lat=31.192240). I think it is the marked point by Yahoo for Alexandria in Yahoo maps.
For anyone interested to test this services in Egypt, Vodafone mcc=602 and mnc=02 as example.

Tuesday, 1 January 2008

Starting Up

I just started my blog, waiting your comments.