 Good afternoon, I promise I'll try to keep you awake, it's post-lunch session, so to keep you awake I'm just going to code all that all along, yeah. So we're starting with this particular piece of code, it's a regular Java code, yeah. And essentially what it does is just to give you a brief overview, there is an authenticator The first thing that the user does is logs in using the system login and password, yeah. And if that fails, user tries to log in using Gmail login, yeah. And if that fails, then user is redirected back to the login page, yeah. The standard web workflow scenario that we have. In case if logging and using system login succeeds, right, what happens is user goes to the step two, which is a two-factor authentication, yeah. And then if that is successful, user is going to get returned, get transferred to dashboard. Fair enough? So if I just run this happy path, I'm just kind of configured to run the happy path. This code is going in system login inside two-factor, and then eventually it kind of goes to redirection, which is the dashboard target page, yeah. So let me just kind of give you a brief overview of code which I have. This is a simple dispatcher, just doing a redirect. And this is the authenticator, yeah. Let's try to fail the system login, yeah. It should go to Gmail login and then go to two-factor. Fair enough? So that's the kind of overall workflow that I have here in case of system login failure. Let's see if Gmail login also fails, yeah. If system login and Gmail login both fail, you are redirected to the login page, yeah. Let's say Gmail login passes, yeah. What do we expect? We expect the user to see the dashboard. Fair enough? Yeah. And in case if two-factor fails in now, we have to redirect back to the login page. So that's what this code is essentially doing, yeah. And we see this kind of code in our day-to-day life. User is just a normal Java bean, yeah, which we see all the time. So this is this bit of code here, right, which is there. And we write this code kind of, we have seen the code in our daily work, right. How many of you have seen this type of code? Some form or the other, almost all of us, right. All right. Now just to kind of go back and forth between the two. So if you see, I've just kind of copy pasted the code here in the slide. And if you look at this code closely, inside the first try block, you know, I have to declare the user variable outside, right, because it's outside the local block of the scope of the local block of tri-catch. So we declare the user outside, right. And then if we get the user back from the system login, we assign it there. In case if it fails, we assign it using the Gmail login. Fair enough. The interesting part is this user gets transferred just to the two-factor authentication right there, right, after initialization, correct. And if you look at the target URL, target URL gets assigned in one of the success try blocks. And in case of failure, it gets assigned to login page, yeah. And then eventually in the last step, there is this redirection that's happening, yeah. We ideally kind of, I mean, the only use of this particular user variable and the target variable is just to pass data around implicitly. We're not mutating that, not doing anything fancy with that data, right. So I'll just kind of, if you were to look at the happy path, we have this, then we have this, and then finally we have this, right. So I'll go back to code now and over here, let's try to visualize the code as if we did not have the try catch blocks, yeah. And I'll just pick up the essential elements out of this, right, to convey the idea what I want to show. What did I do? Oops, sorry. Did it run? Just pick up the essential elements. This is really my happy path, correct. Can I not rewrite this in this fashion? Get rid of this, yeah. Can I not rewrite this in this fashion and get rid of this? So this is the real essence. I've chained functions together to really create the entire happy path flow, yeah. So ideally our goal is, I want to kind of do this so that I can compose and if I can declaratively see this in my code, then I know that this is the entire flow without having my way to sift through all those try catch blocks, yeah. So this is probably where we need to go in terms of chaining the functions together and bring up the entire flow, yeah. But essentially if you see, can I just, if I'm just running it here, I'll just kind of bring it to the happy path where we return the user and there we go, okay. Now, all these things are wrapped in the try catch block, right. That's the repetition that's happening for all the cases. So the first attempt that I want to do take is boil away the boilerplate, yeah. So if I were to boil away the boilerplate, I will have to approach this in baby steps. I'll take one step at a time and let's say if I were to take this particular try catch block, yeah, and just put it in here, right. I'm not bothered about this particular try catch block because it's a nested try catch. We'll deal with this a little later, right. Now, essentially if this is a try catch block and if I wanted to essentially run any code block, yeah, from within a try, because what I'm trying to do is I'm trying to boil away the try catch try block, right. So at this point, what is this particular function doing? It's consuming two final user ID and password, right, and these are constants. So for all purposes of constants, I'm not going to, I'm going to ignore because they are finals. So for now, and it returns what a user, right. So I'm going to ignore for now just what it consumes and say it doesn't consume anything but returns your user, right. And I'm going to say if I want to generify it returns a type T, fair enough. Now, if I have to take this in Java 8, what is the, what is this functional interface which gives me this notation, which gives me this from nothing to type T producer, it's called supplier, right. So if I have to wrap this whole thing, yeah, in a method, right. I don't have a method name, but I have the, I'm slowly building the signature. It has to produce T will work out the method name and it needs to be passed in a code block. Fair enough, which is of the type what supplier of T, right. So far, so good. We'll just take one step at a time. Now I'm slowly moving on. Let's, let's create this as a static method in this particular class. Yeah, which returns a T. And essentially what is this? This is actually a try. We're trying this out. So I'll just kind of give the method name at this point as try with. Yeah, just to convey intention revealing name is what I'm trying to get. And what do I do here? Instead of this line, now I will have return code block dot get. Fair enough. Let's try to compile and see what's happening. Cannot find symbol supplier. Oh, yes, obviously. I just need to import Java.util.function.star and let's see if it compiles. Missing return statement line 52. I guess at this point, I, I don't know what should I be doing. So I'll just kind of rewrap this exception into a runtime. Yeah, code works, compiles. Now I want to use this particular method at all places where I have this particular thing. Yeah. So I would say this is test dot try with and wrap this guy in a lambda. Yeah, it says, and I try to compile and run it says exception must be caught or declared to be thrown. Why is it saying this? It's very simple because this particular method is throwing a check exception. And how many of you feel the pain of working with checked exceptions in lambda? All of us. Yeah, that's, that's the real issue which is out here. Right. So what do we do? We have two options before us. Yeah, either wrap it in a runtime exception and bubble it up or deal with it. Yeah, just two options. Or what we could do, so I will go for the first option where I'll wrap it up. Yeah, I already have created a wrapper which is try with, but this regular supplier won't work because regular supplier signature is what? Get T get me the T pretty much. So I need to create a interface, right? A functional interface or an exceptional Sam is as it's called. And I call this as supplier throws exception. Yeah, fair enough. And all I have to do now is kind of wrap this guy and say this is E where E is and I run the code. Yeah, it works. So now I have replaced a regular supplier. Yeah, with a supplier that throws exception, which matches the signature. Right. And at this point, I have, I've been able to run this code. Can I not do the same for the remaining piece of code which is out here? Yeah. So let's just do that. Wrap this in a lambda. Let's run this super code works. Do the same thing here. Right. And before I do this, I would have to do a little bit of. So first I want to wrap this guy. Yeah, and here I want to put this guy inside a function. Yeah. And say test.try width. And this is going to be the wrapped lambda. And this would be as target equal to an instead of from here assigning it. I'll say return dashboard. Make sense. Let's run this code. It says now we have another error. Local variables reference from lambda expression must be final or effectively final. How many of you come across this as well? We deal with that all the time. What's really happening here behind the scenes? The thing that is really happening is that when you, when you have a lambda expression and if it stands on its own two feet, by that I mean just consumes the variables which are passed to it. Then it's a, it's a lambda which just depends on its local variables. But if the lambda closes over to some other, then it becomes a closure to another variable in the next scope. Yeah. In this case, if you notice this lambda, I mean this particular variable user. Right. Is not final. If you look user ID dashboard login page passwords are. Finals. But user is not final. What the compiler tries to do. It tries to determine whether is user going to be final. But what it finds instead is user being, is being reassigned here is being reassigned here. Right. And it's being used from within this lambda. Yeah. So that's why the compiler shouts and says, you know what? This must be final or effectively final. And many times I see Java developers what they do. Hmm. Let me try to be smarter than the compiler and run the code. How many of you've done that? Never ever do this. This is a hack. Yeah. We don't want to do this dirty work because essentially what you have done if there are two threads or if the lambda is lazily evaluated, you will face issues. Yeah. So never ever, ever, ever do this. This is an opportunity for you to refactor your own code base. Yeah. So I think it's now time to pause and reflect what can we do when you hit this kind of problem? What can you really do? Now I'll go back to the essence of the happy path here. Once again, I am going to take help of this. I am going to take this piece of code and put it in here. Yeah. What is the return type of this user? What is the return type of this URL? Yeah. And finally it's being fed to this chap who does the redirection. Yeah. Now instead of reaching outside to fetch the user, if you notice users just being passed around implicitly, there's no modification to the user. Instead of this, what if I can create a container in which the user is housed? Yeah. And create a container in which URL is housed. Yeah. Now imagine if this test was a container which contain the success value of this execution. Now this execution can result in two outcomes, right? Success or failure. So it could either host the success value or could host the exception itself. Yeah. Now if it's a container and on that container somehow, somehow magically. Yeah. If I'm able to pass the value to this next block, will I need a local variable user to hold it? No. Agreed? Yeah. So let's try to create this container, right? And I'm going to call the, I'm going to give a name to this container at this point. Yeah. I'm going to say that this particular container in which this user will be packaged. Yeah. I'm going to call this as try because this signifies, moment I look at this type, it tells me, oh, there is some computation which is going to be tried. It could succeed or it could result in a failure. So just to kind of move back here, what we are, we are attempting is we're going to create a contri-container. These are the inputs. This is your computation which could result in success. If it's success, it hosts the value. If it's failure, it hosts the exception. Fair enough? Yeah. For that I have to do a little bit of refactoring now again. Yeah. So what I'm going to do, we're going to go towards this one step at a time. Yeah. Okay. So first steps, I'll have to move this method out of this because this naturally does not belong here. Right? So I'm going to create a class called try of T and just move this guy from here to excuse me, here. And let me call this as, because now if I have to invoke this method, it will be try.tryWidth. It's an eyesore. I'm going to just call it width. Yeah. So it's going to be tryWidth. So first things first, need to replace all the references with this. Yeah. Okay. Let's see if it runs. It has run because now we are back to the same error. It says local variables reference from the lambda expression must be final or only final. So just kind of move this method from test to a try class. Right? Now if I have to ponder for a while, will any longer returning T help me here? It won't. Right? Essentially what do I have to do? I have to return a container. Right? And I'm going to call this container the same name which we are in the same class. Fair enough? Now if I have to return a T this, there is a, this signature is what? Returning T. But I need to return what? A try of T. Whereas here it just throws an exception. Right? Fair enough. I'm just deleting that exception line. So if you notice this is what? The success path. So what I end up doing is I'll create two polymorphic variants, one to represent the success and wrap the success in here. Yeah? And the other to wrap the exception. Fair enough? So now I have two polymorphic variants of try itself. One catering to the success flow and the other catering to the failure flow. So let me end up creating those classes. Right? Success of T extends try of T. Right? What's going to, what is it going to have? Just hold the value. Right? Success. Fair enough? Oh yeah. Thank you. Thank you. Which one? No, because I'm going to have exception itself. Yeah? So I'm just going to put exception without thinking too much. So now I have the two polymorphic variants which are available to me. Let's see what happens now. I'm just going to get rid of this. And now we have real issue here. If you notice it says try of T confirms to URL exists. I mean, sorry. What does it say confirms to? No instance type variable T exists. So the try of T confirms to user, to user. Right? Because if you look, this is user. It should be try of user. Right? Next, we have the same issue here. We cannot any longer use URL. We'll have to make it try of URL. Now if I run this, it says what? Try of user cannot be converted to user. Correct? Because absolutely because this is, this is what now a try of user. And in the two factor authentication, this is user. Now at least I've taken broad steps where I have user encapsulated. I mean wrapped in the container at this point. Right? So now if I go ahead and look at this particular code right here. So I'll just kind of get rid of this and just look at it very closely. Now this is return type is try of user. And the return type of this is try of user. Now this is where we want to chain. We started with this that how can I change this? Right? So interestingly, both are the same types now. One is try with the other is also try both are containers. Can I create a method? Yeah, somehow I create a method. I don't know the name of it yet. Right? I'm going to figure the name out and call it on this particular try itself. Such that because the earlier try is going to hold the user within itself. Right? How about passing the user as a lambda to the next try? Make sense? Yeah. For lack of better name, let's call chain because we have been calling chain. Yeah, all along. So what I'm going to do is try with authenticator login and then chain. The user to the next try. Will that solve the local try variable problem that we were facing for not being final? Yeah, it will. Isn't it? Because now it's become just variable which is, you know, the parameter to the lambda. Fair enough? Now let's try to work out what is the signature of this chain going to be looking like? Yeah, signature of chain is going to look like its user. Yeah, to another try. What does it return URL? Yeah, what is this in Java? A function that takes in a user and returns a try of URL with me so far. Generically speaking, what is this function that takes in T and returns a try of U? Fair enough? Hey, losing me or just let me know. We just taking baby steps here. So chain will look something like chain taking in a function F and what does it return? What's the return type? Try of URL set its return type is try of U. Yeah, fair enough. So that's my signature. What I'm going to do is I'm going to take this signature and I'm going to shove it in and where do I shove it in? Well, we have two polymorphic variants, isn't it? Failure as well as success, right? And you would want to do this in case of failure because if login fails, I want to use this. So first place where I'll put this is out here and look at the implementation. Then we'll have to go in success as well because these are polymorphic variants anyway, and we'll kind of triangulate and reach up to try. What do I do here? Evaluate F. Apply. Oh, sorry. Sorry, my mistake. This has to go in success because it's not about failure. It's about success. Sorry, because I was about to pass and I have the value already. I'll just pass the value and this is what I need to return. Simplest implementation of chain. Now it's quite possible that this application of this function may also cause an explosion. So I'll kind of just wrap this also in a tri-exception E and then what do I do here? Return, failure, except that the failure will be now of U and pass the E. Fair enough, in failure if I have chain what do I do? I've already failed, return this because I'm already in failure. So I'll return this. We could also create, so I'll just kind of find for now just cast it to try a few. Just cast it. And because this is present in success and failure, I'll need to put it out here so as to be available in the base class for polymorphism to work. And I can no longer call it, I can no longer have any implementation. I'll call this abstract and for that reason this class will also become abstract. Let's see this in action now. What I'm going to do is let's take this, put it in here. I'll try to comment this whole block out if it's kind of, and let's get it out of the way. All the comments out of the way and this is going to be now, try of URL, illegal start-up expression, try of URL. What is, oh, oh yeah, thank you. Wow, cannot find, oh yeah, so U is missing, so this is again Java generics. I just have to make sure that Java generics, now it says reuse a variable already defined. Oh yeah, I don't need it any longer because I'm chaining it. Now it says finally try of URL cannot be converted to URL. Right, so we've solved the chaining problem. Now try of URL, obviously the type of this is URL whereas the type of this is try of URL. So for now I just want to kind of get the value out of it and make it work. Yeah, because we've been staying red bar for a long time, though there are no tests. But yeah, so I'm just going to introduce get here to get suck out the value and push it in. So this is simple implementation. Right, so in success if I have to get, what will get be? T get, return the value. Yes, failure, what is failure? Failure never returns, right? So I'll just kind of throw exception. When somebody tries get on failure, I'll throw a runtime exception. Yeah, pretty much failure cannot return. And obviously I need to shove this in here as well. All right, so far this is working. Yeah, we will take care of cases one at a time. Where is this evolve this piece of code slowly? Now that is the failure recovery part is what really you are referring to. Right, so we have. Why am I not saying going to? Why is this message not coming? Maybe not sure. Let me try this. Yeah, somehow the last line is getting clipped. Yes, I just put in done. So if you see, we have returned back to our normal flow, right? The happy path. We've been able to change the functions together, right? And this is what the code now looks like. Now let's take care of, as you said, the unhappy path, right? Somebody said, what about Gmail login, right? If you look at this particular code, right from here to here. Essentially, if I treat this as a function block, right? Catches and catches and this is the code body that I really want to execute. And if this is a function block, what is the input to this exception, right? And it returns what another try block, right? And that to returns what a try of URL. So this is the signature of this would be what try of you. And in Java 8, this is a function that consumes an exception and returns a try of you. And why do we throw from exceptions? Why do we throw exceptions in first place? In a hope or in an expectation that the client can recover from it. That's the real essence of exceptions. But all, I mean, I'm a lot of code bases that we see. People just wrap it and put it in the log or just eat the exception, right? So we, this is what essentially recovering from failure. And if I were to come up with a method name for this, let's call this as recover with, yeah? With another function, yeah? And what does it return? What's the return type of this? It's a try block to try of you. So that is the signature of this particular block. If I take this and this is mind you happening inside failure. So first thing I'll go ahead and do is implement this method inside the failure. Yeah. Just make sure it complies with Java generics. What do I do here now? Return f dot apply. I already have the exception because that's yeah. Hey, with me so far. Just putting in exception. The earlier case was putting in a success value to the to chain it to the next block. Now we are recovering from exception. So we are going to just do this, right? Instead of the input being a value, it's now exception. Fair enough. Now again, like the earlier case, when applying this particular recovery procedure, there could be an exception. Yeah. What do I do? Wrap this in a try and now do what? Return failure of you and pass this exception. Fair enough. Same signature. If I am in success, do I need to recover from success? No. What do I do? I just pass it as it is. I'll say return this and all I have to do is cast this again to a try of you. And obviously these two methods are in the polymorphic variants. I go ahead and put it in the abstract class. And where do I now apply this? So this is before chaining. Yes. And after logging in because if this login failed, I would like to recover with Gmail login. And if that succeeded, I would go ahead and then do the two factor authentication. Makes sense. We cover with an exception comes in E. And I want to now say grab this particular piece of code. Yeah. Grab this piece of code from here. And obviously I need to wrap this in a try because this is also going to throw an exception. So this is how it's going to look like. So I'm just going to comment back all this. And let's try to run this piece of code. Let me throw an exception at this point so that we know we are heading down the recovery path. So I go to the authenticator and throw the exception here and run this code. Yeah. Inside system login. Now it's failing. It's recovering with Gmail login and then it's going inside the two factor. Yeah. Fair enough. I hope I'm not losing anybody. Okay. All right. Now let's focus on the next one. What do we do? We have, yeah, let's look at if Gmail login fails. What do we do? We have to go to login page. And if you notice this particular thing is really the same over here as well. If two factor fails, we have to go to the login page. So in essence, if you view this as a chain of computations and if any of the fails default, go to login page. That's the default handler. It's like the chain of responsibility pattern. Yeah. Where the final guy kind of says, all right. That's the default value now. Yeah. So how do I do this? All I have to do is kind of introduce or else if everything fails or else do this. And if you notice here, login page is a URL which is being constructed and dashboard page is also a URL being constructed in Java. URL construction throws exception. And that's why that kind of shows up here and rears its ugly face in here at the main. Yeah. You don't want to do that. So at this point, I have, I have two options before me. I could inline these variables, right? So in other words, what is this? If I were to talk about or else or else go to login page, right? Make sense or else go to login page. But this login also throws what an exception. So what do I do? Wrap this chap as well in a try with excellent. And that's my supplier. Yeah. Now that I've wrapped this guy in try with essentially what I've done. I've evolved the signature of or else. What's the signature of or else? Or else just takes in another try. That's the signature of or else, right? I take this out. Yeah. And we need that only in failure. And what's the simplest implementation? Return other. Yeah. Take this signature because this is a polymorphic variant. What do I do? Do nothing. Return this again or just kind of cast it to try new. Yeah. And because these are polymorphic variants, I'll go ahead abstract. Yeah. And let's try to get rid of the code which was originally comment back the code. Yeah. And let's try this out. Cannot find symbol. Oh, this is Java generics again coming in the way. I just need to do this new. And yeah, it works. Right. So now let's kind of reflect back what you've really done here. You know, if I look at this code essentially, how are we doing time? 40 minutes remaining. Okay. Okay. Thanks. All this code has now kind of turned into, I'll just reduce the font a little bit to see it here in this fashion. Yeah. So we are saying here essentially try with the sort of time we're done to 15. Sorry. So then what we can do is we are almost through. But just to wrap this up very quickly, we can take questions and we can go to unconference. And yeah. Sure. Okay. So just to, we have evolved to a monad without actually talking about the m word. Yeah. And the two functions that really define monad is chain. Yeah. And if you notice how declarative we've become log in, recover with Gmail log in, chain it to the next function for two factor or else you just have regular log in. Yeah. That's pretty much it. So I want to kind of, I wanted to show you guys how it's, you know, visualizing in terms of pipe, but the slide is up there. But if you see essentially what we have done is we have created these things. Right. We have trying with system log in, we change the next computation, we get the URL. If there is a problem, the red pipe pushes the exceptions across. So that was chaining and then chaining with recovering. I mean, chaining and recovering. And then finally, you know, we have the or else. This is a kind of complex piping or the plumbing that we've done. Yeah. So two minutes monad is just chain plus inject this notion of getting into the monad. Yeah. And then being inside the monad and just doing things. Right. But we, we didn't have time to evolve and get, you know, the get was a side effect that I, I would want to continue. But those of you who are interested can join in the unconference and I can demo that and we can take this further down. Yeah. So questions quickly while I unplug. Yeah. Simplest rate to get rid of. Oh, that's just Java syntax. Can't, can't do much here. You have to change the language. Go to another language. Yeah. So the quest. Okay. Right. So essentially his question is that while I am inside, while I'm declaratively going, I can easily visualize the happy flow. So essentially what is try of tea? It's taking care of all the exceptions and other dirty work that you would have to do. Right. Otherwise, and houses it in the context of try of tea and you have to just declare. Okay. If this happens, do this. If this happens, do that. So essentially you're just focusing on the business. Whereas the side effecting part of catching the exceptions happens within the monad. Yeah. Any other questions? All right. So we can head off and anybody who's interested can join there and I can complete this. Yeah. Thank you.