BE Study 3rd

Another further question from the 1st study: what is 'categoryService' and how does it work?

So, let's take a look at it: services/CategoryService.java

package com.sivalabs.techbuzz.posts.domain.services;

import com.sivalabs.techbuzz.posts.domain.models.Category;
import com.sivalabs.techbuzz.posts.domain.repositories.CategoryRepository;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class CategoryService {
    private static final Logger log = LoggerFactory.getLogger(CategoryService.class);
    private final CategoryRepository categoryRepository;

    public CategoryService(CategoryRepository categoryRepository) {
        this.categoryRepository = categoryRepository;
    }

    @Cacheable("categories")
    public List<Category> getAllCategories() {
        log.debug("Fetching all categories");
        return categoryRepository.findAll();
    }

    @Cacheable("category")
    public Category getCategory(String categorySlug) {
        log.debug("Fetching category by slug: {}", categorySlug);
        return categoryRepository.findBySlug(categorySlug).orElseThrow();
    }
}

@Service


1. Client Request the page from the Server
2. Dispatcher Servlet finds the relevant @Controller; I guess Dispatcher Servlet might be something that includes the router..
2.1. @Controller goes to @Service to to conduct a required business logic.
2.1.1. If the DB access is needed, go to @Repository and get the data from the DB
2.1.2. @Service passes the result to the @Controller
2.2. @Controller puts the result into the Model
3. View sends the relevant page to the Client.

This is the most simplified stream of Spring Server.

Thus, @Service means that this class is for Service Layer. But what I could know was that it does substantially identical function as the '@Component' does.
The primary feature of @Component is that objects with @Component are designated as 'Bean', and the Spring Container handles the Bean: this process is called 'Component Scan'

What's 'Bean' and the 'Spring Container'?
Spring Container is a space that manages the bean, including their lifetime and giving extra functions. Bean is a java object that are used in Spring project. ApplicationContext is the most generally used Spring Container, which is extended from 'BeanFactory'.
When making an application, lots of objects refers each other resulting in increased dependency. This is seriously against OOP's philosophy.
Spring's main idea lies here. Instead of granting the programmer to right the whole code including the inheritance, programmer just defines the class and interface. The actual execution(like the main function), including constructing the object and calling the methods is up to the framework(Spring). Especially, when one object wants to be injected to another object, the Spring Container should be involved.
Still, I'm not perfectly understanding this one. I need to study a lot more about it.

To understand this, you know the understand the concept of DI(Dependency Injection). 


@Transactional
This annotation means the below codes are transactional. To say it again, it means that the framework guarantees below codes to meet ACID properties.

public class CategoryService {
Declaration of CategoryService

    private static final Logger log = LoggerFactory.getLogger(CategoryService.class);
Allows Logging. Already mentioned on the 1st study.

    private final CategoryRepository categoryRepository;
member variable with a type CategoryRepository

    public CategoryService(CategoryRepository categoryRepository) {
        this.categoryRepository = categoryRepository;
    }
Constuctor that sets member variable categoryRepository with the given categoryRepository

@Cacheable("categories")
    public List<Category> getAllCategories() {
        log.debug("Fetching all categories");
        return categoryRepository.findAll();
    }
The Cacheable annotation means the method is cacheable. Caching is a great feature that Spring enables you. It will run like below.
Spring looks for the "categories" table for the key(in this case, key=0 because getAllCategories() does not have a parameter) if the below method is called. If the key exists in the table, Spring returns the value which is in pair with the given key instead of executing the method. Else, Spring runs the method and inserts key(given parameters)-value(return of the method) pair into the "categories" table.
Furthermore, if the method has no parameter, Spring just sets the key '0', and if the method takes several parameters, it hashes those parameters to create the corresponding key value.
Guess the function is for getting all of the categories from categoryRepository. It also logs "Fetching all categories" into Logger log in 'debug' format.

    @Cacheable("category")
    public Category getCategory(String categorySlug) {
        log.debug("Fetching category by slug: {}", categorySlug);
        return categoryRepository.findBySlug(categorySlug).orElseThrow();
    }
This also has a 'Cacheable' with name "category" and it seems to return actual category name by its slug. It might throw an exception if findBySlug couldn't find the relevant category via orElseThrow(). For this, 'categoryRepository.findBySlug()' might ahve something to do with 'Optional'. Let's go to 'repositories.CategoryRepository' file.

package com.sivalabs.techbuzz.posts.domain.repositories;

import com.sivalabs.techbuzz.posts.domain.models.Category;
import java.util.List;
import java.util.Optional;

public interface CategoryRepository {

    Optional<Category> findBySlug(String slug);

    Category findById(Long id);

    List<Category> findAll();
}

I was right. findBySlug returns Optional<Category>. Then what's Optional? Java's architect has described it like below.

Optional is intended to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result," and using null for such was overwhelmingly likely to cause errors.

Thus, Optional is a class made to describe "no result" as methods' return. Especially, when the DB's query result is NULL, the methods using the result can have NullpointerException. In such cases, Optional<type> can be the return in the type when the return exists or it can be string, function, or error that is designated by user. Then how is the method's logic? After searching, JooqCategoryRepository is the only class to implement JooqCategoryRepository, its findBySlug() looks like below.

@Override
    public Optional<Category> findBySlug(String slug) {
        return this.dsl
                .selectFrom(CATEGORIES)
                .where(CATEGORIES.SLUG.eq(slug))
                .fetchOptional(CategoryRecordMapper.INSTANCE);
    }

                .fetchOptional(CategoryRecordMapper.INSTANCE);
below is a method of jooq and its document says that it
Throws:
DataAccessException - if something went wrong executing the query
TooManyRowsException - if the query returned more than one record

        model.addAttribute("categories", categoryService.getAllCategories());
So lets's go back to the 1st study at look into the above code.
When the code is run,

@Cacheable("categories")
    public List<Category> getAllCategories() {
        log.debug("Fetching all categories");
        return categoryRepository.findAll();
    }
the above code runs.

and when 
        return categoryRepository.findAll();
runs,


public interface CategoryRepository {

    Optional<Category> findBySlug(String slug);

    Category findById(Long id);

    List<Category> findAll();
}
the above code runs.

Then what's the repository? It's an interface spring uses to access DB.


댓글

이 블로그의 인기 게시물

Interface of Java

Data Analytics Overview(OLTP vs OLAP)

Leetcode