1

Constantly monitor a http request which if returns code 200 then no action is taken but if a 404 is returned then the administrator should be alerted via warning or mail.

I wanted to know how to approach it from a Java perspective. The codes available are not very useful.

Marcel Korpel
  • 21,536
  • 6
  • 60
  • 80
KronnorK
  • 539
  • 5
  • 17
  • 3
    Available where? What is it you do *not* want? What have you tried so far? And Java ≠ JavaScript. BTW, you can't send mail from within JavaScript, you'll need a server-side script for that, too. – Marcel Korpel Apr 20 '11 at 09:57
  • 1
    I wanted a constant http request monitor using Java and if the code returned is 404 then I wanted the program to send a mail to the administrator of the site. Sorry for putting the question wrongly – KronnorK Apr 24 '11 at 17:37
  • Then this question is not at all related to JavaScript. And at which codes did you look that turned out to be not very useful? – Marcel Korpel Apr 24 '11 at 18:51

2 Answers2

2

First of all, you should consider using an existing tool designed for this job (e.g. Nagios or the like). Otherwise you'll likely find yourself rewriting many of the same features. You probably want to send only one email once a problem has been detected, otherwise you'll spam the admin. Likewise you might want to wait until the second or third failure before sending an alert, otherwise you could be sending false alarms. Existing tools do handle these things and more for you.

That said, what you specifically asked for isn't too difficult in Java. Below is a simple working example that should help you get started. It monitors a URL by making a request to it every 30 seconds. If it detects a status code 404 it'll send out an email. It depends on the JavaMail API and requires Java 5 or higher.

public class UrlMonitor implements Runnable {
    public static void main(String[] args) throws Exception {
        URL url = new URL("http://www.example.com/");
        Runnable monitor = new UrlMonitor(url);
        ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
        service.scheduleWithFixedDelay(monitor, 0, 30, TimeUnit.SECONDS);
    }

    private final URL url;

    public UrlMonitor(URL url) {
        this.url = url;
    }

    public void run() {
        try {
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            if (con.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
                sendAlertEmail();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void sendAlertEmail() {
        try {
            Properties props = new Properties();
            props.setProperty("mail.transport.protocol", "smtp");
            props.setProperty("mail.host", "smtp.example.com");

            Session session = Session.getDefaultInstance(props, null);
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress("me@example.com", "Monitor"));
            message.addRecipient(Message.RecipientType.TO,
                    new InternetAddress("me@example.com"));
            message.setSubject("Alert!");
            message.setText("Alert!");

            Transport.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
WhiteFang34
  • 70,765
  • 18
  • 106
  • 111
1

I'd start with the quartz scheduler, and create a SimpleTrigger. The SimpleTrigger would use httpclient to create connection and use the JavaMail api to send the mail if an unexpected answer occurred. I'd probably wire it using spring as that has good quartz integration and would allow simple mock implementations for testing.

A quick and dirt example without spring combining Quartz and HttpClient (for JavaMail see How do I send an e-mail in Java?):

imports (so you know where I got the classes from):

import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

code:

public class CheckJob implements Job {
    public static final String PROP_URL_TO_CHECK = "URL";

    public void execute(JobExecutionContext context) 
                       throws JobExecutionException {
        String url = context.getJobDetail().getJobDataMap()
                            .getString(PROP_URL_TO_CHECK);
        System.out.println("Starting execution with URL: " + url);
        if (url == null) {
            throw new IllegalStateException("No URL in JobDataMap");
        }
        HttpClient client = new DefaultHttpClient();
        HttpGet get = new HttpGet(url);
        try {
            processResponse(client.execute(get));
        } catch (ClientProtocolException e) {
            mailError("Got a protocol exception " + e);
            return;
        } catch (IOException e) {
            mailError("got an IO exception " + e);
            return;
        }

    }

    private void processResponse(HttpResponse response) {
        StatusLine status = response.getStatusLine();
        int statusCode = status.getStatusCode();
        System.out.println("Received status code " + statusCode);
        // You may wish a better check with more valid codes!
        if (statusCode <= 200 || statusCode >= 300) {
            mailError("Expected OK status code (between 200 and 300) but got " + statusCode);
        }
    }

    private void mailError(String message) {
        // See https://stackoverflow.com/questions/884943/how-do-i-send-an-e-mail-in-java
    }
}

and the main class which runs forever and checks every 2 minutes:

imports:

import org.quartz.JobDetail;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

code:

public class Main {

    public static void main(String[] args) {
        JobDetail detail = JobBuilder.newJob(CheckJob.class)
                           .withIdentity("CheckJob").build();
        detail.getJobDataMap().put(CheckJob.PROP_URL_TO_CHECK, 
                                   "http://www.google.com");

        SimpleTrigger trigger = TriggerBuilder.newTrigger()
                .withSchedule(SimpleScheduleBuilder
                .repeatMinutelyForever(2)).build();


        SchedulerFactory fac = new StdSchedulerFactory();
        try {
            fac.getScheduler().scheduleJob(detail, trigger);
            fac.getScheduler().start();
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }
}
Community
  • 1
  • 1
extraneon
  • 23,575
  • 2
  • 47
  • 51