Miscellaneous features
Downloading Temporary Files
Sometimes users must download a file created on the fly, for example when exporting rows of a table in xls format. This can be done in many ways, for example by returning a FileSystemResource. This approach has the drawback of leaving the temporary file on the server and therefore requires an external cron job to clean the temporary folder periodically.
A better solution is to delete the temporary file just after it has been downloaded. This can be
achieved by yadaWebUtil.downloadFile()
:
@RequestMapping("/downloadRows")
public void downloadRows(Long[] id, HttpServletResponse httpResponse) {
File xlsFile = File.createTempFile("temp", ".xls");
[... fetch data from DB and add to xlsFile ...]
yadaWebUtil.downloadFile(xlsFile.toPath(), true, MediaType.APPLICATION_OCTET_STREAM_VALUE, "data.xls", httpResponse);
}
This will start the download on the browser, resulting in a "data.xls" file on the client computer. The "temp.xls" file on the server will be automatically deleted.
There’s no need to create a temporary file when returning json. See the Json section. |
Shell Command Execution
Shell commands can be configured with variable parameters and executed via the
YadaUtil.shellExec()
method. They can be specific to an environment (development, test, production)
or generic, and the executable can be different for different OS.
The following example, added to conf.webapp.prod.xml
only, defines an imagemagick conversion
task that can be used in every environment and different OS:
<imageConversion timeoutseconds="10"> (1)
<executable windows="true">magick</executable> (2)
<executable mac="true" linux="true">/usr/local/bin/magick</executable> (2)
<arg>convert</arg>
<arg>${FILENAMEIN}</arg> (3)
<arg>${FILENAMEOUT}</arg>
</imageConversion>
1 | A timeout in seconds can be specified, the default being 60 seconds |
2 | There can be more than one executable if needed |
3 | Dynamic parameters can be added |
A different environment can have a specific configuration section with the same first tag (<imageConversion>
in the above example).
Be careful when using dynamic parameters because they are implemented by the substitution map of Apache Commons Exec that has the same syntax of Commons Configuration variable interpolation, so they will be substituted if they match any valid configuration tag (even though quite unlikely). |
The above configuration can be used with a code similar to the following:
Map<String, String> params = new HashMap<>();
params.put("FILENAMEIN", imageToCropFile.getAbsolutePath());
params.put("FILENAMEOUT", destinationFile.getAbsolutePath());
int exitValue = yadaUtil.shellExec("config/imageConversion", params, null);
Client Timezone
The timezone of the user is retrieved via javascript on first page load and sent to the server
for storage in the HTTP Session. This is done via an ajax call at each new browser session.
The timezone for unlogged users can be retrieved from the YadaConstants.SESSION_USER_TIMEZONE
session
attribute:
TimeZone userTimezone = (TimeZone) session.getAttribute(YadaConstants.SESSION_USER_TIMEZONE);
On user registration, the timezone is stored in the YadaRegistrationRequest and later in the YadaUserProfile when registration is confirmed. It is also refreshed at each user login so that it is always up to date. It can therefore be retrieved with
TimeZone userTimezone = userProfile.getTimezone();
This feature is totally transparent to the user.
For use cases where the user must be allowed to set the timezone explicitly, the YadaUtil.getTimezones()
method
can be used to retrieve a list of readable timezones to present in a select. When the user sends the
chosen timezone to the server, the yadaUserProfile.timezoneSetByUser
flag should be set to true in order
to prevent the default automatic timezone change on login.
For example:
if (!formBean.getTimezoneId().equals(userProfile.getTimezone().getID())) {
// If the timezone is different from before, set the flag
userProfile.setTimezoneSetByUser(true);
}
userProfile.setTimezone(TimeZone.getTimeZone(formBean.getTimezoneId()));