Copyright © TIBCO Software Inc. All Rights Reserved
Copyright © TIBCO Software Inc. All Rights Reserved


Chapter 1 Overview : Advice Implementations

Advice Implementations
TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in provides support for executing advices developed in JAVA. TIBCO ActiveMatrix BusinessWorks defines both a JAVA API as well as a set of annotations that have to be used for creating advice implementations.
Relationship between an advice and its implementation is very important.
Multiple advices can be implemented with the same implementation. Therefore, there is a many-to-one relationship between advices and their associated java implementation.
An advice implementation provides the business logic of an advice.
Java Annotations for Advertising Advice Implementation Metadata
TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in defines a couple of java annotations that are used for advertising aspect specific metadata. These annotations are defined in the package com.tibco.bw.poa.runtime.annotation.
The following section describes these annotations.
The @AdviceImpl Java Annotation
This annotation is used for tagging java classes as advice implementations. This annotation is specified on a class, in the following way:
@AdviceImpl
public class MyAdviceImplementation … {
}
Table 4 describes the 5 optional parameters.
Advertises the data access mode (for example, read-only vs. read-write).
Advertises whether the advice implementation hibernates jobs
Advertises the kind of the target or join point where the advice implementation gets instantiated.
Advertises an activity type name, which can be used to further narrow down the scope of the target.
scope
Advice implementations get instantiated in different scopes, which can be controlled using the scope parameter. The valid values of this parameter are the following:
One instance of the advice implementation is created for an application. In TIBCO ActiveMatrix BusinessWorks 5.9, the application equals to a BW Project, which means that one instance of the advice is created in a ActiveMatrix BusinessWorks engine.
If the scope parameter is set to a different value than the one mentioned above, the ActiveMatrix BusinessWorks engine throws an AspectException at run-time, when the engine gets initialized.
This example of an advice implementation that uses the application scope:
@AdviceImpl (
scope = "APPLICATION"
)
public class MyAdviceImplementation … }
}
dataAccess
Advice implementations access the data in a way that can be classified in two categories:
Advice implementations that need read-only access to the data
Advice implementations that need read-write access to the data
An advice implementation advertises the category it belongs to by setting the dataAccess parameter. The valid values of this parameter are the following:
The advice implementation mutates the data, hence needs read or write access to it.
The advice implementation does not mutate the data, hence needs read-only access to it.
If the dataAccess parameter is set to a different value than the ones mentioned above, the ActiveMatrix BusinessWorks engine throws an AspectException at run-time, when the engine gets initialized.
Following is an example of an advice implementation that mutates the XML document:
@AdviceImpl (
dataAccess = "READ-WRITE"
)
public class MyAdviceImplementation … {
public void execute(N input, AspectProcessContext context) {
// the advice implementation mutates the data here…
}
}
Hence, an advice implementation that mutates the data must explicitly set the dataAccess parameter to "READ-WRITE". If an advice implementation that mutates the data does not set this parameter appropriately, a ClassCastException is thrown at run-time, when the advice implementation tries to use a mutable XML processing context.
hibernatesJobs
Advice implementations can hibernate and resume jobs. If an advice implementation uses this feature, then it must explicitly declare that it is done through the hibernatesJobs parameter. The valid values of this parameter are:
Following is an example of an advice implementation that hibernates jobs:
@AdviceImpl (
hibernatesJobs = true
)
public class MyAdviceImplementation … {
public void execute(N input, AspectProcessContext context) {
if (need_to_hibernate_job) {
context.setHibernateJobEnabled(0);
}
}
}
The default value of this parameter, which is used when the user doesn't explicitly set it, is false.
If an advice implementation attempts to call the API to hibernate a job without explicitly setting the hibernatesJobs parameter to true, an AspectException is thrown at run-time. This exception may result in the job to be terminated abnormally, depending on how exceptions are handled at the process level.
When accessing the incoming XML document, advice implementations may or may not be dependent on a particular schema. For example, an advice implementation that changes the value of a JMS property in a JMS message sent by the JMSQueueSendReceive activity is dependent on the format (like XML schema) of the JMSQueueSendReceive activity's input message.
For this advice implementation to work, it has to be hardcoded to expect the XML document in this specific format.
Activities that are hardcoded to a specific XML schema can only be instantiated and executed in a context where the incoming document conforms to that particular schema.
A way is provided to the advice implementation developer to declare a dependency of a particular instantiation context through the use of two parameters defined as part of the @AdviceImpl annotation: targetKind and targetFilter.
targetKind
This is used for specifying the kind of the target or join point where the advice is instantiated. This parameter can have one of the following values:
The advice implementation must be instantiated only before activities.
The advice implementation must be instantiated only after an activity, on the path that executes when the activity returns successfully.
The advice implementation must be instantiated only after an activity, on the path that executes when the activity throws an exception.
The advice implementation must be instantiated only after an activity, on the path that executes regardless on whether the activity returns successfully or throws an exception
If the targetKind parameter is set to a different value than the ones mentioned above, the ActiveMatrix BusinessWorks engine throws an AspectException at run-time, when the engine gets initialized.
The default value of this parameter, which is used when the user doesn't explicitly set it, is "". By default, advice implementations do not depend on a particular context (can be executed anywhere).
targetFilter
When the targetKind parameter is set, the developer of the advice implementation can also specify a target filter, using the targetFilter parameter, which is used to further narrow down the scope of the instantiation context. Using this parameter, the developer can specify the type of the activity around which the implementation can be instantiated. For example, the developer can specify the advice implementation that can only be instantiated in the context of a FileReadActivity. The value of the parameter (the filter) is the same as the value of the activity() primitive's "type" parameter that is defined as part of the Point Cut Query Language.
The default value of this parameter, which is used when the advice implementation developer does not explicitly set it, is "". By default, advice implementations can be executed in any context.
Following is an example of an advice implementation that must be instantiated and executed before JMSQueueSend activities.
@AdviceImpl(
targetKind = "ACTIVITY-BEFORE",
targetFilter = "bw.JMSQueueSendActivity"
)
public class JMSPropertyChanger ... {
}
When the Aspect engine gets initialized, the engine checks these two parameters and uses them to validate the aspect configurations. If an advice is about to be instantiated in a context that is not valid, the engine throws an exception.
Important: It ensures that the engine failure is fast when aspects are not properly configured.
A more complicated example shows how all these parameters can be used together. The following is a singleton advice implementation that requires read-write access to the data to hibernates jobs. It must be instantiated and executed before JMSQueueSend activities.
@AdviceImpl(
scope = "APPLICATION",
dataAccess = "READ-WRITE",
hibernatesJobs = true,
targetKind = "ACTIVITY-BEFORE",
targetFilter = "bw.JMSQueueSendActivity"
)
public class JMSPropertyChanger ... {
}
Enable Aspect Engine Logging
To enable tracing for Aspect Engine, set the AspectEngine.Trace property to true in a cfg file. This file should be passed as an argument to the ActiveMatrix BusinessWorks engine.
The @Property Java Annotation
This annotation is used for marking public member variables defined in advice java implementations as properties (like, advice implementation properties).
Following is an example of an advice implementation property:
public class AdviceImplExample<I, U, N extends I, A extends I, S, T, X>
extends SyncAdvice<I, U, N, A, S, T, X> {
@Property
public String currency = "$";
...
}
Advice Implementation Properties
Advice implementations can define configuration properties that are used for configuring the behavior and execution of the java class. For example, an advice implementation that changes the value of a JMS property may choose to define the name of the JMS property using an advice implementation property.
TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in makes these advice implementation properties visible and configurable from advices. This means that two advices that have the same implementation (that are implemented with the same java class) can specify different values for the same property. In the example in The @Property Java Annotation, there could be two or more advices that want to mutate JMS properties. These advices can share the same implementation and each one can configure it with a different JMS property name.
@Property Java Annotation Optional Parameters
 
