Instruction file imported from rschaniel/hexagonal_spring_demo (
.github/instructions/infrastructure.instructions.md). Copyright stays with the author.
Infrastructure Layer Rules
You are generating code in the infrastructure layer (com.ultratrail.infrastructure).
This layer is the outbound adapter: it implements domain ports using Spring Data JPA.
Strict Rules
Allowed imports
com.ultratrail.domain.*(to implement repository ports)org.springframework.data.jpa.repository.*org.springframework.stereotype.Componentjakarta.persistence.*lombok.*java.*
Forbidden imports – NEVER add these
com.ultratrail.api.*com.ultratrail.application.*org.springframework.stereotype.Serviceorg.springframework.web.*
Repository Adapters
- Annotate with
@Componentand@AllArgsConstructor. - Each adapter implements exactly one domain repository interface.
- Delegate every method to a Spring Data JPA repository.
- Convert between domain objects and JPA entities using
fromDomain()andtoDomain(). - JPA entities must never appear in method signatures exposed to other layers.
- Naming:
<Entity>RepositoryAdapter(e.g.,RaceRepositoryAdapter).
@Component
@AllArgsConstructor
public class RaceRepositoryAdapter implements RaceRepository {
private final JpaRaceRepository jpaRaceRepository;
@Override
public Race save(Race race) {
return jpaRaceRepository.save(RaceEntity.fromDomain(race)).toDomain();
}
@Override
public Optional<Race> findById(String id) {
return jpaRaceRepository.findById(id).map(RaceEntity::toDomain);
}
@Override
public List<Race> findAll() {
return jpaRaceRepository.findAll().stream()
.map(RaceEntity::toDomain)
.collect(Collectors.toList());
}
@Override
public void delete(String id) {
jpaRaceRepository.deleteById(id);
}
}
Spring Data JPA Repositories
- Interface extending
JpaRepository<Entity, String>. - Naming:
Jpa<Entity>Repository(e.g.,JpaRaceRepository). - Only add custom query methods as needed.
public interface JpaRaceRepository extends JpaRepository<RaceEntity, String> {
List<RaceEntity> findByStatus(Race.RaceStatus status);
}
JPA Entities
- Annotate with
@Entity,@Table,@Data,@Builder,@NoArgsConstructor,@AllArgsConstructor. - Must include
fromDomain(Domain d)static factory method andtoDomain()instance method. - JPA entities stay confined to this package — never returned from use cases or controllers.
- Naming:
<Entity>Entity(e.g.,RaceEntity).
@Entity
@Table(name = "races")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RaceEntity {
@Id
private String id;
@Column(nullable = false)
private String name;
public static RaceEntity fromDomain(Race race) {
return RaceEntity.builder()
.id(race.getId())
.name(race.getName())
.build();
}
public Race toDomain() {
return Race.builder()
.id(this.id)
.name(this.name)
.build();
}
}