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