Skip to content

Commit 4d7c8a3

Browse files
authored
Added book import functionality (media data streaming example) (#89)
* Implemented books import functionality * Added info about media data streaming to Demonstrated Features in README * bumped version of spring-boot * Removed persistence of Csv entity * Added to readme * Removed dataType field * Simplified handler method
1 parent 8583f7e commit 4d7c8a3

13 files changed

Lines changed: 230 additions & 4 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Domain Model related Features:
5656
- Use of [Aspects](https://cap.cloud.sap/docs/cds/cdl#aspects) in the Model Definition such as the [`managed` or `cuid` Aspect](https://cap.cloud.sap/docs/cds/common#common-reuse-aspects) in [Books](db/books.cds)
5757
- [Input validation](https://cap.cloud.sap/docs/cds/annotations#input-validation) using model annotation `@assert.format`
5858
- [Data Localization](https://cap.cloud.sap/docs/guides/localized-data) for [Books](db/books.cds)
59+
- Use of [Media Data](https://cap.cloud.sap/docs/guides/providing-services#media-data) in [Books](db/books.cds) and [AdminService](srv/admin-service.cds)
5960

6061
Service Model related Features:
6162

@@ -64,6 +65,8 @@ Service Model related Features:
6465
- Add annotations for [searchable elements](https://github.wdf.sap.corp/pages/cap/java/query-api#select) in the [Admin Service](srv/admin-service.cds)
6566
- [Localized Messages](https://cap.cloud.sap/docs/java/indicating-errors) in the [Admin Service Event Handler](srv/src/main/java/my/bookshop/handlers/AdminServiceHandler.java)
6667
- role-based restrictions in [AdminService](srv/admin-service.cds) and [ReviewService](srv/review-service.cds)
68+
- Use of [`@cds.persistence.skip`](https://cap.cloud.sap/docs/advanced/hana#cdspersistenceskip) in [AdminService](srv/admin-service.cds)
69+
- [Media Data](https://cap.cloud.sap/docs/guides/providing-services#media-data) processing in the [Admin Service Event Handler](srv/src/main/java/my/bookshop/handlers/AdminServiceHandler.java)
6770

6871
User Interface related Features:
6972

@@ -73,6 +76,7 @@ User Interface related Features:
7376
- UI Annotations for custom actions in the [Browse Books](app/browse/fiori-service.cds) and [Manage Books](app/admin/fiori-service.cds) UI, including annotations for a button and a popup
7477
- [Value Help](https://cap.cloud.sap/docs/cds/annotations#odata) for [Books](app/orders/fiori-service.cds) and [Authors](app/common.cds)
7578
- [Model Localization](https://cap.cloud.sap/docs/guides/i18n) for [English](app/_i18n/i18n.properties) and [German](app/_i18n/i18n_de.properties) language for static texts
79+
- [Custom File Upload extension](app/admin/webapp/extension/Upload.js) which provides a button for uploading `CSV` files
7680

7781
CDS Maven Plugin Features:
7882

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
sap.ui.define(
2+
["sap/m/MessageBox", "sap/m/MessageToast"],
3+
function (MessageBox, MessageToast) {
4+
"use strict";
5+
6+
function _createUploadController(oExtensionAPI) {
7+
var oUploadDialog;
8+
9+
function setOkButtonEnabled(bOk) {
10+
oUploadDialog && oUploadDialog.getBeginButton().setEnabled(bOk);
11+
}
12+
13+
function setDialogBusy(bBusy) {
14+
oUploadDialog.setBusy(bBusy)
15+
}
16+
17+
function closeDialog() {
18+
oUploadDialog && oUploadDialog.close()
19+
}
20+
21+
function showError(sMessage) {
22+
MessageBox.error(sMessage || "Upload failed")
23+
}
24+
25+
// TODO: Better option for this?
26+
function byId(sId) {
27+
return sap.ui.core.Fragment.byId("uploadDialog", sId);
28+
}
29+
30+
return {
31+
onBeforeOpen: function (oEvent) {
32+
oUploadDialog = oEvent.getSource();
33+
oExtensionAPI.addDependent(oUploadDialog);
34+
},
35+
36+
onAfterClose: function (oEvent) {
37+
oExtensionAPI.removeDependent(oUploadDialog);
38+
oUploadDialog.destroy();
39+
oUploadDialog = undefined;
40+
},
41+
42+
onOk: function (oEvent) {
43+
setDialogBusy(true)
44+
45+
var oFileUploader = byId("uploader")
46+
47+
oFileUploader
48+
.checkFileReadable()
49+
.then(function () {
50+
oFileUploader.upload();
51+
})
52+
.catch(function (error) {
53+
showError("The file cannot be read.");
54+
setDialogBusy(false)
55+
})
56+
},
57+
58+
onCancel: function (oEvent) {
59+
closeDialog();
60+
},
61+
62+
onTypeMismatch: function (oEvent) {
63+
var sSupportedFileTypes = oEvent
64+
.getSource()
65+
.getFileType()
66+
.map(function (sFileType) {
67+
return "*." + sFileType;
68+
})
69+
.join(", ");
70+
71+
showError(
72+
"The file type *." +
73+
oEvent.getParameter("fileType") +
74+
" is not supported. Choose one of the following types: " +
75+
sSupportedFileTypes
76+
);
77+
},
78+
79+
onFileAllowed: function (oEvent) {
80+
setOkButtonEnabled(true)
81+
},
82+
83+
onFileEmpty: function (oEvent) {
84+
setOkButtonEnabled(false)
85+
},
86+
87+
onUploadComplete: function (oEvent) {
88+
var iStatus = oEvent.getParameter("status");
89+
var oFileUploader = oEvent.getSource()
90+
91+
oFileUploader.clear();
92+
setOkButtonEnabled(false)
93+
setDialogBusy(false)
94+
95+
if (iStatus >= 400) {
96+
var oRawResponse = JSON.parse(oEvent.getParameter("responseRaw"));
97+
showError(oRawResponse && oRawResponse.error && oRawResponse.error.message);
98+
} else {
99+
MessageToast.show("Uploaded successfully");
100+
oExtensionAPI.refresh()
101+
closeDialog();
102+
}
103+
}
104+
};
105+
}
106+
107+
return {
108+
showUploadDialog: function (oBindingContext, aSelectedContexts) {
109+
this.loadFragment({
110+
id: "uploadDialog",
111+
name: "admin.extension.UploadDialog",
112+
controller: _createUploadController(this)
113+
}).then(function (oDialog) {
114+
oDialog.open();
115+
});
116+
}
117+
};
118+
}
119+
);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<core:FragmentDefinition xmlns:core="sap.ui.core" xmlns:u="sap.ui.unified"
2+
xmlns="sap.m">
3+
<Dialog title="Import Books" class="sapUiResponsiveContentPadding" beforeOpen=".onBeforeOpen"
4+
afterClose=".onAfterClose">
5+
<content>
6+
<u:FileUploader
7+
id="uploader"
8+
fileType="csv"
9+
multiple="false"
10+
uploadUrl="/api/admin/Csv/data"
11+
fileAllowed=".onFileAllowed"
12+
fileEmpty=".onFileEmpty"
13+
uploadComplete=".onUploadComplete"
14+
typeMissmatch=".onTypeMismatch"
15+
sendXHR="true"
16+
useMultipart="false"
17+
placeholder="Choose a CSV file..."
18+
httpRequestMethod="Put"/>
19+
</content>
20+
<beginButton>
21+
<Button id="ok" text="OK" press=".onOk" type="Emphasized" enabled="false"/>
22+
</beginButton>
23+
<endButton>
24+
<Button id="cancel" text="Cancel" press=".onCancel"/>
25+
</endButton>
26+
</Dialog>
27+
</core:FragmentDefinition>

app/admin/webapp/manifest.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@
7878
"route" : "BooksDetails"
7979
}
8080
}
81+
},
82+
"content": {
83+
"header": {
84+
"actions": {
85+
"upload": {
86+
"press": "admin.extension.Upload.showUploadDialog",
87+
"text": "Import Books"
88+
}
89+
}
90+
}
8191
}
8292
}
8393
}

app/common.cds

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ annotate my.Books with
5454
@(UI : {HeaderInfo : {
5555
TypeName : '{i18n>Book}',
5656
TypeNamePlural : '{i18n>Books}',
57+
TypeImageUrl : 'sap-icon://course-book',
5758
Title : {Value : title},
5859
Description : {Value : author.name}
5960
}, });

assets/books.csv

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
ID;TITLE;DESCR;AUTHOR_ID;STOCK;PRICE;CURRENCY_CODE;GENRE_ID;RATING
2+
8f45cc39-df65-4790-a63f-634e151da734;Pride and Prejudice;It is a truth universally acknowledged that when most people think of Jane Austen they think of this charming and humorous story of love, difficult families and the tricky task of finding a handsome husband with a good fortune.;b834ddb0-613a-4edf-8d47-7d80989e1325;111;20;GBP;15;
3+
3f09036d-3a1a-4eaf-91e2-5aa6f50dcfe0;To Kill a Mockingbird;A novel before its time, Harper Lee’s Pulitzer-prize winner addresses issues of race, inequality and segregation with both levity and compassion. Told through the eyes of loveable rogues Scout and Jem, it also created one of literature’s most beloved heroes – Atticus Finch, a man determined to right the racial wrongs of the Deep South.;b22f5293-7eea-49bb-9ee7-17c5de81f1df;33;7.99;GBP;11;
4+
21c12f7b-089b-42da-8416-d5f67606f939;The Great Gatsby;Jay Gatsby, the enigmatic millionaire who throws decadent parties but doesn’t attend them, is one of the great characters of American literature. This is F. Scott Fitzgerald at his most sparkling and devastating.;a57f75fa-2bda-47b5-ab4d-b644570f29cd;444;6.99;GBP;10;
5+
c49c354e-8c18-4022-804c-78025b529fb1;One Hundred Years of Solitude;Gabriel García Márquez’s multi-generational spanning magnum opus was a landmark in Spanish literature.;1d2ec887-cbf1-491e-943e-33a2b4f39a6f;55;8.99;GBP;10;
6+
0c1ffc7e-734e-4c1d-ba87-3a032ad8a5a0;In Cold Blood;The ‘true crime’ TV show / podcast you’re obsessed with probably owes a debt to this masterpiece of reportage by Truman Capote. Chilling and brilliant.;c0526b1a-9a75-4a43-9133-163325cbbd2b;66;9.99;GBP;16;

db/data/my.bookshop-Authors.csv

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@ ID;NAME;DATEOFBIRTH;PLACEOFBIRTH;DATEOFDEATH;PLACEOFDEATH
33
e3da2c2e-72ee-45d5-8def-52964c7b252a;Charlote Brontë;1818-04-21;Thornton, Yorkshire;1855-03-31;Haworth, Yorkshire
44
e7643aae-2d2f-4656-bb2d-1328ad3c8045;Edgar Allen Poe;1809-01-19;Boston, Massachusetts;1849-10-07;Baltimore, Maryland
55
3c081d9d-abda-4da9-8b6a-4f4555bb26bc;Richard Carpenter;1929-08-14;King’s Lynn, Norfolk;2012-02-26;Hertfordshire, England
6+
b834ddb0-613a-4edf-8d47-7d80989e1325;Jane Austen;1775-12-16;Steventon, United Kingdom;1817-07-18;Winchester, United Kingdom
7+
a57f75fa-2bda-47b5-ab4d-b644570f29cd;F. Scott Fitzgerald;1896-09-24;Saint Paul, Minnesota;1940-12-21;Los Angeles, California
8+
b22f5293-7eea-49bb-9ee7-17c5de81f1df;Harper Lee;1926-04-28;Monroeville, Alabama;2016-02-19;Monroeville, Alabama
9+
1d2ec887-cbf1-491e-943e-33a2b4f39a6f;Gabriel García Márquez;1927-03-06;Aracataca, Columbia;2014-04-17;Mexico City, Mexico
10+
c0526b1a-9a75-4a43-9133-163325cbbd2b;Truman Capote;1924-09-30;New Orleans, Louisiana;1984-08-25;Los Angeles, California

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
<!-- DEPENDENCIES VERSION -->
1818
<jdk.version>1.8</jdk.version>
19-
<cds.services.version>1.15.3</cds.services.version>
20-
<spring.boot.version>2.4.4</spring.boot.version>
19+
<cds.services.version>1.16.0</cds.services.version>
20+
<spring.boot.version>2.4.5</spring.boot.version>
2121
<cloud.sdk.version>3.41.0</cloud.sdk.version>
2222
</properties>
2323

srv/admin-service.cds

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ service AdminService @(requires : 'admin') {
99

1010
entity Authors as projection on my.Authors;
1111
entity Orders as select from my.Orders;
12+
13+
@cds.persistence.skip
14+
entity Csv @odata.singleton {
15+
data : LargeBinary @Core.MediaType : 'text/csv';
16+
}
1217
}
1318

1419
// Deep Search Items

srv/src/main/java/my/bookshop/MessageKeys.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ public class MessageKeys {
1414
public static final String REVIEW_ADDED = "review.added";
1515
public static final String REVIEW_ADD_FORBIDDEN = "review.add.forbidden";
1616
public static final String ORDER_EXCEEDS_STOCK = "order.exceeds.stock";
17+
public static final String BOOK_IMPORT_FAILED = "book.import.failed";
1718
}

0 commit comments

Comments
 (0)