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.
- Imagining 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:
- Find out the problem being solved (or will be solved in the future) by the project.
- I look at what dependencies the project has.
- I look at the database structure.
- I look at the Entity structure.
- I look at the API and/or other controllers.
- I delve into 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 CodegymJira.
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, 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
Database structure
How to run the application:
- Clone the project onto your machine.
- Launch the database server locally (PostgreSQL). I recommend doing this via docker.
- Build the application :
mvn clean install
- Run a Spring Boot application (CodegymJiraApplication) with the profile
prod
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=CodeGymJira -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=CodeGymJira -e POSTGRES_DB=jira-test -e PGDATA=/var/lib/postgresql/data/pgdata -v ./pgdata-test:/var/lib/postgresql/data -d postgres
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.
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.codegym.jira.ref.RefType
. Column
aux – value for calculating bit flags.
task
– tasks. The most basic logical
structural element of the CodegymJira 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'll leave for you to review on your own
Looking at the API and/or other controllers
Swagger is connected to the project, which is responsible for documenting the API. In order to have a 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
You will have to investigate this point 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 enum Role) can add new projects and sub-projects. The project has a backlog (a list of tasks (tasks) that need to be done) and sprints. A project can also have a sub-project. 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 CodegymJira (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.
- Understand the project structure (onboarding).
- Delete social network(s): e.g. facebook. Easy task
- Put sensitive information into a separate property file:
- login
- DB password
- identifiers for OAuth registration/authorization
- Mail settings The values of these properties should be read from the machine’s environment variables when the server starts. Easy task
- 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.
- 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. - Refactor the
com.codegym.jira.bugtracking.attachment.FileUtil#upload
method so that it uses a modern approach to working with the file system. Easy task - Add new functionality: adding tags to a task (REST API + implementation on the service). The frontend is optional.
The
task_tag
table has already been created. - 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) .
changelog.sql
3 records to the table at the end of the database initialization scriptACTIVITY
With statuses:insert into ACTIVITY ( ID, AUTHOR_ID, TASK_ID, UPDATED, STATUS_CODE ) values ...
- start time of work on the task - in_progress
- development end time - ready_for_review
- testing end time - done
- Write a
Dockerfile
for the main server - Write a
docker-compose
file to run the server container along with the database and nginx. For nginx, use the config fileconfig/nginx.conf
. If necessary, the config file can be edited. Hard task - Add localization in at least two languages for letter templates (mails) and the start page
index.html
. - Remake the “friend or foe” recognition mechanism between front and back from
JSESSIONID
toJWT
. Among the difficulties - you will have to redo form submission from the frontend in order to add an authentication header. Extra-hard task
When submitting the project, update the README.md with tasks you completed.