required
The advice implementation developer can declare an advice property either required or optional by setting this parameter.
A required advice property must be set in every advice that uses the implementation class that defines it. The ActiveMatrix BusinessWorks engine throws an exception at the time the engine gets initialized, if it finds a required advice implementation property that is not set in an advice.
The default value, which is used when the "required" parameter is not set, is true. Therefore, by default, advice properties are required to be set in the aspect files.
Advice implementations advertise configuration properties through the use of the @Property annotation. The following example shows an advice implementation with two properties:
@AdviceImpl(
dataAccess="READ-WRITE",
targetKind="ACTIVITY-BEFORE",
targetFilter="bw.JMSQueueSendActivity"
)
public class JMSPropertyChangerWithConfig<I, U, N extends I, A extends I, S, T, X> extends SyncAdvice<I, U, N, A, S, T, X> {
@Property
public String propertyToModify ="foo";
@Property (required = false)
public String propertyToModifyValue = "defaultFooValue";
...
}
Restrictions Imposed by TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in for Advice implementation Properties
Only properties of string type are supported. If the Aspect Engine detects a property of a type different than string, it throws an exception at initialization time.
Member variables that are exposed as advice configuration properties must be declared public. If the ActiveMatrix BusinessWorks Engine detects a property that is not declared public, it throws an exception at initialization time.
At run-time, when an advice is instantiated, the ActiveMatrix BusinessWorks engine injects in the advice instance, the property values that are specified in the aspect XML file.
The ActiveMatrix BusinessWorks engine can inject these property values by accessing the member variables directly.
All advices that share the same implementation instance (for example, when using an implementation configured with an APPLICATION scope) must have the same property values. The ActiveMatrix BusinessWorks Engine configures the implementation instance at the time the first advice that is using, it gets instantiated. If a subsequent advice that uses the same implementation instance is instantiated, the ActiveMatrix BusinessWorks engine validates that all its properties have the same values as the properties set on the advice implementation instance. If a mismatch is found, the ActiveMatrix BusinessWorks Engine throws an exception.
To avoid unnecessary null pointer exceptions at run-time, it is highly recommended that all advice implementation properties have default values specified in the java class.
Refer Advice Configuration Properties about how property values are set in aspect files.
Scopes
At run-time, during its initialization process, the ActiveMatrix BusinessWorks Engine integrates aspects into ActiveMatrix BusinessWorks processes. As part of this process, the ActiveMatrix BusinessWorks engine instantiates advices and injects them in different join points inside processes. Since each advice has an implementation associated with it, which is represented as a Java class, the ActiveMatrix BusinessWorks engine either creates an instance of this class or takes one from a pool of already created object instances. ActiveMatrix BusinessWorks 5.9 supports binding multiple advice instances to the same advice implementation java class instance through the concept of scoping.
The two Advice Implementation Scopes supported are:
Since scope is an attribute of the advice implementation, it is configured at the java class level in an annotation. This means that all advices using the same advice implementation java class, have the same scoping configuration.
Advice Scope Mode
The Advice scope is used when a new advice implementation object instance must be created for every advice instance. This mode is usually used when multiple advices that share the same implementation do not need to share any state. Figure 12 shows this Advice Scope mode.
Figure 12 Advice Scope Mode
Despite one advice implementation object instance being created for every advice instance, the developer of the advice implementation java class will still have to be aware of the data concurrency issues.
Since an advice instance runs in a multi-threaded environment, potentially serving multiple process instances (such as, jobs) at the same time, each job is executed in a different thread.
Application Scope Mode
The Application scope is used when the developer of the advice implementation java class wants to ensure that only one advice implementation object instance is created for the entire application. In TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in, it means that there is one object instance per engine. Hence, all advice instances that are implemented with the same implementation share the same advice implementation object instance. Figure 13 shows the Application Scope mode.
Figure 13 Application Scope Mode
XML Document Access
When it executes, an advice implementation has access to the XML document that is available in a particular context (like, join point). This XML Document is build based on a schema, which is again dependent on the context. For example, when it runs before an activity, the XML Document must be valid against the XML Schema that defines the input type of the activity.
In order to provide a deterministic behavior that allows the engine to fail fast when configuration issues are detected, TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in provides a declarative way of specifying metadata about advice implementations. This metadata is primarily driven by the following two main questions, a developer of an advice implementation needs to answer.
Not all advice implementations mutate the incoming XML document. If the engine knows that an advice does not mutate the XML document, it can perform some optimizations, such as not requiring a revalidation of the document after the execution of the advices.
In TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in, an advice cannot mutate the incoming XML document unless it explicitly states that it does it, in the advice implementation metadata. For details about how to configure an advice to allow the mutation of the XML document, refer The @AdviceImpl Java Annotation.
Figure 14 shows two advices, one that mutates the XML document and another that does not mutate the XML document.
Figure 14 Read-Only vs. Read-Write Data Access
 
