I’m back! I want to write in this post about the new features I’ve added to my code generation project AjGenesis. The main points are:
– A new interactive way to use it, a web based application
– Examples with that new interface, to generate C#, VB.Net, Java and PHP applications, all from the same abstract model
These features were published last January at release 0.5 in CodePlex
Using AjGenesis
Years ago, I began to work in this project. Those days, the only way to execute and use it were the console, with commands. Later, I adopted NAnt, and NAntGui, as interfaces to launch the system and execute tasks and transformations. The project can be used as a set of .DLLs, referenced from custom application. Carlos Marcelo Santos has published posts (in Spanish) about how to use AjGenesis from NAnt
Cómo generar código con AjGenesis sirviéndonos de NAnt
Cómo generar código con AjGenesis sirviéndonos de NAnt – Parte II
Last year, 2007, Jonathan Cisneros wrote a great Windows interface, named AjGenesis Studio:
AjGenesis Studio: una IDE para AjGenesis
AjGenesis Studio at CodePlex
As an exercise at the end of year 2007, I wrote a new project in the original solution, and I published last January inside the last release 0.5 at CodePlex.
It’s a new web project, that I called, inspired by the work of Jonathan, AjGenesis Web Studio
The main point is, with this project, to show that the functionality from the AjGenesis core can be used and exposed in our applications, this time from a web interface, using ASP.NET. With this approach, we can put a server in our internal network or at Internet, and create, edit, upload and download user defined models, generate source code, and download the results. We could call this, Code Generation as a Service.
Let’s look the project, its functions and some inners.
The project
It’s a web project, named AjGenesis.WebStudio.
To launch it, load the AjGenesis.sln solution (located at src directory inside the version 0.5 from CodePlex) with Visual Studio 2005, and build the complete solution.
(If you have errors in the AjGenesis.WebStudio project, probably you must add a reference to a .DLL that manages the file compressions. Add as reference to the project the file src\Libraries\Ionic.Utils.Zip.dll. This library generates .zip files, and expand them).
In the web solution, I used Master Pages, and a default Theme. It doesn’t manage a database, only files and directories. We’ll see below that the project has a mini wiki, to write help pages that can be defined by the user.
The look and feel is simple, but you can change the theme and master page to obtain a better result.
The system can generate code in the fly, and download it as a .zip file. You can use the classic AjGenesis system, as I explained in past post, but now, we can use it from any browser. You don’t need .NET in your client machine, and you can work from other operating systems.
After the build of the solution, click right mouse button on the file \Default.aspx in project AjGenesis.WebStudio, and choose View in browser…:
This is preferred to launch the project in debug mode: if you debug the project, it will execute the code generation task in very slow way.
Working Directory
The system uses a working directory, with a structure that resembles the examples at AjGenesisExamples3.zip (to download from examples at CodePlex). The default working directory is AjGenesis.WebStudioWorkingDirectory:
Some directories:
Projects: There is a directory here for each project model.
Templates: Containing the template files to process during the code generation phase
Build: The code generated code resides in this directory.
The working directory can be changed using the left menu option Working Directory and then, choosing the option Change Working Directory:
Generating Hello World
As I used to comment in my speeches, the acid test of all code generation system is to help us to model and produce the most simple and universal software system, the reknowed Hello World example. There is an explanation on how to do this with classic AjGenesis in my post
Code Generation with AjGenesis- A Hello World application
In AjGenesis Web Studio, select the left menu option Generate. This is the result page
There are two dropdown list. We’ll see how they are filled. At the first list, there are the defined projects:
Choose HelloWorld. Then, go to technology list, showing:
In this project, only Java and Net20 are the defined technologies. Other projects have more technologies. Choose Java and the press the Generate button. After a while, the page shows a result.
How this works?
First point, the system manage a working directory, the default is AjGenesis.WebStudioWorkDirectory, a syster directory of the web project. There is a Projects project, cointaining more directory, each one is a project for the system.
The directory AjGenesis.WebStudioWorkDirectory\Projects\HelloWorld has a Project.xml file that describes the free model we use in this case:
<Project>
<Name>HelloWorld</Name>
<Description>HelloWorld Example</Description>
<GenerateTask>GenerateHelloWorld</GenerateTask>
<Message>Hello World</Message>
</Project>
Inside the directory project, there is a Technologies directory. Each XML file that is found there it’s managed as a technology model in the system. Again, as I explained in my posts on AjGenesis , this file has a free model, you can put here anything to process from code generation process. The concepts of project and technology is not mandatory, but AjGenesis Web Studio takes them as special directories, and read them to obtain the list of project and associated technologies.
The technology Java.xml file contains:
<Technology>
<Name>Java</Name>
</Technology>
and Net20.xml contains:
<Technology>
<Name>Net20</Name>
</Technology>
Nothing special. The value Name inside Technology drives what steps to execute during code generation phase.
After press the generate button, the system loads the project and technology model in memory. Then, it executes the file GenerateCode.ajg located in directory Tasks. But if the project file contains a GenerateTask tag, as in this project, that file is executed instead the default one. This is the content of Tasks\GenerateHelloWorld.ajg:
PrintLine "Generating HelloWorld..."
if not Project.BuildDir then
Project.BuildDir = "${WorkingDir}Build/${Project.Name}"
end if
if not Project.Title then
Project.Title = Project.Name
end if
if not Project.Version then
Project.Version = "1.0.*"
end if
if not Project.Language then
Project.Language = "en"
end if
if not Project.SystemName then
Project.SystemName = Project.Name
end if
PrintLine "Creating Directory ${Project.BuildDir}"
FileManager.CreateDirectory("${Project.BuildDir}")
Include "Tasks\BuildHelloWorld${Technology.Name}.ajg"
This file is written in an scripting language, a pillar of AjGenesis, affectously named AjBasic. The Project variable is the representation in memory of the tag <Project> loaded from the Project.xml file, described above. In memory, it is as an object, with properties. It’s not an static object: you can add properties in runtime, as Project.Version in the above text. If in an if sentence we asks the value of Project.Version and this doesn’t exist, it’s not an error, the result is simply Nothing and that value is treated as false for boolean evaluations (like in other languages, notably PHP).
Finally, the last line includes an additional file to process dinamically. The string contants in AjBasic have expression expansion: all between ${ and } is evaluated. Using the value of Technology.Name (obtained from loading in memory the XML technology file), it executes BuildHelloWorldJava.ajg or BuildHelloWorldNet20.ajg. The first one contains the steps to generate a .java file:
<#
PrintLine "Generating Solution ${Project.Name}"
if not Project.Title then
Project.Title = Project.Name
end if
if not Project.Version then
Project.Version = "1.0.*"
end if
PrintLine "Creating Directories"
FileManager.CreateDirectory("${Project.BuildDir}")
FileManager.CreateDirectory("${Project.BuildDir}\${Technology.Name}")
TransformerManager.Transform("Templates\HelloWorld\ClassJava.tpl", "${Project.BuildDir}\${Technology.Name}\HelloWorld.java", Environment)
#>
This code uses inner AjGenesis utilities that create directories and expand a template file. ClassJava.tpl contains:
//
// Automatically generated by AjGenesis
// http://www.ajlopez.com/ajgenesis
//
public class HelloWorld {
public static void main(String[] args) {
System.out.println("${Project.Message}");
}
}
All this produces the directory Build\HelloWorld\Java:
If we choose the Net20 technology, more files would be generated:
This is a more complete result. It has a VS 2005 solution file, two project directories, one in VB.NET and the other in C#, with source code and project files:
To see the generated code, its files and directories, go to left menu option Builds:
There is a directory for each project. You can download a complete directory, as a .zip file. We can create a file, download a directory, upload and expand a .zip file, and consult a help page. We can read, edit, and delete each file, in this case readme.txt.
Go to the View at HelloWorld directory:
You can browse directories, upload and download files. You can move a directory, or make a copy, to experiment without loosing the original content.
Generating C# and VB.NET solutions
After this simple example, let’s go for more. For more information about the next examples and their models, read:
Application Generation using AjGenesis
Go again to left menu Generate option. Now, we choose a project, AjSecondExample. Its technology list is more complete:
Choose CSharp2 and generate. This process creates a complete solution inside Builds\AjSecondExample\CSharp2. There is an Sql directory with DDL script to create a MS SQL Server database. Inside the Src directory, you’ll find the solution, composed of a set of projects:
This projects follows a layered archictecture, that you can modify from the templates. They use a data access layer, based on my AjFramework project, but you can change to access Enterprise Library or your own data services.
You must create the database using the generated scripts, and modify the connection string in the web.config to match your environment. The application can be compiled and executed:
The administration page shows:
Back to generate page, execute the VbNet2 technology, obtaining a directory with the same structure, now with Visual Basic.NET code:
All these depend of the specified technology inside the files at Projects\AjSecondExample\Technologies. The content of VbNet2.xml is:
<Technology>
<Programming>
<Dialect>VbNet2</Dialect>
</Programming>
<Database>
<Dialect>MsSql</Dialect>
<Name>AjSecondExample</Name>
<Username>sa</Username>
<Prefix>ajse_</Prefix>
<Host>(local)</Host>
</Database>
</Technology>
and CSharp2.xml:
<Technology>
<Programming>
<Dialect>CSharp2</Dialect>
</Programming>
<Database>
<Dialect>MsSql</Dialect>
<Name>AjSecondExample</Name>
<Username>sa</Username>
<Prefix>ajse_</Prefix>
<Host>(local)</Host>
</Database>
</Technology>
These data are used during the code generation process.
Note: inside Tasks\BuildTechnology.ajg file, you’ll find a new variable, injected from the web project:
if not Project.BuildDir then
Project.BuildDir = "${WorkingDir}Build/${Project.Name}/${Technology.Programming.Dialect}"
end if
This is the WorkingDir variable that points to the working directory we selected in AjGenesis Web Studio.
Genarating Java and JSP applications
Many projects (AjFirstExample, AjSecondExample, AjTest….) can be generated in Java with JavaServer Pages. A build.xml file is generated to be modified and used to compile the generated code using the ant utility (you can use this file from an IDE, like Eclipse or NetBeans).
The target build makes a .war deploy file. You can browse and modify the build.xml file to install the .war in a Tomcat web container.
The generated code is composed of .jsp files (web pages in Java) and Java code to compile that implements a service layer and a data access layer, exchanging simple JavaBeans between layers. The DDL script, in these examples, is a MySql one.
If you build and deploy the application, and install the database in a MySql server, you can see it working fromn a Tomcat server:
Generating application using Domain-Driven Design ideas and Hibernate, NHibernate
Many example projects (AjFirstExample, AjSecondExample, AjTest…) have defined technologies CSharp2DDDNh, JavaDDDHb, VbNet2DDDNh, and even VbNet2Nh. The DDD ones implement some concepts from Domain-Driven Desigg, as Application, Domain and Infrastructure layer, but the templates could be improved. The *Nh projects generate code for entities using NHibernate mapping. The *Hb projects use Hibernate.
An example of NHibernate generated mapping:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="AjFirstExample.Domain.Customer, AjFirstExample.Domain" table="ajfe_customers">
<id name="Id" column="Id" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property column="Name" type="String" name="Name" length="255"/>
<property column="Address" type="String" name="Address" length="255"/>
<property column="Notes" type="String" name="Notes" length="255"/>
</class>
</hibernate-mapping>
These solution can be built as the previous examples. You’ll see better generator templates for NHibernate in the AjOmar example at CodePlex. Post (in Spanish) explaining the process at
Generando código para NHibernate (Parte 1)
Generando código para NHibernate (Parte 2)
Generando código para NHibernate (Parte 3)
Generating PHP applications
If you choose PHP technology, web page with PHP code are generated, using MySql as database. The generated code can be copied to a directory in a web site that supports PHP, Apache, or IIS. AjTest example running in a IIS with PHP4:
Other directories
In the working directory, there are other directories:
SourceCode: Containing some source code that is copied into the solution during code generation.
Libraries: Additional .dlls, to copy and use in the generated applications.
The larger subdirectory is Templates:
In previous posts I described in detail the creation and use of a template file. This is the content of a template that generate a C# entity:
<#
rem Entity Generator
rem for C Sharp
include "Templates/CSharp2/CSharpFunctions.tpl"
message "Processing Entity ${Entity.Name}"
include "Templates/CSharp2/Prologue.tpl"
#>
/*
* Project ${Project.Name}
* ${Project.Description}
* Entity ${Entity.Name}
* ${Entity.Description}
*
*/
using System;
namespace ${Project.SystemName}.Entities {
public class ${Entity.Name} {
// Private Fields
<#
for each Property in Entity.Properties
message "Processing Field ${Property.Name}" #>
private ${CSharpType(Property)} ${CSharpFieldName(Property)};
<# end for #>
// Default Constructor
public ${Entity.Name}() {
}
// Public Properties
<#
for each Property in Entity.Properties
message "Processing Property ${Property.Name}"
#>
public ${CSharpType(Property)} ${Property.Name}
{
get {
return ${CSharpFieldName(Property)};
}
set {
${CSharpFieldName(Property)} = value;
}
}
<#
end for
#>
}
}
Help pages
I’m testing some ideas in this web project. There are code to create “wiki” pages, that can be used as help pages in the system.
You can edit this kind of pages:
There is a way to insert links to other wiki pages and to external ones. The page data is represented as a .NET object in memory, and that object is serialized in an XML file in Pages application directory. There is no database to store page: each one is an object, serialized in a .xml file.
Conclusions
I hope this system helps to a better understanding of AjGenesis project features and potential. With a more user friendly interface, the project can be used by more people. We can generate code from command line, or using NAnt utility, or AjGenesis Studio.
I ever remark a point: all these are examples, AjGenesis is not limited to generate only this kind application. You are in charge: you can define the model that matches your project requirements, using any technology you choose. You can codify DDD ideas in a different and better way. You can generate Hibernate/NHibernate mappins using other patterns and mapping idioms. You can use other ORM utilities, and generate code for them. You can generate PHP5 pages that use Prado, instead of plain PHP4. You can generate stored procedures for Oracle, instead of my examples that use MS SQL Server. Or write better ones. You can generate WinForms code, instead of ASP.NET page. You can generate JavaServer Faces pages, views, beans, and abandon JavaServer Pages. You can generate the code or text you want: e.g., unit tests, or documentation pages. I recommend that the generated code resembles the code you could generate manually.
I invite anyone that uses this system, to post his/her work, or leave comments here. You can participate in the Spanish list:
http://groups.google.com/group/codegeneration?hl=es
Next steps
Back to develop, I have some ideas:
– Improve the templates to generate more technologies, as VS 2008 projects, solutions, templates for Struts 1/2, Spring, better mapping for Hibernate, NHibernate, and code generation for the new ASP.NET MVC.
– Write posts about these templates
– Publish the new examples
– Write down a useful documentation (now, it’s minimal: you can found more details in this posts)
Enjoy the project!
Angel “Java” Lopez
http://www.ajlopez.com/en