Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Use Eclipse JET to Automate Model-Driven Development Aspects : Page 3

Get the lowdown on the Eclipse JET code generator and learn how to use it to automate your development processes.


advertisement
A Model Driven Approach
The following example is a bit more involved: you must generate a full-featured Model-View-Controller Java implementation to handle a completely agnostic model. The following listing shows the model for this example:

<scaffold project="ScaffoldSample" srcdir="src"> <model name="Product" > <definition> <column name="id" type="int" id="true" /> <column name="title" type="String" size="50" /> <column name="description" type="String" /> <column name="price" type="double" /> <column name="category" type="com.devx.model.Category" /> </definition> <controller name="Admin" > <operation type="list" /> <operation type="create" /> <operation type="update" /> <operation type="delete" /> </controller> </model> <model name="Category" > <definition> <column name="id" type="int"/> <column name="name" type="String" size="40" id="true" /> </definition> <controller name="Admin" > <operation type="list" /> <operation type="create" /> </controller> </model> </scaffold>

The example model is overly simplified, but you can easily extend the concept to deal with real-world scenarios. For example, you can use the same approach to generate DDL instructions for your database or stubs for your web framework (such as Struts or Spring). The attached code provides further examples for these specific cases.



Although simple, the example model does sport some common features, such as entity relationships and primary keys (identified by the id attribute). In the same way as in the previous example, the main.jet file will start by creating classes for both the MVC models and controllers. This snippet is from the model creation section:

<java:package name="com.devx.model"> <c:iterate select="/scaffold/model" var="currModel"> <java:class name="{$currModel/@name}" template="templates/ModelClass.java.jet" /> </c:iterate> </java:package>

Next, templates such as ModelClass.java.jet will populate the single classes. The following listing shows the template snippet that creates getter and setter methods for every column of the input model, including validation checks where needed (for example, String length verification). Notice the usage of particular functions provided by JET, such as camelCase() to adapt strings to Java naming conventions.

public class <c:get select="$currModel/@name" /> { <c:iterate select="$currModel/definition/column" var="currColumn" > public <c:get select="$currColumn/@type" /> get<c:get select="camelCase($currColumn/@name)" />() { return <c:get select="$currColumn/@name" /> ; } public void set<c:get select="camelCase($currColumn/@name)" /> (<c:get select="$currColumn/@type" /> <c:get select="$currColumn/@name" /> ) { <c:if test="$currColumn/@size" > if (<c:get select="$currColumn/@name" />.length() > <c:get select="$currColumn/@size" />) { throw new IllegalArgumentException("Invalid Size!"); } </c:if> this.<c:get select="$currColumn/@name" /> = <c:get select="$currColumn/@name" /> ; } private <c:get select="$currColumn/@type" /> <c:get select="$currColumn/@name" />; </c:iterate> // ... omissis ... other class methods }

The template also automatically generates stub equals() and hashCode() methods, which the user can safely customize thanks to the userRegion tag described previously.

Once the model classes are ready, you can generate controllers. The following snippet shows how a controller that stores its model in internal collections implements the create operation:

public <c:get select="$currModel/@name" /> create( <c:iterate select="$currModel/definition/column" var="currColumn" delimiter=", " > <c:get select="$currColumn/@type" /> <c:get select="$currColumn/@name" /> </c:iterate> ) { <c:get select="$currModel/@name" /> obj = new <c:get select="$currModel/@name" />(); <c:iterate select="$currModel/definition/column" var="currColumn" > obj.set<c:get select="camelCase($currColumn/@name)" /> (<c:get select="$currColumn/@name" />); </c:iterate> <f:lc><c:get select="$currModel/@name" /></f:lc>List.add(obj); return obj ; }

Here's the generated code for the case of the Category model:

public Category create(int id, String name) { Category obj = new Category(); obj.setId(id); obj.setName(name); // dummy object storage, real apps // should serialize to database here. categoryList.add(obj); return obj ; }

Proceeding in this way for all the other elements of the input model, you finally end up with generated code that successfully passes the following unit test:

public void testProductCRUD() { ProductAdminController controller = new ProductAdminController(); Category cat = new Category(); cat.setId(1); cat.setName("Luxury cars"); Product p1 = controller.create( 1, "A car", "A very beautiful car", 2000.0, cat); Product p2 = controller.create( 2, "A city car", "A very economic car", 500.0, cat); assertEquals(controller.getList().size(), 2); controller.updateDescription( 1,"A very expensive car"); assertEquals(p1.getDescription(), "A very expensive car"); controller.delete(1); assertEquals(controller.getList().size(), 1); }

This is quite an achievement, considering how simple the original input model is. The code generator has extracted a lot of information from the model and transformed it into working code.

Model Code Generation
Now you know how to use JET to define transformations that generate source code or other artifacts according to your models. More generally, you now have an additional way to further abstract your development activities and concentrate on the specific business problem at hand.

JET offers a lot of advanced features that this article didn't cover, including the following:

  • Framework extensibility, which let users define transformations and easily share them
  • Richer tag libraries tailored for specific needs
  • The capability to integrate the entire JET engine into your Eclipse-based applications
  • Integration with the Eclipse Modeling Framework (EMF) to obtain a full-featured MDD environment (no more need to generate both the database definitions and the Java model classes manually!)

If you want to further explore the technology, download the attached sources to find other code-generation examples not described in the article.



Riccardo Govoni has been working since 2003 as a J2EE developer on a variety of applications ranging from financial services to middleware in the IP television field. He currently works for Google as a software engineer. He is a Sun Certified Java Programmer (SCJP).
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap