0maczel / pz

Projekt realizowany w ramach zajęć "Programowanie Zespołowe" na WFiIS w semestrze letnim 2015/2016.
0 stars 0 forks source link

Zaprojektowanie i implementacja infrastruktury hosta WebService. #12

Closed dawidkomorowski closed 8 years ago

dawidkomorowski commented 8 years ago

Przygotowanie konsolowej aplikacji stanowiącej backend będący kontenerem serwisów (najprawdopodobniej) platformy JAX-RS. Warto się zastanowić nad przygotowaniem odpowiedniego bootstrapera sterowanego konfiguracją np. z pliku xml. Kontener IoC lub podobne rozwiązanie również było by przydatne do szybkiego dodawania nowych serwisów pokrywających kolejne funkcjonalności.

W tym tasku warto zrobić jeden serwis stanowiący proof of concept, oraz pokazujący jak wykorzystywać dostarczaną infrastrukturę.

Izzy4me commented 8 years ago

Mapowanie restów na wykonywanie konkretnej akcji (jax-rs) podpada tutaj, czy w implementacji infrastruktury dostępu do danych)?

dawidkomorowski commented 8 years ago

@Izzy4me Z pewnością bardziej tutaj, aczkolwiek to zadanie raczej tego nie obejmuje. Tutaj chodzi o przygotowanie infrastruktury, pod te serwisy, tak aby można było następnie właśnie łatwo dokładać kolejne klasy serwisowe z nadanym im mapowaniem restowych endpointów, a reszta stanie się sama.

Nie wiem czy odpowiedziałem na pytanie?

Izzy4me commented 8 years ago

Tak, myślę, że odpowiedziałeś. Jak coś to ja mam wolną niedzielę wieczorem i cały wtorek, więc mógłbym ogarnąć mapowanie restów i odpowiedzi na konkretne zapytania, jakby ktoś do tego czasu powiedział mi jaka warstwa abstrakcji (szkielet funkcji byłby bardzo przydatny) będzie odpowiadać za wyciąganie danych z modelu (czyste DAO, Hibernate, coś innego). Co do kontenerów niestety nic nie ogarniam, więc z tą koncepcją byłoby ciężko.

dawidkomorowski commented 8 years ago

@invader92 Jak sądzisz, czy dobrym pomysłem byłoby pójście w stronę Springa (jako że dostarcza kontener IoC out of the box) i wykorzystanie modułu org.springframework.boot?

Nie wiem czy dobrze go rozumiem, ale wydaje się on pozwalać na samodzielne hostowanie usług w procesie bez potrzeby serwera aplikacyjnego? Jeżeli tak to rozwiązanie wydaje się idealne ze względu na prostotę i wygodę jaką zapewnia, a co rzutuje na znacznie skrócony czas potrzebny na budowę infrstruktury.

ljedlinski commented 8 years ago

Pójście w stronę springa w tym przypadku uważam za najrozsądniejsze. Spring boot posiada zembeddowany serwer i praktycznie zerową konfigurację. Za chwilkę wrzucę bardzo prostą, prototypową aplikację, która pozwala się niestety tylko uruchomić i pobrać z bazy obiekt o zahardkowanym ID, ale podejrzewam, że jej konstrukcja wystarczy i będzie stanowić prostą bazę do faktycznej implementacji monitora.

Update: Zmiany są w moim branchu

Generalnie, utworzyłem maven parent projekt i dwa pod projekty. Póki co nie wpinałem istniejącego tam projektu. Niestety, dzisiaj nie mam już za bardzo czasu się tym zająć, ale tak na pierwszy rzut oka, to osobiście rozbiłbym dziedziczenie encji. Raz, że wydaje mi się, że wnosi sporo danych, które nie są potrzebne (np. wersje/daty, chyba ze coś mi umknęło), a dwa, współdzielą całą pulę IDków. Wydaje mi się, że można to trochę zrefaktorować.

Poproszę o odpowiedź.

dawidkomorowski commented 8 years ago

