środa, 24 września 2014

QueryDSL metamodel generation + Spring Data

Założenie : queryDSL + Gradle + Spring Data
Oczekiwanie : wygenerowanie metaModelu do zapytań DSL
Definiowanie kwerend w czystym Stringu  jest dobre i sprawdza się często, ale takie podejście to jest podatne na błędy (error-prone).
Błędy te pojawią się nie w fazie kompilacji jak byśmy tego chcieli, ale w fazie runtime co często sprowadza się do ujawnienia błędu gdy już nasza aplikacja trafi na serwer.
Często refaktoring SQL jest bardzo trudny i samo utrzymanie takiego kodu to spore wyzwanie.(zarówno w kodzie javy wstawki SQL czy JPQL)

Ale jest na to sposób to: automatyczne generatory metadanych.
Wygląda to tak, że generator podczas fazy kompilacji generuje za nas encje jako mapowane tabele istniejące w bazie. Wtedy rozwiązuje nam się problem 'rozjazdu SQL i kodu javy'.

QueryDSL to narzędzie do obsługi zapytań SQL, które dostarcza nam generatory kodu, fluent API i współpracę z wieloma bazami również bazami NoSQL. Zapytania w QueryDSL są bardziej user-friendly i bezpieczne typologicznie.
Co jest jeszcze ważne QueryDSL integruje się Spring Data i z takiego połączenia wynikają tylko same korzyści.

Zalety :
  - dynamiczne zapytania
  - czyste i czytelne API
  - składnia weryfikowana w czasie kompilacji
  - wydaje się bardziej czytelne niż użycie Criteria API 
  - mniej  podatny na błędy niż SQL
  - synktatycznie zbliżony do SQL
  - wspiera wiele języków zapytań jak : JPA/Hibernate, MongoDB, SQL, Lucene

Wady :
  -  wymaga generacji meta-modelu 


QueryDSL vs Criteria API
- łatwiejsze tworzenie zapytań
- prostsze tworzenie dynamicznych kwerend
- less verbose

Tak na marginesie : Spring Data umożliwia tworzenie kwerend przy pomocy odpowiednio spreparowanej metody w interfejsie (method name strategy).

Ma to wiele zalet jak :
  - szybka dla prostych zapytań
  - spójna strategia nazewnictwa umożliwia łatwe rozumienie

oraz  wad :
  - totalnie nieczytelne dla bardziej skomplikowanych zapytań
  - weryfikacja poprawności w runtime
  - nie możemy tworzyć dynamicznych tworów.

Strategia Named queries oparta na mechanizmie @NamedQuery i @NamedQueries znanym z JPA czy Hibernate.
Nazwa metody pokrywa się z nazwą @NamedQuery. Oczywiście mamy możliwość parametryzacji.

Zalety tego podejścia to :
 - wsparcie dla JPQL jak i SQL
 - możemy skorzystać z istniejących już zapytań

Wady:
 - walidacja w runtime
 - nie wspiera dynamicznych rozwiązań

Strategia @Query annotation - dekorujemy metody adnotacją @Query i w niej za pomocą JPQL czy SQL definiujemy interesującą nas kwerendę.

Zalety tego podejścia to :
 - wsparcie dla JPQL jak i SQL
 - jasne i czytelne definiowane zapytania i update'y
  - walidacja w czasie inicjowania kontekstu

Wady:
 - nie wspiera dynamicznych rozwiązań

Spring Data wspiera Criteria API za pomocą JpaSpecificationExecutor<T>.
Kluczowy jest tu interfejs :
  
Jeśli stosujesz Criteria użyć statycznego modelu wygenerowanego przez jeden z opisanych w poście generatorów. Zapewnisz sobie bezpieczną typizację kwerend.
Konfiguracja jest możliwa zarówno przez XML jak i JavaConfig :
@EnableJpaRespositories

Tip : Customize your own repositories -> @NoRepositoryBean
Tip : DomainClassConverter ->  (@PathVariable("id") Book book)
Tip : HandlerMethodArgumentResolver -> Pageable i Sort bezpośrednio wbudowany w metodę kontrolera (z requestu)


