Spring & React ile Web Uygulaması Geliştirmek

Spring ve React ile baştan sona bir web uygulamasını nasıl yapıldığını anlattığım eğitimim, Udemy’de yayında.

Spring ve React ile Web Uygulaması Geliştirmek

Tamamen pratik üzerine kurulu olan bu eğitimde, frameworkler hakkında edineceğiniz bilgiler, bir bütün içerisinde, yeri geldiğinde karşınıza çıkacak. Böylece gerçek kullanım ihtiyaçlarını hissederek, Spring’in ve React’ın sunduğu özelliklerin ne tür durumları çözdüğünü daha iyi öğreneceksiniz.

Test Driven Web Application Development with Spring & React

I have been working on my course about Test Driven Web Application Development with Spring & React for a long time. Finally it’s completed and published on Udemy.

In this course, we are building an actual web application and while doing that, we will see how we can use Spring Framework and React JS in a web app and also we will learn how to apply Test Driven Development methodology.

You can use this link https://www.udemy.com/course/test-driven-web-application-development-with-spring-react/?referralCode=5EE4FA2E84E78941F649 to access the course.

Please share with anyone who are interested in learning Full Stack Web application development and who wants to see Test Driven Development in action.

Spring Data Specifications

This tutorial is to show how specifications are used with spring data jpa.
We have this entity

And what we want to do on front end side is to filter the People based on the values of fields.
e.g All people with brown eyecolor and age is older than 25 and who has profile picture.

Since this query parameters can be changed dynamically, we need to come up with a flexible query generation solution which is JPA’s query builders Specification approach.

Specification provides a flexible configurable query generation logic for us. An example Specification is as follows

We are creating specification based on hasPicture condition which would lead query to check if Person picture is null or not.

The Specification implements the method with parameters Root root, CriteriaQuery<?> query, CriteriaBuilder cb
Person_ seen above is the meta model of our entity which is required for Query building. You can check this article about meta model in hibernate.

Our controller takes user query parameters as follows

Filter is the object that represent the RequestVariables.

And the service logic is as follows

So in our service logic we check if we are receiving any filter param and if so, we are creating specifications for each of them and combining it together in the end and asking dao to pull the data based on that specification logic.
The dao must implement JpaSpecificationExecutor to handle specification related queries.

The sample project codes are here

Happy specificating! 🙂

Spring TDD – Test Driven Development

In this blog, I’m sharing an example project to show unit and integration test with Spring.

We have a web service for car. Here is the entity

And lets say we have a Dao for this entity as follows

Spring provides a custom test configuration for testing this Dao class. All you have to do is use @DataJpaTest annotation in your test class.

@RunWith(SpringRunner.class) -> this part is required to use @Autowired or other spring related annotations to be processed.

TestEntityManager is used as a replacement of JPA’s EntityManager for executing SQL queries in test mode.
DataJpaTest will create an in-memory database for the runtime test environment.
By Default this mode is @Transactional which means after each test, the test db will be rolledback.

After completing the Dao test, we can go to next step which is unit test for @Service class.

First of all, make sure to use Constructor injection, not field injection. This will be helpful when we write unit tests for this class.
This is the part of test class

We are using @MockBean annotation for CarDao. Our intention here is, not running the whole Spring App but just run the CarService only. To accomplish that, we create the CarService instance and mock the all possible dependencies (for our case, it s just CarDao but it could be more than that).

With Mockito, we are mocking the behavior of carDao for specific methods and testing them through CarService methods. So we verify our service methods are working as we expected.

After completing the unit testing for the service class, we can do the integration testing of RestController.

This is our rest controller

And this is the integration test

The main difference here is the @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) annotation. This is starting the app in random port.
We are using TestRestTemplate as client to execute REST requests.
Since this test code is also running in spring context, we can inject CarDao here for inserting dummy data to our test database and pull it through rest calls.

I’d highly recommend to use a test profile with test environment database configuration in it to make sure you are in control with your application status during testing.
All you have to do is to add @ActiveProfiles("your-test-profile-name") to your test class.

