This project will be different from all the previous ones that you have already done during the course. Its main difference is that it is a relatively large, working project.

It does not need to be written from scratch, but you need to make changes to the code and not break anything in it, add functionality that has not yet been written, and configure the infrastructure. It is this type of task that you will mainly encounter at work.

This is half of a programmer’s entire job - reading and parsing other people’s code.

At work you will spend all your time on 3 things:

  • Parsing and reading other people's code - 50% of the time.
  • Imagine how to describe your problem in the form of a solution code - 25% of the time.
  • Adding your code to existing project logic - 25% of the time.

When I start getting acquainted with a new project, I try to stick to the following sequence:

  1. Find out what the problem is solved (or will be solved in the future) by the project.
  2. I look at what dependencies the project has.
  3. I look at the database structure.
  4. I look at the Entity structure.
  5. I look at the API and/or other controllers.
  6. I understand what task each service has.

Only after getting acquainted with this list can you look at “what , as a matter of fact, I have to do.” Let's follow this plan and move forward.

Main task

The name of the project is JiraRush.

GitHub of the project

I think you can guess from the name that this is a kind of task board like Jira or Trello. The project is needed to track any activity. This can be either project management or a shopping list from wife to husband. Clone the project for yourself, and let’s see what’s in it.

If you’re not familiar with Jira, here’s a short introduction video on the topic

Technology

  • Spring Boot
  • Spring JPA
  • Hibernate
  • PostgreSQL
  • Liquibase (database versioning system, mainly its structure)
  • Spring Security
  • Spring MVC
  • Thymeleaf
  • jQuery
  • Swagger (API documentation)
  • Caffeine (cache)
  • Lombok
  • Mapstruct (mappers for converting between entity & DTO)
  • Spring Test
  • JUnit
  • Docker [1], [2]

Database structure

How to run the application:

  1. Clone the project onto your machine.
  2. Launch the database server locally (PostgreSQL). I recommend doing this via docker.
  3. Let's create 2 containers with a database. The first one is for launching the application (prod profile), the second one is for the build and tests (test profile). Relevant commands:

     docker run -p 5432:5432 --name postgres-db -e POSTGRES_USER=jira -e POSTGRES_PASSWORD=JiraRush -e POSTGRES_DB=jira -e PGDATA=/var/lib/ postgresql/data/pgdata -v ./pgdata:/var/lib/postgresql/data -d postgres docker run -p 5433:5432 --name postgres-db-test -e POSTGRES_USER=jira -e POSTGRES_PASSWORD=JiraRush -e POSTGRES_DB =jira-test -e PGDATA=/var/lib/postgresql/data/pgdata -v ./pgdata-test:/var/lib/postgresql/data -d postgres 
  4. Build the application : mvn clean install
  5. Run a Spring Boot application (JiraRushApplication) with the profile prod

During the application build the test database population will occur. During application startup there will be a population of databases to work with. More precisely, the structure and dictionaries will be rolled out. To “see” how the application works, you need to run the script data.sql from resources/data4dev.

Now we can look at the structure of the database:

activity – an activity table that stores user actions regarding other entities. For example, “the user wrote a comment”, “the user changed the status of the task”...

attachment – a table for storing information about attached files.

contact – dictionary “user – contact type – contact value”.

mail_case – table where data is saved if sending a letter (email) failed.

< p>profile – user profile. The settings are stored in the mail_notifications field in the form of bit flags.

project – Projects. The largest logical unit of a task board. For example, if a company has microservices, each microservice is led by a team, then a project will be created for such a microservice.

reference – a table of different entities by type. ref_type corresponds to Enum com.javarush.jira.ref.RefType. Column aux – value for calculating bit flags.

task – tasks. The most basic logical structural element of the JiraRush task board.

task_tag is a dictionary of task-tag relationships. One task can have zero or more tags.

user_belong – user connection with entities of the “task”, “sprint”, “project” type.

user_role – dictionary of user-role connections. One user can have several roles.

users list of registered users. The columns endpoint and startpoint are responsible for whether this user is active, or was active, but is no longer active. The password field at the beginning of the password in the form “{...}” stores the encryption method (Spring Security, remember?).

Entity structure

This point I I'll leave it for you to review on your own

I'm looking at the API and/or other controllers

Swagger is connected to the project, which is responsible for documenting the API. In order to look, with the application running, go to http://localhost:8080/swagger-ui/index .html

Here you can see what controllers there are, what methods these controllers have, what input data is expected, types of methods, etc. You can also send a request yourself. It would be a good idea to log in as different users (test data is written in the UI) and see what rights are needed to execute which method.

Which service is responsible for what

