I've added the ability to pass an XMI file to CFC Stub Generator (now at version 1.5) and use that to generate the CFCs, unit tests, and associated files. XMI is an XML format that describes UML, and I believe that most UML tools will export this format.

Using UML to define the CFCs gives a great deal more control over what gets generated. I've created another Captivate presentation to describe the new capabilities:


The files and SVN repository at the CFC Stub Generator RIAForge project have also been updated. You can also get to the RIAForge project download via the link in the right sidebar. The zip and SVN repository now include sample XMI and zuml files to help get you started.

Full details on the improvements:

The Stub Generator can generate components based on an XMI data file. XMI is a standard XML format for describing UML diagrams. I have only tested this with Poseidon UML, but as far as I know any UML tool that can export to XMI should work. Note that the location of the XMI file used in the generation will be used as the base location for the test suite files (the test suite files will be placed in a subdirectory called 'testsuite' beneath the folder containing the XMI file).

  • Built-in ColdFusion data types: The cfctemplate.zuml file already has the necessary data types created to represent most of the built-in ColdFusion data types like query, struct, etc. It also has some Java data types defined since Posiedon will try to create these and they can interfere with the CFC generation. It is crucial that you type all argument and return types using these types, even if you pick the 'any' data type.
  • Packages: Poseidon supports the creation of packages and I suggest using them. The generator will use the package paths for any CFC or interface components and use these when adding argument types, return types, extends, and implements. It also uses the package paths to create the ColdSpring XML, test suites, and ANT build XML files. The package paths are determined relative to the web root. Thus, if you have a package in your UML that resolves to 'myapp.components.beans', the CFCs in that package will be generated to the web root-relative path '/myapp/components/beans'.
  • CFCs: CFCOMPONENT stubs will be generated for all objects in the UML diagram. The name of each component corresponds to the object name given in the UML diagram. Any text included in the Poseidon 'documentation' tab for that object will be inserted into the 'hint' attribute of the CFCOMPONENT tag.
  • CFC Init Methods: Init methods are ignored when generating test methods in the unit test files. Init methods should be given a return type matching the CFC type.
  • CFC Methods: CFFUNCTION stubs will be generated for all methods in the UML diagram. The 'returnType' attribute will be populated with the return type specified in the UML diagram (including concrete CFCs, abstract CFCs, or interfaces). Any text included in the Poseidon 'documentation' tab for that method will be inserted into the 'hint' attribute of the CFFUNCTION tag.
  • CFC Method Arguments: CFARGUMENT tags will be generated for all method parameters specified in the UML diagram (including concrete CFCs, abstract CFCs, or interfaces). Any text included in the Poseidon 'documentation' tab for that parameter will be inserted into the 'hint' attribute of the CFARGUMENT tag.
  • Abstract Methods: Abstract methods are generated with a body containing a CFTHROW tag which specifies that the method is abstract and must be overridden by a subclass. Also, abstract methods are ignored when generating test methods in the unit test files.
  • Inheritance: Inheritance is included in the generated CFCs by applying the 'extends' attribute of CFCOMPONENT or CFINTERFACE.
  • Interfaces: If you incorporate interfaces in your UML, CFINTERFACE files will be created for each interface. If an object in your UML implements one or more interfaces, those interfaces will be added to the 'implements' attribute of the generated CFCOMPONENT tag as a comma-delimited list. If an interface extends one or more interfaces, those interfaces wil be added to the 'extends' attribute of the generated CFINTERFACE tag as a comma-delimited list. Any text included in the Poseidon 'documentation' tab for that interface will be inserted into the 'hint' attribute of the CFINTERFACE tag. Note that as of this writing, interfaces are only supported by ColdFusion 8.
  • Composition and Aggregation: The tool does detect aggregation or composition between components, but I was not sure how to actually use this information. This is because any composed objects have to be passed into the object either in the constructor or a setter. I really can't try to generate these automatically since I would have no way of knowing whether to use constructor or setter injection. If anyone has any ideas on how knowing about composition might be helpful in the generated code please let me know. I suppose I could have it generate a hint or comment in the CFC documenting the relationshipS?
  • Unit Tests: Unit test methods will be created for any public methods in the corresponding CFCs. Unit test files will be created in a 'test' subdirectory of each package, and will contain tests for the CFCs in that package.
  • Test Suites: CFCUnit/CFUnit test runners, ColdSpring XML, and ANT build XML files will be created in a 'testsuite' subdirectory of the directory where the XMI file used to generate the CFCs was read from.

