Levi9 Tech Blog



Tuesday, January 29, 2008

Lightweight Code Generator

For the Ministries projects for Ordina there was a need to write the Java code based on database schema. Websites of the Ministries are based on Hippo CMS, Cocoon, Java and JPOX (a JDO implementation) for persistance layer. Large amount of data is periodically exported on one system and imported to our system.
The majority of the application was generated with ddl2hbm (database to Hibernate mapping) tool but lot of changes on Hibernate 2 tools code was needed.

Hibernate tools also enable generating hibernate mapping from Java class (class2hbm) and vice versa (hbm2java). Since the tool is in Java (no templating supported) it was quite hard to make the changes to meet specific needs.
Based on idea that Hibernate mapping “look a like” XML (extended with several attributes or tags) is used the idea for lightweight code generation tool arrose. The tool should be easily extensible and template based. This is the reason why Jakarta Velocity is used as a simple, yet very effective template engine.
Code generator enables easy code generation based on simple model and easy to write templates. It enables code generation for Java, .NET, PHP, … basically everything that is object oriented.
Based on input model (similar to Hibernate mapping) and Velocity template(s) result is generated in the output directory.

Input model:
<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping>
<class name="nl.levi9.cmt.woonfonds.Complaint">
<id name="id" type="int">
<generator class="identity">
</id>
<property type="String" name="title" name="Title" null="true">
<property type="String" name="email" name="E-mail" null="true">
<property type="int" name="visible" name="Visible" null="true">
</class>
</hibernate-mapping>

Template:
## Bean.vm
#parse( "Macros.vmm" )
#copyright()
package ${class.Package};

import nl.levi9.cmt.entity.GenericBean;
import nl.levi9.cmt.exception.AuthorizationException;
import nl.levi9.cmt.security.Security;
import nl.levi9.cmt.security.SecurityFactory;
import nl.levi9.cmt.util.logging.LogManager;
import nl.levi9.cmt.util.logging.LoggerInterface;
import nl.levi9.cmt.navigation.Project;

/**
* ${class.Name} bean
#vas()
$class.Access class ${class.Name} extends GenericBean {

/** Logger */
private static LoggerInterface logger = LogManager.getLogger(${class.Name}.class);
// Fields
#foreach($att in $class.Attributes)
#set ($access = $att.Access)
$att.Access ${att.Type} ${att.Name} = ${utility.defaultValue(${att.Type}, ${att.defaultValue})};
#end
$access Project project = null;

// Set methods
#foreach($att in $class.Attributes)
public void ${att.setterSignature()}(${att.Type} ${att.Name}) { this.${att.Name} = ${att.Name}; }
#end
public void setProject(Project project) { this.project = project; }

// Get methods
#foreach($att in $class.Attributes)
public ${att.Type} ${att.getterSignature()}() { return this.${att.Name}; }
#end
public Project getProject() { return this.project; }

// Copy method
public ${class.Name} copy() {
${class.Name} cc = new ${class.Name}();
#foreach($att in $class.Attributes)
cc.${att.setterSignature()}(this.${att.Name});
#end
cc.setProject(this.project);
Security sec = null;
try {
sec = SecurityFactory.createSecurity(
SecurityFactory.${class.Name.toUpperCase()}, null, cc);
} catch (AuthorizationException e) {
logger.warn(e);
}
cc.setSecurity(sec);
return cc;
}
}

Generated source:
/*
* Copyright (c) 2007 Levi9. All Rights Reserved.
*/
package nl.levi9.cmt.woonfonds;

import nl.levi9.cmt.entity.GenericBean;
import nl.levi9.cmt.exception.AuthorizationException;
import nl.levi9.cmt.security.Security;
import nl.levi9.cmt.security.SecurityFactory;
import nl.levi9.cmt.util.logging.LogManager;
import nl.levi9.cmt.util.logging.LoggerInterface;
import nl.levi9.cmt.navigation.Project;

/**
* Complaint bean
* @version 3.0
* @author cosmos@mailinglists.levi9.com
* @since 09-10-2007
*/
public class Complaint extends GenericBean {

/** Logger */
private static LoggerInterface logger = LogManager.getLogger(Complaint.class);
// Fields
protected int id = 0;
protected String title = "";
protected String email = "";
protected int visible = 0;
protected Project project = null;

// Set methods
public void setId(int id) { this.id = id; }
public void setTitle(String title) { this.title = title; }
public void setEmail(String email) { this.email = email; }
public void setVisible(int visible) { this.visible = visible; }
public void setProject(Project project) { this.project = project; }

// Get methods
public int getId() { return this.id; }
public String getTitle() { return this.title; }
public String getEmail() { return this.email; }
public int getVisible() { return this.visible; }
public Project getProject() { return this.project; }

// Copy method
public Complaint copy() {
Complaint cc = new Complaint();
cc.setId(this.id);
cc.setTitle(this.title);
cc.setEmail(this.email);
cc.setVisible(this.visible);
cc.setProject(this.project);
Security sec = null;
try {
sec = SecurityFactory.createSecurity(
SecurityFactory.COMPLAINT, null, cc);
} catch (AuthorizationException e) {
logger.warn(e);
}
cc.setSecurity(sec);
return cc;
}

}

