Spring Cloud Contract (HTTP)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi spring fans in this installment of spring tips we're going to look at how to test first api's microservice is in effect first of all we're gonna build a new service so I'm going to build a service that's going to call the customer service we'll use spring support for building web applications will use JPA and h2 we use the verifier the spring cloud contract verifier and of course just to make my my tour a little easier we're gonna use Lombok which is a compile-time annotation processor well then Jen then generate a new project which we can open up in our IDE so I'll do that now under customer service CD customer service Nautilus open this up all right so now we have a new application and our application you know we should spread the test first right keeping in good test trim practice we should write the test first so let's say that we have a new API and when we call this the customer rest controller test all right so this is a new test we're gonna use the spring boot test framework we're gonna run with the spring runner right this is the spring runner that works with J Unit four and five this is going to be a spring boot test that will work with a mock weather environment so we'll say a mock and I think that's it for now that'll be okay we want to use the mock can BC support and spring spring boots we'll use that as well and that'll allow us to auto wire and mock MVC client here and the mock can be C client we can actually work with to issue requests against the database so we'll say public void should return all customers so we're gonna have an endpoint here that we think will return all customer data right so we can say this mock NB C dot perform mock MVC result matures dot get I'm sorry request mattress mock MVC request mattress builders dot get I'm gonna say we make it post to the to it make it get to the guest you get customers in point and we're going to accept it when to send a content type well we don't actually care so we'll that's fine we're gonna expect certain things back right so I'm going to say a mock MVC result matters that status will be okay no problem and we're going to expect that the content type will be well-known it'll be a media type application JSON utf-8 for example and what else do we want to say we want to say that this throws an exception that'll solve this and I think we should also you know have a have a description about what the shape of the payload should be when it comes back so we're gonna say that we expect the the payloads to match a JSON path so I'm gonna say mark MVC result content dot JSON path and then you know we can even use a JSON matric we can say JSON path like this and that's what we're gonna do is so we're gonna say at dot let's say the first record dot what what do I say when I say ID equals one right we'll say equals one and equals that is not empty value there we go one and we can also say that the first name or it may be the let's just say name okay so the name will be equal to Bob okay or Jane there we go nice and good so we haven't a name there and we have now just we've asserted some basic things about the structure we're assuming that's you know the syntax here means look into the jason that comes back it's gonna be an array this means traverse all the arrays and run a predicate we're gonna dereference the first element that comes back on in the in the array and we're gonna assert that the first record should be jane and that the content that comes back will be of type application JSON so let's run this code to see what we get okay so run run run and of course this is going to fail pretty catastrophic Lee we've written more tests than we need to get to that point but we do know that this is going to fail so now it's our job to implement the production code make sure that this kind of works right and normally in Testament development you'd you should only like write a single test it returns okay then you go back to the production code and you you make it return okay and then it says okay I'm gonna return JSON application J's and then you make sure that returns as you expect and you know you go back and forth but let's let me just skip ahead here a little bit I'm gonna write the test for one sort of what I expect to be the minimum sort of feature set for this end point so let's go back now to the customer risk controller which we don't have right so we're gonna have to go back to our code will go here and we'll say source main Java comm example customer service insert customer rest controller and we'll insert the rest controller like so we'll say at risk controller and we'll have some end points here we're gonna say that we're gonna have an end point that returns customers it's gonna return a collection of customer records so we expect so there's that and already we've gotten into some trouble we need some customer data right so we can say get all customers we need a customer record so let's assume that this is a JPA entity it'll have a primary key long ID at ID at generator value and I'll have a string alright and what did we say in the test the test will the test looks for name that's our name okay so we're gonna expect that to be their string name all right so there we go there's our basic entity now of course this requires Gators and setter so I'll use Lombok to create that for me and there we are okay so we've now got two entities here and now we can we can implement this now we know that we're gonna need to be able to persist data into the database so we should use spring data JPA here we're gonna create a Java class a customer repository alright and this is actually not in a class it's gonna be an interface and the interface well that's enough that's actually enough to get what we know is what we want so now we can inject that repository here private final customer repository and dear from set from the constructor and then return this customer pause for defined all right so we have to actually extend JPA repository for this to work all right very good so very basic interface there and this makes it so that we have declarative data management functionality we provide it out-of-the-box thanks to spring data JPA which means that we can go back to our tests here they test and let's see what happens and of course this is gonna fail as well first of all assuming it works I and I think it should work but yeah basically we expected a certain set of data to be in the results and of course there is no data so what we need to do is to mock out the date access layer which makes sense what we're trying to test here in this layer is our interaction with not with the database but with the rest endpoint we're trying to assert that given a request of a certain shape that we get a response of a certain shape back so let's use the spring boot test frameworks support for mock beans basically we can inject the customer repository but of course spring our boot already sees that we have a real customer posit Ori so what this mock be an annotation says is prepare a mock object using mockito and then let the client that's ask the tester let us prepare a mock object in our test and then replace any pointers to this this this repository in the application context with the mock version that we're gonna configure here right so let's configure it so that it's not just a mock it's actually a stub it'll you know it'll return certain data when asked you know it's gonna follow our protocol so this customer posited it findall then return and win return an ArrayList of customers right so a new customer the first one will be Jane second one will be Bob and there we go okay so we've got some records in the results that come back now we have you know we haven't had to do a lot of extra work here right spring is just smart enough to know to replace the the real thing with this mock version for the specific purposes of this test and that seems that worked so we've got you know it's working as we expect we can also prove a negative by by tampering with a test here we can prove that the test was working by breaking the test just in case you never know so that is working as we expect so good so we're now in a good situation now we've got a service let's go build the client let's go build a client to talk to this service all right so we're going to build a new client here it starts out spring that i/o I'm going to call this customer client and in this case we don't need the JPA support nor do we knew the h2 support but we can use this stubborn er here so we'll use spring cloud contract step runner and otherwise looks fine to me so we'll generate that and that'll give us a new project so we'll go to our downloads directory unzip this extract the files ok customer client open that up and open this up and now the customer client is going to be the client API that client that others can use to talk to that service you know we can have a lot of discussions about how much magic should there be in the code for that and all that but for our purposes let's just let's just build a simple client and make sure that there's no magic in it and then it's a the service itself stands on its own and other languages and other protocols can can use it with impunity but for our purposes let's just do that you know we'll write some code here to make it as simple as possible right so we have a package as usual and we'll build a customer client object okay and in the client object we know that we're gonna have a test so let's go test this we're gonna create create a new test here for the customer client test and we'll have a we'll have intelligence help us with that right synchronizing our code there and so in the test we're gonna use the same mechanisms as before it's gonna be a spring boot test we're gonna run it with the spring runner class this is going to use the customer client application though hopefully for most of your clients you use Auto configuration so that spring boot consumers can just add the library to the past path and the bean will get registered in the application context but for our purposes let's say that we've just got a manual pointer to an application context somewhere and we've got a configuration class so I'm going to define a test that tests our interaction with the customer service ok client should return there we are so throws exception and in the code we're going to need the the customer client so let's inject that here of course private customer client all right not bad so now we say BDD assertion stop then this dot client dot dot what right where's the method to get all customers well that's not gonna work so the first thing we need to do is to create that method right get all customers and we're gonna return a collection of what customer right we need a customer as well so we we need to create that DTO that representation there let's just create it in line all right we can say at data and we'll give it a we know it's a long ID and a private string surname all right so there we go there's our DTO and in order for this to work you know we can return a new ArrayList just for now just to see how much of the test we can get to passed there we go so now it's back to working then we can say that the size is equal to two so let's say that there's two records coming back okay let's see if that works well of course that didn't work right several reasons first of all this application this web application is just added to web application so we need to make sure it doesn't start up on port 8081 as well and the other thing is we don't have this beam configured anyway right this is not registered in application context it's not a component so we need to have that in the configuration here so we can we can go here create a new customer client configuration customer client configuration and we'll move the customer out to its own type as well there we are customer client configuration will live here and we'll register the customer client right all right so return new customer client very good and now we've got a simple service let's let's now try that customer client code again well the test work this time somehow I doubt it but we can try ok that failed again right and this this time it's failing from more realist you know reasonable reasons we're returning zero but it's expecting two so now we need to to actually implement enough meat of this test of this client rather so that we can get what we're trying to get done done right we need the rest template so we can make a call right so there we go and inject that into the codebase and of course this implies that we're going to need a configuration for that rest template so let's create that here we'll say at beam rest template returning new rest template like so and we'll inject the rest template there rest template RT there we are now we're cooking so now we have a rest template and we have the customer client and the client test is going to return some data based on a call to a web service so let's write that code here instead of returning an empty array list we can say this dot this template dot exchange HTTP localhost 8080 forward slash customers right so we know that's going to be nice to be get call and that we're not gonna send any data to the service and we know that we need to tell the rest template what kind of data we want back so we're gonna say well a collection of customer data right PTR equals new parameterize type reference of type collection of customer okay so now that that super type took an implementation gives us everything we need to to then return the data back so we can we can put that in here and do you reference the response so get a response entity with a payload of type collection of customer and then we can then do you reference the body which is here and we're off all right we've got the the payload and everything we're good now there's some discussion there's some argument to be made that we could be using you know Thane or something more succinct in this case but for our purposes it suffices to leave things as they are so now we've got an actual service and we can try this alright let's see one more time we've got an actual client rather we can try this now all right that failed yet again and I think you can guess why there's no service right and this is actually the the problem if you will with microservices in order for us to test this effectively in order for us to effectively test the boundary of this of this client rather I need to have the API so ok right I don't want to actually stand up all my api's each time I want to run tests that would mean that all of my unit tests now become integration tests when I move to the world of micro services that sounds like a non-starter because I'd very quickly end up in a situation where I have to wait 20-30 minutes just to deploy and just to integrate you know my simple client right that that's a non-starter and it gets even worse if you talk about the poor html5 and iPhone and Android developers who have to who would have to in theory deploy the whole system just to be able to test the code that they're writing for the client experiences right so we need to we need to synthesize that if here this is you know we can we can't expect every client of every service to run every other service and all the dependent services just to be able to to go through the continuous integration environment remember the whole point of micro services is to optimize for agility to gain the speed change and if we lose that by giving up our ability to quickly test and get fast feedback then what's the point exactly right we want to make sure we have that fast feedback so okay let's mock out the API and here we can take advantage in the customer client test of wire mock right we can Auto configure wire mock this is part of spring cloud contract and this is great for api's that we don't control right we if we know it's an API that's stable and we don't have the ability to control that service then we can use wire mock to build a fake API for us so we're gonna say so our mocks dub for wire mock dot URL equal to wire mock sorry were mocked I can get okay why mock URL equals to customers and what else did we say the client needs so the client needs it should be get customers some port 8081 let's make it on 8081 we know the service will be on 8081 so i'm gonna configure wire mock to start on port 8081 okay there are and what else do we need we know that the payload that comes back will be will be a collection of customers as JSON right so we're gonna we're customers client is using the rest template and restaurant it's gonna convert the data into a collection of customer entities of type JSON so ID and surname all right all right so let's try this we're gonna now return a response wire mock dot a response and the response dot will have a body and I'll have a status code of type 200 naturally because it's gonna be great and we're gonna have a body and now we could pass in a byte array we can pass in a string you know and this is where it becomes very useful to have the support for auto for testing JSON inside of a spring test dream spring loop test framework here we can inject a object mapper and use that to a great effect to just get some JSON for some customer records okay so if customer customer customers okay so what we're gonna do is we're gonna create an ArrayList arrays dot as lists for these customers and turn that into JSON using this object mapper dot right value is string customer list etc and this of course throws an exception so we'll say throw exception very good so there's our customer list and we're just gonna use that that custom method there to return the data so the body will be JSON for customer and I'm gonna return to customers we know that were expecting what did we say we're expecting well we have one got two records right it only says we need to code two customers so let's say we've got two customers I think we need a constructor for this to be kind of fun so all argument constructor no argument constructor very good and we're gonna pass in a ID one and the first name will be Jane and the second one will be Bob okay so there's our two records and what else do we need we need to I think that's it I think that's actually oh you need we probably need a content type right so with header HTTP headers dot content type media type equals application JSON utf-8 value and that should be it that should be a very simple interaction we should have two records if we run the test again everything should be golden ingredient right very good so now let's be a little bit more demanding let's make sure we're marshalling data back and forth correctly so let's say that the the data we're going to store this in a collection first of all we'll do we reference it and use it as a variable so customers there we go and now we're gonna say collection I say customers dot customers dot iterator dot next dot get ID equals one L right and we're gonna say the first one will be Jane right so you can see that we've got these a very convenient assert J api's these disfluent tests so that's been very convenient here because I'm exploring the API exploring the tests I just hit control space and the test basically write themselves alright looks like things are working as we expect right and so we know that there's two records we know that the first one has the data that we expected to so I have no reason to doubt that the second one wouldn't also have that okay so very good so now we have a client and a service and might be enough you know might be enough why are mock certainly helps us here if it's if that API stays stable then this won't be a big problem will it because we can just use this wire mark stub and we know that we got it right this time so as long as it doesn't change I think we'll be okay the trouble of course is that why not that API is a will change they'll change a lot and when they do change we run the risk of this no longer being valid and additionally the producer may not know that they've broken the experience that certain customers or clients rather have a start decided to become accustomed to that they started to expect so they will happily merely evolve their service and perhaps unnecessarily and accidentally break the the interactions that clients have so this is not ideal for either side we know if there's what we need is some way to sort of catalog in that scenario that interaction and ensure that both sides agree on the definition of that interaction that that scenario and this is what consumer driven contract testing or you know contracts give us right we have a project in in the spring portfolio called spring cloud contract spring cloud contract gives us the ability to describe a scenario this is not a schema let's be very clear about that this is actually and it a sort of documentation of how one client expects to interact with our service so let's go back to our service here and we've got this test that we've written and this is this test asserts how we expect the structure of the of the response to look you know from the producer side but again this we were in the risk of this drifting out of sync with what clients actually expect so let's write a can't let's capture what we expect to happen in a given test in a given interaction today right now all right so I'm gonna use a document directory here when I say test resources contracts and we'll create a new contract which is just a GU VDSL so should we turn all customers boovie and this is a type safe DSL so I'm gonna say contract dot make and we're gonna provide a description should return all customers request is going to have a certain shape so we'll describe that here and the response will have a certain shape so now just to give you kind of give you a little bit of a prelude a little bit of foreshadowing here what we're doing is we're saying that down the line we want a test to be generated for us automatically based on what's in the contents of this movie DSL and that test will be run against our API in the same way that our actual test that we the one that we just toiled over a few minutes ago does right now so that test is going to capture all the same things right it's going to capture how we expect one interaction to work so we're saying that we expect a request that goes to the four slash customers endpoint of type get that has a certain you know it could have a certain collection of headers we expect that kind of request to yield a response that looks like this it's gonna have a status of type 200 it'll have a header maybe of content type right so we can say headers header HTTP headers content type media type the equals application JSON you tip it value and the body will be either a map you know J sent the map that we can be turned into a JSON structure it'll be a literally an object value that we can produce back a list you know almost any number of different things you can even return just a string but in our case I'm okay with just which a collection of maps right so that's the syntax here yes but actually this is a list but what we're doing is we're creating a map we're cutting a list of objects dynamic maps so we can use the goofy syntax here we're gonna say ID 1 L and then surname or name is it let's see what we have here name so I would go to the code they'll be called the name and the first one will be called Jane and we'll create another record ID 2 and name is equal to Bob all right so returning this data this is not actual data it's data that we're expecting for our tests right again and that implies that we're gonna need to act you know do the same sort of work as we did before to mock out the data access repository because this is going to actually call our REST API in the same way that we have done before with the mock MVC client right so we need to make sure that this mock interaction is captured right we need to set this up somewhere so let's go configure the build process to respect these contracts and treat them as tests indeed to generate tests from them and this mechanism is why we say this is a contract because the contract is kept by enforcing on compile on build that the API works as expected right we can't install or deploy our service if these contracts aren't passing and similarly clients won't be able to consume a the the definitions of the contract if they haven't been able to deploy it and install it so we're gonna use a build plugin here called the spring cloud contract plugin right so here we go spring cloud I suppose we need the art group idea first so or explain framework cloud spring cloud contract maven plugin and we need a version we can say 1.1.1 release that's fine and this has a few other bits of configuration the first thing we have to do is configure that it works with extensions sure and the other thing that we need to do is to give it an idea of where to find a base class when I say base class what I mean is we need some class that this dynamic generated tests these dynamically generated tests that were going to create well will extend right so we need some sort of base class that it can extend and in which we can do any kind of sort of test setup so let's create a base class for tests and we'll create a new base class here Java base class here we go so this is our base class and well we'll revisit this in a second but let's make sure we finish our thought here so calm the example dot customer service base class alright so we've got that in place now we need to actually implement that base class that base class will be a spring boot test it'll be run with this spring runner right so we're going to use that and we're going to auto configure mock can BC that's fine actually don't need I don't think we even need to do that we do have to do some setup though don't we we need to set up the the rest assured testing right we're not using standards the the base the tests themselves don't use the standard mock MVC spring a machinist a Prada they use the integration with rest assured so it's not hard to set up would you say you need to say rest assured maka MVC standalone setup you can pass in web application context you can pass in a single controller that should be used or configures you can do all sorts of things here I like to use this timeout standalone set up and then just inject the repository under tests so I'll say private customer rest controller and we'll say this dot customer rest controller and then we need to do the same kind of setup that we did before them the mocking of the data tier right so let's go to the test from before and just borrow this bit here and we're gonna mock out when use a mock bean for the custom repository so we'll go to our base class okay and we'll use a at mock bean private customer repository very good so there's our basic setup our basic tests and now we can run this code one more time or we can't run it actually we have to run the code on the by running the compiler right so we go to the command line here and we'll do maven clean install that's more than enough and in the meantime we don't actually need this test I wrote this test but it turns out it's pointless so let's get rid of that and we'll start that compilation again maven clean install ok so we ran the test we didn't find a we didn't give our test our base class enough information for it to find the spring application context so we go back to our base class here here and we say that the class that it should use is a customer service application dot class go back here again all right looks like it's alright so that's our our contract now we can again we should prove the negative let's go back to the the let's go back to the code here and change Jane to Janet do a maven clean install again and you can see that it failed and if you look at what happened there's a test here that is an error contract verifier test so if you go to that cat contract verifier test or cat target i'll here CD target find i name contract verifier test right and we look at the last one grip java cat script Java okay so cat this one and you can see that it's actually a test that was generated for this contract verify test it extends the base class and each test method corresponds to a contract you can have one or ten or a thousand contracts that describes certain scenarios certain interactions all the stuff that you'd expect to be here is here right so it it's saying that were expecting response to come back that has a status code equal to 200 the headers are equal to the following and we're using JSON path to interrogate the structure of the object that comes back from the service so this is basically testing exactly what we tested before it's exactly the same thing as what we tested in our in our previous test it's just that it's done forth automatically and we get that for free but this would and that would be interesting in of itself because I think this is actually a fair bit easier to understand and read than the test code that I wrote but this is this actually has another much more promising benefit which is that I can now export these these contracts so let's go ahead and fix our test and make sure that things work as we expect okay so Jane will be Jane will do a maven clean install one more time maven clean install all right so now we've installed everything and everything is green you can see here that there's been three installations installing custom service snapshot jar installing customer service snapshot palm and finally this is where it gets interesting installing customer service snapshot stubs jar the stubs that jar is the artifact of the plugin that we're using the maven plugin for spring cloud contract the stub contains a JSON document so if we go here jar xvf customer service stub jar and you can see meta incom example customer service mappings cat should return all customers done JSON this is the native configuration file format for wire mock so we can we can we've encoded we've captured the the contract that you provided that we provided and we've used that to turn it into a wire mock document which we can then feed into well anything that supports wire mark already so we can use that in the client to stand up a fake API that looks and acts like the API that we described in our DSL so let's do that we can go to our client now over here and go back to our build and remember in our build we've already got spring cloud starter contract stub runner so we can go here to our test and all we want to do is use the stub runner to stand up a fake API so we don't need wire mock anymore all right we can actually I mean we could use JSON but we don't actually need that so what we need is auto configured step runner and our job now is to specify to the stub Runner where to find the stub definition that we need in order for us to be able to run this test so let's comment at all the bits we don't need we can say IDs equal and work offline equals true work offline means it's gonna look for the stubs in the local m2 repository not just in maven central or artifactory or whatever other repositories you've got in your environment and the IDs that's the the maven coordinates the maven style coordinates or the Ivy coordinates or whatever you know the the syntax for resolving that particular definition that stub jar that we just created so it's gonna be calm example : customer - service : and then we're supposed to provide a version well of course by definition what we want as a client is to get the latest successfully deployed and produced stub definition so if that test hadn't passed then we wouldn't have been able to run maven clean install you can imagine doing maven clean deploy and a real thing but suffice it to say we have another local man m2 repository and either way whether it's deployed and some other repository a local one we want to make sure that we always have the latest and greatest stub definition because that represents the code that's in production presumably right if I've may even clean deployed my my API then I've hopefully if you're doing continuous delivery also deploy that into production and I want to make sure that my client matches whatever is in production so I'm going to say plus that means the latest one and then I'm gonna tell it to run this service on a port 8081 right and that matches the reality of what we're trying to do here right we're trying to say when the client calls HTTP localhost 8080 one for such customers we want some data to come back alright so that should be okay we don't need this anymore we're no longer trying to serialize the data ourselves now let's just try it let's see what happens so run a customer client test now I'm expecting something to break let's see what we got there we go so the difference the the field in the client is different from the field in the service we have surname in the client and in the real thing in the service we have name so we know that one of these is no longer is not valid it's never been valid but our tests were green you might say you might proclaim and yes they were green but they were they didn't reflect the reality of the situation the only way we could have caught that before was to do a proper integration test and yes we have cloud computing technologies and yeah Cloud Foundry has a great reactive Java client that you can use to with Java code deploy all your applications stand them up scale them etc but even that will take them you know minute right you don't want to you don't wanna be on the hook for that so much better to find this kind of stuff out really really quickly so now let's run this test one more time let's see that that works oh yeah get name okay hey look at that it worked huh so we know that it we know that it worked in catching the integration issues because it wouldn't have succeeded that first time and we know that if the producer changes their API in some way that breaks our client we will capture that because we will always consume the latest and greatest stub definitions right so that is very convenient and this helps me make it this means that it's easy for us to write code that is quick right you can see that test ran in 137 milliseconds it's quick it's concise actually this is less code less cognitive overhead then then the other thing and most importantly it's scalable right so I can actually do this for all of my services all my services can use contracts and in so doing they they I'm not one no longer required as a client to deploy every single service I can just consume the contract and I know that that is as good as the service because it's the same tests that the producer of the service is using to validate its own API so you know the the processor is running the contract and using that as a test harness and reusing the contract as a test harness it's the same contract right now of course there are some of those there's some poor schlubs out there who aren't using spring and I've heard about these I understand that those people exist so there is of course great support for running this - for using these stub definitions outside of a spring environment it's so convenient just to be able to say Auto configure stub Runner and then for the lifetime of your test I have all the stubs in this artifact stood up and exposed for you on a certain port but that said maybe you're an iPhone developer maybe you're an Android developer html5 developer and you don't want to have to learn how to make install and deploy Java services any way at all right so for that you can still take a manage of these stubs we can go to our we can see the stubs we've seen that they're already there right so let's now go to the desktop and you can use what's called the the the stub runner boot jar and I happen to have a version of it downloaded so I'm gonna go to the directory here and I've got stubborn er boot jar right there and the syntax is easy you say Java nice jar step run your boot and you say stub runner dot IDs equals comm that example customer - service plus 8081 and you say stub runner dot work offline equals true and you start it up just as simple as we did it before right so now this should start on port 8081 localhost 8080 81 customers and there's our data our actual data that you know it's being driven by that stub and we can just as long as we know the coordinates and we can pass past that jar around nobody else needs to know anything else they don't need to deploy our database and your services they don't need to wait they don't have to have their own confounded cluster or space or whatever they can just test locally iterate quickly and develop alright it's worth understanding that while we've looked at how to test an API a REST API using spring cloud contract there's a number of other possibilities you can use spring cloud contract to test messaging based microservices using the spring cloud stream or spring integration or camel you can use it to mock out your service registry so imagine in all your spring cloud code where you have the discovery client you've got spring cloud contract based services or stubs that are being referenced by a mock service registry so now you can load balance across you know your services that are actually themselves to stubs you don't have to deploy the real thing so there's a lot of options beyond what we've shown you here and indeed there's a whole other workflow called consumer giving contracts where you actually end up as a client you end up driving the evolution of the API in this case we did that kind of but there's a whole approach that you can see to this so a lot of a lot of benefits to using spring called contracts and with that my friends thanks very much for watching and we'll see you next time you
Info
Channel: SpringDeveloper
Views: 7,153
Rating: undefined out of 5
Keywords: Web Development (Interest), spring, pivotal, Web Application (Industry) Web Application Framework (Software Genre), Java (Programming Language), Spring Framework, Software Developer (Project Role), Java (Software), Weblogic, IBM WebSphere Application Server (Software), IBM WebSphere (Software), WildFly (Software), JBoss (Venture Funded Company), cloud foundry, spring boot, spring cloud, testing, contracts, pact
Id: Ki54FB2B25U
Channel Id: undefined
Length: 42min 19sec (2539 seconds)
Published: Wed Oct 27 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.