Step 1: the catalog
The domain's settings
blueprint/petstore/env.yml
elasticore:
enable: true
config:
domainName: petstore
framework: springboot
mode: jpa
j2ee: jakarta
apiPath: "/api" # REST paths: /api/petstore/...
table:
prefix: ps_
referenceColumn: short # references to other aggregates: category_id
annotations:
genid: "genid(io.elasticore.springboot3.util.IdUtils.newId)"
namespace:
base: io.elasticore.sample.petstore
namespace: base lays out the hexagonal packages under io.elasticore.sample.petstore;
referenceColumn: short names the columns of id references after the field (category_id) - a
choice for a new project; ps_ prefixes the tables.
Categories, products, items
blueprint/petstore/model/entity.yml
entity:
# ---- catalog: reference data, edited by the shop ----------------------
Category:
meta: entity @root @editable @expose(20) @access(read=public) -- 분류 (Fish, Dogs ...)
fields:
categoryId: long @id @sequence
name: string(30)! @search(like)
description: string(3000)!
Product:
meta: entity @root @editable @expose(20) @access(read=public) @sort(name+) -- 상품 (Angelfish, Bulldog ...)
fields:
productId: long @id @sequence
name: string(30)! @search(like)
description: string(3000)!
category: Category @ManyToOne # -> categoryId
Item:
meta: entity @root @editable @expose(50) @access(read=public) @terms(pet, 반려동물, 상품) -- 판매 단위 (Large, Male Puppy ...)
fields:
itemId: long @id @sequence
name: string(30)! @search(like)
description: string(3000)!
imagePath: string(100)
unitCost: money(10.2)! @min(0.01, 'price must be positive') @terms(price, 가격)
product: Product @ManyToOne # -> productId
Country:
meta: entity @root @editable @expose(300) @access(read=public) -- 국가
fields:
isoCode: string(2) @id
name: string(80)! @search(like)
printableName: string(80)!
| Line | What it does |
|---|---|
@root @editable | reference data, edited field by field: public setters and PUT |
@expose(20) | the REST API with a page size of 20 (items 50, countries 300) |
@access(read=public) | anyone reads and searches; everything else - create, update, delete - is the administrator's |
@sort(name+) | products come back in name order unless a request asks otherwise |
@search(like) | search by part of the name, ignoring case in the v3 bundles (hexagonal, DDD, Kotlin, -Pv3) |
category: Category @ManyToOne | in the hexagonal bundle a reference to another root: the product holds categoryId |
money(10.2)! @min(0.01, '...') | a Money with a converter, @DecimalMin in the DTO, the same check in the TypeScript client |
@terms(...) | what the business calls it - synonyms in the Ossie export |
The labels after -- are the sample's own, in Korean (분류 = category, 상품 = product, 판매 단위 = unit of
sale, 국가 = country).
What it answers
curl -s https://petstore.elasticore.io/api/petstore/item/1000
curl -s -X POST https://petstore.elasticore.io/api/petstore/product/search \
-H 'Content-Type: application/json' -d '{"name":"gold"}'
GET /api/petstore/item/{id}andPOST /api/petstore/product/searchanswer anyone.{"name":"gold"}finds Golden Retriever and Goldfish;{"name":" BULL "}finds Bulldog - the value is trimmed and compared without case.- A search without
sortCodeis in name order (@sort(name+)). - Creating or changing a product without signing in answers 401; as a customer 403.
GET /api/petstore/item/99999answers 404{"detail":"Item not found","code":"not-found"};GET /api/petstore/item/abcanswers 400itemId: must be a number.- A price of 0 answers 400
price must be positive, the same words as the TypeScriptvalidateItem().
The catalog is filled from data.sql at start-up (its text and images are the original's,
CC BY-SA 3.0).
Next: customers who sign in.