Create Tag Endpoint

Building on our list tag endpoint from the previous lesson, we'll now implement the create tag endpoint.

Request Structure

The CreateTagsRequest DTO enforces validation rules for tag creation:

@Data @Builder @NoArgsConstructor @AllArgsConstructor public class CreateTagsRequest { @NotEmpty(message = "At least one tag name is required") @Size(max = 10, message = "Maximum {max} tags allowed") private Set<@Size(min = 2, max = 30, message = "Tag name must be between {min} and {max} characters") @Pattern(regexp = "^[\\w\\s-]+$", message = "Tag name can only contain letters, numbers, spaces, and hyphens") String> names; }

Repository Enhancement

The TagRepository needs specialized methods for efficient tag lookup and creation:

@Repository public interface TagRepository extends JpaRepository<Tag, UUID> { Set<Tag> findByNameInIgnoreCase(Set<String> names); }

Service Layer Implementation

The TagService interface expands to include tag creation capabilities:

public interface TagService { List<Tag> createTags(Set<String> tagNames); }

The TagServiceImpl provides the creation logic with duplicate handling:

@Transactional @Override public List<Tag> createTags(Set<String> tagNames) { List<Tag> existingTags = tagRepository.findByNameIn(tagNames); Set<String> existingTagNames = existingTags.stream() .map(Tag::getName) .collect(Collectors.toSet()); List<Tag> newTags = tagNames.stream() .filter(name -> !existingTagNames.contains(name)) .map(name -> Tag.builder() .name(name) .posts(new HashSet<>()) .build()) .toList(); List<Tag> savedTags = new ArrayList<>(); if(!newTags.isEmpty()) { savedTags = tagRepository.saveAll(newTags); } savedTags.addAll(existingTags); return savedTags; }

Controller Implementation

The TagController handles the HTTP POST requests for tag creation:

@RestController @RequestMapping("/api/v1/tags") @RequiredArgsConstructor public class TagController { private final TagService tagService; private final TagMapper tagMapper; @PostMapping public ResponseEntity<List<TagDto>> createTags(@RequestBody CreateTagsRequest createTagsRequest) { List<Tag> savedTags = tagService.createTags(createTagsRequest.getNames()); List<TagDto> createdTagRespons = savedTags.stream().map(tagMapper::toTagResponse).toList(); return new ResponseEntity<>( createdTagRespons, HttpStatus.CREATED ); } }

Summary

  • Implemented tag creation with validation and duplicate prevention
  • Created transactional service method for atomic tag operations
  • Enhanced repository with efficient name-based tag lookup
© 2026 Devtiro Ltd. All rights reserved