10014---Trail ~ CronJobs

Motivation

CronJobs provide a means for performing business logic at particular times and intervals. For example, 

an administrator might want to perform an inventory every Sunday at midnight,

 or notify the web administrator every hour between 9 and 5 from Monday to Saturday of the peak loads on the servers.

Our cronjob should run on a daily basis and send eMails containing a ranking-list.

 If you are lucky enough to have an SMTP server that you can use, you can set up the details as below. 

If you don't, the Cronjob will just echo the text to the command prompt.

Setting up eMail with gmail

We'll configure here a sample gmail SMTP server. You can create an account to be used with this training (http://mail.google.com).

config/local.properties

mail.from=cuppy-no-reply@hybris.de
mail.replyto=cuppy-no-reply@hybris.de
mail.smtp.server=smtp.gmail.com
mail.smtp.port=587
mail.smtp.user=YOUR_GMAIL_ACCOUNT
mail.smtp.password=YOUR_GMAIL_PASSWORD
mail.smtp.starttls.enable=true

Defining the Job

Create a new java class SendRankingJob in the package de/hybris/platform/cuppytrail/jobs:

de/hybris/platform/cuppytrail/jobs/SendRankingJob.java
/*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2011 hybris AG
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of hybris
 * ("Confidential Information"). You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the
 * license agreement you entered into with hybris.
 *
 *
 */
package de.hybris.platform.cuppytrail.jobs;
 
import de.hybris.platform.cronjob.enums.CronJobResult;
import de.hybris.platform.cronjob.enums.CronJobStatus;
import de.hybris.platform.cronjob.model.CronJobModel;
import de.hybris.platform.cuppy.model.PlayerModel;
import de.hybris.platform.cuppy.services.MailService;
import de.hybris.platform.cuppy.services.PlayerService;
import de.hybris.platform.cuppy.services.RankingData;
import de.hybris.platform.servicelayer.cronjob.AbstractJobPerformable;
import de.hybris.platform.servicelayer.cronjob.PerformResult;
 
import java.util.List;
 
import org.apache.log4j.Logger;
 
 
public class SendRankingJob extends AbstractJobPerformable<CronJobModel>
{
    private static final Logger LOG = Logger.getLogger(SendRankingJob.class);
 
    private PlayerService playerService;
    private MailService mailService;
 
    @Override
    public PerformResult perform(final CronJobModel cronJob)
    {
        LOG.info("Sending ranking mails");
        final List<RankingData> rankings = playerService.getRankings();
 
        if (rankings.isEmpty())
        {
            LOG.info("No competitions have changed, skipping send of ranking mails");
            return new PerformResult(CronJobResult.SUCCESS, CronJobStatus.FINISHED);
        }
 
        for (final PlayerModel player : playerService.getAllPlayers())
        {
            final List<RankingData> playerRankings = playerService.filterRankingsForPlayer(rankings, player);
            if (!playerRankings.isEmpty() && player.isSendNewsletter())
            {
                mailService.sendRankingMail(player, playerRankings);
            }
        }
        return new PerformResult(CronJobResult.SUCCESS, CronJobStatus.FINISHED);
    }
 
    public void setPlayerService(final PlayerService playerService)
    {
        this.playerService = playerService;
    }
 
    public void setMailService(final MailService trailMailService)
    {
        this.mailService = trailMailService;
    }
}

The new JobPerformable has to be defined as a Spring bean in cuppytrail-spring.xml. 
Add the following line at the bottom of the file, but inside the beans-tag:

resources/cuppytrail-spring.xml

<bean id="sendRankingJob" class="de.hybris.platform.cuppytrail.jobs.SendRankingJob" autowire="byName"/>

Rebuild the hybris Platform by calling ant in the $/{HYBRIS_BIN_DIR}/platform directory. 
(warning) Run a system update with only essential data checked - during the phase of essential data creation, 

for each Spring definition of a class implementing the JobPerformable interface, a ServicelayerJob instance gets created and the code attribute of the job is set to the name of the Spring bean.

You can check in the FlexibleSearch console: http://localhost:9001/console/flexsearch that the new item was created by executing the following query:

select {code} from {servicelayerjob} where {code} = 'sendRankingJob'

Create the CronJob and the Trigger

To create the CronJob and the Trigger, you can either:

  • You can go in the hybris Admin Console to the Console tab select ImpEx Import and execute the following impex-script there by clicking on the Import Content button

INSERT_UPDATE CronJob; code[unique=true];job(code);singleExecutable;sessionLanguage(isocode)
;sendRankingCronJob;sendRankingJob;false;de
 
