B
B
BRONNER2015-10-15 23:04:39
Java
BRONNER, 2015-10-15 23:04:39

What should be the service layer. Spring and beyond?

I relatively recently learned about such things as DAO, Service layer, partly as I studied individual Spring components, partly looking at other examples of very trivial projects, where the entire service layer was reduced to a DAO call wrapper, and the DAO itself is an EntityManager wrapper . This was not enough, more complex examples with more complex logic were required in order to thoroughly understand how exactly a real service layer should look like, what business logic it should contain, and which it should not, and maybe something would need to be taken out separately.
I would like to clarify a little, I'm not interested in Spring and not even in the web, but in general the service layer, as a template, so to speak.
And so, having some vision of all this, I wrote pseudo-code, but which clearly reflects the degree of how I understood this area. Let's say that we have a console application that processes user commands.
How valid is what I wrote and what could have been done differently?

@Command("category")
class CategoryController
{
  @Inject
  private CategoryService service;
  
  /**
  * Handles command like #category view <name>
  *
  * Output on error: 'You don not have enough permissions' | 'Category does not exists'
  * Output on success: 'Category(name = "myCategory")'
  */
  @SubCommand("view")
  @Permissions({Permission.USER})
  public void createCategory(SessionUser sender, String categoryName) throws ValidationException
  {
    Category category = service.getCategory(categoryName, sender.getFoo());
    sender.send(new Message(category));
  }
  
  /**
  * Handles command like #category create <name>
  *
  * Output on error: 'You don not have enough permissions' | 'Category with {name} already exists'
  *		| 'You have reached the limit of categories' | 'Invalid category format' | 'Invalid category length'
  * Output on success: 'Category {name} was successfully created'
  */
  @SubCommand("create")
  @Permissions({Permission.ADMIN})
  public void createCategory(SessionUser sender, String categoryName) throws ValidationException
  {
    service.createCategory(categoryName, sender);
    sender.send(new Message("Category {} was successfully created", categoryName));
  }
}

Service
@Service
@Transactional
class CategoryService
{
  @Inject
  private CategoryDao categoryDao;
  
  @Inject
  private UserDao userDao;
  
        /** Проблема 1
        * Бросаем исключение с сообщением пользователю в одном месте,
        * вместо дублирования обработки этого null в разных местах, где используется этот метод
        */
  public Category getCategory(String categoryName, FooObject foo) throws ValidationException
  {
    Category category = categoryDao.getByPK(new CategoryPK(categoryName, foo.getId()));
        if (category == null)
        {
            throw new ValidationException(Messages.CATEGORY_DOES_NOT_EXIST);
        }
        return category;
  }

        /** Проблема 2
        * Валидация и исключения
        */
  public void createCategory(@Nonnull String categoryName, @Nonnull SessionUser sender) throws ValidationException
  {
                // Проблема 3 - Дублирование кода, создание нового объекта
    Category category = categoryDao.getByPK(new CategoryPK(categoryName, sender.getFoo().getId()));
        if (category != null)
        {
            throw new ValidationException(Messages.CATEGORY_ALREADY_EXIST);
        }
    if (isCategoryLimitReached(sender.getName()))
    {
      throw new ValidationException(Messages.YOU_HAVE_REACHED_THE_LIMIT_OF_CATEGORIES);
    }
    if (!validateFormat(categoryName))
    {
      throw new ValidationException(Messages.INVALID_FORMAT);
    }
    if (!validateLength(categoryName))
    {
      throw new ValidationException(Messages.INVALID_LENGTH);
    }
    
    User user = userDao.find(sender.getName());
    category = new Category(categoryName, user, wrapFoo(sender.getFoo()));
    categoryDao.persist(category);
  }
  
  public boolead isCategoryLimitReached(String userName)
  {
    User user = userDao.find(userName);
    return user.getCategories().size() >= Config.CATEGORY_PER_USER;
  }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Viktor Maksimov, 2015-10-21
@ValorVl

In short, the service level is also the business logic level. Those. everything that does not concern the presentation logic should be there, work with the database, other services, in general, almost everything. In the controller, we process the input and prepare the data in the response.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question