Przykład zastosowania tips'ów w jakimś moim kodzie :
Zalety :
 - dynamiczne tworzenie kwerend
 - składnia weryfikowana w czasie kompilacji

Wady:
 - skomplikowane zapytania mogą być nieczytelne


 Querydsl core - główna funkcjonalność do silnika QueryDSL
 Querydsl APT - dostarcza wsparcie dla APT generatora kodu
 Querydsl JPA - wsparcie dla adnotacji JPA

QuerydslAnnotationProcessor - generuje kod dla klas oznaczonych adnotacją :  @QueryEntity czy @QueryEmbeddable

JPAAnnotationProcessor - dla klas oznaczonych @Entity czy @Embeddable

HibernateAnnotationProcessor - to samo jak dla JPAAnnotatationProcessor tylko z uzwględnieniem standardu Hibernate
 

JDOAnnotationProcessor - wsparcie dla adnotacji JDO

MongoAnnotationProcessor - dla adnotacji @Document

QueryDslPredicateExecutor - stanowi wsparcie dla predykatów QuerySQL



Konsola: -> metaModel generuje : gradle generateQueryDSL


Mój gradle.build wygląda tak:
Prosty model domenowy :

Wygenerowany meta-model:
Podpięcie z Spring Data :
Testujemy :
Kod to posta jest tutaj:)
Porównanie z podejściem jpa metaModel jest tutaj.
Widać bardzo dobrze jak bardziej przyjazdne dla programisty jest podejście QueryDSL zamiast Criteria API.
Przykład podejścia Criteria API +JPA metaModel jest w poście ->

Gradle + JPA meta-model + Spring Data

Zadanie : wygenerować meta-model JPA dla objektów domenowych


Zastosowanie : Criteria API , Spring Data -> JpaSpecificationExecutor

Zysk : Utrzymywalny, dobrze refaktoryzujący się oraz pozbawiony zbędnego do minimu kodu projekt. Bezpiecznym kwerendy pod każdym względem : SQL Injection jak i typologicznie.
 



gradle.build wygląda jak poniżej : generowanie metaModelu odpalam przy pomocy stworzonego taska : gradle generateMetaModel

Prosty model domenowy :

Wygenerowany meta-model:
A tak w eclipsie :






















 



Tworzymy prostą przykładową implementację Specification (tak napradę dwie przykładowe : Specification getUserByLogin(final String str) oraz Specification getUsersWhoEarMoreThan(final BigDecimal salary))

Testuje:

Tyle .... :) 

Polecam gorąco książki :
Spring Data by Petri Kainulainen
oraz Spring Data by Mark Pollack, Oliver Gierke, Thomas Risberg and Jon Brisbin

ja od nich zaczynałem naukę Spring Data  
W nich znajdziecie skrypty pozwalające na to samo ale z pomocą mavena.
Kod to posta tutaj ->
Bliźniaczne rozwiązanie z zastosowanie QueryDSL tutaj ->

środa, 17 września 2014

Spring Profiles

Kiedyś definiowałem ustawienia projektu z poziomu mavena. Wydawało się mi to oczywiste i działało tak jak się tego spodziewałem. Zresztą profile to bardzo fajny feature mavena.
Z wejściem bodajże Springa3 podobny mechanizm mamy dostępny już w kodzie javowym jak i w plikach xml.
Jest to bardzo wygodne bo można dodawać do kontekstu poszczególne bean'y co w przypadku mavena sprowadzało się jedynie do podmiany konfiguracji czy ustawień konfiguracyjnych.
Z nadejściem Springa 4 dostaliśmy coś co zwiększa jeszcze elastyczność oraz moc  @Profile czyli @Coditional

@Conditional pozwala na tworzenie bardziej dynamicznych mechanizmów niż tylko statyczne @Profile . Dzięki niemu możemy reagować na szerszy kontekst np beans, enviroment properties, szczególne klasy w classpath itd.

To on dał takiego kopa projektowi Spring Boot.


Jak to wyglądało w XMl ?
Kilka lat temu akurat jak wchodził mechanizm profili przeprowadzałem szkolenie ze Springa. Chodziło mi o to aby zaprezentować różnice w podejściu do persystencji :
 - hibernate
 - jpa
 - jdbc = spring jdbc template
 - Spring Data