INSERT_UPDATE Trigger;cronjob(code)[unique=true];cronExpression
#% afterEach: impex.getLastImportedItem().setActivationTime(new Date());
; sendRankingCronJob; 0 0 0 * *
A cron expression is a string comprised of 6 or 7 fields separated by white space. Fields can contain any of the allowed values, along with various combinations of allowed special characters for that field.

---

  • Quartz cron trigger is used, see Quartz Scheduler for more details.
    Any changes you are making for testing can easily be redeployed or reexecuted.

  • OR create the file resources/impex/essentialdataJobs.impex with the same content. Further changes are only taken into account after a server-restart and a system update (with only essential data checked). Changes made to resources after being loaded as classloader-resources are not visible.
===

l10NService.getLocalizedString("mail.registration.subject", new Object[]{ player.getUid() })
mail.registration.subject=Player {0} has registered

=======

DefaultMailService.java

/**
 *
 */
package de.hybris.platform.cuppy.services.impl;

import de.hybris.platform.commons.model.renderer.RendererTemplateModel;
import de.hybris.platform.commons.renderer.RendererService;
import de.hybris.platform.commons.renderer.exceptions.RendererException;
import de.hybris.platform.cuppy.model.MatchModel;
import de.hybris.platform.cuppy.model.NewsModel;
import de.hybris.platform.cuppy.model.PlayerModel;
import de.hybris.platform.cuppy.services.MailService;
import de.hybris.platform.cuppy.services.RankingData;
import de.hybris.platform.cuppy.services.SingletonScopedComponent;
import de.hybris.platform.servicelayer.i18n.FormatFactory;
import de.hybris.platform.servicelayer.i18n.I18NService;
import de.hybris.platform.servicelayer.i18n.L10NService;
import de.hybris.platform.servicelayer.session.SessionExecutionBody;
import de.hybris.platform.servicelayer.session.SessionService;
import de.hybris.platform.util.Config;

import java.io.StringWriter;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;


/**
 * @author andreas.thaler
 * 
 */
@SingletonScopedComponent(value = "mailService")
public class DefaultMailService implements MailService, InitializingBean
{
	private final static Logger LOG = Logger.getLogger(DefaultMailService.class);
	private String domain;
	private String fromAddress;
	private String replyToAddress;

	@Autowired
	private JavaMailSender mailSender;
	@Autowired
	private SessionService sessionService;
	@Autowired
	private I18NService i18nService;
	@Autowired
	private FormatFactory formatFactory;
	@Autowired
	private RendererService rendererService;
	@Autowired
	private L10NService l10NService;

	@Override
	public void afterPropertiesSet()
	{
		domain = Config.getParameter("cuppy.domain");
		fromAddress = Config.getParameter("mail.from");
		replyToAddress = Config.getParameter("mail.replyto");

		if (domain == null || domain.isEmpty() || fromAddress == null || fromAddress.isEmpty() || replyToAddress == null
				|| replyToAddress.isEmpty())
		{
			throw new IllegalStateException(
					"Can not start mail service, please configure properties 'cuppy.domain','mail.from' and 'mail.replyto'");
		}
	}

	@Override
	public void sendConfirmationMail(final PlayerModel player)
	{
		final MailPreparator preparer = new MailPreparator()
		{
			@Override
			public void prepare(final MimeMessageHelper message) throws MessagingException
			{
				message.setSubject(l10NService.getLocalizedString("mail.confirmation.subject"));
				message.setText(l10NService.getLocalizedString("mail.confirmation.body", new Object[]
				{ player.getName(), "http://" + domain + "/index.zul", player.getUid() }));
			}
		};
		send(preparer, player);
	}

	@Override
	public void sendRegistrationMail(final PlayerModel player, final List<PlayerModel> admins)
	{
		for (final PlayerModel admin : admins)
		{
			final MailPreparator preparer = new MailPreparator()
			{
				@Override
				public void prepare(final MimeMessageHelper message) throws MessagingException
				{
					message.setSubject(l10NService.getLocalizedString("mail.registration.subject", new Object[]
					{ player.getUid() }));
					message.setText(l10NService.getLocalizedString("mail.registration.body", new Object[]
					{
							admin.getName(),
							"http://" + domain + "/index.zul?persp=cuppy.perspective.cuppy&events=activation&act-item="
									+ player.getPk().toString() }));
				}
			};
			send(preparer, admin);
		}
	}

	@Override
	public void sendNewsletter(final NewsModel news, final List<PlayerModel> players)
	{
		for (final PlayerModel player : players)
		{
			if (player.isSendNewsletter())
			{
				final MailPreparator preparer = new MailPreparator()
				{
					@Override
					public void prepare(final MimeMessageHelper message) throws MessagingException
					{
						message.setSubject(l10NService.getLocalizedString("mail.news.subject"));
						message.setText("<html><body>" + l10NService.getLocalizedString("mail.news.text", new Object[]
						{ StringEscapeUtils.escapeHtml(player.getName()), news.getContent() }) + "</body></html>", true);
					}
				};
				send(preparer, player);
			}
		}
	}

