Implemening business rules in ADF Business Components means implementing them in so-called entity objects. For an application that uses a relational database, to a certain extend you can compare an entity object with an EJB entity bean, as like an entity bean the purpose of the entity object is to manage storage of data in a specific table. Unlike EJB entity beans, ADF entity objects provide hooks to implement business rules that go way beyond what you can do with EJB entity beans.
I won't go into detail about these hooks. When you're interested, enough documentation about the subject can be found on the internet (to begin with the Steve Muench's web log) or read the white paper! I will let you know when it is available and where to find it.
Where I do want to go into detail is one aspect, being how to prevent that rules get fired unneccessarily, for example for reasons of performance. I assume some basic knowledge of ADF Business Components, so if you don't have that, this is where you might want to stop reading.
There are the following typical options, provided as methods on any EntityImpl:
- The isAttributeChanged() method can be used to check if the value of an attribute has actually changed, before firing a rule that only makes sense when this is the case.
- Furthermore there is the getEntityState() method that can be used to check the status of an entity object in the current transaction, which can either be new, changed since it has been queried, or deleted. You can use this method to make that a rule that only gets fired, for example when the entity object is new.
- There is also the getPostState() that does a similiar thing as getEntityState() but which takes into consideration whether the change has been posted to the database.
"So what", you might think, "when do I ever want to use the beforeCommit()?". Well, you have to as soon as you are dealing with a rule that concerns two or more entity objects that could trigger the rule, as in that case the beforeCommit() is the only hook of which you can be sure that all changes made are reflected by the entity objects involved.
Suppose you have a Project with ProjectAssignments and you want to make sure that the begin and end date of the ProjectAssignments fall within the begin and end date of the Project. A classical example, I dare say. Now the events that could fire this rule are the creation of a ProjectAssignment, the update of the Project its start or end date or the update of the ProjectAssignment its start or end date.
Regarding the creation of the ProjectAssignment, that you can verify by using the getEntityState() which would return STATUS_NEW in that case. Regarding the change of any of the dates, you can check for STATUS_MODIFIED, but that also returns true when any of the other attributes have been changed.
Now suppose that, as there can be multiple ProjectAssignments for one Project, you only want to validate this rule when one of those dates actually did change. The only way to know is by comparing the old values with the new one. As explained before, as the hook you are using will be the beforeCommit() method, the getPostedAttribute() also will return the new value as that time the changes already have been posted to the database.
Bugger, what now? Well, I wouldn't have raised the question unless I would have some solution to it, would I? The solution involves a bit yet pretty straightforward coding. I will only show how to solve this for the Project, for the ProjectAssignment the problem can be solved likewise. The whole idea behind the work-around is that you will use instance variables to store the old values so that they are still available in the beforeCommit().
Open the ProjectImpl.java and add the following private instance variables:
private Date startDateOldValue;
private Date endDateOldValue;
protected void doDML(int operation, TransactionEvent e)
{
// store old values to be able to compare them with
// new ones in beforeCommit()
startDateOldValue = (Date)getPostedAttribute(STARTDATE);
endDateOldValue = (Date)getPostedAttribute(ENDDATE);
super.doDML(operation, e);
}
public static boolean valuesAreDifferent(Object firstValue
, Object secondValue)
{
boolean returnValue = false;
if ((firstValue == null) || (secondValue == null))
{
if (( (firstValue == null) && !(secondValue == null))
||
(!(firstValue == null) && (secondValue == null)))
{
returnValue = true;
}
}
else
{
if (!(firstValue.equals(secondValue)))
{
returnValue = true;
}
}
return returnValue;
}
public void beforeCommit(TransactionEvent p0)
{
if ( getEntityState() == STATUS_MODIFIED &&
( AdfbcUtils.valuesAreDifferent(startDateOldValue,
getStartDate()) ||
AdfbcUtils.valuesAreDifferent(endDateOldValue,
getEndDate())
)
)
{
brProjStartEndDate();
}
super.beforeCommit(p0);
}
public void brProjStartEndDate()
{
RowIterator projAssignSet = getProjectAssignments();
ProjectAssignmentImpl projAssign;
while (projAssignSet.hasNext())
{
projAssign =
(ProjectAssignmentImpl)projAssignSet.next();
if (((getEndDate() == null) ||
(projAssign.getStartDate().
compareTo(getEndDate()) <= 0)
) &&
(projAssign.getStartDate().
compareTo(getStartDate()) >= 0)
)
{
// rule is true
}
else
{
throw new JboException("Project start date must " +
"be before start date of any Project Assignment");
}
}
}
5 comments:
Interesting to know.
Interesting very much .. thanks good to read this
Your Escort Agency offers exclusive and most beautiful London escort girls of various nationalities.
Bestescort4U more then ten years providing best London escorts companionship in the UK.
Hot - Collection is a honest and confidential London escort agency which provides genuine London escorts girls for gentlemen of taste.
Post a Comment