Skip to main content
ElastiCORE 3.0 is a release candidate: 3.0.261022-rc1 on Maven Central. Projects on the 2.2 line: see the 2.2 documentation.
Version: 3.0

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)!
LineWhat it does
@root @editablereference 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 @ManyToOnein 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} and POST /api/petstore/product/search answer anyone.
  • {"name":"gold"} finds Golden Retriever and Goldfish; {"name":" BULL "} finds Bulldog - the value is trimmed and compared without case.
  • A search without sortCode is in name order (@sort(name+)).
  • Creating or changing a product without signing in answers 401; as a customer 403.
  • GET /api/petstore/item/99999 answers 404 {"detail":"Item not found","code":"not-found"}; GET /api/petstore/item/abc answers 400 itemId: must be a number.
  • A price of 0 answers 400 price must be positive, the same words as the TypeScript validateItem().

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.