P02: Maven multi-module skeleton — domain, application, adapter-persistence, adapter-web, bootstrap
build / build (push) Failing after 18s
build / build (push) Failing after 18s
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
name: build
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
# Runner ke paas sirf do label hain (ubuntu-latest, node-22) — Java ka koi nahi.
|
||||
# Isliye job ko Maven ke apne image ke andar chalate hain. Build ka environment
|
||||
# pinned ho jaata hai: jo yahan chala, wahi laptop pe chalega.
|
||||
container:
|
||||
image: maven:3.9-eclipse-temurin-21
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build aur test
|
||||
run: mvn -B clean verify
|
||||
@@ -0,0 +1,4 @@
|
||||
target/
|
||||
*.class
|
||||
.idea/
|
||||
*.iml
|
||||
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.3.4</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<groupId>dev.shopforge</groupId>
|
||||
<artifactId>shopforge</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>ShopForge</name>
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
<module>shopforge-domain</module>
|
||||
<module>shopforge-application</module>
|
||||
<module>shopforge-adapter-persistence</module>
|
||||
<module>shopforge-adapter-web</module>
|
||||
<module>shopforge-bootstrap</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.shopforge</groupId><artifactId>shopforge-domain</artifactId><version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.shopforge</groupId><artifactId>shopforge-application</artifactId><version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.shopforge</groupId><artifactId>shopforge-adapter-persistence</artifactId><version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.shopforge</groupId><artifactId>shopforge-adapter-web</artifactId><version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
</project>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent><groupId>dev.shopforge</groupId><artifactId>shopforge</artifactId><version>0.1.0-SNAPSHOT</version></parent>
|
||||
<artifactId>shopforge-adapter-persistence</artifactId>
|
||||
<name>ShopForge :: adapter-persistence</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency><groupId>dev.shopforge</groupId><artifactId>shopforge-domain</artifactId></dependency>
|
||||
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package dev.shopforge.persistence;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.Optional;
|
||||
|
||||
interface JpaShopRepository extends JpaRepository<ShopEntity, String> {
|
||||
Optional<ShopEntity> findBySubdomain(String subdomain);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.shopforge.persistence;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
/** DB ka naksha. Ye domain ka Shop NAHI hai — jaanbujhkar alag rakha gaya hai. */
|
||||
@Entity
|
||||
@Table(name = "shop")
|
||||
public class ShopEntity {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
private String naam;
|
||||
|
||||
@Column(unique = true)
|
||||
private String subdomain;
|
||||
private boolean active;
|
||||
|
||||
protected ShopEntity() { }
|
||||
|
||||
public ShopEntity(String id, String naam, String subdomain, boolean active) {
|
||||
this.id = id; this.naam = naam; this.subdomain = subdomain; this.active = active;
|
||||
}
|
||||
|
||||
public String getId() { return id; }
|
||||
public String getNaam() { return naam; }
|
||||
public String getSubdomain() { return subdomain; }
|
||||
public boolean isActive() { return active; }
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package dev.shopforge.persistence;
|
||||
|
||||
import dev.shopforge.domain.*;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.util.Optional;
|
||||
|
||||
/** ADAPTER — domain ka port yahan poora hota hai. Anuvaad yahin hota hai, kahin aur nahi. */
|
||||
@Repository
|
||||
public class ShopRepositoryAdapter implements ShopRepository {
|
||||
|
||||
private final JpaShopRepository jpa;
|
||||
|
||||
ShopRepositoryAdapter(JpaShopRepository jpa) { this.jpa = jpa; }
|
||||
|
||||
@Override
|
||||
public Optional<Shop> bySubdomain(String subdomain) {
|
||||
return jpa.findBySubdomain(subdomain).map(this::toDomain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shop save(Shop shop) {
|
||||
ShopEntity saved = jpa.save(new ShopEntity(
|
||||
shop.id().value(), shop.naam(), shop.subdomain(), shop.active()));
|
||||
return toDomain(saved);
|
||||
}
|
||||
|
||||
private Shop toDomain(ShopEntity e) {
|
||||
return new Shop(new TenantId(e.getId()), e.getNaam(), e.getSubdomain(), e.isActive());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent><groupId>dev.shopforge</groupId><artifactId>shopforge</artifactId><version>0.1.0-SNAPSHOT</version></parent>
|
||||
<artifactId>shopforge-adapter-web</artifactId>
|
||||
<name>ShopForge :: adapter-web</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency><groupId>dev.shopforge</groupId><artifactId>shopforge-application</artifactId></dependency>
|
||||
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.shopforge.web;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
class HealthController {
|
||||
|
||||
@GetMapping("/hello")
|
||||
Map<String, String> hello() {
|
||||
return Map.of("service", "shopforge", "status", "up");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.shopforge.web;
|
||||
|
||||
import dev.shopforge.application.ShopService;
|
||||
import dev.shopforge.domain.Shop;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/shops")
|
||||
class ShopController {
|
||||
|
||||
private final ShopService service;
|
||||
|
||||
ShopController(ShopService service) { this.service = service; }
|
||||
|
||||
@GetMapping("/{subdomain}")
|
||||
ShopResponse get(@PathVariable String subdomain) {
|
||||
Shop s = service.bySubdomain(subdomain);
|
||||
return new ShopResponse(s.id().value(), s.naam(), s.subdomain(), s.active());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package dev.shopforge.web;
|
||||
|
||||
/** DTO — domain ka Shop bahar nahi jaata (Java Doc 23 ka sabak). */
|
||||
record ShopResponse(String id, String naam, String subdomain, boolean active) { }
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent><groupId>dev.shopforge</groupId><artifactId>shopforge</artifactId><version>0.1.0-SNAPSHOT</version></parent>
|
||||
<artifactId>shopforge-application</artifactId>
|
||||
<name>ShopForge :: application</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency><groupId>dev.shopforge</groupId><artifactId>shopforge-domain</artifactId></dependency>
|
||||
<!-- sirf spring-context — DI ke liye. Web nahi, JPA nahi. -->
|
||||
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,7 @@
|
||||
package dev.shopforge.application;
|
||||
|
||||
public class ShopNotFound extends RuntimeException {
|
||||
public ShopNotFound(String subdomain) {
|
||||
super("Is subdomain ki koi shop nahi mili: " + subdomain);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.shopforge.application;
|
||||
|
||||
import dev.shopforge.domain.Shop;
|
||||
import dev.shopforge.domain.ShopRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/** Use case. Domain ka port maangta hai — JPA ka naam tak nahi jaanta. */
|
||||
@Service
|
||||
public class ShopService {
|
||||
|
||||
private final ShopRepository shops;
|
||||
|
||||
public ShopService(ShopRepository shops) { // constructor injection — Java Doc 22
|
||||
this.shops = shops;
|
||||
}
|
||||
|
||||
public Shop bySubdomain(String subdomain) {
|
||||
return shops.bySubdomain(subdomain)
|
||||
.orElseThrow(() -> new ShopNotFound(subdomain));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent><groupId>dev.shopforge</groupId><artifactId>shopforge</artifactId><version>0.1.0-SNAPSHOT</version></parent>
|
||||
<artifactId>shopforge-bootstrap</artifactId>
|
||||
<name>ShopForge :: bootstrap</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency><groupId>dev.shopforge</groupId><artifactId>shopforge-adapter-web</artifactId></dependency>
|
||||
<dependency><groupId>dev.shopforge</groupId><artifactId>shopforge-adapter-persistence</artifactId></dependency>
|
||||
<dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency>
|
||||
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- fat jar sirf YAHIN banta hai — baaki module saadi jar hain -->
|
||||
<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.shopforge;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = "dev.shopforge")
|
||||
@EntityScan("dev.shopforge.persistence")
|
||||
@EnableJpaRepositories("dev.shopforge.persistence")
|
||||
public class ShopForgeApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ShopForgeApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
spring.datasource.url=jdbc:h2:mem:shopforge
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
server.port=19080
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.shopforge;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class ContextLoadTest {
|
||||
@Test
|
||||
void context_uthta_hai() { }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.shopforge</groupId><artifactId>shopforge</artifactId><version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>shopforge-domain</artifactId>
|
||||
<name>ShopForge :: domain</name>
|
||||
|
||||
<!-- 🔴 YAHAN JAANBUJHKAR KUCH NAHI HAI.
|
||||
Ek bhi Spring dependency nahi. Ye khaalipan is module ka poora matlab hai. -->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
package dev.shopforge.domain;
|
||||
|
||||
/** Ek shop. Sirf Java — koi annotation, koi framework nahi. */
|
||||
public record Shop(TenantId id, String naam, String subdomain, boolean active) {
|
||||
|
||||
public Shop activate() { return new Shop(id, naam, subdomain, true); }
|
||||
public Shop deactivate() { return new Shop(id, naam, subdomain, false); }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.shopforge.domain;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* PORT — domain batata hai ki use kya chahiye, na ki wo kahan se aayega.
|
||||
* Iska implementation adapter-persistence me hai. Teer domain ki taraf aata hai, jaata nahi.
|
||||
*/
|
||||
public interface ShopRepository {
|
||||
Optional<Shop> bySubdomain(String subdomain);
|
||||
Shop save(Shop shop);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.shopforge.domain;
|
||||
|
||||
/** Ek shop ki pehchaan. Value object — bani to badal nahi sakti. */
|
||||
public record TenantId(String value) {
|
||||
public TenantId {
|
||||
if (value == null || value.isBlank())
|
||||
throw new IllegalArgumentException("TenantId khaali nahi ho sakta");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.shopforge.domain;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ShopTest {
|
||||
|
||||
@Test
|
||||
void khaali_tenantId_bante_hi_mana_hai() {
|
||||
assertThrows(IllegalArgumentException.class, () -> new TenantId(" "));
|
||||
}
|
||||
|
||||
@Test
|
||||
void activate_naya_object_deta_hai_purana_nahi_badalta() {
|
||||
Shop band = new Shop(new TenantId("t1"), "Chai Point", "chaipoint", false);
|
||||
Shop chalu = band.activate();
|
||||
assertFalse(band.active());
|
||||
assertTrue(chalu.active());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user