BrandGhost

Quartz NET Best Practices - Merged Job Data and Serialization

Quartz NET is a POWERFUL job scheduler... But you know what they say... With great power, comes great complexity! Something like that, right? This video explores two best practices from the Quartz documentation: - Using the merged job data collection - Handling serialization of complex objects What are your tips for using Quartz effectively?
View Transcript
using job schedulers like courts give us a lot of power when it comes to persisting data to a database so we can have those jobs persisted and read them back that also means they come with a lot of complexity hi my name is Nick centino and I'm a principal software engineering manager at Microsoft in this video I'm going to walk through a couple of best practices for quartz.net as presented by quartz.net themselves so this information is available on their website and I figured it would be good to walk through a couple of these so that if you're trying to use quartz and you're getting used to it you can see from early on how you can try to establish some best practices if that sounds interesting remember to subscribe to the channel and check out that pin comment for my courses on dome train with that said let's jump over to visual studio and check out some chs.net all right in a previous video I was talking about being able to pass job data into jobs and I want to walk through this a little bit more because there are some best practices to consider so if you look on my screen you can see I have some commented out code here for using job data I have uh set job data here as well so that's on the job detail this one's for the trigger if we scroll down a little bit more we can see that on theuer itself we do have a similar type of thing where on the context we can also pass in data so there is a recommended way that uh quartz.net doeses suggest to get that data back out and I wanted to talk about these three ways that we looked at before and then talk about the recommended way the recommended way is to use this merged job data collection and when you do this it should be able to pull out sort of the result if you were to set different values for the same keys that it gets you the right one but I wanted to talk about what that actually looks like in practice so if we scroll back up again just a reminder the scheduler sets some message and then on these other two spots we have a message as well but I have these other ones commented and the reason I'm doing that is because I want us to be able to see what comes out when we go to ask for this merged job data and we only have the scheduler set and then we'll layer on the other ones we have our breakpoint being hit and we can start to see the data coming back out so obviously if we look for the job detail one it's null because it's not set trigger was not set and the scheduler was set so we can see message from scheduler so that's as expected but when we go to ask for the message merge so the merge job data it's null just to heads up when you're passing data into your jobs if you're leveraging the scheduler to provide that data merged job data does not get you values from the scheduler it's only going to be pulling it from the job detail and the job trigger if we stop this now let's go reintroduce the one for the job detail so we'll add this one in and hopefully what we see is when we run this that we go to ask the merge job data and we will get the result from the job detail okay so our breakpoint has been hit we can see the job detail one we do have that value provided as expected when we ask for the merged one we do see the one from the job detail so this is sort of the Bas base case if you're asking for merged job data it will give you what is provided on the job detail so now we stop this we'll layer on the very last one here the idea here is that the trigger should be able to override the job detail so we should see message from trigger when we ask for the merged one and that's because they have the same key right they both say message on them if they were different Keys we would see both of these things show up okay so our break Point's been hit we see message from trigger is populated so message merged is message from trigger and the job detail one is also still populated if you can see on the little tool tip popping up there so in fact both are populated but the merge one will give you the overlay of the trigger value instead of from the job detail at the same time just a reminder the message from Schuler has been populated this whole time but it never shows up in the job data map before we move on this is just a quick reminder that I do have a course on C refact in available on dome train refactoring is one of the most critical skills that you can learn as a software engineer and this helps you continue to build upon applications that already exist making sure that they can scale and have extensibility I walk you through a bunch of various techniques and give you some examples that we walk through together to see how we can apply these techniques to refactor the code check out the pin comment and the links in the description to get this course now back to the video I'm going to go give these two different uh Keys here and if we go run this and look at the merged job data we should be a able to see that we do get both in the merge job data because they have different Keys they're not going to override each other so if I just hover over the merge job data map and we go through you can see there's two keys in here message one and message two so it is going to have both the job detail and the trigger of course the way that I I set this up I didn't go change the keys that we're accessing here so not going to be as you'd expect but I just wanted to show you the merge job data map does have both because they're not overriding each other okay one of the last tips that I want to talk about in this video is serialization and that's because the examples that we're looking at so far are very simple with strings now when we look at the serializer up at the top here when I was configuring the persistence store I did tell it to go use the system text Json serializer we should be doing pretty good because this thing works really well for serialization but one of the tips that the quartz.net team is suggesting in their documentation is that you want to be careful about what you're serializing and it makes a lot of sense if you're thinking about systems that need to uh live on for a long time and evolve over time and that's because if you have jobs that are in your data store if you are changing what the actual class looks like in between runs you're going to have a very difficult time being able to maintain like being able to deserialize that once again from the data store it's kind of like you need to maintain uh multiple different classes to be able to deserialize different versions of things so it can get pretty complicated I wanted to walk through something that I thought was kind of interesting and that interesting thing is going to be serializing a more complex object so if we scroll down in the job detail now I am setting this complex key to being this data uh this overall data object and you'll see that it has child objects inside of it so it's not really that complicated but it's just that it has a a hierarchy to it right so there is a string there's an integer it has these uh child objects so this gives us a hierarchy so that's kind of interesting it's not just a string anymore technically though if we were to use system text Json to serialize and deserialize it should handled it very cleanly for us like that's a it's a very simple object everything on it is serializable should not be an issue their point of course was that you want to be able to maintain these things so you could still have problems maintaining this if all of a sudden I required another property on here so that's not really their point but I just wanted to show you something a little bit more complicated than a string so if we go to read this complex value back let's see what happens when we have it set up like this right so we're just pulling out the key uh and that's because it's on the job detail we should be able to pull it out of the merge job data map and you can see that I am setting it on the job detail right here let's see what happens and that doesn't look very good does it that's a whole lot of exceptions I'm actually amazed that it's throwing exceptions that fast so let's go ahead and pause it and if we have a little scroll through we can see that it's complaining unexpected runtime exception in put string was not in correct format parse near offset 1 2 3 format item ends prematurely so if we have a little look through what's happening is that uh if I find part of the stack as I ran this prior it's actually having a difficult time because of this right here cannot get the value of a token type number as a string for some reason even though it's system teex Json serializer it's unable to work with numbers so it's able to handle the other parts of this okay just not the numbers let's see if we can go change this right so if we weren't using uh integers as the type here and we instead just use strings could we go ahead and maybe make this look a little bit more gross and put quotes around our numbers something else on our application is going to later have to go convert that let's see if this works now because the thing it was complaining about was numbers and no still throwing tons and tons of exceptions so let's go ahead and pause that and if we jump back over we can see it's looking and it's having some issue with the array part so it's really not working with anything but strings so kind of interesting I think I probably have some type of configuration thing wrong on the uh the Json serializer I'm not really sure but I wanted to show you basically a very quick workaround for this type of thing and in fact I'm going to go ahead and put these things back to being integers so let me undo some of this code and go back down to the bottom we'll make these integers so back to where we were but an easy solution is just to handle the serialization yourself if we said we're going to serialize this as a string what's happening is we're not telling quartz to go do the serialization for us we're saying hey look here's a string quartz it happens to be more complex because we've serialized something but that means that we also have to deserialize it down here so if I say deserialize and this is the overall data object and then I need to cast this part as a string inside if we go pull this back now quartz only sees this as a string so let's go ahead and run this and this time our break point is hit which is interesting right so it's not throwing tons of exceptions we can see that we do have this complex object pulled back it has all of the child objects on it so the moral of the story here is number one probably that I have a configuration setting wrong and I'm not totally sure so it might not be obvious you might be running into something like this but uh I think sort of a meta point so the second thing I want to get across here is instead of delegating the work to quartz.net to handle complex serialization instead of doing that it might be kind of going along with their guidelines like having complex things being serialized in the first place is kind of crappy kind of challenging because if you're going to evolve these things over time you might be asking for some versioning problems but at least if you own it if you own how to serialize and deserialize you're not going to feel like your hands are tied because something in quartz is doing it so that's kind of the meta point I wanted to get across with this second part here was that if you do have more complex things if you control the serialization and der serialization at least you can make decisions about how you want to go do that with versioning these were just two quick tips for Best Practices from courts.net the first one was about using the merged job data that is what they recommend men you use so that you don't have to go ask for it off the job detail or the trigger separately you want the merge job data and the second part was really about serialization so they recommend sticking to Strings and I think that's what I was trying to demonstrate here especially if you own the deserialization and serialization on your own so if you thought this was helpful you can check out this video next for some more quartz.net tips thanks and I'll see you next time for

Frequently Asked Questions

What is the recommended way to handle job data in Quartz.NET?

The recommended way to handle job data in Quartz.NET is to use the merged job data collection. This allows you to retrieve values from both the job detail and the job trigger, ensuring that if there are overlapping keys, the trigger values will override the job detail values.

Why is serialization important when working with Quartz.NET?

Serialization is important because if you change the structure of the classes that represent your jobs over time, it can lead to issues when trying to deserialize those jobs from the data store. It's crucial to manage serialization carefully to avoid versioning problems and ensure that your jobs can be maintained effectively.

What should I do if I need to serialize complex objects in Quartz.NET?

If you need to serialize complex objects, it's best to handle the serialization and deserialization yourself rather than relying on Quartz.NET's built-in mechanisms. This way, you have full control over how the data is processed, which can help you manage versioning and avoid potential issues with the serialization of different data types.

These FAQs were generated by AI from the video transcript.
An error has occurred. This application may no longer respond until reloaded. Reload