Further reading:
http://today.java.net/pub/a/today/2004/05/12/generation1.html
http://www.onjava.com/pub/a/onjava/2004/05/05/cg-vel1.html
http://www.codegeneration.net/
http://jakarta.apache.org/velocity/
http://www.andromda.org/
http://xdoclet.sourceforge.net/xdoclet/index.html
http://www.codesmithtools.com/


posted by Damir Solajic
+ Read comments 0 comments
 

Monday, November 13, 2006

Views on a new technology


Once in a while – it can be a few months or a few years – a typical programmer reaches a point in which he or she feels: “I have been doing this specific task over and over again”.


Developers are naturally inclined and professionally formed to minimize the effort spent for “repetitive tasks”. This leads to less time needed for development of an application and to a shift of work to the most interesting parts – the real, core logic of the application, the nicest pieces of functionality which presence will make a customer and a development team happy.


This natural desire is especially to be taken into account when working in a highly dynamic environment, where a project has requirements that evolve during its life; where various teams are building different functionalities of the same application (or even module), sometimes accessing the same resources, objects or files; where groups of people, with different background, skills and qualifications are attacking the same projects from a developer, project manager or customer angle; where technology knowledge and methodology can vary from developer to developer, from team to team, from development center to development center; where business, technology, deployment requirements are complex and can be simplified by using a structured, block-oriented way of thinking and designing.


Results are poor if in this environment architects and programmers must frequently address topics such as:

- how is data going to be exported from my module to the rest of application
- what is the general layout of our user interfaces
- how many layers does my application have, what are standard protocols for invoking methods of those layers

Not only time is consumed for repetitive tasks (both "horizontally" and "vertically", the programmer itself is repeating those activities, but others in other teams might too), but the quality of the results is usually diminished – time and resources will not be oriented towards the really important and visible features of the application, but will be spent for building this base of the application, which is prioritized because no other task is possible in its absence.


Typical events that occur in such a development environment are:


- Different technology is used by different developers to solve the same issue inside a project, which leads to the dissolution of the accepted architecture – generally the obtained result is a “no-architecture”, an unstable mix of different approaches
- Untraceable technical issues – “did that problem originate from my solution?”; “Is my approach the one that’s being most used or endorsed by other architects?; “Do I have to document my solution or go over the official ones that have been used so far?”
- Hazardous interactions between modules – “we thought that we should call that method from here, not from there…why isn’t the rest of the system designed to support this approach? We have discussed on…and you replied on…”
- Unreadable and unmanageable code, especially for parts that involve more than one developer / team or that are iterated multiple times throughout the project’s life
- Dramatic increase in bugs, with the additional problem that the process of identifying a bug takes longer since it can simply be an architectural misunderstanding/misuse
- Overall feeling of a non-architected application, of a product that does not resemble the requirements even if the problems are not coming from a lack of features but from a lack of unity
- Time-consuming activities are performed and are distracting the effort from where it should go – realizing the main functionalities, the logic of the application, providing added value in user interfaces or functionality gadgets

This is where a framework comes in.

A framework is a tool that is usually designed for a specific programming environment and serves, as its name suggests the purpose of “framing” the development work. It sets up a comfortable but standardized environment for the developer to work in by doing the following:

- provide quick and reliable solutions for the most usual tasks, such as basic data operations, method calls, event handling, querying
- facilitate the creation of complex structures based on small, atomic solutions that are already included in the interface
- diminish or eliminate the need for technical documentation regarding various solutions implemented in the applications and offer a common discussion platform for design and architecture
- specify and enforce n-tier architecture
- specify and enforce coding standards

As an advanced feature, the framework can even provide standardized interfaces that are generated on-the-fly based on requirements passed to it. Generation of a window with filters, grids, panels, tabs, fonts and fields that link to physical data objects can be completely automated.

The developer is now working in a structured approach, using the methodology offered by the framework. Although it does not discourage creativity and flexibility, the framework makes sure that all the parts of the application will speak the same language, regardless of their purpose, origin, behavior or aspect.

Frameworks have been constantly included in Progress releases through time, such as Dynamics or ADM2. With early 2006 a new application that is maturing into a framework is being developed by Progress Software NL together with partners in Romania, one of them being the company I work for, Levi9 Global Sourcing.

Under the name of OESDK (Open Edge Software Development Kit) a methodology for managing data across a n-tier application is implemented. Based on the OERA standard (Open Edge Reference Architecture) the framework divides the application in layers – User Interface, Business Logic, Data Access Logic and Database. Using an UML modeling tool the architects create various objects, such as Database Design, Temp-Tables (Progress-Specific data structures) and ProDataSets (collections of temp-tables), Data Access Objects, Business Logic Objects, Interface diagrams all which, when ran through the OESDK application, are turned into meaningful Progress code for the corresponding layer.

