diff --git a/.wildfly-base/configuration/standalone-full.xml b/.wildfly-base/configuration/standalone-full.xml index a2d4ff1..3aa52d9 100644 --- a/.wildfly-base/configuration/standalone-full.xml +++ b/.wildfly-base/configuration/standalone-full.xml @@ -1,582 +1,583 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=${wildfly.h2.compatibility.mode:REGULAR} - h2 - - - - - org.h2.jdbcx.JdbcDataSource - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=${wildfly.h2.compatibility.mode:REGULAR} + h2 + + + + + org.h2.jdbcx.JdbcDataSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ${jboss.bind.address:127.0.0.1} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${jboss.bind.address:127.0.0.1} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/uebungen/uebung-4.tex b/docs/uebungen/uebung-4.tex new file mode 100644 index 0000000..be9a424 --- /dev/null +++ b/docs/uebungen/uebung-4.tex @@ -0,0 +1,105 @@ +\documentclass{uebung} + +\author{Linus Nagel} +\chapter{4} + +\begin{document} + +\maketitle + +\begin{exercises} + +\item \textbf{Welchen Zweck erfüllen SOAP-Web Services?} + +SOAP-Web Services stellen Geschäftslogik als Service für entfernte Aufrufe bereit. Sie ermöglichen eine programmiersprachen- und systemübergreifende Kommunikation, indem sie Methodenaufrufe über standardisierte XML-Dokumente (SOAP) abbilden. Die Kommunikation erfolgt in der Regel über HTTP, wodurch eine lose Kopplung und hohe Interoperabilität erreicht wird. + +\item \textbf{Wie wird ein SOAP-Webservice erstellt?} + +Ein SOAP-Webservice wird durch eine Klasse (POJO oder EJB) realisiert, die mit der Annotation \texttt{@WebService} versehen ist. Die Klasse muss \texttt{public} sein und einen parameterlosen Konstruktor besitzen. Nach dem Deployment generiert der Application Server automatisch eine WSDL-Datei und stellt den Service unter einer URL bereit. Beispiel: +\begin{minted}[breaklines]{java} +@WebService +public class HelloWorld { + public String getHello() { + return "Hello World"; + } +} +\end{minted} + +\item \textbf{Welchen Zweck erfüllt die WSDL-Datei?} + +Die WSDL (Web Service Definition Language) ist ein XML-basiertes Interface, das die verfügbaren Methoden, deren Parameter, Rückgabewerte, Exceptions, das verwendete Protokoll (Binding) und die konkrete Endpoint-URI eines Web Services beschreibt. Der Client kann daraus die nötigen Proxy-Klassen generieren. + +\item \textbf{Wie können die Clientklassen aus einer bestehenden WSDL-Datei generiert werden?} + +Mit dem Tool \texttt{wsimport} (ab Java 11 aus dem Projekt \texttt{jaxws-ri}) werden aus einer vorhandenen WSDL-Datei Java-Clientklassen generiert. Aufrufbeispiel: +\begin{verbatim} +wsimport.sh http://localhost:8080/Pfad/HelloWorld?wsdl +\end{verbatim} +Die erzeugten Klassen werden in eine JAR-Datei verpackt und dem Clientprojekt hinzugefügt. + +\item \textbf{Wie kann ein Fehler programmiersprachenunabhängig übertragen werden? Welche Maßnahmen sind dabei bei der Programmierung notwendig?} + +Fehler werden über das \texttt{soap:Fault}-Element im SOAP-Body übertragen. Es enthält \texttt{faultcode}, \texttt{faultstring} und \texttt{detail}. In Java wird standardmäßig eine \texttt{SOAPFaultException} geworfen. Für sprachunabhängige Fehler kann eine eigene, von \texttt{SOAPFaultException} abgeleitete Exception erstellt werden, die eine \texttt{SOAPFault} erhält. Auf Serverseite wird die Exception mit einer erzeugten \texttt{SOAPFault} geworfen. Dadurch wird der Fehler als standardisierte SOAP-Nachricht übertragen. + +\item \textbf{Wie muss eine Fachkonzeptklasse modifiziert werden, damit sie bei einem SOAP-Aufruf eine Fachkonzeptklasse übertragen werden kann?} + +Die Fachkonzeptklasse muss mit der JAXB-Annotation \texttt{@XmlRootElement} versehen werden. Dadurch wird sie in ein XML-Element umgewandelt und kann im SOAP-Nachrichtenbody transportiert werden. + +\item \textbf{Beschreiben Sie den REST-Architekturstil. Gehen Sie dabei auch auf den Begriff Ressource ein und beschreiben, wie eine Ressource aufgerufen werden kann.} + +REST (Representational State Transfer) ist ein Architekturstil, bei dem jede Information als \emph{Ressource} aufgefasst wird, die über eine eindeutige URI erreichbar ist. Ressourcen werden mit den HTTP-Methoden POST (anlegen), GET (abfragen), PUT (ändern) und DELETE (löschen) manipuliert. Der Server speichert nur den Zustand der Ressource, der Client verwaltet den Anwendungszustand. Eine Ressource kann mehrere Repräsentationen (z.B. HTML, XML, JSON) besitzen. Der Aufruf erfolgt durch Senden einer HTTP-Anfrage an die URI der Ressource mit der entsprechenden HTTP-Methode. + +\item \textbf{Wie wird im einfachsten Fall ein RESTful Web Service erstellt?} + +Eine POJO-Klasse wird mit \texttt{@Path} annotiert, die Methode mit einer HTTP-Methode wie \texttt{@GET}. Zusätzlich ist eine Konfigurationsklasse nötig, die von \texttt{jakarta.ws.rs.core.Application} abgeleitet und mit \texttt{@ApplicationPath} versehen wird. Beispiel: +\begin{minted}[breaklines]{java} +@Path("/hallo") +public class HalloWelt { + @GET + public String sagHallo() { + return "Hallo Welt"; + } +} +\end{minted} + +\item \textbf{Wie kann aus einem Response ein Objekt ausgelesen werden?} + +Über das \texttt{Response}-Objekt wird die Methode \texttt{readEntity(Class)} aufgerufen. Beispiel: +\begin{minted}[breaklines]{java} +String ergebnis = response.readEntity(String.class); +\end{minted} + +\item \textbf{Wie kann eine ID als URI-Parameter übergeben werden?} + +In der \texttt{@Path}-Annotation wird ein Platzhalter in geschweiften Klammern definiert (z.B. \texttt{@Path("/buch/\{id\}")}). Der Methodenparameter wird mit \texttt{@PathParam("{}id")} annotiert. Beispiel: +\begin{minted}[breaklines]{java} +@GET +@Path("/buch/{id}") +public String getBuch(@PathParam("id") int id) { ... } +\end{minted} + +\item \textbf{Was ist gemeint, wenn von Content-Negotiation gesprochen wird? Mit welchen Annotationen wird dies mit RESTful Web Services in Java realisiert?} + +Content-Negotiation bezeichnet die Auswahl der passenden Repräsentation einer Ressource basierend auf dem \texttt{Accept}-Header des Requests. In JAX-RS wird dies mit den Annotationen \texttt{@Produces} (für die Antwort) und \texttt{@Consumes} (für die Anfrage) realisiert. Als Attribut wird ein \texttt{MediaType} (z.B. \texttt{MediaType.APPLICATION\_JSON}) übergeben. + +\item \textbf{Durch welche Klasse kann der Response (StatusCode und Rückgabe) einer Klasse beeinflusst werden? Wie kann ein solches Objekt erstellt werden und wie wird der eigentliche Response generiert?} + +Die Klasse \texttt{jakarta.ws.rs.core.Response} ermöglicht die Kontrolle über HTTP-Statuscode, Header und Entität. Ein \texttt{Response}-Objekt wird über einen \texttt{ResponseBuilder} erzeugt, den man z.B. mit \texttt{Response.ok().build()} erhält. Beispiel: +\begin{minted}[breaklines]{java} +return Response.status(Response.Status.NOT_FOUND) + .entity("Nicht gefunden") + .type(MediaType.TEXT_PLAIN) + .build(); +\end{minted} + +\item \textbf{Erstellen Sie einen Restful Web Service, der eine Methode namens getTime() bereitstellt. Diese Methode soll die aktuelle Zeit des Servers unter der URI localhost:8080/projektname/time zurück liefern.} + +\noindent\textbf{TimeService.java} +\inputminted[breaklines]{java}{../../server/src/main/java/org/example/demo/uebung4/aufgabe13/TimeService.java} + +\noindent\textbf{ApplicationConfig.java} +\inputminted[breaklines]{java}{../../server/src/main/java/org/example/demo/uebung4/aufgabe13/ApplicationConfig.java} + +\end{exercises} + +\end{document} diff --git a/flake.nix b/flake.nix index ae3cb5a..cbd515c 100644 --- a/flake.nix +++ b/flake.nix @@ -90,6 +90,7 @@ "uebung-1" = mkUebungPdf 1 {}; "uebung-2" = mkUebungPdf 2 {}; "uebung-3" = mkUebungPdf 3 {}; + "uebung-4" = mkUebungPdf 4 {}; }; devShells.default = with pkgs; diff --git a/server/pom.xml b/server/pom.xml index 7571b6c..bba4c65 100755 --- a/server/pom.xml +++ b/server/pom.xml @@ -8,7 +8,7 @@ ../pom.xml ejb-server - ejb + war jakarta.enterprise diff --git a/server/src/main/java/org/example/demo/uebung4/aufgabe13/ApplicationConfig.java b/server/src/main/java/org/example/demo/uebung4/aufgabe13/ApplicationConfig.java new file mode 100644 index 0000000..1631ca9 --- /dev/null +++ b/server/src/main/java/org/example/demo/uebung4/aufgabe13/ApplicationConfig.java @@ -0,0 +1,8 @@ +package org.example.webservice; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; + +@ApplicationPath("/") +public class ApplicationConfig extends Application { +} diff --git a/server/src/main/java/org/example/demo/uebung4/aufgabe13/TimeService.java b/server/src/main/java/org/example/demo/uebung4/aufgabe13/TimeService.java new file mode 100644 index 0000000..50edfae --- /dev/null +++ b/server/src/main/java/org/example/demo/uebung4/aufgabe13/TimeService.java @@ -0,0 +1,17 @@ +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +@Path("/time") +public class TimeService { + @GET + @Produces(MediaType.TEXT_PLAIN) + public String getTime() { + LocalDateTime now = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss"); + return "Aktuelle Serverzeit: " + now.format(formatter); + } +}