Project Setup with Spring Initializr
Hey, it's Random Code here, and today on our circle is how we can quickly and easily create an API in Java using Spring Boot. So I will just first create a new project and we'll use a Spring Initializr. Let's call this project "Spring API".
You're going to be using Java. I'm going to be using Maven. Group fine, that's fine. I'm going to be using Java 17, which should be fine. And for dependencies, the one dependency we're going to be needing is Spring Web. So I will just add Spring Web, finish, and let the project load.
Structuring the Application
So we now have a very simple Spring-based project and it might take a few minutes for you for it to load the first time, or maybe to get all dependencies, get everything set up. But otherwise, we will then have a Spring API folder with, most importantly, our src/main/java, and then inside com.example.springapi, we have the Spring application, which is a very Spring setup for a basic Spring Boot application that then starts our opposite void main from this position.
So to then create our REST API, I will add a few folders just to create a basic structure. So I would create an API folder, and I will create a service folder. Because I would be using the basic structure of the API and then have them have a service handling kind of like the back-end setup for this API. Inside my API folder, I would then also have another folder. I'm going to call them packages, it's not the same thing, but I would then have a controller and I would have a model.
Creating the Component Classes
Not like that, let's actually take a look at the project files instead. And I would also have my... like that. So inside the API package, I have both my controller and my model package. So inside my controller, I would create a new Java class, and let's say in this case we are building a base API to get some user data, so I might be creating a UserController.
I'll create our model for our user. And inside Services, I will create a UserService.
We would then create a very simple user. So let me just quickly construct a user. And here we go.
Defining the User Model and Annotating Components
So now I have a very basic user. I have a userID, a name, an age, and an email. I have a constructor taking all these parameters. I have getters and setters for all of my values. So what I will then very simply do is, inside my user controller, I would then highlight this user controller as a @RestController. And if you just add alt+enter, so we have a RestController, @RestController. And I would then also for my service, just add it as a @Service.
Building the REST Controller Endpoint
But then very simply inside my REST controller, I would then create a public method. So I'll do public and then I would like it to return, in this case, just a User. And I'll just call it getUserExample. And I would then make this method into a @GetMapping, which means we can make GET calls to this API setup to get this information. And I would then, in this example, just very simply create a @RequestParameter, which is kind of the input we give to our API to tell, in this case, which user we would like to get. So I'll do a @RequestParameter where I would do it as an Integer ID.
We would then just very simple inside this method, just return some user based on some ID. And I would then create my service. So I would do a a private UserService userService. I would then use constructor injection to set up this service. So I will do a public UserController taking in a UserService userService. And then this.userService = userService. And I will then add an @Autowired for constructor injection to then inject my user service into this controller. And I would then simply here just return my userService.getUser(ID). And of course, we haven't created this method yet, so I would create the method in User.
Implementing the Service Layer Logic
And now we're getting to a point where it's not very realistic because normally you would probably have this in this service connect to some kind of database and then actually extract some visuals, might have some SQL queries. To kind of simulate this database setup, I would just in here create a private List<User> userList.
And I'll then inside our empty constructor just create a new userList = new ArrayList<>(). I will then create a few users. User user = new User(), and I've got an ID of 1, the name of Ida, an age of 32, and an email of [email protected]. And let me just add a few more users.
Like that. So I now have five users with different IDs, different names, different ages, different emails. I then add all these users to my user list. I would then very simply whenever I get this get user call to my service, I would just simply go through my... I'm just going to do a simple for loop, that's very simple. So we go through our User user in our userList. Simply do if the ID from the input is the same as our user.getId(), then we would simply return this user. Otherwise, we would return something. And then actually, there's quite a few different ways we could do this a bit more optimal. Yeah, let's actually just do it properly. So instead of actually returning a user here, I would be returning an Optional containing a user. And I would then create a new optional, so Optional<User> optional = Optional.empty(). We would then, instead of just returning that user, we then set our optional to be equal to Optional.of(our specified user). And would then return our optional. And in case we actually never hit any other optional or we don't hit any user, I'll just return my optional like that.
Handling Nulls with Optional
And in here, instead of just returning this user, because it's not going to be a user, it's going to be an optional. I would then have my... let me get an Optional<User> user = our userService.getUser(). I mean, then simply say if our user.isPresent(), we then return our user.get(). Otherwise, we would return, let's just return null.
And this is definitely not the best way of doing it because normally we probably wouldn't just return a user directly. We'd probably return some kind of entity with some kind of network code, so we can define that in case the user's not present. Instead of just returning the user we would return a specific code, so we might return 'content not found' or something like that. But now I think it's just a simple setup, so it should be fine.
Testing the API with Postman
So let me actually just open Postman so we can actually check this works. So we now have Postman running. And one last thing, instead of just having our get mapping run on default, let's actually add a path. So just add /user. So now when you run the program, if I didn't make any mistakes, we should be able to have our API running on localhost:8080.
As we see here, we can now do localhost:8080/user and we can then pass it a query parameter for id. And let's just try doing ID 1. So here you can see the actual API call we're doing. So localhost:8080/user with the parameter of id=1. And as you can see here, we actually end up getting our ID 1, which is Ida, 32, and with the specified email. And if we go back into the service, we can also see that it is actually matching correctly. And then just to check it works, let's change and let's do 5, for example. We now get Ida 9, which matches.
Let's actually check the setup we did without any users. So for example, six. In this case, we just return null, which ends up returning nothing, which is not perfect.
Final Review and Conclusion
And definitely not the best, as mentioned. We might actually want to change instead of having the response status be '200 OK', you could probably be... I don't remember all the numbers in my head, but I think at least there's something called like 'partial data found', something like that, so I actually showcase that something's not here. Or maybe you would actually just like want it like this where we just have a setup where if you try to request something that's not there, it returns nothing, because that's also kind of logical and makes sense.
But this is the entire setup of our Spring-based API in Java, which I think is a very simple and very quick setup where we actually have a controller, a model, and a service. And we then simply connected it through Spring using some basic Spring principles. Like for example, inside our controller we did constructor injection, injecting our service into our controller, then simply called it. We use an optional which allows us to simply check as long as the user is present we return the user, otherwise return nothing. So I think this is a very good showcase of a very powerful tool or very powerful library, Spring Boot, which can be used for creating some very simple and very niceREST APIs with plain Java. So if you enjoyed this quick showcase, or relatively quick showcase, please leave a like and subscribe. And I wish you all a wonderful day.