martedì 29 settembre 2009

New Hook Aspect to use AOP concepts inside Roma Framework

Hook Aspect

The Hook Aspect aims to write listeners of POJO events in simple way. The Hook Aspect allows the developer to extend an existent application in a flash. The Hook Aspect is based on the well known principles of Aspect Oriented Programming, AOP by now. The AOP supports the Object oriented paradigm. The two approaches can be used together to get the best of both.

You can hook any action of any POJO at runtime as well as read/write of any fields.

Using the Hook Aspect you can change and customize your application behaviour in a non-invasive mode.

Scope

Each hook belong to a scope. Scope can be:

  • SESSION, means that all the registered POJOs that are part of the current User Session will be waked up when the event is raised

  • APPLICATION, means that the POJOs are components declared into the IoC container (Spring IoC).

Using the scope APPLICATION you must assure that the POJO loaded by Spring IoC use the annotation @CoreClass(loading=EARLY) on top of the class declaration (look at the example below). This is the only way to assure to activate the Roma configuration when the application starts.

Below a table of the hooks available for the action:

@HookAction

Description

onBeforeAction

Invoked just before an action is called

onAroundAction

Invoked in place of the original action

onAfterAction

Invoked just after an action is called

onBeforeFieldRead

Invoked just before a field is read

onAroundFieldRead

Invoked in place of the original read. The action must return the value to return in place of the original

onAfterFieldRead

Invoked just after a field is read

onBeforeFieldWrite

Invoked just before a field is written

onAroundFieldWrite

Invoked in place of the original write. The action must return the value to assign to the field in place of the original

onAfterFieldWrite

Invoked just after a field is written



@HookField

Description

field

Copy the content of the field hooked everytime changes

Change the behaviour at run-time

In this example you need to avoid further login into the application for a while. The classic path would be to change the code or to write a parameter to switch on/off this feature.

Using a hook makes all things much easyer. Please note that the hook hookAroundAction means in-place-of. This action will be called in place of the original one.

ApplicationControl Example





@CoreClass(loading = LOADING_MODE.EARLY)
public class ApplicationControl {
@HookAction(hookAroundAction="CustomLogin.login", scope=HookScope.APPLICATION)
public void hook() {
// DISABLE THE LOGIN
System.out.println("Application in mantainance: login disabled");
RomaFrontend.flow().forward(
new MessageOk("login", "Login temporary disabled").
setMessage("Login is temporary disabled, please try in few minutes"),
"screen:popup:alert");
}
}

In the same way you can customize strategies, alghoritms, navigation paths all by using the Hook Aspect.

Collect results

This is an example of a simple profiler that record in a Map in memory the times the actions are called.


Remember that to use the scope “application” you need to instantiate the component as singleton by the IoC container (Spring IoC at this time). Add this line at the end of applicationContext.xml file of your application:

<bean id="ProfilerDemo" singleton="true" class="com.orientechnologies.moobilis.server.view.domain.ProfilerDemo" />


And create a class in this way:


ProfilerDemo Example:


import java.util.HashMap;

import org.romaframework.aspect.hook.annotation.HookAction;
import org.romaframework.aspect.hook.annotation.HookScope;

@CoreClass(loading = LOADING_MODE.EARLY)
public class ProfilerDemo {

protected HashMap<String, Long> totalTimes = new HashMap<String, Long>();

@HookAction(hookAfterAction = "*", scope = HookScope.APPLICATION)
public void profileAllActions() {
Long times = totalTimes.get("allActions");
if (times == null)
times = new Long(0);
times = times + 1;
totalTimes.put("allActions", times);
}

@HookAction(hookAfterAction = "*Login*", scope = HookScope.APPLICATION)
public void profileAllLoginActions() {
Long times = totalTimes.get("loginActions");
if (times == null)
times = new Long(0);
times = times + 1;
totalTimes.put("loginActions", times);
}
}

lunedì 21 settembre 2009

Finally released the "Virtual Objects" in SVN trunk

Roma Framework is strictly based on the POJO Java architecture. Anything is a POJO from the view to the persistence. But in some circumstances it could be better having a lighter way to hide some fields in a form or adding a new action to an existent POJO.

