SprinMVC ve MongoDB 1: Projenin Hazırlanması
SpringMVC ve MongoDB
Daha önceki yazılarda Rest servislerinin nasıl geliştirilebileceği üzerine konuşmuştuk. Bu sefer RDB yerine NoSQL, JPA yerine Spring Data ve Jersey yerine de SpringMVC kullanacağız. Ek olarak en temel halindeki rest servis mimarisini değil daha gelişmiş bir Rest servis mimarisini kullanacağız. Fakat bu servis mimarisi Hateoas kadar gelişmiş olmayacak. Gelişmişlik açısından Hateoas’ın bir tık altını hedef alacağız. Ayrıca uygulamamızı cloud servislere deploy edeceğiz. Cloud Servis sağlayıcısı olarak heroku kullanacağız. Projenin paket yönetimi yine maven yönetecek, test ve canlı ortamımızda servlet container olarak Jetty kullanacağız.
Yazı dizisinin özeti aşağıdaki gibidir.
- Projenin Hazırlanması
- Projenin Yaratılması
- Genel Proje Ayarları
- Heroku’da Proje Nasıl Yaratılır?
- MongoLab – Cloud Servis Olarak MongoDB
- MongoDB ve SpringData ile DAO Katmanı
- SpringData ile Modeller
- SpringData’da DAO Katmanı
- SpringData ve MongoDB Erisim Ayarları
- DAO Testleri ve Fongo
- Servis Katmanı
- Servis Katmanı Nasıl Olmalı?
- Mockito ile Servis Testlerinin Yazılması
- SpringMVC ile Rest Servisleri
- Rest Servisi – Yani Controller
- SpringMVC Ayarları Nasıl Yapılır?
- SpringMVC Testleri ve JsonPath
SprinMVC ve MongoDB 1: Projenin Hazırlanması
Öncelikle projemizi ve cloud servislerimizi hazırlayalım. Amacım herokunun ve diğer cloud servislerinin nasıl kullanılacağını göstermek. Tutorial çerçevesinde, temel Spring ve Java bilginizin olduğunu varsayacağım. Aynı şekilde heroku sistemine kayıt yaptırdığınızı ve komut satırı araçlarını yüklediğinizi varsayacağım. Benim komut satırından anlattığım herşeyi online web uygulaması üzerinden yapmakta mümkün tabi.
Projenin Yaratılması
Şimdi öncelikle projemizi oluşturalım. Basit bir projemiz olacak. Temel olarak sadece bir User nesnemiz olacak. Servisler üzeirnden bu User nesnesinde CRUD(Create, Read, Update ve Delete) işlemleri yapılabilecek. Bu sebepten projemizin adı user-application olsun.
Maven ile projeyi oluştururken aşağıdaki adımları izleyebilirsiniz. Genelde diğer tutoriallarda yaptığım gibi önce Maven ve komut satırı araçlarından ilerleyip sonrasında IDE’ye geçiş yapacağım.
- mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp
- Group Id olarak, com.bahadirakin
- ArtifactId olarak user-application
- Paket adı olarak ise com.bahadirakin
Projemiz oluştuğuna göre, bağımlılıkların tanımlanması gerekiyor. Bunun için pom.xml dosyasının içeriğini aşağıdaki gibi yapıyoruz.
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.bahadirakin</groupId> <artifactId>user-application</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>user-application Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.java.version>1.6</project.java.version> <slf4j.version>1.7.7</slf4j.version> <logback.version>1.0.13</logback.version> <spring.version>4.0.7.RELEASE</spring.version> <spring.data.version>1.6.2.RELEASE</spring.data.version> <mongodb.driver.version>2.13.0</mongodb.driver.version> <jackson.version>2.4.0</jackson.version> <!-- Testing.Version --> <junit.version>4.11</junit.version> <fongo.version>1.6.0</fongo.version> <mockito.version>1.9.5</mockito.version> <jsonpath.version>0.9.1</jsonpath.version> </properties> <build> <finalName>user-application</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>${project.java.version}</source> <target>${project.java.version}</target> </configuration> </plugin> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.2.1.v20140609</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.3</version> <executions> <execution> <phase>package</phase> <goals><goal>copy</goal></goals> <configuration> <artifactItems> <artifactItem> <groupId>org.mortbay.jetty</groupId> <artifactId>jetty-runner</artifactId> <version>7.5.4.v20111024</version> <destFileName>jetty-runner.jar</destFileName> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <!-- Logging Dependencies --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <!-- Spring Dependencies --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>${spring.data.version}</version> </dependency> <!-- MongoDB Driver --> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>${mongodb.driver.version}</version> </dependency> <!-- JSON Processing --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson.version}</version> </dependency> <!-- Runtime Dependencies --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <!-- Test Dependencies --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.github.fakemongo</groupId> <artifactId>fongo</artifactId> <version>${fongo.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>${mockito.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>{jsonpath.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path-assert</artifactId> <version>${jsonpath.version}</version> <scope>test</scope> </dependency> </dependencies> </project> |
Daha sonrasında mvn clean install diyerek pom.xml içerisinde bir hata yapıp yapmadığınızı kontrol edebilirsiniz. Burada proje genelindeki tüm bağımlılıkları tanımladık. Bundan sonra başka bir tanımlama yapmamıza gerek olmayacak.
Genel Proje Ayarları
Herbir alt modül her ne kadar kendi içerisinde ayarlanacak olsa da genel ayarlamaları burada belirtmekte fayda var. Öneğin SpingMVC anlatırken SpringMVC ile ilgili ayarlara ya da Spring Data anlatırken Spring Data ile ilgili ayarlara değinilecektir. Fakat alt modüllerin ayarlamaları bu bölümde yapılanlar dikkate alınarak yapılacaktır.
Öncelikle web.xml dosyamızı ayarlayalım.
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="user-application" version="2.5"> <display-name>user-application</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app> |
Genel spring ayarlamalarını belirttik. Şimdi ise web.xml içerisinde spring ayarlarını yaparken belirttiğimiz applicationContext.xml dosyasını yaratlım. Bunun için src/main/resources dizinin altına applicationContext.xml isminde bir dosya oluşturuyoruz ve içeriğini aşağıdaki gibi yapıyoruz.
applicationContext.xml
1 2 3 4 5 6 7 8 9 10 11 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> </beans> |
Taslak halindeki ayarlamalarımız da yaptık. Ayarlarımızın doğru olup olmadığını anlamak için önce “mvn clean install jetty:run” komutunu çalıştırıyoruz. Ardından tarayıcıdan “http://localhost:8080” adresine giderek uygulamamızın düzgün başlayıp başlamadığını kontrol ediyoruz.
Heroku’da Projenin Nasıl Yaratılır?
Heroku’da projenin nasıl yaratılacağına geçmeden önce, tutorial çerçevesinde kullanacağım komutlardan kısaca bahsetmek istiyorum.
- heroku: Ana heroku komutu. Sisteme login olmaktan tutunda, sistemdeki git reposunu kullanmaya kadar tüm işlemlerinizi bu komut üzerinden yapacaksınız. İlgili komutlarınızı çalıştırmaya başlamadan önce illaki sisteme login olmalısınız.
- forearm: Sık sık kullanacağımız diğer komut. Bu komut heroku projenizin, cloud’ta çalıştırıldığı gibi lokalinizde çalıştırmanıza olanak sağlar. Örneğin her heroku projesinde Procfile isminde dosyalar bulunur. Heroku sunucuda bu dosyaları okuyarak sizin için hangi modülleri ayağa kaldıracağını bilir. Procfile içerisinde yaptığınız değişiklikleri lokalinizde forearm kullanarak test edebilirsiniz.
Öncelikle heroku’ya login oluyoruz. Bunun için komut satırından “heroku login” komutunu kullanıyoruz. Bu komutu çalıştırdığımızda bize heroku’ya kayıt olduğumuz email ve şifreyi soracaktır. Bu bilgileri sağladıktan sonra herokuya başarılı şekilde login yapmış oluyoruz.
Login yaptıktan sonra “heroku create” diyerek heroku sisteminde proje yaratıyoruz. Komut çalıştıktan sonra, komut satırında aşağıdakine benzer bir çıktı göreceksiniz.
$ heroku create
More information here: https://blog.heroku.com/archives/2014/12/23/updateyourgitclientsonwindowsandosx
Creating mysterious-woodland-4843… done, stack is cedar-14
https://mysterious-woodland-4843.herokuapp.com/ | https://git.heroku.com/mysterious-woodland-4843.git
Burada koyu işaretlediğim(mysterious-woodland-4843) yer herokunun uygulamanız için atadığı isim. Her kullanıcı için ismi otomatik olarak yaratacaktır. Bu ismi değiştirmeniz mümkün, fakat nasıl yapacağınıza bu tutorial kapsamında değinmeyeceğim.
Projenizi herokuya deploy etmeden önce, projenizin nasıl çalıştırılacağını belirtmeniz gerekiyor. Bunun için ana dizinde Procfile isimli bir dosya oluşturup içeriğini aşağıdaki gibi yapıyoruz.
Procfile
1 | web: java $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war |
Procfile dosyasınıda oluşturduktan sonra forearm uygulamasıyla test ediyoruz. Bunun için projenin ana dizininde “forearm start” komutunu çalıştırdıktan sonra localhost:5000 adresinden projemizin doğru çalışıp çalışmadığını test ediyoruz.
Herokuya projenizi deploy edebilmek için git kullanmanız gerekiyor. Bu sebepten projenizin ana dizininde “git init” komutunu çalıştırıyoruz. Bu komut bizim için lokalde git repository’si oluşturuyor. Tüm dosyalarımızı git repository’sine commitleyebilmek için “git add .” komutuyla ekliyoruz. Tüm dosyalar eklendikten sonra git commit -m “Initial Commit” diyerek lokal repository’mize commit geçiyoruz. Daha sonra “heroku git:remote -a <uygulama_adi>” şeklinde komutumuzu çalıştırıyoruz. Bu komut bizim için git uzak adresi (remote) olarak heraku adresini veriyor. Benim için bu örnekte komut heroku git:remote -a mysterious-woodland-4843 şeklinde oluyor. Eğer uygulamanızı herokuya deploy etmek isterseniz “git push heroku master” komutunu çalıştırmanız yeterli olacaktır. Eğer procfile dosyanızda bir sorununuz bulunmuyorsa deployment başarıyla gerçekleşecektir. Hemen ardından projeniz oluşturulurken verilen adresten (benim proje adıma göre bu adres https://mysterious-woodland-4843.herokuapp.com/ şeklindedir) uygulamanızı test edebilirsiniz.
MongoLab – Cloud Servis Olarak MongoDB
Projemizi herokuya deploy ettiğimize göre şimdi sırada MongDB kurulumuna geldi. Herşeyimizi Cloud’ta yönettiğimize göre, gidip lokalimize mongodb kurmak saçma olacak. Bu sebepten heroku servisimize MongoLab eklentisini kuracağız ve mongodb’mizi bu şekilde yöneteceğiz.
MongoLab tahmin edeceğiniz üzere Cloud servis olarak mongodb sağlıyor. Bedava olan planıda mevcut. Zaten proje genelinde de biz bu planını kullanacağız. MongoLab eklentisini yüklemek için, sisteme login olduktan sonra heroku addons:add mongolab komutunu çalıştırıyoruz.
Eğer heroku sistemine kayıt olurken kredi kartı bilgilerinizi vermediyseniz, bu eklenti kurulumunu gerçekleştiremezsiniz. Eğer kredi kartı bilgilerinizi vermek istemiyorsanız, MongoLab üzerinde kendiniz gidip hesap açabilir ve veritabanınızı burada oluşturabilirsiniz. Eğer heroku sistemine kayıt olurken kredi kartı bilgilerinizi vermediyseniz fakat şimdi vermek istiyorsanız https://heroku.com/verify adresindeki yönergeleri takip edebilirsiniz. Bundan sonra yukarıdaki komutu tekrar çalıştırdığınızda sorunsuzca eklentinizi ekleyebilmiş olmanız gerekiyor. Örnek komut satırı çıktısı aşağıdaki gibidir.
$ heroku addons:add mongolab
Adding mongolab on mysterious-woodland-4843… done, v7 (free)
Welcome to MongoLab. Your new subscription is being created and will be available shortly. Please consult the MongoLab Add-on Admin UI to check on its progress.
Use
heroku addons:docs mongolab
to view documentation.
MongoDB’nizi mongolab üzerinden yarattıktan sonra şimdi buna nasıl bağlanabileceğinize bakalım. Bunun için aşağıdaki komutu çalıştırmanız yeterli olacaktır. Daha sonradan favori MongoDB(ben mac’te robomongo arayüzünü kullanıyorum) arayüzünüzden bağlantı bilgilerinizi test edebilirsiniz.
$ heroku config | grep MONGOLABURI
MONGOLABURI: mongodb://<kullaniciadi>:<sifre>@ds031601.mongolab.com:31601/herokuapp33810136
Bu bağlantı bilgilerini ileride SpringData ile MongoDb bağlantısı yaparken kullanacağız. Burada ek bir bilgi olarak şunu belirteyim, isterseniz komut satırından yaptığımız gibi heroku bağlantı bilgilerini heroku config üzerinden almanızda mümkün, fakat basitlik sağlaması açısından biz elle vereceğiz.
Son Dokunuslar
Projenin hazırlanması kısmını bitirmeden önce son dokunuşlarımızı yapalım. GIT reposunu yarattık fakat .gitignore dosyamızı eklemedik. Öncelikle bu dosyamızı ekleyelim. Örnek .gitignore dosyamız aşağıdaki gibidir.
.gitignore
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | # Created by https://www.gitignore.io log/ ### Intellij ### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm *.iml ## Directory-based project format: .idea/ # if you remove the above rule, at least ignore the following: # User-specific stuff: # .idea/workspace.xml # .idea/tasks.xml # .idea/dictionaries # Sensitive or high-churn files: # .idea/dataSources.ids # .idea/dataSources.xml # .idea/sqlDataSources.xml # .idea/dynamic.xml # .idea/uiDesigner.xml # Gradle: # .idea/gradle.xml # .idea/libraries # Mongo Explorer plugin: # .idea/mongoSettings.xml ## File-based project format: *.ipr *.iws ## Plugin-specific files: # IntelliJ out/ # mpeltonen/sbt-idea plugin .idea_modules/ # JIRA plugin atlassian-ide-plugin.xml # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties ### Eclipse ### *.pydevproject .metadata .gradle bin/ tmp/ *.tmp *.bak *.swp *~.nib local.properties .settings/ .loadpath # External tool builders .externalToolBuilders/ # Locally stored "Eclipse launch configurations" *.launch # CDT-specific .cproject # PDT-specific .buildpath # sbteclipse plugin .target # TeXlipse plugin .texlipse ### Maven ### target/ pom.xml.tag pom.xml.releaseBackup pom.xml.versionsBackup pom.xml.next release.properties ### OSX ### .DS_Store .AppleDouble .LSOverride # Icon must end with two \r Icon # Thumbnails ._* # Files that might appear on external disk .Spotlight-V100 .Trashes # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk ### Windows ### # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ # Windows Installer files *.cab *.msi *.msm *.msp # Windows shortcuts *.lnk ### Linux ### *~ # KDE directory preferences .directory |
Eğer kendiniz başka sistemler için de gitignore dosyası oluşturmayı planlıyorsanız https://www.gitignore.io adresini tavsiye ederim.
Arzu ederseniz projenin son halinin kaynak kodlarına Git adresi üzerinden erişebilirsiniz.
End Of line