Devreal

Modern Web Apps with Play Framework

Event: Silicon Valley Scala Symposium

funconf 2013, James Ward: Modern Play Apps with Play Framework

Recording: funconf 2013, James Ward: Modern Play Apps with Play Framework

all right welcome everyone thanks for coming so this talk is on building modern web applications with play and schola um who here has used play before wow awesome okay so for those of you that have used play um this this may be a little introductory for you but um but at least uh the whole presentation is no slides I'm just going to write some code uh and we can kind of take that where you guys want to go so so I've got a little bit that I'll get through and and then we can go from there um so the to set a little bit of context the the way that we build web applications is changing uh obviously we're doing uh kind of going back to the client server architecture for most of our web applications where we have restful Json services on our server and then we write JavaScript uis or mobile uis on top of those so play supports that um very well and so I wanted to go through first starting out just creating a new application show you how to do that and then showing how we build in play these these new new types of applications that uh have a JavaScript front end for a Json service back in um so that's the tentative agenda uh we'll see how that goes uh if you have questions or or have other things that you want me to cover uh feel free to to raise your hand and and ask those and uh give me feedback as I go so let me dive in and start uh building an app and let me get my screen recording going so uh with play the the typical way to get started with play is to download Play from playf framework. comom you get a zip file and then add the uh the contents that zip file extracted to your hard drive you add that to your path directory so that then you can just run the play command um there's another new way that types safe has been working on to get started building Play application it's called activator uh it's a a way to get started with template applications and start building your applications in a in a local web uh interface local running web interface uh I'm not going to be using activator today usually I use activator but I discovered a bug in activator uh that that would um that would be annoying and so uh so until I get that bug fixed um I'm going to be using the play uh command instead so uh to create a new app play new and I'm going to call this one Foo and then I'm going to make a schala application so there's my uh my app is created so it's in the food directory there we go so um before I open up this app into uh my ID I'm going to use intellig uh I'm going to edit the build configuration file to add a few dependencies that I'll be using later so and I have a cheat sheet on a on a gist so I'm going to try to do most of this uh without using my cheat sheet but um the build file is in project build. schola so this uses SBT plays play uses SBT to do it build we're just talking uh before before I got started about support for other build tools MBE in Gradle uh today we don't have a good way in play to support those other build tools really SBT is the the uh the main build tool for doing play stuff um so this is the spt configuration file I'm going to come in and change my dependencies here add in a couple so I'm going to be using for persistence uh the sorm framework uh Scola om I'll be using web I'll tell you about that in a little bit and uh bootstrap uh Twitter bootstrap so now that I've updated my dependencies what I'm going to do oh and there's one more change I need to make here uh I also need to set the Scola version the swarmm framework doesn't um it doesn't deal well with multiple versions of Scala so I'm going to change the Scola version for this app to be 2101 okay so now I'm going to run play idea this will generate my my ID descriptor files you could also type play Eclipse to generate the eclipse files uh and then I'll be able to open this up in intellig um so so uh the way that I usually do development with play is to use a command line for being able to to uh run the application run the test and then I have I do my code editing in an ID usually until aent um but you can choose however you want a lot of play developers use sublim text or or just regular text editors and I'll show you uh how play makes it easy to use really just a plain old text editor when you're building your application so there we go let's go open it up in intellig so come in here to desktop and go open up Fu so now while that's opening up let's go back here and run the application so when you run a Play application uh you can either do play run or you can do play twidle run the difference between the two is that twidle run watches the file system for changes and on file system change it automatically recompiles uh based on on file system change play run Waits until you hit refresh in your browser to do the recompile and so the time that it takes me the like 400 milliseconds that it takes me to get from from my IDE to my web browser and hit reload uh by the time I usually get there and hit reload the compile changes have already happened so that's why I prefer uh twidle run but uh when I'm on an airplane and battery power is uh is a valuable resource then I use just you run because uh there's certainly a lot more compiling going on if it's watching the file system for changes especially because intellig automatically saves changes all all the time it's like whenever you leave Focus from intellig it saves changes so um okay so now my app is up and running let me go check this out in the browser so Local Host 9000 is the default so first it will compile this application while it's compiling let's go take a look in here at um what the code looks like and let me let me um before let me increase my font size and inell so you can see that little better okay so let me walk through the the the basic parts of this Play application before we dive in and start uh making some changes so first app is the main source directory for this application so uh so this is if you're familiar with like Source main Java or Source main Scola this is a combined Source directory for play this is a default you can change that to be any directory structure that you want but for play the default is app uh I personally like having my skull and Java classes uh source source files in the same directory structure but if you want to separate those out into separate ones you certainly can do that so in app uh I have some some schola source for this application and some uh server site templates I'll walk through that more in a couple minutes and then the comp directory I have my main configuration file uh I'm not going to do anything in this configuration file today but this uses type saap config a library for managing your configuration allows you to change your configuration between a test environment production environment and so on um then I have a comp routes file the comp routes file is where I Define a mapping between an HTTP verb an HTTP path and then the code that actually is going to handle that request so uh this is where play is just a restful framework by default when you define your mappings you're defining them in in a restful way you're defining the verbs explicitly you're defining the past you can do substitution uh value substitution in the past so um so it really puts us close to the H protocol if you're familiar with traditional Java web application development a lot of the web Frameworks try to hide the HTTP protocol from you whereas play gets you working directly with the HTP protocol so if you're building rest back ends it's perfect for that sort of thing um so the routes file is actually compiled uh everywhere that that play can use type safety in a compiler it's going to do that and one of the nice things about this is that I'm going to get compile errors if I screw up the syntax of my routes file so um so let's take a look first at the browser so there's my application my default application up and running uh that's great how that got handled was by uh my browser made a get request to slash and then that was handled by controllers. application. Index right and if I go in here and I make a change to this file let's try to go back well that would be a compile error oh indexing come on inell let's uh there we go so if I make a change to that file is if I hit reload in my browser anytime that there's a compiler play is going to show me that compiler in the browser and it's going to show me the line number it's going to show me the air Message in a really nice way so this is how you don't have to use an ID with a player a lot of people don't because we see the air messages in a really nice way in the browser you only see these air messages when you're in development mode so when you're in production mode your users are not going to see your source code leaking uh out so we don't have you know that kind of security issue um so one of the other nice things about this file being compiled is that uh play compiles also a reverse routing table so this is the forward routing table that play uses to figure out how to route requests but a lot of times in your code you need to reference URLs uh throughout your application if you need to do a redirect or something you need a URL to know what to redirect to and the way that I used to do this is have strings that contained my URLs and I change change routing information in one place and then forget to change it in the strings and so uh that obviously is it results in regressions in uh in applications and I've experienced this personally it's not very fun so what play does to avoid that is to actually compile the the forward routing table into a reverse routing table so now in my code whenever I need to specify a route I actually use a compiled class that's derived from this uh so that if I refactor my routes it's automatically going to be reflected throughout my application um the routing syntax is is pretty flexible you can do uh you can do substitutions in here this would take everything uh through the end of the line you can also do U just a single uh part of the path substitution you can do Rex uh so a number of different things here and of course of course you can do different uh all the different verbs as well so we'll see that in a couple minutes but before I go on uh any questions about the the routing to tax inl one thing about the the routing is that this is the default routing mechanism in play but there's an easy way to override routing and do your own custom routing as well so if you don't want to use plays routing syntax there's a couple other projects out there there's play Navigator there's one that takes the ja RS annotations for doing routing and uses that instead of this routing configur uh this routing file so up to you how you ultimately do routing but this is the the default syntax yeah so if I want to do some client side routing and I just want to have them um like I have a one page app y can I use some like like a back router on top of this yeah definitely yeah so there's a few different ways to to handle that one of the ways is that uh one of one of the things that play compiles when it compiles the routes file is it compiles a reverse routing table for JavaScript so this will actually create a JavaScript file that will contain all the reverse routing information into it and so then you use that routing table to to hook into backbones uh routing or to to use we use knockout for activator uh so we build all on top of that JavaScript reverse routing table um that's one way to do it there's uh there's also uh if you're using web jars there support for requir JS and required JS will automatically use the reverse routing table and uh automatically set up the the the required JS information so that you can uh just use required JS and not have to worry about any paths on your system so so yeah so there's definitely a lot of different ways to to handle that but it works well with with backbone Knockouts uh all the the the kind of modern routing client side routing systems yeah yeah go ahead uh if you put less files in the assets directory they should build automatically right uh I'll get to that yep yeah yeah but but yeah there's the asset compiler that I'll cover in a few minutes en um so the yeah so there's a few different ways to do that if I wanted to run this application in in production mode from the command line I would type play start instead of play run that's that's one way to do it but if you're creating like a distribution to put on a server uh it's a different way to to start the application yeah uh and then you can also specify a different configuration file to you to run play Under from the command you can say play minus D config file equals give it a different config file and then say run that's okay so that's the routing syntax uh let's go take a a little bit deeper look at what's actually going on here so so I'm uh I'm routing this request that's great uh to that controllers. application uh. index so here's that schola class that's doing that it extends controller just to bring in some convenience methods you don't have to do that if you don't want to and then I have my My Method here index which creates an action and action is the thing that's going to return the response and so in this case the response that I'm returning is okay which means status code 200 if I wanted to get a 404 it would be not found um and then what's actually being returned in the response body is what I'm passing in here so this is a server site template we'll take a look at how that's generated in a minute but one of the things I want to show you is that if we take a look at this string on the page let's go refresh this you'll see that this string is coming in here your your new application is ready so if we change this string so say hello world and just save that so as soon as I save that file uh play is going to automatically recompile that and now we see the change there so this is the workflow with play you don't have to rebuild War files redeploy War files restart Tomcat you just hit refresh in your browser and you see your changes um so that also works for Java I'm using Scola here but um but the same thing is true for for for Java okay so I'm using a server side template so in uh a views package you'll see that there's an index. Scola HTML and this file is a serers side template in play uh serers side templates in a modern web application aren't uh very oftenly used the main reason I'm using them here is one it's the the default and then another one is uh I'll show you another file in a second um but I I'm using server side templating to get the routing information for uh the the assets that I need for the client side So This Server site template uh it's written in Scola it's a Scola HTML combined uh thing it's the default templating language in play is Scola with HTML you can swap that out for any other templating language uh Scola makes a pretty good templating language in our case because it's type safe uh and it's a a pretty simple Syntax for being able to to do composition functional composition of templates so uh first the the first line here is the parameter that this template takes and then the second line is another template that I'm going to compose into this one so what's actually happening is that play has a template compiler that's compiling all of the the templates that I have down into Scola functions and then I can compose together those Scola functions and use those Scola functions just like I would any other any other function so app main is calling the main template so you'll see that this template takes two parameters there's a string and then a a Content block and then this is the main body of my page right but it's taking that content block and putting it into the body part of that page so the first uh the the parameters here this is the first parameter and then this is the second parameter so in this case what's actually being rendered in this page is the play to welcome message uh this is another server side template that's actually included in play to render the documentation and render that first page that we are seeing so we can come in and and make a change to this let's say that we don't want to see that we just want to see the message parameter there on the page we can make a change and just like before play is going to recompile that template and I just hit refresh and see that change okay um so that's the the server site templates any questions on those before we go on okay um so we've got our templates there's a few other things I want to point out here uh public is the directory for static assets uh what really what happens in this case with play is that the static assets go into jar files essentially and so this becomes something that's available in the class path and then play static asset uh Handler actually pulls files out of the class path um so uh so that's how we do static assets and flp then there's a test directory here and the test directory contains my tests obviously it's a combined directory structure so instead of source test Java Source test Scola we combine them into just a test directory you can of course override that change that to be whatever you want but the default is just test uh I'm not going to show the testing support too much today but play testing support uh is pretty extensive it allows you to test your routes directly test your controllers directly test your templates directly uh that's one of the nice things about using compiled templates is now I can test actually write a test against a compiled template uh you can also use selenium you can start up an actual play server and test that with actual HTTP calls so lots of different levels of doing testing in play uh the way to run tests is to let's go over here if I type play test this will just run the test once usually when I'm developing a Play application I run with play twiddle test and that twiddle says keep that test session open and whenever the test whenever any Source or test code changes then recompile and rerun the test and so uh so I always usually have a twiddle run window and a twiddle test window and if I want to see my test output then I just go uh check it out it's going to run automatically and my one of my tests is now failing because uh it was my test is looking for your new application is ready and I changed that string to hello world so um so anyways so that's the the testing support any questions about the testing support before we gone yeah so can that integ with SBD test or so yeah uh good question so the play command all that it really is doing is wrapping SVT so everything that I'm doing with play something it's really just SBT and so running play test is the same thing as running SBT test um so it's it the reason why play has this wrapper on top of SBT is because it applies some additional SBT settings for you that's really all that it's doing um but you could also just runbt directly on this project because really at the end of the day it's just SBT ni yeah yeah all so I'm a scholar and a and a p newbie so a newbie question yeah can can you swap test Frameworks around like something like Spec R spec yeah good question so uh play supports anything with a junit interface just like SBT does uh because that's how we run the test is through SBT so anything that has a junit interface so the default testing in play is specs two for schola and junit for Java but you can easily put in Scala test or put in any anything that that complies to the junit interface for testing thank you yeah and you just drop those tests in the test directory and and run your test and you're good yeah good question other questions before we dive more into the modern web app side okay all right so that's your that's your basic primer uh to getting started with play um so now I want to uh take this a bit further and start building up more of a modern application to show you the different pieces uh that play supports for doing that so first what I want to do is create uh a model uh we have to have some some data to play with so I'm going to create a new model so we come in and create a new scholar class this is going to be models

