Introduction

I'll start apologizing the name of this project, it isn't great! The PojoGenerator is a utility that will generate test data for your data model. This is great when, for instance you have a separate back-end and front-end development team and the back-end developers are not done yet or the webserver an other team is building is not done. You as front-end developer could continue to develop you front-end by letting the PojoGenerator fill your data model. It could also be useful when you want to develop outside the office and the database must remain there for security reasons.

How does it work

The PojoGenerator is build using Spring and if your application also uses spring it's dead simple to get it going. If you do not use spring, don't worry you can still use it. So your're backed isn't done yet so you properly defined an interface. This is we're the PojoGenerator steps in. The PojoGenerator dynamically implements this interface by using spring aop. When you're code uses one of the methods of you're interface the PojoGenerator will try to figure out what domain object it needs to create, this is what we call Domain item revolving, methods to determine this) and instantiate it. Domain item resolving there are currently two different types:

  • 'return type' analysis
  • 'method name' analysis

'Return type' analysis is a simple method by using reflection we can easily figure out what to return. This will only fail when you're program expects an collection and you are using java1.4. 'Method name' will take the name of method and try to find a domain model object name in it. So if you're interface has a method like findAllCatByName, this method will succeed and know it's Cats we need to instantiate. So the PojoGenerator knows what object to create, than it needs to initialize the fields of this object. When you don't configure anything it's hard to generate useful data. The PojoGenerator comes with standard instantiators for the common classes for example an int in your domain object will get a random value between 1 and 15. This is properly not an very good value for the cat age, or what ever the field in you're domain model represents. To produce more "meaningful" data a configuration needs to be made in xml. We'll discuss the configuration in chunks in the end we'll put it all together.

generators

This section is used to register generators, a generator is a object that creates object of an specific type. Per field of you domain object you can specify which generator should be used. If nothing was specified the one marked as default will be used. The PojoGenerator comes with a lot of generators and provides a simple interface to write your own.

Below you'll find that we registerd 4 generators each takes a few parameters to configure them you can find out about these in the javadocs if it says default="true" if not configured differently this generator will be used for instances of this class.

   <generators>
      <generator id="numberGenerator" generatorClass="nl.beesting.beangenerator
        .generator.IntegralNumberInstanceGenerator" defaultGenerator="true">
         <parameters>
            <parameter name="from" value="1"/>
            <parameter name="until" value="15"/>
         </parameters>
         <generates-for-classes>
            <java-class>java.lang.Integer</java-class>
            <java-class>java.lang.Long</java-class>
         </generates-for-classes>
      </generator>
      <generator id="reGenerator" generatorClass="nl.beesting.beangenerator
        .generator.RegularExpressionInstanceGenerator" defaultGenerator="true">
         <parameters>
            <parameter name="sloppy_mode" value="true"/>
            <parameter name="debug" value="false"/>
         </parameters>
         <generates-for-classes>
            <java-class>java.lang.String</java-class>
            <java-class>java.lang.StringBuffer</java-class>
         </generates-for-classes>
      </generator>
      <generator id="wordlistGenerator" generatorClass="nl.beesting.beangenerator
        .generator.WordListInstanceGenerator">
         <parameters>
            <parameter name="dictonaryLocation" value="kitten_names.txt"/>
         </parameters>
         <generates-for-classes>
            <java-class>java.lang.String</java-class>
            <java-class>java.lang.StringBuffer</java-class>
         </generates-for-classes>
      </generator>
      <generator id="colorGenerator" generatorClass="nl.beesting.beangenerator
        .generator.ColorInstanceGenerator">
         <generates-for-classes>
            <java-class>java.awt.Color</java-class>
         </generates-for-classes>
      </generator>
   </generators>

class-definitions

This section is used to specify 2 things, you can define what generators should be used when creating domain objects and you can override the Domain item revolving. In the example below:

 <class-descriptor id="cat" class="nl.beesting.beangenerator.example.Cat" 
      collection-type="java.util.ArrayList">
   <field-definitions>
     <field-descriptor name="name" class="java.lang.String"
generator="reGenerator">
      <parameters>
         <parameter name="mask">
            <value><![CDATA[ [A-Z]{1}[a-z]{1,10} ]]></value>
         </parameter>
      </parameters>
     </field-descriptor>
   </field-definitions>
</class-descriptor>

This configuration "tells" the PojoGenerator when it's creating objects of type Cat use the regular expression generator when it's instantiating the name field. So when name strings are generated the generator will make sure that the result matches the regular expression. You don't have to specify all the fields for the left out fields the default generators will be used. You can also override the "Domain item revolving" by specifying something like this

