In OpenXava v4.x you can use the old
AccessTracking project. Other alternative for auditing is Hibernate Envers.
OpenXava has a mechanism to track any change done by users to the data and
also read access. This mechanism is totally configurable and it's disable
by default.
Access
tracker custom implementation
To track the data access you need an
IAccessTrackerProvider (an interface from
org.openxava.util).
Creating one is easy, just create a class that implement that interface,
like the next one:
package org.openxava.util;
import java.io.*;
import java.util.*;
import org.apache.commons.logging.*;
import org.openxava.application.meta.*;
public class LogAccessTrackerProvider implements IAccessTrackerProvider {
private static Log log = LogFactory.getLog(LogAccessTrackerProvider.class);
private static String fileName;
public void consulted(String modelName, Map key) {
log("CONSULTED: user=" + Users.getCurrent() + ", model=" + modelName + ", key=" + key);
}
public void created(String modelName, Map key) {
log("CREATED: user=" + Users.getCurrent() + ", model=" + modelName + ", key=" + key);
}
public void modified(String modelName, Map key, Map<String, Object> oldChangedValues, Map<String, Object> newChangedValues) {
StringBuffer changes = new StringBuffer();
for (String property: oldChangedValues.keySet()) {
if (changes.length() > 0) changes.append(", ");
changes.append(Labels.getQualified(property));
changes.append(": ");
changes.append(Strings.toString(oldChangedValues.get(property)));
changes.append(" --> ");
changes.append(Strings.toString(newChangedValues.get(property)));
}
log("MODIFIED: user=" + Users.getCurrent() + ", model=" + modelName + ", key=" + key + ", changes=" + changes);
}
public void removed(String modelName, Map key) {
log("REMOVED: user=" + Users.getCurrent() + ", model=" + modelName + ", key=" + key);
}
private static void log(String line) {
try {
createFileIfNotExist();
FileOutputStream f = new FileOutputStream(getFileName(), true);
PrintStream p = new PrintStream(f);
p.println(line);
p.close();
f.close();
}
catch (Exception ex) {
log.warn(XavaResources.getString("log_tracker_log_failed"), ex);
}
}
private static void createFileIfNotExist() throws Exception {
Files.createFileIfNotExist(getFileName());
}
private static String getFileName() {
if (fileName == null) {
Collection applicationNames = MetaApplications.getApplicationsNames();
String app = "openxava-app";
if (!applicationNames.isEmpty()) app = applicationNames.iterator().next().toString().toLowerCase();
fileName = Files.getOpenXavaBaseDir() + app + "-access.log";
}
return fileName;
}
}
This is the simplest possible implementation, just it registers the
accesses in a log file. Note that you have to implement four simple
methods:
consulted(),
created(),
modified()
and
removed(). You can write your own tracker provider to
include more data and to save the accesses in a database table, for
example. The above tracker provider,
LogTrackerAccessProvider,
is included in OpenXava, in the package
org.openxava.util, so
you can use it "as is" if you don't need more.
Register
the tracker provider
In order that your tracker provider works you have to declare it in
xava.properties
of your project, using the
accessTrackerProvidersClasses entry:
accessTrackerProvidersClasses=org.openxava.util.LogAccessTrackerProvider
You can declare several access tracker providers separated by commas.
Now, all changes and read access from the users will add a line in the
.openxava/yourapplication-accesss.log
file.
Notify
your own changes
By default, all the changes done via
MapFacade, that includes
all creation, consult, modification and deletion (in main entity and
collections) from a standard OpenXava module. Moreover, the editors
included in OpenXava, such as
Discussion,
ImagesGallery
or
Files also notify for changes. However, if you access to data
from your own code using JPA or JDBC directly you should notify the access
using
AccessTracker class from
org.openxava.util.
For example:
createInvoiceWithJPA(getView().getKeyValues(), getView().getValues()); // Here you saved in your own way
AccessTracking.created("Invoice", getView().getKeyValues()); // YOU HAVE TO ADD THIS LINE