spring - Quartz doesn't recognize schema job_scheduling_data_2_0.xsd present in quartz jar file -
i getting below exception on server startup.
i using quartz 2.2.21 spring 3.2. have enabled quartz plugin (org.quartz.plugins.xml.xmlschedulingdataprocessorplugin).
please find below start tag of our xml file:
during server startup getting below log information , stacktrace:
error message:
unable load local schema packaged in quartz distribution jar. utilizing schema online @ http://www.quartz-scheduler.org/xml/job_scheduling_data_2_0.xsd
exception:
caused by: org.xml.sax.saxparseexception; systemid: file:///quartz_job_data.xml; linenumber: 5; columnnumber: 104; schema_reference.4: failed read schema document 'http://www.quartz-scheduler.org/xml/job_scheduling_data_2_0.xsd', because 1) not find document; 2) document not read; 3) root element of document not <xsd:schema>.
i have same problem. i'm using 7.1.1 of jboss , problem appears when don't have connection internet. easy putting fake address that's unreachable in hosts.
i tried force local copy not work.
what did partially overwrite functionality until fixed. watch: https://jira.spring.io/browse/spr-13706
public class customxmlschedulingdataprocessor extends org.quartz.xml.xmlschedulingdataprocessor { public static final string quartz_xsd_path_in_jar_classpath = "classpath:org/quartz/xml/job_scheduling_data_2_0.xsd"; public customxmlschedulingdataprocessor(classloadhelper clh) throws parserconfigurationexception { super(clh); } @override protected object resolveschemasource() { inputsource inputsource; inputstream = null; try { = classloadhelper.getresourceasstream(quartz_xsd_path_in_jar_classpath); } { if (is != null) { inputsource = new inputsource(is); inputsource.setsystemid(quartz_schema_web_url); } else { return quartz_schema_web_url; } } return inputsource; } }
and did new plugin xmlschedulingdataprocessorplugin overwritting instanciation of above class.
public class xmlschedulingdataprocessorplugin extends schedulerpluginwithusertransactionsupport implements filescanlistener { /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * data members. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ private static final int max_job_trigger_name_len = 80; private static final string job_initialization_plugin_name = "jobschedulingdataloaderplugin"; private static final string file_name_delimiters = ","; private boolean failonfilenotfound = true; private string filenames = customxmlschedulingdataprocessor.quartz_xml_default_file_name; // populated initialization private map<string, jobfile> jobfiles = new linkedhashmap<string, jobfile>(); private long scaninterval = 0; boolean started = false; protected classloadhelper classloadhelper = null; private set<string> jobtriggernameset = new hashset<string>(); /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * constructors. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public xmlschedulingdataprocessorplugin() { } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** * comma separated list of file names (with paths) xml files should read. */ public string getfilenames() { return filenames; } /** * file name (and path) xml file should read. */ public void setfilenames(string filenames) { this.filenames = filenames; } /** * interval (in seconds) @ scan changes file. * if file has been changed, re-loaded , parsed. default * value interval 0, disables scanning. * * @return returns scaninterval. */ public long getscaninterval() { return scaninterval / 1000; } /** * interval (in seconds) @ scan changes file. * if file has been changed, re-loaded , parsed. default * value interval 0, disables scanning. * * @param scaninterval scaninterval set. */ public void setscaninterval(long scaninterval) { this.scaninterval = scaninterval * 1000; } /** * whether or not initialization of plugin should fail (throw * exception) if file cannot found. default <code>true</code>. */ public boolean isfailonfilenotfound() { return failonfilenotfound; } /** * whether or not initialization of plugin should fail (throw * exception) if file cannot found. default <code>true</code>. */ public void setfailonfilenotfound(boolean failonfilenotfound) { this.failonfilenotfound = failonfilenotfound; } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * schedulerplugin interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /** * <p> * called during creation of <code>scheduler</code> in order give * <code>schedulerplugin</code> chance initialize. * </p> * * @throws org.quartz.schedulerconfigexception * if there error initializing. */ public void initialize(string name, final scheduler scheduler, classloadhelper schedulerfactoryclassloadhelper) throws schedulerexception { super.initialize(name, scheduler); this.classloadhelper = schedulerfactoryclassloadhelper; getlog().info("registering quartz job initialization plug-in."); // create jobfile objects stringtokenizer stok = new stringtokenizer(filenames, file_name_delimiters); while (stok.hasmoretokens()) { final string filename = stok.nexttoken(); final jobfile jobfile = new jobfile(filename); jobfiles.put(filename, jobfile); } } @override public void start(usertransaction usertransaction) { try { if (jobfiles.isempty() == false) { if (scaninterval > 0) { getscheduler().getcontext().put(job_initialization_plugin_name + '_' + getname(), this); } iterator<jobfile> iterator = jobfiles.values().iterator(); while (iterator.hasnext()) { jobfile jobfile = iterator.next(); if (scaninterval > 0) { string jobtriggername = buildjobtriggername(jobfile.getfilebasename()); triggerkey tkey = new triggerkey(jobtriggername, job_initialization_plugin_name); // remove pre-existing job/trigger, if getscheduler().unschedulejob(tkey); jobdetail job = newjob().withidentity(jobtriggername, job_initialization_plugin_name).oftype(filescanjob.class) .usingjobdata(filescanjob.file_name, jobfile.getfilename()) .usingjobdata(filescanjob.file_scan_listener_name, job_initialization_plugin_name + '_' + getname()) .build(); simpletrigger trig = newtrigger().withidentity(tkey).withschedule( simpleschedule().repeatforever().withintervalinmilliseconds(scaninterval)) .forjob(job) .build(); getscheduler().schedulejob(job, trig); getlog().debug("scheduled file scan job data file: {}, @ interval: {}", jobfile.getfilename(), scaninterval); } processfile(jobfile); } } } catch(schedulerexception se) { getlog().error("error starting background-task watching jobs file.", se); } { started = true; } } /** * helper method generating unique job/trigger name * file scanning jobs (one per filejob). unique names saved * in jobtriggernameset. */ private string buildjobtriggername( string filebasename) { // name w/o collisions prefix + _ + filename (with '.' of filename replaced '_') // example: jobinitializationplugin_jobinitializer_myjobs_xml string jobtriggername = job_initialization_plugin_name + '_' + getname() + '_' + filebasename.replace('.', '_'); // if name long (db column 80 chars), truncate max length if (jobtriggername.length() > max_job_trigger_name_len) { jobtriggername = jobtriggername.substring(0, max_job_trigger_name_len); } // make sure name unique in case same file name under different // directories being checked, or had naming collision due length truncation. // if there conflict, keep incrementing _# suffix on name (being sure // not long), until find unique name. int currentindex = 1; while (jobtriggernameset.add(jobtriggername) == false) { // if not our first time through, strip off old numeric suffix if (currentindex > 1) { jobtriggername = jobtriggername.substring(0, jobtriggername.lastindexof('_')); } string numericsuffix = "_" + currentindex++; // if numeric suffix make name long, make room it. if (jobtriggername.length() > (max_job_trigger_name_len - numericsuffix.length())) { jobtriggername = jobtriggername.substring(0, (max_job_trigger_name_len - numericsuffix.length())); } jobtriggername += numericsuffix; } return jobtriggername; } /** * overriden ignore <em>wrapinusertransaction</em> because shutdown() * not interact <code>scheduler</code>. */ @override public void shutdown() { // since have nothing do, override base shutdown don't // extranious usertransactions. } private void processfile(jobfile jobfile) { if (jobfile == null || !jobfile.getfilefound()) { return; } try { customxmlschedulingdataprocessor processor = new customxmlschedulingdataprocessor(this.classloadhelper); processor.addjobgrouptoneverdelete(job_initialization_plugin_name); processor.addtriggergrouptoneverdelete(job_initialization_plugin_name); processor.processfileandschedulejobs( jobfile.getfilename(), jobfile.getfilename(), // systemid getscheduler()); } catch (exception e) { getlog().error("error scheduling jobs: " + e.getmessage(), e); } } public void processfile(string filepath) { processfile((jobfile)jobfiles.get(filepath)); } /** * @see org.quartz.jobs.filescanlistener#fileupdated(java.lang.string) */ public void fileupdated(string filename) { if (started) { processfile(filename); } } class jobfile { private string filename; // these set initialize() private string filepath; private string filebasename; private boolean filefound; protected jobfile(string filename) throws schedulerexception { this.filename = filename; initialize(); } protected string getfilename() { return filename; } protected boolean getfilefound() { return filefound; } protected string getfilepath() { return filepath; } protected string getfilebasename() { return filebasename; } private void initialize() throws schedulerexception { inputstream f = null; try { string furl = null; file file = new file(getfilename()); // files in filesystem if (!file.exists()) { url url = classloadhelper.getresource(getfilename()); if(url != null) { try { furl = urldecoder.decode(url.getpath(), "utf-8"); } catch (unsupportedencodingexception e) { furl = url.getpath(); } file = new file(furl); try { f = url.openstream(); } catch (ioexception ignor) { // swallow exception } } } else { try { f = new java.io.fileinputstream(file); }catch (filenotfoundexception e) { // ignore } } if (f == null) { if (isfailonfilenotfound()) { throw new schedulerexception( "file named '" + getfilename() + "' not exist."); } else { getlog().warn("file named '" + getfilename() + "' not exist."); } } else { filefound = true; } filepath = (furl != null) ? furl : file.getabsolutepath(); filebasename = file.getname(); } { try { if (f != null) { f.close(); } } catch (ioexception ioe) { getlog().warn("error closing jobs file " + getfilename(), ioe); } } } } }
that way have use plugin in configuration , work default.
org.quartz.plugin.jobinitializer.class = com.level2.quartz.processor.plugin.xmlschedulingdataprocessorplugin
Comments
Post a Comment