Uczestnicy szkolenia pomimo, iż  obejmowało ono temat Spring-Hibernate szybko chcieli zmiany na Spring Data zamiast postawowego tematu jakim miał być Hibernate. Spowodowane to było magią Spring Data, ilością potrzebnego kodu jak oraz gotową funkcjonalnością (CRUD) jaką out-of-the-box oferuje Spring Data.

Jak ma się do profili ? -> aplikacja pozostała spójna.

Jedyna zmiana w konfiguracji znajdowała się w pliku spring_data.xml. Zmieniająć profil z poziomu danych testów, wczytywał się odpowiedni kontekst oraz wraz z nim odpowiednie bean'y.

Tip: Z poziomu testów ustawiaj profil przez :
@ActiveProfiles(value = {$profile_name})

Możesz też tworzyć swoje własne profile :

@PropertySource służy do wprowadzenia zmiennych do mechanizmu Spring Enviroment (<context:property-placeholder>)
Obowiązująca tutaj kolejność ładowania properties to : 
  - System properties for the running JVM
  - Environment variables
  - Zmienne zdefiniowane w aplikacji *.properies

tutaj również działa super mechanizm placeholdera:
@PropertySource("classpath:${my.placeholder:/etc/conf/}/server.properties"
W przypadku xml wygląda to tak :

Uwaga zastosowanie połączenia @PropertySource i @Value wymaga użycia : propertySourcesPlaceholderConfigurer


Ustawienie profili wiąże się z zarejestrowaniem tego w ramach kontekstu Springa. A ustawić profil można również tak jak poniżej w przykładzie, i tak naprawdę każde działanie jawnie czy niejawnie się do tego sprowadzi.

W przypadku Spring Boot'a
profile aktywuje poprzez :

application.properties:
 spring.profiles.active={profile_name}
np :
 spring.profiles.active=dev,cache

to samo moge odpalić z linii poleceń :

 --spring.profiles.active=dev,cache


jeśli korzystam z yaml sprawa wygląda identycznie

należy jednak pamięć o dodaniu zależności

Zaleźności możemy zmieniać wygodnie i dynamicznie przez linię poleceń i tak zapis w pliku properties :

Skutkuje wystartowaniem serwera na porcie 8091.
W przypadku dodania argumentu jak --server.port=9002 serwer wystartuje na porcie 9002.
 I|Http11NioProtocol |Starting ProtocolHandler ["http-nio-9002"]
Jest to wygodny feature szczególnie podczas fazy developmentu.


Spring Boot określa także porządek ustawiania properties :
  1. Linia komend
  2. Java system properties (System.getProperties)
  3. Properties z OS
  4. JNDI -> java:comp/env
  5. RandomValuePropertySource

  6. Properties z poza jara gdzieś na path : application.proprties
  7. Properties wewnątrz jara -> application.properties
  8. @PropertySource w klasie oznaczonej @Configuration
  9. Domyślne ustawienia -> SpringApplication.setDefaultProperties

Można tworzyć ustawienia względem danego profilu:

application-{profile}.properties

Analogicznie konfigurację multi-profilową możemy stworzyć korzystając z Yaml w następujący sposób jak w przykładzie z dokumentacji:
Fajna jest możliwość zwiększania poprawności typów w przypadku ładowania properties i też taką możliwość oferuje nam Spring : (przykład z dokumentacji Spring Boota)

zastosowanie mechanizmu w jakimś moim kodzie :

@ConfigurationProperties

Objaśnienia :
@ConfigurationProperties - określamy jaką część pliku/sekcje nasza klasa ma reprezentować

@EnableConfigurationProperties - mówi Springowi, że dana klasa ma być traktowana jako konsumer wiadomość

@EnableConfigurationProperties  <-  kolaboruje z -> @ConfigurationProperties
czyli obie klasy żyją w symbiozie.

Tip : W Spring Boot może być mylące lub wydawać się niejasne jak przekonfigurowywać np ds, jms, health indicator czy inne tego typu historie.
Ja robię to tak :
Kluczem jest element @ConfigurationProperties - dlatego bo określa kawałek mojego pliku z properties z którego to kawałka Spring ładuje sobie interesującego go parę (klucz-wartość).

Czyli na @ConfigurationProperties naciskam combo (Shift+Ctrl+G) i ujawniają mi się wszystkie pliki z konfiguracji, które są w ogóle w ten sposób konfigurowalne.
Ok przykład: Jest to bardzo ważne, bez tej wiedzy można się trochę bujać ...;)