The XML document is passed as an input parameter to the execute() method that is defined as part of the Advice Implementation Java class. The following is the signature of the method:
public N execute(N inputDoc, AspectProcessContext context)
throws AspectException;
The XML document is the first input parameter (like, "inputDoc"). TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in uses gXML (Generic XML) as the data model, which allows it to support multiple underlying XML tree models such as DOM, Axiom, and so on. For more information about gXML and general information on how to manipulate an XML document with gXML, refer to References in the TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in API Reference.
In order to manipulate an XML document, the advice implementation must get access to the gXML processing context object, which is an instance of org.gxml.sa.GxProcessingContext. This object can be retrieved by an advice implementation from the advice's context, in the following way:
GxProcessingContext<I,U,N,A,S,T,X> pContext = getAdviceContext().getGxProcessingContext();
This object is then used for traversing and pulling information from the XML document. This object cannot be used for mutating an XML document, though. In order to mutate an XML document, the advice implementation needs to get a mutable gXML processing context, which is an instance of org.gxml.sa.GxProcessingContextMutable. Since this class extends GxProcessingContext, the way to retrieve a mutable processing context is very similar to the way to retrieve the immutable processing context (like, note the extra type casting):
GxProcessingContextMutable<I,U,N,A,S,T,X> pContext = GxProcessingContextMutable)getAdviceContext().getGxProcessingContext();
If an advice implementation type casts the returned value of getGxProcessingContext() to a mutable processing context without explicitly setting the @AdviceImplementation or dataAccess parameter to "READ-WRITE", the previous call throws a ClassCastException at run-time. That is since the engine injects a mutable processing context in an advice instance only if its implementation is mutable.
Packaging and Deployment of Advice Implementations
Advice implementations are packaged in JAR files and need to be available in the CLASSPATH at run-time in order for the engine to properly instantiate advices. It does not really matter how these advice implementations are packaged in JAR files. What is important is that all the advice implementations (like, java classes) are referenced by advices to be available in the CLASSPATH at run-time, at the time the ActiveMatrix BusinessWorks engine gets initialized.
TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in does not support loading a JAR file in the CLASSPATH at run-time, after the engine has been initialized. Therefore, unless it gets restarted, the ActiveMatrix BusinessWorks engine cannot execute an advice implemented with a java class that was not available in the CLASSPATH at initialization time.
The TIBCO ActiveMatrix BusinessWorks ActiveAspects Plug-in installer creates a "lib" folder under BWAA_HOME and adds it to the CLASSPATH. This folder can be used for storing all the advice implementation libraries (that is, JAR files).
 
 

Copyright © TIBCO Software Inc. All Rights Reserved
Copyright © TIBCO Software Inc. All Rights Reserved