The generated code enforces standard communication between the parts and adds important features, such as security checks, context management and object factories.

Currently various components of this framework are developed by partners in Europe such as Levi9 Global Sourcing and endorsed by important companies in The Netherlands interested in upgrading to this managed way of developing applications.

For someone that has been closely involved in developing and using frameworks written in technologies such as .NET, the experience is meaningful since it is the first time I have been working directly with the team that initiated such a project and that is handling its development.

The main characteristic of a project called “Developing a framework” is that the framework is developing…itself.

A first application is built with the minimum set of existent framework functionalities – usually related to handling data – and a “wish list” is being composed. Based on that, the framework’s developers go through a new iteration to provide missing functionality that can be built on the initial set. This process can continue indefinitely until the completion of the framework.

A constant and interesting challenge in such an effort is related to the support of your framework. Since the framework itself is a need coming from real-life projects, it is normal to construct it while maintaining a close contact with potential customers for applications using your tool. They can act as a “steering committee”, providing guidance in what can sometimes be a very exhaustive effort so that the most important and application-related functionalities of the framework are being constructed at a given moment. This committee maintains the communication between the framework’s logic and the specific application requirements that the committee has or plans to have in the future.

To address this topic, Progress built a group of both managers and developers interested in constructing and enriching the OESDK framework. Those two groups meet regularly to establish the short and medium plans of action for developing the framework.

Another important topic is the need of throughout documentation of the framework. When lots of development teams are using the framework in their real-life projects, when issues, questions and version are coming from all directions, the team(s) that develop(s) the framework must maintain a strict documentation and versioning system to ensure that:
- Each new version of the framework contains documents that explain what are the new features, what old implementations are obsolete, how have the past solutions been improved
- Each development team is working with a stable release of the framework
- The upgrade process between versions of the framework is smooth and (ideally) results in little to no architectural changes (no new applications to install, no settings to change) It makes sense that the tools to report issues, track changes and maintain framework solutions are provided by the team developing the framework since they have access to the entire information regarding it.

Interesting moments in developing a framework such as OESDK are the ones in which a new technical problem coming from a real customer had to be addressed – specific functionalities that were not “literally” implemented in the framework.

It is always an important choice between:

a) Postponing the functionality for the next release of the framework
b) Implementing the desired functionality with the existing features of the interface

Each solution has advantages and disadvantages.

The first solution leads to an enhancement in the framework, that is going to be used on further applications as well, and the functionality itself will gain from all the structures of the interface – it will be properly integrated in it from the point it is created, it will be documented and its issues will be tracked through the framework support system.

The second one is best used for functionalities that are very peculiar to that application’s situation and requirements so that it makes little sense to force it to become a framework feature.

In the beginning of the life of the framework, most solutions will fall into the first group since any new functionality is likely to be needed in the framework. When the product matures most requirements have to be implemented by developers and rarely translate into a new framework feature.

What is most important in such a project can be summed up as: communication. Between teams working on the interface and teams working on actual products using it, between management looking for features to be implemented and management distributing the request through different versions of the framework, between all the parts involved in this effort to simplify development and enrich the quality of real-life applications.

The present article serves the same purpose of communication by picturing the environment in which a framework is being created and readied for large-scale usage. It will be followed by articles focusing on specific issues that have or have not been addressed here. For questions, details and materials related to the general topic of developing frameworks or to the actual OESDK environment please contact the members of this blog or the author at b.vulcan@levi9.com.

posted by Bogdan Vulcan
+ Read comments 0 comments
 

Thursday, September 14, 2006

Tomorrow it happens: Progress Software is hosting the first OE-SDK user group meeting for decision makers in The Netherlands. The goal of the user group is to share knowledge and experience on working with the OE-SDK as well as discuss the functionality of future releases.

The Progress Center of Excellence at Levi9 in Bucharest is one of the first users of the OE-SDK and is even part of the development community that develops on the SDK itself. In this Blogspot we want to share our experience, give hints and tips and discuss relevant Open Edge SDK topics. We are looking forward to your questions as well. You can mail them to
info@levi9.com


posted by Unknown
+ Read comments 0 comments
 

 

Links

Get the RSS Feed
Levi9 Global Sourcing

Previous Posts

Lightweight Code GeneratorFor the Ministries proje...
Views on a new technologyOnce in a while – it can ...
Tomorrow it happens: Progress Software is hosting ...

Archives

September 2006
November 2006
January 2008

Powered by Blogger
Levi9 Global Sourcing | Jan van Goyenkade 8 | 1075 HP Amsterdam | The Netherlands | +31(0)206701947 | info@levi9.com
Copyright © Levi9 | www.levi9.com | www.levi9.de