I am developping a migration program, which transfers the data from sybase to postgresql in grails. In the backend, a grails migration service is running in a dedicated thread. In the frontend, I want to display how many data and how much time the grails service takes. In this moment, I can only manually refresh the gsp page so that the current time can number of data can be displayed on the gsp page. However, a good idea is to refresh the gsp page automatically via ajax timer. I try to use the setInterval or setTimeOut on HTML, but it somehow doesn't work at all. The following is my grails controller and corresponding view
def migrateSchuldner() {
def isRunning = personMigrationThreadService.isRunning() // boolean is the Service is running
def results = MigrationRun.findAllByEndDateIsNull()
def threadInfo
if (results.empty) {
def runCounter = personMigrationService.lastRun()
threadInfo = MigrationRun.findByCounter(runCounter) // threadInfo contains the Date and processedData and ErrorData
}
else {
threadInfo = results.get(0)
}
render view: 'migrateSchuldner', model: [threadInfo: threadInfo, isRunning: isRunning]
}
The corresponding view is:
<%@ page import="de.rvgmbh.nemesis.domain.security.Role" %>
<sec:ifAnyGranted roles="ROLE_ADMIN,ROLE_MIGRATION">
<g:applyLayout name="mainSecured" params="[currentTopNavigationIndex: 'migration', currentLeftNavigationIndex: 3]">
<head>
<title>${message(code: 'page.migration.migrate.SchuldnerData.headline.show')}
</title>
</head>
<body>
<div class="span-20 rightBorder">
<h3>${message(code: "page.migration.migrate.schuldnerData.headline.show")}</h3>
</div>
<fieldset id="migration-form">
<table>
<tr><td style="background-color: transparent">
<g:if test="${isRunning}">
<legend>
${message(code: 'page.migration.migrate.SchuldnerData.migrationInProgress')}
</legend>
</g:if>
<g:else>
<g:form action="migrateSchuldnerButtonClick" method="post" useToken="true">
${message(code: 'page.migration.migrate.SchuldnerData.legend.text')}
<input type="submit"
value= ${message(code: "page.migration.migrate.SchuldnerData.submit.text")}>
</g:form>
</g:else>
<g:if test="${threadInfo}">
<g:if test="${!isRunning}">
<legend>
${message(code: 'page.migration.migrate.SchuldnerData.lastResult')}
</legend>
</g:if>
<ul>
<li>
<label>${message(code: 'page.migration.migrate.SchuldnerData.currentTime')}:</label>
<p>${threadInfo.currentRuntime}</p>
</li>
<li>
<label>${message(code: 'page.migration.migrate.SchuldnerData.processedPersons')}:</label>
<p>${threadInfo.processedPersons}</p>
</li>
<li>
<label>${message(code: 'page.migration.migrate.SchuldnerData.personErrors')}:</label>
<p>${threadInfo.personErrors}</p>
</li>
<li>
<label>${message(code: 'page.migration.migrate.SchuldnerData.processedPersonData')}:</label>
<p>${threadInfo.processedPersonData}</p>
</li>
<li>
<label>${message(code: 'page.migration.migrate.SchuldnerData.dataErrors')}:</label>
<p>${threadInfo.dataErrors}</p>
</li>
</ul>
</g:if>
</td></tr>
</table>
</fieldset>
</body>
</g:applyLayout>
The thing is the variable currentRuntime, processedPersons... are always updating inside the thread. I have to refresh the gsp view to get the current time and processedPersons. Does anyone have a idea which Ajax timer I should use to achieve the goal
1) Move the whole <fieldset id="migration-form">
to a separate action, say, progress
with progress.gsp
. Enclose the action include into a div with id:
def progress = {
[threadInfo: threadInfo]
}
in main page:
<div id="migration_progress">
<g:include action="progress" model="[threadInfo: threadInfo]">
</div>
2) Use remoteFunction to update migration_progress
div by timer like:
onsomething="${remoteFunction(action: 'progress', update: 'migration_progress')"