Servoy 2020.09 Lauch Part 1
Servoy 2020.09 Lauch Part 1
Today we’ll be covering part one of the 2020-09 quarterly release. And typically when we do the release webinars, I spend the first webinar, the first part of the first webinar just going over kind of the release notes, everything that’s updated and changed, everything you have to know. I like these webinars to be always demoing and showing in a bit more fun and a bit more short. So this one I decided we have some interesting feature work that’s in the core part of the platform. And I wanted to just jump right into giving some demos and showing what’s new, because I think that’s why people join these webinars later in the series later this week. We’ll catch up to some of the finer details. So today on the agenda, I want to show the enhanced validation APIs that we’re added in this release, which allows developers a really greater control and makes it easier for developing better UX and better architecture around the subject of validation. So I’ll just kind of walk through some demos and highlight what’s new. And then later this week we’ll go through some of the package updates. So as you know, Servoy comes with many packages or extensions, which you can add to projects. And so we’ll go over some of the updates there. There were some nice updates to the pop-up filter component, which is one of the more popular components. And then, toward the end of the week, we’ll get to those odds and ends about the release. So some of the specific things in the release notes. So let’s start with a demo as we always do, and then we’ll go over kind of the API and overview. And again, if you have any questions, just put them in the tab window as we go along, and we’ll make time for that at the end. So I’m going to switch over to, I think I have a ID here. I have a very simple application that I made this morning, and we’ll go over the validation, the new validation setup. And then I’ll show a nicer application, which gives you a bit more of a real-world feel. But since this is kind of a new API, I wanted to show a very stripped-down example to walk you through kind of the order everything goes in. This is the order’s table from the sample data that ships with any copy of Servoy for many years now. So what I’m going to do is walk through each part of the sort of events. The first thing that we added is a centralized way to do validation. So we added a new event, which binds at the entity level, so at a database table or data source level, and is fired whenever validation is needed. So I’m going to go ahead and show you what that’s like in the IDE. So this is my form here. I can show you that it’s based on the data source, the orders table here. And we’ve added under here, under the entity event, a new event that you’ll see here, you won’t see this in prior versions called on validate. And this gets fired at various times, and I’ll explain when that happens. Take a look at the code here. When this event gets fired, it passes in, obviously, the record, which is being validated, and a new new class, a new object called record markers. And record markers is kind of like a stateful object, sort of like the validation state of the record. And it has its own API. It’s its own class. It’s now JS record markers. You would see it over here if you were exploring the API and the solution explorer. You would see it here, JS record markers. And here’s all the API that comes with that. Essentially, what happens is, anytime validation is going to happen, this gets passed into the validators, and you could have many validators attached to a single data source. It could be in different modules or something. In this case, we just have one. That gets passed in, and you can report problems or warnings or errors on the record itself. And then it gets passed out of the validator, and that gets handled downstream. So this is a really nice way for, and people have been asking about this for years, for developers to kind of implement their rules and their validation logic in a place which is completely separate from the application workflow and the UI. And it’s just sort of a hard rules definition, which goes in one place, and it’s respected everywhere throughout the application. In this situation, you can see that I made up a couple of little rules here. One is that, well, I’m checking the record shift date to make sure that you’re not shipping it before it was actually ordered that would make no sense. And then you can see that we report a message and I’ll give you some code complete here on this. If I was typing this out from scratch, I would call one of these overloaded report methods. And you can see the parameters here, and there’s really a message that you’re going to report the data provider about which you’re reporting. That could be null too. Then there’s the log level. So this would be the severity of the marketer and then there’s something there called the custom object or custom state object, which could just be extra info that you want to have passed in and out. So in this case, I’m just giving the message that you can’t ship it before you’ve ordered it, obviously. And that’s an error, and then I just put some junk in here for the custom state. So whatever you want in there because you could later retrieve this, you could put extra info in there. For example, I could say that this is related to both order date and ship date because maybe the UI I want to highlight both of those fields or something. Finally, there’s an array you can put in, and this is not required, I just put it in there. This could be an I18N key, and that’s actually recommended not just for multilingual, but if you really wanted to have like codified externalized strings, that the error message that you would show would sort of have the code and the real display value and you could change that without going back into the code. In this case, I just put in directly, but this could anywhere you show text, this could be an I18N message here, and then you could you could parameterize it with this argument. So, and that’s true of anywhere where you show I18N messages, they can be parameterized. So, that’s what’s going on in my validator, and then down here I have something which say is just a warning that hey, this order total goes over 1000 bucks, maybe the customer credit needs to be checked or something. So that goes in under a warning. So now as a developer, my job is done, I’ve implemented my business logic, maybe my colleague is designing the user interface or the application workflow, and they’re going to work off of this. They don’t need to go about putting this in mixed in with their other business logic. So what happens, when does this get called? Well, going back to the sample solution here, it gets called whenever you are saving. So, I’ve put a save button here, it calls the save data API call, which has been in surfoise API since the beginning. I am also proactively calling it programmatically when there’s a data change. So, I’m going to make this ship date July 1st. You’ll notice right away that I have a sort of printing out the validation here, that there’s an error there, and it just shows me the state of the record. If I were to put it back to something later, you can see that it’s instantly cleared. So, I’m actually validating continuously here on data change in the form. But if I were to put this to a bad value and then try to save it, you can see that I’m popping a toaster message here that the save failed. The thing that I want to point out is this is not happening. It really in the form logic, this is using that validator. If I were to, well, I’ll put this back to something valid, and then save it, and you can see that it’s successful. If I were to pick another record here, this one, the order totals over 1,000, and now already, I ran the validation even on selection. And now I have this warning that it’s over 1,000 credit check is recommended. That’s not going to block the save. So, even if I change the ship date, for example, and save this, you can see that it still updates it. So, I’m not saying any log level, you know, less severe than error is not going to prevent the save. So, let me take you back into the code here and just show you what’s happening on the orders form. So, you can see that, let’s first look at that save method that’s bound to this button. Here’s calling good old database manager save data, and that hasn’t changed that API has always returned a boolean. And it’s true if all of the data saved and false if it didn’t, and then you can inspect it, you know, what the errors were, etc. But in this case, what happens is save data will always first call the validator for records that are being saved. So, by simply implementing that on validate handler, I am now routing all saves through my validator. And if I attach any errors to the record, then the save will fail. It won’t be pushed to the database. So, it’s not just a way of putting stateful markers on a record. It’s also a way of really preventing bad data from going into your database. And that happens application-wide. I don’t have to proactively call it. It’s just there. When I call save data, and you can see that if it’s false, I’m throwing that little red toaster to show you the save failed. Now, there are some folks that use the auto-save mode. And if you’re new to Sir Boy, that’s the ability to just dynamically save the data anytime a user is changing the interface. This is a very productive workflow to have, although not everyone uses it because they want to have control over when data gets saved. But it is available, so let’s talk about it. So, here I’m enabling auto-save. I just put a checkbox on this form, but that’s typically an application setting you would do at the beginning. So, now, when I’m automatically committing records as I add to some, what’s going to happen then? Because you saw that I programmatically called save data, but here I’m not calling anything. It’s just going to do it automatically. There is no code attached to that. So, I’m going to go ahead and put the ship date back before the order date. And you can see that once I click out, it says, save failed, and ship date cannot be before order date. That is because we have added another event at the solution level. So, my solution here, test validate that I made this morning, I have the auto-save failed event. This is brand new. You won’t see this in earlier versions of Sir Boy. And if I look at this, what it does is it actually passes in an array of those record markers objects. So, that could be, because I could be in a, you know, I could be editing more than one record or I’m sorry, there could be more than one validator happening. And it could return this array. So, I sort of iterate over the groups of markers and then I actually get any errors that might be there. And again, you have this record markers object. It has this method get markers and you can pass in a log level here I did error, because I’m only interested in the errors. I could get warnings, for example, or in foes. But in this case, I’m just getting the errors because those are going to block the save. And then I iterate over the errors and I sort of stick them all together. There’s only one in this case and then I put them under this toaster message. I want to reiterate here that I’m not proactively blocking the save here. That’s already happened for me. I wouldn’t have to even handle this event simply by implementing the validator and attaching those errors at the point of validation. Again, it’s not going to save it to the database, either through database managers’ save data or through the auto-save. So, I just wanted to point that out. Now, going back to our example, you may notice that it’s kind of nice as I’m editing here. You can see that I’m updating the validation that I’m printing out to the screen here. So, I want to show another approach you can take with these APIs. Again, in my orders form, I have this method print validation. I put a button on the form there, but I’m actually calling it proactively when there’s a data change. So, if you look at the events for the whole form, there’s this nice event that binds to the form called on element data change. And that’s fired anytime you have an input control which has a change data value. And all I’m doing is calling that print validation method. I also have a form variable which shows that marker text that I’m showing on the screen. So, I clear that. And then I am programmatically calling yet another new method database manager validate. This is brand new. You won’t see this in earlier versions. And if I mouse over it, I’ll get a tool tip. There’s a lot of text there. But if I scroll down, you’ll see the parameters. It takes a record object. You can also pass in an optional state object. So, again, remember that when I was handling it, there’s that optional object which can take a state. And that can be anything I want. So, if there’s some information that you want to make sure gets into your validator or you get back out of your validator, you can use that. In this case, I’m just passing the record. This will read. Yes, Evo. Sorry, I don’t want to take you out if you’re a flow. There is a question when you have time. Yeah, that’s fine. You want to do it now? Yeah. Okay. And then I think it’s from somebody in Australia. Not in Australia. Very late there or not. So, the question is… What was… We better answer now then. I know. I know. I know. The data validate method will it call for all the records in the farm sets if you save the data without passing the record object. Okay. I understand the question. Yep. Yep. So, the question is, we’ll… Suppose I don’t have auto-save on, which is very common. Usually that people will disable that. And I go in from… You know, I go into this one and I set it to July 1st. So, I have an error on this record. And then I go to this record and I’m also going to set this one to July 1st. So, now I have these two records here, both having invalid… invalid markers saying they’re invalid. So, what happens to the validator? It will be called twice because it gets called per record and that gets passed in automatically. So, I didn’t try this so we’re going off scripts but what the heck. So, here it’s just saying save failed because one of those, at least one of the records was not able to be saved but you’ll see in fact that neither of these records is committed to the database. It will not let the record go through. I don’t have a cancel button on here but if I were to programmatically cancel it, I can sort of jump into my session here and database manager at a did records. That refers all of them. You can see the ship date here goes back to July, the ship date here goes back to July 31 and the errors are gone. So, those are never one in the database and I actually programmatically cancel those edits and that it reverts them back to the way they were. So, the answer to the question, short answer is yeah, absolutely. All the records that are being edited will all run through that. If validators are implemented, if I didn’t implement the validator then nothing is run of course. So, it gives you a chance to really look at each record. Cool, thank you. Yeah. So, I was showing how to print the validation here. So, this again this little box here which is showing hey there’s a order greater than 1000 check your credit. That’s coming off of directly from validation so how is that getting back to the UI in this case. I’m handling any time there’s a data change also a record selection in this case and I’m calling this this method validate on the database manager. There you can programmatically pass in a record. Oh, I think the question might have been what goes in here. You would call this you can’t pass in a whole found set you would have to pass in each record separately. But you can always get the edited records from a found set so that’s pretty easy. So, I pass in the record here and then I get back the validation markers object which could be null if there’s nothing returned. So, if there’s no markers generated then it’s null so then I’m then I’m done. There’s nothing to print I cleared it and then I’m done. So, I return. However, I can call this markers you know there’s a bunch of stuff in here. Not markers validation sorry. If I look at the code complete validation there’s you know get markers get markers at a level. I’ll get to generic exceptions in a minute. But if I get the markers in this case I get markers at all levels. I don’t know why the when I do zoom meetings I get lots of a tool tip cursor action here. Anyway, I get the markers and then I iterate over them and really what I’m doing is I’m checking the marker level. So, for each one of these markers again I’ll get get you code complete. So, you can see this is what I when I call that method report. Report markers on the on the markers object and I passed in my message and you know information about the data provider or this custom data object. That’s carried back out of the validator now and I can say oh this was this info an error warning what was the message. You can get the resolved I 18 and message for translations. So, in this case I’m just saying I cheated a bit. I said if it’s not error it’s warning but really you’d want to check any you know what what is the. The log level error worn info etc. But but I’m only doing error warning here so it’s one or the other and then I push that into my list of messages and that’s how I’m printing out. One and then what’s coming from the validator here. The idea is that there’s there’s two ways to do this one is to. To allow the validators to just work on save because they will anyway and then you can handle that in the UI and that’s typically when you call save and it and it fails because it will return false. But the other way is proactively do it and programmatically call that new method database manager dot validate pass in the record and then you get back those those validation markers. This UI here is not you know typically you might show this. A nice way I’m going to get to that next example but I have actually seen some of our customers with like a very complicated invoicing system for example. And as they’re working on on the invoice record. There’s all kinds of information and not all of it is breaking the invoice not all of it you want to prevent saving. In fact I think it’s really nice UX when you can save data which is invalid but you know has has problems but. But you’re able to report what those problems are to the user and so so these other log levels are nice for like warning or infos that you know it’s not just preventing save but but putting errors will will block to save. You can see two questions related to this issue. Yeah that’s fine because I’m going to switch over to another example so it’s a good stopping point. Okay. One question is can you show the error visually I even make the input border rats for example or can you show the error text below it. You voted to make that up for me. No. No that’s the real question. Okay. That’s exactly what I’m going to switch over to this other solution here and show you a more real world approach. Okay. May or may not. May or may not involve a red border. So I said I do the next one as well then maybe you can take a look at the same time. Yeah please. Well this is very soon. Can you can you validate with each key stroke. The technical answers yes you can. And I don’t have a working example here that does that. There are. That there is an extension called the key listener extension which you can then on key strokes and it can be throttled to. You can attach. A handler to key strokes and then you could run validation. There’s also something we’re putting in which is client side. Validate. Which could actually run client side. I didn’t do this in this webinar. But that could be another approach where if you really want to validate something. You know with a key stroke you might want to have that logic running client side. Because you’re making a server side round trip when they’re typing. It depends though if you need access to your data model then you need to go server side. And we have a we have a service for that. We use it for other stuff like our look ups component. So the technical answers yes but I’m not going to be able to show it in this webinar. Okay so let me launch this. And this one has this is by the way this is our sample application which is starting to appear in tutorials now. And we use this for some trainings and workshops and demos. So we’ll be probably be adding the validation to this in a standard way where when you get the sample solution. You can actually see the way the code is used in a more framework way rather than the very from scratch way I just showed. So in this case I’m going to jump into my orders grid and double click on this order record. It’s a little bunched at the bottom so make my screen smaller is that still visible Evo. The fields and such are just too small. Yeah I can see everything. Okay. So I put almost the identical rules in this solution that the ship date. This should be although this one looks like it’s already got a bad ship date. I will change it and then change it back so I’ll save that record. So I have a, oh I was looking at the required date. I’m sorry. I have an ordered date of July 5th. I have a ship date of September 23rd. And I have the same sort of rule that I want to not allow the ship date to be before the order date. So I’m going to put this to July 1 and in this case this is a warning. So I’ve put it in sort of yellow and orange. And as I mouse over you can see ship date cannot be before order date. Should probably say warning or something, ship date is before order date. Because I was playing around with it this morning and I originally said this as an error. This would not block me from saving. So I’m able to save the data and come back in. I didn’t clear the warning here. I guess it’ll show it every time but you could do that. But it didn’t prevent it from saving. It did save. Now suppose that order date can’t be, you know, is not, cannot be empty. And it’s not being specified at the database level but in the application level. So if I click off that you can see that that becomes red. And it says order date is required. And now if I were to try to save it, you could see that it could not save order date is required. I’m not able to actually put that in the database and I get a tool to bear indicating that what the error is. And also clearly it is in red with that red border. If I were to try to navigate away from here to the sort of editing framework. And this sample will say, what would you like to do? Discard the changes and everything goes back to the way it was. So this is taking all the same principles I just showed. But showing it in a more real world, looking solution with a little bit more enhanced UX. And I’ll take you into the code there and show you what’s happening. So this is the orders edit form right there. And we’ll see that what I’ve done is actually this form is extending a base form. In fact, all of the edit forms here extend a base form which has a little bit of a framework or rules in this sample of how it works. But you can see that again that on element data change is implemented actually down in a base form. There’s this base code which does it. And it looks a lot like the method I showed in the previous example, which was calling that print validation, which just dumps it onto the screen. In this case, I’m doing a bit of CSS. So the first thing I do is I take the origin of the event, so the field that was just changed. And I remove any styling that I had applied, any extra styling that I had applied with this remove style class. Then I’m calling that database manager validate method again. I was passing in, I was playing around with like element name here and passing it in, but I didn’t do anything with it. That’s that extra info. But just select the record. Again, if there’s no markers, we’re good. Otherwise, we continue down here and I check if it has errors, then I cheated a bit here because it could have multiple errors. But I just grabbed the first one because I’m just playing with an example here. And I get the first error and I get the message and I put that in the tool tip. And again, I add that style class field invalid, which gives it some of the styling you saw. The same goes for warnings. I ask for markers at the log level warning. And I change my style class here to field warning for that if it has warnings. I guess it could have errors and warnings and warnings would go last and that’s all you see. But of course, you could be more nuanced in how you do it. Just to show you what the CSS looks like, although it’s not really relevant to this sample. In the less file here, I put these two selectors at the top of the file. Probably best practice not to have hard coded colors here, but to use brand colors. But I just went for it. So you can see there’s the color, the border, thick border bottom that turns to red. And the background color, which turns kind of pinkish and the same for the warning, which is the orange and yellow. So nice that you can just do a little CSS. You don’t have to hard code it to any particular form. This is running on a base form. So that would apply to on element change would apply to any form that inherits from this and any field. You could make hundreds of screens that have a nice validation workflow like this without really any extra code except for the validator, which is the whole point that on validate. You just centralize it. You don’t have to worry about UI UX. You worry only about business logic. And then you know your data is safe. Probably the last thing to show here, because we’re getting long on time is the save and the toaster, even though we kind of already saw that. But in this case, the base crud, if I look at the outline here. Where’s my outline? Now all my go to meeting stuff is in the way. I’ll just scroll there. Save. So this is being called when I click that green apply button. Again, database manager saved data is the way you always save. So you get that validate for free because it’s returning false. And we know return false then we get in and grab those validation markers. I didn’t point this out earlier. I didn’t have an example of this. So it’s worth pointing out that whenever save fails, you can have an array of failed records. So this is typically how you would respond as this goes back many versions of Servoy. Database manager get failed records, which gets an array of records which could not be saved. But now there’s this property on JS record that’s been added. Dot record markers, if I jump in here and ask for code complete, you’ll see it. It’s taking a minute. There we go. So you can see there’s the JS record markers object, which is attached to every record. So any record has like the stateful record markers object or can have it. And it follows it around until that record’s been re-validated again. So that’s all added into this new API. Again, I get the errors there and I put them in the toaster message, same as before. But worth pointing out that I grabbed the failed records from the save data in this case. I cheated and grabbed the first one, but you could go through I could be editing. I could make an order. I could add some line items. And then I could save and I might have, you know, 10 errors with that. And if you had a nice way to show those to the user, they would be all in your transaction there. So I see some other questions coming in. So I will. Oh, I did want to go over a review here. I know we’re getting long and I have a few slides, but just to make sure this is clear. You want to do the questions before you do the slides? Yeah, that’s that’s fine. Okay, because there’s some stuff I didn’t show that I want to mention. Okay, yeah. There’s there’s somebody that’s asking where the field is that costs. Sorry. I’ll just read it. I missed where the field that caused the error is stored or kept. Say that again. I missed where the field that caused the error is stored or kept. The field because the error. Yeah. So the. The error itself maybe like the error tech. I showed that at the beginning and maybe I’ll point it out again because it’s kind of the root of everything here is. It attaches to the entity. So if I look at the in this case, the orders table. Yes, so. Vincest like the order date instead of the whole record. Does that make more sense? In terms of showing it or in terms of validating it? It’s a good question. So just to just to cover the original thing, there was this event. And this happens at the entity level. And this says. This attaches to the errors when that gets validated. There’s the shift date one there. And then it got rendered in the. In the base form here. And it didn’t it was generic. It didn’t say go specifically to this field. It actually responded to the element that was in the. It’s down here the on element data change. So this this event itself has a source. And so I did a vent get element name and then the field as elements. And you could also do event.get source. It will return the same object. So I’m working kind of implicitly. I never said go to this field here. I’m just saying whatever. You could do that because you could get the error markers. And then there’s also a data provider or extra info that you pass. Which could also be used. So there’s a lot of ways to kind of triangulate which field or fields. Because I might want to show order date and ship date. So I’m going to put that off the validation markers and show it that way. So there’s a number of ways to triangulate maybe which field you’re talking about. And some some things might not even be related to field. It might be. You know something a bit more complex or harder to describe. Yep. You says he got the answer. Okay. Sorry. Other question. Yeah. Can you combine the validation with validation rules that come from the database? Would that make sense? Yeah. Okay. So I think I get the question. So it could be that you want to abstract this a bit. I have my and you’ll see this in older rad tools. I have here my on validate which is the which is the handler. And this is some code here that I wrote and this gets called anywhere validation is happening. But it could be that I want to abstract this a level further and say, hey, I want to have some rules. And I want to be allow you know, non developers to put in a few rules and have even like a rules builder where I have. You know, you see this in ERP applications where they might say you can have up to three decimal places or. You know, the limit that you I did the credit check recommended right when an order was over a thousand bucks. Often you’ll see like an in ERP systems, those will be custom rules that the tenant for the ERP system sets, not the developer. And in those cases you want to pull that from metadata. And of course, serve way as a fully robust business logic layer and data binding and all of those things you could be pulling from data. And that’s probably what would happen in the real world. Other questions? Nope. That’s a turn out. Okay. Then just cover a couple other things. Again, why would you why is this updated and why would you use it? Yeah, everything I showed could kind of could always have been done in Servoy. Just it was a bit more cumbersome, a bit more moving parts. So why do it this way and why change this now? First of all, it supports really good architecture. You could see that the validation is completely separate from the application workflow and the UI and the UX. Moreover, as the last question pointed out, you could abstract that even further and start to really put rules into. Because it’s not really logic, it’s more like rules and put those rules into metadata and have a metadata driven rules that have a standard UX that reflects those and have them separate. So it’s really good architecture. It makes it easier to build frameworks that do that sort of thing. You saw I did it a little bit with form inheritance, but you can imagine on a bigger scale. And it also allows you to have your UI, your UX driven from the rules. So those validation messages, those are coming right out of the rules. I don’t have to like in my form code say if this show this. And again, I recommend those use I 18 and so you can codify them even further and not have them be loose text. The main center of everything I showed is this on validate method. Our event, it gets called anytime that you’re saving and it also gets called anytime you proactively call validate. Again, you’re always validating one record at a time from a data source. And you can at any point append markers to it. And these are sort of like the validation state errors in those warnings. They have their own level for that. When you when you’re saving it gets called automatically, but there is another API that we added called database manager validate. You pass in that record object and it will get validate. You can also pass in an optional state again if you want some extra info to go on. So that’s that’s a new API. So that’s a programmatic way you saw when I was doing the on data change handler. That’s when I was calling the validate because I hadn’t yet tried to save it. There’s a new class we saw there. You can see it in the solution explorer if you expand that and click on it. There’s actually two of them. There’s just record markers and then just record marker which is like an instance of it. So this is kind of like the outer class which collects all the markers for given record and then the inner class, which is the individual marker. The individual marker has the the message and the sort of severity level plus the data provider that that wasn’t they have been affected. The main security that severity levels you would want to use are errors in frozen warnings. And the message itself can always be localized or internationalized. And of course, many times you’re doing that you can also parameterize it so that it’s flexible. I recommend that you use IATN so that you don’t have developers making choices about what text a user might see because someone from business might come along and say, can you change it from you know ship date instead of cannot must be must not and then you know, oh geez you got to go back to the source code and change it. You’d rather put in an IATN key and then to oh yeah we’ll just go into the configuration and change the translation for that key doesn’t have to be multilingual that’s a best practice. I just I made a little diagram so you could kind of see that that all validation is passing through all saving is passing through the validator. So you do not get to the database without passing through the validator if you’ve implemented the validator and if the validator attaches one or more errors to the record or I should say any of the validators because you can attach more than one. from say different modules if any of them returns one or attaches one or more error then you get you get a failed save in the case where you’re calling save data programmatically which is I think the more freaking case where people have like save buttons and and they’re not auto saving. then save data returns false as you know as it always has and then you can go and grab the failed records and look at their record markers look at their validation state and I showed one example of that for other applications where you where you do have auto save. and we added this event this on auto save failed and so that’s like a callback anytime where you’re like clicking out of a field and all the sudden you thought auto save would work but validation failed again it passes in the markers to that I showed a quick example of how you can handle that as well so those are two new additions. the other way that this could happen is that you have someone entering data in the UI again you’re calling that validate method and I call this sort of the on demand or programmatic. this is not tied to save necessarily because one I call save data but here I could at any point to say hey validate I haven’t tried to save it yet but I might want to give feedback to the user you saw that I did this on data change and then I was able to highlight that sealed with a red border what have you. so there’s there’s the third model there. some things I didn’t get to that I think are worth covering and I’ll just do this really quickly. of course some errors are not validation some errors happen after you’ve tried to save right and these are typically like database constraints like a non you know a unique constraint violation or non null. violation we’ve always handled those before they fail to save and you go and you get the record and it gets attached to the exception. now we’re taking those and we’re writing them back into the validation markers the record markers class you’ll see a method there called there’s called get markers but there’s also get generic exceptions. so and again this will get all of them so you might see stuff coming back from the database it wouldn’t matter to the person who’s. who’s designing the UX they could just check for errors and they could check for generic exceptions that could be coming from the database and maybe for those they might just say unexpected error or something like that because it’s not really meant to be reported directly to the user like a database error and that gives you the nice flexibility to handle those differently. null empty values so these are these are columns on the table which which we don’t allow null you’ll see that in the table editor. this is something Servoy has always enforced so this is set again this is at the application level at the like the metadata level to say you know we won’t allow null server always always enforce those but now we actually route those back and attach them as. markers and what we do is we use an i.t. and key for the message so it’s an error with a message in the message I think by default says you know the data provider cannot be null and it names the data provider. but it’s an i.e. an n key so of course you can go and put in whatever you want and then you can also parameterize it so again it doesn’t force you to some standard message. what about custom column validators. I think I missed something I thought I had size in there oh I did that out of order yeah here. there’s also the size validators so suppose you have a column with a length you know 30 and you try to pass in a piece of text which is 50 that will also fail. we we validate this in advance we always have but now again we route this through and put it on the markers and there’s again a generated i.t. and key which you can replace with whatever you want so now it’s really nice as a you I developer you can just say hey what are my errors and report them all. as such but the logic is all is all handled for you in one place. and then finally what happens to custom column validators. this is a feature that we’ve had for many years it’s not the most common feature but people do attach these method handlers for validation events on columns which we put in the platform many years ago. those always were executed immediately either from the UI or even programmatically the moment it was set on the record. now what we’ve done is we’ve deferred those they do not execute automatically until you save them until you say the record. there is a configuration to bypass this because this could be we realize this could be a breaking change right if you’ve built your application you’re expecting column validation to fire. immediately and it no longer does then you might want to just go and change that it’s in the documentation I didn’t put it up here there’s a configuration you can set. but I think that if you’re if you’re not using them then this is much nicer because what you can do is implement custom column validators. if you want separately and then and then they get deferred until the end and they go back on to the markers that way so. just want to point out I could be a breaking change if you use validators you want to take a closer look at that part. I’m going to take any more questions we have I’ll leave some links up here again this is recorded will posted at that tech series homepage later today or tomorrow. you can download the latest release candidate there’s instructions on our forum so I would go there first because there’s like release notes links and helpful stuff there and you can download it and try it out. Any more cool well first of all people are noticing the clip art that you’re using specifically the three and a half inch floppy drive. So we want to see more of that on Wednesday and Friday. Okay then there’s also a serious question. Will the on validates also call the column validation rules which are defined on the table columns. Yes I think so I will double check that but I’m pretty sure it gets deferred but then if you call validate or save then it gets executed. So it’s it’s it’s in fact yeah I’m sure because I remember now that they go last so it actually goes in the order that I presented it’ll do your validator then it’ll do all the built in stuff like the size validable the null validators the size validators and then the custom validators and then everything gets routed back on to those. markers and you can handle them in the UI accordingly. Cool. All right so I think that’s that’s it Sean in terms of wait that’s one. Yep no. That was it in terms of questions. Thanks for the webinar Sean as always thanks everybody for joining and we’ll see you Wednesday same time same place. Yep we’ll be back Wednesday with with all the extensions the packages are updated the pop up filter mainly. All right awesome. All right have a good Monday everybody and say bye.