")
55 | .append($("| ").text(name))
56 | .append($(" | ").text(category))
57 | .append($(" | ")
58 | .append($("")
59 | .attr("type", "checkbox")
60 | .attr("id", id)
61 | .attr("checked", isComplete)
62 | .attr("class", "isComplete")
63 | ))
64 | .addClass(rowColor)
65 | );
66 | },
67 |
68 | /*
69 | * UI Bindings
70 | */
71 | bindCreateButton: function() {
72 | todoApp.ui_createButton().click(function() {
73 | todoApp.createTodoItem(todoApp.ui_createNameInput().val(), todoApp.ui_createCategoryInput().val(), false);
74 | todoApp.ui_createNameInput().val("");
75 | todoApp.ui_createCategoryInput().val("");
76 | });
77 | },
78 |
79 | bindUpdateButton: function() {
80 | todoApp.ui_updateButton().click(function() {
81 | // Disable button temporarily.
82 | var myButton = $(this);
83 | var originalText = myButton.text();
84 | $(this).text("Updating...");
85 | $(this).prop("disabled", true);
86 |
87 | // Call api to update todo items.
88 | $.each(todoApp.ui_updateId(), function(index, value) {
89 | todoApp.updateTodoItem(value.name, value.value);
90 | $(value).remove();
91 | });
92 |
93 | // Re-enable button.
94 | setTimeout(function() {
95 | myButton.prop("disabled", false);
96 | myButton.text(originalText);
97 | }, 500);
98 | });
99 | },
100 |
101 | bindUpdateCheckboxes: function() {
102 | todoApp.ui_table().on("click", ".isComplete", function(event) {
103 | var checkboxElement = $(event.currentTarget);
104 | var rowElement = $(event.currentTarget).parents('tr');
105 | var id = checkboxElement.attr('id');
106 | var isComplete = checkboxElement.is(':checked');
107 |
108 | // Togle table row color
109 | if (isComplete) {
110 | rowElement.addClass("active");
111 | rowElement.removeClass("warning");
112 | } else {
113 | rowElement.removeClass("active");
114 | rowElement.addClass("warning");
115 | }
116 |
117 | // Update hidden inputs for update panel.
118 | todoApp.ui_updateForm().children("input[name='" + id + "']").remove();
119 |
120 | todoApp.ui_updateForm().append($("")
121 | .attr("type", "hidden")
122 | .attr("class", "updateComplete")
123 | .attr("name", id)
124 | .attr("value", isComplete));
125 |
126 | });
127 | },
128 |
129 | /*
130 | * UI Elements
131 | */
132 | ui_createNameInput: function() {
133 | return $(".todoForm #inputItemName");
134 | },
135 |
136 | ui_createCategoryInput: function() {
137 | return $(".todoForm #inputItemCategory");
138 | },
139 |
140 | ui_createButton: function() {
141 | return $(".todoForm button");
142 | },
143 |
144 | ui_table: function() {
145 | return $(".todoList table tbody");
146 | },
147 |
148 | ui_updateButton: function() {
149 | return $(".todoUpdatePanel button");
150 | },
151 |
152 | ui_updateForm: function() {
153 | return $(".todoUpdatePanel form");
154 | },
155 |
156 | ui_updateId: function() {
157 | return $(".todoUpdatePanel .updateComplete");
158 | },
159 |
160 | /*
161 | * Install the TodoApp
162 | */
163 | install: function() {
164 | todoApp.bindCreateButton();
165 | todoApp.bindUpdateButton();
166 | todoApp.bindUpdateCheckboxes();
167 |
168 | todoApp.getTodoItems();
169 | }
170 | };
171 |
172 | $(document).ready(function() {
173 | todoApp.install();
174 | });
175 |
--------------------------------------------------------------------------------
/src/com/microsoft/azure/cosmos/sample/dao/DocDbDao.java:
--------------------------------------------------------------------------------
1 | package com.microsoft.azure.cosmos.sample.dao;
2 |
3 | import com.azure.cosmos.CosmosClient;
4 | import com.azure.cosmos.CosmosContainer;
5 | import com.azure.cosmos.CosmosDatabase;
6 | import com.azure.cosmos.CosmosException;
7 | import com.azure.cosmos.implementation.Utils;
8 | import com.azure.cosmos.models.CosmosContainerProperties;
9 | import com.azure.cosmos.models.CosmosContainerResponse;
10 | import com.azure.cosmos.models.CosmosDatabaseResponse;
11 | import com.azure.cosmos.models.CosmosItemRequestOptions;
12 | import com.azure.cosmos.models.CosmosQueryRequestOptions;
13 | import com.azure.cosmos.models.FeedResponse;
14 | import com.azure.cosmos.models.PartitionKey;
15 | import com.fasterxml.jackson.core.JsonProcessingException;
16 | import com.fasterxml.jackson.databind.JsonNode;
17 | import com.fasterxml.jackson.databind.ObjectMapper;
18 | import com.fasterxml.jackson.databind.node.ObjectNode;
19 | import com.google.gson.Gson;
20 | import com.microsoft.azure.cosmos.sample.model.TodoItem;
21 |
22 | import java.util.ArrayList;
23 | import java.util.List;
24 |
25 | public class DocDbDao implements TodoDao {
26 | // The name of our database.
27 | private static final String DATABASE_ID = "TestDB";
28 |
29 | // The name of our collection.
30 | private static final String CONTAINER_ID = "TestCollection";
31 |
32 | // We'll use Gson for POJO <=> JSON serialization for this example.
33 | private static Gson gson = new Gson();
34 |
35 | // The Cosmos DB Client
36 | private static CosmosClient cosmosClient = CosmosClientFactory
37 | .getCosmosClient();
38 |
39 | // The Cosmos DB database
40 | private static CosmosDatabase cosmosDatabase = null;
41 |
42 | // The Cosmos DB container
43 | private static CosmosContainer cosmosContainer = null;
44 |
45 | // For POJO/JsonNode interconversion
46 | private static final ObjectMapper OBJECT_MAPPER = Utils.getSimpleObjectMapper();
47 |
48 | @Override
49 | public TodoItem createTodoItem(TodoItem todoItem) {
50 | // Serialize the TodoItem as a JSON Document.
51 |
52 | JsonNode todoItemJson = OBJECT_MAPPER.valueToTree(todoItem);
53 |
54 | ((ObjectNode) todoItemJson).put("entityType", "todoItem");
55 |
56 | try {
57 | // Persist the document using the DocumentClient.
58 | todoItemJson =
59 | getContainerCreateResourcesIfNotExist()
60 | .createItem(todoItemJson)
61 | .getItem();
62 | } catch (CosmosException e) {
63 | System.out.println("Error creating TODO item.\n");
64 | e.printStackTrace();
65 | return null;
66 | }
67 |
68 |
69 | try {
70 |
71 | return OBJECT_MAPPER.treeToValue(todoItemJson, TodoItem.class);
72 | //return todoItem;
73 | } catch (Exception e) {
74 | System.out.println("Error deserializing created TODO item.\n");
75 | e.printStackTrace();
76 |
77 | return null;
78 | }
79 |
80 | }
81 |
82 | @Override
83 | public TodoItem readTodoItem(String id) {
84 | // Retrieve the document by id using our helper method.
85 | JsonNode todoItemJson = getDocumentById(id);
86 |
87 | if (todoItemJson != null) {
88 | // De-serialize the document in to a TodoItem.
89 | try {
90 | return OBJECT_MAPPER.treeToValue(todoItemJson, TodoItem.class);
91 | } catch (JsonProcessingException e) {
92 | System.out.println("Error deserializing read TODO item.\n");
93 | e.printStackTrace();
94 |
95 | return null;
96 | }
97 | } else {
98 | return null;
99 | }
100 | }
101 |
102 | @Override
103 | public List readTodoItems() {
104 |
105 | List todoItems = new ArrayList();
106 |
107 | String sql = "SELECT * FROM root r WHERE r.entityType = 'todoItem'";
108 | int maxItemCount = 1000;
109 | int maxDegreeOfParallelism = 1000;
110 | int maxBufferedItemCount = 100;
111 |
112 | CosmosQueryRequestOptions options = new CosmosQueryRequestOptions();
113 | options.setMaxBufferedItemCount(maxBufferedItemCount);
114 | options.setMaxDegreeOfParallelism(maxDegreeOfParallelism);
115 | options.setQueryMetricsEnabled(false);
116 |
117 | int error_count = 0;
118 | int error_limit = 10;
119 |
120 | String continuationToken = null;
121 | do {
122 |
123 | for (FeedResponse pageResponse :
124 | getContainerCreateResourcesIfNotExist()
125 | .queryItems(sql, options, JsonNode.class)
126 | .iterableByPage(continuationToken, maxItemCount)) {
127 |
128 | continuationToken = pageResponse.getContinuationToken();
129 |
130 | for (JsonNode item : pageResponse.getElements()) {
131 |
132 | try {
133 | todoItems.add(OBJECT_MAPPER.treeToValue(item, TodoItem.class));
134 | } catch (JsonProcessingException e) {
135 | if (error_count < error_limit) {
136 | error_count++;
137 | if (error_count >= error_limit) {
138 | System.out.println("\n...reached max error count.\n");
139 | } else {
140 | System.out.println("Error deserializing TODO item JsonNode. " +
141 | "This item will not be returned.");
142 | e.printStackTrace();
143 | }
144 | }
145 | }
146 |
147 | }
148 | }
149 |
150 | } while (continuationToken != null);
151 |
152 | return todoItems;
153 | }
154 |
155 | @Override
156 | public TodoItem updateTodoItem(String id, boolean isComplete) {
157 | // Retrieve the document from the database
158 | JsonNode todoItemJson = getDocumentById(id);
159 |
160 | // You can update the document as a JSON document directly.
161 | // For more complex operations - you could de-serialize the document in
162 | // to a POJO, update the POJO, and then re-serialize the POJO back in to
163 | // a document.
164 | ((ObjectNode) todoItemJson).put("complete", isComplete);
165 |
166 | try {
167 | // Persist/replace the updated document.
168 | todoItemJson =
169 | getContainerCreateResourcesIfNotExist()
170 | .replaceItem(todoItemJson, id, new PartitionKey(id), new CosmosItemRequestOptions())
171 | .getItem();
172 | } catch (CosmosException e) {
173 | System.out.println("Error updating TODO item.\n");
174 | e.printStackTrace();
175 | return null;
176 | }
177 |
178 | // De-serialize the document in to a TodoItem.
179 | try {
180 | return OBJECT_MAPPER.treeToValue(todoItemJson, TodoItem.class);
181 | } catch (JsonProcessingException e) {
182 | System.out.println("Error deserializing updated item.\n");
183 | e.printStackTrace();
184 |
185 | return null;
186 | }
187 | }
188 |
189 | @Override
190 | public boolean deleteTodoItem(String id) {
191 | // CosmosDB refers to documents by self link rather than id.
192 |
193 | // Query for the document to retrieve the self link.
194 | JsonNode todoItemJson = getDocumentById(id);
195 |
196 | try {
197 | // Delete the document by self link.
198 | getContainerCreateResourcesIfNotExist()
199 | .deleteItem(id, new PartitionKey(id), new CosmosItemRequestOptions());
200 | } catch (CosmosException e) {
201 | System.out.println("Error deleting TODO item.\n");
202 | e.printStackTrace();
203 | return false;
204 | }
205 |
206 | return true;
207 | }
208 |
209 | /*
210 |
211 | private CosmosDatabase getTodoDatabase() {
212 | if (databaseCache == null) {
213 | // Get the database if it exists
214 | List databaseList = cosmosClient
215 | .queryDatabases(
216 | "SELECT * FROM root r WHERE r.id='" + DATABASE_ID
217 | + "'", null).getQueryIterable().toList();
218 |
219 | if (databaseList.size() > 0) {
220 | // Cache the database object so we won't have to query for it
221 | // later to retrieve the selfLink.
222 | databaseCache = databaseList.get(0);
223 | } else {
224 | // Create the database if it doesn't exist.
225 | try {
226 | CosmosDatabase databaseDefinition = new CosmosDatabase();
227 | databaseDefinition.setId(DATABASE_ID);
228 |
229 | databaseCache = cosmosClient.createDatabase(
230 | databaseDefinition, null).getResource();
231 | } catch (CosmosException e) {
232 | // TODO: Something has gone terribly wrong - the app wasn't
233 | // able to query or create the collection.
234 | // Verify your connection, endpoint, and key.
235 | e.printStackTrace();
236 | }
237 | }
238 | }
239 |
240 | return databaseCache;
241 | }
242 |
243 | */
244 |
245 | private CosmosContainer getContainerCreateResourcesIfNotExist() {
246 |
247 | try {
248 |
249 | if (cosmosDatabase == null) {
250 | CosmosDatabaseResponse cosmosDatabaseResponse = cosmosClient.createDatabaseIfNotExists(DATABASE_ID);
251 | cosmosDatabase = cosmosClient.getDatabase(cosmosDatabaseResponse.getProperties().getId());
252 | }
253 |
254 | } catch (CosmosException e) {
255 | // TODO: Something has gone terribly wrong - the app wasn't
256 | // able to query or create the collection.
257 | // Verify your connection, endpoint, and key.
258 | System.out.println("Something has gone terribly wrong - " +
259 | "the app wasn't able to create the Database.\n");
260 | e.printStackTrace();
261 | }
262 |
263 | try {
264 |
265 | if (cosmosContainer == null) {
266 | CosmosContainerProperties properties = new CosmosContainerProperties(CONTAINER_ID, "/id");
267 | CosmosContainerResponse cosmosContainerResponse = cosmosDatabase.createContainerIfNotExists(properties);
268 | cosmosContainer = cosmosDatabase.getContainer(cosmosContainerResponse.getProperties().getId());
269 | }
270 |
271 | } catch (CosmosException e) {
272 | // TODO: Something has gone terribly wrong - the app wasn't
273 | // able to query or create the collection.
274 | // Verify your connection, endpoint, and key.
275 | System.out.println("Something has gone terribly wrong - " +
276 | "the app wasn't able to create the Container.\n");
277 | e.printStackTrace();
278 | }
279 |
280 | return cosmosContainer;
281 | }
282 |
283 | private JsonNode getDocumentById(String id) {
284 |
285 | String sql = "SELECT * FROM root r WHERE r.id='" + id + "'";
286 | int maxItemCount = 1000;
287 | int maxDegreeOfParallelism = 1000;
288 | int maxBufferedItemCount = 100;
289 |
290 | CosmosQueryRequestOptions options = new CosmosQueryRequestOptions();
291 | options.setMaxBufferedItemCount(maxBufferedItemCount);
292 | options.setMaxDegreeOfParallelism(maxDegreeOfParallelism);
293 | options.setQueryMetricsEnabled(false);
294 |
295 | List itemList = new ArrayList();
296 |
297 | String continuationToken = null;
298 | do {
299 | for (FeedResponse pageResponse :
300 | getContainerCreateResourcesIfNotExist()
301 | .queryItems(sql, options, JsonNode.class)
302 | .iterableByPage(continuationToken, maxItemCount)) {
303 |
304 | continuationToken = pageResponse.getContinuationToken();
305 |
306 | for (JsonNode item : pageResponse.getElements()) {
307 | itemList.add(item);
308 | }
309 | }
310 |
311 | } while (continuationToken != null);
312 |
313 | if (itemList.size() > 0) {
314 | return itemList.get(0);
315 | } else {
316 | return null;
317 | }
318 | }
319 |
320 | }
321 |
--------------------------------------------------------------------------------
|