Java tutorial
/** * Copyright (C) 2013 Seajas, the Netherlands. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.seajas.search.attender.service.task; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.script.ScriptException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.MessageSource; import org.springframework.context.NoSuchMessageException; import org.springframework.stereotype.Component; import com.seajas.search.attender.model.profile.Profile; import com.seajas.search.attender.model.profile.ProfileSubscriber; import com.seajas.search.attender.model.searchresult.SearchResult; import com.seajas.search.attender.service.attender.AttenderService; import com.seajas.search.attender.service.mail.MailService; import com.seajas.search.attender.service.search.SearchService; import com.seajas.search.attender.service.template.TemplateService; import com.seajas.search.attender.service.template.TemplateService.TemplateResult; import com.seajas.search.utilities.logging.SearchLogger; import com.seajas.search.utilities.ui.InterfaceQueryUtils; /** * Quartz job for notifying subscribers of new results. * * @author Jasper van Veghel <jasper@seajas.com> */ @Component public class SubscriberSenderTask { /** * The logger. */ @Autowired protected SearchLogger logger; /** * The attender service. */ @Autowired private AttenderService attenderService; /** * The template service. */ @Autowired private TemplateService templateService; /** * The mail service. */ @Autowired private MailService mailService; /** * The search service. */ @Autowired private SearchService searchService; /** * The message source. */ @Autowired private MessageSource messageSource; /** * The maximum thread pool size. */ @Value("${attender.project.concurrent.threads.maximum}") private Integer threadMaximum; /** * Send out the actual profile e-mails. */ public void send() { if (Boolean.getBoolean("attender.attending.disabled")) { logger.info( "Attending has been explicitly disabled using 'attender.attending.disabled=true'. Skipping subscriber checks."); return; } logger.info("Started subscriber job"); // Create a new UTC-based calendar to base ourselves on final Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); final Date utcDate = calendar.getTime(); // Also use a regular date for reference, to pass to the search engine final Date currentDate = new Date(); // Retrieve the list of profile profiles to attend to List<Profile> profiles = attenderService.getNotifiableProfiles(calendar); if (profiles.size() == 0) { logger.info("No notifiable profiles found - finishing subscriber job"); return; } // Re-initialize the mail-server, if needed mailService.updateWorkingMailServer(); // Now process the profiles using a thread-pool of at most threadMaximum threads ExecutorService threadPool = Executors.newFixedThreadPool(Math.min(profiles.size(), threadMaximum)); for (final Profile profile : profiles) threadPool.submit(new Runnable() { @Override public void run() { List<ProfileSubscriber> subscribers = attenderService.getNotifiableSubscribers(calendar, profile.getSubscribers()); for (ProfileSubscriber subscriber : subscribers) { try { // Round up the search parameters and taxonomies into a concise parameter list Map<String, String> searchParameters = InterfaceQueryUtils .combineParametersAndTaxonomies(profile.getSearchParametersMap(), profile.getTaxonomyIdentifierNumbers()); String searchQuery = InterfaceQueryUtils.createQueryFromParameters(profile.getQuery(), searchParameters); // Determine the start date depending on the user's last notification date, and retrieve the results List<SearchResult> searchResults = searchService.performSearch(profile.getQuery(), subscriber.getLastNotification(), currentDate, searchParameters, mailService.getResultsPerMessage(), subscriber.getEmailLanguage()); if (logger.isInfoEnabled()) logger.info("Found " + searchResults.size() + " result(s) for profile with ID " + profile.getId() + " and query '" + profile.getQuery() + "'"); // Now create a template result based on the search results TemplateResult templateResult = templateService.createResults( subscriber.getEmailLanguage(), searchQuery, profile.getQuery(), subscriber.getUniqueId(), profile.getUniqueId(), searchResults); // Take the subject in the given language, or resort to the default language if it doesn't exist (yet) String subject = null; try { subject = messageSource.getMessage( "mail.results.subject." + subscriber.getNotificationType().toString().toLowerCase(), new Object[] { profile.getQuery() }, new Locale(subscriber.getEmailLanguage())); } catch (NoSuchMessageException e) { logger.warn("Could not retrieve results message subject header in language " + subscriber.getEmailLanguage() + ", resorting to the default language " + attenderService.getDefaultApplicationLanguage()); subject = messageSource.getMessage("mail.confirmation.subject", new Object[] { profile.getQuery() }, new Locale(attenderService.getDefaultApplicationLanguage())); } // And send out the actual e-mail if (mailService.hasWorkingMailServer()) mailService.sendMessage(subscriber.getEmail(), subject, templateResult.getTextResult(), templateResult.getHtmlResult()); else logger.error( "Could not e-mail the results message - no mail server has been configured. Users may retrieve results using the RSS feed."); // Update the processed subscribers' lastNotification indicator attenderService.updateProfileSubscriberLastNotification(subscriber.getId(), utcDate); } catch (ScriptException e) { logger.error("Could not create a template result", e); } } } }); logger.info("Finishing subscriber job"); } }