728 lines
30 KiB
TeX
728 lines
30 KiB
TeX
% Preamble
|
||
\documentclass[11pt]{article}
|
||
|
||
% Packages
|
||
\usepackage{a4wide}
|
||
\usepackage[T1]{fontenc}
|
||
\usepackage[utf8]{inputenc}
|
||
\usepackage[hidelinks]{hyperref}
|
||
\usepackage{multicol}
|
||
\usepackage{graphicx}
|
||
\usepackage{minted}
|
||
\setminted{fontsize=\small}
|
||
%\usepackage[outputdir=../../auxil]{minted}
|
||
|
||
% Document
|
||
\begin{document}
|
||
\author{Phillip Wo \\ Benjamin Moser \\ Daniel Sommer}
|
||
\title{PSE Ausarbeitung}
|
||
\maketitle
|
||
\pagebreak
|
||
\tableofcontents
|
||
\pagebreak
|
||
|
||
\part{Pattern im Projekt}
|
||
\section{Layers Pattern}
|
||
\subsection{Erkläre die Funktionsweise + Skizze}
|
||
\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}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.8\textwidth]{pics/esa_layers.jpg}
|
||
\end{figure}
|
||
\subsubsection{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 \textbf{Service Layer Pattern} (aka Session Fassade - siehe~\ref{sec:slp})
|
||
\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
|
||
\item View (WebApp)
|
||
\end{itemize}
|
||
\end{itemize}
|
||
\begin{figure}[tph!]
|
||
\centering
|
||
\includegraphics[width=0.4\textwidth]{pics/layer-pattern}
|
||
\end{figure}
|
||
\section{Data Access Object (DAO) Pattern}
|
||
Befindet sich im Projekt in data und damit innerhalb des Data Layer.
|
||
\subsection{Erkläre die Funktion + Skizze}
|
||
\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{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.8\textwidth]{pics/dao_pat1.jpg}
|
||
\end{figure}
|
||
\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}
|
||
\subsection{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}
|
||
\section{Service Layer Pattern (auch Session Fassade - in unserem Projekt im Domain Layer}\label{sec:slp}
|
||
\subsection{Erkläre die Funktion + Skizze}\label{subsubsec:service-layer-pattern}
|
||
\begin{itemize}
|
||
\item Der Service Layer (Ordner "`service"' im Projekt) delegiert auf die Business Logik (Zeile 68 community.setDocumentlibrary) und zum DAO (z.B. Zeile 66)
|
||
\item Bei wenig Logik wird zumindest Transaktions (Zeile 40), Error (ab Zeile 42) und Validierungshandling (ab Zeile 23) im Service erledigt
|
||
\end{itemize}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.8\textwidth]{pics/sl_pat1.jpg}
|
||
\end{figure}
|
||
\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;
|
||
|
||
// Validierungshandling gefolgt von Error Handling
|
||
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); // Transaktionshandling
|
||
logger.info(String.format("Document %s saved in database", filename));
|
||
// Error Handling
|
||
} 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) {...}
|
||
|
||
private Documentlibrary addDocumentlibrary(Long communityID) {
|
||
logger.info("Create missing documentlibrary");
|
||
Community community;
|
||
Documentlibrary documentlibrary = new Documentlibrary();
|
||
documentlibraryDAO.insert(documentlibrary); // Delegation zum DAO
|
||
community = communityDAO.findById(communityID); // Delegation zum DAO
|
||
community.setDocumentlibrary(documentlibrary); // Delegation zur Business Logik (Entity)
|
||
communityDAO.update(community); // Delegation zum DAO
|
||
return documentlibrary;
|
||
}
|
||
|
||
@Override
|
||
public List<DocumentDTO> getDocumentsFromCommunity(Long communityID) {...}
|
||
|
||
@Override
|
||
public List<DocumentDTO> getDocumentsFromUser(String userID) {...}
|
||
|
||
@Override
|
||
public void removeDocument(Long documentID) {...}
|
||
|
||
@Override
|
||
public DocumentDTO getDocumentById(Long documentID) {...}
|
||
}
|
||
\end{minted}
|
||
|
||
\subsection{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}
|
||
|
||
\section{Model-View-Controller (MVC) Pattern}
|
||
\subsection{Erkläre die Funktion + Skizze}
|
||
MVC unterteilt eine interaktive Applikation in drei Teile: Model, View und Controller.
|
||
\begin{itemize}
|
||
\item Controller und View befinden sich im Presentation Layer und haben gegenseitig Abhängigkeiten
|
||
\item Das Model darf keine Abhängigkeiten haben (Controller und View hängen vom Model ab)
|
||
\end{itemize}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.8\textwidth]{pics/mvc_pat.jpg}
|
||
\end{figure}
|
||
\subsubsection{Model}
|
||
\begin{itemize}
|
||
\item Es befinden sich Teile im Domain und Data Source Layer.
|
||
\item Das Model enthält die Kernfunktionalität und Daten. (z.B.: Datenbankzugriff)
|
||
\item Im Projekt ... % TODO
|
||
\end{itemize}
|
||
\subsubsection{View}
|
||
\begin{itemize}
|
||
\item Im Projekt im Ordner WebApp zu finden.
|
||
\item Enthält im Projekt xhtml Dateien zur Darstellung und User Interaktion
|
||
\end{itemize}
|
||
\subsubsection{Controller}
|
||
\begin{itemize}
|
||
\item Im Projekt sind Controllerklassen im Ordner web zu finden.
|
||
\item Sie enthalten die Logik und behandeln Benutzereingaben
|
||
\end{itemize}
|
||
\subsection{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}
|
||
\section{Front Controller}
|
||
\subsection{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}
|
||
\subsection{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)
|
||
\item Im Projekt wurde der Front Controller in Form eines Servlet realisiert, dessen Einbindung in der Konfigurationsdatei "`web.xml"' erfolgt:
|
||
\end{itemize}
|
||
\begin{minted}[linenos,breaklines=true]{xml}
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
|
||
...
|
||
<servlet>
|
||
<servlet-name>Faces Servlet</servlet-name>
|
||
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
|
||
<load-on-startup>1</load-on-startup>
|
||
</servlet>
|
||
<servlet-mapping>
|
||
<servlet-name>Faces Servlet</servlet-name>
|
||
<url-pattern>*.xhtml</url-pattern>
|
||
</servlet-mapping>
|
||
\end{minted}
|
||
\subsection{Anwendung im Projekt}
|
||
JavaServer Faces: mächtiges Framework, wo das MVC Pattern verwendet wird. Auf der einen Seite
|
||
stehen die reinen Views (XHTML Seiten) und auf der anderen Seite Java Beans (Java Klassen), die als
|
||
View Helper fungieren können. Beispiel: layered/MVC-JSF
|
||
Primefaces ist eine konkrete Implementierung der JavaServer Faces (siehe POM.XML).
|
||
|
||
\begin{minted}[linenos,breaklines=true]{xml}
|
||
<?xml version='1.0' encoding='UTF-8' ?>
|
||
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||
xmlns:p="http://primefaces.org/ui"
|
||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||
template="communityTemplate.xhtml">
|
||
<ui:define name="communityContent">
|
||
<h1>#{msg.document_manage_title}</h1>
|
||
<f:metadata>
|
||
<f:viewAction action="#{documentListController.loadDocumentsFromCommunity()}" />
|
||
</f:metadata>
|
||
|
||
<h:form id="doclistform">
|
||
<p:commandButton value="Refresh list" actionListener="#{documentListController.loadDocumentsFromCommunity()}" update="@form doclistform"></p:commandButton>
|
||
<p:dataTable id="doclisttable" value="#{documentListController.communityDocuments}" var="docs">
|
||
<p:column class="documenttimecolumn" headerText="#{msg.document_uploaded}">#{docs.createdTimestamp}</p:column>
|
||
<p:column class="documenttimecolumn" headerText="#{msg.label_userid}">#{docs.user.userId}</p:column>
|
||
<p:column headerText="#{msg.label_filename}">#{docs.filename}</p:column>
|
||
<p:column headerText="" class="documentbuttoncolumn">
|
||
<p:commandButton value="#{msg.button_download}" ajax="false"
|
||
onclick="PrimeFaces.monitorDownload(start, stop);">
|
||
<p:fileDownload value="#{documentController.downloadDocument(docs.id)}"/>
|
||
</p:commandButton>
|
||
</p:column>
|
||
<p:column headerText="" class="documentbuttoncolumn">
|
||
<p:commandButton id="btnDel" value="#{msg.button_delete}"
|
||
actionListener="#{documentController.removeDocument(docs.id)}"
|
||
update="@form doclistform">
|
||
</p:commandButton>
|
||
</p:column>
|
||
</p:dataTable>
|
||
</h:form>
|
||
<h:form id="formdocupload" enctype="multipart/form-data">
|
||
<p:fileUpload id="fileupload"
|
||
dragDropSupport="false"
|
||
update="@form doclistform"
|
||
fileUploadListener="#{documentController.uploadDocument}"
|
||
allowTypes="/(\.|\/)(pdf|jpe?g|docx)\$/" sizeLimit="5000000"
|
||
mode="advanced" label="Add document (.pdf .jpg .docx)">
|
||
</p:fileUpload>
|
||
</h:form>
|
||
<p:messages id="feedbackBox" severity="info,error" showDetail="true" showSummary="false">
|
||
<p:autoUpdate/>
|
||
</p:messages>
|
||
</ui:define>
|
||
</ui:composition>
|
||
\end{minted}
|
||
|
||
\subsection{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}
|
||
\section{View Helper}
|
||
\subsection{Erkläre die Funktion + Skizze}
|
||
\begin{figure}[h!]
|
||
\centering
|
||
\includegraphics[width=0.8\textwidth]{pics/view-helper_pat1.jpg}
|
||
\end{figure}
|
||
\begin{itemize}
|
||
\item View (xhtml-Dateien im Ordner webapp) delegiert Aufgaben an Helper (*Controller-Klassen - z.B. DocumentController im Ordner web)
|
||
\item Helper adaptieren View zu Model (Klassen in den Ordnern service und data)
|
||
\item in View befindet sich HTML Code im ViewHelper Java Code zur Aufbereitung der Daten (+ wenig HTML)
|
||
\end{itemize}
|
||
\subsection{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}
|
||
|
||
|
||
\section{Dependency Injection (don't call us, we'll call you)}
|
||
\subsection{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 (Framework) erzeugt die Interface-Implementierungen (z.B.: durch Factory)
|
||
\item Es wird zwischen Constructor Injection und Setter Injection unterschiedlichen
|
||
\begin{minted}[linenos,breaklines=true]{java}
|
||
// Constructor Injection
|
||
puplic class Client
|
||
{
|
||
private Interface iface;
|
||
public Client(Interface iface)
|
||
{
|
||
this.iface = iface;
|
||
}}
|
||
|
||
// Setter Injection
|
||
puplic class Client
|
||
{
|
||
private Interface iface;
|
||
public setIface(Interface iface)
|
||
{
|
||
this.iface = iface;
|
||
}}
|
||
\end{minted}
|
||
\end{itemize}
|
||
\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
|
||
\end{itemize}
|
||
\subsection{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}
|
||
\section{Data Transfer Object (DTO) Pattern}
|
||
\subsection{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}
|
||
\subsection{Beschreibe ein konkretes Anwendungsbeispiel}
|
||
% todo: Anwendungsbeispiel
|
||
\subsection{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}
|
||
\section{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}
|
||
\section{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}
|
||
\section{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}
|
||
|
||
\section{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}
|
||
\section{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}
|
||
\section{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}
|
||
\section{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}
|
||
\section{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}
|
||
|
||
\section{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}
|
||
\section{Nenne die Nachteile von debugging mit printf() sowie die Vorteile die Logging Frameworks wie log4j bieten}
|
||
\subsection{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}
|
||
\subsection{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}
|
||
\part{Project Structure}
|
||
\section{Annotationen}
|
||
\subsection{@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.
|
||
\section{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
|
||
\section{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
|
||
\section{Reihenfolge - Wildfly - Abfolge - einzelne Schritte}
|
||
Reihenfolge:
|
||
\begin{multicols}{2}
|
||
\begin{enumerate}
|
||
\item Compile
|
||
\item Surefire (unitTests)
|
||
\item Packaging - war file erstellen
|
||
\item Wildfly - fressen und deployen
|
||
\item Failsafe IT-test
|
||
\item MVN site
|
||
\item Gui test
|
||
\end{enumerate}
|
||
\end{multicols}
|
||
|
||
\section{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
|
||
|
||
|
||
\section{Die CONFIG-Files}
|
||
\begin{figure}[!htp]
|
||
\centering
|
||
\includegraphics[width=0.7\textwidth]{pics/ConfigFiles.png}
|
||
\end{figure}
|
||
\subsection{web.xml}
|
||
\begin{itemize}
|
||
\item konfiguriert den Java Webserver (Wildfly - JBOSS)
|
||
\item befindet sich im Ordner \textbf{src/main/webapp/WEB-INF/web.xml}
|
||
\end{itemize}
|
||
|
||
\begin{minted}[linenos,breaklines=true]{xml}
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
|
||
...
|
||
<servlet>
|
||
<servlet-name>Faces Servlet</servlet-name>
|
||
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
|
||
<load-on-startup>1</load-on-startup>
|
||
</servlet>
|
||
<servlet-mapping>
|
||
<servlet-name>Faces Servlet</servlet-name>
|
||
<url-pattern>*.xhtml</url-pattern>
|
||
</servlet-mapping>
|
||
|
||
<!-- Security roles -->
|
||
<security-role>
|
||
<description>administrators</description>
|
||
<role-name>ADMIN</role-name>
|
||
</security-role>
|
||
<security-role>
|
||
<description>portal administrators</description>
|
||
<role-name>PORTALADMIN</role-name>
|
||
</security-role>
|
||
<security-role>
|
||
<description>standard user</description>
|
||
<role-name>USER</role-name>
|
||
</security-role>
|
||
|
||
<!-- Security constraints -->
|
||
<security-constraint>
|
||
<web-resource-collection>
|
||
<web-resource-name>admin area</web-resource-name>
|
||
<url-pattern>/admin/*</url-pattern>
|
||
</web-resource-collection>
|
||
<auth-constraint>
|
||
<role-name>ADMIN</role-name>
|
||
</auth-constraint>
|
||
</security-constraint>
|
||
|
||
<security-constraint>
|
||
<web-resource-collection>
|
||
<web-resource-name>community area</web-resource-name>
|
||
<url-pattern>/community/*</url-pattern>
|
||
</web-resource-collection>
|
||
<auth-constraint>
|
||
<role-name>USER</role-name>
|
||
<role-name>PORTALADMIN</role-name>
|
||
<role-name>ADMIN</role-name>
|
||
</auth-constraint>
|
||
</security-constraint>
|
||
|
||
<security-constraint>
|
||
<web-resource-collection>
|
||
<web-resource-name>user administration area</web-resource-name>
|
||
<url-pattern>/userAdministration/*</url-pattern>
|
||
</web-resource-collection>
|
||
<auth-constraint>
|
||
<role-name>USER</role-name>
|
||
<role-name>PORTALADMIN</role-name>
|
||
<role-name>ADMIN</role-name>
|
||
</auth-constraint>
|
||
</security-constraint>
|
||
|
||
|
||
<security-constraint>
|
||
<web-resource-collection>
|
||
<web-resource-name>user functionalities</web-resource-name>
|
||
<url-pattern>/user.xhtml</url-pattern>
|
||
<url-pattern>/userlist.xhtml</url-pattern>
|
||
<url-pattern>/notImplemented.xhtml</url-pattern>
|
||
</web-resource-collection>
|
||
<auth-constraint>
|
||
<role-name>USER</role-name>
|
||
<role-name>PORTALADMIN</role-name>
|
||
<role-name>ADMIN</role-name>
|
||
</auth-constraint>
|
||
</security-constraint>
|
||
|
||
<security-constraint>
|
||
<web-resource-collection>
|
||
<web-resource-name>other functionalities</web-resource-name>
|
||
<url-pattern>/notImplemented.xhtml</url-pattern>
|
||
</web-resource-collection>
|
||
<auth-constraint>
|
||
<role-name>USER</role-name>
|
||
<role-name>PORTALADMIN</role-name>
|
||
<role-name>ADMIN</role-name>
|
||
</auth-constraint>
|
||
</security-constraint>
|
||
|
||
<login-config>
|
||
<auth-method>FORM</auth-method>
|
||
<realm-name>pse</realm-name>
|
||
<form-login-config>
|
||
<form-login-page>/login.xhtml</form-login-page>
|
||
<form-error-page>/login.xhtml</form-error-page>
|
||
<!-- <form-error-page>/loginerror.xhtml</form-error-page> -->
|
||
</form-login-config>
|
||
</login-config>
|
||
</web-app>
|
||
\end{minted}
|
||
\end{document} |