Overview : Advices, Advice Instances and Advice Implementation Instances

Advices, Advice Instances and Advice Implementation Instances
This section describes the difference between an advice and an advice instance. Advice is a design-time concept whereas Advice Instance is a run-time concept. An advice defined at design-time in an aspect XML file, has a configuration that includes a reference to a point cut. At run-time, one advice instance is created for every join point that is selected by the point cut. Unless Scoping is specified this is the default behavior. For details refer to, Scopes.
The advice instance is actually the entity that is executed at run-time, not the advice.
Figure 3 shows an advice that gets instantiated and injected before all activities. Since the process has three activities, three advice instances are actually created at run-time.
Figure 3 Advice Instances Created at Run-Time
At run-time, the TIBCO ActiveMatrix BusinessWorks engine may not always create three DocumentLogger instances.. This mainly depends on the scope attribute of the DocumentLogger class. If the scope is "Application", only one java object instance of DocumentLogger is actually created at run-time per TIBCO ActiveMatrix BusinessWorks application. This is very important to understand since it represents the key difference between an advice instance and an advice implementation instance. The instance of the advice implementation (such as the object of the java class that provides the implementation of the advice) is not the same as the advice instance. Three advice instances may in fact share the same advice implementation java object instance.
Figure 4 shows two advice instances sharing the same advice implementation instance.
Figure 4 Two Advices Sharing Same Advice Implementation Instance
Advice Configuration Properties
Advice implementations (i.e. Java classes) can define configuration properties. These properties provide a way for advices to configure the execution of their associated Java class. This is very useful especially when different advices that share the same implementation, want to execute it using different parameter values. For details about how advice implementations can define configuration properties, refer Advice Implementation Properties.
For each configuration property defined in the advice implementation there can be a value set in the advice configuration. If an advice implementation property is not set in an advice, the default value that is specified in the java class, if exists, is used.
Each advice has a <properties> element that contains these property values.
Example 1
An advice with two properties:
<advice name = "Advice1" ...>
<activity where = "Before">
<implementation.java className = "com.tibco.bw.poa.samples.JMSPropertyChangerWithConfig"/>
</activity>
<properties>
<property name = "propertyToModify">Bar</property>
<property name = "propertyToModifyValue">BarValue1</property>
</properties>
</advice>
In this case, the advice implementation (i.e. the JMSPropertyChangerWithConfig java class) defines two configurable member variables:
These two properties are visible and configurable from an advice, in this case Advice1. The @name attribute of the <property> element must match the name of the advice implementation property. If a match is not found, the BW Engine throws an AspectException at the time the engine gets initialized.
Another advice could share the same implementation and configure it in a different way.
Example 2
Advice2 configures its implementation to mutate the same property "Bar" but with a different value:
<advice name = "Advice2" ...>
<activity where = "Before">
<implementation.java className = "com.tibco.bw.poa.samples.JMSPropertyChangerWithConfig"/>
</activity>
<properties>
<property name = "propertyToModify">Bar</property>
<property name = "propertyToModifyValue">BarValue2</property>
</properties>
</advice>
Example 3
Advice3 configures its implementation to mutate a different property altogether:
<advice name = "Advice3" ...>
<activity where = "Before">
<implementation.java className = "com.tibco.bw.poa.samples.JMSPropertyChangerWithConfig"/>
</activity>
<properties>
<property name = "propertyToModify">Abc</property>
<property name = "propertyToModifyValue">Xyz</property>
</properties>
</advice>
Advice Ordering
Advices get injected in processes based on the point cuts that are associated with them. At run-time multiple advices can be injected in the same join point. Sometimes, the order in which these advices get executed is very important and needs to be controlled by the Aspect Developer. The BW engine executes the advices in a specific order, which is computed based on a priority order associated with each advice.
Executing of advices also depends on the process execution flow; which decides the availablity of input or output XML document which is to be used by the advice.
Since the advices that are injected in a specific join point can be specified either in the same or in different aspect files, the priority order of an advice is computed based on:
1.
The value of the @order attribute that is specified on the aspect that defines the advice.
2.
The location (such as the position) of the advice element inside the aspect definition (such as the location inside the XML file). An advice with a position that is closer to the root element <aspect> has a higher priority than an advice that is located farther than the root element.
The optional @order attribute that can be specified on an aspect is used to establish a priority order between different aspects that are applied to a BW project. All advices defined in the same aspect share the same @order attribute value. This value can range between 1 and 255. The lower the number the higher the priority of the aspect. If the @order attribute is not specified, 255 is used by default, which means that the aspect has the lowest priority.
Although the @order attribute is xsd:unsignedByte, 0 is an invalid value. A validation error is thrown if used.
The order in which the advices are specified in an aspect file is very important. The BW engine uses this order to execute the advices that are run when a specific event occurs. This is true regardless of the event (for example, before executing an activity, after an activity returns successfully, and so on). For example, if a target activity throws an exception and there are "after" advices as well as "after throwing" advices injected after the target activity, the order in which these advices execute is influenced by the order in which they appear in the aspect file.
Figure 5 shows two aspect definitions - Aspect-1 and Aspect-2, each one defining a few "Before" advices. The order of Aspect-1 is "2" and the order of "Aspect-2" is 1, which means that Aspect-2 has a higher priority order than Aspect-1.
Figure 5 Aspect Definitions
Assume that the order in which these advices appear in the aspect definitions is exactly the other in which they are shown in this diagram (For example, A is before B, C is before D, and D is before E).
Figure 6 shows that after evaluating the point cuts associated with these advices, the BW Engine injects these two aspects before a specific activity of a process.
Figure 6 Injecting Two Aspects Before Specific Activity in a Process
Since Aspect-2 has a higher priority than Aspect-1, all its "Before" advices will execute before the advices defined in Aspect-1. The order of execution of the advices defined in the same aspect is given by the order in which they appear in the aspect XML file. Therefore, the order in which these advices get executed is shown in Figure 7.
Figure 7 Order of Execution of the Advices
Advice Execution Model
The advices that are injected in a specific join point execute always in sequence. As shown in Advice Ordering, the order in which these advices execute is computed based on the way the aspects are configured as well as the type of the join point.
Here are the details about how these aspects get executed by focusing on other characteristics that are not related to ordering.
It is important to note that an advice always has access to the XML Document as well as the Process Context that is available in the join point where it is injected. The Process Context can provide access to other XML documents that were contributed by the previous activities (such as activities that executed before the join point).
Advices do not contribute to the Process Context new XML documents that are visible to TIBCO ActiveMatrix BusinessWorks activities. Only activities can do that. XML documents contributed by advices are visible only to other advices that execute downstream in the process.
The information available to an aspect for each of the supported join point is:
The XML Document that is passed to a "Before" advice is the same XML Document that had been passed to the target activity, if the advice was not injected in the process. The advice can alter the document but it cannot change its structure. The XML Document that is produced by the advice must be valid against the same schema (such as the schema of the input element), which is defined by the target activity. The same rule applies to all the subsequent advices that are inserted in the same join point. This means that all the XML Documents that flow through all the "Before" advices that are injected in the same join point share the same schema. This is shown Figure 8.
Figure 8 XML Document Passed to a "Before" Advice
In Figure 8, the File-Read-Activity's input type is T1. The advices that are injected before this activity receive at run-time the XML Documents, that are valid against the same schema (such as, they are instance of T1).
The XML Document passed to an "After Returning" advice is the XML Document that is generated by the target activity, if the activity has an output type or it is a null object otherwise. The advice can alter the document but it cannot alter its structure. The XML document that is produced by the advice must be valid against the same schema (such as, the schema of the output type), which is defined by the target activity.
The same rule applies to all the subsequent advices that are inserted in the same join point. This implies that all the XML Documents that flow through all the "After Returning" advices that are injected in the same join point, share the same schema. This is shown in Figure 9.
Figure 9 XML Document Passed to An "After Returning" Advice
The XML Document that is passed to an "After Throwing" advice, is the XML Document that represents the exception thrown by the target activity.
The advice can alter the document (for example, change the exception message, add more information to the exception, and so on) but cannot alter its structure.
The XML document that is produced by the advice must be valid against the schema of the output exception type, which basically means that the advice cannot change the exception type that is thrown by the activity.
Since an activity can report multiple exception types, an "After Throwing" advice has to support multiple XML schema types, which usually makes it difficult to develop. If an advice is interested in a particular exception type, it can use the @exceptionType attribute to specify its QName. The value of this attribute has the following format:
<exceptionType> ::= <exceptionTypeQName> (", " <exceptionTypeQName> )*
<exceptionTypeQName> ::= "{" <exceptionTypeNamespace> "}" <exceptionTypeLocalName>
where,
<exceptionTypeNamespace> is the target namespace of the XML Schema that defines the exception type.
<exceptionTypeLocalName> is the name of the exception type.
This syntax supports multiple QName values incase an advice may want to register its interest in more than one exception type.
To provide a flexible way to select a wide range of exception types, both the exception type namespace as well as the exception type name support "*" wildcards. This is the only wildcard supported.
In such cases, the advice is executed only when an exception instance of that type is thrown by the target activity. All the subsequent advices that are inserted in the same join point follow these rules. The "After Throwing" advices should not throw back the exception that is passed to them. Instead, they should return the exception message when they finish executing.. If an exception is thrown by an "After Throwing" advice, the engine treats it as any other exception thrown by other types of advices. Figure 10 shows an example of two "After Throwing" advices.
Figure 10 Example of Two "After Throwing" Advices
The XML Document that is passed to an "After" advice represents either the output of the target activity or one of its exceptions. The advice can alter the document (for example, change the output message, change the exception message, and so on) but it cannot alter its structure. The XML document produced by the advice must be valid against either the schema of the output XML document or the schema that describes the exception thrown by the activity. This basically means that the same type of document that is passed to an "After" advice is passed to any other subsequent "After" advices that might run in the same join point. While writing an "After" advice a developer should be careful since it needs to handle different semantics (for example, successful returns as well as multiple exception types).
An "After" advice cannot use the @exceptionType attribute to register its interest in a particular exception type. If an exception is thrown by an "After" advice, the BW engine treats it as any other exception thrown by other types of advices. Figure 11 shows an example of two "After" advices.
Figure 11 Example of Two "After" Advices
Any exception thrown by an advice is propagated as a RuntimeException and handled by the BW engine as thrown by the target activity. The engine processes it based on the business logic defined in the process containing the target activity.
Packaging and Deployment of Aspects
This section describes the structure of an aspect JAR and the deployment process of aspect libraries.
Aspects are packaged together in JAR files, that are referred to as "aspect JARs".
An aspect JAR is a JAR file that contains a file with the ".AMF" (Aspect Manifest File) extension in the META-INF folder. There can be only one file with the ".AMF" extension in that folder.
The Aspect Manifest File contains information about where all the aspects are located inside the aspect JAR file. These locations can be specified in two ways:
By specifying a folder name inside the JAR file. All aspects that are part of that folder will be loaded by the BW engine. The BW engine will not locate aspects in the subfolders. The root folder is specified using "" (which is an empty string).
By specifying the full name (like including the folder location) of an individual aspect inside the JAR file.
The AMF file is an XML file that must be valid against the Aspect Manifest File XML Schema. When loading an aspect JAR file, the BW engine validates the Aspect Manifest File against this schema. If validation errors are found, the BW engine throws an AspectException.
The following snippet shows the Aspect Manifest File pseudo-schema:
<bwpoa xmlns = "http://schemas.tibco.com/bw/poa/manifest" ...>
<aspects>
<aspectsFolder>...</aspectsFolder>*
<aspect>...</aspect>*
</aspects>
</bwpoa>
A JAR file that contains aspects but does not contain an Aspect Manifest File, is not recognized by the BW engine as an aspect JAR. Hence none of the aspects defined in that JAR are loaded by the BW engine.
Examples of Aspect Manifest File
An aspect JAR with the following structure:
If the aspects.amf file is the following:
<?xml version = "1.0" encoding = "UTF-8"?>
<bwpoa
xmlns = "http://schemas.tibco.com/bw/poa/manifest"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://schemas.tibco.com/bw/poa/manifest bwpoa.xsd">
<aspects>
<aspectsFolder>auditAspects</aspectsFolder>
</aspects>
</bwpoa>
Then only Aspect1.bwaspect and Aspect2.bwaspect are loaded by the BW engine. The aspects specified in the ExternalMessages folder are not loaded.
However, if the aspects.amf file is the following:
<?xml version = "1.0" encoding = "UTF-8"?>
<bwpoa
xmlns = "http://schemas.tibco.com/bw/poa/manifest"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://schemas.tibco.com/bw/poa/manifest bwpoa.xsd">
<aspects>
<aspectsFolder>auditAspects</aspectsFolder>
<aspectsFolder>auditAspects/ExternalMessages</aspectsFolder>
</aspects>
</bwpoa>
Then,
all the aspects defined in this aspect JAR are loaded by the BW engine. The same behavior could be accomplished by specifying some or even all of the aspects individually. For example, the following manifest file would have the same result as the previous one:
<?xml version = "1.0" encoding = "UTF-8"?>
<bwpoa
xmlns = "http://schemas.tibco.com/bw/poa/manifest"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://schemas.tibco.com/bw/poa/manifest bwpoa.xsd">
<aspects>
<aspect>auditAspects/Aspect1.bwaspect</aspect>
<aspect>auditAspects/Aspect2.bwaspect</aspect>
<aspectsFolder>auditAspects/ExternalMessages</aspectsFolder>
</aspects>
</bwpoa>
Deploying Packaged Aspects in BW Engine
Multiple aspect JARs can be deployed in a BW Engine. When the engine starts up, all these aspect JARs are loaded and their aspects are weaved into the BW Project.
The name of the folder is specified through the following java system property:
aspectPath
This property can be specified in the bwengine.tra. For example:
# BW Aspect Definition Files
java.property.aspectPath
%BW_HOME%/examples/poa/Scenario1/Aspects
Same in the case of folders specified inside aspect JARs, the BW engine does not look at sub-folders when loading aspect JARs. The engine loads only the JARs that are part of this top level folder.
The engine writes out information about all advices that are woven in the TIBCO ActiveMatrix BusinessWorks project. For each process, the engine analyses the advices that are configured to be woven and skips the ones that cannot be woven due to product limitations. After finishing weaving of a process, the engine logs out all advices that were skipped. For more information about the advices that cannot be skipped, read the release notes or contact TIBCO Support.