In integration test, the test methods are not in transactional mode which means they will not be rolled back after each test execution. Therefore you should be careful about not changing the applications state between tests. Since Junit is not running the tests in order (which can be configured to run in order but I wouldn’t suggest it), if any test would be leaving unexpected data in db, it may break other tests. So make sure you return to your original state after the test is completed. You can use @Transactional annotation. Or you can add a method to clear the database after each test run and you make sure it with @After annotation.

Spring TDD code is here

Happy testings!

Spring Boot with Docker

In this project there is a simple rest backend which will be running inside docker container.
We’ll have multiple instances of this application and we’ll be using HAProxy for load balancing for the backend apps.

The network diagram is as follows

LBDiagram

The project source code can be found at this github link.

The backend app is a single rest controller (/hello) which generates json response with hello message.

In the controller, environment value of message is being used. This variable will be set by docker commands later. It’s just for confirmation of load balancing.

After running mvn package in this project folder, helloserver.jar file will be generated inside the target folder. This jar will be copied to docker image.
This is the Dockerfile of spring boot application.

It’s copying the jar, setting the port to be exposed and setting the run command of the application.

This folder contains the Dockerfile and haproxy.cfg files. We’ll be building an image for haproxy with our custom configuration of docker network.

This is the Dockerfile for haproxy

This will be building a new image with the copy of haproxy.cfg with the haproxy:1.5 image.

This is the config file

bind *:80 – this is setting public network port for haproxy
server server1 hello1:8080 check – server is config keyword. server1 is the internal name . hello1:8080 is the address and port of the backend server. check is for the health check for this server
server server2 hello2:8080 check – same config for server 2 which will be called as hello2

hello1:8080 and hello2:8080 will be resolved by docker’s networking capability.

here’s how to build images
This is for the spring boot image
\helloserver> docker build -t hello/server .

and this is for the haproxy
\helloserver\haproxy> docker build -t hello/haproxy .
You should be seeing these images in your docker image list
\helloserver\haproxy> docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
 hello/haproxy latest c8d6f80893a7 9 seconds ago 136.2 MB
 hello/server latest e589ccbd5a65 52 seconds ago 195.5 MB

Create a custom network for docker
> docker network create hellonetwork

And run the images.
Since the haproxy is configured with servernames (hello1, etc) during initialization, it’ll try to discover those devices. But if there is no running device with name “hello1” in docker, haproxy will not find it and fail to start. To eliminate this problem, run the haproxy after the backend servers are started.

start the backend instance
> docker run -d --net hellonetwork -e message=Server1 --name hello1 hello/server
-d – the daemon mode
--net – setting the net to be used for that image (hellonetwork)
-e – setting environment variable (message=Server1) – rest controller will be reading this parameter
--name – setting the name for this image (hello1)

start another instance from same image with different name and message
> docker run -d --net hellonetwork -e message=Server2 --name hello2 hello/server

since both of the backend servers are up we can start the haproxy

> docker run -d --net hellonetwork -p 80:80 --name haproxy hello/haproxy
-p – the docker will expose the internal port 80 to external 80, so we’ll access to haproxy through 80

the environment is ready to test
> docker-machine ip
192.168.99.100

Open a browser and go to http://192.168.99.100/hello . Refresh it couple of times. You’ll see the response will be {“content”:”hello from server Server1″} or {“content”:”hello from server Server2″}

Thanks

Injecting custom object to controller in Spring Boot

In Spring, you can inject your custom object to the controller methods like this

Here are the steps of this implementation.

In my sample project I have ClientRequest object which contains incoming request related variables.

These variables are basically taken from the HttpServletRequest object. So we could inject HttpServletRequest instead of ClientRequest and would generate the same content, but that’s not the point. In your project, you may need custom objects which would need additional object dependencies or you may want to centralize the object creation algorithm instead of repeating it in every controller method.

