628 lines
27 KiB
TeX
628 lines
27 KiB
TeX
\part{Layered Architectures}
|
||
\section{Architektur-Pattern}
|
||
\subsection{Layers Pattern}
|
||
\subsubsection{Erkläre die Funktionsweise + Skizze}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.5\textwidth]{pics/esa_layers.jpg}
|
||
\end{figure}
|
||
\begin{itemize}
|
||
\item Client schickt eine Anfrage an Layer N
|
||
\item Layer N reicht da er nicht vollständig alleine beantworten kann, Anfragen an darunterliegenden Layer weiter
|
||
\item Eine Anfrage kann bei Bedarf auch in mehrere Anfragen an darunterliegende Layer geteilt werden
|
||
\item dies wird immer weiter fortgesetzt bis Layer 1 erreicht ist
|
||
\item dabei gehen Abhängigkeiten nur von oben nach unten
|
||
\end{itemize}
|
||
3 Schichten Architektur:
|
||
\begin{itemize}
|
||
\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}
|
||
\end{itemize}
|
||
\subsection{Data Access Object (DAO) Pattern}
|
||
\subsubsection{Erkläre die Funktion + Skizze}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.5\textwidth]{pics/dao_pat1.jpg}
|
||
\includegraphics[width=0.3\textwidth]{pics/dao_pat2.jpg}
|
||
\end{figure}
|
||
\begin{itemize}
|
||
\item Client erstellt ein DAO Object und kann nach Entitäten suchen, einfügen, löschen, etc.
|
||
\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}
|
||
\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<Document> findByCommunity(Community community) {}
|
||
|
||
@Override
|
||
public List<Document> 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
|
||
\item Details des Speichers werden versteckt
|
||
\item ermöglicht einheitlichen Zugriff auf Daten
|
||
\item entkoppelt Implementierung von Persistierung (Datenbank,...)
|
||
\item ermöglicht Objektorientierte Ansicht des Speichers
|
||
\end{itemize}
|
||
\subsection{Service Layer Pattern (auch Session Fassade)}
|
||
\subsubsection{Erkläre die Funktion + Skizze}
|
||
|
||
\begin{itemize}
|
||
\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<DocumentDTO> getDocumentsFromCommunity(Long communityID) {
|
||
try {
|
||
List<Document> 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<DocumentDTO> getDocumentsFromUser(String userID) {
|
||
try {
|
||
List<Document> 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{Nenne die Konsequenzen der Anwendung}
|
||
\begin{itemize}
|
||
\item Reduzierung der Abhängigkeiten zwischen Presentation und Domain Layer
|
||
\item Zentralisiertes Sicherheits und Transaktionshandling
|
||
\item verbirgt vor Client Komplexität der Business Logik
|
||
\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]
|
||
\centering
|
||
\includegraphics[width=0.5\textwidth]{pics/mvc_pat.jpg}
|
||
\end{figure}
|
||
\begin{itemize}
|
||
\item MVC unterteilt eine interaktive Applikation in drei Teile:
|
||
\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}
|
||
\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
|
||
\item verschiedene Darstellungen möglich
|
||
\item einfaches Testen der Domain-Logik
|
||
\item gute Strukturierung
|
||
\item View wird leichter austausch bzw. änderbar
|
||
\end{itemize}
|
||
\subsection{Front Controller}
|
||
\subsubsection{Erkläre die Funktion + Skizze}
|
||
\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}
|
||
\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)
|
||
\end{itemize}
|
||
\subsubsection{Nenne die Konsequenzen der Anwendung}
|
||
\begin{itemize}
|
||
\item es muss nur EIN (Front) Controller konfiguriert werden
|
||
\item da bei jedem Request ein neues Command Objekt erzeugt wird ist Thread-Safety nicht notwendig
|
||
\item da nur EIN Controller sind auch Erweiterungen durch z.B.: Decorator einfach (auch zur Laufzeit)
|
||
\end{itemize}
|
||
\subsection{View Helper}
|
||
\subsubsection{Erkläre die Funktion + Skizze}
|
||
\begin{figure}[h!]
|
||
\centering
|
||
\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)
|
||
\item in View befindet sich HTML Code im ViewHelper Java Code zur Aufbereitung der Daten (+ wenig HTML)
|
||
\end{itemize}
|
||
\subsubsection{Beschreibe ein konkretes Anwendungsbeispiel}
|
||
\begin{itemize}
|
||
\item bei Verwendung von JSP (Java Server Pages enthalten neben HTML auch Java Code)
|
||
\end{itemize}
|
||
\subsubsection{Nenne die Konsequenzen der Anwendung}
|
||
\begin{itemize}
|
||
\item kapselt Design-Code in View und View-Processing-Code Logik in Helper
|
||
\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}
|
||
\end{itemize}
|
||
|
||
|
||
\subsection{Dependency Injection (don't call us, we'll call you)}
|
||
\subsubsection{Erkläre die Funktion + Skizze}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.5\textwidth]{pics/dependency_inj_pat.jpg}
|
||
\includegraphics[width=0.4\textwidth]{pics/dependency_inj_spring_pat.jpg}
|
||
\end{figure}
|
||
\begin{itemize}
|
||
\item Grundidee sind loose gekoppelte Objekte
|
||
\item Objekte werden mittels externem Assembler verknüpft
|
||
\item Abhängigkeiten bestehen nur auf Interfaces
|
||
\item Assembler Objekt erzeugt die Interface-Implementierungen (z.B.: durch Factory)
|
||
\end{itemize}
|
||
\subsubsection{Beschreibe ein konkretes Anwendungsbeispiel}
|
||
\begin{itemize}
|
||
\item Im Spring Context: Dependency Injection mit XML-Datei
|
||
\item alle Beans sind dort gelistet und werden verknüpft
|
||
\item Context wird geladen damit alles verknüpft ist
|
||
\item erspart Factories
|
||
\item man unterscheidet Constructor und Setter Injection
|
||
\end{itemize}
|
||
\subsubsection{Nenne die Konsequenzen der Anwendung}
|
||
\begin{itemize}
|
||
\item loose gekoppelte Objekte
|
||
\item Referenzen nurmehr auf Interfaces
|
||
\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}
|
||
\end{itemize}
|
||
\subsection{Remote Facade}
|
||
\subsubsection{Erkläre die Funktion + Skizze}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.5\textwidth]{pics/rem_fass_pat.jpg}
|
||
\end{figure}
|
||
\begin{itemize}
|
||
\item bietet dem Client ein grobes Interface
|
||
\item ist Schicht die von grob zu fein-granularem Interface umwandelt
|
||
\item steigert so Netzwerkeffizienz
|
||
\end{itemize}
|
||
\subsubsection{Beschreibe ein konkretes Anwendungsbeispiel}
|
||
\begin{itemize}
|
||
\item Implementierung in Applikation um überlastetes Netzwerk zu entlasten.
|
||
\end{itemize}
|
||
\subsubsection{Nenne die Konsequenzen der Anwendung}
|
||
\begin{multicols}{2}
|
||
\begin{itemize}
|
||
\item weniger Remote Calls
|
||
\item Entlastung des Netzwerkes
|
||
\item steigert Zuverlässigkeit
|
||
\end{itemize}
|
||
\end{multicols}
|
||
\subsection{Data Transfer Object (DTO) Pattern}
|
||
\subsubsection{Erkläre die Funktion (Skizze - ein Grund für DTO)}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.9\textwidth]{pics/lok-vs-remote.jpg}
|
||
\end{figure}
|
||
\begin{itemize}
|
||
\item Transportiert Daten zwischen Prozessen um Remote Methodenaufrufe zu minimieren
|
||
\item besteht aus Fields, Getter und Setter
|
||
\item fasst Daten verschiedener Objekte zusammen die vom Remote Objekt benötigt werden
|
||
\item ev. Map, Record Set, ...
|
||
\end{itemize}
|
||
\subsubsection{Beschreibe ein konkretes Anwendungsbeispiel}
|
||
% todo: Anwendungsbeispiel
|
||
\subsubsection{Nenne die Konsequenzen der Anwendung}
|
||
\begin{itemize}
|
||
\item kapselt und versteckt
|
||
\item nimmt Komplexität
|
||
\item steigert Effizienz da weniger Aufrufe über Remotegrenze
|
||
\end{itemize}
|
||
\subsection{Page-Object-Pattern}
|
||
PageObjectPattern
|
||
|
||
HTML – wrappen mit JavaCode, um es zu manipulieren
|
||
|
||
GUI-Test-Klasse und Page-Object
|
||
|
||
Über die Page-Object-Klasse manipuliere ich das HTML-Dokument
|
||
|
||
Bei HTML-Änderung muss ich nur Page-Objekt ändern und ansonsten nichts angreifen (Verkapselung)
|
||
\section{Remote}
|
||
\subsection{Beschreibe die Unterschiede zwischen lokalem und Remote Interface Design}
|
||
\begin{itemize}
|
||
\item Aufrufe innerhalb des Prozesses sind schneller als über Prozessgrenzen
|
||
\item lokale Interfaces sind möglichst fein-granular während Remote Interfaces grob-granular sein müssen (weniger Aufrufe - Effizienz)
|
||
\item viele kleine Aufrufe mit wenigen Daten sind "teuer" (Latenz durch Verbindungsherstellung)
|
||
\end{itemize}
|
||
\subsection{Beschreibe drei Situationen wo Multiple Prozesse in Applikationen verwendet werden müssen}
|
||
\begin{itemize}
|
||
\item Trennung zwischen Clients und Servern in Business Software
|
||
\item Trennung zwischen server-basierter Applikationssoftware und Datenbank (SQL ist als Remote Interface designed, daher sind hier schnelle Abfragen möglich)
|
||
\item Trennung wegen unterschiedlichen Anbietern oder Programmiersprachen
|
||
\end{itemize}
|
||
|
||
\subsection{Beschreibe das folgende Diagramm. Was können wir daraus für das Design von Remote Interfaces folgern?}
|
||
\begin{itemize}
|
||
\item speziell bei "teuren" Remote Calls ist es empfehlenswert weniger Calls mit großen Datenmengen anstatt vielen Calls mit wenigen Daten zu machen
|
||
\item dieser Gedanke befürwortet auch den Einsatz von DTO um Calls und Daten zu bündeln
|
||
\end{itemize}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.9\textwidth]{pics/lok-vs-remote.jpg}
|
||
\end{figure}
|
||
\section{Exception Handling}
|
||
\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}
|
||
\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}
|
||
\end{itemize}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.3\textwidth]{pics/except_class_dia.jpg}
|
||
\end{figure}
|
||
\subsection{Beschreibe einen Use Case für eine Checked Exceptions in Java}
|
||
\begin{itemize}
|
||
\item eine Netzwerkübertragung schlägt fehl - es ist vorgesehen, dass der Applikations-User dies neu anstoßen kann
|
||
\end{itemize}
|
||
\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.
|
||
\end{itemize}
|
||
\subsection{Beschreibe 5 Best Practice Beispiele beim Einsatz von Exceptions}
|
||
\begin{itemize}
|
||
\item Exceptions nicht für Programmflusskontrolle verwenden (schlechte Performance)
|
||
\item offene Ressourcen schließen (try-with-resources bzw. close im finally)
|
||
\item selbst erstellte Exceptions auch mit nützlichen Infos ausstatten
|
||
\item Implementierungsspezifische Exceptions nicht bis zum User durchwerfen (stattdessen catch + trow RuntimeException)
|
||
\item dokumentieren mit @trows im DOC, testen mit JUnit
|
||
\end{itemize}
|
||
|
||
\subsection{Beschreibe 5 Exception Handling Anti Pattern}
|
||
\begin{itemize}
|
||
\item Log and Trow (nie beides: entweder, oder)
|
||
\item Trowing Exception bzw. catch Exception (spezifischere anstatt Basisklasse verwenden)
|
||
\item Destructive Wrapping (wenn bei catch + trow = wrapping nicht die Original Exception weitergegeben wird)
|
||
\item Log and return Null (provoziert an einer anderen Stelle eine NullPointerException)
|
||
\item Catch and Ignore
|
||
\item Unsupported Operation return Null (besser UnsupportedOperationException)
|
||
\end{itemize}
|
||
\section{Logging}
|
||
\subsection{Nenne die Nachteile von debugging mit printf() sowie die Vorteile die Logging Frameworks wie log4j bieten}
|
||
\subsubsection{Nachteile printf()}
|
||
\begin{itemize}
|
||
\item Produktiv-Code wird überfüllt -> erschwert Lesbarkeit
|
||
\item Consolenausgabe wird bei vielen prints auch schnell unübersichtlich
|
||
\item im Falle eines vorzeitigen Absturzes können Ausgabedaten verloren gehen
|
||
\item Performance bei vielen Logprints
|
||
\end{itemize}
|
||
\subsubsection{Vorteile Logging mittels Framework (z.B.: log4j)}
|
||
\begin{itemize}
|
||
\item Nutzt ein einheitliches Format / Konventionen
|
||
\item logging kann optional an und ausgeschalten werden
|
||
\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
|
||
@Resource – fast wie Dependency Injection
|
||
@Stateless – speichert den Client Status nicht
|
||
@Entity – Data Access Layer
|
||
@Table – Tabellenname im SQL
|
||
@Column – SQL-Spalten nullable=false
|
||
@OneToMany Beziehung
|
||
@JoinColums – welche Spalten zusammen gehören FK
|
||
@OneToMany FK auf anderen Seite
|
||
@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
|
||
@Local – Klasse für lokale Aufrufe.
|
||
@Remote – interprozessaufrufe. RMI
|
||
@ApplicationException – Rollback wenn so eine Exception kommt, Nachricht zum Client.
|
||
\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. 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.
|
||
|
||
FrontController web.xml
|
||
ViewHelper *ServiceImpl
|
||
\subsection{Konfigurationsdateien (pom.xml), (persistence.xml) und noch a bissl mehr Scheiß}
|
||
Resource plugin – klar für Ressourcen
|
||
Wildfly – server
|
||
Primeafce = jsf Framework
|
||
Jacoco = test Coverage
|
||
Slf4j = logger
|
||
Jaxb – xml
|
||
Cdi = context dependancy injection
|
||
\subsection{Reihenfolge - Wildfly - Abfolge - einzelne Schritte}
|
||
Reihenfolge:
|
||
1. Compile
|
||
2. Surefire (unitTests)
|
||
3. Deploy (warplugin)
|
||
4. Failsafe IT-test
|
||
5. MVN site
|
||
6. Gui test
|
||
\subsection{Frageart Prüfung}
|
||
Welche Fehler können bei Exception-Handling vorkommen in unserem Projekt?? – wie funktioniert es grundsätzlich in unserem Code
|
||
|
||
DocumentDAO – DocumentService – DocumentController – so sollte Exception-Handling implementiert warden
|
||
|
||
DAO wirft Exception – im ServiceLayer wird dies gefangen und der Stack-Trace wird im weggeloggt und eine benutzerfreundliche Fehlermeldung wird ausgegeben (Destructive Wrapping).
|
||
|
||
Alle Patterns, die vorkommen – praktische Beispiele aus dem Code
|
||
|
||
Was sind JavaBeans? Wie funktioniert das Konzept? Wie wird es genau implementiert?
|
||
NamedBean, TypedBean etc.
|
||
|
||
DTO
|
||
|
||
|
||
|
||
|
||
|