Następny przykład użycia:
@Profile -> @Bean
Generalnie jak widać to w kodzie wyżej  profil w javie ustawia się przez dodanie adnotacji @Profile.

Tip: Jest możliwość również wykluczania danego profilu: @Profile({"dev","!cache"})


To tyle na dzisiaj.... ) Generalnie elastyczność jest ogromna. Prostota użycia również. Według mnie ewolucja i rozwój Springa sprzyja coraz to łatwiejszemu pisaniu aplikacji. @Profile ułatwiają konfigurację, utrzymanie i rozwój.
@Conditional dostarcza super fajną elastyczność i otwiera możliwości w Spring Boot.
Yaml jest bardziej zwięzły, ludzki i Json podobny niż można czy sądzić.
Użycie Yaml w Springu sprowadza się do w sumie do dodania odpowiedniej zależności - procesora.

wtorek, 16 września 2014

REST API part 2

Inspiracją do napisania tego posta był projekt mojego kolegi z pracy, który użył swaggera do projektu Play'a jako obsługa REST API (konsumowanie i produkowanie).
Mi wydawało się, że korzystając kiedyś z Typesafe Activator już wcześniej widziałem w którejś aplikacji typu demo takie połączenie.
Ok. Wyzwanie na dziś : Integracja Swagger + Spring Boot. 
W poprzednim poście pokazałem jak projektować i czym się kierować podczas tworzenia serwisów REST'owych. (czyli dobre praktyki)
Swagger jest to framework, którego zadaniem jest wizualizacja, konsumowanie i produkowanie wiadomości w formacie JSON jak i XML.
Dzięki niemu nie musimy zaglądać do dokumentacji czy kodu źródłowego, wszystko mamy podane jak na talerzu w możliwie wygodniej i czytelnej dla użytkownika postaci.
Swagger Spring MVC używa @Annotation do budowy dokumentacji serwisów.

Krok 1:Konfiguracja gradle:
Krok 2:
Konfiguracja springa:

Pamiętaj o stworzeniu profilu : tak naprawdę swagger sprawdzi się fazie developmentu. (@Profile("dev"))

Krok 3: Opisujemy usługę :  przykładowa konfiguracja w kontrolerach
Opcjonalnie możemy opisać klasy domenowe lub zwykłe DTO:
Na konsoli widzę coś takiego : -> czyli sukces :)
Wygenerowane info -> czyli opis usług wystawionych przez aplikację (info definiujemy w SwaggerConfig.java - patrz wyżej):
Przy uderzenia na główny URL z przeglądarki odpala się index.html. Plik ten pochodzi z webjara  org.ajar:swagger-spring-mvc-ui:0.2, którego definiowaliśmy w gradle.

TIP : używaj zawsze webjar'ów są kompaktowe i projekt de facto będzie zawierał mniej plików. Webjary podpinasz za pomocą static-resource ze Springa.
W przypadku javaConfig - korzystając z obiektu ResourceHandlerRegistry registry



lub za pomocą xml :

Krok 4: Odpalamy i wklejamy link api-docs do swagger (można zedytować index.html i wstawić tam odpowiedniego dla nas linka zamiast cały czas wklejać odpowiedni..)























Ukazuje nam się nasze API: )

Listujemy , lub pobieramy


























Mniej więcej tak to wygląda....
Dokładny opis integracji znajdziecie u źródła czyli tutaj.
Integracja i customize'zacja dla swagger UI opisana jest tutaj.

W następnych postach pokaże inne narzędzia i sposoby do szybkiego korzystania z REST API w naszych aplikacjach. Swagger nie jest jedynym narzędziem do tego aby sprawnie używać serwisy restowe. Ale o tym potem...


środa, 10 września 2014

