tag:blogger.com,1999:blog-48358351422965414402023-11-16T03:34:57.357-08:00JNormoxic Weekdays and Hyperoxic WeekendsUnknownnoreply@blogger.comBlogger32125tag:blogger.com,1999:blog-4835835142296541440.post-35916784011921820522012-06-09T10:57:00.001-07:002015-03-13T08:19:36.139-07:00Moving to jayvilalta.com<p>Hello friends.</p> <p>After much debating with myself, I've decided to change blogging platforms and to start blogging at my own domain. From now on, I'll start blogging at <a href="http://jayvilalta.com/blog">http://jayvilalta.com/blog</a>. Feel free to update your reader subscription to point to this new site. </p> <p>One of the main reasons that I am moving my blog is that I am writing a Quartz.Net eBook. This book will include all of the topics that I have blogged about here, as well as some new ones. As I add chapters to the book, I'll also write posts about the same topics at my new blog. The book will in essence provide more in-depth information on the same topics, with the added benefit that it will al be tied together, as opposed to just small and to-the-point posts on a very specific topic.If you would like to know more about the eBook, take a look at <a href="http://jayvilalta.com/blog/2012/06/09/quartz-net-ebook/" target="_blank">this post</a>, where I explain what I am up to.</p> <p>If you would like to know more, please subscribe to my new blog feed or follow me on twitter: @jayvilalta. <br />  <br />I hope to see you at my new site.</p> <p>J</p> Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4835835142296541440.post-70187913801295000722012-01-05T13:57:00.001-08:002015-02-10T16:05:59.754-08:00Using Quartz.Net 2.0 With SQL Compact 4.0NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
Now that SQL Compact 4.0 is out, you might want to use it to as your Quartz.Net job store. Here is how to set up a Quartz.Net 2.0 scheduler with a SQL Compact 4.0 database.<br />
<h5>
Prerequisites</h5>
First, you will need to download the SQL Compact 4.0 runtime and install it on the same box that will run the Quartz.Net scheduler. You can download the runtime directly from the <a href="http://www.microsoft.com/download/en/details.aspx?id=17876" target="_blank">Microsoft site</a>. Be sure to download the correct version for the bit-ness of your operating system. Once it is installed, we’ll configure Quartz.Net to use it as the default job store.<br />
<h5>
Configuring Quartz.Net 2.0 to Use SQL Compact 4.0 as the Jobstore</h5>
By default, Quartz.Net uses a memory based jobstore. This means that all of the jobstore information (jobs, triggers, next fire times, etc.) is lost every time that the scheduler is stopped. A database job store lets you persist this information so that the next time the scheduler starts you will not need to create all of your job and trigger information. <br />
To use a database as the jobstore, you need to set several configuration properties. Here is a sample configuration that uses SQL Compact 4.0 as the job store:<br />
<span style="font-family: Consolas; font-size: x-small;">quartz.jobStore.type = Quartz.Impl.AdoJobStore.JobStoreTX, Quartz <br />quartz.jobStore.driverDelegateType = Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz <br />quartz.jobStore.dataSource = quartzDataSource <br />quartz.dataSource.quartzDataSource.connectionString = Data Source=C:\quartz\quartz.sdf;Persist Security Info=False; <br />quartz.dataSource.quartzDataSource.provider = SqlServerCe-400</span><br />
<h5>
Setting Up the Database File</h5>
You will need a SQL Compact 4.0 database file in which to store the job store information. You can either create the database yourself (that’s a whole separate post itself, which I might write if there is enough interest…) or you can just download <a href="https://github.com/jvilalta/QuartzNetFeaturePack/raw/master/databases/SQL%20Compact%204.0/quartz2-sqlce4.sdf" target="_blank">this empty database</a> that I have already created. Once you have your database file ready to go, just change the data source for the connection string to point to the location of your database file. <br />
<h5>
Starting the Scheduler</h5>
Let’s start our scheduler so that we can see what to expect. Here’s what the console output looks like when everything works correctly:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPykPCd4Pg8YnCmHrShj_HLTblW6R6uh4L3tk0vmljgOEDGzZlx46W-HNbXKSrd3w4HobqYSvZGn3Y83v_JM5kuH6TII__5alhyBMUZffgOIfpSwV3H_ckfa1TZyKuh2-Lm6DKRwDCbEU/s1600-h/image2.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmehn22HPbiP-pnw8kJ8Td2tdElQQH06zDqwH7PSINwhsmpPI6ZweWckGgww7OfKQMsH0neeSsA2gziX-ZnYGh10QIrAGNNHJJZwcg8EZf89KSSI346aUPI-MwUyM1gCqU6vYAJNi2JfI//?imgmax=800" height="185" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
If you already have a running instance of the scheduler, this post should tell you all that need to do to get your scheduler to use SQL Compact 4.0 as a job store.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4835835142296541440.post-59844836967679298802011-12-19T14:18:00.001-08:002014-07-29T08:15:53.901-07:00Installing Multiple Instances of Quartz.Net on One MachineNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
It’s possible to have multiple instances of Quartz.Net on one machine. This is especially useful if you want to run an instance of Quartz.Net 2.0 alongside an existing Quartz.Net 1.0 instance. However, you can install 2 (or more) instances of Quartz.Net 2.0 on the same box if that’s what you want. Fortunately for us, this can all be done via the configuration file.<br />
<h4>
Pre-Requisite (Step 0)</h4>
First you need to create a separate directory for the new Quartz.Net instance that we are about to create. You can/should follow the steps outlined in <a href="http://jvilalta.blogspot.com/2011/12/installing-quartnet-20-beta-1-as.html">this post</a> all the way up to and including step 3. Do not install the service just yet. This is where the configuration changes come into play. <br />
At this point I am going to assume that you have all of your Quartz.Net files in a new directory and that you have verified that the scheduler starts up properly. We’re now ready to configure the scheduler so that we can install an instance of Quartz.Net with a name of our choosing.<br />
<h4>
Step 1 – Change the Configuration File</h4>
In order to the change the Quartz.Net service name, we’re going to be modifying the Quartz.Server.exe.config file. Open up the file in your favorite editor and look for the <quartz> section. In the default distribution, this section is commented out (shown in green below). <br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT6rJ6I8fplNuViSxR3mi5rvBn5LYyzE2K7f8v0eH4-uF0M4EIES-oGegcUtqAGOkyuBrrLUP36dYS-gwIXPPplu4eTS8Himxps16skAy9aVSqyK3N5zrUdQiZ724ia8pTs1fa_2-nyv8/s1600-h/image2.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg88qMZX8gtqaTlXO2RxgQwAkGGBW62zFQJT5zoT4mHjFFBy1YmwKMBMWd257V36_PO-nmSt14NCXSzOKM-ESZvDL8wbQ74k8mjEFC1nY_PncWiMmA9bMA8q1AQlANXNdZpZpbewCACwA//?imgmax=800" height="162" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
We’ll uncomment it and add a few settings in there. Here is what the configuration file looks with our changes:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqBLfWvoKUfB_qHjAyl5zo0_z_MwkKSQyyl-G7tfwWocDxb3R06LHB5zyaO6S1UbDnLCpF3odyqlKo6JOl4tMtXGdVMswyCSGU5BSeNwP8Sacu8dYlLNl-r09XFzmvSCRqz2dy_zORaWc/s1600-h/image5.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiz5upHZ_MWB9zTd8PKs-R7JNG6vSBZzZbxIkUafFOlTQmGCVWzkpLIjGKSAJkQ3r7sjpXY-Dr11jgVw84gMMMGLP56NjnFOUNYP_zMv8YUpAW0R5NOkisy3GtBhqKjtHiFN0puSvPS2WU//?imgmax=800" height="172" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
And here is the <quartz> section itself, so that you can cut and paste it into your configuration file. Feel free to name your service appropriately.<br />
<quartz > <br /> <add key="quartz.checkConfiguration" value="false"/> <br /> <add key="quartz.server.serviceName" value="JQuartz"/> <br /> <add key="quartz.server.serviceDisplayName" value="JQuartz"/> <br /> <add key="quartz.server.serviceDescription" value="JQuartz description"/> <br /></quartz> <br />
<h4>
Step 2 – Install the Service</h4>
Installing the service is now pretty straightforward. Open a command prompt as administrator in the same folder where your new service files are. Now type Quartz.Server.exe install in the command prompt and watch as the service installs. You can also refer to <a href="http://jvilalta.blogspot.com/2011/12/installing-quartnet-20-beta-1-as.html">this post</a> if you want a few more details on the install itself. After installing, you should now have a Quartz.Net service with the same name you specified in the configuration file. We’ll talk about the configuration itself now, but if you already know what the configuration keys above do, feel free to skip the next section and I’ll see you next time.<br />
<h4>
Appendix – The Configuration Details</h4>
If you’re still here then you probably want to know a bit more about the changes we made, so let’s take a look at the configuration itself. First, let me start by saying that you MUST make these changes to the Quartz.Server.exe.config file. Modifying the Quartz.config file will not work. Also, you must set the checkConfiguration key to false, otherwise the scheduler will throw an exception. <br />
The keys themselves are quite explanatory, but I’ll illustrate with a picture of where these keys end up once you install the service. For the configuration above, this is what the installed service looks like:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim0RsSVCFnE_Xh4-ZEx7L3Y6VYy2iiKYGp2FtKsVWb5oxuzlHpt29__pxagEThobUK4mJtbdIakbNUVNgwDHbza7D5TmZnxxlHBpoP7yuUhFhlkt_Lm4mivdcJV66Q6waSa8RNt3Al6MY/s1600-h/image8.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpZZ2qBp4v_Yt6bWpuNTUcwCNh3QkLL0VvHkqwyeOZ1WLmsAk3xshLPDVVBh1Hp6FznBtk42bZdFvGgeOVimvz64FUejclyOx_5d7J-8nlO5sOH5vbW26FiHvV9s8uoG-dVpBWCg1aFIc//?imgmax=800" height="114" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
Finally, be sure to provide both the serviceName and serviceDisplayName values when doing a custom install and make sure that the names are unique so that the installation process works properly.<br />
I’ve tested this on Windows 7 and Windows 2K3, so let me know if you run into any issues.Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-4835835142296541440.post-56917212551752565462011-12-02T12:34:00.001-08:002014-07-29T08:16:10.203-07:00Installing Quart.Net 2.0 Beta 1 as a Windows ServiceNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
Now that there is an official beta release of Quartz.Net 2, I thought it would be a good idea to go through the installation process and describe it step by step. Before we get started I’d like to point out that this post was written using Windows 7, so the screenshots may not match exactly what you see if you are on a different version.<br />
<h4>
Step 1: Download and Unpack the Binaries</h4>
The latest Quartz.Net 2.0 binaries are available from Sourceforge, <a href="http://sourceforge.net/projects/quartznet/">here</a>. Download the zip file and unpack the contents to a folder. If you are using Windows 7, be sure to unblock the downloaded zip file before extracting the files. This is done by right clicking on the downloaded file and clicking on the unblock button BEFORE unzipping the file. <br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZUm0RM454dq_DgLlKBCu2J0ZC79x0n4dNj-kLovIHukk1jrzLMwOzivIZFV76K1jZI7xYDyqt3Ep7jsUtm56RPYvG1xGHWbl0AF3PXRMeIt0JgJ-37mPt3RYvUmmzOtAk4M9vvGhJE0M/s1600-h/image17.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_ISprd3xLfjSh5YPelKUb9kwT2e_LY2frDt8Ys9bGQ1Ym2_TTX4gP0dbKQ-yg06fJvZxVkLxkL-MIqHARf4qrT-7pMcT9zlcNFZTTCrTh4iqJ7uGLOPtSmDGAh0vWj_r3NCO4-hlINLk//?imgmax=800" height="244" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="180" /></a><br />
I will be unzipping the file to c:\quartznet2 for this article. Once you’ve downloaded and unpacked the files, you should have the following directory structure:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbaYeCnSWNDF__hcOIXC30LLSGqorrGZKtghjp_L-ZQj7cRsLD7dodzoUDSHsYAjo1x6QqeJeWJmpLJGp7GTUjKaSzybJAVEIurk5PMArcWmnfyfQzIwnHuexph0AYz-cbqA-I1ZW6CXY/s1600-h/image2.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUZ_2P4eulcpr37dfrnSGIEUy1zDDRQocv3BENrsMR0Qf0vim0LdaiFlCA79CqbMbfbfDXXkDkj5OfVQ_l8url8n_XQh_uECNp-v9Clpn-RWdD2gXWylVNSDjGaykuw9SuSOMy6ynohRo//?imgmax=800" height="153" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="169" /></a><br />
<h4>
Step 2: Select the Appropriate Version</h4>
The beta 1 distribution provides binaries for the 3.5 and 4.0 versions of the .Net framework. Select the appropriate folder for your version from the following:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsDN6MLI3_Q6kYscABCADxnkhU55NoIrwSGYL62_zUX3YvufICe_MeJ4BzAcAL66yuj2jq8tAybvOR1y0Il7ymftbpaDIFpIVAXfDVRjmDUYZmHRqTfsE4sR-EQF1t9s4al2c7hIhUR5o/s1600-h/image5.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBPJ1zmd6i-lrhNHsiFeYi3iInDHUzWFeNqNvuuAuXcpSwQJ1HZG_sFIwBNI5v7jLzE7ye0O2Uxz8_n7hOd4DQpJcbFzskunG7VrHOzhAyuS5YDzjrJuPdXkXoMbJ6_IpMrSJNOubb9MA//?imgmax=800" height="238" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="156" /></a><br />
<h4>
Step 3: Sanity Check </h4>
Before installing Quartz.Net 2 as a service, let’s check that everything is working properly. I’m running version 4.0 of the framework so I will open a command prompt <strong>as Administrator</strong> in the 4.0 folder. <strong>Note: If you don’t open the command prompt as administrator, you will get no error messages or UAC prompts. The installation will simply fail.</strong><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHP1N4pemLBENhl7DlQtkmeVVkH5S931o_x6uwOGLMeT3369MzHPGKkdkSQpQX10f1J7VFh2PIwAr4ieqTWYz8Uj7cvEdgFYxK6EBh63xYbk9rleFWCw9N5zMXgV_6jL2hU78GZZ-AX2Y/s1600-h/image11.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-MXe9bI3GqpkrOIj0cSWKpqsQ-Id4ueDoqMTp5s4LV8fsqJjqdTgi4JyCXdNx6ONBu5zbhyphenhyphenGjGUXuOZ5M9odDARfnTT-k3A3cIBKn5_7PoReeQwCfS72VpTTMh-vOJPPebVpUrt4oQIo//?imgmax=800" height="125" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
Now that we have a command prompt, let’s try starting the Quartz.Net server. To do this, simply run Quartz.Server.exe by typing it into the command prompt. <br />
If nothing happens, then you probably forgot to unblock the files you downloaded. Go back to Step 1 and start over. If everything is well, you will see some output in the command prompt. This means Quartz.Net is running and that the sample job that is configured out of the box is running correctly.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia5OplvXRIRgp3YGWQlAxnjgt3FTjXJCBAz7srq7O4jXqn_NnOXjy6JdBTJDjxSUOh_v8KJBIoZe7Q5Vq9XDvscxo7BfuVoMQQqOZxIJKXDnA13zDE5zRYzWmDk1VsLv787behnhcAgSo/s1600-h/image20.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSnasnCjf9jusckwxQONX_Zo2-RX0peXWxaxxEhGhAQPjrWzjQAd3AGuc69bHNsn36bSs_MBbL_34SpKy4eoPLnopjggvYgEQhfQLz13VoE9bdpAgZ15P1U4NBXq-FUrpmWxb6AMKjbUw//?imgmax=800" height="125" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
You may also get a firewall warning window, similar to this one:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2ATowOofhSN9sjzpCQsDVzHwfiJlW4ZJuIj6nBbC9KOBxLPPcw5pRKuv1bseT47niXBytt4b1GKuJBfXlLMM1arrGAV2K3TIMOvm_QhAXI1ceB8k1xUx2upbD8KDB73nkC84uG0nnANA/s1600-h/image23.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVbs0mTJcnrrzIkykq6sBDsqPvjA8mHEEto3ThXLqrWT-iIBPk80WVEjyD0j7a45lWUdg930CJIU5piHevtXVC93IGxdtbmH6SQ30r4PoX3f6-NReoH5-FF79TKKtYVb7pLC0ITJU-Zb0//?imgmax=800" height="192" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
This is because by default the scheduler exposes a remoting interface that allows you to interact with it. If you wish to enable access to remoting, then go ahead and click allow access. otherwise, click cancel. You’ll have to configure the firewall manually later if you wish to enable remoting access on the scheduler.<br />
Press CTRL-C to stop the scheduler.<br />
<h4>
Step 4: Installing the Service</h4>
At this point you should be quite confident that the base distribution will work once installed as a windows service. Now it’s time to install the service. To do this, type Quartz.Server.exe install in the command prompt. If all goes well, you should see the following in your command prompt.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrwLP3pjQ-aKj5WppqPAR2J2yQl0cvyRx-9VWvv80ibRdgInutrL2xnuwsVNwMH3UHJ8fcwUABdppRTw3VVMB5tqwghYvYgvd46KlH_vEVQ4Kk5FVM57Wl7ZFCx_iiQA3PYNPIgxO-A-E/s1600-h/image26.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijDIoUf04qF5kUajEukvRaJPmvRO40ytjR6evMOmSg4HPvXHUMmneRR2wJZZazur5S24JIYTV02Wwt8XKTXPxOLXKGSJqmcF6Sk39GdDouEpDArCT0Ib3nB7SbaxwdQe8oBa3x5tcbgU0//?imgmax=800" height="125" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
Now type services.msc in the command prompt to open the services administration window. There you should see the quartz service installed as “Quartz Server” with automatic startup and running under the Local System account. <br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoeKS_BjPFYFIqUgPgTqkzTP0QJDdOjgRx8qzdrhUVDnSlhgBy0r1e_zqlxrc1wDHyC2HCi1Yjr09MJtvSvEgzf5P1fkS2WobrzOR03GDVHdHW8woa4EZJO3zok8amjVS8vaz7e_RMnDU/s1600-h/image29.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNzD5zToMGron-fHmgt8bnpCboMX8eVc6suywEcTzMw-6TKoywKVARbq57F3B8zrfu5MlRMQYE9yUD2ci1OmuZQrG6S7X0BFtdOoFDLZzfhpEj_6rKid42AecON-XYlbA7-fsdKtiO6bI//?imgmax=800" height="128" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
You should now be able to start and stop the service through the administration window. Unknownnoreply@blogger.com11tag:blogger.com,1999:blog-4835835142296541440.post-778084845413009362011-07-15T10:39:00.001-07:002014-07-29T08:16:57.949-07:00Configuring a DirectoryScanJob in Quartz.Net 2.0NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
In today’s post I will explain how to configure a DirectoryScanJob in Quartz.Net 2.0. Configuring the DirectoryScanJob can be done either programmatically or using the quartz_jobs.xml file. We will cover how to configure the job using the xml file in this post as it is not exactly straightforward to do so. If you’re interested in a post on how to configure the job programmatically, please leave a comment.<br />
<h4>
How to Configure the DirectoryScanJob using quartz_jobs.xml</h4>
For our example we will configure a DirectoryScanJob that looks at given directory for changes and then writes out to the log how many files were updated. Then we will add a file to the directory and we will see what happens on the scheduler. Let’s get started.<br />
First, we’ll create the folder that will be our scan folder: C:\FolderToScan.<br />
Now, let’s create the quartz_jobs.xml file and configure it appropriately. It will look something like this:<br />
<div class="csharpcode">
<pre><span class="lnum"> 1: </span><span class="kwrd"><</span><span class="html">schedule</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 2: </span> </pre>
<br />
<br />
<pre><span class="lnum"> 3: </span><span class="kwrd"><</span><span class="html">job</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 4: </span> <span class="kwrd"><</span><span class="html">name</span><span class="kwrd">></span>directoryScanJobExample<span class="kwrd"></</span><span class="html">name</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 5: </span> <span class="kwrd"><</span><span class="html">group</span><span class="kwrd">></span>directoryScanJobExample<span class="kwrd"></</span><span class="html">group</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 6: </span> <span class="kwrd"><</span><span class="html">description</span><span class="kwrd">></span>Sample job for Quartz Server<span class="kwrd"></</span><span class="html">description</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 7: </span> <span class="kwrd"><</span><span class="html">job-type</span><span class="kwrd">></span>Quartz.Job.DirectoryScanJob, Quartz<span class="kwrd"></</span><span class="html">job-type</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 8: </span> <span class="kwrd"><</span><span class="html">job-data-map</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 9: </span> <span class="kwrd"><</span><span class="html">entry</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 10: </span> <span class="kwrd"><</span><span class="html">key</span><span class="kwrd">></span>DIRECTORY_NAME<span class="kwrd"></</span><span class="html">key</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 11: </span> <span class="kwrd"><</span><span class="html">value</span><span class="kwrd">></span>C:\FolderToScan<span class="kwrd"></</span><span class="html">value</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 12: </span> <span class="kwrd"></</span><span class="html">entry</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 13: </span> <span class="kwrd"><</span><span class="html">entry</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 14: </span> <span class="kwrd"><</span><span class="html">key</span><span class="kwrd">></span>DIRECTORY_SCAN_LISTENER_NAME<span class="kwrd"></</span><span class="html">key</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 15: </span> <span class="kwrd"><</span><span class="html">value</span><span class="kwrd">></span>DirectoryScanListenerExample<span class="kwrd"></</span><span class="html">value</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 16: </span> <span class="kwrd"></</span><span class="html">entry</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 17: </span> <span class="kwrd"></</span><span class="html">job-data-map</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 18: </span><span class="kwrd"></</span><span class="html">job</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 19: </span> </pre>
<br />
<br />
<pre><span class="lnum"> 20: </span><span class="kwrd"><</span><span class="html">trigger</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 21: </span> <span class="kwrd"><</span><span class="html">simple</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 22: </span> <span class="kwrd"><</span><span class="html">name</span><span class="kwrd">></span>directoryScanJobExampleSimpleTrigger<span class="kwrd"></</span><span class="html">name</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 23: </span> <span class="kwrd"><</span><span class="html">group</span><span class="kwrd">></span>directoryScanJobExampleSimpleTriggerGroup<span class="kwrd"></</span><span class="html">group</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 24: </span> <span class="kwrd"><</span><span class="html">description</span><span class="kwrd">></span>Simple trigger to simply fire sample job<span class="kwrd"></</span><span class="html">description</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 25: </span> <span class="kwrd"><</span><span class="html">job-name</span><span class="kwrd">></span>directoryScanJobExample<span class="kwrd"></</span><span class="html">job-name</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 26: </span> <span class="kwrd"><</span><span class="html">job-group</span><span class="kwrd">></span>directoryScanJobExample<span class="kwrd"></</span><span class="html">job-group</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 27: </span> <span class="kwrd"><</span><span class="html">misfire-instruction</span><span class="kwrd">></span>SmartPolicy<span class="kwrd"></</span><span class="html">misfire-instruction</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 28: </span> <span class="kwrd"><</span><span class="html">repeat-count</span><span class="kwrd">></span>-1<span class="kwrd"></</span><span class="html">repeat-count</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 29: </span> <span class="kwrd"><</span><span class="html">repeat-interval</span><span class="kwrd">></span>10000<span class="kwrd"></</span><span class="html">repeat-interval</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 30: </span> <span class="kwrd"></</span><span class="html">simple</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 31: </span><span class="kwrd"></</span><span class="html">trigger</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 32: </span> </pre>
<br />
<br />
<pre><span class="lnum"> 33: </span><span class="kwrd"><</span><span class="html">job</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 34: </span> <span class="kwrd"><</span><span class="html">name</span><span class="kwrd">></span>addDirectoryScanListener<span class="kwrd"></</span><span class="html">name</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 35: </span> <span class="kwrd"><</span><span class="html">group</span><span class="kwrd">></span>directoryScanJobExample<span class="kwrd"></</span><span class="html">group</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 36: </span> <span class="kwrd"><</span><span class="html">description</span><span class="kwrd">></span>Sample job for Quartz Server<span class="kwrd"></</span><span class="html">description</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 37: </span> <span class="kwrd"><</span><span class="html">job-type</span><span class="kwrd">></span>Examples.DirectoryScanListenerExample, Examples<span class="kwrd"></</span><span class="html">job-type</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 38: </span><span class="kwrd"></</span><span class="html">job</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 39: </span> </pre>
<br />
<br />
<pre><span class="lnum"> 40: </span><span class="kwrd"><</span><span class="html">trigger</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 41: </span> <span class="kwrd"><</span><span class="html">simple</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 42: </span> <span class="kwrd"><</span><span class="html">name</span><span class="kwrd">></span>addDirectoryScanListenerSimpleTrigger<span class="kwrd"></</span><span class="html">name</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 43: </span> <span class="kwrd"><</span><span class="html">group</span><span class="kwrd">></span>directoryScanJobExampleSimpleTriggerGroup<span class="kwrd"></</span><span class="html">group</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 44: </span> <span class="kwrd"><</span><span class="html">description</span><span class="kwrd">></span>Simple trigger to simply fire sample job<span class="kwrd"></</span><span class="html">description</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 45: </span> <span class="kwrd"><</span><span class="html">job-name</span><span class="kwrd">></span>addDirectoryScanListener<span class="kwrd"></</span><span class="html">job-name</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 46: </span> <span class="kwrd"><</span><span class="html">job-group</span><span class="kwrd">></span>directoryScanJobExample<span class="kwrd"></</span><span class="html">job-group</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 47: </span> <span class="kwrd"><</span><span class="html">misfire-instruction</span><span class="kwrd">></span>SmartPolicy<span class="kwrd"></</span><span class="html">misfire-instruction</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 48: </span> <span class="kwrd"><</span><span class="html">repeat-count</span><span class="kwrd">></span>0<span class="kwrd"></</span><span class="html">repeat-count</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 49: </span> <span class="kwrd"><</span><span class="html">repeat-interval</span><span class="kwrd">></span>10000<span class="kwrd"></</span><span class="html">repeat-interval</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 50: </span> <span class="kwrd"></</span><span class="html">simple</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 51: </span><span class="kwrd"></</span><span class="html">trigger</span><span class="kwrd">></span></pre>
<br />
<br />
<pre><span class="lnum"> 52: </span><span class="kwrd"></</span><span class="html">schedule</span><span class="kwrd">></span></pre>
<br /></div>
<br />
<style type="text/css"><br /><br /><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style><br />
<br />
Lines 3-31 of the xml file are used to define the DirectoryScanJob and to set the required properties on it. The job is set to look at the C:\FolderToScan folder that we created earlier (lines 9-12). The listener that will be notified when files are updated in the folder is called <strong>DirectoryScanListenerExample </strong>(lines 13-16)<strong>. </strong>This is just the listener’s friendly name (the key used to look it up actually). We could have called it Jim. Next up is the trigger definition (lines 20-31), which creates a SimpleTrigger that fires every 10 seconds until the scheduler is stopped.<br />
<br />
<br />
Right after the configuration of the DirectoryScanJob you will find another job configuration. This extra job is necessary because we have no way other way of adding the DirectoryScanListener to the scheduler through the quartz_jobs.xml. What we have done is created a job that runs once and adds the DirectoryScanListener to the scheduler. Let’s take a look at the code for Examples.DirectoryScanListenerExample, which is both the job that adds the listener as well as the listener itself. This is done by implementing both IJob and IDirectoryScanListener. You probably don’t want to do this in your production code, but for a quick example it works fine. Here’s the code for <strong>DirectoryListenerExample</strong>:<br />
<br />
<br />
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> DirectoryScanListenerExample : IDirectoryScanListener, IJob
{
<span class="kwrd">public</span> <span class="kwrd">void</span> FilesUpdatedOrAdded(FileInfo[] updatedFiles)
{
logger.InfoFormat(<span class="str">"Found {0} updated files"</span>, updatedFiles.Length);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Execute(IJobExecutionContext context)
{
logger.Info(<span class="str">"Adding the listener to the context"</span>);
context.Scheduler.Context.Add(<span class="str">"DirectoryScanListenerExample"</span>, <span class="kwrd">new</span> DirectoryScanListenerExample());
logger.Info(<span class="str">"Added the listener to the context"</span>);
}
<span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">readonly</span> ILog logger = LogManager.GetLogger(<span class="kwrd">typeof</span>(JobListenerExample));
}</pre>
<br />
<style type="text/css"><br /><br /><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style><br />
<br />
This implementation of the <strong>IDirectoryScanListener</strong> is quite simple. The <strong>FilesUpdatedOrAdded</strong> method gets called when the job detects changes and it prints out to the log how many files were updated. The <strong>Execute</strong> method is called once, and here is where we add the listener to the scheduler’s context. The listener’s name is hard coded here, but you could also make that a parameter that gets passed in from the quartz_jobs.xml file via the job data map.<br />
<br />
<br />
<h4>
Running the DirectoryScanJob</h4>
<br />
<br />
Let’s start up our scheduler with this quartz_jobs.xml and see what happens. Here is the output from the scheduler’s start up process (I’ve removed the non interesting bits…).<br />
<br />
<br />
<div class="csharpcode">
<br />
<pre><span class="lnum"> 1: </span>Parsing XML file: C:\quartznet2\quartz_jobs.xml with systemId: ~/quartz_jobs.xml</pre>
<br />
<br />
<pre><span class="lnum"> 2: </span>Adding 2 jobs, 2 triggers.</pre>
<br />
<br />
<pre><span class="lnum"> 3: </span>Adding job: directoryScanJobExample.addDirectoryScanListener</pre>
<br />
<br />
<pre><span class="lnum"> 4: </span>Adding job: directoryScanJobExample.directoryScanJobExample</pre>
<br />
<br />
<pre><span class="lnum"> 5: </span>Scheduler ServerScheduler_$_NON_CLUSTERED started.</pre>
<br />
<br />
<pre><span class="lnum"> 6: </span>Adding the listener to the context</pre>
<br />
<br />
<pre><span class="lnum"> 7: </span>Job directoryScanJobExample.directoryScanJob</pre>
<br />
<br />
<pre><span class="lnum"> 8: </span>Example threw a JobExecutionException:</pre>
<br />
<br />
<pre><span class="lnum"> 9: </span>Parameters: refire = False, unscheduleFiringTrigger = False, unscheduleAllTriggers = False</pre>
<br />
<br />
<pre><span class="lnum"> 10: </span> Quartz.JobExecutionException: DirectoryScanListener named <span class="str">'DirectoryScanListenerExample'</span> not found <span class="kwrd">in</span> SchedulerContext</pre>
<br />
<br />
<pre><span class="lnum"> 11: </span> at Quartz.Job.DirectoryScanJob.Execute(IJobExecutionContext context) <span class="kwrd">in</span> C:\git\quartznet\src\Quartz\Job\DirectoryScanJob.cs:line 90</pre>
<br />
<br />
<pre><span class="lnum"> 12: </span> at Quartz.Core.JobRunShell.Run() <span class="kwrd">in</span> C:\git\quartznet\src\Quartz\Core\JobRunShell.cs:line 188</pre>
<br />
<br />
<pre><span class="lnum"> 13: </span>Added the listener to the context</pre>
<br /></div>
<br />
<style type="text/css"><br /><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style><br />
<br />
Lines 1 – 5 show us the scheduler starting, the xml file being parsed and the jobs being added. So far so good. It gets a little confusing from now on because we have several threads running, but I think we can make sense of it. Line 6 tells us that the job to add the listener has kicked off. However, lines 7 – 12 tell us that the scan job is trying to run, but it fails to run because the listener is not available. That’s because the job that adds the listener is not finished yet. Line 13 tells us that the listener is ready and has been added to the scheduler. From now on, the scan job will run successfully because it has its listener in place. Let’s add a file to the folder and see what happens.<br />
<br />
<br />
After adding a file to the folder, we see the following:<br />
<br />
<br />
<pre class="csharpcode">Directory <span class="str">'C:\FolderToScan'</span> contents updated, notifying listener.
Found 1 updated files</pre>
<br />
<style type="text/css"><br /><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style><br />
<br />
This is what we expected, so all is good. We’ve successfully configured a DirectoryScanJob and a listener using the quartz_jobs.xml.Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-4835835142296541440.post-86825700369452029322011-06-25T13:22:00.001-07:002015-03-16T08:37:14.143-07:00Implementing a Job Listener in Quartz.Net 2.0NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
In this post we will be implementing the job listener that we discussed in the <a href="http://jvilalta.blogspot.com/2011/06/implementing-plugin-in-quartznet-20.html" target="_blank">previous post</a>. The previous post showed us how to add a scheduler listener to the scheduler using a plugin. Now we will describe what you need to do to implement a job listener in Quartz.Net 2.0. If you’re interested in learning how to implement a job listener in version 1.0 of Quartz.Net, take a look at <a href="http://jvilalta.blogspot.com/2010/11/creating-quartznet-joblistener.html" target="_blank">this post</a>.<br />
<h4>
Implementing the IJobListener Interface</h4>
To create a job listener, we must write a class that implements the IJobListener interface. This interface is defined as follows:<br />
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">interface</span> IJobListener
{
<span class="kwrd">string</span> Name { get; }
<span class="kwrd">void</span> JobExecutionVetoed(IJobExecutionContext context);
<span class="kwrd">void</span> JobToBeExecuted(IJobExecutionContext context);
<span class="kwrd">void</span> JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException);
}</pre>
<br />
<br />
<style type="text/css"><br /><br /><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style>The <strong>Name</strong> property will hold the name of the job listener and is read-only. The rest of the interface is what is of most interest to us. These three methods give you the opportunity to interact with a job during its lifecycle. The first method, <strong>JobExecutionVetoed</strong> gets called whenever a trigger listener vetoes the execution of a job. If this method is called, no other methods in this interface will be called. The second method, <strong>JobToBeExecuted</strong>, is called right before the job is about to be executed. The third method, <strong>JobWasExecuted</strong>, is called after the job has been executed. You do not have to provide implementations for all 3 methods unless you want to, but the methods do need to be present in your class to satisfy the interface.<br />
<br />
<br />
<h4>
The JobListenerExample</h4>
<br />
<br />
In our example we will provide very simple implementations of these methods, only to illustrate how to build a listener. All the JobListenerExample does is log an informational message whenever one of the methods of the interface are called. The code for the simple listener is listed below.<br />
<br />
<br />
<pre class="csharpcode"><span class="kwrd">class</span> JobListenerExample : IJobListener
{
<span class="kwrd">public</span> <span class="kwrd">void</span> JobExecutionVetoed(IJobExecutionContext context)
{
logger.Info(<span class="str">"JobExecutionVetoed"</span>);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> JobToBeExecuted(IJobExecutionContext context)
{
logger.Info(<span class="str">"JobToBeExecuted"</span>);
}
<span class="kwrd">public</span> <span class="kwrd">void</span> JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException)
{
logger.Info(<span class="str">"JobWasExecuted"</span>);
}
<span class="kwrd">public</span> <span class="kwrd">string</span> Name
{
get { <span class="kwrd">return</span> <span class="str">"JobListenerExample"</span>; }
}
<span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">readonly</span> ILog logger = LogManager.GetLogger(<span class="kwrd">typeof</span>(JobListenerExample));
}</pre>
<br />
<style type="text/css"><br /><br /><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style><br />
<br />
If you would like a more in depth example of a job listener that actually does something useful, take look at <a href="http://jvilalta.blogspot.com/2010/11/creating-quartznet-joblistener.html" target="_blank">this post</a>, which describes how to implement a job listener that logs job execution information to a database. The example is for Quartz.Net 1.0, but you’ll notice that the only difference between the two interfaces is that the method signatures are now defined using interfaces instead of concrete types.<br />
<br />
<br />
<h4>
Loading and Executing the Listener</h4>
<br />
<br />
In order to load and execute your listener, you will have to add it to the scheduler upon start up. You must also specify whether it should executed for all jobs, or for some job in particular. How to do this using a plugin is described in the <a href="http://jvilalta.blogspot.com/2011/06/implementing-plugin-in-quartznet-20.html" target="_blank">previous post</a>. Finally, you must make sure that the assembly that contains your listener is available somewhere that the scheduler can load it upon startup.Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-4835835142296541440.post-53861156150684740892011-06-06T20:46:00.001-07:002014-07-29T08:17:53.211-07:00Implementing a Plugin in Quartz.Net 2.0NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
Today we will implement a plugin for Quartz.Net 2.0. If you’re looking for a way to implement a plugin for version 1.0 of Quartz.Net, take a look at <a href="http://jvilalta.blogspot.com/2010/09/creating-quartznet-plug-in.html" target="_blank">this post</a>. Most of the steps are the same, but there are some API changes, so the plugin isn’t exactly the same, as you will see.<br />
What are plugins used for in Quartz.Net 2.0? Well, plugins come in handy if there is something you want to do whenever the scheduler is started or stopped. Some examples of handy plugins are: <br />
<ul>
<li>plugins to load jobs into a RAM jobstore upon scheduler startup (this one is available out of the box) </li>
<li>plugins to register listeners (listeners must be registered with the scheduler upon startup since they are not persisted) </li>
</ul>
In order to implement a listener in Quartz.Net 2.0 there are several steps we need to take. First we must implement the ISchedulerPlugin interface and then we must configure the scheduler to load our plugin. Let’s get started.<br />
<h4>
Implementing the ISchedulerPlugin Interface</h4>
In order to create your own plugin, you have to implement the ISchedulerPlugin interface. Here is the ISchedulerPlugin interface definition:<br />
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">interface</span> ISchedulerPlugin
{
<span class="kwrd">void</span> Initialize(<span class="kwrd">string</span> pluginName, <span class="kwrd">IScheduler</span> sched);
<span class="kwrd">void</span> Start();
<span class="kwrd">void</span> Shutdown();
}</pre>
<br />
<style type="text/css"><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style><br />
<br />
As you can see it’s not a very complicated interface. Let’s take some time to look at these methods in a little more detail.<br />
<br />
<br />
<h5>
Initialize</h5>
<br />
<br />
The Initialize method is called before the scheduler is started and it gives your plugin a chance to initialize itself. Keep in mind that at this point the scheduler itself is not running nor fully initialized. Here is what the code comments have to say: <br /> <br />
<br />
<br />
<pre>Called during creation of the IScheduler in order to give the ISchedulerPlugin a chance to Initialize. At this point, the Scheduler's IJobStore is not yet (initialized?). If you need direct access (to) your plugin, you can have it explicitly put a reference to itself in the IScheduler’s SchedulerContext (in the) Initialize(string, IScheduler) method.</pre>
<br />
<br />
<h5>
Start</h5>
<br />
<br />
The Start method is probably the method where most of the logic for your plugin will go. I will let the method’s comments describe the method’s purpose: <br />
<br />
<br />
<pre>Called when the associated IScheduler is started, in order to let the plugin know it can now make calls into the scheduler if it needs to.</pre>
<br />
<br />
<h5>
Shutdown</h5>
<br />
<br />
The shutdown method is there to allow you to do any cleanup that might be necessary for your plugin. The code comments are as follows: <br /> <br />
<br />
<br />
<pre>Called in order to inform the ISchedulerPlugin that it should free up all of it's resources because the scheduler is shutting down.</pre>
<br />
<br />
<h4>
Sample Implementation</h4>
<br />
<br />
Now we will go ahead and actually implement the plugin. In our sample implementation all that our plugin will do is to register a job listener. We are following the same approach we took while discussing how to implement a plugin in version 1.0 of Quartz.Net. This is intentional, to allow you see what the differences are between the two versions. <br />
<br />
<br />
The implementation of our plugin is still very simple, albeit a little different from the one on the <a href="http://jvilalta.blogspot.com/2010/09/creating-quartznet-plug-in.html" target="_blank">previous post</a>: <br /><br /> <br />
<br />
<br />
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class </span>PluginExample : ISchedulerPlugin
{
<span class="kwrd">public</span> <span class="kwrd">void</span> Initialize(<span class="kwrd">string</span> pluginName, <span class="kwrd">IScheduler</span> sched)
{
sched.ListenerManager.AddJobListener(<span class="kwrd">new</span> JobListenerExample(), EverythingMatcher<JobKey>.AllJobs());
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Shutdown()
{
<span class="rem">//Do Nothing</span>
}
<span class="kwrd">public</span> <span class="kwrd">void</span> Start()
{
<span class="rem">//Do Nothing</span>
}
}</pre>
<br />
<style type="text/css"><br /><br /><br /><br /><br /><br />.csharpcode, .csharpcode pre<br />{<br /> font-size: small;<br /> color: black;<br /> font-family: consolas, "Courier New", courier, monospace;<br /> background-color: #ffffff;<br /> /*white-space: pre;*/<br />}<br />.csharpcode pre { margin: 0em; }<br />.csharpcode .rem { color: #008000; }<br />.csharpcode .kwrd { color: #0000ff; }<br />.csharpcode .str { color: #006080; }<br />.csharpcode .op { color: #0000c0; }<br />.csharpcode .preproc { color: #cc6633; }<br />.csharpcode .asp { background-color: #ffff00; }<br />.csharpcode .html { color: #800000; }<br />.csharpcode .attr { color: #ff0000; }<br />.csharpcode .alt <br />{<br /> background-color: #f4f4f4;<br /> width: 100%;<br /> margin: 0em;<br />}<br />.csharpcode .lnum { color: #606060; }</style><br />
<br />
<h4>
Configuring the Scheduler to Load the Plugin</h4>
<br />
<br />
Now that we have created our plugin, the next step is to tell the scheduler to load it. This is done by adding this line to our properties file : <br /> <br /><span style="font-family: Courier New;">quartz.plugin.myplugin.type = Examples.PluginExample, Examples <br /> </span><br /><br /> <br />The plugin property needs to be structured like this: <br /><br /> <br /><span style="font-family: Courier New;">quartz.plugin.{name}.type = {type name}, {assembly name} <br /> </span><span style="font-family: Courier New;"><br /> </span>Let’s discuss the components of the property. First, the <strong>quartz.plugin</strong> part of the property tells the scheduler that this is a plugin that needs to be loaded. The <strong>{name}</strong> part is the name that you want to give to your plug-in, and is the name that is passed in to the <strong>Initialize</strong> method above. The value of the property <strong>{type name}, {assembly name}</strong> tells the scheduler the <strong>Type</strong> of the plug-in, so that it can be loaded into memory. <strong>{type name}</strong> is the full name of your plugin, which in our case would be Examples.PluginExample. <strong>{assembly name}</strong> is the name of your assembly file, minus the .dll extension. Here’s another example of a plugin configuration property, lifted from the Quartz.Net default configuration file: <br /><br /> <br /><span style="font-family: Courier New;">quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz </span><br />
<br />
<br />
<h4>
Final Step</h4>
<br />
<br />
Now that your plugin has been added to the configuration, all you need to do is start the scheduler and check the log for errors. Remember that the dll that contains your plugin needs to be in the same folder as the Quartz.Net binaries so that it can be found by the .Net framework and loaded into memory.Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-4835835142296541440.post-4514694768663784972011-03-15T18:58:00.001-07:002015-03-16T08:38:18.526-07:00New in Quartz.Net 2.0–New Job File FormatNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
The xml format for the quartz_jobs.xml file has changed in Quartz.Net 2.0. This is a breaking change, so you won’t be able to use your existing jobs file with the new version of Quartz.Net without updating it to the 2.0 format. If you’re interested in the details of what can be configured in this file, I would recommend looking at the xsd file that defines the schema for the file. The xsd file that defines the new file format can be downloaded directly from the source code repository, <a href="https://github.com/quartznet/quartznet/blob/master/src/Quartz/Xml/job_scheduling_data_2_0.xsd" target="_blank">here</a>.<br />
Today I’m going to provide a sample quartz_jobs.xml file in the new format and walk you through the creation of the file. Alternatively, you can take a look at the default file (that will be) provided with the Quartz.Net 2.0 distribution, <a href="https://github.com/quartznet/quartznet/blob/master/server/Quartz.Server/quartz_jobs.xml" target="_blank">here</a>.<br />
The new file format starts off with the following root element:<br />
<pre><pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;"><</span><span style="color: maroon;">job</span>-<span style="color: red;">scheduling</span>-<span style="color: red;">data</span> <span style="color: red;">xmlns</span>=<span style="color: blue;">"http://quartznet.sourceforge.net/JobSchedulingData"</span> <span style="color: red;">xmlns</span>:<span style="color: red;">xsi</span>=<span style="color: blue;">"http://www.w3.org/2001/XMLSchema-instance"</span> <span style="color: red;">version</span>=<span style="color: blue;">"2.0"</span><span style="color: blue;">></span></pre>
</pre>
<br />
Right after the root node, our configuration file has two elements, which we will describe in detail below:<br />
<ol>
<li>The <processing-directives> element </li>
<br />
<li>The <schedule> element </li>
</ol>
<br />
<h4>
The <processing-directives> Element</h4>
The processing directives element contains two elements. The first element, <pre-processing-commands> is used to run commands prior to adding jobs and triggers to the scheduler. I’m not going to spend much time going over these in detail, but here is a list of the commands available to you:<br />
<br />
<ul>
<li>delete the jobs in a group </li>
<li>delete the triggers in a group </li>
<li>delete a job </li>
<li>delete a trigger </li>
</ul>
If you find yourself in need of help with these elements, leave a comment and I will write a follow-up post.<br />
<br />
The second element, <processing-directives>, lets you specify how the xml file is to be processed. Here you will find a familiar configuration setting (from Quartz.net 1.0), the <overwrite-existing-data> element. Setting this element’s value to true will replace any jobs currently scheduled with the new schedule given in the xml file (true is the default setting!). The <ignore-duplicates> element is the other element allowed under the <processing-directives> element.<br />
<br />
<h4>
The <schedule> Element</h4>
The <schedule> element is where we describe the jobs and triggers that we want to schedule. This section has also changed its format. Now, instead of grouping jobs and triggers under an element, jobs and triggers are all specified at the same level, and are not grouped under the job element, as was the case in version 1.0.<br />
<br />
Under the <schedule> element, we can have <job> and <trigger> elements, which are the building blocks that we use to put together our schedule. Let’s take a look at these elements now.<br />
<br />
<h4>
The <job> Element</h4>
The <job> element is used to describe the IJob that we want the scheduler to execute. Job details are specified by using the following elements:<br />
<ul>
<li><name> </li>
<li><group> </li>
<li><description> </li>
<li><job-type> </li>
<li><durable> </li>
<li><recover> </li>
<li><job-data-map> </li>
</ul>
All of these elements serve the same purpose as they did in version 1 and, except for the job-data-map, they’re all simple types, so I’m not going to go into great detail here either. If you need a little more help with these, leave a comment and I’ll expand on the explanation as needed.<br />
<br />
The job-data-map, being a complex element, supports an <entry> element inside. The <entry> element has <key> and <value> elements inside, which describe the job property to be added to the job map.<br />
<br />
<h5>
The <trigger> Element</h5>
The <trigger> element is used to describe the trigger that we want to attach to a given job. The xml file loader plugin supports 3 types of triggers:<br />
<ul>
<li>simpleTriggerType</li>
<li>cronTriggerType</li>
<li>calendarIntervalTriggerType </li>
</ul>
These three trigger types are based on the abstractTriggerType, which has the following common elements:<br />
<ul>
<li><name> </li>
<li><group> </li>
<li><description> </li>
<li><job-name> </li>
<li><job-group> </li>
<li><priority> </li>
<li><calendar-name> </li>
<li><job-data-map> </li>
</ul>
In addition to the elements listed above, each trigger type supports some additional elements. These additional elements are used to set parameters that are not common across all of the trigger types. The table below summarizes each of the trigger types and the elements they support.<br />
<br />
<table border="1" cellpadding="2" cellspacing="0" style="width: 400px;"><tbody>
<tr> <td valign="top" width="200"><strong>Trigger Type</strong></td> <td valign="top" width="198"><strong>Additional Elements</strong></td> </tr>
<tr> <td valign="top" width="200">SimpleTrigger</td> <td valign="top" width="198"><misfire-instruction>,<repeat-count>,<repeat-interval></td> </tr>
<tr> <td valign="top" width="200">CronTrigger</td> <td valign="top" width="198"><misfire-instruction>,<cron-expression>,<time-zone></td> </tr>
<tr> <td valign="top" width="200">CalendarIntervalTrigger</td> <td valign="top" width="198"><misfire-instruction>,<repeat-interval>,<repeat-interval-unit></td> </tr>
</tbody></table>
<br />
<br />
I’m not going to go into detail here either. This is already a pretty long post, so if anybody needs more information leave me a comment and I will write a follow-up post.<br />
<br />
<h4>
Putting It All Together</h4>
At this point we’ve described all of the elements that are necessary to describe a job in the new Quartz.Net 2.0 xml format. To put it all together, here are the contents of a sample quartz_jobs.xml file that you can use as a guide:<br />
<br />
<pre><pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;"><?</span>xml version="1.0" encoding="UTF-8"<span style="color: blue;">?></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: green;"><!-- This file contains job definitions in schema version 2.0 format --></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;"><</span><span style="color: maroon;">job</span>-<span style="color: red;">scheduling</span>-<span style="color: red;">data</span> <span style="color: red;">xmlns</span>=<span style="color: blue;">"http://quartznet.sourceforge.net/JobSchedulingData"</span> <span style="color: red;">xmlns</span>:<span style="color: red;">xsi</span>=<span style="color: blue;">"http://www.w3.org/2001/XMLSchema-instance"</span> <span style="color: red;">version</span>=<span style="color: blue;">"2.0"</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">processing</span>-<span style="color: red;">directives</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">overwrite</span>-<span style="color: red;">existing</span>-<span style="color: red;">data</span><span style="color: blue;">></span>true<span style="color: blue;"></</span><span style="color: maroon;">overwrite</span>-existing-data<span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"></</span><span style="color: maroon;">processing</span>-directives<span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">schedule</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">job</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">name</span><span style="color: blue;">></span>nativeJobExample<span style="color: blue;"></</span><span style="color: maroon;">name</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">group</span><span style="color: blue;">></span>nativeJobExampleGroup<span style="color: blue;"></</span><span style="color: maroon;">group</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">description</span><span style="color: blue;">></span>Sample job for Quartz Server<span style="color: blue;"></</span><span style="color: maroon;">description</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">job</span>-<span style="color: red;">type</span><span style="color: blue;">></span>Quartz.Job.NativeJob, Quartz<span style="color: blue;"></</span><span style="color: maroon;">job</span>-type<span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">job</span>-<span style="color: red;">data</span>-<span style="color: red;">map</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">entry</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">key</span><span style="color: blue;">></span>command<span style="color: blue;"></</span><span style="color: maroon;">key</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">value</span><span style="color: blue;">></span>native_job_example.bat<span style="color: blue;"></</span><span style="color: maroon;">value</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"></</span><span style="color: maroon;">entry</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">entry</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">key</span><span style="color: blue;">></span>consumeStreams<span style="color: blue;"></</span><span style="color: maroon;">key</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">value</span><span style="color: blue;">></span>true<span style="color: blue;"></</span><span style="color: maroon;">value</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"></</span><span style="color: maroon;">entry</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"></</span><span style="color: maroon;">job</span>-data-map<span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"></</span><span style="color: maroon;">job</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">trigger</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">simple</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">name</span><span style="color: blue;">></span>nativeJobExampleSimpleTrigger<span style="color: blue;"></</span><span style="color: maroon;">name</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">group</span><span style="color: blue;">></span>nativeJobExampleSimpleTriggerGroup<span style="color: blue;"></</span><span style="color: maroon;">group</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">description</span><span style="color: blue;">></span>Simple trigger example<span style="color: blue;"></</span><span style="color: maroon;">description</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">job</span>-<span style="color: red;">name</span><span style="color: blue;">></span>nativeJobExample<span style="color: blue;"></</span><span style="color: maroon;">job</span>-name<span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">job</span>-<span style="color: red;">group</span><span style="color: blue;">></span>nativeJobExampleGroup<span style="color: blue;"></</span><span style="color: maroon;">job</span>-group<span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">misfire</span>-<span style="color: red;">instruction</span><span style="color: blue;">></span>SmartPolicy<span style="color: blue;"></</span><span style="color: maroon;">misfire</span>-instruction<span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">repeat</span>-<span style="color: red;">count</span><span style="color: blue;">></span>5<span style="color: blue;"></</span><span style="color: maroon;">repeat</span>-count<span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"><</span><span style="color: maroon;">repeat</span>-<span style="color: red;">interval</span><span style="color: blue;">></span>10000<span style="color: blue;"></</span><span style="color: maroon;">repeat</span>-interval<span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"></</span><span style="color: maroon;">simple</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"></</span><span style="color: maroon;">trigger</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;"></</span><span style="color: maroon;">schedule</span><span style="color: blue;">></span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;"></</span><span style="color: maroon;">job</span>-scheduling-data<span style="color: blue;">></span></pre>
</pre>
<br />
This is a working example of a quartz_jobs.xml file that schedules a NativeJob using a SimpleTrigger. This example also shows how to configure the <job-data-map> to pass configuration information to the job.<br />
<br />
I hope this post helps you in building a job configuration file for Quartz.Net 2.0.Unknownnoreply@blogger.com11tag:blogger.com,1999:blog-4835835142296541440.post-23921702772768402512011-03-09T18:54:00.001-08:002015-03-16T08:42:17.375-07:00Scheduling Jobs Programmatically in Quartz.Net 2.0NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
Scheduling jobs programmatically in Quartz.Net 2.0 is very similar to scheduling a job in Quartz.Net 1.0. The overall process is the same, but the scheduler API has changed for version 2.0, so the code used will be significantly different. <br />
In this post we will only highlight the differences between the two versions, so if you’re not familiar with the process, then read <a href="http://jvilalta.blogspot.com/2011/03/scheduling-jobs-programmatically-in.html" target="_blank">this post</a> first. Then come back to this post to understand what has changed in version 2.0.<br />
<h4>
What Has Changed</h4>
Only a couple of things have changed in Quartz.Net 2.0 when it comes to scheduling a job programmatically: the way you build jobs and triggers. <br />
The new Quartz.Net scheduler API uses more interfaces now. It also provides builder objects to create triggers (ITrigger now) and job details (IJobDetail now). I think the simplest way to highlight the differences is to take the code from my original post and convert it to the new API. Here’s the updated code:<br />
<pre><pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">void</span> ScheduleOneTimeJob(Type jobType, JobDataMap dataMap)</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">{</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">string</span> name = DateTime.Now.ToString("<span style="color: darkred;">yyyyMMddHHmmss</span>"));</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">string</span> group = "<span style="color: darkred;">OneTimeJobs</span>";</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: green;">// create job</span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> IJobDetail jobDetail = JobBuilder</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .Create()</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .OfType(jobType)</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .WithIdentity(<span style="color: blue;">new</span> JobKey(name, group))</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .UsingJobData(dataMap)</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .Build();</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: green;">// create trigger</span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> ITrigger trigger = TriggerBuilder</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .Create()</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .ForJob(jobDetail)</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .WithIdentity(<span style="color: blue;">new</span> TriggerKey(name, group));</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .WithSchedule(SimpleScheduleBuilder.Create())</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .StartNow()</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> .Build();</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: green;">// get reference to scheduler (remote or local) and schedule job</span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> GetScheduler().ScheduleJob(jobDetail, trigger);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">}</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
</pre>
<br />
<br />
As you can see, the changes to the code are pretty significant, but the overall process remains the same. I’d like to provide you with some links to documentation or some other examples, but I’m unaware of any at this point, as Quartz.Net 2.0 has not yet been released.Unknownnoreply@blogger.com8tag:blogger.com,1999:blog-4835835142296541440.post-67682819513298742722011-03-09T18:50:00.001-08:002014-07-29T08:19:12.147-07:00Scheduling Jobs Programmatically in Quartz.Net 1.0NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
This post is one of those back to basics posts and is inspired by a comment left by <a href="http://www.blogger.com/profile/13836508558710622258" target="_blank">Jan</a> on one of the Getting Started posts. Today we’ll take a look at how to schedule a job programmatically in Quartz.Net 1.0. I’ll follow up with a post on how to schedule a job programmatically in Quartz.Net 2.0 as well.<br />
<h4>
Scheduling Jobs in Quartz.Net</h4>
There are two ways you can schedule a job to run on Quartz.Net. The first way is to schedule it using the plugin that reads an xml file containing the job and scheduling information. If you want more information on how to schedule jobs using the xml plugin, take a look at <a href="http://jvilalta.blogspot.com/2009/04/getting-started-with-quartznet-part-3.html" target="_blank">this post</a>.<br />
You can also schedule jobs by interacting directly with the scheduler API. The Quartz.Net scheduler supports remote access via the .Net remoting facility, so this method of scheduling jobs is available to you regardless of whether the scheduler is running as a standalone windows service or whether it is embedded in your application. The remote scheduler does have some limitations, but we will not run into them while scheduling jobs. Let’s take a look at how we can schedule jobs using the scheduler API.<br />
<h4>
Scheduling Jobs via the Scheduler API</h4>
In a nutshell, these are the steps you would follow to schedule a job using the API:<br />
<ol>
<li>Get a reference to the scheduler object. How you do this will depend on whether you are running a standalone or embedded scheduler.</li>
<li>Create a <a href="http://quartznet.sourceforge.net/apidoc/topic358.html" target="_blank">JobDetail</a> object and set all the necessary properties. At a minimum you must set the <a href="http://quartznet.sourceforge.net/apidoc/topic386.html" target="_blank">Name</a>, the <a href="http://quartznet.sourceforge.net/apidoc/topic381.html" target="_blank">Group</a> and <a href="http://quartznet.sourceforge.net/apidoc/topic384.html" target="_blank">JobType</a>. <span style="color: black;">Please note that because the type of JobType is </span><a href="http://msdn.microsoft.com/en-us/library/system.type(v=VS.100).aspx" target="_blank"><span style="color: black;">Type</span></a><span style="color: black;">, the dll containing the JobType <strong>MUST</strong> be available to the code that is scheduling the job <strong>AS WELL</strong> as to the scheduler. </span></li>
<li>Create a <a href="http://quartznet.sourceforge.net/apidoc/topic644.html" target="_blank">Trigger</a> object (<a href="http://quartznet.sourceforge.net/apidoc/topic644.html" target="_blank">Trigger</a> itself is an abstract class, so you will actually be creating one of these concrete types: <a href="http://quartznet.sourceforge.net/apidoc/topic603.html" target="_blank">SimpleTrigger</a>, <a href="http://quartznet.sourceforge.net/apidoc/topic285.html" target="_blank">CronTrigger</a> or <a href="http://quartznet.sourceforge.net/apidoc/topic446.html" target="_blank">NthIncludedDayTrigger</a>) and set all the necessary properties. At a minimum you must set the <a href="http://quartznet.sourceforge.net/apidoc/topic688.html" target="_blank">Name</a>, and the <a href="http://quartznet.sourceforge.net/apidoc/topic680.html" target="_blank">Group</a>. The <a href="http://quartznet.sourceforge.net/apidoc/topic684.html" target="_blank">JobGroup</a> and the <a href="http://quartznet.sourceforge.net/apidoc/topic685.html" target="_blank">JobName</a> are also necessary as they are what links the <a href="http://quartznet.sourceforge.net/apidoc/topic358.html" target="_blank">JobDetail</a> you created in the previous step with the <a href="http://quartznet.sourceforge.net/apidoc/topic644.html" target="_blank">Trigger</a> you are creating now. However, you do not need to set these properties right now. Read on to step 4 to understand why. </li>
<li>Call the <a href="http://quartznet.sourceforge.net/apidoc/topic89.html" target="_blank">ScheduleJob</a> method on your scheduler object passing in your Trigger and your Job. If you call <strong>this</strong> overload of the <a href="http://quartznet.sourceforge.net/apidoc/topic89.html" target="_blank">ScheduleJob</a> method, then the scheduler will link your trigger and your job, so there is no need for you to set the link explicitly. </li>
</ol>
<h4>
Code Example</h4>
I’d like to close out this post with a code sample that implements the steps outlined above. <br />
<pre><pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">void</span> ScheduleOneTimeJob(Type jobType, JobDataMap dataMap)</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">{</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">string</span> name = DateTime.Now.ToString("<span style="color: darkred;">yyyyMMddHHmmss</span>"));</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">string</span> group = "<span style="color: darkred;">OneTimeJobs</span>";</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: green;">// create job</span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> JobDetail jobDetail = <span style="color: blue;">new</span> JobDetail(name, group, jobType);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> jobDetail.Description = "<span style="color: darkred;">One time job.</span>";</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> jobDetail.JobDataMap = dataMap;</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> </pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: green;">// create trigger</span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> SimpleTrigger trigger = <span style="color: blue;">new</span> SimpleTrigger();</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> trigger.Name = name;</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> trigger.Group = group;</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> trigger.StartTimeUtc = DateTime.UtcNow;</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> trigger.RepeatCount = 0;</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> trigger.RepeatInterval = TimeSpan.Zero;</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> </pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: green;">// get reference to scheduler (remote or local) and schedule job</span></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> GetScheduler().ScheduleJob(jobDetail, trigger);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">}</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
</pre>
<br />
<br />
This sample code demonstrates one way of creating and scheduling a job that runs once, immediately.<br />
<br />
<br />
In Quartz.Net 2.0 the scheduler API has changed significantly, so we will cover that topic in another post.Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4835835142296541440.post-47010988727733562002011-03-01T13:04:00.001-08:002014-07-29T08:19:17.555-07:00How Does Quartz.Net Configuration Work?NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
In this post we will explain in great detail how the Quartz.Net scheduler loads its configuration upon startup. Since the scheduler configuration did not change between versions 1.0 and 2.0, the information here is applicable to both Quartz.Net versions.<br />
In Quartz.Net, the StdSchedulerFactory is responsible for configuring the scheduler. When the Quartz.Net scheduler is started, the factory will try to automatically configure a scheduler by looking for configuration information in different places:<br />
<ul>
<li>the hosting application’s configuration file </li>
<li>a file specified in an environment variable </li>
<li>the quartz.config file </li>
<li>the embedded configuration file </li>
</ul>
<h4>
Configuring From the Hosting Application’s Configuration File</h4>
First, the factory will try to load the scheduler configuration from the <quartz> section of your application’s config file. If you are running Quartz.Net as a windows service, then the service’s configuration file will be used. This file (Quartz.Server.exe.config) can be found in the same folder as the server executable. If you are hosting the Quartz.Net scheduler in your web application, then the web.config file will be checked.<br />
<h4>
Configuring From A File Specified in an Environment Variable</h4>
If the factory was not able to load the quartz configuration section, then the second place it will check is the environment variables of the process. Specifically, the factory will check to see if the quartz.config environment variable has been defined. If such a variable exists and is not empty, the factory will try to load the configuration from whatever file is specified as the value of the variable. For example, let’s say that your configuration file is called myconfig.config. If you set the quartz.config environment variable equal to myconfig.config, then the scheduler will load the configuration information from the file named myconfig.config.<br />
<h4>
Configuring From the Quartz.config File</h4>
Let’s assume that so far, the factory has not been able to load the scheduler’s configuration. The next step that the factory will take is to try to load a file called quartz.config from the same directory where the hosting application’s assembly was loaded. In fact, this is the file that an out-of-the-box Quartz.Net server/service installation uses to configure itself. <br />
<h4>
Configuring From the Embedded Configuration File</h4>
If all of the previous configuration options fail, then the factory falls back on loading the configuration file that is embedded in the quartz assembly. In case you’re curious, here are the configuration properties that are embedded in the assembly:<br />
<table border="0" cellpadding="2" cellspacing="0" style="width: 471px;"><tbody>
<tr> <td valign="top" width="200"><strong>Property</strong></td> <td valign="top" width="269"><strong>Value</strong></td> </tr>
<tr> <td valign="top" width="200">quartz.scheduler.instanceName</td> <td valign="top" width="269">DefaultQuartzScheduler</td> </tr>
<tr> <td valign="top" width="200">quartz.threadPool.type </td> <td valign="top" width="269">Quartz.Simpl.SimpleThreadPool, Quartz</td> </tr>
<tr> <td valign="top" width="200">quartz.threadPool.threadCount </td> <td valign="top" width="269">10</td> </tr>
<tr> <td valign="top" width="200">quartz.threadPool.threadPriority </td> <td valign="top" width="269">Normal</td> </tr>
<tr> <td valign="top" width="200">quartz.jobStore.type </td> <td valign="top" width="269">Quartz.Simpl.RAMJobStore, Quartz</td> </tr>
<tr> <td valign="top" width="200">quartz.jobStore.misfireThreshold </td> <td valign="top" width="269">60000</td> </tr>
</tbody></table>
If after checking all of the above locations for configuration information, the factory was not able to configure the scheduler, then an exception is thrown. As you can probably gather from the previous paragraph, unless you actually change the quartz assembly, this configuration exception will not be raised, because a configuration file is already embedded in the quartz assembly by default.<br />
<h4>
One Final Step</h4>
You’d think that by now, the whole configuration process is finished and the scheduler has been configured successfully. Well, the default scheduler factory takes one last step before giving you the configured scheduler. <br />
Here’s what happens just after your configuration is loaded: if any of the configuration properties that you set in a configuration are also present in the environment variables, then the factory will overwrite them with the environment value. This the expected behavior. However, due to <a href="http://jira.opensymphony.com/browse/QRTZNET-246" target="_blank">a bug</a>, this does not work in Quartz.Net 1.0, but is fixed in Quartz.Net 2.0.Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-4835835142296541440.post-53879342439692053392011-02-08T15:49:00.001-08:002014-07-29T08:19:26.012-07:00New in Quartz.Net 2.0-No More IStatefulJobNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
Welcome to the the third post of my <a href="http://jvilalta.blogspot.com/search/label/new%20in%20Quartz.Net%202.0" target="_blank">New in Quartz.Net 2.0 series</a>. <br />
<h4>
Goodbye IStatefulJob</h4>
Yes, it’s true. In Quartz.Net 2.0 the IStatefulJob has been marked as obsolete. To be sure, it’s still available to use, but if you are using IStatefulJobs you should think about migrating them to use the new Quartz.Net 2.0 features. <br />
<h4>
The Disallow Concurrent Execution Attribute</h4>
So how do I implement an IStatefulJob in Quartz.Net 2.0? Fortunately, it’s not very hard to do. You just need to mark your IJob with the new DisallowConcurrentExecutionAttribute. Any jobs that have this attribute set are only allowed to run one instance of the job at a time. Keep in mind that an instance is defined by a JobKey (job name and group combination), which means that if you have the same job type scheduled with a different job name or a different job group, you may get more than one instance of that type of job running at the same time.<br />
<h4>
The Persist Job Data After Execution Attribute</h4>
Seems simple enough so far? Well, it is! There is only one other thing to consider. If you want the scheduler to persist the job’s state between executions, you must also add the PersistJobDataAfterExecutionAttribute to the class. This attribute tells the scheduler that you would like for it store the job’s JobDataMap once it is finished executing. <br />
<h4>
One Last Thing</h4>
While you can use each of these attributes separately, if you are going to use the PersistJobDataAfterExecutionAttribute to persist your job’s state, you should always use the DisallowConcurrentExecutionAttribute, because if you don’t, you might find that your job state is corrupted due to race conditions.Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4835835142296541440.post-40162593477349970982011-02-04T07:37:00.001-08:002015-03-16T08:31:31.103-07:00New in Quartz.Net 2.0–Directory Scan JobNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
This is the second post of the <a href="http://jvilalta.blogspot.com/search/label/new%20in%20Quartz.Net%202.0" target="_blank">New in Quartz.Net 2.0 series</a>. Today we will look at the DirectoryScanJob, which is a new job in Quartz.Net 2.0. <br />
The DirectoryScanJob is very similar to the FileScanJob, which is available in Quartz.Net 1.0. As you can probably tell from the names, the main difference between the two jobs is that the DirectoryScanJob scans for changes in… you quessed it… a directory , whereas the FileScanJob scans for changes in… yes, you guessed it again… a file. If you’re not familiar with the FileScanJob, don’t worry, we will look at the DirectoryScanJob in detail.<br />
<h4>
Introducing the DirectoryScanJob</h4>
First, let’s take a look at what the documentation says about this new job:<br />
<blockquote>
<em>“Inspects a directory and compares whether any files' "last modified dates" have changed since the last time it was inspected. If one or more files have been updated (or created), the job invokes a "call-back" method on an identified DirectoryScanListener that can be found in the SchedulerContext.”</em></blockquote>
That seems pretty self explanatory, no? Basically, you tell the job that it needs to check a certain directory to see if new files have been added or if existing files have been modified. When the job is executed it checks the files and stores the file information in its JobDataMap. The next time the job runs, it compares the information stored in the job’s JobDataMap, with the files in the directory. If any changes are found, the job calls the FilesUpdatedOrAdded method of the IDirectoryScanListener that was configured for that job, passing in an arrary of FileInfo objects.<br />
<h4>
Configuring the DirectoryScanJob</h4>
To configure and use a DirectoryScanJob, you will need to set the following keys in the JobDataMap:<br />
<ol>
<li>DIRECTORY_NAME: this is the path to the directory that you want to monitor. </li>
<li>DIRECTORY_SCAN_LISTENER_NAME: this is the name of the DirectoryScanListener that should called if changes are detected </li>
<li>MINIMUM_UPDATE_AGE: this is an optional parameter which lets you specify how many milliseconds must have passed since the file’s last modified time in order to consider the file modified. If this parameter is not specified, it defaults to 5000 milliseconds. </li>
</ol>
<h4>
Possible Uses for the DirectoryScanJob</h4>
There are many uses for the DirectoryScanJob, so let’s list a few here:<br />
<ul>
<li>You could replace any FileWatcher type services that you might have implemented </li>
<li>Scan files uploaded by users for viruses </li>
<li>Schedule other jobs to process files that have been copied to the directory for processing </li>
</ul>
The next post in the series will cover a change to the IStatefulJob interface: it has been marked as obsolete and is replaced by a class attribute!Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4835835142296541440.post-40026527660350817362011-01-30T09:13:00.001-08:002015-03-16T08:44:40.684-07:00New in Quartz.Net 2.0–The Calendar Interval TriggerNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
This is the first post of what will become a series of posts highlighting the new features that will be available in Quartz.Net 2.0.<br />
To kick off the series, we will take a look at the CalendarIntervalTrigger. This trigger is used to fire jobs based on a recurring calendar time interval. The following time intervals are available:<br />
<table border="0" cellpadding="2" cellspacing="0" style="width: 104px;"><tbody>
<tr> <td valign="top" width="102"><strong>IntervalUnit</strong></td> </tr>
<tr> <td valign="top" width="102">Minute</td> </tr>
<tr> <td valign="top" width="102">Hour</td> </tr>
<tr> <td valign="top" width="102">Day</td> </tr>
<tr> <td valign="top" width="102">Week</td> </tr>
<tr> <td valign="top" width="102">Month</td> </tr>
<tr> <td valign="top" width="102">Year</td> </tr>
</tbody></table>
This trigger has a RepeatInterval property, which can be used to indicate that the trigger should fire every N intervals. For example, if you set the RepeatIntervalUnit to Week and the RepeatInterval to 2, your trigger will fire every two weeks.<br />
Here is what the source code documentation says about this trigger:<br />
<blockquote>
<em>A concrete ITrigger that is used to fire a IJobDetail based upon repeating calendar time intervals. </em><br />
<em>The trigger will fire every N (see RepeatInterval) units of calendar time (see RepeatIntervalUnit) as specified in the trigger's definition. This trigger can achieve schedules that are not possible with ISimpleTrigger (e.g because months are not a fixed number of seconds) or ICronTrigger (e.g. because "every 5 months" is not an even divisor of 12).</em><br />
<em>If you use an interval unit of IntervalUnit.Month then care should be taken when setting the startTime value that is on a day near the end of the month. For example, if you choose a start time that occurs on January 31st, and have a trigger with unit IntervalUnit.Month and interval 1, then the next fire time will be February 28th, and the next time after that will be March 28th - and essentially each subsequent firing will occur on the 28th of the month, even if a 31st day exists. If you want a trigger that always fires on the last day of the month - regardless of the number of days in the month, you should use ICronTrigger.</em></blockquote>
That’s it for today’s “New in Quartz.Net 2.0” post. Stay tuned for more, coming soon!Unknownnoreply@blogger.com8tag:blogger.com,1999:blog-4835835142296541440.post-6997631774865637862011-01-28T16:17:00.001-08:002015-03-16T08:41:17.102-07:00Installing Quartz.Net 2.0 as a Windows ServiceNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
UPDATE: I've written a new post that has been updated with the release of Beta 1. Take a look at this <a href="http://jvilalta.blogspot.com/2011/12/installing-quartnet-20-beta-1-as.html">newer post</a> instead.<br />
Quartz.Net 2.0 is currently under development. No official release (beta or otherwise) is available yet but if you really want to get started with it, you can download the source code from <a href="https://github.com/lahma/quartznet" target="_blank">Github</a> and build it yourself. In this post I am going to describe how to install the latest version of Quartz.Net 2.0 from source. <br />
<h4>
Getting the Source</h4>
If you are familiar with <a href="http://git-scm.com/" target="_blank">Git</a>, <a href="https://github.com/" target="_blank">Github</a> and how it works, then just download the repository locally using whatever method you prefer. There are a lot of posts and even a <a href="http://progit.org/book/" target="_blank">free book</a> on how to use Git, so I am not going to go over that stuff here. <br />
If you’re not familiar with how to use Git or Github, then go ahead and download a zipped file of the source from <a href="https://github.com/lahma/quartznet/zipball/master" target="_blank">here</a>.<br />
At this point I am going to assume that you have already downloaded the Quartz.Net source code and that it is in a folder somewhere on your drive. On my box I have downloaded the source to C:\git\quartznet, and the image below shows what that folder looks like. Your folder should look similar to the screenshot below.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-MtAIaxUSOP-pBEnF-63Fiju3BS2JaTsdg0qoxYiRiGZ95UFOKS9HN5ADSDruHWm1tIId9z4ufCPcjbthUuvjpxL9q8CFp1vz4X0tgqNoX-ziXuAJZRggP5clUGfDqgK1SLYJUp3CS9M/s1600-h/image%5B21%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheaDFW5ArhFfv9ggC7mf7tR3PXq3VsfYrC7r0y0s1IbfBbXYL9lVJ64gVGCnus34sLCPTSANFa0HVpGSmo350JLkbmz7dieRaFsPJNXVK5wp48tbAf8dqkYcX5c6CIXX2h0Htc01xK6H8//?imgmax=800" height="617" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="754" /></a><br />
<h4>
Building The Source Code</h4>
Since this post is about installing Quartz.Net 2.0 as a windows service, let’s build the server project. <br />
<h5>
Instructions for Visual Studio 2008 and .Net 3.5</h5>
Double click on the Quartz.Server.2008.sln file if you have Visual Studio 2008 installed. This will open the file in VS 2008. Build the solution by pressing F6. This will build the binaries targeting the 3.5 framework. The build output for this project can be found under the build\3.5\Debug\Quartz.Server folder, as shown below.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4kuwEtHvjvoMMGvIJSetohuEdsip2-j6nTB2CST9bux4ZffHEVlWt599ZODpKyKyqQGsbkjoklAoc20AZxvzVg0nYIEN7_rXCv4CagHwuFNY3P2ORemxr9nenDGRyIn8Cn97TTeGNxU4/s1600-h/image%5B14%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvbSsD4RN9qUf6KSoqmazwn64KW1hacJQDVN_OpKkFPLA4xEk7_Zx4LzhOz99ZVjwCVXb1smZSejKjLeLOMiYf2taEna-H3tFZ2ROpIXQJGfmf25W2L6raTDK9ggLye2fXa499M4gJKkI//?imgmax=800" height="595" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="754" /></a><br />
<h5>
Instructions for Visual Studio 2010 and .Net 4.0</h5>
If you have Visual Studio 2010 installed, double click on the Quartz.Server.2010.sln file to open it in VS 2010. Build the solution by pressing F6. This will build the binaries targeting the 4.0 framework. The build output for this project can be found under the build\4.0\Debug\Quartz.Server folder, as shown below.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi77gJHACG6WWa_qT75xOJpUD7F91gZNbjwqfBDXz6OPZ1Jj0XcJooTJ-BCWS4BrVTTOteHgaogxCcZ1B_6D83nxhMm_6jEAoRJ_lgHjHU0_MBgw9wptmkuyoZFuUWITyQEJgk8EHblk9s/s1600-h/image%5B24%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX5rgp2iFsCqy6K3pcQZI-5iNdvW5plrmt4XxS_LYpqkWS_lX1rcjowbSiKfuUYe0nKJxoJp33Nun86rC7NV9v4TAHEiARfjFDG_mezHXPeEK2U53Cqrtwhb7UWAFxW7LWKOnFePam868//?imgmax=800" height="595" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="754" /></a><br />
<h4>
Installing Quartz.Net 2.0 as a Windows Service</h4>
Now that you have built the source code, let’s install the service. Open a command prompt <strong>as administrator</strong> (if you are running a Vista or later OS) and cd to the directory that contains the Quartz.Server.exe file. This directory will be different based on whether you use VS 2008 or VS 2010, so double check that the file exists first in one of the paths that I mention above. At this point, all that is left is to install the service. Type the following into your command prompt: <br />
Quartz.Server.exe install<br />
If all goes well, then you should see the following in your command prompt window (replace 3.5 with 4.0 where appropriate):<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEix2Mv0R_89l-FntYyxFBFbNbP-vHE8GiizQIeOzyuooly_gE1UWRzRUSLB6P79-H_2cy5i-aQldT2mAPeMAgWJZlVJ3xtXbVMy6RlGRV_-lMvYsNw5IUebT4CxxwsZK3n3yCcJ5VeiYO8/s1600-h/image%5B28%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXvpw0lxOlTA0t32tmdh1wX5YTUYLBRQLi4rDNBM-eX_FFJKpEYvWnTMmC8QwCZSOJPKQGxVCYsyL96Gt-CjqUAaQM2ROIe6SwZbGyo2at1Qabnw3SfKPSFTudzWwMop-0h8fmdRsOfK8//?imgmax=800" height="438" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="754" /></a><br />
By default, the service is installed with a startup type of automatic and under the Local System account. To uninstall, type the following into your command prompt:<br />
Quartz.Server.exe uninstall<br />
Now, go fire that puppy up and start experimenting!<br />
As always, let me know in the comments if this stuff is useful and what topics you’re interested in reading about.Unknownnoreply@blogger.com19tag:blogger.com,1999:blog-4835835142296541440.post-73025663913279206592011-01-18T10:18:00.001-08:002014-07-29T08:20:05.909-07:00Quartz.Net Library is Available on NuGetNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
The <a href="http://nuget.org/Packages/Packages/Details/Quartz-1-0-3" target="_blank">Quartz.Net</a> library has been uploaded to <a href="http://nuget.org/" target="_blank">NuGet</a>. If you’re using Quartz.Net and NuGet, this should help you with setting up your environment and in keeping things current. The <a href="http://nuget.org/Packages/Packages/Details/Common-Logging-1-2-0" target="_blank">Common.Logging</a> and the <a href="http://nuget.org/Packages/Packages/Details/Common-Logging-Log4Net-1-2-0" target="_blank">Common.Logging.Log4net</a> and <a href="http://nuget.org/Packages/Packages/Details/log4net-1-2-10" target="_blank">Log4net</a> libraries are on NuGet as well. These are all required dependencies for running Quartz.Net with Log4net. Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4835835142296541440.post-68265919301822863852011-01-15T17:30:00.001-08:002014-07-29T08:20:11.642-07:00Quartz.Net Development is Moving to GithubNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
In case you didn’t know it yet, development of Quart.Net is moving from <a href="http://sourceforge.net/projects/quartznet/" target="_blank">Sourceforge</a> to <a href="https://github.com/lahma/quartznet" target="_blank">Github</a>. If you want to follow development of the latest version of Quartz.Net. be sure and check out the project on <a href="https://github.com/lahma/quartznet" target="_blank">Github</a>. This should make it easier for everybody to contribute any changes to the project.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4835835142296541440.post-30766389223522373382010-11-09T15:52:00.001-08:002015-03-16T08:35:21.092-07:00Quartz.Net GUI Tour - Part 2NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
This is the second part of the Quartz.Net GUI Tour. The <a href="http://jvilalta.blogspot.com/2010/11/quartznet-gui-tour.html">first part</a> of the tour covered connecting to schedulers and adding jobs. In this post, I’ll go over the remaining features.<br />
<h2>
Running Jobs</h2>
To run a job immediately, select the job from the left tree. The job details will be displayed on the right, and the run button will be enabled, as in the attached screenshot:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ1CUDIBXq0-5ISYBhyphenhyphenPNH6mEj7-eWUDqGZpTYpNOrIS4C7TXQk6j26rzp3o5ugAuPDKq4v7yVTPRJL4evxsWYMvBJb3NEX4gbIUlwDdrbQ8oNLY15HEz1NMX3v4LDMLvjJOj24rXy7J4/s1600-h/image%5B5%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd5OUZWvdfcDHre3ZpfGb27n3OarIt508HlimC9YmJ9AFEuwVpnOXjoKR06kLLCRxTxMT2uq_GVFyf4chSAPL6vNVkw_JSfBchXesbmtbAPgn4SZHASfFlfu4gEuAOBzrO_moNYfwaStU//?imgmax=800" height="185" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
Clicking on the button will cause the job to be scheduled to execute once, immediately.<br />
<h2>
Deleting Jobs</h2>
To delete a job, select it from the left tree. The delete button will then become enabled. Click the delete button on the right to delete the job and all of its associated triggers. <br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXRKfHHw95yNn7bp2c_iJWhyphenhyphenFYd7uBdjLszUCh8-1-eco4UGbuNZmUq6CUs7qau8b0wIfYuI6rs-Jyi4aE9FCQZElIMhKITPgruJ4PcxQrWsg4lcjNJdlNk1xQd0QCDVUIwLlJqbZDcvE/s1600-h/image%5B8%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNEHWv36B-DF7oQaHf5i0Vcbbsd5HT5aT8CPD3a5OlMrfaH5E2Q17JuxIMrp_WARN4px99W2tDxnEdkaLb9bVT5Xa18V3yX7V2qYe_U5jnnHDBrkJO6Fk4CjMkuAY6XCWPx8BhxrJ8OtQ//?imgmax=800" height="185" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
<h2>
Pausing and Resuming Triggers</h2>
Quartz.Net manager allows you to pause and resume triggers as well. To enable the pause / resume button, you must first select a trigger from the tree on the left. Once a trigger is selected, the pause button will be enabled. Click on the pause button to pause a trigger. If the trigger you selected is already paused, the button will say Resume instead of Pause. Click on the resume button to reactivate the selected trigger.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNn_Voa1aNSmIatECH-BSJXALz3JOtd5E-Nj7YXIRq37bdAEXNNr6BsgRuurebrMhAJVmvs1JnSwQ1G4WxCV85b4fjZO9V5jdYC0B2Z9C4iKx3vsQzY0FQqP7JMHfD_VUHpc35ZCqqZcg/s1600-h/image%5B11%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzn1XQmKO-YLnCRYAJD488toFe7Bc2KtThr1YggWjsGMSzGhyphenhyphen8_Iddbbqs8swPU7wT8Q59IR91nAuV1H1vgcH9jNDIjiIs9s5f29bOUL-csVRuANx6RmT97c1w9HlQK30rw9ye9NuQ6xw//?imgmax=800" height="185" style="background-image: none; border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
<h2>
Backup To File</h2>
The last feature we’ll discuss in the tour is the backup to file feature. This feature lets you backup all of your jobs and triggers to a text (xml) file. This file can be then be used by the xml plugin to load all the job information into, say, a new scheduler instance. To create a backup of your scheduler, right click on the entry for the scheduler in the tree. Select the backup option and enter a file name for your backup file.<br />
This concludes the quick tour of the Quartz.Net manager features. I hope you have found it useful.Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-4835835142296541440.post-8451046668171078832010-11-08T14:41:00.001-08:002014-07-29T08:24:29.791-07:00Quartz.Net GUI TourNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
In this post I will do a quick walkthrough of the Quartz.Net GUI that we open sourced last week.<br />
<h2>
Installation</h2>
We do not have an installer right now, so your options are:<br />
<ol>
<li>1. Download the source code and hit F5. </li>
<li>2. After having downloaded the source code and done a successful build, run the executable. </li>
<li>3. Download the <a href="https://github.com/adometry/QuartzNetManager/downloads">binaries</a>, extract them into a folder and run the executable. </li>
</ol>
<h2>
Connecting to a Scheduler</h2>
Click on Scheduler –> Connect. You should get the following connection dialog:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOEmMpUptuLWFJjO8IkPk5MyCXeguXNTPyHCEIVTvuz9yzZQCLj47XD3HS5qf17I6gD2eajf6ecf2fXEY3raCkQBL4vBMkpjZs9rhzBRFkqde454TPJGLliaIMrPqSpfTDnc7SMG9Uyyw/s1600-h/image%5B2%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKXbDQCFTMp99zDfBCAH5vt5mIijYrdDzWAyJoaLo3juypbBuOrae8DG6NRg_z9iOJYwXUaP5Zk_yDodUXAFjhpxcLM6W2cm-EzBVohX8nB-7FioMQthgU0iZdYn8WirrMO8QZpPfntxM//?imgmax=800" height="181" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
Type in your server name, and change any of the default connection information if necessary. Once connected, your screen should look something like this:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL2rdh04CwpOAfM-xo_NUy1xxT5YUDS3URljxuCe0GADZJ9j1exT0klAjDaYJMiZfw_n_T359WVk3Uhlkq1cuzpHRanaJ02dMY2fFRZbVjkLW2BRG_JOG8tTKVcdPH6lB1eHVAZafcqpw/s1600-h/image%5B5%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcZ6cVvqzPVCUV-w8MFTNBZ2GuLNtAVS5kowM1bbV_gZue_Z5HqttB-r1hRt0ispeP7_iQblzxXrmk8BgJp3tCBHaz1pPFs8P7C0bgkLrkfFcgj4OHfbHyvMiwmMFYU58ZnEDvgD4fbac//?imgmax=800" height="185" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
<h2>
Adding Custom Jobs to the Manager</h2>
Before we can add a custom job, we must first tell the application which dlls contain the jobs that we want to add. Adding dlls to the list of scanned dlls is done by editing the JobAssemblies.txt file. Just include the name of your dll in the file, by adding it to the bottom of the list.<br />
<h2>
Adding a Job to the Scheduler</h2>
To add or schedule a job on the scheduler that you are connected to, click on the Jobs –> Add menu. You should get a dialog box like this:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgajR1r2aM1un6q5bn6IYpm-nZVgSHTH4H-McRdHJ2Rk-JQ7BD828DGTB-xJM-J7xBd19VtKXHp5IGqn24hTjs5elpnoPoSzqmbQwWzxqfkf_T6O4VV_e3ScnrDyKjmhGksM47myNDOGD8/s1600-h/image%5B8%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh99s8utpPm-6FGPVvEtoTQDcYRCock1S0KZEG-3ZIi4hsLkoTRPqKsoyW3lOJ6rJyHekWdZP_1VA4bz49m9gybT2JzzQdjuUFSiWb49z05-3ghRNhCZipTRMVhvc-WBp1bsbgfa__i6IY//?imgmax=800" height="89" style="background-image: none; border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline; margin: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px;" title="image" width="244" /></a><br />
Now, select a job type from the dropdown and fill out all the boxes with the necessary information. You do not need to add job data unless your job requires it. If your job requires job data to be set, use the right hand side of the dialog to add as many key value pairs of data as needed.<br />
Once you have set up your data, click on add and your job will be scheduled. The dialog will close and the Scheduler objects pane will show the job that you scheduled.<br />
<h2>
What About the Run, Pause, Delete and Edit Buttons?</h2>
<a href="http://jvilalta.blogspot.com/2010/11/quartznet-gui-tour-part-2.html">Part 2</a> of the tour is now available, with a quick description on how to use these buttons.Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-4835835142296541440.post-12232032301024863412010-11-01T14:12:00.001-07:002015-03-16T08:39:18.010-07:00Open Source Graphical User Interface (GUI) for Quartz.NetNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
Click Forensics, the company I work for, has graciously allowed me to open source the code to a GUI for Quartz.net. The latest code is currently available on <a href="https://github.com/adometry/QuartzNetManager">github</a>. We have been using Quartz.net for over a year and we use this tool to manage our schedulers. The application is written in C#, using windows forms and is targeting .Net 4.0<br />
The code should be considered alpha quality at this point, as some features are missing and some don’t work properly. The documentation is pretty much non-existent at this point, but as I have some spare time I will post updates here and on <a href="https://github.com/adometry/QuartzNetManager">github</a>. Please give it a try send us any feedback you might have.<br />
I would suggest you download the source and build it yourself, but for your convenience, you can download the binaries from <a href="https://github.com/adometry/QuartzNetManager/downloads">https://github.com/adometry/QuartzNetManager/downloads</a>.Unknownnoreply@blogger.com14tag:blogger.com,1999:blog-4835835142296541440.post-78160448919628250412010-11-01T13:48:00.001-07:002014-07-29T08:24:07.560-07:00Creating a Quartz.Net JobListenerNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
This post will describe how to create a Quartz.Net job listener. As an example, we will write a job history listener that will log job start and end times to a database.<br />
<h3>
Creating the Job Listener</h3>
To create a job listener, we need to implement the IJobListener interface. Here is the interface: <br />
<pre><pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">interface</span> IJobListener</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">{</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">string</span> Name { <span style="color: blue;">get</span>; }</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">void</span> JobExecutionVetoed(JobExecutionContext context);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">void</span> JobToBeExecuted(JobExecutionContext context);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">void</span> JobWasExecuted(JobExecutionContext context, JobExecutionException jobException);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">}</pre>
</pre>
<br />
<br />
For the task at hand, we will not implement JobExecutionVetoed, since we just want to be notified when a job starts and when it ends. Since we want to log start and end times for our jobs, we will focus on implementing the JobToBeExecuted and the JobWasExecuted methods.<br />
<br />
<br />
<h4>
Implementing the JobToBeExecuted Method</h4>
<br />
<br />
In this method, we will write a record to the database, indicating that the job has started processing. Your implementation of the method could look something like this:<br />
<br />
<br />
<pre><pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">Guid historyId = Guid.NewGuid();</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">context.JobDetail.JobDataMap.Add("<span style="color: darkred;">historyID</span>", historyId);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">string</span> sql = @"<span style="color: darkred;">INSERT INTO [dbo].[QRTZ_JOB_HISTORY]([JobHistoryID],[JobName],[StartDate],[Server],[JobType]) VALUES(@JobHistoryID,@JobName,@StartDate,@Server,@JobType)</span>";</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">using</span> (SqlConnection connection = <span style="color: blue;">new</span> SqlConnection(connectionStringGoesHere)</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">{</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> connection.Open();</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">using</span> (SqlCommand command = <span style="color: blue;">new</span> SqlCommand(sql, connection))</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> {</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> command.Parameters.AddWithValue("<span style="color: darkred;">@JobHistoryID</span>", historyId);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> command.Parameters.AddWithValue("<span style="color: darkred;">@JobName</span>", context.JobDetail.Name);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> command.Parameters.AddWithValue("<span style="color: darkred;">@StartDate</span>", DateTime.Now);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> command.Parameters.AddWithValue("<span style="color: darkred;">@Server</span>", Environment.MachineName);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> command.Parameters.AddWithValue("<span style="color: darkred;">@JobType</span>", context.JobDetail.JobType.ToString());</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> command.ExecuteNonQuery();</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> }</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">}</pre>
</pre>
<br />
<br />
Basically we are inserting a row into a table with all the information we need in order to be able to determine the job’s run time. One thing you should note is that we are creating a GUID and sticking it into the context. This is so that we can record when the job finishes running. <br />
<br />
<br />
<h4>
Implementing the JobWasExecuted Method</h4>
<br />
<br />
This method gets called whenever the job finishes running. The only thing left to do now is to update the row we inserted when the job began running and set the end time. Here is what that method might look like:<br />
<br />
<br />
<pre><pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">string</span> sql = "<span style="color: darkred;">UPDATE [dbo].[QRTZ_JOB_HISTORY] SET [EndDate]=@EndDate WHERE [JobHistoryID]=@JobHistoryID</span>";</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">using</span> (SqlConnection connection = <span style="color: blue;">new</span> SqlConnection(connectionStringGoesHere))</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">{</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> connection.Open();</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">using</span> (SqlCommand command = <span style="color: blue;">new</span> SqlCommand(sql, connection))</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> {</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> command.Parameters.AddWithValue("<span style="color: darkred;">@JobHistoryID</span>", (Guid)jobDetail.JobDataMap.Get("<span style="color: darkred;">historyID</span>"));</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> command.Parameters.AddWithValue("<span style="color: darkred;">@EndDate</span>", DateTime.Now);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> command.ExecuteNonQuery();</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> }</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">}</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
</pre>
<br />
<br />
As you can see here, we are reaching into the context and extracting the GUID that we put there when the job started running. This will allow us to update the correct row and thus be able to calculate how long it took the job to finish running.<br />
<br />
<br />
<h3>
Wrapping Up</h3>
<br />
<br />
Now that you have written a job listener. You have a couple of choices:<br />
<br />
<br />
<ol><br />
<li>You can add the listener directly to your job, in which case only jobs that have the listener attached will log their execution in our database.</li>
<br /><br />
<li>Add the listener as a global listener. Global listeners get called whenever any job runs, and our history listener seems like a good candidate for becoming a global listener. My <a href="http://jvilalta.blogspot.com/2010/09/creating-quartznet-plug-in.html">previous post</a> describes how to schedule a global listener.</li>
</ol>
<br />
<br />
I hope this post was useful. Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-4835835142296541440.post-36138888242060010492010-09-08T13:12:00.001-07:002014-07-29T08:23:53.401-07:00Creating A Quartz.Net Plug-inNOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
In this post I’ll walk you through creating and configuring a Quartz.Net plug-in. It’s not very complicated, but this will depend on what you are trying to do with your plug-in. For the example we will create a plug-in that attaches a global job listener to the quartz scheduler. This will come in handy later on, since I will be posting another article describing how to create a job listener for Quartz.Net. The Quartz.net source code also includes an example of how to do this in the LoggingJobHistoryPlugin.<br />
Why do we need to create a plug-in to register a global job listener? Global job listeners are not stored in the job store, so they need to be added to the scheduler every time it starts. That’s why we’re going with the global job listener / plug-in combo.<br />
<h2>
The Plug-in Interface</h2>
To create the plug-in we need to implement the <a href="http://quartznet.sourceforge.net/apidoc/topic2871.html">ISchedulerPlugin</a> interface. Here is the ISchedulerPlugin interface: <br />
<pre><pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">interface</span> ISchedulerPlugin</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">{</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">void</span> Initialize(<span style="color: blue;">string</span> pluginName, IScheduler sched);</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">void</span> Start();</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> <span style="color: blue;">void</span> Shutdown();</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">}</pre>
</pre>
<br />
<br />
This interface has 3 methods that we could implement. Let’s look at these methods in a little more detail.<br />
<br />
<br />
<h3>
The Initialize method</h3>
<br />
<br />
The comments in the code say that this method is “Called during creation of the IScheduler in order to give the ISchedulerPlugin a chance to initialize. At this point, the Scheduler's IJobStore is not yet (ready?). If you need direct access (to) your plug-in, you can have it explicitly put a reference to itself in the IScheduler's SchedulerContext Initialize(string, IScheduler) method”. We’re just adding a global listener to the scheduler, so we’ll include the code to do this in the Initialize method. Alternatively, we could move this code to the Start method and the result would be the same.<br />
<br />
<br />
<h3>
The Start Method</h3>
<br />
<br />
The comments in the code say that this method is called when the associated IScheduler is started, in order to let the plug-in know it can now make calls into the scheduler if it needs to. We’re not going to be making any calls into the scheduler, so there is no need to implement this method.<br />
<br />
<br />
<h3>
The Shutdown Method</h3>
<br />
<br />
For this method the code comments say that it is called in order to inform the ISchedulerPlugin that it should free up all of it's resources because the scheduler is shutting down. We don’t have any resources to free up, so we aren’t going to implement this method either.<br />
<br />
<br />
<h2>
Creating the Plug-In</h2>
<br />
<br />
Now, let’s take a look at the code for the plug-in. We’re doing something pretty simple here, so the implementation is very short.<br />
<br />
<br />
<pre><pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">public</span> <span style="color: blue;">void</span> Initialize(<span style="color: blue;">string</span> pluginName, IScheduler sched)</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">{</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"> sched.AddGlobalJobListener(<span style="color: blue;">new</span> JobListener());</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;">}</pre>
</pre>
<br />
<br />
Yes, that’s all there is to creating a very simple plug-in. We’re not entirely done though, since now we need to tell the scheduler to load the load the plug-in upon startup.<br />
<br />
<br />
<h2>
Configuring the Scheduler to Load the Plug-In</h2>
<br />
<br />
The last step is to let the scheduler know that it needs to load your plug-in upon start. This is done via the configuration file, by setting a property as follows:<br />
<br />
<br />
<blockquote>
<br />
<pre>quartz.plugin.{name}.type = {type name}, {assembly name}</pre>
<br /></blockquote>
<br />
<br />
Let’s look at all the components of this property in detail. First there is quartz.plugin, which tells the scheduler that this is a plug-in that needs to be loaded. The {name} portion is the name that you want to give to your plug-in, and is the name that is passed in to the <strong>Initialize</strong> method above. The value of the property indicates the <strong>Type</strong> of the plug-in, so that the scheduler can load it into memory. {type name} is the full name of your plug-in, which in our case would be something.something.JobListener. {assembly name} is the name of your assembly file, minus the .dll extension.<br />
<br />
<br />
Once you add your configuration information, you are done. Make sure that your dll is in the same folder as the Quartz.Net binaries and that should be all you need to do.<br />
<br />
<br />
In my next post we’ll tackle the implementation of the JobListener that we used as an example in this post.Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4835835142296541440.post-37448198326927463252010-06-01T15:59:00.001-07:002014-07-29T08:23:46.663-07:00Running Quartz.Net 1.0.2 on .Net 4.0NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
We recently upgraded one of our application to .Net 4.0. As part of this upgrade, we also upgraded out Quartz.net jobs to run on the 4.0 version of the .Net framework. The process was fairly straightforward, but not without surprises, so I figured I would post it here in case it’s useful. I hope that there will be an official 4.0 release made soon, so I have only included the steps of the process I followed in this post. If there’s enough interest I can upload the updates solution file. If you want to try it out for yourself, I’ve broken the process down into simple steps. Feel free to skip over the steps that are familiar to you.<br />
<h4>
Step 1 – Downloading the Source Code</h4>
First, I downloaded the source code from sourceforge using subversion. The subversion url for the project is: <a href="https://quartznet.svn.sourceforge.net/svnroot/quartznet">https://quartznet.svn.sourceforge.net/svnroot/quartznet</a>. If you’re using TortoiseSVN, then you just have to right click on the folder you want to download the source to, and then select SVN Checkout. Paste the URL above into the box and select OK. Here’s a screenshot of what I’m talking about:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvYOVsHqbqXrtqMuRI4swYHmmgdP45DY0wlV7wJwMkmRmDSvTiicwgVlVjawDtvVZ-VrlsdD_wRDggB1xw3hOONbqLxaS-tp7_qKMjAHeYQB4KLZ74k5alsqg5C2gM2km43BKYu8vTXe8/s1600-h/image3.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwT8WC7coANXJjP-Nmijovlr47yUe5LUh3t3uGm28HVulQTyQxp-GV97fa-1uITj3Aa9RK4kIm1SzssX4RJ0wvmDSwUTeCCiysLIHizIJgvC-IFQa8KgalPOU93y9egjSqo09Msj8adMc//?imgmax=800" height="190" style="border-bottom-width: 0px; border-left-width: 0px; border-right-width: 0px; border-top-width: 0px; display: inline;" title="image" width="244" /></a> <br />
<h4>
Step 2 – Convert the Solution File</h4>
Next locate the main solution file for the maintenance release (this is the branch I used, since it corresponds to the latest released version). The file is called Quartz.2008.sln and is located under branches –> Quartz-1.0-Maintenance. Open this file in VS2010 (right click, select open with… VS2010) and run through the upgrade wizard. Once that’s done, there are some small changes to be made.<br />
<h4>
Step 3. – Target .Net 4.0</h4>
This is the tedious part… you’ll have to right click on each project, select properties and then under the Applications tab, select the new target framework:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7o_c4YgHqREy0gT6P0JU_Qv6n-Qlqmoq7o_7TU10Qcho-rCWLCA4jgrn93VLMVxd-lFEyexKs12f8cF1c2581plpsTnYs1008VaXJTLXH_g34VMVUYTSJ6svW8djIuxUdsn-gibNwNqY/s1600-h/image%5B9%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnrYVEagYNINfgbdrZNyrY-yxzUp1SzgcdSphPWf8Tk6Wd_slHNBGYvMKgGG6xsj-p7A04QvAfniEhwuNX8Ou53GEtzE60eOn6HSvCaexQDCPv2Ppi0Ed_n4mco1DAfM5uQDoJwB5ShwI//?imgmax=800" height="77" style="border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline;" title="image" width="244" /></a> <br />
<h4>
Step 4 – Fix the Build</h4>
If you build the solution now, you’ll get some warnings are errors. You have 2 options:<br />
1. Fix the errors, which are basically documentation errors. You’ll have to look at each of the individual errors to fix them, so I won’t describe the process in detail. Just keep pressing F8 until you’ve fixed them all.<br />
2. Turn off warnings as errors. This is the path of least resistance.<br />
At this point, whether you selected option 1 or 2, you should have a working build. By default, the results of the build are put under the build\2.0 folder: <br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL_fIMhHABDaHV6V9p6WyMt2xguFrNahcYF2Et-kOpvVjYe8MwkU9Mfnxe9B6xamYNkvV3VIjc7u99A2GMWpjKM-4WJ1Y3hBUA6Lc4Q98cg3duqP1jfuFNsHs7WSSpHlz9tJvbZRGzbwg/s1600-h/image%5B3%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4-y7Qf-aaQbETdo8hhNhu5qgWQzd5nfB8hLPVwagx3V3QBPRs3Gt-94uiLZq5jGVAXJDi_XaWtjAtz3x_ZPPcIagNw0NFIwhLTAMn5nnj8m6SYcn-npflOTI3jP-w9gGjE7dJLu5PXMU//?imgmax=800" height="231" style="border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline;" title="image" width="244" /></a> <br />
<h4>
Step 5 – Fix the Version Number and Service Name</h4>
Note: this part is optional…<br />
Since I already have a working scheduler and didn’t want to risk screwing it up, I changed the name of the scheduler in the installer file so that I could install it side by side with my existing scheduler to be able to test it. I also changed the version numbers in case for some reason the dlls got mixed up. To change the service name, open Configuration.cs file. It’s under the Quartz.Server.Core project. Change these lines as follows (or use your imagination):<br />
<pre><pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">const</span> <span style="color: blue;">string</span> DefaultServiceName = "<span style="color: darkred;">QuartzServerForNet4</span>";</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">const</span> <span style="color: blue;">string</span> DefaultServiceDisplayName = "<span style="color: darkred;">Quartz Server For Net4</span>";</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"><span style="color: blue;">private</span> <span style="color: blue;">const</span> <span style="color: blue;">string</span> DefaultServiceDescription = "<span style="color: darkred;">Quartz Job Scheduling Server For Net4</span>";</pre>
<pre style="background-color: white; font-family: consolas,'Courier New',courier,monospace; font-size: 12px; margin: 0em; width: 100%;"></pre>
</pre>
<br />
<br />
This will let you install the updated scheduler side by side with the old scheduler. <br />
<br />
<br />
To update the version number you will have to right click on each project, select properties and then under the application tab, click on the Assembly Information button to update it:<br />
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg72hgiwFKFp09FmX6Gz76VQ8Hd0Z1YVP2JqWgrWSefELN-vMNI8uHnuH4Cma5HSdGXcxNoX6uCCE2WSKIJO80TBbZi_BX8JSyAdRJWKGkZYu7CW2rLKJLKKhiqi5N0FE613MG25zBXfoY/s1600-h/image%5B12%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiewnfDvHfqS-JrFFvMwAE1XiEG7q7EdrC8pxRf2JSelqrWGotjD44L-0Fp5kuOaNFJOzFhvf2lERmReyxYmcmoHEvQppsJkjnkwkvVUoFyU2pgwQ60sdaXr08KlKqq6rgDL8qjb6jmE6A//?imgmax=800" height="83" style="border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline;" title="image" width="244" /></a> <br />
<br />
<br />
Then just, update it to the version number of your preference. Something like this:<br />
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcz9DZWycH_PTWE9Ir20GiynSXNyp8tNEp7WTaaRHNwaiI7k3coRLKm3L-pu85oDe2PX3LDUUaxk1A5D54KDRxMZEHMYzln_32yomH9cj8V9dtbuBN-XWI79RF-qSbu87NMCxgrcyU6Ak/s1600-h/image%5B15%5D.png"><img alt="image" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEja3DnqIEvkEnQrd3mhwPhJ-WEO3eLR8itH_yIG-cYRxqvE_pqJG9YG4QSyB2SJ22V9nD9WYcj7zVR0zdXmEkZkzjx-O6R3WjipbwyOtHDInSYw4K9mcyeLBg4jJy2VhdI087j-AQczdy4//?imgmax=800" height="243" style="border-bottom: 0px; border-left: 0px; border-right: 0px; border-top: 0px; display: inline;" title="image" width="244" /></a> <br />
<br />
<br />
<h4>
Step 6 – Final Steps</h4>
<br />
<br />
You should be ready to use Quartz.Net with the 4.0 framework now. If you’re going to install Quartz.net as a service, then take a look at <a href="http://jvilalta.blogspot.com/2009/03/getting-started-with-quartznet-part-1.html">this post</a>. The steps you need to follow will be identical, just remember to use the new files you just built. If you are running Quartz.net embedded in your application, then update your references so they point to the new dlls.Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-4835835142296541440.post-43441367510014943892010-04-28T15:33:00.001-07:002014-07-29T08:21:47.061-07:00Configuring Quartz.Net with an ADO.Net Job Store (AdoJobStore) – Part 2NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
In <a href="http://jvilalta.blogspot.com/2010/04/configuring-quartznet-with-adonet-job.html">Part 1</a> we set up our database so that we could use it as a job store for Quartz.Net. Now, we need to set up our scheduler job store properties to use said database. Here are the most common properties and values that need to be set in order to get the scheduler to use the database as its job store:<br />
<table border="1" cellpadding="2" cellspacing="0" style="width: 728px;"><tbody>
<tr> <td valign="top" width="291"><strong>Property</strong></td> <td valign="top" width="435"><strong>Value</strong></td> </tr>
<tr> <td valign="top" width="292">quartz.jobStore.type</td> <td valign="top" width="435">Quartz.Impl.AdoJobStore.JobStoreTX, Quartz</td> </tr>
<tr> <td valign="top" width="292">quartz.jobStore.dataSource</td> <td valign="top" width="435">default</td> </tr>
<tr> <td valign="top" width="292">quartz.jobStore.tablePrefix </td> <td valign="top" width="435">QRTZ_</td> </tr>
<tr> <td valign="top" width="292">quartz.jobStore.clustered</td> <td valign="top" width="435">true</td> </tr>
<tr> <td valign="top" width="292">quartz.jobStore.lockHandler.type</td> <td valign="top" width="435">Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz</td> </tr>
<tr> <td valign="top" width="292">quartz.jobStore.driverDelegateType</td> <td valign="top" width="435">Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz</td> </tr>
<tr> <td valign="top" width="292">quartz.dataSource.default.connectionString</td> <td valign="top" width="435">Server=localhost;Database=youeverseethefly;Uid=brundle;Pwd=fly;</td> </tr>
<tr> <td valign="top" width="292">quartz.dataSource.default.provider</td> <td valign="top" width="435">SqlServer-20</td> </tr>
<tr> <td valign="top" width="292">quartz.jobStore.useProperties</td> <td valign="top" width="435">true</td> </tr>
</tbody></table>
You can set these properties in your config file, but the specific file will depend on whether you are using the default configuration file or something else. If you are using the default (distribution) settings, these properties will go in your quartz.config file.<br />
That’s all there is to setting up an AdoJobStore. Start up your service and take a look at the event log to see if the scheduler started up correctly.Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-4835835142296541440.post-33408740229875397312010-04-28T14:27:00.001-07:002014-07-29T08:21:33.961-07:00Configuring Quartz.Net with an ADO.Net Job Store (AdoJobStore) – Part 1NOTE: I'm now blogging at <a href="http://jayvilalta.com/blog" target="_blank">http://jayvilalta.com/blog</a> and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.<br />
<br />
Quartz.Net stores all of its job related configuration in an aptly named JobStore. There are two different kinds of job stores available out of the box: RAMJobStore and AdoJobStore. By default, Quartz.Net uses a RAMJobstore. The RAMJobStore is extremely simple to configure, but it is a volatile store, so all job configuration is lost whenever the scheduler is restarted.<br />
If you need your job configuration to be persisted between scheduler restarts and/or you are going to be running more than one instance of the scheduler in a cluster, you will need to use the AdoJobStore. This job store uses ADO.Net to persist all the job configuration information in a database. The following table shows the most common database providers that are supported, as well the name of the Quartz.Net database provider to use. The full list of providers can be found <a href="http://quartznet.sourceforge.net/tutorial/lesson_9.html" target="_blank">in lesson 9 of the Quartz.Net tutorial.</a><br />
<table border="0" cellpadding="2" cellspacing="0" style="width: 494px;"><tbody>
<tr> <td valign="top" width="314"><strong>Database Provider</strong></td> <td valign="top" width="178"><strong>Quartz.Net Provider Name</strong></td> </tr>
<tr> <td valign="top" width="314">SQL Server driver for .NET Framework 2.0</td> <td valign="top" width="178">SqlServer-20</td> </tr>
<tr> <td valign="top" width="314">Oracle Driver (by Microsoft)</td> <td valign="top" width="178">OracleClient-20</td> </tr>
<tr> <td valign="top" width="314">MySQL Connector/:NET v. 5.1 (.NET 2.0)</td> <td valign="top" width="178">MySql-51</td> </tr>
<tr> <td valign="top" width="314">SQLite ADO.NET 2.0 Provider v. 1.0.56 (.NET 2.0)</td> <td valign="top" width="178">SQLite-10</td> </tr>
</tbody></table>
This post will focus on configuring the job store for SQL Server. If you’d like to see similar posts for the other databases, please let me know in the comments.<br />
First, let’s take a look at the steps you will need to follow to start using an ADO.Net job store:<br />
<ol>
<li>Set up the database by creating the tables that Quartz.Net will use. </li>
<li>Configure the scheduler to use the database server that you just set up. </li>
</ol>
It’s not that complicated, is it?<br />
<h2>
Step 1: Setting up the database</h2>
First, you will need to locate the setup script for your database server. In our case, we will use the SQL Server setup script. All setup scripts are located under the database/tables folder of the Quartz.Net distribution. The script we are looking for is called tables_sqlServer.sql. Open the script in a text editor and update the USE [enter_db_name_here] statement to point to whatever database you want to use. Once you’ve changed the database name in the script, you can go ahead and execute it. This script will create several tables in the database you set in the script. All of the Quartz.Net tables will be prefixed by QRTZ_ . Once you’ve successfully created all the tables, it’s time to configure the scheduler.<br />
In Part 2 we will cover configuration of the scheduler.Unknownnoreply@blogger.com4