Comments Comments (10) | del.ico.us del.icio.us | Digg It! Digg It! | Linking Blogs Linking Blogs | 12885 Views

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)

  • # Posted By Jason Blum | 6/12/07 8:25 AM

    This is pretty damn cool Brian. Don't know which is more useful: your presentation or the Stub Generator. With MX8, any thoughts about running this tool online like http://rooibos.maestropublishing.com/ and <cfzip>'ing up the resulting files for download? Thanks for sharing. Very cool stuff.

  • # Posted By Brian | 6/12/07 10:01 AM

    Thanks Jason. Actually the tool itself runs fine on CFMX 7 (and probably 6.1 too). It's only the generated components that will require CF8 if you choose to specify interfaces in the UML. Maybe I will look at running the tool online, thanks for the idea!

  • # Posted By Chip Temm | 6/12/07 11:03 AM

    Cool! I had started down this route with my OpenModel project a couple of years ago ( http://coldfusion.sys-con.com/read/289659_2.htm ) but haven't had the time to keep it moving forward. Also CFOpen seems to have closed shop on me, so I'll have to put my stuff somewhere else. Your feature list is pretty similar to mine and I hit my head in the same place- composition/aggregation. Do you think ColdSpring might help with that?

    I'm going to download your project and take a look. This is definitely the right direction to go: all of those 'generate a CFC from your data model' things are coming at design from the wrong end.

  • # Posted By Brian | 6/12/07 11:08 AM

    Thanks, Chip. I'm still not sure what I could do with the aggregation information even with ColdSpring. Because you have to define getters and setters for the composed beans in order for ColdSpring to be able to inject the target bean, those methods are already there. The only thing I could do is autogenerate the getters and setters for composed objects, but then I'm forcing setter injection on people, and some folks prefer constructor injection. And since it is so easy to define the methods in Poseidon, it wouldn't save much time anyway (10 seconds? heh).

  • # Posted By Justin Carter | 6/12/07 8:45 PM

    Nice one Brian, this is a very cool tool! Seeing UML -> CF code is impressive, espcially with the CF8 stuff thrown in already :)

  • # Posted By Paul Marcotte | 6/13/07 6:18 PM

    Hi Brian,

    Great work adding xmi support for the Stub Generator! I recently switched to using VioletUML for diagramming, simply for the ease of use as an eclipse plugin (on Windows at least). Unfortunately, it does not appear that you can export to xmi. :( If folks out there are not inclined to pay monthly for Poseidon Community Edition, ArgoUML (http://argouml.tigris.org/) is an alternative.

    Regarding aggregation v. composition, I think that it is less a matter of using constructor or setter injection and more a matter of whether the dependent object is a singleton or not. So, in your generated ColdSpring xml, a composition would have the attribute singleton="false", whereas an aggregation would use singleton="true".

  • # Posted By Sammy Larbi | 6/14/07 7:45 PM

    Brian, awesome work.

    Now if I start using UML more often ... =) Actually, UML could become much more useful for me in this case, but I normally only model things that are hard to understand without the diagram.

    Seriously though, this will save a lot of programmers a lot of time, so nice work!

  • # Posted By Joseph Lamoree | 6/21/07 4:42 AM

    I think link 177 of CFCStubGeneratorFromXMI.cfc should have an edit:
    arguments.cfcData.cfcPath should be arguments.cfcData.path

  • # Posted By Brian | 7/2/07 11:46 AM

    @Paul - Thanks for the kind remarks. Not sure I agree though about the idea of aggregation and composition. Neither of these actually implies a Singleton. Consider the two scenarios:

    A ContentElement aggregates one or more Style objects. This is aggregation because nn individual instance of a Style object could be aggregated to one or many ContentElements.

    A Car composes four Tire objects. This is composition because the tires on a car can only belong to ONE car at a time.

    In neither case is there necessarily a Singleton involved. Even though a Style object can be associated with many ContentElements at a time, there still could be multiple Style objects representing different styles. Hopefully that makes sense.

  • # Posted By Michael Cole | 1/9/08 12:38 PM

    Thanks but
    cfm can't take the future of web ,
    i like php
    cfm is a little unknown still