package de.superx.spring.batch.job; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import javax.xml.XMLConstants; import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.junit.FixMethodOrder; import org.junit.Ignore; import org.junit.Test; import org.junit.runners.MethodSorters; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.core.JdbcTemplate; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import de.superx.BaseDbTest; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestBiQuartzBatchJob extends BaseDbTest { @Test public void jobDetailReadFromXmlFileTest() { JdbcTemplate jt = new JdbcTemplate(dataSource); Integer count = jt.queryForObject("SELECT COUNT(*) FROM qrtz_job_details WHERE job_class_name='de.superx.spring.batch.job.BiQuartzBatchJob' AND job_name='ETL-TEST'", Integer.class); assertEquals("Exactly one ETL-TEST job", Integer.valueOf(1), count); } @Ignore @Test public void changeJobXmlTest() throws IOException, ParserConfigurationException, SAXException, XPathExpressionException, TransformerException, InterruptedException { ClassPathResource xml = new ClassPathResource("quartz-test_jobs.xml"); boolean exists = xml.exists(); assertTrue("quartz-test_jobs.xml exists", exists); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); // builder.setExpandEntities(false); // optional security option try (InputStream is = new FileInputStream(xml.getFile())) { Document jobs = db.parse(is); XPathFactory xFactory = XPathFactory.newInstance(); XPath xpath = xFactory.newXPath(); xpath.setNamespaceContext(new QuartzNs()); XPathExpression expr = xpath.compile("//q:cron-expression"); NodeList cron = (NodeList) expr.evaluate(jobs, XPathConstants.NODE); cron.item(0).setTextContent("0 0 0 1 1 ? 2098"); System.out.println("CRON: " + cron.item(0)); Transformer tf = TransformerFactory.newInstance().newTransformer(); tf.setOutputProperty(OutputKeys.INDENT, "yes"); tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); tf.transform(new DOMSource(jobs), new StreamResult(xml.getFile())); Thread.sleep(500); // give the scanner time to record the new lastModified JdbcTemplate jt = new JdbcTemplate(dataSource); String s = null; long deadline = System.currentTimeMillis() + 40_000; long slept = 0; while (System.currentTimeMillis() < deadline) { s = jt.queryForObject("SELECT cron_expression FROM qrtz_cron_triggers WHERE trigger_name='ETL-Test Trigger'", String.class); if ("0 0 0 1 1 ? 2098".equals(s)) { System.out.println("Cron expression in db changed to: " + s); break; } Thread.sleep(500); slept += 500; } System.out.println("Waited " + slept + "ms for cron expression to change in db"); assertEquals("Cron expression changed in db", "0 0 0 1 1 ? 2098", s); cron.item(0).setTextContent("0 0 0 1 1 ? 2099"); tf.transform(new DOMSource(jobs), new StreamResult(xml.getFile())); } } private static class QuartzNs implements NamespaceContext { private static final String PREFIX = "q"; private static final String NS_URI = "http://www.quartz-scheduler.org/xml/JobSchedulingData"; @Override public String getNamespaceURI(String prefix) { return PREFIX.equals(prefix) ? NS_URI : XMLConstants.NULL_NS_URI; } @Override public String getPrefix(String namespaceURI) { return NS_URI.equals(namespaceURI) ? PREFIX : null; } @Override public Iterator getPrefixes(String namespaceURI) { return PREFIX.equals(getPrefix(namespaceURI)) ? java.util.Collections.singleton(PREFIX).iterator() : java.util.Collections.emptyIterator(); } }}