The Web Experience Factory framework enables the creation of very powerful builders that do all sorts of code generation and modification. Many builders are primarily “creation” builders that generate new application elements. For example, the View & Form builder generates multiple pages and supporting code for viewing and updating data from a service. Other builders are primarily “modification” builders that enhance or modify elements that were created by other builders. For example, the Data Layout builder can modify the layout of a page that was created by another builder such as View & Form or Data Page.
Some of the most powerful modification builders are ones that work across a whole application to implement cross-cutting concerns. One example is the Data Field Settings builder, which can modify all the data fields on all pages to control all the rich behavior and appearance of the fields. Builders like this provide a kind of aspect-oriented programming (AOP) functionality.
The attached sample is a custom builder that illustrates how a builder can provice AOP features to automate the implementation of cross-cutting concerns such as logging. The builder "enhances" service operations which are created by other builders such as Service Consumer, Service Operation, SQL Data Services, or many others. This builder modifies all of the execution methods for the service operations and adds calls to LJO methods that can do things like logging. You can use this builder to enhance all the Data Services in a model, or you can select a single Data Service. In this example, the builder does the following:
• Adds an LJO to the WebApp (called serviceEnhancerLjo by default). The LJO in this sample has preServiceCall and postServiceCall methods.
• For each service operation, it generates a new method that will be used instead of the existing service execution method. It does this by calling the Method builder, using the "Rename Existing" option in the Method builder.
• The new method makes three calls: one to "preServiceCall", one to the renamed service execution method, and one to "postServiceCall".
The LJO in the sample code simply writes information to SystemOut, including the service operation inputs and results. For real use it would need to be modified, for example to call logging APIs. It could provide automation and enforcement of your desired practices for logging service call execution.
This type of cross-cutting builder could also be used to add other functionality, such as adding error handlers or other functions that you want to automate. One general high-level goal when using Web Experience Factory is to automate and enforce common best practices, so that you have: (1) simpler model code to develop and maintain; and (2) consistent implementations of the best practices you want to follow.
This builder can be used with any Data Services, in provider or consumer models. If you use the “Modify All Services” option, it will modify
all Data Services in the model. In a consumer model, it will modify the Data Service generated by Service Consumer builders; in a provider model, it will modify the public Data Service as well as any other Data Services such as the ones generated by the SQL Call builder.
Here's the builder user interface:
Here's the output from the LJO when selecting a details link on the sample OrdersServiceConsumer model. In the “PreServiceCall” output you can see the input to the operation, and in “PostServiceCall” you can see the results of the operation.
[4/13/12 14:57:10:943 EDT] 00000087 SystemOut O PreServiceCall model: samples/gettingstarted/OrdersServiceProvider operation: orders/getOneOrder
[4/13/12 14:57:10:943 EDT] 00000087 SystemOut O inputs: <RowToSelectOne xmlns="http://bowstreet.com/services/XMLProvider"><ORDER_ID>000715</ORDER_ID>
</RowToSelectOne>
[4/13/12 14:57:10:943 EDT] 00000087 SystemOut O PostServiceCall model: samples/gettingstarted/OrdersServiceProvider operation: orders/getOneOrder
[4/13/12 14:57:10:943 EDT] 00000087 SystemOut O results: <Row xmlns=""><ORDER_ID>000715</ORDER_ID>
<DATE_ORDERED>2000-02-12</DATE_ORDERED>
<STATUS>Out of Stock</STATUS>
<SHIPPED>false</SHIPPED>
<DATE_SHIPPED>-</DATE_SHIPPED>
<QUANTITY>4</QUANTITY>
<AMOUNT>457.72</AMOUNT>
<BILLING>1</BILLING>
<STATE>MA</STATE>
</Row>
Some notes about how the builder is implemented:
• The builder does all of its work in “POST_CONSTRUCTION” phase of the regeneration process. This lets the builder work correctly even if it's above other builders in the builder call list.
• The builder loops over all the operations in the specified Data Service(s), and for each one, it finds the implementation method name, then generates a new method body that calls the old method. It invokes the Method builder with the “Rename Existing” option enabled, so that the old method will be renamed. If you look in the Application Tree you will see two methods for each execution method, one with a “_renamed” suffix added.
For links to more information on creating custom builders, see the section on custom builders on the “Learning Web Experience Factory” page on our wiki.
The sample package doesn't include a test model, but you can add the builder to any model that includes any Data Services (look in the Application Tree view to see the Data Services in a model). You can use it in provider or consumer models.
Hopefully this example gives a picture of how you can use builders in Web Experience Factory for an AOP approach, to automate the implementation of cross-cutting concerns in an application.