Öğretici: Azure Cosmos DB'yi ve NoSQL için API'yi kullanarak Java web uygulaması oluşturma

UYGULANANLAR: NOSQL

Bu Java web uygulaması öğreticisi, Azure App Service Web Apps’te barındırılan bir Java uygulamasında verileri depolamak ve bunlara erişmek için Microsoft Azure Cosmos DB hizmetinin nasıl kullanılacağını size gösterir. Kredi kartı veya Azure aboneliği olmadan ücretsiz Azure Cosmos DB'yi deneyin hesabı ayarlayabilirsiniz. Bu makalede aşağıdakileri öğreneceksiniz:

  • Eclipse'te temel bir JavaServer Pages (JSP) uygulaması oluşturma.
  • Azure Cosmos DB Java SDK’sı kullanılarak Azure Cosmos DB hizmetiyle çalışma.

Bu Java uygulaması öğreticisi görevleri oluşturmanızı, almanızı ve aşağıdaki görüntüde gösterilen şekilde tamamlandı olarak işaretlemenizi sağlayan bir web tabanlı görev yönetimi uygulamasını nasıl oluşturacağınızı gösterir. Yapılacaklar listesindeki görevlerin her biri, Azure Cosmos DB'de JSON belgeleri olarak depolanır.

Yapılacaklar Listesi Java uygulamam

İpucu

Bu uygulama geliştirme öğreticisi, Java kullanımına ilişkin deneyim sahibi olduğunuzu varsayar. Java veya önkoşul araçlarında yeniyseniz GitHub'dan yapılacaklar projesinin tamamını indirmenizi ve bu makalenin sonundaki yönergeleri kullanarak projeyi oluşturmanızı öneririz. Oluşturduktan sonra, proje bağlamında kodu daha iyi kavramak için makaleyi inceleyebilirsiniz.

Bu Java web uygulaması öğreticisi için önkoşullar

Bu uygulama geliştirme öğreticisine başlamadan önce aşağıdakilere sahip olmanız gerekir:

Bu araçları ilk kez yüklüyorsanız coreservlets.com, Öğretici: TomCat7'yi Yükleme ve Eclipse ile kullanma makalesinin hızlı başlangıç bölümünde yükleme işlemine ilişkin bir kılavuz sağlar.

Azure Cosmos DB hesabı oluşturma

İlk olarak bir Azure Cosmos DB hesabı oluşturalım. Zaten bir hesabınız varsa veya bu öğretici için Azure Cosmos DB Öykünücüsü’nü kullanıyorsanız 2. Adım: Java JSP uygulaması oluşturma adımına atlayabilirsiniz.

  1. Azure portal menüsünden veya Giriş sayfasındaKaynak oluştur'u seçin.

  2. Azure Cosmos DB için arama. Azure Cosmos DB Oluştur'u> seçin.

  3. Azure Cosmos DB hesabı oluşturma sayfasında, NoSQL için Azure Cosmos DB bölümünde Oluştur seçeneğini belirleyin.

    Azure Cosmos DB çeşitli API'ler sağlar:

    • Belge verileri için NoSQL
    • PostgreSQL
    • Belge verileri için MongoDB
    • Apache Cassandra
    • Tablo
    • Grafik verileri için Apache Gremlin

    NoSQL API'si hakkında daha fazla bilgi edinmek için bkz. Azure Cosmos DB'ye Hoş Geldiniz.

  4. Azure Cosmos DB Hesabı Oluştur sayfasında yeni Azure Cosmos DB hesabının temel ayarlarını girin.

    Ayar Değer Açıklama
    Abonelik Abonelik adı Bu Azure Cosmos DB hesabı için kullanmak istediğiniz Azure aboneliğini seçin.
    Kaynak Grubu Kaynak grubu adı Bir kaynak grubu seçin veya Yeni oluştur seçeneğini belirleyin ve yeni kaynak grubu için benzersiz bir ad girin.
    Hesap Adı Benzersiz bir ad Azure Cosmos DB hesabınızı tanımlamak için bir ad girin. URI’nizi oluşturmak için sağladığınız ada documents.azure.com ekleneceği için benzersiz bir ad kullanın. Ad yalnızca küçük harf, sayı ve kısa çizgi (-) karakteri içerebilir. 3-44 karakter uzunluğunda olmalıdır.
    Konum Kullanıcılarınıza en yakın bölge Azure Cosmos DB hesabınızın barındırılacağı coğrafi konumu seçin. Verilere en hızlı erişimi sağlamak için kullanıcılarınıza en yakın olan konumu kullanın.
    Kapasite modu Sağlanan aktarım hızı veya Sunucusuz Sağlanan aktarım hızı modunda hesap oluşturmak için Sağlanan aktarım hızı'na tıklayın. Sunucusuz modda hesap oluşturmak için Sunucusuz'u seçin.
    Azure Cosmos DB ücretsiz katman indirimi uygulama Uygula veya Uygulama Azure Cosmos DB ücretsiz katmanı ile bir hesapta ilk 1000 RU/sn ve 25 GB depolama alanını ücretsiz olarak alırsınız. Ücretsiz katman hakkında daha fazla bilgi edinin.
    Toplam hesap aktarım hızını sınırla Seçili veya değil Bu hesapta sağlanacak toplam aktarım hızı miktarını sınırlayın. Bu sınır, sağlanan aktarım hızıyla ilgili beklenmeyen ücretleri engeller. Hesabınız oluşturulduktan sonra bu sınırı güncelleştirebilir veya kaldırabilirsiniz.

    Azure aboneliği başına en fazla bir ücretsiz katman Azure Cosmos DB hesabınız olabilir ve hesabı oluştururken bunu kabul etmeniz gerekir. Ücretsiz katman indirimini uygulama seçeneğini görmüyorsanız abonelikteki başka bir hesap ücretsiz katmanla zaten etkinleştirilmiştir.

    Azure Cosmos DB Hesabı Oluştur sayfasını gösteren ekran görüntüsü.

    Not

    Kapasite modu olarak Sunucusuz seçeneğini belirlediğinizde aşağıdaki seçenekler kullanılamaz:

    • Ücretsiz Katman İndirimi Uygula
    • Toplam hesap aktarım hızını sınırla
  5. Genel Dağıtım sekmesinde aşağıdaki ayrıntıları yapılandırın. Bu hızlı başlangıç için varsayılan değerleri bırakabilirsiniz:

    Ayar Değer Açıklama
    Coğrafi Yedeklilik Devre Dışı Bırak Bölgenizi bir çift bölgeyle eşleştirerek hesabınızda genel dağıtımı etkinleştirin veya devre dışı bırakın. Daha sonra hesabınıza daha fazla bölge ekleyebilirsiniz.
    Birden Çok Bölgeli Yazmalar Devre Dışı Bırak Çok bölgeli yazma özelliği, dünya genelindeki veritabanlarınız ve kapsayıcılarınız için sağlanan aktarım hızını kullanmanıza olanak tanır.
    Kullanılabilirlik Alanları Devre Dışı Bırak Kullanılabilirlik Alanları uygulamanızın kullanılabilirliğini ve dayanıklılığını daha da artırmanıza yardımcı olur.

    Not

    Önceki Temel Bilgiler sayfasında Kapasite modu olarak Sunucusuz seçeneğini belirlediğinizde aşağıdaki seçenekler kullanılamaz:

    • Coğrafi yedeklilik
    • Birden Çok Bölgeli Yazmalar
  6. İsteğe bağlı olarak, aşağıdaki sekmelerde daha fazla ayrıntı yapılandırabilirsiniz:

    • Ağ iletişimi. Sanal ağdan erişimi yapılandırma.
    • Yedekleme İlkesi. Düzenli veya sürekli yedekleme ilkesi yapılandırın.
    • Şifreleme. Hizmet tarafından yönetilen anahtar veya müşteri tarafından yönetilen anahtar kullanın.
    • Etiketler'i seçin. Etiketler, birden çok kaynağa ve kaynak grubuna aynı etiketi uygulayarak kaynakları kategorilere ayırmanızı ve birleştirilmiş faturalamayı görüntülemenizi sağlayan ad/değer çiftleridir.
  7. Gözden geçir ve oluştur’u seçin.

  8. Hesap ayarlarını gözden geçirip Oluştur seçeneğini belirleyin. Hesabın oluşturulması birkaç dakika sürer. Portal sayfasında Dağıtımınız tamamlandı iletisinin görüntülenmesini bekleyin.

    Dağıtımınızın tamamlandığını gösteren ekran görüntüsü.

  9. Azure Cosmos DB hesabı sayfasına gitmek için Kaynağa git seçeneğini belirleyin.

    Azure Cosmos DB hesap sayfasını gösteren ekran görüntüsü.