With this point you also you'll have to find out on your own. Instead, let's look at the already implemented functionality. We will look at it from a user with the ADMIN role, since he has the most extensive powers. But you will need to look at both MANAGER and DEV.

  • Project tree. There is a list of projects. Administrator or Manager (see enam Role) can add new projects and subprojects. The project has a backlog (a list of tasks (tasks) that need to be done) and sprints. A project can also have a subproject. A task can relate to a sprint directly, or through an epic (a large group of tasks). See http://localhost:8080/view/tree
  • Task board ). You can choose which project to view the dashboard for. The active (or last) sprint for the project will be shown. Sprint tasks are divided into columns. The ones you need to pay attention to are highlighted in color. Changing task statuses is done by right-clicking on the task. See http://localhost:8080/ui/dashboard
  • Sprint report : a minimum set of statistics on completed sprints with the ability to select a project and sprint. See http://localhost:8080/ui/reports
  • List of users. List of all registered users with the ability to search, sort, add, edit and delete. Page http://localhost:8080/view/admin/users
  • Links - functionality for setting up JiraRush (which fields are available to which type of entities. For example, which social networks to show in a user’s contact, or what priorities a task has). See http://localhost:8080/ui/admin/references
  • Editing a user profile (your profile).
  • Registration of a new user via email + password.
  • Registration of a new user via social networks (Google, GitLab, GitHub) .
  • Sending emails when a password is reset.
  • Sending emails to confirm it.
  • Creating a new task in the backlog (with the ability to attach files as attachments ).

Some more information about the project “by word of mouth”

The structure of the project is similar to the Spring Modulith project. That is, there are internal packages that cannot be accessed by code from outside the top-level package.

This is done with a “future reserve” so that the server can be easily divided into microservices. At least, this was the architect’s idea, but the implementation may differ (yes, this almost always happens in real projects).

Static files for the front are distributed through the nginx server. At least this should be the case in production, but when running locally, everything is simpler.

PostgreSQL. You won't write native queries. You will need to use JPQL queries. The only new thing for you will be connecting to PostgreSQL to view the table structure and their data. I recommend using the database IDEA tab.

Liquibase is an open, database-independent library for tracking, managing, and enforcing database schema changes. The project uses it to automatically execute the database initialization script and populate it with test data. If you change the table structure, you need to delete 2 Liquibase service tables (databasechangelog and databasechangeloglock). After this, the next time you start the application, Liquibase will re-execute the database initialization script. You don't need to make any settings, everything works out of the box.

Swagger - allows you to visually see through the UI which methods are in the application controllers and perform test requests to them. There will be no Swagger tasks. It is added for ease of working on the project.

Caffeine cache is a high-performance cache library for Java. I recommend seeing how it connects. There will be no tasks to use.

Tasks of your choice

Start with easy tasks and only then proceed to the rest. Try to complete as many tasks as possible.

  1. Understand the project structure (onboarding).
  2. Delete social networks: vk, yandex. Easy task
  3. Put sensitive information into a separate property file:
    • login
    • DB password
    • identifiers for OAuth registration/authorization
  4. mail settings
  5. The values of these properties should be read from the machine’s environment variables when the server starts. Easy task
  6. Rework the tests so that during the tests the in memory database (H2) is used, and not PostgreSQL. To do this, you need to define 2 beans, and which one to use should be determined by the active Spring profile. H2 does not support all the features that PostgreSQL has, so you will have to simplify your scripts with test data a little.
  7. Write tests for all public methods of the ProfileRestController controller. Although there are only 2 methods, there should be more test methods, because you need to check the success and unsuccess path.
  8. Refactor the com.javarush.jira.bugtracking.attachment.FileUtil#upload method so that it uses a modern approach to working with the file system. Easy task
  9. Add new functionality: adding tags to a task (REST API + implementation on the service). The front is optional. The task_tag table has already been created.
  10. Add a count of the time the task was in operation and testing. Write 2 methods at the service level that accept a task as a parameter and return the elapsed time:
    • How long the task was in progress (ready_for_review minus in_progress).
    • How long the task was under testing (done minus ready_for_review) .
    To write this task, you need to add changelog.sql 3 records to the table at the end of the database initialization script ACTIVITY
     insert into ACTIVITY ( ID, AUTHOR_ID, TASK_ID, UPDATED, STATUS_CODE ) values ... 
    With statuses:
    • start time of work on the task - in_progress
    • development end time - ready_for_review
    • testing end time - done
  11. Write a Dockerfile for the main server
  12. Write a docker-compose file to run the server container along with the database and nginx. For nginx, use the config file config/nginx.conf. If necessary, the config file can be edited. Hard task
  13. Add localization in at least two languages for letter templates (mails) and the start page index.html.
  14. Remake the “friend or foe” recognition mechanism between front and back from JSESSIONID to JWT. Among the difficulties - you will have to redo form submission from the front in order to add an authentication header . Extra-hard task

When submitting the project in README.md write which tasks you completed.