chore: initial commit - project structure with domain, application, infrastructure, bootstrap, and basic dependencies
This commit is contained in:
49
infrastructure/pom.xml
Normal file
49
infrastructure/pom.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<project>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.pablotj</groupId>
|
||||
<artifactId>portfolio-api</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>infrastructure</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.pablotj</groupId>
|
||||
<artifactId>domain</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.pablotj</groupId>
|
||||
<artifactId>application</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MapStruct -->
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.pablotj.portfolio.infrastructure.persistence.adapter;
|
||||
|
||||
import com.pablotj.portfolio.domain.project.Project;
|
||||
import com.pablotj.portfolio.domain.project.ProjectId;
|
||||
import com.pablotj.portfolio.domain.project.port.ProjectRepositoryPort;
|
||||
import com.pablotj.portfolio.infrastructure.persistence.entity.ProjectJpaEntity;
|
||||
import com.pablotj.portfolio.infrastructure.persistence.mapper.ProjectJpaMapper;
|
||||
import com.pablotj.portfolio.infrastructure.persistence.repo.SpringDataProjectRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public class ProjectRepositoryAdapter implements ProjectRepositoryPort {
|
||||
|
||||
private final SpringDataProjectRepository repo;
|
||||
private final ProjectJpaMapper mapper;
|
||||
|
||||
public ProjectRepositoryAdapter(SpringDataProjectRepository repo, ProjectJpaMapper mapper) {
|
||||
this.repo = repo;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project save(Project p) {
|
||||
ProjectJpaEntity entity = mapper.toEntity(p);
|
||||
ProjectJpaEntity saved = repo.save(entity);
|
||||
return mapper.toDomain(saved);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Project> findById(ProjectId id) {
|
||||
return repo.findById(id.value()).map(mapper::toDomain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Project> findAll() {
|
||||
return repo.findAll().stream().map(mapper::toDomain).toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.pablotj.portfolio.infrastructure.persistence.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Table(name = "projects")
|
||||
@Getter @Setter
|
||||
public class ProjectJpaEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String title;
|
||||
|
||||
@Column(columnDefinition = "text")
|
||||
private String description;
|
||||
|
||||
private String url;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.pablotj.portfolio.infrastructure.persistence.mapper;
|
||||
|
||||
import com.pablotj.portfolio.domain.project.Project;
|
||||
import com.pablotj.portfolio.domain.project.ProjectId;
|
||||
import com.pablotj.portfolio.infrastructure.persistence.entity.ProjectJpaEntity;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface ProjectJpaMapper {
|
||||
|
||||
@Mapping(target = "id", ignore = true)
|
||||
ProjectJpaEntity toEntity(Project domain);
|
||||
|
||||
default Project toDomain(ProjectJpaEntity e) {
|
||||
if (e == null) return null;
|
||||
return Project.builder()
|
||||
.id(e.getId() == null ? null : new ProjectId(e.getId()))
|
||||
.title(e.getTitle())
|
||||
.description(e.getDescription())
|
||||
.url(e.getUrl())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.pablotj.portfolio.infrastructure.persistence.repo;
|
||||
|
||||
import com.pablotj.portfolio.infrastructure.persistence.entity.ProjectJpaEntity;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface SpringDataProjectRepository extends JpaRepository<ProjectJpaEntity, Long> {}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.controller;
|
||||
|
||||
import com.pablotj.portfolio.application.project.CreateProjectUseCase;
|
||||
import com.pablotj.portfolio.application.project.GetProjectUseCase;
|
||||
import com.pablotj.portfolio.infrastructure.rest.dto.CreateProjectRequest;
|
||||
import com.pablotj.portfolio.infrastructure.rest.dto.ProjectDto;
|
||||
import com.pablotj.portfolio.infrastructure.rest.mapper.ProjectRestMapper;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/projects")
|
||||
public class ProjectController {
|
||||
|
||||
private final CreateProjectUseCase createUC;
|
||||
private final GetProjectUseCase getUC;
|
||||
private final ProjectRestMapper mapper;
|
||||
|
||||
public ProjectController(CreateProjectUseCase createUC, GetProjectUseCase getUC, ProjectRestMapper mapper) {
|
||||
this.createUC = createUC;
|
||||
this.getUC = getUC;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<ProjectDto> all() {
|
||||
return getUC.all().stream().map(mapper::toDto).toList();
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<ProjectDto> byId(@PathVariable Long id) {
|
||||
return getUC.byId(id)
|
||||
.map(mapper::toDto)
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<ProjectDto> create(@Valid @RequestBody CreateProjectRequest request) {
|
||||
var cmd = new CreateProjectUseCase.Command(
|
||||
request.title(),
|
||||
request.description(),
|
||||
request.url()
|
||||
);
|
||||
var created = createUC.handle(cmd);
|
||||
var body = mapper.toDto(created);
|
||||
return ResponseEntity.created(URI.create("/api/projects/" + body.id())).body(body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public record CreateProjectRequest(
|
||||
@NotBlank String title,
|
||||
String description,
|
||||
String url
|
||||
) {}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public record ProjectDto(Long id, @NotBlank String title, String description, String url) {}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.pablotj.portfolio.infrastructure.rest.mapper;
|
||||
|
||||
import com.pablotj.portfolio.domain.project.Project;
|
||||
import com.pablotj.portfolio.infrastructure.rest.dto.ProjectDto;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface ProjectRestMapper {
|
||||
|
||||
@Mapping(target = "id", source = "id.value")
|
||||
ProjectDto toDto(Project domain);
|
||||
}
|
||||
Reference in New Issue
Block a user