Azure Cosmos DB hesabı sayfasına gidin ve Anahtarlar'ı seçin. Daha sonra oluşturduğunuz web uygulamasında kullanılacak değerleri kopyalayın.

Azure Cosmos DB hesap sayfasında Anahtarlar düğmesinin vurgulandığı Azure portal ekran görüntüsü

Java JSP uygulamasını oluşturma

JSP uygulaması oluşturmak için:

  1. İlk olarak bir Java projesi oluşturarak başlayacağız. Eclipse'i başlatın, Dosya'yı, Yeni'yi ve ardından Dinamik Web Projesi'ni seçin. Kullanılabilir bir proje olarak Dinamik Web Projesi'ni listede görmüyorsanız aşağıdakileri yapın: Dosya'yı seçin, Yeni'yi seçin, Proje...'yi seçin, Web'i genişletin, Dinamik Web Projesi'ni seçin ve İleri'yi seçin.

    JSP Java Uygulaması Geliştirme

  2. Proje adı kutusuna bir proje adı girin ve Hedef Çalışma Zamanı açılan menüsünde isteğe bağlı olarak bir değer seçin (örneğin Apache Tomcat v7.0) ve ardından Son'u seçin. Bir hedef çalışma zamanının seçilmesi, projenizi Eclipse aracılığıyla yerel olarak çalıştırmanızı sağlar.

  3. Eclipse'te Proje Gezgini görünümünde projenizi genişletin. WebContent'e sağ tıklayın, Yeni'yi ve ardından JSP Dosyası'yı seçin.

  4. Yeni JSP Dosyası iletişim kutusunda dosyaya index.jsp adını verin. Üst klasörü aşağıdaki çizimde gösterildiği gibi WebContent olarak tutun ve İleri'yi seçin.

    Yeni bir JSP Dosyası Oluşturma - Java Web Uygulaması Öğreticisi

  5. JSP Şablonu Seç iletişim kutusunda, bu öğreticinin amacı doğrultusunda Yeni JSP Dosyası (html) öğesini ve ardından Son'u seçin.

  6. Index.jsp dosyası Eclipse'te açıldığında, var olan <body> öğenin içinde Merhaba Dünya! görüntülemek için metin ekleyin. Güncelleştirilmiş <body> içeriği aşağıdaki kod gibi görünmelidir:

    <body>
      <% out.println("Hello World!"); %>
    </body>
    
  7. index.jsp dosyasını kaydedin.

  8. 2. adımda bir hedef çalışma zamanı ayarlarsanız, JSP uygulamanızı yerel olarak çalıştırmak için Project'i ve ardından Çalıştır'ı seçebilirsiniz:

    Hello World - Java Uygulaması Öğreticisi

SQL Java SDK'sını yükleme

Apache Maven, SQL Java SDK'sını ve bağımlılıklarını çekmenin en kolay yolunu sağlar. Bunu yapmak için aşağıdaki adımları kullanarak projenizi maven projesine dönüştürmeniz gerekir:

  1. Proje Gezgini'nde projenize sağ tıklayın, Yapılandır'ı ve Maven Projesine Dönüştür'ü seçin.

  2. Yeni POM oluştur penceresinde varsayılan değerleri kabul edin ve Son'u seçin.

  3. Proje Gezgini'nde pom.xml dosyasını açın.

  4. Bağımlılıklar sekmesindeki Bağımlılıklar bölmesinde Ekle'yi seçin.

  5. Bağımlılık Seç penceresinde aşağıdakileri yapın:

    • Grup Kimliği kutusuna yazıncom.azure.
    • Yapıt Kimliği kutusuna girinazure-cosmos.
    • Sürüm kutusuna yazın4.11.0.

    Veya Grup Kimliği ve Yapıt Kimliği için bağımlılık XML'sini doğrudan pom.xml dosyasına ekleyebilirsiniz:

    <dependency>
      <groupId>com.azure</groupId>
      <artifactId>azure-cosmos</artifactId>
      <version>4.11.0</version>
    </dependency>
    
  6. Tamam'ı seçtiğinizde Maven SQL Java SDK'sını yükler veya pom.xml dosyasını kaydeder.