bar whoops and that's not exactly what I wanted to call it that's okay doesn't well but I I get really anal about naming stuff did I just copy and paste something into a file we'll see if that screws up something um let's one sec models where' It Go oh gosh totally screwed that up okay let's try this one more time new scholar class models. bar there we go okay so what I'm going to do is create first a case class so case class bar and uh what this app is going to do is store my favorite list of bars and so I just need a name property here on each bar it's a pretty basic data model for this one and then I'm also going to do some Json serialization so let me show you how we set up the Json serializers and der serializers in play in um play Java you don't have to set up the serializers and deserializers uh because it uses Jackson and does reflection in Scala we want we want to avoid reflection and have uh the Jason part of play is is really powerful but we do have to create the Jason parsers and uh and sterilizers and deral so to do that I'm going to create an object called bar and I'm going to create in here an implicit uh vow that's going to be my rights the rights is what will create a Jason string from an object so what I do the easy way to do this is let's first import that thing I'm going to create a json. wrs oops we go okay adjacent wrs of bar this is using this is a new feature in play 2.1 where uh in play 20 I had to explicitly create the actual serializers and deserializers it was a lot of boiler plate code uh wasn't very fun to write so now in in play 21 we're actually using uh macros and Scala to be able to generate that boiler plate for you so if if you have a straight forward uh serialization and deserialization you can just say create the create the adjacent rights of this object and a macro is actually going to fill that in for you you can also explicitly Define your your serialization and der serialization so that's um the easy way to do that let's create another one here uh that's going to be the reads so the reads are going to be able to parse ajason string into a bar and again I'm going to use the macro to be able to do that okay so that's that's a super simple way to do Json uh there's like like probably 40 pages of documentation in the play documentation about how to do uh how to do Jason and all the different Json features and Jason uh structur traversals and uh and Jason uh there's something cool called Jason Coast to Coast so uh this is a pretty cool concept where if you have Jason coming from a backend data store whether that's through a web service or whether that's uh mongod DB or something like that you don't need to have intermediary objects that you're transforming that Jason into and then and then transforming out out into some other format Jason Coast to Coast just allows you to to work with Rod Jason in a really nice scholar DSL to be able to do Json Transformations and combine two different Json objects into one object with uh different fields excluded so there's some really powerful things in the the play Jason schola stuff um I'm going to stick with the basics today um but if you have any specific questions about play Jason um I could try to answer those any questions about play Jason yeah oh thank you yeah it's always good to have H massive pair programming going on when I'm live coding thank you questions about play Jason where we going okay so we've got our our companion object there that will do our Json serialization and der serialization uh I'm also going to create an object that will use swarm to do persistence uh so to do this I'm going to create a new object called uh DB and this uh extends um instance inance there we go and then this takes some parameters so the first parameter is the entities that I want to be able to work with in swarmm so this will be a sequence of entity of bar let go import that okay so that's the first parameter there we go there it is okay uh then I need the connection string usually I would pull this out of the application comp file uh at runtime right parse the configuration and use the configuration here but I'm just going to do it the easy way and put in here the the URL directly so I'm going to use an inmemory database for this one so that's my connection string to that database so that's storm framework pretty easy to set up so um you could also use any kind of persistence framework that you want uh with play Scala the default persistence framework is called anorm anorm stands for anorm is not an omm uh so it's great because you can work directly with the the jdbc um structures and write your own parsers for parsing rows and uh it's it's just a bit more powerful but it's a bit more verbose than I want to spend time on today so that's why I chose uh chose to use sorm instead there's a number of other persistence Technologies out there uh relational persistence there's if you're not doing relational if you're doing you get into some really interesting things around uh there's a plugin for play called reactive which is a fully async and non-blocking driver for uh so there's some pretty cool stuff uh out there for for doing persistence in all sorts of different ways but today I'm going to use storm because that's that's an easy one okay so I've got my my bar object any questions about this before I go on okay so the next thing we need to do is create some controller methods that will allow us to to add a new bar and to uh to fetch the list of bars out so first let's write the addar one so I'll just call this uh addar so this will be an action but this action is going to parse Jason so I can tell it the parser to use so I'm going to say par. Json okay so you can tell uh by default play we'll just use kind of the generic body parser uh but if you explicitly set a body parser then it makes it easier to uh you don't have to to in your code say which which uh body type to use it's automatically just going to throw an air uh if if it can't parse the the request body okay so what I'm going to do is I need to get my bar out of the the request uh body so let's create a new bar and what I need to do is is get the request bodies so to do that and add the request here and then I'm going to say request. body you'll see that that is a JS value is the type of that the reason why it's a JS value in this case is because I set the body parser to be uh to be Json okay then I need to take this this uh object and I need to parse it into a bar actual bar object so I just say as bar and let's go import that there we go and so now uh that bar will be an actual bar uh instance of that bar case class right but what I really want to do is I want to save this new bar into the database so to do that what I'm going to do is do DB that's my that database object that I created so let's go import that and I'm I'm going to say save this thing and that's it so now that bar is actually going to be a uh the way that storm works is that it gives me back a new uh an object that is not just a bar case class it's a bar withd persisted and the withd persisted adds an ID field to that object so pretty cool way to to do that but now that's going to be um that's going to be my my bar uh my saved bar file that should be should have been saved in the database okay so now what I want to do is return a response back to the user and in this case there's a lot of different things I could do here I could do a redirect or just return a okay 200 response but in this case I'm going to return the actual bar that was created back to the user so um I don't really need to do it this way but I want to show you how we do the Json serialization so I'm going to do uh Json and let's import that do2 Json whoops to Json and then I'm going to give it the thing to serialize and that's a bar there we go so now automatically what that'll do is it'll it'll look for uh something that can serialize a bar into Json and because I'm using the companion object that has that implicit rights now it's going to be able to find the serializer that it needs to be able to turn that bar object into the Json the uh because I'm because the response uh or the output of two Json let's take a look is actually a JS value uh play will know hey uh oh you're giving this thing this okay you're giving in a JS value so it's automatically going to set the content type and the response to the to be application Json so that happens for us automatically one of the other things to point out about this is that um often times what we want to do is return a different content type based on what the user has asked for so if a if a browser is making a request then the user the accepts header what the user is asking for uh will be HTML and so we may want to return an HTML representation of this object rather than the Json representation so play uh 2.1 now has a way where you can use uh a match on the the request accept header and and then return a different format pretty easily so pretty nice uh feature if you want to be able to handle different content types in these methods okay so that's the ad method any questions about that before I go on yeah good question so um this obviously is assuming that we're never going to get errors which is a bad assumption uh but I believe that db. saave uh will either throw an exception or or there's something on the width persisted that will tell us whether or not that actually did save uh so we would obviously have to check that and then if that didn't work then instead of returning okay we'd return internal server air with some air message back out to the user um so we could certainly do that there's there's a number of different ways to handle the failure uh depending on what framework you're using a lot of times when we do asynchronous programming in play uh we handle the failure at the future level so if the the future doesn't uh completes with an error then we then we handle that return a nice airor message back to the user um so there's lots of different ways to do it but in this case there's probably something in swarm that would that we would key off of to know that there was a problem saving in Futures so um relational databases most of them don't have a way to do async non- blockin requests to them so in this case there's we could wrap this up into a future but it doesn't really make a whole lot of sense because we're going to be blocking on talking to the database anyways when we get into reactive which is an async and non-blocking way then something like save would not return a a response immediately it would return a future of the actual object to be saved and then we'd have to set up uh a way to handle the the complete event on the on that future so um so yeah this is assuming that we're doing all blocking things here uh because relational databases we essentially have to be blocking but but when we get to reactive we certainly could be use Futures and be asyn non blocking throughout the whole thing play has a way to also have the request handlers the controller handlers also be async and nonblocking uh so the way that we would do that is if we want this method to be uh async and nonblocking we'd say async like this and then we no longer can return an actual result we have to return a future of a result so I could you know create a future around this thing but uh so but underneath the covers this is actually working the same way as as before um because there's actually nothing really asynchronous about this but um but so you certainly in play can tell your controllers that they are async and return a future of a response rather than the response but it it won't work it's using this will this definitely works yeah so so if I go reload um execution context let's go import that thing I'm not going to uh spend time on that but but it certainly will work this is this is actually exactly what play does underneath the covers but in this case we don't need to have the additional stuff there because we're not actually doing anything asynchronous in this case yeah okay let's continue on let me go uh good question so uh plays built on on uh Java nio and NTI is the implementation and so that allows you to not have a thread per connection so what technically would happen if we were doing something async and non block in the request would come into the server the server would go off and and do something but in the time that we're waiting to send the response back out to the user we're going to take that thread that you normally have to keep allocated we're going to give it to somebody else to let you know some other request be handled or whatever and then as soon as the future completes we're using all Scola futures for all this soon as the future completes then we'll get a thread back and send the response back to the user so it's all built on Java and IO we also have in place support for websockets which is also built on Futures and async and non block and netti and Java nio so so from Place perspective it doesn't matter if it's a regular request or if it's a websocket or a comment Channel or whatever it's all async and non blocking underneath the covers got okay so let's let's keep moving here so next I want to create a method that will uh that will return the list of bars so say def um get bars and we'll create an action and now what I want to do is get my list of bars out of the database so create a new valve called bars and this will be db. um query I'm going to query for my bars and get it to uh fetch just all of them so there we'll get all the bars bars out and now I'm going to return a Jason response so Jason to Jason and give it my bars there we go okay so that's all I need for my controller to be able to do add and uh get all obviously very simple not full not the full rest scheme with you know delete and update and those sorts of things but um but when it's not too hard to add the rest of those so next thing I need to do is add routes in to define the mapping the URL mapping to these so first let's do a get Handler for/ bars and that's going to go to controllers. application