	@Override
	public void sendReminder(final List<MatchModel> matches, final PlayerModel player)
	{
		final MailPreparator preparer = new MailPreparator()
		{
			@Override
			public void prepare(final MimeMessageHelper message) throws MessagingException
			{
				final DateFormat dateFormat = formatFactory.createDateTimeFormat(DateFormat.MEDIUM, DateFormat.MEDIUM);
				final List<MatchReminderHelper> matchReminders = new ArrayList<MatchReminderHelper>();
				for (final MatchModel match : matches)
				{
					final String name = match.getGroup().getCompetition().getName();
					final String kickOffTime = dateFormat.format(match.getDate());
					final String home = match.getHomeTeam().getName();
					final String guest = match.getGuestTeam().getName();
					final MatchReminderHelper reminder = new MatchReminderHelper(name, kickOffTime, home, guest);
					matchReminders.add(reminder);
				}
				final ReminderContext reminderContext = new ReminderContext(player, matchReminders);
				final StringWriter mailMessage = new StringWriter();
				final RendererTemplateModel reminderTemplate = rendererService.getRendererTemplateForCode("reminder");
				rendererService.render(reminderTemplate, reminderContext, mailMessage);

				message.setSubject(l10NService.getLocalizedString("mail.reminder.subject"));
				message.setText(mailMessage.toString(), true);
			}
		};
		send(preparer, player);
	}

	@Override
	public void sendNewPassword(final PlayerModel player, final String newPassword)
	{
		final MailPreparator preparer = new MailPreparator()
		{
			@Override
			public void prepare(final MimeMessageHelper message) throws MessagingException
			{
				message.setSubject(l10NService.getLocalizedString("mail.newpassword.subject"));
				message.setText(l10NService.getLocalizedString("mail.newpassword.body", new Object[]
				{ player.getName(), "http://" + domain + "/index.zul", player.getUid(), newPassword }));
			}
		};
		send(preparer, player);
	}

	private String getMailExceptionMessage(final MailException exception)
	{
		final StringBuilder result = new StringBuilder(exception.getMessage());
		if (exception.getCause() != null)
		{
			final Throwable cause = exception.getCause();
			result.append(": ").append(exception.getMessage());
			if (cause.getCause() != null)
			{
				result.append(": ").append(cause.getMessage());
			}
		}
		return result.toString();
	}

	protected void send(final MailPreparator preparer, final PlayerModel player)
	{
		sessionService.executeInLocalView(new SessionExecutionBody()
		{
			@Override
			public void executeWithoutResult()
			{
				i18nService.setLocalizationFallbackEnabled(true);
				if (player.getSessionLanguage() != null)
				{
					i18nService.setCurrentLocale(new Locale(player.getSessionLanguage().getIsocode()));
				}

				final MimeMessagePreparator preparator = new MimeMessagePreparator()
				{
					@Override
					public void prepare(final MimeMessage mimeMessage) throws Exception //NOPMD
					{
						final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "UTF-8");
						message.setTo(player.getEMail());
						message.setFrom(fromAddress);
						message.setReplyTo(replyToAddress);
						preparer.prepare(message);
					}
				};
				try
				{
					mailSender.send(preparator);
				}
				catch (final MailException e)
				{
					//log it and go on
					LOG.error("Can not send mail to " + player.getUid() + " - " + player.getEMail() + ": "
							+ getMailExceptionMessage(e));
				}
			}
		});
	}

	@Override
	public void sendRankingMail(final PlayerModel player, final List<RankingData> rankings)
	{
		try
		{
			final MailPreparator preparer = new MailPreparator()
			{
				@Override
				public void prepare(final MimeMessageHelper message) throws MessagingException
				{
					message.setSubject(l10NService.getLocalizedString("mail.ranking.subject"));

					final RendererTemplateModel template = rendererService.getRendererTemplateForCode("rankingMail");
					final StringWriter renderedText = new StringWriter();

					rendererService.render(template, new RankingMailContext(rankings, player), renderedText);
					message.setText(renderedText.getBuffer().toString(), true);
				}
			};
			send(preparer, player);
		}
		catch (final RendererException e)
		{
			LOG.error("Error while rendering ranking mail for " + player.getUid() + ", skipping send of mail", e);
		}
	}

	protected interface MailPreparator
	{
		void prepare(MimeMessageHelper message) throws Exception; //NOPMD
	}

	public void setMailSender(final JavaMailSender mailSender)
	{
		this.mailSender = mailSender;
	}

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值