Next, we implement ClientRequestArgumentResolver which implements HandlerMethodArgumentResolver.

ClientRequest object is created in the resolveArgument(...) method.

All we have to do is add a new Configuration class to our project and add this ArgumentResolver to Spring’s argumentResolvers List.

Now we can inject ClientRequest to our controller methods.

You can check the sample project in my github.
And the objects are
ClientRequest
ClientRequestArgumentResolver
ClientRequestContext
Controller is here.

The data is displayed in this html file.

Run the app and open the page http://localhost:8080/request

Have fun!.

Returning user requested variables with Spring

When implementing a REST API, you may want to provide flexibility for users about filtering the content based on their requests.

when requesting GET /movies/1

and when user sets fields, GET /movies/1?fields=year,subject,director the result would be

Implementation of this behavior is very similar to my previous tutorial about Role Based Content in Spring. I’m using the same sample project for this tutorial also.

We have this Movie entity.

And we have this movie controller.

We are injecting @AuthenticatedUser TutorialUser user (Check here for the details of this implemantation) and @RequestParam(value = "fields", defaultValue = raw) String rawFields to our controller method.

Since we’ll be doing variable filtering, the method is returning MappingJacksonValue. In getMappingJacksonValue method, comparing the variables coming with the fields parameter to the existing variable List of corresponding user role. Creating the String array for the matching variables and setting it as a filter and returning the result.

So this code is checking both user role and the fields in the request before generating the response content.

Since user/user has limited variable set, executing GET /movies/1?fields=actor,actress,year would result following json with only year in it.

If year is removed from request, GET /movies/1?fields=actor,actress the response would be

You can check the sample project at my github.

I’m using Postman when I want to play with the requests. Postman scripts for this application is here. You can just import and use them. But if you would like to use another tool, here is the api doc

user/pass = admin/admin and user/user

base url: http://localhost:8080
GET /movies // gets list of movies
GET /movies?fields=id,year… // return the specified fields in the list of movies
GET /movies/{id} //gets the movie with specified id
GET /movies/{id}?fields=id,year… // return the specified fields of the specified movie

POST /login?username=admin&password=admin

Have fun!

Returning role based content in Spring Rest Controller

When implementing a rest backend, you may be looking for a way to hide the variables of an entity based on the logged in user’s role.

Here’s a sample entity. Movie

It has id, year, length, title, subject, actor, actress, director variables.

And in my application, I have two user roles which are admin and user.

I want admin to see all variables of the Movie. But I want user to see only year, title, subject variables.

Here’s how to filter variables..

In the Movie entity we have @JsonFilter annotation. This is a Jackson feature. You can check here for more details about it.

This entity is processed in the controller as follows.

Our controller method (getMovies) at Line 12 is executed when we request GET /movies from browser.
This method is returning MappingJacksonValue in the response.

There are two String arrays which contain the set of variable names for the limited version and the all version.

In controller method, we inject the current logged. @AuthenticatedUser TutorialUser user . Check here for the details of this implemantation.

All we do here is (Line 16 – 17) select the String array based on user role, and set as a filter for our MappingJacksonValue object.

You can check the sample project at my github.

Run the app. Open the page at http://localhost:8080
user/pass = admin/admin and user/user

If you log in with admin, you’ll see this page where all the variables exist in the table.
admin_list

when you log in with user, you’ll see
user_list

Have fun!.

Getting current Authenticated User in Spring Rest controller

When you need to get the active logged in user in your controller, the most common way would be injecting Principal to your controller methods.

But when you need this to be done in multiple methods, you may be looking for a cleaner approach like injecting the exact User instead of Principal object.

To inject your user object (e.g. TutorialUser) follow these steps.
Make your TutorialUser to implement org.springframework.security.core.userdetails.UserDetails

Create the annotation you want.
Make sure to add the @AuthenticationPrincipal annotation. Otherwise it won’t work.

Then you can use this annotation with your User object in your controllers.

You can check an example code at my github page.