KotlinConf 2019: Creating Full-stack Web Apps with Kotlin DSLs by Pamela Hill

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] good afternoon hello so my name is Pamela Hill I'm from a very sunny South Africa which is a little strange to be in a very rainy Copenhagen but we have 11 official languages in South Africa but I'm not going to agree to you in every single one of them but rather just in one in my mind it's the most beautiful one and it's Zulu greeting salut Bona it means I see you you are important and I value you thank you for coming to my talk so my talk today is centered around a project which you might have guessed from the title of my talk is a full stack web app written in cotton and we'll be going high going through how I created this talk layer-by-layer from back to front end so my project is a vision board and it's called life visualizer now according to Wikipedia the source of all truth it is a vision wood is a collage of images and photos and affirmations of one's dreams and desires designed to serve as a source of inspiration and motivation how does it work well let's have a look right so we're going to start by registering a user I just want to see that this is playing pardon Alison that trick that this is thing okay I'll just talk you through it so what we sought but doing is we register a new user and then we go through to a I think it's my planer we go through to a little screen where we can add some some inspirations like you can see over here so then we search for something that's interesting that we want to make our life goals and that would be something like cuddle a cute cat that sounds like a life goal right so I use an API called unsplash to select some or to find some nice images that matches a keyword cat and then I create a little inspiration light you can see it in the middle at the bottom my next inspiration was to see the Northern Lights so what I go ahead and do then is I select the picture I add some tags to it and then I create that inspiration and then I do some filtering on it it was very impressive I'm so sorry you can't see it but this is what completed life visualizer will look like so I want to see the Northern Lights I want to visit Rome in Barcelona and I went to move to Cape Town because I'm from a very small weird town called Pretoria and I also want to meet my boyfriend Shaun's cats and I went to go shark cage diving because that's the thing that people do in Cape Town right so let's have a look at how all those moving parts fit together now starting from the bottom we have a web app written in cotton Jas and it uses the Axios library to connect to some rest services on a Couture server via HTTP and that Couture server connects to that API the unflushed api that provides us with images they're nice and high quality but really free and that cater server uses a kato client just for variety to connect to the API over HTTP the cater server also saves some user data so we save that into an h2 database through the xposed library but the purpose of my talk isn't just to show how to build a full stack web app I could do that but that sounds a little bit boring so my project also has a philosophy behind it and it's the philosophy of beautiful code but that's a pretty vague concept right yeah so would Cunningham a very famous programmer actually made a statement about beautiful code that might clarify what I mean by it he said you can call it beautiful code when the code makes it look like the language was made for the problem and one of the many ways in which Kotlin shines is the way that it allows us to create beautiful code and beautiful DSL so not only are we going to be using we're creating this full stack web app but we're also going to meet and say hi to some really beautiful dear cells along the way I just want to quickly align with everyone everyone pretty sure what the DSL is just show hands you know what it is all is okay that should be everyone just a quick recap it's a domain-specific language internal DSL is written in cotton but it's still a DSL that normal DSL would be sequel and yep sequel or regex whereas a internal DSL is the ones that we're going to be looking at today is written in a general-purpose language but why would we want to use dsls well firstly diesels are declaratives I really focused on describing a problem or was the solution rather than how to get there so they're also super super concise great dia cells can be very readable and some carton is call this fluency reading almost like natural language good dear cells also make it very clear what the original author intended to do so the original developer and that makes it easier to understand and code a data code requirements without introducing some extra bugs and while that's not all there is to maintainability it's a really great place to start so what makes caught in a great language for dsls well cotton helps us and this this was actually presented by Venkat Subramanyam at the last cotton conf so kudos to him some of the language features that support creating those fluent ear cells are the optional semicolon which removes a lot of syntactic noise in fixing functions that improves our rebuild readability not requiring that loss parentheses around our lost lambda argument also removes a lot of syntactic noise operator overloading using conventions which gives us a nice shorthand notation extension functions that make our code more our existing code more fluent and maybe two relatively unknown language features lend us with receivers and the invoke convention just a quick show of hands lambdas with receivers anybody know what that is okay we will going through that quickly because it's actually a very important way of understanding how mostly cells are constructed so my one friend always says she went through years Lando's with receivers she always thinks llamas with hats and I'm like that is the most absurd thing that I've ever heard but okay llamas with hats so Lando's with receivers or lambdas that are executed within the context of a receiver what does that mean well it's a lambda that has a receiver object and the receiver object is inside that method implementation is represented with the this context object but it's always nice to have a look at example said let's have a look at one say that we wanted to create a lander with receiver where we want to determine whether the in where the integer is even and that's what the type would look like we have an interest Sivir we don't take any parameters and return a boolean inside the implementation of this function or Landa the this context object refers to the int receiver and we just do our normal old calculation of the number modular 2 equals to 0 to determine if it's 0 and when we want to call this lambda and we just use the regular old way which is very fancy if you're in Java but for us Carly knows this looks a little bit like an extension function but it's actually a lambda with receiver so on to our next section so we will be going through Kate or exposed and also the color next HTML as DSL and building everything step by step so we start with Couture which is a cotton framework for creating asynchronous servers and clients it's nice an open source but it is created and maintained mostly by JetBrains for cater we use a DSL and in order to create our application behavior and it's also really really easy to set up we'll be looking at how to actually go ahead and set it up but you can either use the IntelliJ plugin or you can use the generator at start catered and I are interesting enough thought works which is has a has a technology radar and Cato actually featured on this radar quite recently under the trial category and it's been slowly making its way from you know a very experimental bigquery of it to something that's trialing so in other words try and use this project on a project can that they can actually handle the risk but it's probably a good bit so this is what they said about Couture I say the flexible it's it incorporates different tools in addition to its lightweight architecture makes Kate or an interesting choice for create for creating restful services so let's have a high-level look at how the Couture application is structured so a caterer application has one or more modules that are user-defined and each module implements a part of the application logic by installing and creating configuring features so a feature has a particular functionality that it does and it does it intercepts some requests and responses and then performs something a little function so examples of features include with indication reaching logging and content negotiation cater supports HTTP 1 2 and also WebSockets and once the request comes in its converted to an application call and that application of call flows through a pipeline of interceptors now this is what the normal interceptor pipeline will actually look like we have a setup phase for preparing the coolants attributes for processing and then a monitoring phase for tracing features where most features are going to intercept the pipeline calls for completing the code the way most features and interceptors that actually complete the cool rule rang and also a fullback phase for handling an unhandled calls so this is how you can set up a project I realize that it's probably not so easily readable I hope it is a little readable but this is what it what the website actually looks like so we'll let's go through step by step so creating the project is easy you can either use the IntelliJ plugin and use it directly inside IntelliJ or you can use the Skype so starting from the top left we select our our build system which can be Gradle or a cradle with a nice cotton DSL I will sound like a chef when I said that a nice Scotland DSL and also Maiden thank you smiling they also can use then we select our server engine which is Nate ejt Tomcat or CIO which is cotton which is curry teens iron something from JetBrains so then we select our Couture version which is currently one point two point four in stable but if you're feeling a little adventurous there's also one point three point zero any beta one after configuring our Gradle we go ahead and select some server features which is going to be something like routing locations which we're going to look at next is a pretty exciting feature that laws us to do reading in a typed way and also reason for JSON serialization because we're going to be using the Cato giant in the Couture server we also use the HTTP client engine and we also use some JSON serialization stuff so let's have a look at how we actually create the application so we need to do two things we need to create the application module and set up the server so because our application is quite small I heard about maybe eight routes will only really have one module which I called life visualizer and if the application is bigger you're going to split up your application into multiple modules that handle separate areas of your application so we create a module using a extension function on application do some feature installations and also do some reading then inside the main function of our application we go ahead and create our server which is based on nettie listening on port 8080 and with our life visualizer application module configured in we start the server it waits for calls to come in tada right so our next task is to actually go ahead and install some features we install the content negotiation feature and also routing so let's start with content negotiation which is going to do the JSON serialization for the app we simply say install with a feature name and then we configure that feature here we're just using saying that we want gisun TV used as our content negotiator routing is automatically installed because we use caterham mostly for routing so we actually only have to configure it so the way that we configure it is by defining some routes and in order to define that route well we just say it's a good call and with a path it's pretty simple right so let's zoom in on okay well let me just tell you what the - it's our the first one we'll get that selected amount of like a sample size of images from unsplash and return that based on some keywords the second route gets a user's specific users inspirations life inspirations and I wish that I could have shown you the demo because that would have terrified a lot but you know the demo gods or whatever you want to call them mmm right so let's have luck zoom in on that first route because that's going to clarify how we do our route configuration okay so we need to get our keywords query parameter from the request so we use the call object to get that but what is this call object and where is it coming from well cool is just a way of representing the requests and responses and it's actually just a extension property on that kind of that route configuration block body so we use the parameters map to get the keywords and then we check what did we get a nice client that sent us something through what did they forget so if the keywords is now we use cool to respond with a bad request response but if the keyword is not no we go ahead and search the unsplash API with our keywords we also then if we get some results we say okay the hcg status is okay and we hand the inspirations through but if we couldn't find anything if I typed in a SDF I would get nothing from unsplash because what is a asdf picture look like anyway so then we would actually go ahead and get a no country will actually respond with no content so this looks okay but it's it can actually get better so let's have a look at your finance that we can actually go ahead and make on this piece of routing code so our first our first refinement is locations and all this manual retrieval of the query in the path parameters can result in quite a lot of boilerplate so it's in order to minimize this boilerplate that we've got in a nice time safe way we can use locations but note that it is still experimental so you're gonna get warnings all over the place and the first thing we need to do install locations it's a typical pattern install configure next we need to define the locations with at location the annotation and we also have our path and we also need to create a data class that is going to hold in will hold all our parameters and things that we want to get from the request and then the last step is to actually go ahead and use that data structure that we just created so we get a specific data class or a specific data structure and and we template that gate with that data structure that we just created and inside that block where we actually go ahead and do the routing we can we can refer to that generic templates as it's which might be a good thing or a bad thing depending on readability but you can use it to get to the keywords and the rest is pretty much the same but we've cleaned up the code significantly our next refinement is ready for a little bit larger than toy server so all these route definitions can quickly get out of hand it it gets pretty long the more redefinitions you actually add so it would be nice if we could split them into separate files and we can so each route is actually an instance of read class and by defining an extension function on route we can go ahead and spit that in its own file and then we just refer to that function from application and then it's it's a really simple change but to me it made a world of difference so let's have a look at how we actually get those images into App so first we have to learn to register with unsplash which provides these amazing photographs and we also need to describe our app to unsplash so that we can get access to an access and a secret key and most of the OPI was put behind some earth security stuff but luckily not for the services that we go we just have to pass on our theater that has the access key so that made it a lot simpler so to retrieve the images from unsplash we're going to use the Kato client and here we can configure it with cio although we could have used Apache or jetty as well and we install a JSON feature we tell it please use Jason and that's about it we do a little bit of extra configuration just to handle the nulls and they escaping a little bit better to search the footers we have to create a suspending function now remember suspending because so we create the suspending function the text in our keywords and returns us a result of inspirational images and it's really important that this is a suspending function because it's a longer in the operation so previously I actually went ahead and read and splashed an /url and also the access key and we're going to use them now so we create our URL and we use HTTP client to initiate the gate call on that URL and we also define a header which I spoke about earlier that does the old stuff with our access key and then we just go ahead and map the results that we get to our internal data structure so in the beginning of my talk I was talking about if occurred so let's think about what we just saw with the Kate or DSL it was beautiful in the first iteration maybe not so much right but in the following iterations the framework and the language actually helped us refactor it to get rid of boilerplate and to also kind of manage complexity a bit more it didn't require a lot of setup and I'm not talking about the project setup I'm talking about the code it literally was just a small application file and that's pretty cool routing was really easy to read and understand so yes I think I think that this DSL was probably quite beautiful so exposed is a sequel library for cotton and once again it was created and it's it's open source but it was created and maintained by jetbrains mostly and expose has a DSL that used specify o database operations which we're going to look at now but it also has a Deo or data access object version that you can use and it supports a lot of different versions a lot of different traditional databases like Postgres and my sequel but for the Android people in here that also have sequel Lite and also h2 which which is what we're going to use here h2 is a little in-memory database so to set up our stuff we need to create we need to do two things we have to first get all the dependencies into our project and here we're saying these please place h2 exposed and Hikari CP in our project as compile time dependencies Hikari CP is used for connection pooling our next step is to create a Hikari datasource the database and set up our table so we have three tables its users for the users inspirations which is for our for saving kind of connecting the users and the inspirational images and also tags so this is what a table definition looks like and it's pure pure cotton it's a singleton object that extends table and inside that table definition we have different columns and they're all represented by vowels the first two are the most interesting the first column is basically ID and it's just a normal character column but it's defined as a primary key the second one user ID is also normal normal character column but is reference is another tables columns so it's a foreign key and we would actually go ahead and create the other two tables similarly now I find a little piece of cotton magic in the middle of my research for this talk and it's this it's called a DB operation and most database operations have to run on the right thread and it should sometimes runs in the transaction as well so this little function makes sure that you're actually running on the right thread for Iyer and also in its own transaction it's really simple but it's actually pretty effective because we use it all over the place so this is how we would go ahead and insert a row into the table remember the table that we just created called Inspirations well it's in order to actually put a user's inspirational image into that table we call insert on that table with a little configuration block that's going to tell us how to alter that that row the it context object refers to the row and the this context object refers to the table so it's maybe not so readable especially maybe the it it might be a little confusing so to take to take into consideration whether it's readable but it is quite concise so here is also we're going to use our little piece of cotton magic we wrap the whole thing in DB transaction which is going to take care of the threading and also the transactions for us so here we just assign all the values to the row and that's all database alteration code let's look at querying some data say that we want to get a specific specific users inspirational images by ID so once again we were with the inspirations table and we use the Select function here we have an interesting little piece of expression code a little sequel like expression that is going to refer to the column first and then the value so inspirations that ID equals ID that reads quite nicely don't you think it reads like the column equals the value it's pretty nice and then we have a collection functions that we use to map the our internal data structure and kind of pass through all the row values to it and then we just make sure that we have just one result what I wanted to point out next or last is really is this DSL beautiful and what I really liked about this but about this DSL is that it was pretty much following sequel very closely which i think is a good thing if you know sequel and I think most developers have seen a little bit of it before so I think that that is good you know it's it's counting a lot and also they use the use of the dissing the it objects the context objects actually can make your code nice and concise but considering some previous talks that we've had I've actually kind of rethought this and thought it could be a good thing it could also not be a good thing you have to evaluate for yourself but what I really liked about this DSL was the little query that we could do and it has exposed has a whole language that you can actually use to define your queries and it's nice and concise and expressive and if and it reads a lot like natural language so yes I think that it is beautiful our last section for the talk is really about building the front end so I used react as a front-end framework because JetBrains provides a wrapper library for react and that was a massive time saver so we'll also be looking at a DSL for creating HTML which is called cotton XHTML and finally I'm going to show you how to use a JavaScript library and kind of wrap it around wrap cotton around it so that we can use it normally and that we're going to use to connects to our kite or servers rest services just a little bit of react background so in react large screens are decomposed into smaller components and this is kind of reminding the when I was attending some of the jetpack compose talks it kind of reminded me of this so our large components are broke up and broken up into medium components which are broken up into smaller components and the larger component or parent creates the smaller component or child so when that child component is created we pass properties down from the parent to the child but the veins it's maybe a button click and the child will flow up so that the events so that the parent will actually know that there has been a vent and it could handle it so in summary the properties flow down but the event slab and this is exactly how yet by compose also structured stuff so to actually set up the project you go ahead and use some NPM modules and that makes it nice and quick so it's first necessary to install the project creator and then you can use that project creator to create your own project we use NPM start which will run the project in the browser and also do some live reloading to create a component in cotton / react we need to do five things first we define properties interface so that is the one where we pass from the parent to the child a couple of properties we define a state interface for all the internal state of the application we create the component finally with templated with those two interfaces we have to create a render method that is compulsory and we're going to use a nice little cuddlin HTML cotton XHTML yourself for that and lastly we create a builder so it's nice and quick for a parent component or another component to go and head and use that component so to create the properties interface I need to extend our props and then we pass through all the properties that we want the parent component to be to stand through to the child now the unfortunately you haven't seen the demo but there is a photo selector component where you can select the image so maybe we have all kinds of different pictures of cats so we select the cat that we liked the most and that will be our little component it will transition to the next component where we actually do the title and the tags and and so on but that is the component that we're going to be looking at and for this component we are going to notify the parent component when a photo has been selected so the parent component actually needs to pass down a callback function so that the child can call it back the state interface we need to in order to actually implement that one we need to extend our state and we list all the variables that will form internal state of that component so in the case of photo selector we're going to have a list of search results of just images based on the keywords that we typed in which in this case is cats to create the component we extend our component and we have our two interfaces that we template with it inside and this is compulsory we need to have a render method it's a scoped function on Boulder but you can also override some lifecycle functions and create your own functions too now in the render method I created so just a little bit bit of background I used the material design web components library and all that I really needed to do was to put some CSS and JavaScript in my project and also a bunch of HTML tags so the reason why do that is because I wanted it to look pretty for you so we wanted to create we okay so the first thing that we need to do is we extend we we have extension function on our builder called render and the first line over here actually just creates a div with two classes and some text and that forms the title of our little page the next one will form the card and at what I wanted to illustrate here is that you can actually go ahead and nest some of those pretty much like HTML but this is not HTML this is definitely definitely cotton because here I'm iterating over some things I'm iterating over those photos in order to make our cards for each photo so to make it as easy as possible to to use that photo select a selector object component we actually have to create a builder for it now each Boulder pretty much looks the same for each component it follows a similar pattern and here we create extension function on our builder we that you pass on all the parameters that you want to actually use as properties so inside the method we use our builders child function and we pass in what we want the component we want to create and also all the properties that we want to assign and we just do the assignment of the parameters and the properties there but maybe you're wondering okay this is nice but I don't want to use react maybe you want to use something else so how do we actually go about using just any old JavaScript library that isn't already wrapped for cotton it's a look so say that we wanted to use Axios which is a library for connecting to just normal rest services over HTTP and we wanted to use that one to connect to the Couture server to get all our user data so the first thing we need to do is use am/pm to install Axios that will make sure that it's nice in the project in in the node modules section we then create some external functions and interfaces so the important thing here is that it's marked with external and that it's gonna mimic what is happening in the JavaScript and then we pretty much use these external interfaces and functions like regular old Kotlin so here we can see that after installation we've got this node module in our project and Axios is actually just a normal little function that we pass in a configuration object and we get a promise of results back so our first step is actually to define those interfaces now here you a little bit on your own you have to look at either the source the source code or the documentation that is associated with whatever JavaScript project you're looking at and then you have to create your little interface normal cuddlin interfaces that mimic the JavaScript equivalents and Mark it with external that's really really important our next step is to have our Axios function it's just a normal function and we just give the fine bits we just actually give the function signature and market external so once again external is really key here we also have to link the in words whatever is in node modules with function so we use the adjacent module notation for that and our last step is just to call that function actually so we it's it's it's pretty much what you would expect it's normal cotton except for one thing and it's we using a JS object to create that little piece of interface that will configure that cool with your l method and the timeout and this is part of the Catlin joyous night race so the rest is pretty much react specific not all that interesting but what's left for us to really consider about this DSL is is it beautiful it follows HTML quite closely and they are very nice Boulder functions for it but it also took the longest it was very laborious and a little bit boring so I would say it's kind of beautiful but maybe not so much it was a lot of work to actually create so maybe and with that thank you bye donkey and remember to write [Applause]
Info
Channel: JetBrainsTV
Views: 4,388
Rating: 4.9058824 out of 5
Keywords: JetBrains, software development, developer tools, programming, developer, kotlin, kotlinconf, kotlinconf 19, Pamela Hill, full-stack web apps, web apps with kotlin, kotlin dsl, dsl, ktor, asynchronous backend, frontend, kotlinx.html
Id: 0wdOI-S29SE
Channel Id: undefined
Length: 40min 28sec (2428 seconds)
Published: Wed Dec 18 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.