Use Selenium for easier UAT testing

Selenium w służbie UAT....
8 lat temu, gdy zaczynałem pisać aplikacje webowe oparte na GWT, ktoś z mojego zespołu wprowadził narzędzie do testowania o nazwie Selenium.
Wydawało się być super i sprawdziło się wtedy, ale pojawiły się też inne problemy związane z testowaniem z tym narzędziu jak :
 - powtarzalność
 - utrzymywalność
 - ajax
 - wytwarzanie testów.

Genaralnie idea była bardzo dobra. Każdy kto pisał frontend miał za zadanie testować swój kawałek funkcjonalności. Istniały profile w mavenie i ja odpalałem tylko testy, które mnie dotyczyły. Dodatkowo  jest to fajnie zorganizowane w mavenie bo możemy się wstrzelić w daną fazę bez większych problemów.
Było to coś na kształt kodu poniżej : 

Zaczynamy ......czyli z krótki wstęp... Trochę o testach już pisałem tutaj


Testy funkcjonalne – są to testy mające zagwarantować, iż cała praca analityków, biznesu oraz programistów nie poszła na darmo. Zazwyczaj testy takie są przeprowadzane przez testerów. Jednak rozwój w dziedzinie IT spowodował automatyzację wielu procesów czy zadań.
Dziś standardem oraz dobrą praktyką jest pisanie różnego rodzaju testów w każdej chwili wytwarzania oprogramowania.
Tak samo wygląda sprawa z testami funkcjonalnymi (znane także jako testy UAT). Tego typu testy zaliczamy do kategorii black box, ponieważ nie interesuje nas kod a tylko wynik działania jakiejś funkcjonalności.
Punktem wyjścia do tego typu testów jest przygotowanie zbioru danych wejściowych oraz wyjściowych.
Dane wejściowe są wprowadzane do systemu, a odpowiadający im dane wyjściowe są porównywane do tych które zwróci nam aplikacja.
Testy funkcjonale warto umieścić na maszynie Continuum Integration co pozwoli nam na periodyczne lub na żądanie odpalanie takich testów. Dzięki czemu uzyskamy regresję oraz możliwość sprawdzenia czy developerzy nie uszkodzili starej funkcjonalności dodając lub poprawiając nową.

Testy funkcjonalne testują nam wszystkie warstwy aplikacji od warstwy danych do warstwy prezentacji oraz ich integrację ze sobą. (nie myl z testami integracyjnymi....)
Ponadto stanowią idealną dokumentację projektu. Mając stworzone takie testy możemy łatwo zrozumieć funkcjonalność, oraz intencje autora systemy czy danej funkcjonalności. Wspomagają również procesy refaktoryzacji.

Tip : Testy i kod są najlepszą dokumentacją projektu

Za pomocą tego rodzaju testu możemy zweryfikować :
- błędy w kodzie źródłowym
- brak implementacji wymagań biznesowych
- niepoprawna implementacja wymagań

Selenium pozwala nam wykonać testy typu : UAT czy e2e(end-to-end) oraz ich automatyzację.


Selenium jest tak naprawdę typem frameworka do testowania aplikacji webowych.
Współpracuje z przeglądarkami jak : IE, Firefox,Google Chrome czy Safari.
Należy pamiętać iż nie wspiera rozwiązań typu Silverlight, Flex/Flash czy JavaFx.
Framework ten składa się z narzędzi jak :
- Selenium IDE – plugin do Firefoxa dzięki któremu użytkownik może nagrać interesujący go przypadek testowy
(działanie JS + DOM)

- Selenium WebDriver – odpala nagrany test na różnego typu przeglądarkach (proxy pomiędzy kodem testowym a dowolną przeglądarką). Dostarcza nam API do iteracji z przeglądarką oraz sterownik umożliwiający tego typu połącznie.

(wpiera również wiele języków od javy zaczynając po PHP czy Ruby)
- Selenium Standalone Server – pozwala na zdalne wywoływanie skryptów Selenium.

Upraszczając do minimum Selenium ma za zadanie udawać akcje zwyczajnego użytkownika, poprzez kliknięcia na linki, przyciski, wybierając opcje z combo czy testować obecność tekstu czy kontrolki na formularzu.
Możemy też robić screenshot'y co czasem może być przydatne.




