2

Let's say a sample case where we want to create an article with some tags. Following are my pseudocode, and the questions are at the bottom.

Sample Case

Request:

@Data
public class CreateArticleRequest {
    @NotEmpty
    String content;
    @NotEmpty
    List<Integer> tagIds;
}

Controller:

@RestfulController
public class ArticleController {
    // ... some autowire ...
    public void create(@Valid CreateArticleRequest request) {
        // (i) shall I do this?
        if(!repository.doesAllTagIdsExists(request.getTagIds())) {
            throw new RuntimeException("bad tagIds");
        }

        service.create(request); // or shall I put something here?
    }
}

Service:

@Service
public class ArticleService {
    // ... some autowire ...
    public void create(CreateArticleRequest request) {
        Article article = new Article();
        article.setContent(request.getContent());
        Article createdArticle = repository.createArticle(article);
        // (ii)
        repository.createArticleTagRelation(createdArticle.getId(), request.getTagIds());
    }
}

Model:

@Data class Article { int id; String content; }
@Data class Tag { int id; ...sth else... }

Database:

Table "article" columns: id, content
Table "tag" columns: id, sth_else
Table "article_has_tag" columns: article_id, tag_id

Questions

  1. Of course, we need to validate whether the tagId exists and is visible to this user, instead of trusting it and directly putting into database. Where shall I do it? Shall I do it at (i)? (I know we can validate things like "not empty" etc using @NotEmpty, but how can I validate that tagIds which need database?)
  2. At (ii) in Service, shall the createArticle + createArticleTagRelation be handled here, or combine them into one repository function repository.createArticleAndWithTagRelation?
  3. Is it good to have such XXXRequest and YYYResponse objects? Is there anything wrong with my overall architecture?

1 Answer 1

1

Well, typically a tag is used as short link to some object.

'An article has a tag' means it can be located by this tag. This also means that tag text should be unique.
In provided code snippets there is no such checking, so think this is first thing you should care of.

Of course, we need to validate whether the tagId exists and is visible to this user

This 'tagId' field is actually internal ( for backend ) information, best practice is to isolate internally used properties from input DTOs. So DTO 'CreateArticleRequest' should have something like this:

public class CreateArticleRequest  {
 private Set<String> tags = new TreeSet<>();
 ..
}

instead of full tag entities. Also using 'Set' will help to keep tags unique right from REST API input, without additional checks.

Next step will be tag validation yes, basically you'll need to check if tag currently present in database by it's text. If present - link it to article, otherwise - create & persist new tag entity and also link to article. As because you already have service level - better to put this logic there.

At (ii) in Service, shall the createArticle + createArticleTagRelation be handled here, or combine them into one repository function repository.createArticleAndWithTagRelation

This is not always technically possible, but of course better to save all related data at once, in single transaction.

Is it good to have such XXXRequest and YYYResponse objects?

It depends on project nature and overall API requirements.

For example having common request/response DTOs is good when you need to maintain backward compatibility as long as possible or put common additional fields inside, like 'request time', 'request id' and so on.

1
  • Thanks very much for your detailed reply!
    – ch271828n
    Feb 9, 2020 at 23:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.