@invader92 Przejrzałem artefakty twojej pracy, niestety jeszcze nie uruchomiłem jak na ten moment (kwestia konfiguracji bazy - mogłeś zrobić serwis bez bazy to by się uruchomiło :) ). Nie wiem jak to jeszcze ustrukturyzować - pierwotnie zakładałem zrobić wszystko w jednym projekcie i jedynie podzielić pakietami, ale jak już naspawniłeś projekty to teraz myślę jak to w tym kierunku popchnąć.

Widziałem, że zastosowałeś Springowe wsparcie dla baz danych, czego pierwotnie nie zakładałem bo nie wiedziałem w jaki Framework dokładnie pójdziemy, ale chyba ten fragment wyrzucę (tzn. przerobię pod to co już powstało z mojej ręki, nawet jeśli to nie jest dobry pomysł, to po co już napisany kod ma się marnować :P ).

Co do zarzutów o mapowanie i strukturę encji:

  1. Sporo danych jest względne - myślę ze gabaryty tej aplikacji nie dadzą odczuć żadnych negatywnych skutków, ale jeżeli myślisz, że tak czy siak warto coś wyrzucić, to można klasę Entity rozbić na 2 klasy np. Entity (id oraz entityVersion) i AuditableEntity (oba timestampy) i klasy modelu, które nie potrzebują "datowania" mogą mieć płytszą hierarchię wtedy.
  2. Fakt, wspólne ID dla wszystkich klas może nie być optymalne - szczególnie ze względu na obecność typu jak Measurement, którego instancje obecne będą pewnie w sporych ilość w kontraście do pozostałych. Ale solucja na to rozsądna to IMO @MappedSuperclass (mapuje pola klasy w jej subklasie), wtedy ID wszystkie typy będą miały rozłączne, a w modelu obiektowym wciąż zachowujemy rozsądne DDD.

Generalnie, jeżeli chcesz nie pozwolić na zmasakrowanie twojej pracy, to odpisz coś zanim zrobię jakiegoś commita narzucającego moją wizję :P

Update: W oparciu o to co zrobiłeś, w pierwszym wydaniu rozszerzę ten pierwotny projekt jako Proof Of Concept (dziś wieczorem zcommituje) i zamkne to issue, a później się zastanowimy (to już na osobne issue) nad strukturą w którą będziemy celować oraz wszelkimi zmianami, usprawnieniami aplikacji tudzież samego kodu. Chciałbym dostarczyć możliwe szybko pierwszy deployment dla innych zespołów dlatego jakieś prototypowe serwisy(endpointy) na żywej bazie z praktycznie zerową konfiguracją oraz jednym "jarem" do kliknięcia to jest obecny cel ;)

Izzy4me commented 8 years ago

Panowie, panowie to na czym my stoimy? Chciałem coś pokodzić, widzę interfejs wystawiony przez Dawida a teraz springową rewolucję (ba, dyskutujecie nad zmianą modelu)... Prosiłbym o uzgodnienie :)