źródło : http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=selenium_rc


Rozwiązanie  1.

1. Pierwszy krok to nagranie testu za pomocą narzędzia Selenium IDE. 
Ze strony producenta http://seleniumhq.org należy ściągną i zainstalować plugin do Firefoxa.

Po zainstalowaniu wygląda to tak :


Kliknięcie na 'czerwony przycisk' powoduje zaczęcie nagrywania scenariusza testowego. Mamy do dyspozycji także asercje, które działają identycznie jak przypadku unit testów czyli weryfikują daną wartość zgodnie z naszymi oczekiwaniami.
(Asercja – sprawdzenie czy element znajduję się na stronie)
Nagrany test możemy wyeksportować do danego języka programowania w postaci unit testu.
Taki test powinien być wywoływany w ramach testów integracyjnych na maszynach Contiuum Integration.
Możemy też testy pogrupować w logiczne części i wtedy otrzymamy odpowiednik 'suite testu' z testów jednostkowych.

Nagrany test wygląda jak poniżej :































 
Następny krok to eksport do danego języka programowania w naszym przypadku javy.































 
Zatrzymajmy się chwilę ....
 
- dostajemy narzędzie do nagrywania testów i ich odtwarzania

- współpracuje one z wieloma przeglądarkami

- mamy możliwość asercji oraz lokacji pól, treści czy id kontrolek na stronie (findElement() and findElements())

to daje duże możliwość :

- sprawdzenie czy dana klasa czy id w css istnieje

- wsparcie dla aplikacji używających ajax

- ładowanie strony bądź jej kawałka (waitForPageToLoad, waitForFrameToLoad)

- pop up (waitForElementPresent)

- progress bar (waitForElementPresent)

- statusy wiadomości (waitForTextPresent waitForAlertPresent)

- dostępność przycisków np. button'a (waitForElementPresent)

Możemy wskazać lub znaleźć (lokacja) element dzięki po :
   - id

   - nazwie

   - linku

   - Xpath

   - CSS

Tutaj pomocy może się okazać program typu FireBug. Dzięki któremu szybko i bezboleśnie można znaleźć interesujące nas informację na temat kontrolek czy widgetów na danej stronie.

Zalety :

   - Łatwy sposób wygenerowania testów typu UAT

Wady :

   - rozwiązanie to nadaje się jedynie do prostych przypadków. Nie obsługujemy odpowiednio transakcji po stronie bazy więc po każdym teście istnieje możliwość pojawienia się duplikacji czy ujawnienia ograniczeń na bazie.

   - nieutrzymywalność oraz powtarzalność

- często nieobliczalne w stosunku do rozwiązań ajax (callback time problem)

Rozwiązanie 2.
 
(Selenium DSL)
Rezygnujemy całkowicie z narzędzia Selenium IDE. Nie nagrywamy testów z poziomu przeglądarki.

Test piszemy tylko w javie symulując w prostej linii co ma na myśli użytkownik. 
Projektujemy generyczne rozwiązanie zawierające obsługę formularza, akcje, stawianie asercji.
Oraz składnice danych testowych i transakcyjny mechanizm wycofujące dane po każdym teście. 

Zaleta :

   - skomplikowane systemy testów

    - baza danych pozostaje spójna cały czas, transakcje po teście są wycofywane
    - utrzymywalność
    - powtarzalność

Wada:

   - wymaga dużej wiedzy na temat testowania i doświadczenia programistycznego.

   - relatywnie duży koszt wytworzenia


Wniosek :
Nie traktuj Selenium jako silver bullet. Dobre utrzymywalne i powtarzalne testy będą kosztowamy zawsze sporego przynajmniej na wstęp nakładu pracy.
Ale rozwiązania generyczne i modułowe zawszę przynoszę zyski w długofalowej perspektywie.  

piątek, 5 września 2014

Create your own content repository (Content Management Systems based on Spring Boot + GridFS)

Ok. Posty powinny być krótkie więc... dziś krótko i do rzeczy.
Jakiś czas temu publikowałem materiały na temat baz Nosql. Potem przeszedłem do bazy Neo4j. Ten post powstał dopiero w pierwszej części i niedługo dokończę publikacje :)


