 Okay. Hi everyone. Thanks for coming down here. So my name is Franz, I'm ending just to introduce a bit about myself. So today I'm going to share with you how to build a data API with GraphQL and Spring. So above myself. So I'm right now working at DBS as a solution architect. And before coming to Singapore I worked in United States for several years. And I also studied and graduated from Stanford University. So just to get started. So to build this data API for the demo today we are going to use two libraries. The first one is GraphQL and Java. And the second one is Spring. So just to get a sense of how many of you know Spring, can I get as many of you as Spring before? Okay. So we are using Spring mostly for booting the application. The logic of building the API itself will be in GraphQL Java. So if you don't know much about Spring that's okay. But we just use it to create the endpoint for the API. And after that all the logic will be in Java with the GraphQL library. Okay. So next I'm going to explain the difference between the REST API versus GraphQL API. So in the REST API someone will call get on the resource URL. So for example in this case we are calling get on a person. So we have a resource called person and we want to get more info about that person. And then we can pass in the sub selection which is in this case is the ID of the person. So we want to get the person whose ID is equal to 1. And then the REST API is going to return the data about that person. So in this case for example that's the first name that's last name it has age. So it may have other fields. It could have 100 other fields. Email, age, shoe size and whatsoever it will be written. All the information will be written. So now compare with the GraphQL. So in the GraphQL we do a post on a certain URL. In this case you just say post on the URL called query. And in this on the post body we are giving the structure of the response. What the format and what is the structure of the response we want to see. So in this case we want to see only first name and age. So we specify those first name and age. And in this case also I want to point out that we give a parameter at humans ID equal to 1. So in this case we cannot filter in. We want to see only the person whose ID equal to 1. And the response for this is the same as before similar in the JSON format we have a person and we have the first name and age. So because the client is asking only those two fields first name and age the server will return only those two fields. So they are not going to see any other fields. So it's safe bandwidth, it's safe resource, it's safe time. So those are the main two difference between the REST API and the GraphQL API. So the next I mentioned before in the beginning the topic we are going to build a data API. So what is a data API? So a data API is a single API to access all the data that we have. So the assumption here we have the data in a multiple data source. We have the data can be in Oracle database, can be in the NoSQL database, can be even in file system can be in Hadoop. So the data are spread out in all multiple data source. And we also assume that some kind of a metadata catalog is available. So the client is able to see what kind of data is available for them to retrieve. And the last one, we assume the client wants to join across data source. They may want to join from maybe the employee information from Oracle join with the partner information from file system from Hadoop whatsoever. So it can be joined between multiple data source. We want to have only a single API that can do this joining across multiple data source. So this is the goal. We want to build this data API. So now why GraphQL? Why we want to use GraphQL to build this kind of API? So the first one, GraphQL can fetch only the needed fields. So as I mentioned we want only the first name and age. We suffered return only the first name and age. So this is for API is important because the API can be used by multiple client, multiple application. Different application has different needs. I want to show the last name maybe different application doesn't need to show that. So this is important to be able to specify what field they need to retrieve. And the second reason is the ability to pass arguments to field. This is useful for filtering for example. We can pass ID equal to one for a person. So it means that we can filter only a person whose ID equal to one. Another useful case is for example the dip. We want to return some field of dip. Different client has different formats. Some client want year, month and dip. Some client want dip, month and year. So there are any other format. They can pass it to the API. I want the dip in this format. The server can return the dip according to what the client wants. So we can customize the fields how it looks like. We can pass a filter. So this is the second reason why we use GraphQL. And the third one, it becomes the filterization layer for multiple data source. So as I mentioned before, we can have multiple data source. We have a database. We have no SQL. We have a file system. And the GraphQL data API, it can become the layer, abstraction layer to filterize the multiple data source. The client does not need to know what is behind in the back end. They just need to know the API is available. They can retrieve employee. They can retrieve department. But on the line it can be multiple data source. We can take in more detail how we can do that in GraphQL. But this is the reason why we use GraphQL. Okay, so now I'm going to explain how to use GraphQL. Basically, two steps. The first one is we need to define the schema. And then the second one, we execute the query against the schema. So now for the defining schema, there are two ways of defining the schema using the GraphQL Java. We can do it programmatically using Java code. So we have to run the Java code to write the schema. It's a bit more robust, we can see. But it's a bit more flexible also. The second way is using a schema definition or all ideal interface definition language. This one is easier. This one is cleaner. This is the recommended way of creating the schema. The first one is more powerful because you can use Java so you can create the schema on the fly, run time. So you can have a while, you can have if, you can dynamically create the schema. But the second one for general purpose application using a schema definition is more simpler. So I show you the first for one, how to create the schema using a Java code. So in here, we want to create a new object type for person. Sorry. So we want to create a new object type for person. So we name the object person and we add a new field. So we have new field definition. The field is first name of a type string and then we do a build. So this is a building an object of person that has the first name as an attribute of type string. The second way doing the same thing, we just type, we just create a type person, open bracket, close bracket and the first name is string. So just two things achieve the same thing in creating the new object type. But this one is more clear, more easier to write. Okay. So after we define the schema, I explain a bit about the data feature. So this is the reason why we can virtualize access to the multiple data source behind the scene. What is data feature? Data feature, basically it provides the data for a field. If we don't specify anything for a field, by default it will use something called property data feature. Property data feature will try to fetch data. If it's a Java object pojo, it will call the getter of that pojo. If it's a map, it will call the map.get to get the value for that particular field. So for example, if a person has a first name, then it will call get first name. If it's a map, then it will do a get of the property name. If it's the first name, it will obtain the value. So if we don't specify anything by default, it will use the property data feature. But we can also specify a custom data feature which the implementation can actually fetch the data from any data source. So if you have the data in Mongo, we've write it the custom data feature to fetch the data from Mongo. In Oracle, use Oracle GDBC to fetch the data. So this is how we can make the API to join across multiple data source. So I'll show some example how can we do this to create a custom data feature. Okay. So next, this is how we create the schema using the GraphQL Java. So the first line, we have the schema definition file. I name it person.graphqls. So we just need to load the schema into a schema file. Into a file. And then the next step is to create something called type definition registry by using the schema parser, new schema parser. And then we parse the schema file. So this is all provided by the GraphQL library. We don't need to write it. So once we have this, we have something called type registry. And the next step is to build the runtime wiring. So we have runtime wiring. We call build runtime wiring. We need to give the implementation for build runtime wiring. So in this step is actually where we specify the data feature. Custom data feature will be specified inside this method. So now we have the type registry we have wiring. Then we can create the schema. We use the schema generator. Again, this is provided by the GraphQL library. We call make executable schema. We pass in the type registry and the wiring that we created in previous steps. So we have the schema. Once we have the schema, we create a new GraphQL object by calling new GraphQL. We pass in the schema.build. We get an object of GraphQL. So now we get an object of GraphQL. We can use it to execute. So different query. This one can be a different binary client. So we can execute the query. GraphQL that executes the query, we will get an execution result. And then from the result, we can get the response. So this is the steps how to use the GraphQL to define schema and then to execute it. Any questions so far? It's not your example. It's loading one power. Right. You have to load it one by one. I think we can have a load to load different multiple files. This one only take one single file. Any other questions? Okay. So now I want to build a demo of a data API that returns a person. So in this API, we want to have two entry points. One is called all people. So in the REST API, this is analogous to if we have a slash people. So we return all the people in the system. And the second field is a person that takes an ID of that string. This is analogous to if we have a REST API that slash people slash ID. So this is the API that we are going to build. So okay. Now we need to define the schema. So this is the root entry of our GraphQL. So we define the schema. The schema, the root entry is something called query. And then in this query we have two entry points. As I mentioned, we have all people that return an array of a person. So the data here indicate that it's an array. It can be a multiple object return from this entry point. And its object is of a type person. And the second entry point is a person that takes an argument ID and it will return a single object person. And as before, we have the type person. And the first name is of type string. So now the sample query to retrieve all the people. This is a sample query. We say all people. And we give the property that we want to fetch, which is the first name. So it's going to return all the person in the system and show only the first name. Or if we want to retrieve a single person, we use the second entry point, say person, pass in a parameter ID equal to one with the field first name. It will only be written only a single person. Okay. This is the data patcher. So there's a method before that I mentioned that we need to implement it, which is the build runtime writing. So I'm showing it now how we implement it to retrieve from multiple data source. So retrieve new runtime writing. And then we specify for an object type query. Because object type query has two fields. One is the all people and then another entry points of person. So for all the people, we specify all people data patchers. This object, we need to implement ourselves. And for a person, we give the person data patchers. So in the demo, I will actually build this data patcher. But on the schema, on the high level, this is how we can specify a custom data patcher. So if, for example, if the person is on a Mongo, we can, this implementation can talk to Mongo and retrieve the data. It's an Oracle. You can talk to Oracle. So this is how we can plan the API to talk to multiple data source. Okay. So now we're going to do a hands-on demo for all the API that we just described. Okay. So I'm using Java IntelliJ here. So I already created the project beforehand. So I created the project beforehand for booting up the application. So I'm using a spring boot to boot the application. And I created beforehand more like a person, how it, the person is just an entity that we are going to retrieve from the database and how we are going to retrieve it using a JPA repository to save some time because we want to focus on the GraphQL. So I also created a controller. I exposed a method called query and I can do a post on this URL. And right now we've just written Hello API Graph. So let me just run it. Okay. So I can do a query here. So it returns me Hello API Graph. So this is the starting point. And also I have a fast person loader so that populate the database so that I don't have to create an individual user person now. So I preloaded so in the database I'm using something called H2Database. So it's in memory database. So I can run and in my system right now we can see I have five, five persons. Okay. So now in my query controller, this is the endpoint of the API. So I, okay, first actually I need to define the schema first. So I'm going to define the schema new file. So I'm going to say person.graph ULS. So this is where I define the new schema. So I say schema and then I say the query, the root type object is query. And then I define the root type object query. It has two entry points all people. It returns an array of a person and then the second entry point is a person that takes an idea of string and then it returns a type of person. Now I need to define a new object type for person. So right now it is just id string first name string. Let's say last name string and then some s of f in. So this is my schema and then in my rest endpoint here I'm going to load that file. So I'm going to use spring to load it. So I say schema resource and then I mentioned that the value of this variable it will come from a file in the class path with the file name is draft and the file name is person.graph ULS. So it will load it for me. So once the application starts I want to create the schema. So I will just say public point load schema. I noted this with the abstract. So when this object is constructed it will call this method load schema. So what I do is now I have a file. So I schema file and I have the schema resource here. I say get file. So I will get the file reference to that file. And get file can throw an exception. Also I just need to define it. It says throw and it can throw an error exception. So now the second step I need to create something called type registry. By using a new schema parser and then I say parse. So I say parse give the file the schema file. Now I have the type registry. The third step is to have runtime wiring and then I say build runtime wiring. I need to provide the implementation for this one. So for now I leave it empty. The next one I can now create the GraphQL schema. By using the schema generator dot make executable schema. We pass in the two things. We have the type registry and we have the wiring. So now we have the GraphQL schema. And the last step is we want to save the actual GraphQL object. So we create something called GraphQL. So now I have the GraphQL equal to, so I say new GraphQL I pass in the schema and I do a build. So now we have the GraphQL object. So what can we do with that GraphQL? This is my entry point query. This is the post body which is the query itself. So what I can do I can do the GraphQL dot execute. I pass in the query. So this will give me an execution result. So now when we return we can return the result dot get data. If there are any error it will be available in get errors. So we can do a log the information so that we can see what is the error. This one needs a string. So I just wrap into a string. Now we need to build this runtime wiring. So what we'll do is we return a new runtime wiring dot build. This is the basically runtime wiring but right now it's not doing anything. So I want to specify a custom data feature. So I will save time. So I have an object called query. So I put a query and then this expect to give me a text in a one object called type wiring. So what I can do is stop wiring and do a dot data feature. I want to custom data feature for entry point for all people. So I specify that one and then the object that I want to pass in is all people data feature. Right now it's not created yet so I need to create it so I need to create a field all people data feature here. So I'm going to use auto wire so that this is a spring. That this is going to be injected automatically. I'm going to create a custom class all people data feature. This one is not available so I need to create a class. I created the class in some object called data feature. So I noted this with component and these data features need to implement an interface called data feature and then it parametrized with the type of the object and being returned. In this case this one can return a list of a person. So this one needs something important so I'm specifying some important implement the method. So there is one method that data feature need to implement. It says get and then it passes me the data fetching environment where I can get the contacts where I can get the source. So to make it easier I just rename this to environment. So the implementation will just retrieve all the person from the database and I already have the class something called person repository that I already created before. So I will just use it and then I just auto wire it. So this is basically a JPA. It will come to the database and find all the person. So the implementation for this is just person repository dot find all. So we return all the person in the system. So we are done with the first entry point. We need to create the second entry point which is the specific single person. So when there is a single person we want to call the second person data fetcher. So I specify a different object. I need to create this fill so it created for me so I need to auto wire and I'm going to do a custom object, a person data fetcher. So I need to create a class, specify the package name. So it creates the class, I have a component. And the same thing this one needs to implement an interface for data fetcher and it needs the type of object being returned. In this case it's just a single person. So I need to import the class. I need to implement the one single method that returns a single person. So I will just rename this to environment. I will use the same person repository. So I'm going to auto wire it. So the difference now is this is specific to a single person. So when someone calls a person they give or passing the ID equal to one. I'm able to get that ID from the environment because the environment containing all the source all the context. So there is something called get arguments. So I will say get arguments. I got a map. So I will say map arguments. So I get a map of all the arguments. So I need to import that map. So now when I call the person repository I get one. So I want to have one object. It takes a single string ID which is the ID of the person. And I can get it from the arguments get ID. Because the user try and pass the argument as the ID. So this one expect a string. So I just need to downcast it as a string. So we are done creating the second entry point. So we are done with actually creating the API. So we have one entry point, two entry point, all people and person. And yeah. So we are done. So and we have the person so we can now run it. Let me run. Okay. So now I'm going to query this. You just remove this. So I want to in this case I want to retrieve a person that I need one. I want to see the first name and it's. So I just do a query. So if the API returns me the person of Adam with it's 30. So I can change the ID equal to two. It will return me a different person. Or I can do all people because we have two entry points. All people will return me all the new person in the system. And for each person it will return only the first name and page. So that's the first part of the demo. I will do more feature by joining with the address. But until now any questions then I can continue. So the next part is I'm going to introduce a relationship. I call it an address. So a person can have many address. And this address information is actually stored in just a file just to show that we can actually retrieve from multiple data source. So what we are going to do is we are going to add a new field of address that return an array of an address. And then the address itself it has a field say street of web string. So I'm going to do the next is that one. So address. I introduce another field called addresses that return an array of address. And then I need to define type of address. It has a string. It can have a street. It can have a block. A string. It can have let's say region. It can have a country. Safe. Okay. So we define the schema. So next one we need to create a custom data features. So before we have an object for query and we specify two data features for all people in person. Now we need to create a new one for a object or person. We are going to do the same thing here. Typewiring data feature. But the object, the fields that we want to add data feature is the address. So we specify a new custom data feature address data feature. So we need to create this object. Create a field. The same thing as before. So I need to create this class. Okay. So just to the addresses actually I store it in the file. So this is a many to many join. So I have this kind of a table in the file. So this is many joins. So we have person ID and address ID. So person ID one, it stays at the address ID 1,000. This ID person ID one also stay at 1,001. This person stay to address. So the second person stay at the same as the first address and so on. So this is the join. And then I have this file which contain information about the address itself. So in the address 1,000 the street is this block number region, country, safe and so on. So I have five addresses. So and beforehand I created a repository for to fetch those files. So address repository, it loads two files, two CSV files stay set and address. So basically this is just a basic programming to load the file, look through the file and then return the address for a different single person. So I expose a method, get address, different a person ID can return me the list of address. This is from the file. So the detail I don't want to go through because it's just basically a programming to load all to the file. So I need to create now address data feature here. So I'm going to create a class here, address data feature. I specify it stays inside the package data feature. I annotated with a component and this one also need to implement the data feature interface that return a list of address. I need to import. Okay, so now I need to implement this method that given the context, the environment to return a list of address. So in the implementation I'm going to use the repository that I already created. So I use auto wire. And now the difference is we need to know the source, the pattern object. So because the address always live within the context of a person. So we can get that information from get source. Get source will return you the pattern object of this address. So the source of this environment is actually a person. So I can type downcast this to a person. So once I have the person, then I can use this address repository to get address for a single person ID. Which I get from a person.getID. So I get from the context, the person, the pattern object. I use that ID to retrieve the address for that person. Okay, so we are done with that also. So now I just need to run it now. Okay, so now if I just query without any change it will just return the same information. But now I have a new fields address and then inside this address let's say I want to see the thread. And maybe the zip. So I just specify here and I do a send. So now in addition to first time and age it returns me the address. So for the first person it has to address. For the second person it has one address and so on. Based on the csv file that is specified. And we can also use the first entry point with the single, with the single specifying the ID. So it will retrieve our single person. Everything still works the same as before. So what we build is the person is actually in the Oracle database. It joins with the address which is just residing in the single simple csv file. It can be any kind of data source Mongo and so on. That's basically the demo that I have prepared. So any questions? Yes, yes, yes. You can do a get also. It's just that the query that you need to pass in will be in the query parameter. And some query will be lengthy. So it's a bit IPM will become a bit messy. So that's why I chose to have it in a post. But you don't have to do a post. You can do a get and then pass in the query as query parameter. So the framework that I built here is actually using a spring boot. So if we want to have a security around this API, we can integrate the spring boot with the spring security. You can do a full out authentication. Everything. So there is outside the GraphQL itself. It's more handleable. So you can do a get and then pass in the query parameter. The GraphQL itself is more handled by the spring. Spring as an ecosystem handles many things. So the GraphQL here is just to text in the string query and we can return the data. So the client can specify the fields they want. They can specify parameter they don't need to know but behind the scene is actually from multiple data source. So the application itself will be handled by the spring. Any other questions? Do you have a GraphQL browser? Yes, there is another project GraphQL tool or something. That one you can install and then it will give you the GraphQL. But in here I didn't install that so I create the custom endpoint. But there is a library for doing that also. You have it. But essentially it's the same with Postman? Yes, similar with Postman. It's the same. Every time you type it automatically shows you the response how it looks like. So it's a bit faster. This one is more if you want to build your application. So if we actually give the wrong query it will return an error. For example if I give something called hide actually in the log it will say here field type hide is undefined. So the parser will do the validation. The query with the schema will match it and say oh there is no type fields called hide and I don't know. So it will just block it as an error. So it depends on how we handle it. We can return the error or we can just lock the error and so on. If there is no more question then I think I'm done.