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