diff --git a/.gitignore b/.gitignore index aadc7ca..2ce2709 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ *.out *.gz *.lot +_minted* diff --git a/parts/01_layered-arc.tex b/parts/01_layered-arc.tex index eecdc5d..9b76557 100644 --- a/parts/01_layered-arc.tex +++ b/parts/01_layered-arc.tex @@ -15,26 +15,41 @@ \end{itemize} 3 Schichten Architektur: \begin{itemize} - \item Presentation Layer: serverseitig, kümmert sich um Benutzerinteraktion - \item Domain Layer: enthält Business Logik (Berechnungen, Datenvalidierung, ...) - \item Data Source Layer: Zugriff auf Daten, kümmert sich um Kommunikation mit anderen Systemen (z.B.: Datenbank) + \item Data Source Layer(data): Zugriff auf Daten, kümmert sich um Kommunikation mit anderen Systemen (z.B.: Datenbank) + \begin{itemize} + \item beinhaltet DAO und DAOImpl >> DocumentDAO, DocumentlibraryDAO + \end{itemize} + \item Domain Layer(service): enthält Business Logik (Berechnungen, Datenvalidierung, ...) + \begin{itemize} + \item beinhaltet + \begin{itemize} + \item DTO >> DocumentDTO + \item Mapper >> DocumentMapper + \begin{minted}[breaklines=true]{java} +public static Document toEntity(DocumentDTO documentDTO, Document document){}; +public static DocumentDTO toDTO(Document document){}; + \end{minted} + \end{itemize} + \end{itemize} + \item Presentation Layer(web): serverseitig, kümmert sich um Benutzerinteraktion + \begin{itemize} + \item Controller (ViewHelper) >> DocumentController, DocumentListController + \end{itemize} \end{itemize} +\begin{figure}[!htp] + \centering + \includegraphics[width=0.4\textwidth]{pics/tree-projectmain.png} + \includegraphics[width=0.4\textwidth]{pics/web-2ndpart.jpg} +\end{figure} \subsubsection{Beschreibe ein konkretes Anwendungsbeispiel} \begin{itemize} \item Java Enterprise Edition (JEE) Architektur bestehend aus - \begin{itemize} - \item Client Tier (Client Machine) - \item Web Tier, Business Tier (Java EE Server) - \item EIS Tier (Database Server) - \end{itemize} + \begin{itemize} + \item Client Tier (Client Machine) + \item Web Tier, Business Tier (Java EE Server) + \item EIS Tier (Database Server) + \end{itemize} \end{itemize} -\subsubsection{Nenne die Konsequenzen der Anwendung} -\begin{itemize} - \item hilft dabei eine Applikation die in Unteraufgaben zerlegt werden können, zu strukturieren - \item jede Teilaufgabengruppe befindet sich in einem eigenen Layer - \item ermöglicht bzw. vereinfacht Austauschbarkeit -\end{itemize} - \subsection{Data Access Object (DAO) Pattern} \subsubsection{Erkläre die Funktion + Skizze} \begin{figure}[!htp] @@ -47,10 +62,30 @@ \item das DAO selbst soll keine spezifischen Elemente enthalten (Entity Manager, SQL Exception -> stattdessen DAOException) \item dadurch entsteht eine Kapselung bei der die DAOImpl ohne den Client zu verändern ausgetauscht werden kann \end{itemize} -\subsubsection{Beschreibe ein konkretes Anwendungsbeispiel} -\begin{itemize} - \item EntityManager in JEE -\end{itemize} +\begin{minted}[breaklines=true]{java} + @ApplicationScoped + public class DocumentDAOImpl implements DocumentDAO, Serializable { + private static final long serialVersionUID = 1L; + private static final Logger logger = LoggerFactory.getLogger(DocumentDAOImpl.class); + @PersistenceContext + private EntityManager entityMangaer; + + @Override + public List findByCommunity(Community community) {} + + @Override + public List findByUser(User user) {} + + @Override + public void insert(Document document) {} + + @Override + public void delete(Document document) {} + + @Override + public Document findById(Long id) {} + } +\end{minted} \subsubsection{Nenne die Konsequenzen der Anwendung} \begin{itemize} \item Zugriff auf persistenten Speicher wird abstrahiert @@ -63,18 +98,194 @@ \subsubsection{Erkläre die Funktion + Skizze} \begin{itemize} - \item Service Layer delegiert auf Business Logik und zum DAO - \item bei wenig Logik wird zumindest Transaktions, Error und Validierungshandling im Service erledigt + \item Service Layer delegiert auf Business Logik (z.B.: Zeile 82 community.setDocumentlibrary) und zum DAO (z.B.: Zeile 80, 81,82 ...) + \item bei wenig Logik wird zumindest Transaktions (z.B. Zeile 39), Error (z.B. Zeile 42-50) und Validierungshandling (z.B.: Zeile 24-27) im Service erledigt \end{itemize} +\begin{minted}[xleftmargin=\parindent,linenos,breaklines=true]{java} + + @Local(DocumentService.class) + @Remote(DocumentServiceRemote.class) + @Stateless + public class DocumentServiceImpl implements DocumentService, DocumentServiceRemote, Serializable { + private static final long serialVersionUID = -1L; + private static final Logger logger = LoggerFactory.getLogger(DocumentServiceImpl.class); + + @Inject + private DocumentDAO documentDAO; + @Inject + private DocumentlibraryDAO documentlibraryDAO; + @Inject + private CommunityDAO communityDAO; + @Inject + private UserDAO userDAO; + @Inject + private MessageDAO messageDAO; + @Override + public DocumentDTO addDocument(Long communityID, String userID, byte[] data, String filename) { + Document addedDocument; + User user; + + try { + if (communityID <= 0) throw new IllegalArgumentException("community must not be empty"); + if (userID == null) throw new IllegalArgumentException("user must not be empty"); + if (data == null) throw new IllegalArgumentException("uploaded file must not be empty"); + if (filename == null) throw new IllegalArgumentException("filename must not be empty"); + + Documentlibrary documentlibrary = documentlibraryDAO.findByCommunityId(communityID); + + //create a document library, if there isn't already one in the database + if (documentlibrary == null) { + documentlibrary = addDocumentlibrary(communityID); + } + + user = userDAO.getByUserId(userID); + + addedDocument = new Document(documentlibrary, user, filename, data); + documentDAO.insert(addedDocument); + logger.info(String.format("Document %s saved in database", filename)); + + } catch (IllegalArgumentException iaex) { + String errorMsg = "Uploading file failed (illegal argument)"; + logger.error(errorMsg, iaex); + throw new ServiceException(errorMsg); + + } catch (Exception ex) { + String errorMsg = String.format("Uploading file %s failed.", filename); + logger.error(errorMsg, ex); + throw new ServiceException(errorMsg); + } + + String msgText = "Uploaded Document " + filename + " by user " + user.getUserId(); + addMessageToStream(communityID, user, msgText, addedDocument); + return DocumentMapper.toDTO(addedDocument); + } + + + private void addMessageToStream(Long communityID, User user, String text, Document document) { + try { + Activitystream activitystream = communityDAO.findById(communityID).getActivitystream(); + Date now = new Date(); + Calendar calendar = Calendar.getInstance(); + calendar.set(9999, Calendar.DECEMBER, 31); + Date until = calendar.getTime(); + Message message = new Message(user, text, now, until, now, activitystream, null, "Document Upload", null, null); + messageDAO.insert(message); + } catch (Exception ex) { + String errorMsg = String.format("Add entry to stream for %s failed.", document.getFilename()); + logger.error(errorMsg, ex); + throw new ServiceException(errorMsg); + } + } + + + private Documentlibrary addDocumentlibrary(Long communityID) { + logger.info("Create missing documentlibrary"); + Community community; + Documentlibrary documentlibrary = new Documentlibrary(); + documentlibraryDAO.insert(documentlibrary); + community = communityDAO.findById(communityID); + community.setDocumentlibrary(documentlibrary); + communityDAO.update(community); + return documentlibrary; + } + + + @Override + public List getDocumentsFromCommunity(Long communityID) { + try { + List documents; + if (communityID <= 0) throw new IllegalArgumentException("community must not be empty"); + Community community = communityDAO.findById(communityID); + if (community == null) throw new IllegalStateException("community " + communityID + " not found"); + documents = documentDAO.findByCommunity(community); + return documents.stream().map(DocumentMapper::toDTO).collect(Collectors.toList()); + + } catch (IllegalArgumentException iaex) { + String errorMsg = "Could not load docs from community (illegal argument)"; + logger.error(errorMsg, iaex); + throw new ServiceException(errorMsg); + + } catch (Exception ex) { + String errorMsg = "Could not load docs for community."; + logger.error(errorMsg + " id " + communityID, ex); + throw new ServiceException(errorMsg); + } + } + + + @Override + public List getDocumentsFromUser(String userID) { + try { + List documents; + User user = userDAO.getByUserId(userID); + if (user == null) throw new IllegalArgumentException("user must not be empty"); + documents = documentDAO.findByUser(user); + return documents.stream().map(DocumentMapper::toDTO).collect(Collectors.toList()); + + } catch (IllegalArgumentException iaex) { + String errorMsg = "Could not load documents from user (illegal argument)"; + logger.error(errorMsg, iaex); + throw new ServiceException(errorMsg); + + } catch (Exception ex) { + String errorMsg = String.format("Could not load documents from user %s.", userID); + logger.error(errorMsg, ex); + throw new ServiceException(errorMsg); + } + } + + + @Override + public void removeDocument(Long documentID) { + String filename = ""; + Document document; + + try { + if (documentID <= 0) throw new IllegalArgumentException("documentID must not be zero"); + document = documentDAO.findById(documentID); + if (document == null) + throw new IllegalArgumentException("document must not be empty (id " + documentID + ")"); + filename = document.getFilename(); + Long communityId = document.getDocumentlibrary().getCommunity().getId(); + documentDAO.delete(document); + + User user = document.getUser(); + String msgText = "Removed Document " + filename; + addMessageToStream(communityId, user, msgText, document); + + } catch (IllegalArgumentException iaex) { + String errorMsg = "Could not remove document (illegal argument)"; + logger.error(errorMsg, iaex); + throw new ServiceException(errorMsg); + + } catch (Exception ex) { + String errorMsg = String.format("Could not remove document %s.", filename); + logger.error(errorMsg, ex); + throw new ServiceException(errorMsg); + } + } + + + @Override + public DocumentDTO getDocumentById(Long documentID) { + try { + Document document = documentDAO.findById(documentID); + return DocumentMapper.toDTO(document); + + } catch (Exception ex) { + String errorMsg = "Could not load document."; + logger.error(errorMsg + " id " + documentID, ex); + throw new ServiceException(errorMsg); + } + } + + } +\end{minted} \begin{figure}[!htp] \centering \includegraphics[width=0.45\textwidth]{pics/sl_pat1.jpg} \includegraphics[width=0.45\textwidth]{pics/sl_pat2.jpg} \end{figure} -\subsubsection{Beschreibe ein konkretes Anwendungsbeispiel} -\begin{itemize} - \item eine Applikation mit unterschiedlichen Clienttypen -\end{itemize} \subsubsection{Nenne die Konsequenzen der Anwendung} \begin{itemize} \item Reduzierung der Abhängigkeiten zwischen Presentation und Domain Layer @@ -83,6 +294,7 @@ \item stellt Client ein grobkörniges Interface zur Verfügung \item gut für Remote Aufrufe geeignet (weniger Aufrufe) \end{itemize} + \subsection{Model-View-Controller Pattern} \subsubsection{Erkläre die Funktion + Skizze} \begin{figure}[!htp] @@ -91,18 +303,18 @@ \end{figure} \begin{itemize} \item MVC unterteilt eine interaktive Applikation in drei Teile: - \begin{itemize} - \item Model: Kenfunktionalität und Daten (z.B.: Datenbankzugriff) - \item View: Visualisierung bzw. User-Interaktion - \item Controller: enthält Logik und behandelt Benutzereingaben - \end{itemize} + \begin{itemize} + \item Model (ServiceLayer): Kenfunktionalität und Daten (z.B.: Datenbankzugriff) + \item View (WebApp >> xhtml Dateien): Visualisierung bzw. User-Interaktion + \item Controller (web): enthält Logik und behandelt Benutzereingaben + \end{itemize} \item Controller und View befinden sich im Presentation Layer und haben gegenseitig Abhängigkeiten \item Model darf keine Abhängigkeiten haben (Controller und View hängen vom Model ab) \end{itemize} -\subsubsection{Beschreibe ein konkretes Anwendungsbeispiel} -\begin{itemize} - \item Look\&Feel fokusierte Anwendung -> so kann View ohne Große Probleme ausgetauscht werden -\end{itemize} +\begin{figure}[h!] + \centering + \includegraphics[width=0.5\textwidth]{pics/webapp-location.jpg} +\end{figure} \subsubsection{Nenne die Konsequenzen der Anwendung} \begin{itemize} \item Visualisierung abhängig vom Model - nicht umgekehrt @@ -113,22 +325,22 @@ \end{itemize} \subsection{Front Controller} \subsubsection{Erkläre die Funktion + Skizze} -\begin{figure}[!htp] - \centering - \includegraphics[width=0.5\textwidth]{pics/fc_pat.jpg} -\end{figure} \begin{itemize} \item Client schickt Request an Front Controller \item FC erfasst nur Infos die er für die weiter Delegation braucht \item FC gibt Request an entsprechenden ConcreteCommand oder View weiter \item es gibt zwei Implementierungsvarianten des Controller - \begin{multicols}{2} - \begin{itemize} - \item Servlet - \item ConcreteCommand - \end{itemize} - \end{multicols} + \begin{multicols}{2} + \begin{itemize} + \item Servlet + \item ConcreteCommand + \end{itemize} + \end{multicols} \end{itemize} +\begin{figure}[h!] + \centering + \includegraphics[width=0.5\textwidth]{pics/fc_pat.jpg} +\end{figure} \subsubsection{Beschreibe ein konkretes Anwendungsbeispiel} \begin{itemize} \item Java Server Faces (bei Java Server Faces enthält das File zwar keinen Java Code, interagiert aber direkt mit Java Code einer Backing Bean) @@ -141,10 +353,9 @@ \end{itemize} \subsection{View Helper} \subsubsection{Erkläre die Funktion + Skizze} -\begin{figure}[!htp] +\begin{figure}[h!] \centering - \includegraphics[width=0.4\textwidth]{pics/view-helper_pat1.jpg} - \includegraphics[width=0.4\textwidth]{pics/view-helper_pat2.jpg} + \includegraphics[width=0.5\textwidth]{pics/view-helper_pat1.jpg} \end{figure} \begin{itemize} \item View delegiert Aufgaben an Helper (Helper adaptieren View zu Model) @@ -160,10 +371,10 @@ \item steigert Wiederverwendbarkeit, Wartbarkeit und Strukturierungsqualität der Anwendung \item vereinfacht Tests (Helperfunktionen ohne View) \item bessere Trennung zwischen - \begin{itemize} - \item Presentation und Data Source Layer - \item Entwickler und Designer - \end{itemize} + \begin{itemize} + \item Presentation und Data Source Layer + \item Entwickler und Designer + \end{itemize} \end{itemize} @@ -195,10 +406,10 @@ \item hohe Flexibilität (Strategy, Proxy,..) \item bessere Erweiterbarkeit und Testbarkeit \item bei Spring kann Dependency Injection mittels XML oder Annotation erfolgen - \begin{itemize} - \item Vorteil Annotation: Typ-Sicherheit (Tippfehler passieren schnell im XML) - \item Nachteil Annotation: nicht so flexibel wie XML - \end{itemize} + \begin{itemize} + \item Vorteil Annotation: Typ-Sicherheit (Tippfehler passieren schnell im XML) + \item Nachteil Annotation: nicht so flexibel wie XML + \end{itemize} \end{itemize} \subsection{Remote Facade} \subsubsection{Erkläre die Funktion + Skizze} @@ -280,13 +491,13 @@ Bei HTML-Änderung muss ich nur Page-Objekt ändern und ansonsten nichts angreif \subsection{Beschreibe den Unterschied zwischen Checked und Runtime Exceptions in Java (inkl. Klassendiagramm)} \begin{itemize} \item Checked Exceptions (z.B. SQL-Exception) leiten von Exception Klasse ab und müssen behandelt werden (trows - catch) - \begin{itemize} - \item Verwendung für Probleme die durch User behoben werden können (alternative Aktion) - \end{itemize} + \begin{itemize} + \item Verwendung für Probleme die durch User behoben werden können (alternative Aktion) + \end{itemize} \item Unchecked Exceptions (z.B. NullPointerException) leiten von RuntimeException ab - \begin{itemize} - \item Verwendung für technische Probleme (User kann nichts machen außer neu starten) - \end{itemize} + \begin{itemize} + \item Verwendung für technische Probleme (User kann nichts machen außer neu starten) + \end{itemize} \end{itemize} \begin{figure}[!htp] \centering @@ -299,7 +510,7 @@ Bei HTML-Änderung muss ich nur Page-Objekt ändern und ansonsten nichts angreif \subsection{Beschreibe einen Use Case für eine Runtime Exceptions in Java} \begin{itemize} \item Die Datenbank ist beschädigt - die Exception geht durch alle Layer erst mit - Implementierungsspezifischer Exception später mit Runtime ohne Stacktrace (Sicherheit) bis zum User. + Implementierungsspezifischer Exception später mit Runtime ohne Stacktrace (Sicherheit) bis zum User. \end{itemize} \subsection{Beschreibe 5 Best Practice Beispiele beim Einsatz von Exceptions} \begin{itemize} @@ -335,8 +546,20 @@ Bei HTML-Änderung muss ich nur Page-Objekt ändern und ansonsten nichts angreif \item durch verschiedene Log-level können Logs gefiltert erstellt werden \item Layout für Ausgabe kann zentral definiert/geändert werden \end{itemize} +\section{Project Structure} +\begin{figure}[!htp] + \centering + \includegraphics[width=0.4\textwidth]{pics/tree-project-main.png} + \includegraphics[width=0.4\textwidth]{pics/tree-project-test.png} +\end{figure} \section{Toni} \subsection{Annotationen} +\subsubsection{@MappedSuperclass} +\begin{itemize} + \item ist im Hybernate Framework eine Klasse durch die gemeinsame Felder definiert werden. + \item definiert eine abstrakte Superklasse +\end{itemize} + @Produces – kommt während deployment, markiert Factory Method damit man nicht direkt auf die Klasse zugreifen muss @Typed – zeigt die Vererbung Wieso bei uns allein stehend? @Named – Zeigt bei Mehrdeutigkeit das richtige Objekt mit dem Namen @@ -348,7 +571,7 @@ Bei HTML-Änderung muss ich nur Page-Objekt ändern und ansonsten nichts angreif @OneToMany Beziehung @JoinColums – welche Spalten zusammen gehören FK @OneToMany FK auf anderen Seite -@ApplicationScoped – lebt die ganze Applikation lang, wird einmal gemacht. +@ApplicationScoped – lebt die ganze Applikation lang, wird einmal gemacht. @PersistenceContext – persistance.xml auslesen für Treiber und andere JPA Geschichten + Data Source. Entity Manager Injection. @Id – das ist die id @GeneratedValue – Wert kommt aus der DB @@ -358,13 +581,13 @@ Bei HTML-Änderung muss ich nur Page-Objekt ändern und ansonsten nichts angreif \subsection{Patterns in Practice} Data Access Layer Entity – Java Repräsentation vom DB Entity -DAO damit man auf die Entities zugreifen kann. DB abstrahieren. Methoden mit denen man auf die DB zugreifen kann. -DAOImpl – Implementierung -DAOImpl – DAOException fehlt. Schlecht weil Input wird nicht kontrolliert. EntityManager in try catch, sonst kann es kleschen. Zudätzlich in DaoException wrappen. +DAO damit man auf die Entities zugreifen kann. DB abstrahieren. Methoden mit denen man auf die DB zugreifen kann. +DAOImpl – Implementierung +DAOImpl – DAOException fehlt. Schlecht weil Input wird nicht kontrolliert. EntityManager in try catch, sonst kann es kleschen. Zusätzlich in DaoException wrappen. AbstractEntity – hier wird die id gemanaged Service Layer DTO – Aufrufgeschw. Verringern, nicht jedes Objekt einzeln aufrufen, sondern mit einmal alle notwendigen Objekte. -Mapper – von DTO in Entity und Entity ins DTO. +Mapper – von DTO in Entity und Entity ins DTO. FrontController web.xml ViewHelper *ServiceImpl diff --git a/pics/tree-project-main.png b/pics/tree-project-main.png new file mode 100644 index 0000000..18296f5 Binary files /dev/null and b/pics/tree-project-main.png differ diff --git a/pics/tree-project-test.png b/pics/tree-project-test.png new file mode 100644 index 0000000..634733b Binary files /dev/null and b/pics/tree-project-test.png differ diff --git a/pics/tree-projectmain.png b/pics/tree-projectmain.png new file mode 100644 index 0000000..3470544 Binary files /dev/null and b/pics/tree-projectmain.png differ diff --git a/pics/web-2ndpart.jpg b/pics/web-2ndpart.jpg new file mode 100644 index 0000000..0f5d3d6 Binary files /dev/null and b/pics/web-2ndpart.jpg differ diff --git a/pics/webapp-location.jpg b/pics/webapp-location.jpg new file mode 100644 index 0000000..2b2fe46 Binary files /dev/null and b/pics/webapp-location.jpg differ diff --git a/sw-arc.tex b/sw-arc.tex index d830dd4..649e332 100644 --- a/sw-arc.tex +++ b/sw-arc.tex @@ -8,20 +8,21 @@ \usepackage[hidelinks]{hyperref} \usepackage{multicol} \usepackage{graphicx} -%\usepackage{minted} -\usepackage[outputdir=../../auxil]{minted} +\usepackage{minted} +\setminted{fontsize=\small} +%\usepackage[outputdir=../../auxil]{minted} % Document \begin{document} - \author{Phillip Wo \\ Benjamin Moser \\ Daniel Sommer} - \title{Enterprise Software Architecture - FAQ Ausarbeitung} - \maketitle - \pagebreak - \tableofcontents - \pagebreak +\author{Phillip Wo \\ Benjamin Moser \\ Daniel Sommer} +\title{Enterprise Software Architecture - FAQ Ausarbeitung} +\maketitle +\pagebreak +\tableofcontents +\pagebreak - \include{parts/01_layered-arc} - %\include{parts/02_comp-based_arc} - %\include{parts/03_service-orientated_arc} +\include{parts/01_layered-arc} +%\include{parts/02_comp-based_arc} +%\include{parts/03_service-orientated_arc} \end{document}