This has been covered in various forms for quite some time but here is my preferred solution to running a job from your app server. Typical use cases for this are reports, system status checks or cleanup operations.
What is the JavaBean/POJO to be called?
<bean name="systemMonitorBean" class="com.myco.HostPortMonitor"> <property name="serverList" value="${system.monitoring.serverport.locations}"/> <property name="timeout" value="${system.monitoring.serverport.timeout}"/> <property name="emailTo" value="${system.monitoring.serverport.emailto}"/> <property name="emailSender" ref="emailSender"/> |
The properties above are grabbed from a file on the classpath:
<context:property-placeholder location="classpath*:myapp.properties"/> |
I find the best way to call the Java class above is to get Spring to call a method on it:
<bean id="methodInvokingJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="systemMonitorBean"/> <property name="targetMethod" value="checkSystems"/> </bean> |
Now this effectively is a Quartz "job", ie the pojo and its specified method have become the subject of a Quartz job and can therefore be called by Quartz. So the rest of the setup is to have a trigger, in this case a simple check every hour (time is defined in milliseconds):
<bean id="serverPortMonitoringTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="methodInvokingJob"/> <property name="startDelay" value="10000"/> <property name="repeatInterval" value="3600000"/> </bean> |
You could use a CRON trigger as well: http://www.quartz-scheduler.org/docs/tutorials/crontrigger.html
Final step is to have a scheduler running that can call multiple triggers:
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="serverPortMonitoringTrigger"/> </list> </property> </bean> |
Very easy.
Used in this were some other helper classes. The Java class being called is just a simple check if a server:port is running and email out:
public class HostPortMonitor extends BaseSystemMonitor { private String serverList; private Integer timeout; private List<ServerPort> serverPortList = new ArrayList<ServerPort>(); @Override public void checkSystems() { if (ObjectUtil.isEmpty(timeout) || timeout < 100) { timeout = 10000; } for (ServerPort serverPort : serverPortList) { log.info("Checking system up/down for: " + serverPort.getServerName() + ":" + serverPort.getPort()); try { if (NetworkUtils.checkServerPort(serverPort.getServerName(), serverPort.getPort(), timeout)) { String checkStatus = "OK"; sendEmail(serverPort, checkStatus); } else { String checkStatus = "FAILED - No Connect"; sendEmail(serverPort, checkStatus); } } catch (UtilException e) { log.error("Could not check server:port - " + serverPort.getServerName() + ":" + serverPort.getPort(), e); String checkStatus = "FAILED - " + e.getMessage(); sendEmail(serverPort, checkStatus); } } } private void sendEmail(ServerPort serverPort, String checkStatus) { StringBuilder body = buildMessageBody(serverPort, checkStatus); try { log.info("Sending email for system up/down: " + body); emailSender.sendGenericEmail(emailTo, "Monitor: " + checkStatus, body.toString()); } catch (MessagingException e) { log.warn("While emailing system monitor report I received error: " + e.getMessage()); } } private StringBuilder buildMessageBody(ServerPort serverPort, String checkStatus) { StringBuilder body = new StringBuilder(); body.append("System check: ").append(checkStatus).append(TextUtil.getLineSeparator()); body.append("To server:port - ").append(serverPort.getServerName()); body.append("At time: ").append(new Date()).append(TextUtil.getLineSeparator()); body.append(":").append(serverPort.getPort()).append(TextUtil.getLineSeparator()); return body; } public Integer getTimeout() { return timeout; } public void setTimeout(Integer timeout) { this.timeout = timeout; } public String getServerList() { return serverList; } public void setServerList(String serverList) { this.serverList = serverList; String[] serverPorts = serverList.split(";"); for (String serverPort : serverPorts) { String[] split = serverPort.split(":", 2); serverPortList.add(new ServerPort(split[0], split[1])); } } class ServerPort { String serverName; Integer port; ServerPort(String serverName, String portString) { this.serverName = serverName; if (ObjectUtil.isEmpty(portString)) { this.port = 80; } else { try { this.port = Integer.parseInt(portString); } catch (NumberFormatException e) { this.port = 80; } } } public String getServerName() { return serverName; } public void setServerName(String serverName) { this.serverName = serverName; } public Integer getPort() { return port; } public void setPort(Integer port) { this.port = port; } } } |
The properties are read from a file included in the classpath using standard Java properties syntax
system.monitoring.serverport.locations=goolge.com:80 system.monitoring.serverport.timeout=3000 # etc... |
The basic code for the EmailSender is:
public class EmailSender extends JavaMailSenderImpl { public void sendGenericEmail(String emailIds, String subject, String body, EmailAttachment... attachments) throws MessagingException { MimeMessage message = super.createMimeMessage(); // use the true flag to indicate you need a multipart message MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setTo(emailIds); // use the true flag to indicate the text included is HTML helper.setSubject(subject); helper.setText(body, false); for (EmailAttachment attachment : attachments) { helper.addAttachment(attachment.getName(), attachment.getBodyAsStream()); } // let's include the infamous windows Sample file (this time copied to c:/) /*FileSystemResource res = new FileSystemResource(new File("c:/Sample.jpg")); helper.addInline("identifier1234", res);*/ send(message); } } |
system.monitoring.serverport.locations=goolge.com:80 system.monitoring.serverport.timeout=3000 # etc... |
No comments:
Post a Comment