Java uygulamanızda Azure Cosmos DB hizmetini kullanma

Şimdi modelleri, görünümleri ve denetleyicileri web uygulamanıza ekleyelim.

Model ekleme

İlk olarak, yeni bir TodoItem.java dosyası içinde bir model tanımlayalım. sınıfı, TodoItem getter ve setter yöntemleriyle birlikte bir öğenin şemasını tanımlar:

package com.microsoft.azure.cosmos.sample.model;

//@Data
//@Builder
public class TodoItem {
    private String entityType;
    private String category;
    private boolean complete;
    private String id;
    private String name;

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getEntityType() {
        return entityType;
    }

    public void setEntityType(String entityType) {
        this.entityType = entityType;
    }

    public boolean isComplete() {
        return complete;
    }

    public void setComplete(boolean complete) {
        this.complete = complete;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    
}

Veri Erişim Nesnesi (DAO) sınıflarını ekleme

ToDo öğelerini Azure Cosmos DB'de kalıcı hale getirmek için soyut bir Veri Erişim Nesnesi (DAO) oluşturun. Yapılacaklar öğelerini bir koleksiyona kaydetmek için, istemcinin hangi veritabanı ve koleksiyona kalıcı hale getireceğini (kendine bağlantılar tarafından başvurulduğu üzere) bilmesi gerekir. Genel olarak, veritabanına ek gidiş gelişleri önlemek için veritabanı ve koleksiyonu mümkün olduğunda ön belleğe almak en iyisidir.

  1. Azure Cosmos DB hizmetini çağırmak için yeni cosmosClient bir nesne örneği oluşturmanız gerekir. Genel olarak, sonraki her istek için yeni bir istemci oluşturmak yerine nesneyi yeniden kullanmak cosmosClient en iyisidir. sınıfı içinde tanımlayarak istemciyi cosmosClientFactory yeniden kullanabilirsiniz. 1. adımda kaydettiğiniz HOST ve MASTER_KEY değerlerini güncelleştirin. HOST değişkenini URI'nizle değiştirin ve MASTER_KEY PRIMARY KEY ile değiştirin. CosmosClientFactory.java dosyasında sınıfını oluşturmak CosmosClientFactory için aşağıdaki kodu kullanın:

    package com.microsoft.azure.cosmos.sample.dao;
    
    import com.azure.cosmos.ConsistencyLevel;
    import com.azure.cosmos.CosmosClient;
    import com.azure.cosmos.CosmosClientBuilder;
    
    public class CosmosClientFactory {
        private static final String HOST = "[ACCOUNT HOST NAME]";
        private static final String MASTER_KEY = "[ACCOUNT KEY]";
    
        private static CosmosClient cosmosClient = new CosmosClientBuilder()
                .endpoint(HOST)
                .key(MASTER_KEY)
                .consistencyLevel(ConsistencyLevel.EVENTUAL)
                .buildClient();
    
        public static CosmosClient getCosmosClient() {
            return cosmosClient;
        }
    
    }
    
  2. Yeni bir TodoDao.java dosyası oluşturun ve todo öğelerini oluşturmak, güncelleştirmek, okumak ve silmek için sınıfını ekleyin TodoDao :

    package com.microsoft.azure.cosmos.sample.dao;
    
    import java.util.List;
    
    import com.microsoft.azure.cosmos.sample.model.TodoItem;
    
    public interface TodoDao {
        /**
         * @return A list of TodoItems
         */
        public List<TodoItem> readTodoItems();
    
        /**
         * @param todoItem
         * @return whether the todoItem was persisted.
         */
        public TodoItem createTodoItem(TodoItem todoItem);
    
        /**
         * @param id
         * @return the TodoItem
         */
        public TodoItem readTodoItem(String id);
    
        /**
         * @param id
         * @return the TodoItem
         */
        public TodoItem updateTodoItem(String id, boolean isComplete);
    
        /**
         *
         * @param id
         * @return whether the delete was successful.
         */
        public boolean deleteTodoItem(String id);
    }
    
  3. Yeni bir MockDao.java dosyası oluşturup sınıfını MockDao ekleyin, bu sınıf öğelerinde CRUD işlemleri gerçekleştirmek için sınıfını uygular TodoDao :

    package com.microsoft.azure.cosmos.sample.dao;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import lombok.NonNull;
    
    import com.microsoft.azure.cosmos.sample.model.TodoItem;
    
    public class MockDao implements TodoDao {
        private final Map<String, TodoItem> todoItemMap;
    
        public MockDao() {
            todoItemMap = new HashMap<String, TodoItem>();
        }
    
        @Override
        public TodoItem createTodoItem(@NonNull TodoItem todoItem) {
            if (todoItem.getId() == null || todoItem.getId().isEmpty()) {
                todoItem.setId(generateId());
            }
            todoItemMap.put(todoItem.getId(), todoItem);
            return todoItem;
        }
    
        @Override
        public TodoItem readTodoItem(@NonNull String id) {
            return todoItemMap.get(id);
        }
    
        @Override
        public List<TodoItem> readTodoItems() {
            return new ArrayList<TodoItem>(todoItemMap.values());
        }
    
        @Override
        public TodoItem updateTodoItem(String id, boolean isComplete) {
            todoItemMap.get(id).setComplete(isComplete);
            return todoItemMap.get(id);
        }
    
        @Override
        public boolean deleteTodoItem(@NonNull String id) {
            todoItemMap.remove(id);
            return true;
        }
    