This is the reason because Roma (starting from version 2.0.3) supports the Virtual Objects. Virtual Objects are treated just as real Java Objects but they are declared using a descriptor. Now only XML descriptor is supported but in future it could be planned JSON or other ways.

Virtual Objects, in effects, are declared using the same XML Annotation syntax with minor additions to handle field types, inheritance and other stuff that Roma can't know since the XML descriptor is not backed by a real class file.

Cross language

Virtual object's business logic is written inside the tag using the Scripting Aspect. This means that Virtual Objects are totally decoupled by the Java technology and they can be written in any language supported by the JSR 223.

Hot changes high productivity

Virtual Objects are loaded at run-time and reloaded every time the file is saved. This boost up the productivity since it never requires to restart the JVM!

Indeed changing the signature of a class (add and remove attributes and methods) require always the JVM to restart. This is the reason why the Virtual Objects are strongly suggested to being used to build forms to display.

Web IDE

It's planned for the end of 2009 a powerful graphic editor on the Web to change the virtual objects directly from the running application without the need of an IDE.

Not Just Forms

Even though Virtual Objects makes the difference used in the View Aspect, they can be improve the productivity in any Aspect of Roma. Think for example to a service written entirely in Javascript just creating the XML descriptor and annotating it with the Service Aspect.

Below an example of a Virtual Object that extends the Roma's CustomLogin standard POJO used to make the login. Note that by default the language setted is the Scripting Aspect is JavaScript but you can use any language installed using the JSR 223 implementations.

MyLogin.xml




<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<class xmlns="http://www.romaframework.org/xml/roma" xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance"
xsd:schemaLocation="http://www.romaframework.org/xml/roma http://www.romaframework.org/schema/v2/roma.xsd" extends="CustomLogin">
<aspects>
<view>
<form>
<area name="main" type="grid" size="1">
<area name="help" />
<area name="fields" type="grid" size="2" />
<area name="actions" type="row" />
</area>
</form>
</view>
<scripting>
me.field("help", "Please insert your account." );
</scripting>
</aspects>
<fields>
<field name="help" type="String">
<aspects>
<view render="html" />
</aspects>
</field>
<field name="additionalCode" type="String">
<aspects>
<validation required="true" min="5" max="5" />
</aspects>
</field>
</fields>
<actions>
<action name="login">
<aspects>
<scripting>if( me.field("additionalCode") == "12345" ) me.parent.login();</scripting>
</aspects>
</action>
<action name="close">
<aspects>
<scripting>org.romaframework.frontend.RomaFrontend.view().close(me.pojo);</scripting>
</aspects>
</action>
<action name="standardLogin">
<aspects>
<scripting>
<![CDATA[
print('Goto standard login...')
org.romaframework.frontend.RomaFrontend.flow().forward("ProjectLogin")
]]>
</scripting>
</aspects>
</action>
</actions>
</class>

In this example the Virtual Object called “MyLogin” makes the following changes to the class CustomLogin that extends:

  • Add a new field called “help” defined as a String and displayed as HTML on top of all fields (see area definition)

  • Add a new field called “additionalCode” defined as a String. This field define some validation rules: it's mandatory and the length must be of 5 characters

  • In the constructor (see the scripting declaration inside the class) the field help is initialized with a welcome message.

  • The login action is overridden to check if the virtual field “additionalCode” is equals to “12345”. Only in this case calls the super.login(). Not the use of “me.parent” that returns the super class.

  • Add a new action called “close” to close the form. Note the use of “me.pojo” to return the real POJO in Roma.

  • Add a new action called “Standard Login” that show the classic Login form.

You can use a Virtual Object such as normal POJO in Roma. To display the Virtual Object just created write:

public void test() {

RomaFrontend.flow().forward(new VObject("MyLogin"), "screen:popup");
}
Or just:
public void test() {

RomaFrontend.flow().forward("MyLogin");
}
The final result is the image on top of this post.

Enjoy!

mercoledì 9 settembre 2009

Uploaded the new Roma Handbook version 642

Uploaded the new Roma Handbook version 642:
  • Documented the new feature about rendering images: now the type can be a java.net.URL to display remote images or images located in the filesystem outside the project
  • New chapter about creating Wizards