overview of last week - ut · overview of last week ddd & data access luciano garcÍa-baÑuelos...
Post on 29-May-2020
1 Views
Preview:
TRANSCRIPT
Overviewoflastweek
DDD&DATAACCESSLUCIANOGARCÍA-BAÑUELOS 1
Application
Domain model
JPAadapterWeb UI
adapter
SalesServiceSalesController
PlantDTO
PlantRepository
Plant
OrdersRepository
PurchaseOrder
PODTO
Apictureoftodayslecture• Whatiftheexecutionofanenterprisesoftwarespansacrosstheboundariesofanorganization?◦ Goal:Interoperability◦ Challenges:Distribution,Heterogeneity, Loose-coupling,Security,etc.
• Ourfocuswillbeontwoarchitecturalstyles:◦ REST:Resourceorientedarchitecture
◦ SOA:Serviceorientedarchitecture
RESTLUCIANOGARCÍA-BAÑUELOS 2
Enterprisesoftw
are Presentation
Application logic
Dataaccess
Integrationlayer
Presentation
Application logic
Dataaccess
ServiceAnalysis&Design• ServiceAnalysis. identificationanddefinitionofthebusinessservices thatanorganizationprovidesorconsumes,internallyorexternally.
à Collectionofbusiness-level services,theircontextand theirinteractions
• ServiceAPIDesign. identificationanddefinitionoftechnicalservices(e.g.REST)tosupportthedeliveryofbusinessservices.
à CollectionofserviceAPIs(operations, inputs&outputs)
Decomposing InformationSystems
1. Functionalorcapability-drivendecomposition• Whichbusiness functions, capabilitiesorspecializationperformworkinthe
organization(organizational chart)
2. Process-drivendecomposition• Whichchainsofactivitiescreatevaluetotheorganization?
3. Data-drivendecomposition• Whatinformation isstored&circulatesintheorganization?
ServiceAnalysis andDesignMethodsCapability-drivenmethods• SteveJones:EnterpriseSOAAdoptionStrategies.InfoQ,2005.
Process-drivenmethods• ThomasErl:“Service-OrientedArchitecture,Concepts,Technology,andDesign”,PrenticeHall,2005
Data-drivenmethods• PetriSelonen:FromRequirementstoaRESTfulWebService.InREST:FromResearchtoPractice,Springer,2011
Outlook
DDD&DATAACCESSLUCIANOGARCÍA-BAÑUELOS 6
Application
Domain model
JPAadapterWeb UI
adapter
SalesService
PlantRepository
Plant
OrdersRepository
PurchaseOrder
SalesController
PlantDTOPODTO
RESTadapter
BuilditSalesRestController
PlantDTO’PODTO’
Theprobleminanutshell
RESTLUCIANOGARCÍA-BAÑUELOS 7
ServerClient
Request
Response
• Anapplicationprogramminginterface (API)specifieshowsomesoftwarecomponentsshouldinteractwitheachother
• OurproblemconsistsindesigningAPIsforsomeofthecomponentsintheenterprisesoftware
Capability-driven ServiceAnalysis• Service
◦ Sub-systemwhereacollectionoftasksareperformed toachieveagoal.
• Actor◦ Useror“external”system(application) thatinteractswithagivenservice
• Interaction◦ Anencounterbetweentwoservicesorbetweenanactorandaserviceto
achieveagoal.◦ Includes:physicalorelectronic,manualorautomatic
Capability-driven ServiceAnalysisdefinition of the services scope: what the services are
external actors driving or interacting with the services
reasons of the service-to-service and service-to-actor interactions
details of services to be delivered by the IT team
Services
Actors
Interactions
API Design (resources & operations)
WHAT
WHO
WHY
HOW
Capability-drivenAnalysis– LevelsTheframeworkisappliedatincreasinglyfinerlevelsofgranularity
• Level0.Definitionofthecoreservicestothebusinessdomain.Level1.DecompositionoftheLevel0modelintofiner-grainedservicesforeachcoreservice.
• Level2+ Refinementsofpreviouslevelstoidentifysupport&sharedservicesintegrating&complementingtheservicesalreadydefined.
“Level0”ContextDiagram
Customer
SuppliersLogistics Company
MakeItem(s)
Ship Order Add to StockShip Order Bill Customer
Invoice
InvoicePayment
Order
Supply
Deliver
Deliver
Contact
OrderCheck Stock
Manufacture Sales
Logistics & Warehouse Finance
What
Who
Why
Rule of thumb:2-8 services at this level
“Level1”ContextDiagram(Manufacture)What
Who
Why
Research & Development Supplies In
Regulatory Approval Product Manufacture
Regulator
Send For Approval ManufactureTest Final Product
Request newsupplies
ManageApproval
Verify
Verify Supplies
Quality Control
Packaging
Order Supplies Stock Management
Request Stock / Add Stock
TestProduct
Finish
Request Stock / Add Stock
Supply Stock
External
Manufacture
Sales
Logistics & Warehouse
Finance
Process-DrivenServiceDesign1. Identifywhichprocess(es)needtobesupportedandtheiractors
2. Captureeachprocess(e.g.asaprocessmodel)
3. Analyzetasks/eventsinprocessmodeltoidentify:◦ Atomicinteractions(operations) thattheprocessshouldprovide◦ Atomicinteractions(operations) thattheprocessrequires fromothersystems
Supplier
CustomerProcurement Service
Warehouse Inventory Control
Service
FinanceInvoicing Service
Inte
rface Inte
rface
Inte
rface
Supplier(Order Management Service)
Process-Driven ServiceDesignSteps1.IdentifyingProcess&Actors
Process we need to support
Service Required by Process
Service Required by Process
External Actor
Process-Driven ServiceDesign2.CapturingtheOrderManagementProcess
Step3.Identifyoperations(OrderManagementService)Providedoperations(tocustomer)
• ReceiveRFQ
• Receiveorder
Requiredoperations
• Frominventorycontrol◦ Checkstockavailability◦ Requestorder shipment
• Invoicing◦ Requestinvoicing
Step3.IdentifyOperations• Lessobviousprovided operationsofordermanagementservice◦ Cancelorder/requestordercancellation◦ Modifyorder/request ordermodification◦ Checkorderstatus◦ …
Step3.IdentifyoperationsLessobviousrequired operations
• Topreparequote◦ Retrievepricelist◦ Retrievecustomerdata(contractualterms)
• Toprepareshipmentorder◦ Retrievecustomerdeliverydata
• Toprepareinvoicerequest◦ Retrievecustomerinvoicingdata
Rentit’s domain
DDD&DATAACCESSLUCIANOGARCÍA-BAÑUELOS 19
Plant catalogand purchase
orders
Maintenance plan
Plant reservation
Invoicing
Plant transportation
Domain
Maintenance
Reservations
Transportation
Invoicing
Sales(core)
Sub-domain
BoundedContext
Rentit’s domainmodel
DDD&DATAACCESSLUCIANOGARCÍA-BAÑUELOS 20
PurchaseOrder
BusinessPeriod
Address
Comment
ContactPerson
siteAddr
notes
rentalPeriod
contact
Customerrepresentatives
orders
customer
PlantInventoryEntry
PlantInventoryItem
PlantReservation
MaintenancePlan
MaintenanceTask
BusinessPeriodBusinessPeriod
plant
stock
type
reservation
rentalplant
scheduleschedule
tasks
maintPlan
plant
plantSpec
reservation
*
*
*
*1
1
1
*
1
1
1
1
0..1
0..11
1
1
11
0..1PurchaseOrder
BusinessPeriod
Address
Comment
ContactPerson
siteAddr
notes
rentalPeriod
contact
Customerrepresentatives
orders
customer
PlantInventoryEntry
PlantInventoryItem
PlantReservation
MaintenancePlan
MaintenanceTask
BusinessPeriodBusinessPeriod
plant
stock
type
reservation
rentalplant
scheduleschedule
tasks
maintPlan
plant
plantSpec
reservation
*
*
*
*1
1
1
*
1
1
1
1
0..1
0..11
1
1
11
0..1
Examplerepository
DDD&DATAACCESSLUCIANOGARCÍA-BAÑUELOS 21
Data-DrivenServiceDesign• SuitableparticularlyforRESTfulservicedesign
• Startsfromadatamodel
• Keyentitiesinmodelbecome“resources”
• CRUDframeworkusedtoidentifyoperations
• Onepossiblemethod(youmustreadit!):◦ PetriSelonen:FromRequirementstoaRESTfulWebService.InREST:FromResearchtoPractice,Springer,2011
Data-DrivenServiceDesign1. Capturedomainmodel◦ High-leveldatamodel
2. Refinedomainmodelintoresourcemodel◦ Identifyresourcesofdifferent typesandhypermedia relations
3. DeriveRESTAPI◦ UseCRUD(orSCRUD)framework
REST•RESTstandsforRepresentationalStateTransfer◦ Introduced/definedin2000byRoyFieldinginhisDoctoralDissertation
◦ BTW,FieldingisoneoftheprincipalauthorsofHTTPspecificationversions1.0and1.1
•RESTisanarchitecturestylefordesigningnetworkedapplications◦ Inmanyways,theWorldWideWeb itself,canbeviewedasaREST-basedarchitecture
•RESTisnotanstandardnoraproductØ Incontrast,SOAP,WSDLandaplethoraofWS-*standardsprovideafoundationforSOAontheWeb
RESTLUCIANOGARCÍA-BAÑUELOS 24
(Conceptual)buildingblocks
RESTLUCIANOGARCÍA-BAÑUELOS 25
URI
HTTP
Hypermedia
Resourceidentifiere.g.,http://en.wikipedia.org/wiki/Representational_State_Transfer
InteractionprotocolMethods:GET,POST,PUT,DELETE,etc.
Statuscodes:200Ok,404Notfound, etc.Metadata:Contentformat,Location,etc.
InteractionmodelTraversalofhyperlinks
Approachnumber1• Foreachresourceidentifiedinyoursystem,listallpossibleoperation andassociateauniqueURItoeachofthem
RESTLUCIANOGARCÍA-BAÑUELOS 26
/getPlant/getAllPlants/isPlantAvailable
/createPurchaseOrder/acceptPurchaseOrder/rejectPurchaseOrder/getPurchaseOrder/getAllPurchaseOrders/updatePurchaseOrder/isPurchaseOrderOpen/isPurchaseOrderPaid
/createInvoice/sendInvoiceToCustomer/getInvoiceStatus/acceptInvoice/rejectInvoice
/createPlantHireRequest/acceptPlantHireRequest/rejectPlantHireRequest/updatePlantHireRequest
/createRemittanceAdivice/createInvoiceResponse/createCreditNote...
Example
RESTLUCIANOGARCÍA-BAÑUELOS 27
Plant
name: Stringdescription: Stringprice: Float
Customer
name: StringvatNumber: String
PurchaseOrder
start: Dateend: Datecost: Floatstatus: POStatus
«resource instance» Plant
name: Stringdescription: Stringprice: Float
«resource instance» PurchaseOrder
start: Dateend: Datecost: Float
«resource instance» Plant
name: Stringdescription: Stringprice: Float
«resource instance» PurchaseOrder
start: Dateend: Datecost: Float
Example:Resourcemodel
RESTLUCIANOGARCÍA-BAÑUELOS 28
«container» PurchaseOrders
«container» Plants
«container» POPlants
«root» RentIt REST endpoint
{URI http://rentit.com/rest}
http://rentit.com/rest/pos
http://rentit.com/rest/pos/{po.id}/plants
http://rentit.com/rest/pos/{po.id}
HTTPverbs&behaviormodel• Convenienceoperations◦ HEAD Retrievesmetadata◦ OPTIONS Askswhichmethodsaresupportedbyaresource
• Basicoperations◦ GET Retrievesarepresentationforagivenresource◦ DELETE Deletesanexistingresource
• Otheroperations◦ PUT Canbeusedforcreatingorreplacingaresource◦ POST Canalsobeusedforcreatingorupdatingaresource◦ PATCH Updatesaresource
RESTLUCIANOGARCÍA-BAÑUELOS 29
ResourcecreationwithPOST
RESTLUCIANOGARCÍA-BAÑUELOS 30
RentItBuildIt
POST /poshttp://rentit.com/rest
<purchaseOrder><rentalPeriod><start>2017-06-21</start><end>2017-06-24</end>
<rentalPeriod><plant><name>Excavator</name>
<plant></purchaseOrder>
HTTP/1.1201CreatedLocation: /pos/1253
Resourceretrieval
RESTLUCIANOGARCÍA-BAÑUELOS 31
RentItBuildIt
GET /pos/1253http://rentit.com/rest
HTTP/1.1200Ok<purchaseOrder>
<id>1253</id><rentalPeriod><start>2017-06-21</start><end>2017-06-24</end>
<rentalPeriod><cost>1500.00</cost><plant><name>Excavator</name>
<plant><status>OPEN</status>
</purchaseOrder>
Resource creation: PUTvs.POST• IfPUTisused,then:◦ theresourceidentifier issetbytheclient
◦ thefullrepresentationoftheresourceisalwaysprovided
RESTLUCIANOGARCÍA-BAÑUELOS 32
☛ UsePUTonly inscenarioswherea“fullreplacement” oftheresourcerepresentationisimplied
• IfPOSTisused,then:◦ theresourceidentifier issetbytheserver
◦ onlyapartoftherepresentationneedstobeexchanged
<purchaseOrder><id>1253</id><start>2016-03-21</start><end>2016-03-24</end><cost>1500.00</cost><plant>
<name>Excavator</name><plant><status>OPEN</status>
</purchaseOrder>
<purchaseOrder><start>2016-03-21</start><end>2016-03-24</end><plant>
<name>Excavator</name><plant>
</purchaseOrder>
PUT /pos/1235 POST /pos
Updating theresources (take1)• Sofar,thereisnotconsensusonhowtoimplementthe"update"operationonresources◦ SomesaythatweshouldusePUT.Butshouldweusefullorpartialrepresentation?
◦ SomeotherssaythatweshouldusePOST
• Toavoidambiguitywewilldothefollowing:◦ POST Creation◦ PUT Replacement◦ PATCH Partialupdate
• Butthisisjustaconventionandnotanorm
RESTLUCIANOGARCÍA-BAÑUELOS 33
<purchaseOrder><end>2016-03-31</end>
</purchaseOrder>PATCH /pos/1235
URIpatternsandHTTPverbs
RESTLUCIANOGARCÍA-BAÑUELOS 34
URI HTTPverb Comments
/pos GET Retrieveallpurchaseorders
POST Create newpurchaseorder
/pos/{po.id} GET Retrieveaspecific purchaseorder
PATCH Updateapurchaseorder
DELETE Removeapurchaseorder
/pos/{po.id}/plants GET Retrieveallplantsassociatedtoagivenpurchaseorder
POST Addaplanttoagiven purchaseorder
/pos/{po.id}/plants/{plant.id} GET Retrieve aspecificplantwithinapurchaseorder
PATCH Modify aplant?
DELETE Remove aplantfromapurchaseorder
Queryingandfiltering• Insomecases,wewillneedtorestrictourattentiontoasubsetofresourceinstances:◦ Onlyopenpurchaseorders◦ Invoiceswithinafiscalperiod
• Itisalsointerestingtousecertaincriteriawhenqueryinga“container”◦ Setofplantsofcertaincapacitiesandavailableinforagivenperiodof time
• Inthosecases,useURIquerytemplatesoftheform:
• Note:AlltheaboveURIsshouldberequestedviaanHTTPGET
RESTLUCIANOGARCÍA-BAÑUELOS 35
GET/plants?name=excavator
GET/phrs?status=OPEN
HTTPstatuscodes• TheHTTPstatuscodesprovidemetadataaboutthestateofresources
• TheyarepartofwhatmakestheWebarichplatformforbuildingdistributedsystems
• Theycoverfivebroadcategories◦ 1xx– Metadata
◦ 2xx– Everything’s fine
◦ 3xx– Redirection
◦ 4xx– Clientdidsomething wrong
◦ 5xx– Serverdidabadthing
RESTLUCIANOGARCÍA-BAÑUELOS 36
Thehappypath:
200 Ok201 Created202 Accepted204 Nocontent
“Location”shouldcontaintheURIforaccessingtheresourcewhenever itbecomesavailable:• 201– immediately• 202– subsequently
HTTPstatuscodes• TheHTTPstatuscodesprovidemetadataaboutthestateofresources
• TheyarepartofwhatmakestheWebarichplatformforbuildingdistributedsystems
• Theycoverfivebroadcategories◦ 1xx– Metadata
◦ 2xx– Everything’s fine
◦ 3xx– Redirection
◦ 4xx– Clientdidsomething wrong
◦ 5xx– Serverdidabadthing
RESTLUCIANOGARCÍA-BAÑUELOS 37
Exceptionnotification:
400 Badrequest404 Notfound405 Methodnotallowed406 Notacceptable409 Conflict
Implementingtheintegrationlayer
RESTLUCIANOGARCÍA-BAÑUELOS 38
Domainobjectvs.Resource
RESTLUCIANOGARCÍA-BAÑUELOS 39
@Entity@Getterpublic class Plant {
@Idprivate Long id;private String name;private String description;private BigDecimal price;
}
@Datapublic class PlantDTO extendsResourceSupport {
private Long _id;private String name;private String description;private BigDecimal price;
}
public class PlantAssembler extendsResourceAssemblerSupport<Plant, PlantDTO> {public PlantAssembler() {
super(InventoryRestController.class, PlantDTO.class);}public PlantDTO toResource(Plant plant) {
...}public List<PlantDTO> toResource(List<Plant> plants) {
...}
}
Package:~.application.service
Package:~.application.dtoPackage:~.domain.model
RESTservicefaçade
RESTLUCIANOGARCÍA-BAÑUELOS 40
@RestController@RequestMapping("/api/orders")public class PurchaseOrderRestController {
@RequestMapping(method = RequestMethod.GET, path = "")public List<PurchaseOrderResource> getAllPOs() {
...}
@PostMappingpublic ResponseEntity<Plant> createPO(@RequestBody PurchaseOrderResource res) {
...}
@GetMapping("/pos/{id}")public PurchaseOrderResource getPO(@PathVariable Long id) {
...}
@PostMapping("/pos/{id}/plants")public ResponseEntity<PurchaseOrderResource> addPlantToPO(@PathVariable Long id,
@RequestBody PlantResource res) {...
}}
Resourcecreation
RESTLUCIANOGARCÍA-BAÑUELOS 41
@RestController@RequestMapping("/api/orders")public class PurchaseOrderRestController {
@AutowiredSalesService salesService;
@PostMappingpublic ResponseEntity<PurchaseOrderDTO> createPO(
@RequestBody PurchaseOrderDTO inputPO) {
PurchaseOrderDTO po = salesService.createPO(inputPO);
HttpHeaders headers = new HttpHeaders();URI location = ServletUriComponentsBuilder.fromCurrentRequestUri().
pathSegment(po.get_id()).build().toUri();headers.setLocation(location);
return new ResponseEntity<>(po, headers, HttpStatus.CREATED);
}}
Example
RESTLUCIANOGARCÍA-BAÑUELOS 42
$ curl -v -X POST -H "Content-type: application/xml" \-d @po.xml http://localhost:8080/api/orders
> POST /api/orders HTTP/1.1> Host: localhost:8080> Accept: */*> Content-type: application/xml
< HTTP/1.1 201 Created< Location: http://localhost:8080/api/orders/1
Retrievingaresource
RESTLUCIANOGARCÍA-BAÑUELOS 43
@RestController@RequestMapping("/api/orders")public class PurchaseOrderRestController {
@AutowiredSalesService salesService;
@GetMapping@ResponseStatus(HttpStatus.OK)public List<PurchaseOrderDTO> getAllPOs() {
return salesService.findAllPurchaseOrders();}
}
Contentnegotiation
RESTLUCIANOGARCÍA-BAÑUELOS 44
$curl-H"Accept:application/json"http://localhost:8080/api/orders<HTTP/1.1200OK<Content-Type:application/json;charset=UTF-8
{"purchaseOrder":[{
"startDate":1381093200000,"endDate":1381438800000,"total":1250.0,"plant":null
}]}
Contentnegotiation
RESTLUCIANOGARCÍA-BAÑUELOS 45
$curl-H"Accept:application/xml"http://localhost:8080/api/orders
<HTTP/1.1200OK<Content-Type:application/xml;charset=UTF-8
<?xmlversion="1.0"encoding="UTF-8"standalone="yes"?><purchaseOrders>
<purchaseOrder><endDate>2013-10-11T00:00:00+03:00</endDate><startDate>2013-10-07T00:00:00+03:00</startDate><total>1250.0</total>
</purchaseOrder></purchaseOrders>
ExceptionhandlingwithinourRESTcontroller
46
@RestController@RequestMapping("/api/orders")public class PurchaseOrderRestController {
@ExceptionHandler({PlantUnavailableException.class, InvalidRentalPeriodException.class})
public ResponseEntity<String> handleBadRequest(Exception ex) {return new ResponseEntity<>(ex.getMessage(), HttpStatus.CONFLICT);
}
@ExceptionHandler(EntityNotFoundException.class)public ResponseEntity<String> handleNotFound(Exception ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);}
}
RESTLUCIANOGARCÍA-BAÑUELOS
top related