Teraz padło na MongoDB.


Wyzwanie jest następujące : przetrzymywać treści nie ważne czy to rysunki, dokumenty pdf czy inne tworzy binarne. Wielkość tych pakunków ma być rozsądna do kliku MB.





1. Research -> Google 
  - blob +standardowe bazy relacyjne - słabe podejście(wydajność,skalowalność)
  - system plikowy + rsync - już dużo lepiej wymaga zaimplementowania jakiegoś serwera plików czy treści
  - jackrabbit - trudniej integruje się ze Springiem, najbardziej rozbudowane i zaawansowane ze wszystkich tutaj wymienionych
  - GridFS  - Łatwa integracja ze Spring oraz Spring Boot. Idealne na skalowane repo dokumentów. Posiada też proste API. Wydaje się być optymalne do moich potrzeb.Pozostałe potrzebne dane oraz dokumenty około elementów dziedziny możemy trzymać w bazie MongoDB.

GridFS to dwie kolekcje :
  - chunks - zawiera binarne kawałki danych. (zwykle rozćwiartowane na kawałki po 256KB)
  - files - zawiera meta dane do powyższych binariów (zawiera informacje o nazwie pliku, wielkości, sumie kontrolnej, ekstra informacje dostarczone przez użytkownika,)
Dostęp do nich otrzymyjemy odpowiednio przez :
  - fs.files
  - fs.chunks

Dokładny opis pól z namespace fs znajdziesz tutaj.

TIP : fs - to default namespace, zawsze możemy stworzyć nowe np żeby przechowywać inny typ plików.

TIP : GridFS najlepiej sprawdza się w przypadku większych plików, przechowywanie małych może powodować problemy wydajnościowe.

Dane zapisywane są w postaci BSON o limicie 16MB. Jeśli chcesz włożyć większy kawałek danych musisz go podzielić na kilka dokumentów.
Pliki są replikowane pomiędzy instancjami mongoDB. Usunięcie lub włożenie danych binarnych z jednej powoduje propagacje działania na inne bazy.  

 2. Założenia
Chce aby aplikacja była przenośna i mogła działać w chmurze. Sprawdzam MongoDB na Heroku, więc jest ok.
Pragnę stworzyć aplikacje w duchu microservices, wybór jak Spring Boot jest jak najbardziej odpowiedni.

W części następnej chce wystawić REST + WS-* API. Muszę zaimplementować też security. Zależy mi na tym aby aplikacja działała podobnie jak w chmurach. Pobieranie i udostępnianie zasobów -> Token -> w prostej linii kieruje mnie to w stronę Auth2.

Projekt ma być szybki i pokazać, że szybko można też coś sensownego zrobić.
Publikuje na razie wersję bez REST API.


TIP : w stosunku do Spring Security opłaci się stosować podejście hybrydowe. Co to oznacza ? Tyle , że całość implementuje w Java Config a konfigurację security ze względu na czytelność lepiej wydaje się pozostawić w plikach XML.
Wygląda to tak jak poniżej.


Konfiguracja MongoDB + Spring Boot

Konfiguracje mongoDB repo - tak na wszelki wypadek np na metaDane
Konfiguracja ustawień - yaml

Wstępne API
Implementacje API
Testujemy API


Z perspektywy mongoDB:
Szukanie pliku:
mongo klient szukanie pliku :
Możemy użyć poleceń konsoli przez program : mongofiles
 - mongofiles put 2.png - włóż do GridFS
 - mongofiles list - listuj
 - mongofiles delete 2.png - usuwanie pliku
 - mongofiles get 2.png - pobranie z bazy na dysk
 - mongofiles search 2.png - szukaj plików

szukanie :
usuwanie :












To co się dzieje w bazie podczas użycia programowego dostępu do danych.

































Kod do posta jest tutaj.

Krótkie podsumowanie : mamy bazę do tworzenia rozmaitych rozwiązań. Nie jest to pełen CMS a jego zalążek czyli tylko składowanie binariów ich meta-danych. Do wielu zastosowań to wystarczy.