btw: Id rzeczywiście można by wyrzucić z dziedziczenia by były unique per table (byłoby to ładniejsze przy prezentacji RESt'a), ale co do timestampów to bym się aż tak nie rozdrabniał... Measurement i Sensor powinny go mieć, a co do innych tabel to może się przydać zamiast logowania. Można też usunąć. Nie jest to zbyt istotne w skali tego projektu.

ljedlinski commented 8 years ago

Tę konfigurację, którą ja zostawiłem na psqlu można zostawić (w sensie formę) i tylko zastąpić jakąś zembeddowaną bazą (hsql, sqlite, cokolwiek). To springowe coś, co wyplułem pozwala na wystawienie siebie w postaci pojedynczego jara.

Sprignowa rewolucja generalnie zawiera wszystko co potrzebne praktycznie zerowym kosztem, aby (taki mi się zdaje) implementować logikę monitora. Jest kontekst bazy danych, jest wypluwanie danych via rest (fakt - nie sprawdzałem w drugą stronę, ale podejrzewam, że już działa OutOfBox), jest kontekst wstrzykiwania zależności dla łatwiejszego developementu.

Spawn projektów był czysto odruchowy, chciałem sprawdzić ile mi się uda uruchomić w ciągu kilkunastu-dziesięciu minut i mieć gotowy dostęp do danych. Springowe wsparcie to głównie wszytkiwanie zależności i trasakcje robiona aopami, bez manualnego otweirania/zamykania/rollbackowania.

Edit: Nawiasem mówiąc trochę mi się wydaje przekombinowane Repository w tym projekcie. Nie bardzo widzę w jaki sposób nam to upraszcza sprawę, zwłaszcza, w stosowaniu tego (spora lista lamb/ anonimowych implementacji, które mogą robić cokolwiek). (W skrócie - nie widzę sensu, aby przejmować się wprowadzaniem abstrakcji wszystkiego co się da w tak małym i tak niczego nie wartym projekcie, który w dniu oddania idzie do kosza).

Izzy4me commented 8 years ago

Właśnie wypadałoby rozwiązać kwestię bazy, czy SQLite bo mały i ctr+C ctrl+P, czy PostgreSQL, bo szybszy :P

Ah i w końcu w tym przypadku wystawiana osobnego jara i użyciu springa, ma to być jednak nie zrobione w JAX-RS, tylko w tych springowych adnotacjach https://spring.io/guides/tutorials/bookmarks/ ? Czy to nie ma różnicy? (pytam, bo nigdy nie pisałem w springu poza zabawą na jakiś laborkach)

ljedlinski commented 8 years ago

Domyślnie będzie coś a'la SQLice (embeddable), żeby pozbyć się zewnętrznych zależności poza JVM. Jar - będzie tylko jeden, z całą aplikacją (rest api + db + konfiguracja).

Annotacje - jeżeli korzystalibyśmy z tego co wrzuciłem, to już te dostarczone przez springa przy mapowaniu wywołań u pamaterów metod rest-serwisowego api, natomiast dla mapowania klas na JSONa annotacje z Jacksona (com.fasterxml.jackson.annotation.*).

dawidkomorowski commented 8 years ago

Co do bazy, to ja testowałem w tej części bazodanowej HSQL i myślę że można się skierować ku niemu.

Update: Jednak dzisiaj nie zamknę tego issue bo nie wiem do końca jak się zabrać za sensowne zlepienie obecnie tego wszystkiego co tam jest, a nie widzi mi się teraz walka z paskudnym springowym xml-em.

Do tematu wróci się jutro (miło by było móc nawiązać jakąkolwiek komunikacje w czasie rzeczywistym - to by oszczędziło mnóstwo czasu).

ljedlinski commented 8 years ago

Xmla już nie trzeba ruszać. Konfiguracja bazy jest w pliku monitor.properties. Podejrzewam, że aby zamienić Postrgrsa na HSQL wystarczy w tym pliku zmienić dialekt, nazwę klasy terwonika i url, tak by wskazywał na plik. No i dokleić hsqla do zależności w pom.xml.

dawidkomorowski commented 8 years ago

Kilka pytań:

  1. Czy plik .properties jest deployowany obok jara, tak ze za każdym razem jest odczytywany i można za jego pomocą dalej konfigurować aplikacje? To jest istotne dla innych zespołów i do procesu instalacji u klienta (co jest tematem KM3). Jeśli nie, to trzeba taką funkcjonalność dostarczyć.
  2. Dalej, jeśli odpowiedź na poprzednie pytanie brzmi tak, to driver JDBC nie powinien być tam konfigurowalny - i tak nie zadziała podanie drivera z jakim aplikacja nie jest dostarczona, więc powinno być to zaszyte na etapie developmentu.
  3. Gdzie odbywa się wskazanie, które klasy będą mapowane przez Hibernate? Czy classpath jest przeszukiwany w poszukiwaniu @Entity i te są mapowane? Czy typy jako takie trzeba podać explicite? Jeśli trzeba je podać, to jako że SessionFactory "tworzysz" tam deklaratywnie, zakładam że jego konfiguracja również jest deklaratywna tj. w XML lub innym wskazanym pliku.
  4. Co do @Transactional, czy przypadek użycia zastosowany przez ciebie jest poprawny? Adnotacja jest na DAO co oznacza, że sam serwis nie jest transakcyjny, jedynie pojedyncza operacja DAO jest - dobrze rozumiem?
  5. Jako, że przedstawiony przez ciebie kod wykorzystuje automatycznie stworzone SessionFactory, wielokrotnie używa jednej sesji i używasz aspektowych transakcji, to UnitOfWork można wyrzucić a Repository (które jest tu w zasadzie jedynie generycznym DAO bo nie ma żadnej logiki biznesowej) uzależnić zamiast od sesji to od SessionFactory i go już wprost używać w klasach serwisowych.
  6. Jak koniec końców ze strukturą projektu - czy jest sens robić więcej niż jeden projekt (jako że w sumie wyjdzie nam pewnie góra kilkanaście klas)? Jeśli tak, to jak to sensownie podzielić?

UPDATE: I ten POM twój wydaje się nieco przeładowany zależnościami, czy mi się wydaje (głównie mam na myśli Springa)?

ljedlinski commented 8 years ago
  1. Raczej myślałem o tym, aby go zagnieździć w jarze. Zostawiłem go po to, aby było czytelniej konfigurować bazę, zamiast osadzać wartosci w javie. Można go wystawić na zewnątrz (wtedy okroić tylko do nazwy bazy, loginu i hasła etc).
  2. j.w
  3. W xmlu springowym jest konfiguracja hibernate. Tam jest wskazany bazowy pakiet, po którym ma skanować za encjami. Nie trzeba ich podawać jawnie.
  4. Nie, to jest błąd którego nie pushnąłem. Transakcyjne oczywiście powinno być wywołanie serwisu, nie DAO. Mój błąd, dobrze rozumiesz.
  5. Można by tak zrobić. O czym chciałbym podysktutować, to złożone zapytania etc, ale o tym pewnie podyskutujemy via IM i spiszemy wnioski. Nie wiem czy dobrze rozumiałem jeżeli chodzi o wielokrotnie używa jednej sesji, ale to nie jest reużywanie jednej sesji. Reużywane jest sessionFactory, a getCurrentSession() dostarcza sesję per wątek (wątek per request). Transaction manager po drodze dba o to, aby sesję otwierać, zamykać etc. Wiem, że jawnie tego nie widać, ale w sumie o to chodzi - nie trzeba się tym przejmować.
  6. Można śmiało zmieścić się w jednym projekcie. Odruchowo zrobiłem dwa, ale nie zawarłem wszystkiego tutaj. monitor-api jest do usunięcia.

Update 7: Nie przeglądałem zależności. Ten projekt, który wstawiłem w ramach brancha to stworzony na szybko ultraprosty szielet podglądowy jak bym to widział, żeby można było tej projekt (monitor) napisać w miarę szybko, łatwo i nie zastanawiać się nad problemami, które już ktoś rozwiązał.

ljedlinski commented 8 years ago

Po ustaleniach: Szczegóły implementacji W masterze pojawiła się finalna wersja szkieletu (jakkolwiek to brzmi). Prawdopodobnie od tego momentu będzie już rozbudowywany o faktyczną implementację.

  1. Przeniesiono bazę z PostgreSQL na HSQL. 1.1. HSQL jest zembeddowany, nie trzeba żadnego serwera bazodanowego 1.2. Póki co, baza istnieje w pamięci RAM na czas życia aplikacji. Ponowne uruchomienie postawi bazę na nowo.
  2. Spłaszczono hierarchię projektów., Nie będziemy rozbijać aplikacji na Core, Api etc. Przy tej skali nie ma sensu.
  3. Repository do dostępu do danych jedno na całą aplikację (do przejrzenia w kodzie).
  4. Póki co, zostało trochę kodu przeniesione prawie 'as-is' z istniejącego projektu oraz pozostawiłem przykładowe klasy (serwisu, stare dao etc jako fundament wzorca).
  5. Preferowane Springowe annotacje do restów, Jackson do mapowania na JSONa, konfiguaracja przez springa (springowe DI).
  6. RestSeriwsy będą pewnie prosto korzystać z Repository i mapować dane In/Out
  7. Z powyższego wynika, że na świat wystawione będą DTO.

Chyba wszystko co chciałem/chcieliśmy zakomunikować z @dawidkomorowski .