WEBVTT

00:00.110 --> 00:00.650
Hi everyone.

00:00.650 --> 00:01.250
Welcome back.

00:01.250 --> 00:04.910
In this lecture we will look into some of the internals of constructors.

00:04.910 --> 00:10.100
And how can we apply domain validations before constructing this product instance.

00:10.130 --> 00:17.000
Because by default there are constructors generated by the compiler whenever you create a record class.

00:17.000 --> 00:22.610
And those constructors are called canonical constructors, because without the constructor there is

00:22.610 --> 00:25.160
no way we can create objects in Java.

00:25.190 --> 00:27.620
The concept is applicable for records too.

00:27.620 --> 00:32.840
So now in this case for the product, let's say when you are creating a product, you want to make sure

00:32.840 --> 00:39.230
the name is not null or the name is not blank, and the cost should be greater than zero, right.

00:39.230 --> 00:43.190
If you want to apply those kind of validations, what are the options we have?

00:43.220 --> 00:43.580
Now?

00:43.580 --> 00:46.190
Let's quickly jump into it and then explore those concepts.

00:46.190 --> 00:49.190
So the very first thing is we can apply those kind of validations.

00:49.190 --> 00:52.340
So what we need to do we just need to create a product.

00:52.340 --> 00:54.620
But this is not going to be a constructor.

00:54.650 --> 00:57.080
What this is going to be is a simple code block.

00:57.080 --> 01:03.210
So this code block has access to all the parameters that we pass to this specific record class.

01:03.210 --> 01:10.020
So in this case we can apply validations like if name not equal to null and and name is blank.

01:10.050 --> 01:13.440
If the name is blank we want to throw an illegal argument exception.

01:13.440 --> 01:13.800
Right.

01:13.800 --> 01:19.020
So in this case we can do throw new Illegalargumentexception.

01:19.020 --> 01:23.910
And the value is going to be name is not valid okay.

01:23.910 --> 01:25.350
So this is one exception.

01:25.380 --> 01:31.350
The other exception is we want to make sure the cost should not be zero or less than zero.

01:31.380 --> 01:32.370
In those kind of scenarios.

01:32.370 --> 01:39.240
What we can do in this case we can do if cost dot compare to because that's a function that we can use

01:39.240 --> 01:42.690
in order to compare the values that are part of the cost.

01:42.720 --> 01:43.200
Right.

01:43.200 --> 01:49.080
So in this case it can be bigdecimal dot zero is less than or equal to zero.

01:49.080 --> 01:55.050
So in this kind of scenarios we will make sure that the cost that's been passed to this product instance

01:55.080 --> 01:57.050
is always greater than zero.

01:57.080 --> 02:01.190
So in this case we also throw the illegal argument exception.

02:01.220 --> 02:01.640
Okay.

02:01.670 --> 02:04.010
But in this case it's going to be cast.

02:04.010 --> 02:05.810
Value is not valid.

02:05.990 --> 02:09.920
So these are the two validations that we have for the product record class.

02:09.920 --> 02:15.170
And this is how you can actually apply exceptions before constructing the object.

02:15.200 --> 02:16.970
Now let's go ahead and test this one.

02:16.970 --> 02:21.800
So what we are going to do we are going to be testing the name being not valid first.

02:21.800 --> 02:24.530
And then we will test the cast being not valid.

02:24.560 --> 02:28.250
So in this case I am going to name this one as name.

02:28.250 --> 02:29.630
Not valid.

02:29.840 --> 02:30.380
Okay.

02:30.410 --> 02:34.340
So in this case I'm going to pass the value as empty over here.

02:34.340 --> 02:39.230
And the way we are going to call this, it's going to be a little different because in JUnit five there

02:39.230 --> 02:40.910
is a handy way to test this one.

02:40.910 --> 02:44.870
So in this case what we are going to do we are going to call assert throws.

02:44.900 --> 02:47.900
So we are going to assert what that exception is thrown right.

02:47.930 --> 02:50.210
So in this case we can call assert throws.

02:50.210 --> 02:54.560
And then we can call out which exceptions we are expecting as part of this call.

02:54.590 --> 02:57.560
So in this case we are expecting an illegal argument exception.

02:57.590 --> 02:57.830
Right.

02:57.860 --> 03:00.290
So that's the exception which is thrown from here.

03:00.320 --> 03:03.950
Let's copy this one and then put it over here or dot class.

03:03.980 --> 03:04.340
Okay.

03:04.370 --> 03:06.590
And then what we do is we provide a supplier.

03:06.620 --> 03:10.310
So the way you provide the supplier is by providing a lambda right.

03:10.340 --> 03:12.890
So we are using the lambda syntax to provide the supplier.

03:12.920 --> 03:16.820
And then we can actually copy this one and then put this one over here.

03:16.850 --> 03:22.520
So what this is going to do is that when this code gets executed while we run this test case, this

03:22.520 --> 03:23.960
code is going to throw an exception.

03:23.960 --> 03:27.170
And that will be caught by this specific assert throws block.

03:27.170 --> 03:30.260
And that exception is going to be illegal argument exception.

03:30.260 --> 03:33.500
If there is a match then we will have access to that exception too.

03:33.530 --> 03:37.070
So the way we do it is by calling where exception.

03:37.100 --> 03:37.730
There you go.

03:38.360 --> 03:40.040
So in the then block what we can do.

03:40.070 --> 03:43.070
We can actually check what the actual message is.

03:43.070 --> 03:46.490
So in this case the message is going to be name is not valid.

03:46.520 --> 03:49.670
Let's copy it over here and then put it over here.

