here is an extremely complicated Hibernate audit solution: http://www.hibernate.org/318.html. I also read about envers but not interested in anything too fancy for auditing only one table.
anyways, I tried to clone the List and then use it for the change log logging (I don't know how/if I can access the original data in the List like we did in the Powerbuilder days with the datawindow buffers). The issue I'm running into is that the values for the entities are the same for both List (original and clone) in the submit() method. I think somehow the entities in the two Lists are being sync'd up. I gave up figuring it out.
Problem: the value that gets inserted into the change log table are the new values, not the old values.
Can someone kindly point out what I'm missing in my code that's causing this to happen?
.xhtml:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:s="http://jboss.com/products/seam/taglib"
template="/templates/normal.xhtml">
<ui:define name="body">
<h3>Site Administration</h3>
<h:form id="form1">
<rich:dataTable value="#{applicationSettingDataList}" var="appSetting">
<rich:column>
<f:facet name="header"><h:outputText value="ID"/></f:facet>
<h:outputText value="#{appSetting.settingId}"/>
</rich:column>
<rich:column>
<f:facet name="header"><h:outputText value="Setting Name"/></f:facet>
<b><h:outputText value="#{appSetting.settingName}"/></b>
<h:outputText value="#{appSetting.settingDescription}"/>
</rich:column>
<rich:column>
<f:facet name="header"><h:outputText value="Setting Value"/></f:facet>
<h:inputText value="#{appSetting.settingValue}"/>
</rich:column>
</rich:dataTable>
<h:commandButton value="Submit" action="#{applicationSetting.submit}"/>
<!-- <a4j:commandButton type="button" value="Cancel"/> -->
</h:form>
</ui:define>
</ui:composition>
backing bean:
@Name("applicationSetting")
@Stateful
public class ApplicationSettingsAction implements ApplicationSettingsLocal {
@In
private EntityManager entityManager;
@Logger
private Log log;
@DataModel
private List<ApplicationSetting> applicationSettingDataList;
private List<ApplicationSetting> applicationSettingDataOriginalList;
private List<String> previousSettingValueList = new ArrayList<String>();
//----------------------------------BEGIN METHODS--------------------------------------------//
@Factory("applicationSettingDataList")
@Begin(join=true)
@SuppressWarnings("unchecked")
public void getApplicationSettingData(){
applicationSettingDataList = entityManager.createQuery("from ApplicationSetting").getResultList();
applicationSettingDataOriginalList = entityManager.createQuery("from ApplicationSetting").getResultList();
/*for(int i = 0; i < applicationSettingDataList.size(); i++){
previousSettingValueList.add(applicationSettingDataList.get(i).getSettingValue());
}
*/
log.info("in submit: before applicationSettingDataList");
log.info("***********************************************************************");
for(ApplicationSetting appSetting : applicationSettingDataList){
log.info("appSetting.getSettingId() = " + appSetting.getSettingId());
log.info("appSetting.getSettingName() = " + appSetting.getSettingName());
log.info("appSetting.getSettingValue() = " + appSetting.getSettingValue());
}
log.info("in submit: before applicationSettingDataOriginalList");
log.info("***********************************************************************");
for(ApplicationSetting appSetting : applicationSettingDataOriginalList){
log.info("appSetting.getSettingId() = " + appSetting.getSettingId());
log.info("appSetting.getSettingName() = " + appSetting.getSettingName());
log.info("appSetting.getSettingValue() = " + appSetting.getSettingValue());
}
}
//@End
public void submit() {
//testing
log.info("in submit: before applicationSettingDataList");
log.info("***********************************************************************");
for(ApplicationSetting appSetting : applicationSettingDataList){
log.info("appSetting.getSettingId() = " + appSetting.getSettingId());
log.info("appSetting.getSettingName() = " + appSetting.getSettingName());
log.info("appSetting.getSettingValue() = " + appSetting.getSettingValue());
}
log.info("in submit: before applicationSettingDataOriginalList");
log.info("***********************************************************************");
for(ApplicationSetting appSetting : applicationSettingDataOriginalList){
log.info("appSetting.getSettingId() = " + appSetting.getSettingId());
log.info("appSetting.getSettingName() = " + appSetting.getSettingName());
log.info("appSetting.getSettingValue() = " + appSetting.getSettingValue());
}
//end testing
Date today = new Date();
for (int i = 0; i < applicationSettingDataList.size(); i++){
//update ApplicationSetting table
entityManager.merge(applicationSettingDataList.get(i));
//ntUsername needs to be populated by outjection from Authenticator...
String ntUsername = "CORP\\asookazi";
//where do we get the employeeId from? possibly NotificationOfAbsence.dbo.Employee table. hardcoding to 0 (admin) for now...
List<Employee> employeeList = entityManager.createQuery("from Employee e where e.ntusername = :ntUsername")
.setParameter("ntUsername", ntUsername)
.getResultList();
Employee employee = employeeList.get(0);
//insert record(s) into ApplicationSettingChangeLog table as required...
if (applicationSettingDataOriginalList.get(i).getSettingValue() != applicationSettingDataList.get(i).getSettingValue()){
ApplicationSettingChangeLog applicationSettingChangeLog = new ApplicationSettingChangeLog(employee,
applicationSettingDataOriginalList.get(i),
employee,
applicationSettingDataOriginalList.get(i).getSettingValue(),
today,
today);
entityManager.persist(applicationSettingChangeLog);
}
}
}
@Remove @Destroy
public void destroy() {
log.info("in destroy()");
}
}