addar and then let's do another one that's going to get the bars so we'll come in and make up add bar shouldn't be a get should be a post there we go so post to slash bars is going to call Adar and then a get two slash bars is going to call uh git bars uh if you're doing rful style stuff the way that plays routing syntax is set up where where I have to define a new line for each of the different methods uh becomes a bit cumbersome in rest so there is a way where you can actually create uh a you use a different syntax you use like minus greater than to set up some like a rest controller that would have the typical rest methods on it and then you'd be able to map all of the the uh all the uh HTP verbs that are needed to that so there is a Syntax for doing that um but it's not integrated that syntax isn't fully integrated into play yet uh there's some blog posts on how to do it uh out there and it's something that we're looking at integrating uh just as a first class citizen into into the uh play okay so that's our routing syntax so if we go try this out if I go to SL bars then what we should see once we get a database created is very exciting an empty array from Json so that's a Json array that has no objects in it I haven't created any bars yet so great so now I have my backend services that I'm going to use to now build a frontend application on so um so let me go on to the next part where now let's create the actual front end to this application so first let let me go into my index. sc. HTML and the UI that I want to display and I'm actually going to copy and paste some of this to save a little bit of time here UI that I want to display is just going to be uh this form that allows me to add a bar and then a unordered list that's going to display my list of bars so I'm still writing my uh I could be using some client side uh templating language in this case I don't I don't need that I'm just using uh just uh in the base HTML page I'm I'm uh rendering that HTML okay so I've got that then what we need is the JavaScript that will uh that will actually produce the actual interaction on this page so play has a asset compiler built into it that can compile copy script into JavaScript it can compile uh JavaScript uh so basically just syntax check JavaScript it can compile less into CSS and then you can also plug additional asset compilers into it uh so I'm going to create the actual JavaScript in cycript so let me create a new package here the package is assets. javascripts is the directory that play keys off of to compile both copy script and JavaScript so in here I'm going to create a new file called index. Cofe and then again I'm going to cheat and just copy and paste the the client side I'll tell you what uh what this is all doing so first I have a git bars function uh all that it does is make a get request to/ bars which should give me my Json data with the list of bars and then it iterates through each of those and puts each of those items into that UL uh that I defined in HTML so there's some jQuery stuff there obviously there's a few um ways that this could be better one is that I'm hardcoding the URL SL bars I should be using the reverse routing table to do that there is a way with play as as I was saying earlier to do the JavaScript reverse routing table and pull that in just takes a couple other steps uh and then the other thing is I should be using some client side templating uh to do this instead of uh instead of you know doing jQuery Dom manipulation to to render the page okay so then when the page loads I fetch the bars and then I set up an event handler on the form that's in the HTML so when the form is submitted what I do is I assemble my request to the server which goes to uh goes to the the URL is SL bars it's defined actually on the form I assemble my Json and then on success I just refresh refresh my list of bars and then turn the um input value to back to nothing okay so that's the client side of my application written in copy script so let me show you how we bring that into the actual page so if I go uh to my HTML page here and I want to now pull that that uh that compiled file into my page the way that I do it is I say I'm going to load in index. min. JS index. min.js doesn't actually exist anywhere in my source code but this is what play is actually doing is it's taking that copy script it's compiling it down into a Javascript file it puts that