03:49.670 --> 03:54.720
And then we are going to be calling exception dot message.

03:54.720 --> 03:58.290
So this is how you test the exception scenario in JUnit five.

03:58.290 --> 04:01.710
So what we are doing is that we are calling the product record class.

04:01.710 --> 04:06.690
Basically we are creating an instance of the product record class, but we are passing the name as empty

04:06.720 --> 04:07.110
string.

04:07.110 --> 04:11.250
So in this case if the name is blank it's going to throw an illegal argument exception.

04:11.280 --> 04:13.080
Let's go ahead and execute this test case.

04:15.600 --> 04:16.110
There you go.

04:16.140 --> 04:17.010
The test case passed.

04:17.010 --> 04:19.560
So this means this is working as expected.

04:20.310 --> 04:24.000
Now the next step is to write a test case that's going to validate the cost right.

04:24.030 --> 04:28.140
So let's go ahead and copy this one and then create another test case.

04:28.140 --> 04:30.450
Let's name this one as cost not valid.

04:30.660 --> 04:33.180
So it's going to be cost not valid.

04:33.180 --> 04:37.890
And then in the place of this one this is going to be iPhone again which means we are passing a valid

04:37.890 --> 04:38.610
product name.

04:38.610 --> 04:40.920
But the value is going to be negative.

04:40.920 --> 04:49.890
So the cost represents -9.99999 which is not a valid value because we have a check over here that's

04:49.890 --> 04:56.330
going to throw an illegal argument exception in this case we can actually call cast is not valid.

04:56.360 --> 04:56.750
Okay.

04:56.780 --> 05:00.050
So now let's go ahead and execute this specific test case.

05:01.670 --> 05:02.060
There you go.

05:02.090 --> 05:03.710
This test case also passed.

05:03.740 --> 05:09.800
Now what I wanted to do I want to execute the whole test class to make sure that all the test cases

05:09.830 --> 05:11.630
are succeeding without any issues.

05:11.630 --> 05:15.920
So the introduction of these validations did not break the positive test case.

05:15.920 --> 05:21.890
So if we pass a valid name and the valid cast, then the test case is going to execute as expected.

05:21.920 --> 05:27.710
Now what I wanted to show you is that what are the options when it comes to creating a custom constructor.

05:27.710 --> 05:30.980
So let's assume the type is not something which is always known.

05:31.010 --> 05:36.680
If the type is not passed, then we would like to assign some generic type name like general, right.

05:36.680 --> 05:41.360
So if the type is not passed we would like to assign the type to be general, because in this case for

05:41.360 --> 05:44.360
iPhone we are passing the type as electronics, right.

05:44.360 --> 05:48.890
So from a product perspective we might not know the type all the time.

05:48.890 --> 05:50.720
So that's what this domain represents.

05:50.750 --> 05:51.170
Okay.

05:51.200 --> 05:55.970
So in this case what we will do is we will create the public and then provide the class name.

05:55.970 --> 05:58.790
And then we are going to be passing the name and cast.

05:58.790 --> 06:02.270
Because this is a mandatory value which will always be passed.

06:02.300 --> 06:02.660
Okay.

06:02.690 --> 06:08.990
And then when this happens if you take a look at the error over here, non-canonical record constructor

06:08.990 --> 06:11.030
must delegate to another constructor.

06:11.060 --> 06:15.830
What this means is that it needs to definitely call the canonical constructor.

06:15.830 --> 06:22.010
So in this case, the way you call it is by calling this dot or this name cast.

06:22.010 --> 06:25.880
And then we can assign the generic type as general.

06:26.210 --> 06:26.660
Okay.

06:26.660 --> 06:30.080
So this is how you create a custom constructor.

06:30.110 --> 06:34.190
Now let us go ahead and quickly write a test case to make sure this is going to work as expected.

06:34.190 --> 06:37.490
So in this case let's copy this one and then put it at the bottom.

06:38.180 --> 06:44.120
And we can name this one as create product custom constructor.

06:44.150 --> 06:44.480
Okay.

06:44.510 --> 06:46.310
And then I'm not going to pass the type right.

06:46.340 --> 06:51.330
So in this case this is going to make sure the call goes to the custom constructor that we created.

06:51.330 --> 06:53.040
So now the call goes to this one.

06:53.040 --> 06:59.340
But in the case of the type the type is going to be general because that's a default type that gets

06:59.340 --> 07:01.290
assigned if you don't pass a type.

07:01.290 --> 07:03.450
Now if I go ahead and execute this test case.

07:03.450 --> 07:06.330
So this is going to give me a green signal to there you go.

07:06.360 --> 07:08.490
So we got the green signal as expected.

07:08.490 --> 07:11.940
And if you take a look at the product the product type is assigned as general.

07:11.940 --> 07:16.380
And this particular code is being invoked by the this block.

07:16.380 --> 07:21.750
So any time you create a custom constructor, calling the canonical constructor using the this operator

07:21.750 --> 07:24.540
is a must, otherwise the compiler won't be happy.

07:24.570 --> 07:27.030
I hope you all had fun coding this.

07:27.030 --> 07:30.630
Custom validations and how to create custom constructors.

07:30.630 --> 07:32.850
So these are some of the advanced concepts.

07:32.850 --> 07:38.760
You will be actually implementing it for different use cases, but it is good to be aware that you have

07:38.760 --> 07:43.110
all these additional concepts that are available with record classes.

07:43.140 --> 07:44.430
This marks the end of this lecture.

07:44.430 --> 07:45.420
Thank you for watching.