<class-descriptor id="catService" class="nl.beesting.beangenerator.example.
  service.CatService" collection-type="java.util.HashSet">
    <field-definitions>
        <field-descriptor name="findCats" class="nl.beesting.beangenerator.example.Cat"/>

The configuration will make sure that when the findCats method of the CatService is called, objects of type Cat will be created. This is useful when the other Domain item resolving methods fail, or when you want a specific subtype to be created. Note that you can also specify what type of collection should be used to return collections. This way you can easily generate test data that will live up to you're expectations. Now we've seen descussed the entire configuration we'll put it all together

<?xml version="1.0" encoding="UTF-8"?>
<bean-generator-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="pojo-generator-config_1_0.xsd">
   <generators>
      <generator id="numberGenerator" generatorClass="nl.beesting.beangenerator
        .generator.IntegralNumberInstanceGenerator?" defaultGenerator="true">
         <parameters>
            <parameter name="from" value="1"/>
            <parameter name="until" value="15"/>
         </parameters>
         <generates-for-classes>
            <java-class>java.lang.Integer</java-class>
            <java-class>java.lang.Long</java-class>
         </generates-for-classes>
      </generator>
      <generator id="reGenerator" generatorClass="nl.beesting.beangenerator
        .generator.RegularExpressionInstanceGenerator">
         <parameters>
            <parameter name="sloppy_mode" value="true"/>
            <parameter name="debug" value="false"/>
         </parameters>
         <generates-for-classes>
            <java-class>java.lang.String</java-class>
            <java-class>java.lang.StringBuffer</java-class>
         </generates-for-classes>
      </generator>
      <generator id="wordlistGenerator" generatorClass="nl.beesting.beangenerator
        .generator.WordListInstanceGenerator">
         <parameters>
            <parameter name="dictonaryLocation" value="kitten_names.txt"/>
         </parameters>
         <generates-for-classes>
            <java-class>java.lang.String</java-class>
            <java-class>java.lang.StringBuffer</java-class>
         </generates-for-classes>
      </generator>
      <generator id="colorGenerator" generatorClass="nl.beesting.beangenerator
        .generator.ColorInstanceGenerator" defaultGenerator="true">
         <generates-for-classes>
            <java-class>java.awt.Color</java-class>
         </generates-for-classes>
      </generator>
   </generators>

   <class-definitions>
      <class-descriptor id="catService" class="nl.beesting.beangenerator
        .example.service.CatService" collection-type="java.util.HashSet">
         <field-definitions>
            <field-descriptor name="findCats" class="nl.beesting.beangenerator
              .example.Cat"/>
            <field-descriptor name="findCatById" class="nl.beesting.beangenerator
              .example.Cat"/>
         </field-definitions>
      </class-descriptor>

      <class-descriptor id="cat" class="nl.beesting.beangenerator.example.Cat"
        collection-type="java.util.ArrayList">
         <field-definitions>
            <field-descriptor name="name" class="java.lang.String" 
              generator="reGenerator">
               <parameters>
                  <parameter name="mask">
                     <value><![CDATA[ [A-Z]{1}[a-z]{1,10} ]]></value>
                  </parameter>
               </parameters>
            </field-descriptor>
            <field-descriptor name="age" class="java.lang.Integer" 
              generator="numberGenerator"/>
         </field-definitions>
      </class-descriptor>

      <class-descriptor id="kitten" class="nl.beesting.beangenerator
        .example.Kitten" collection-type="java.util.ArrayList"/>
         <field-definitions>
            <field-descriptor name="name" class="java.lang.String" 
              generator="wordlistGenerator"/>
            <field-descriptor name="color" class="java.awt.Color" 
              generator="colorGenerator"/>
         </field-definitions>
      </class-descriptor>
   </class-definitions>

</bean-generator-config>

For more examples also look at the provided demo application.

Installation

Download the jar from sourceforge, put it in you projects classpath and put import the spring context from the jar in you spring context with:

<import resource="classpath:applicationContext-beangenerator.xml"/>

Create the aop proxies like so

<bean id="yourDao" 
    class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="proxyInterfaces">
        <value>com.mycompany.MyDao</value>
    </property>

    <property name="interceptorNames">
        <list>
            <value>beanCreationIntereptor</value>
        </list>
    </property>
</bean>

edit configuration and you're ready to go. Also see the demo application for a working example.

Feature Request

If you have feature request please send them to erikjan_dewit@sourceforge.net