JS file into the class path so the static asset controller can get to it and then it also Min creates a minified version of that Javascript file and also puts that in the class path so that the static asset controller can get to it okay so let's give it a try let's go see if it everything works as it expected so got to go to the actual app here so there we go there's our beautiful form to uh create new bars so let's go create a new bar and cross our fingers there we go yay so I'm adding bars so what's happening is it's listening for the form submit the JavaScript is listening for the form submit making the the host request to the server sending it as uh the Json string up to the server that's saving to the database and then uh the response should contain the the serialized Json that I added to the database but then I'm essentially ignoring that and then just refreshing the list of bars so so if I hit reload right just loading up that that uh list of bars if I go now to back to SL bars now I see my serialize Json for those objects so okay so that's my that's my functional application but um have a couple minutes left to make it look a little bit prettier and I want to show you some web jar stuff but before I go into that any questions about how the asset compiler works and that stuff yeah go ahead yep yeah so so if we come in here and we change this to index.js that's the non-minified version and it should still work the exact same way um usually what people will do is they'll wrap that uh in the server side template where I'm saying load in index. min.js uh they'll wrap that in a function call that based on a configuration parameter will say whether to use the minified versions or the the non-minified vers versions depending on if I'm in development or production and then the other thing that you can do is is hook this all into required JS play has support for required JS and so you can also uh just do this all through required GS and let required GS manage that for you as well so so a number of different ways to to handle that depending on what you want to do yeah you were saying about the less files would they end up in the same place so you'd be yeah oh yeah so let me show you that so um so the way where I would put less files is in assets. stylesheets and then those would be loaded in the same way that I'm loading in the JavaScript uh right now I'm loading in a CSS file that's main.css which comes from my public directory you'll see down here that's main.css for my public directory if I had instead created a less file in asset in app assets stylesheets and named it main. l then I would actually load this in the same way I'd have to remove the the one that's already there but it end up in your uh main style sheets directory or you don't actually see the compiled version they somewhere in the like SBT Target directory somewhere so you don't actually see those uh directly uh you uh but they're available through this uh the static asset controller in play the assets controller in play okay is there any way to get them though if you want these so you can either get them through your browser like if you go to um let me show you how that routing is set up so in the routes file we have this mapping that says map request for SL asset SL something to the static asset controller so I could go in my browser and say Local Host SL let me show you localhost SL asset SL stylesheets slash uh main.css and actually this file's empty so uh so not nothing in there let me go make a change to it um body padding top 50 pixels okay and hit refresh so so you can you can either get to those through your browser or you could go find the compiled files that are in the Target directory that play is actually serving that file from so you could do it either way can I see that that configuration real quick for the uh the uh the routes yeah the routes yeah so this is in a in a Play application when you create a new Play application it automatically will have this this route syntax in it to go to the static asset controller but you can set up your own router your own routing for static assets how I'll show you another way that you do it with something called Web jars right now so the next to in is in basically 7 minutes so if you can wrap up in a couple minutes if you guys want to stay here stay here uh the next Talk starts 11 sharp so basically if you ask more question for James you can ask him in the brakes uh and then basically use this opportunity to change room if you need to okay so we don't have a break between sessions um so we're not going to have time to go through the web driver stuff uh but if you go through uh there's a few different ways you could learn about the next step which is to set up your client side dependencies for your application called Web jars uh if you want to learn more about that just go to web jars. org it's a way to pull in client side dependencies into your application um but yeah so that's that's how we build modern web apps with play was useful