        private String generateId() {
            return new Integer(todoItemMap.size()).toString();
        }
    }
    
  4. Yeni bir DocDbDao.java dosyası oluşturun ve sınıfını DocDbDao ekleyin. Bu sınıf, TodoItems öğesini kapsayıcıda kalıcı hale getirmek için kod tanımlar, varsa veritabanınızı ve koleksiyonunuzu alır veya yoksa yeni bir tane oluşturur. Bu örnekte, TodoItem Düz Eski Java Nesnelerini (POJO'lar) JSON belgelerine seri hale getirmek ve seri durumdan silmek için Gson kullanılır. Yapılacaklar öğelerini bir koleksiyona kaydetmek için, istemcinin hangi veritabanı ve koleksiyona kalıcı hale getireceğini (kendine bağlantılar tarafından başvurulduğu üzere) bilmesi gerekir. Bu sınıf ayrıca belgeleri kendi kendine bağlamak yerine başka bir öznitelikle (ör. "Kimlik") almak için yardımcı işlevi tanımlar. Bir TodoItem JSON belgesini kimliğe göre almak ve ardından pojoya seri durumdan çıkarabilmek için yardımcı yöntemini kullanabilirsiniz.

    Sql sorgusu kullanarak TodoItems koleksiyonunu veya listesini almak için istemci nesnesini de kullanabilirsiniz cosmosClient . Son olarak, bir TodoItem öğesini listenizden silmek için delete yöntemini tanımlarsınız. Aşağıdaki kod sınıfın DocDbDao içeriğini gösterir:

    package com.microsoft.azure.cosmos.sample.dao;
    
    import com.azure.cosmos.CosmosClient;
    import com.azure.cosmos.CosmosContainer;
    import com.azure.cosmos.CosmosDatabase;
    import com.azure.cosmos.CosmosException;
    import com.azure.cosmos.implementation.Utils;
    import com.azure.cosmos.models.CosmosContainerProperties;
    import com.azure.cosmos.models.CosmosContainerResponse;
    import com.azure.cosmos.models.CosmosDatabaseResponse;
    import com.azure.cosmos.models.CosmosItemRequestOptions;
    import com.azure.cosmos.models.CosmosQueryRequestOptions;
    import com.azure.cosmos.models.FeedResponse;
    import com.azure.cosmos.models.PartitionKey;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    import com.google.gson.Gson;
    import com.microsoft.azure.cosmos.sample.model.TodoItem;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class DocDbDao implements TodoDao {
        // The name of our database.
        private static final String DATABASE_ID = "TestDB";
    
        // The name of our collection.
        private static final String CONTAINER_ID = "TestCollection";
    
        // We'll use Gson for POJO <=> JSON serialization for this example.
        private static Gson gson = new Gson();
    
        // The Cosmos DB Client
        private static CosmosClient cosmosClient = CosmosClientFactory
            .getCosmosClient();
    
        // The Cosmos DB database
        private static CosmosDatabase cosmosDatabase = null;
    
        // The Cosmos DB container
        private static CosmosContainer cosmosContainer = null;
    
        // For POJO/JsonNode interconversion
        private static final ObjectMapper OBJECT_MAPPER = Utils.getSimpleObjectMapper();
    
        @Override
        public TodoItem createTodoItem(TodoItem todoItem) {
            // Serialize the TodoItem as a JSON Document.
    
            JsonNode todoItemJson = OBJECT_MAPPER.valueToTree(todoItem);
    
            ((ObjectNode) todoItemJson).put("entityType", "todoItem");
    
            try {
                // Persist the document using the DocumentClient.
                todoItemJson =
                    getContainerCreateResourcesIfNotExist()
                        .createItem(todoItemJson)
                        .getItem();
            } catch (CosmosException e) {
                System.out.println("Error creating TODO item.\n");
                e.printStackTrace();
                return null;
            }
    
    
            try {
    
                return OBJECT_MAPPER.treeToValue(todoItemJson, TodoItem.class);
                //return todoItem;
            } catch (Exception e) {
                System.out.println("Error deserializing created TODO item.\n");
                e.printStackTrace();
    
                return null;
            }
    
        }
    
        @Override
        public TodoItem readTodoItem(String id) {
            // Retrieve the document by id using our helper method.
            JsonNode todoItemJson = getDocumentById(id);
    
            if (todoItemJson != null) {
                // De-serialize the document in to a TodoItem.
                try {
                    return OBJECT_MAPPER.treeToValue(todoItemJson, TodoItem.class);
                } catch (JsonProcessingException e) {
                    System.out.println("Error deserializing read TODO item.\n");
                    e.printStackTrace();
    
                    return null;
                }
            } else {
                return null;
            }
        }
    
        @Override
        public List<TodoItem> readTodoItems() {
    
            List<TodoItem> todoItems = new ArrayList<TodoItem>();
    
            String sql = "SELECT * FROM root r WHERE r.entityType = 'todoItem'";
            int maxItemCount = 1000;
            int maxDegreeOfParallelism = 1000;
            int maxBufferedItemCount = 100;
    
            CosmosQueryRequestOptions options = new CosmosQueryRequestOptions();
            options.setMaxBufferedItemCount(maxBufferedItemCount);
            options.setMaxDegreeOfParallelism(maxDegreeOfParallelism);
            options.setQueryMetricsEnabled(false);
    
            int error_count = 0;
            int error_limit = 10;
    
            String continuationToken = null;
            do {
    
                for (FeedResponse<JsonNode> pageResponse :
                    getContainerCreateResourcesIfNotExist()
                        .queryItems(sql, options, JsonNode.class)
                        .iterableByPage(continuationToken, maxItemCount)) {
    
                    continuationToken = pageResponse.getContinuationToken();
    
                    for (JsonNode item : pageResponse.getElements()) {
    
                        try {
                            todoItems.add(OBJECT_MAPPER.treeToValue(item, TodoItem.class));
                        } catch (JsonProcessingException e) {
                            if (error_count < error_limit) {
                                error_count++;
                                if (error_count >= error_limit) {
                                    System.out.println("\n...reached max error count.\n");
                                } else {
                                    System.out.println("Error deserializing TODO item JsonNode. " +
                                        "This item will not be returned.");
                                    e.printStackTrace();
                                }
                            }
                        }
    
                    }
                }
    
            } while (continuationToken != null);
    
            return todoItems;
        }
    
        @Override
        public TodoItem updateTodoItem(String id, boolean isComplete) {
            // Retrieve the document from the database
            JsonNode todoItemJson = getDocumentById(id);
    
            // You can update the document as a JSON document directly.
            // For more complex operations - you could de-serialize the document in
            // to a POJO, update the POJO, and then re-serialize the POJO back in to
            // a document.
            ((ObjectNode) todoItemJson).put("complete", isComplete);
    
            try {
                // Persist/replace the updated document.
                todoItemJson =
                    getContainerCreateResourcesIfNotExist()
                        .replaceItem(todoItemJson, id, new PartitionKey(id), new CosmosItemRequestOptions())
                        .getItem();
            } catch (CosmosException e) {
                System.out.println("Error updating TODO item.\n");
                e.printStackTrace();
                return null;
            }
    
            // De-serialize the document in to a TodoItem.
            try {
                return OBJECT_MAPPER.treeToValue(todoItemJson, TodoItem.class);
            } catch (JsonProcessingException e) {
                System.out.println("Error deserializing updated item.\n");
                e.printStackTrace();
    
                return null;
            }
        }
    
        @Override
        public boolean deleteTodoItem(String id) {
            // CosmosDB refers to documents by self link rather than id.
    
            // Query for the document to retrieve the self link.
            JsonNode todoItemJson = getDocumentById(id);
    
            try {
                // Delete the document by self link.
                getContainerCreateResourcesIfNotExist()
                    .deleteItem(id, new PartitionKey(id), new CosmosItemRequestOptions());
            } catch (CosmosException e) {
                System.out.println("Error deleting TODO item.\n");
                e.printStackTrace();
                return false;
            }
    
            return true;
        }
    
        /*
        
        private CosmosDatabase getTodoDatabase() {
            if (databaseCache == null) {
                // Get the database if it exists
                List<CosmosDatabase> databaseList = cosmosClient
                        .queryDatabases(
                                "SELECT * FROM root r WHERE r.id='" + DATABASE_ID
                                        + "'", null).getQueryIterable().toList();
    
                if (databaseList.size() > 0) {
                    // Cache the database object so we won't have to query for it
                    // later to retrieve the selfLink.
                    databaseCache = databaseList.get(0);
                } else {
                    // Create the database if it doesn't exist.
                    try {
                        CosmosDatabase databaseDefinition = new CosmosDatabase();
                        databaseDefinition.setId(DATABASE_ID);
    
                        databaseCache = cosmosClient.createDatabase(
                                databaseDefinition, null).getResource();
                    } catch (CosmosException e) {
                        // TODO: Something has gone terribly wrong - the app wasn't
                        // able to query or create the collection.
                        // Verify your connection, endpoint, and key.
                        e.printStackTrace();
                    }
                }
            }
    
            return databaseCache;
        }
    
        */
    
        private CosmosContainer getContainerCreateResourcesIfNotExist() {
    
            try {
    
                if (cosmosDatabase == null) {
                    CosmosDatabaseResponse cosmosDatabaseResponse = cosmosClient.createDatabaseIfNotExists(DATABASE_ID);
                    cosmosDatabase = cosmosClient.getDatabase(cosmosDatabaseResponse.getProperties().getId());
                }
    
            } catch (CosmosException e) {
                // TODO: Something has gone terribly wrong - the app wasn't
                // able to query or create the collection.
                // Verify your connection, endpoint, and key.
                System.out.println("Something has gone terribly wrong - " +
                    "the app wasn't able to create the Database.\n");
                e.printStackTrace();
            }
    
            try {
    
                if (cosmosContainer == null) {
                    CosmosContainerProperties properties = new CosmosContainerProperties(CONTAINER_ID, "/id");
                    CosmosContainerResponse cosmosContainerResponse = cosmosDatabase.createContainerIfNotExists(properties);
                    cosmosContainer = cosmosDatabase.getContainer(cosmosContainerResponse.getProperties().getId());
                }
    
            } catch (CosmosException e) {
                // TODO: Something has gone terribly wrong - the app wasn't
                // able to query or create the collection.
                // Verify your connection, endpoint, and key.
                System.out.println("Something has gone terribly wrong - " +
                    "the app wasn't able to create the Container.\n");
                e.printStackTrace();
            }
    
            return cosmosContainer;
        }
    
        private JsonNode getDocumentById(String id) {
    
            String sql = "SELECT * FROM root r WHERE r.id='" + id + "'";
            int maxItemCount = 1000;
            int maxDegreeOfParallelism = 1000;
            int maxBufferedItemCount = 100;
    
            CosmosQueryRequestOptions options = new CosmosQueryRequestOptions();
            options.setMaxBufferedItemCount(maxBufferedItemCount);
            options.setMaxDegreeOfParallelism(maxDegreeOfParallelism);
            options.setQueryMetricsEnabled(false);
    
            List<JsonNode> itemList = new ArrayList();
    
            String continuationToken = null;
            do {
                for (FeedResponse<JsonNode> pageResponse :
                    getContainerCreateResourcesIfNotExist()
                        .queryItems(sql, options, JsonNode.class)
                        .iterableByPage(continuationToken, maxItemCount)) {
    
                    continuationToken = pageResponse.getContinuationToken();
    
                    for (JsonNode item : pageResponse.getElements()) {
                        itemList.add(item);
                    }
                }
    
            } while (continuationToken != null);
    
            if (itemList.size() > 0) {
                return itemList.get(0);
            } else {
                return null;
            }
        }
    
    }
    
  5. Ardından yeni bir TodoDaoFactory.java dosyası oluşturun ve yeni bir DocDbDao nesnesi oluşturan sınıfı ekleyin TodoDaoFactory :

    package com.microsoft.azure.cosmos.sample.dao;
    
    public class TodoDaoFactory {
        private static TodoDao myTodoDao = new DocDbDao();
    
        public static TodoDao getDao() {
            return myTodoDao;
        }
    }
    

Denetleyici ekleme

TodoItemController denetleyicisini uygulamanıza ekleyin. Bu projede oluşturucuyu, alıcıları, ayarlayıcıları ve bir derleyici oluşturmak için Project Lombok'u kullanırsınız. Alternatif olarak, bu kodu el ile yazabilir veya IDE'nin oluşturmasını sağlayabilirsiniz:

package com.microsoft.azure.cosmos.sample.controller;

import java.util.List;
import java.util.UUID;

import lombok.NonNull;

import com.microsoft.azure.cosmos.sample.dao.TodoDao;
import com.microsoft.azure.cosmos.sample.dao.TodoDaoFactory;
import com.microsoft.azure.cosmos.sample.model.TodoItem;

public class TodoItemController {
    public static TodoItemController getInstance() {
        if (todoItemController == null) {
            todoItemController = new TodoItemController(TodoDaoFactory.getDao());
        }
        return todoItemController;
    }

    private static TodoItemController todoItemController;

    private final TodoDao todoDao;

    TodoItemController(TodoDao todoDao) {
        this.todoDao = todoDao;
    }

    public TodoItem createTodoItem(@NonNull String name,
            @NonNull String category, boolean isComplete) {
        TodoItem todoItem = new TodoItem();
        
        todoItem.setName(name);
        todoItem.setCategory(category);
        todoItem.setComplete(isComplete);
        todoItem.setId(UUID.randomUUID().toString());

        return todoDao.createTodoItem(todoItem);
    }

    public boolean deleteTodoItem(@NonNull String id) {
        return todoDao.deleteTodoItem(id);
    }

    public TodoItem getTodoItemById(@NonNull String id) {
        return todoDao.readTodoItem(id);
    }

    public List<TodoItem> getTodoItems() {
        return todoDao.readTodoItems();
    }

    public TodoItem updateTodoItem(@NonNull String id, boolean isComplete) {
        return todoDao.updateTodoItem(id, isComplete);
    }
}

Servlet oluşturma

Ardından HTTP isteklerini denetleyiciye yönlendirmek için bir servlet oluşturun. ApiServlet.java dosyasını oluşturun ve altında aşağıdaki kodu tanımlayın:

package com.microsoft.azure.cosmos.sample;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.gson.Gson;
import com.microsoft.azure.cosmos.sample.controller.TodoItemController;

/**
 * API Frontend Servlet
 */
@WebServlet("/api")
public class ApiServlet extends HttpServlet {
    // API Keys
    public static final String API_METHOD = "method";

    // API Methods
    public static final String CREATE_TODO_ITEM = "createTodoItem";
    public static final String GET_TODO_ITEMS = "getTodoItems";
    public static final String UPDATE_TODO_ITEM = "updateTodoItem";

    // API Parameters
    public static final String TODO_ITEM_ID = "todoItemId";
    public static final String TODO_ITEM_NAME = "todoItemName";
    public static final String TODO_ITEM_CATEGORY = "todoItemCategory";
    public static final String TODO_ITEM_COMPLETE = "todoItemComplete";

    public static final String MESSAGE_ERROR_INVALID_METHOD = "{'error': 'Invalid method'}";

    private static final long serialVersionUID = 1L;
    private static final Gson gson = new Gson();

    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {

        String apiResponse = MESSAGE_ERROR_INVALID_METHOD;

        TodoItemController todoItemController = TodoItemController
                .getInstance();

        String id = request.getParameter(TODO_ITEM_ID);
        String name = request.getParameter(TODO_ITEM_NAME);
        String category = request.getParameter(TODO_ITEM_CATEGORY);
        String itemComplete = request.getParameter(TODO_ITEM_COMPLETE);
        boolean isComplete = itemComplete!= null && itemComplete.equalsIgnoreCase("true");

        switch (request.getParameter(API_METHOD)) {
        case CREATE_TODO_ITEM:
            apiResponse = gson.toJson(todoItemController.createTodoItem(name,
                    category, isComplete));
            break;
        case GET_TODO_ITEMS:
            apiResponse = gson.toJson(todoItemController.getTodoItems());
            break;
        case UPDATE_TODO_ITEM:
            apiResponse = gson.toJson(todoItemController.updateTodoItem(id,
                    isComplete));
            break;
        default:
            break;
        }

        response.setCharacterEncoding("UTF-8");
        response.getWriter().println(apiResponse);
    }

    @Override
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

Java uygulamasının geri kalanını birbirine bağlama

Artık eğlenceli bitleri tamamladığımıza göre, geriye sadece hızlı bir kullanıcı arabirimi oluşturup DAO'nuza aktarmak kaldı.

  1. Kullanıcıya görüntülemek için bir web kullanıcı arabirimine ihtiyacınız vardır. Şimdi daha önce oluşturduğumuz index.jsp dosyasını aşağıdaki kodla yeniden yazalım:

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge;" />
      <title>Azure Cosmos Java Sample</title>
    
      <!-- Bootstrap -->
      <link href="//ajax.aspnetcdn.com/ajax/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
    
      <style>
        /* Add padding to body for fixed nav bar */
        body {
          padding-top: 50px;
        }
      </style>
    </head>
    <body>
      <!-- Nav Bar -->
      <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
        <div class="container">
          <div class="navbar-header">
            <a class="navbar-brand" href="#">My Tasks</a>
          </div>
        </div>
      </div>
    
      <!-- Body -->
      <div class="container">
        <h1>My ToDo List</h1>
    
        <hr/>
    
        <!-- The ToDo List -->
        <div class = "todoList">
          <table class="table table-bordered table-striped" id="todoItems">
            <thead>
              <tr>
                <th>Name</th>
                <th>Category</th>
                <th>Complete</th>
              </tr>
            </thead>
            <tbody>
            </tbody>
          </table>
    
          <!-- Update Button -->
          <div class="todoUpdatePanel">
            <form class="form-horizontal" role="form">
              <button type="button" class="btn btn-primary">Update Tasks</button>
            </form>
          </div>
    
        </div>
    
        <hr/>
    
        <!-- Item Input Form -->
        <div class="todoForm">
          <form class="form-horizontal" role="form">
            <div class="form-group">
              <label for="inputItemName" class="col-sm-2">Task Name</label>
              <div class="col-sm-10">
                <input type="text" class="form-control" id="inputItemName" placeholder="Enter name">
              </div>
            </div>
    
            <div class="form-group">
              <label for="inputItemCategory" class="col-sm-2">Task Category</label>
              <div class="col-sm-10">
                <input type="text" class="form-control" id="inputItemCategory" placeholder="Enter category">
              </div>
            </div>
    
            <button type="button" class="btn btn-primary">Add Task</button>
          </form>
        </div>
    
      </div>
    
      <!-- Placed at the end of the document so the pages load faster -->
      <script src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.1.min.js"></script>
      <script src="//ajax.aspnetcdn.com/ajax/bootstrap/3.2.0/bootstrap.min.js"></script>
      <script src="assets/todo.js"></script>
    </body>
    </html>
    
  2. Son olarak, web kullanıcı arabirimini ve servlet'i birbirine bağlamak için istemci tarafı JavaScript yazın:

    /**
     * ToDo App
     */
    
    var todoApp = {
      /*
       * API methods to call Java backend.
       */
      apiEndpoint: "api",
    
      createTodoItem: function(name, category, isComplete) {
        $.post(todoApp.apiEndpoint, {
            "method": "createTodoItem",
            "todoItemName": name,
            "todoItemCategory": category,
            "todoItemComplete": isComplete
          },
          function(data) {
            var todoItem = data;
            todoApp.addTodoItemToTable(todoItem.id, todoItem.name, todoItem.category, todoItem.complete);
          },
          "json");
      },
    
      getTodoItems: function() {
        $.post(todoApp.apiEndpoint, {
            "method": "getTodoItems"
          },
          function(data) {
            var todoItemArr = data;
            $.each(todoItemArr, function(index, value) {
              todoApp.addTodoItemToTable(value.id, value.name, value.category, value.complete);
            });
          },
          "json");
      },
    
      updateTodoItem: function(id, isComplete) {
        $.post(todoApp.apiEndpoint, {
            "method": "updateTodoItem",
            "todoItemId": id,
            "todoItemComplete": isComplete
          },
          function(data) {},
          "json");
      },
    
      /*
       * UI Methods
       */
      addTodoItemToTable: function(id, name, category, isComplete) {
        var rowColor = isComplete ? "active" : "warning";
    
        todoApp.ui_table().append($("<tr>")
          .append($("<td>").text(name))
          .append($("<td>").text(category))
          .append($("<td>")
            .append($("<input>")
              .attr("type", "checkbox")
              .attr("id", id)
              .attr("checked", isComplete)
              .attr("class", "isComplete")
            ))
          .addClass(rowColor)
        );
      },
    
      /*
       * UI Bindings
       */
      bindCreateButton: function() {
        todoApp.ui_createButton().click(function() {
          todoApp.createTodoItem(todoApp.ui_createNameInput().val(), todoApp.ui_createCategoryInput().val(), false);
          todoApp.ui_createNameInput().val("");
          todoApp.ui_createCategoryInput().val("");
        });
      },
    
      bindUpdateButton: function() {
        todoApp.ui_updateButton().click(function() {
          // Disable button temporarily.
          var myButton = $(this);
          var originalText = myButton.text();
          $(this).text("Updating...");
          $(this).prop("disabled", true);
    
          // Call api to update todo items.
          $.each(todoApp.ui_updateId(), function(index, value) {
            todoApp.updateTodoItem(value.name, value.value);
            $(value).remove();
          });
    
          // Re-enable button.
          setTimeout(function() {
            myButton.prop("disabled", false);
            myButton.text(originalText);
          }, 500);
        });
      },
    
      bindUpdateCheckboxes: function() {
        todoApp.ui_table().on("click", ".isComplete", function(event) {
          var checkboxElement = $(event.currentTarget);
          var rowElement = $(event.currentTarget).parents('tr');
          var id = checkboxElement.attr('id');
          var isComplete = checkboxElement.is(':checked');
    
          // Togle table row color
          if (isComplete) {
            rowElement.addClass("active");
            rowElement.removeClass("warning");
          } else {
            rowElement.removeClass("active");
            rowElement.addClass("warning");
          }
    
          // Update hidden inputs for update panel.
          todoApp.ui_updateForm().children("input[name='" + id + "']").remove();
    
          todoApp.ui_updateForm().append($("<input>")
            .attr("type", "hidden")
            .attr("class", "updateComplete")
            .attr("name", id)
            .attr("value", isComplete));
    
        });
      },
    
      /*
       * UI Elements
       */
      ui_createNameInput: function() {
        return $(".todoForm #inputItemName");
      },
    
      ui_createCategoryInput: function() {
        return $(".todoForm #inputItemCategory");
      },
    
      ui_createButton: function() {
        return $(".todoForm button");
      },
    
      ui_table: function() {
        return $(".todoList table tbody");
      },
    
      ui_updateButton: function() {
        return $(".todoUpdatePanel button");
      },
    
      ui_updateForm: function() {
        return $(".todoUpdatePanel form");
      },
    
      ui_updateId: function() {
        return $(".todoUpdatePanel .updateComplete");
      },
    
      /*
       * Install the TodoApp
       */
      install: function() {
        todoApp.bindCreateButton();
        todoApp.bindUpdateButton();
        todoApp.bindUpdateCheckboxes();
    
        todoApp.getTodoItems();
      }
    };
    
    $(document).ready(function() {
      todoApp.install();
    });
    
  3. Şimdi geriye yalnızca uygulamayı test etmek kaldı. Uygulamayı yerel olarak çalıştırın, ardından öğe adı ve kategoriyi doldurarak ve Görev Ekle'ye tıklayarak birkaç Yapılacaklar öğesi ekleyin. Öğe göründükten sonra onay kutusunu açıp Görevleri Güncelleştir'e tıklayarak öğenin tamamlanıp tamamlanmadığını güncelleştirebilirsiniz.

Java uygulamanızı Azure Web Sitelerine dağıtma

Azure Web Siteleri Java uygulamalarını dağıtmayı, uygulamanızı bir WAR dosyası olarak dışarı aktarmak ve kaynak denetimi (ör. Git) veya FTP aracılığıyla karşıya yüklemek kadar basit hale getirir.

  1. Uygulamanızı WAR dosyası olarak dışarı aktarmak için Proje Gezgini'nde projenize sağ tıklayın, Dışarı Aktar'ı ve ardından WAR Dosyası'na tıklayın.

  2. WAR Dışarı Aktar penceresinde aşağıdakileri yapın:

    • Web projesi kutusuna azure-cosmos-java-sample girin.
    • Hedef kutusunda WAR dosyasını kaydetmek için bir hedef seçin.
    • Son'u seçin.
  3. Artık elinizde bir WAR dosyası olduğuna göre, bunu Azure Web Sitenizin webapps dizinine yüklemeniz yeterlidir. Dosyayı karşıya yükleme konusunda yönergeler için bkz. Azure App Service Web Apps’e Java uygulaması ekleme. WAR dosyası webapps dizinine yüklendikten sonra çalışma zamanı ortamı eklediğinizi algılar ve otomatik olarak yükler.

  4. Tamamlanmış ürününüzü görüntülemek için, http://YOUR\_SITE\_NAME.azurewebsites.net/azure-cosmos-java-sample/ adresine gidip görevlerinizi eklemeye başlayın!

Projeyi GitHub'dan alma

Bu öğreticideki tüm örnekler GitHub'daki todo projesinde bulunur. todo projesini Eclipse'e aktarmak için Önkoşullar bölümünde listelenen yazılım ve kaynaklara sahip olduğunuzdan emin olun ve ardından aşağıdakileri yapın:

  1. Proje Lombok'u yükleyin. Lombok projede oluşturucular, alıcılar ve ayarlayıcılar oluşturmak için kullanılır. Lombok.jar dosyasını indirdikten sonra, yüklemek için buna çift tıklayın veya komut satırından yükleyin.

  2. Eclipse açıksa kapatın ve Lombok'u yüklemek için yeniden başlatın.

  3. Eclipse'te , Dosya menüsünde İçeri Aktar'ı seçin.

  4. İçeri Aktar penceresinde Git'i, Git'ten Projeler'i ve ardından İleri'yi seçin.

  5. Depo Kaynağı Seç ekranında URI'yi Kopyala'yı seçin.

  6. Kaynak Git Deposu ekranında, URI kutusuna yazın https://github.com/Azure-Samples/azure-cosmos-java-sql-api-todo-appve İleri'yi seçin.

  7. Dal Seçimi ekranında main öğesinin seçili olduğundan emin olun ve ardından İleri'yi seçin.

  8. Yerel Hedef ekranında, deponun kopyalandığı klasörü seçmek için Gözat'ı ve ardından İleri'yi seçin.

  9. Projeleri içeri aktarmak için kullanılacak sihirbazı seçin ekranında Varolan projeleri içeri aktar'ın seçili olduğundan emin olun ve ardından İleri'yi seçin.

  10. Projeleri İçeri Aktar ekranında DocumentDB projesinin seçimini kaldırın ve son'u seçin. DocumentDB projesi, daha sonra bağımlılık olarak ekleyeceğimiz Azure Cosmos DB Java SDK'sını içerir.

  11. Proje Gezgini'nde azure-cosmos-java-sample\src\com.microsoft.azure.cosmos.sample.dao\DocumentClientFactory.java adresine gidin, HOST ve MASTER_KEY değerlerini Azure Cosmos DB hesabınız için URI ve BİRİnCİl ANAHTAR ile değiştirin ve dosyayı kaydedin. Daha fazla bilgi için bkz . 1. Adım. Azure Cosmos DB veritabanı hesabı oluşturun.

  12. Proje Gezgini'ndeazure-cosmos-java-sample öğesine sağ tıklayın, Derleme Yolu'nu ve ardından Derleme Yolunu Yapılandır'ı seçin.

  13. Java Derleme Yolu ekranında, sağ bölmede Kitaplıklar sekmesini ve ardından Dış JAR Ekle'yi seçin. lombok.jar dosyasının konumuna gidin, Aç'ı ve ardından Tamam'ı seçin.

  14. Özellikler penceresini yeniden açmak için 12. adımı kullanın ve sol bölmede Hedeflenen Çalışma Zamanları'nı seçin.

  15. Hedeflenen Çalışma Zamanları ekranında Yeni'yi, Apache Tomcat v7.0'ı ve ardından Tamam'ı seçin.

  16. Özellikler penceresini yeniden açmak için 12. adımı kullanın ve sol bölmede Proje Modelleri'ni seçin.

  17. Proje Modelleri ekranında Dinamik Web Modülü ve Java'yı ve ardından Tamam'ı seçin.

  18. Ekranın alt kısmındaki Sunucular sekmesinde localhost'ta Tomcat v7.0 Server'a sağ tıklayın ve Ekle ve Kaldır'ı seçin.

  19. Ekle ve Kaldır penceresinde azure-cosmos-java-sample öğesini Yapılandırılmış kutusuna taşıyın ve son'u seçin.

  20. Sunucular sekmesinde Localhost'ta Tomcat v7.0 Server'a sağ tıklayın ve yeniden başlat'ı seçin.

  21. Bir tarayıcıda, http://localhost:8080/azure-cosmos-java-sample/ konumuna gidin ve görev listenizi eklemeye başlayın. Varsayılan bağlantı noktası değerlerinizi değiştirdiyseniz 8080'i seçtiğiniz değere değiştirmeyi unutmayın.

  22. Projenizi bir Azure web sitesine dağıtmak için bkz . 6. Adım. Uygulamanızı Azure Web Sitelerine dağıtın.

Sonraki adımlar

Azure Cosmos DB'ye geçiş için kapasite planlaması yapmaya mı çalışıyorsunuz? Kapasite planlaması için mevcut veritabanı kümeniz hakkındaki bilgileri kullanabilirsiniz.