Last year, thanks to the initial idea from Omar del valle Rodriguez, and suggestions of Fabio Maulo, I wrote tasks and templates in my open source code generation tool, AjGenesis, to generate an example of a .NET application, using NHibernate. It shows the use of NHibernate from .NET, using .hbm mapping files (one per class). It generates four applications, two in Visual Basic .NET 2.x, and two in C# 2.0, using DAOs and DDD ideas
The example can be downloaded from the AjGenesis example page at Codeplex. The file is named AjOmar-v1.1.zip.
If you are new to AjGenesis, I wrote some introductory posts:
The base idea in AjGenesis is to use a free-defined model, where you can specify what you want to express for your domain at hands. In this example, I model entities, and from such model, AjGenesis generates complete applications, that you can modify and improve. The model is written in XML files, part of the model is at file Projects/AjOmar/Project.xml:
<Project> <Name>AjOmar</Name> <Description>Example AjOmar for (N)Hibernate</Description> <Prefix>AjOm</Prefix> <Domain>com.ajomar</Domain> <CompanyName>ajomar</CompanyName> <Model> <Entities> <Entity Source="Entities/Client.xml"/> <Entity Source="Entities/Company.xml"/> <Entity Source="Entities/User.xml"/> </Entities> </Model> </Project>
Omar initial project have Company and User , both inheriting from Client. In the database, there are three tables, and NHiberate’s magic is in charge of mapping that entity domain to the corresponding tables.
The User.xml describe the user, according to Omar specifications:
<Entity> <Name>User</Name> <Description>User Entity</Description> <SetName>Users</SetName> <Descriptor>User</Descriptor> <SetDescriptor>Users</SetDescriptor> <SqlTable>users</SqlTable> <Inherits>Client</Inherits> <Properties> <Property> <Name>FirstName</Name> <Type>Text</Type> <SqlType>varchar(200)</SqlType> </Property> <Property> <Name>LastName</Name> <Type>Text</Type> <SqlType>varchar(200)</SqlType> </Property> </Properties> </Entity>
The User entity inherits from Client, described as:
<Entity> <Name>Company</Name> <Description>Company Entity</Description> <SetName>Companies</SetName> <Descriptor>Company</Descriptor> <SetDescriptor>Companies</SetDescriptor> <SqlTable>companies</SqlTable> <Inherits>Client</Inherits> <Properties> <Property> <Name>CompanyName</Name> <Type>Text</Type> <SqlType>varchar(200)</SqlType> </Property> <Property> <Name>ContactName</Name> <Type>Text</Type> <SqlType>varchar(200)</SqlType> </Property> </Properties> </Entity>
There are technology elements, in separate files, as database to use, the language to generate, and other details. So, we can change the technology details without changing the above abstract model. An example of a technology file is Projects/AjOmar/Technologies/VbNet2Nh.xml:
<Technology> <Programming> <Dialect>VbNet2Nh</Dialect> </Programming> <Database> <Dialect>MsSql</Dialect> <Name>AjOmar</Name> <Username>sa</Username> <Prefix>ajom_</Prefix> <Host>(local)</Host> </Database> <NHibernate> <Dialect>NHibernate.Dialect.MsSql2000Dialect</Dialect> </NHibernate> </Technology>
You can change this file to your convenience. Following Fabio Maulo suggestion, there is one .hbm per entity. Using AjGenesis templates and tasks, this is an example of such mapping file, Build/AjOmar/VbNet2Nh/Src/AjOmar.Data/Company.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="AjOmar.Entities" namespace="AjOmar.Entities" > <joined-subclass name="Company" table="ajom_companies" extends="Client"> <key column="Id" /> <property name="CompanyName" type="String"/> <property name="ContactName" type="String"/> </joined-subclass> </hibernate-mapping>
The example generate complete applications, with class library projects and web site to use as presentation layer. The code generation process is invoked from command line, using this four commands from AjOmar folder:
GenerateProject AjOmar VbNet2Nh
GenerateProject AjOmar CSharp2Nh
GenerateProject AjOmar VbNet2DDDNh
GenerateProject AjOmar CSharp2DDDNh
You must add the AjGenesis bin folder to your path. The first two commands generate ASP.NET 2.x applications, in VB.NET and C#, using DAOs that invoke NHibernate. Additionaly, they generate the DDL scripts to create the MS SQL Server database. The last two are similar, but using some ideas from Domain-Driven Design. This is tipical output of the tool:
Under the build folder the applications are generated:
This is the C# application loaded in Visual Studio:
The Web client project implements a navigational model to browse and update entities.
Note: the model is not fixed. You can define the model as you want. This is an example only to show AjGenesis capabilities. But you can write your own model, transformations and templates. AjGenesis is not limited to one predefined model, and you can generate all the text artifacts you want, if you write the corresponding tasks and templates. Sky is the limit!
There are solutions using DDD ideas. They have class library projects:
- AjNHibernate: containing the classes to call NHibernate: configuration, session factory, and session management.
- AjOmar.Domain: Entities, Services, Repositories, a la Evans. There is no Value Objet or Aggregate The services are called Managers: the name service is used in Application project.
- AjOmar.Application: the tier that coordiname the calls to Domain, from presentation.
There is a web application, AjOmar.WebClient, with pages to list, view and update entities:
The idea is to expand this example to generate code that uses Hibernate, Java, EJB3, MySql, and/or Struts2. I have some examples written, but I have to update them to the ideas presented by Omar and Fabio. Code generation for other technologies is the acid test for AjGenesis: from the same model, generate different applications with many technologies. Suggestions, comments, welcome!
Angel “Java” Lopez