Chapter 5. Adding your own code to a Jamda-generated application

Contents

Where you need to add your own code
Possible ways of adding code
Merge code from an external source into the generated application
Write implementation code in subclasses of the generated classes
Specify the operation completely in the model so it can be generated directly
Adding code to Jamda-generated classes

A Jamda model compiler will normally generate all the standard "plumbing" for an application, leaving you free to concentrate on the specific business logic code. This section describes how to add your own code to the generated application in order to implement your own specific requirements.

Where you need to add your own code

Many kinds of class that your model compiler generates will need no extra code. For example, a Value Object whose only purpose was to act as a carrier of data across a network would usually only have code for setting and getting properties. This code would all follow a predictable pattern, and could be entirely generated. However, where you generate implementations of the business objects in your application, you will need to add your own code to the application to implement the calculations and business rules that the system requires. For example, if you were generating Entity Enterprise Java Beans, some methods, such as those required by the EJB specification, and the CMP field accessors, would be generated by the model compiler. However, you will need to provide the code for the business methods of the EJB in some way.

Possible ways of adding code

Merge code from an external source into the generated application

The code generator looks up the code for the hand-coded methods from an external source, such as an XML code file with an element for each method. This produces the cleanest generated code, but it is a difficult system to use. It is difficult to write correct code unless you can actually compile the source file to check it, so the hand-written code needs to be part of a valid Java source file. Jamda includes a tool, XmlScraper, to extract method body code from Java source files and place it in an XML file. It would be possible with this tool to create a "round-tripping" system, whereby you edit the generated source, then extract the hand-coded method bodies and include them in the next generation run. This approach may initially appear attractive, but it has certain disadvantages:

  • In most projects, anything written by hand should go into a source control system. Files that are generated should not usually be under source control. So what do you do with the files that have been generated and then modified? This will cause a serious clash with most source control procedures.

  • You may want to add private variables or helper methods. The Jamda tools do not cater for reverse-engineering these back into the UML model, so these would be lost when the system was regenerated. Even if this facility was available, it is not very desirable. The UML input model is meant to be at a higher level of abstraction than the generated source code, so it should only include those features that are related to the specification of the system, rather than implementation features (the "what", not the "how"). Introducing private implementation features into the UML model would "pollute" it. The same applies if you add the helper methods and variables to the input model directly, so that they are included in the generated application.

Write implementation code in subclasses of the generated classes

The model compiler generates an abstract class that contains all the variables and methods that can be generated, leaving out the methods that need to be hand-coded. The developer creates a subclass of the generated class that includes these methods. The generated code and hand-coded methods go into completely separate files. This approach may appear more cumbersome, but its advantages include:

  • No source control clashes - the hand-coded files go under source control, the generated ones do not

  • You can add private variables or helper methods as necessary to the hand-coded classes.

  • You can override generated methods if there are occasional exceptions to the rules used by the model compiler

  • The code you edit is directly compiled into the generated application, so there are no problems with line numbers being different for debugging, for example

Specify the operation completely in the model so it can be generated directly

This is probably the best solution in the long term, but it will need much more development in languages to specify operations and the technology to create efficient implementations from these specifications.

Adding code to Jamda-generated classes

It is recommended that you follow the subclassing method for adding your own custom code to generated classes. To do this:

  • When designing your architecture, decide which kinds of classes will require custom code.

  • For these kinds of classes, decide which attributes and operations can be generated from the information in the input model, and which will be hand-coded

  • Create a generator for a base class that includes the generated attributes and operations. You may want to include "placeholders" for the hand-coded methods, perhaps as comments or abstract methods.

  • For each of the generated base classes, create by hand a subclass that extends the generated base class, and fill in the necessary methods and variables. The subclass name should be related to the base class name by a consistent naming convention. You can add any "helper" methods or variables necessary. You can even override an individual generated method if you wish.

  • Optional: instead of writing the subclasses from scratch, you can create a generator for the subclass that will produce a skeleton ready to have the code filled in. If you do this, take care that this generator is not run by accident to overwrite files in which you have already filled in the code

  • If you need to refer to these classes in any other part of the system, you will usually want to refer to the subclass, not the generated base class. For example, if this method is used to generate EJBs, you might generate a class XYZBaseBean, and code the business method implementations in a subclass XYZBean. In the deployment descriptor, you would need to specify XYZBean as the bean class.

  • You may want to generate part of the code for an Operation, and hand-code the rest. For example, you may want to have generated code at the start of your method to log the call and at the end to log the result. This can be achieved using the Template Method pattern. Generate a method that includes the logging statements, and calls another abstract method in between that will do the work. In your implementation subclass, code this abstract method, rather than the original method.