{"id":206,"date":"2015-01-23T13:37:51","date_gmt":"2015-01-23T12:37:51","guid":{"rendered":"http:\/\/blog.thecodecampus.de\/?p=206"},"modified":"2025-04-22T10:46:05","modified_gmt":"2025-04-22T08:46:05","slug":"pimp-my-legacy-webapp-integration-von-angularjs-und-struts1","status":"publish","type":"post","link":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/","title":{"rendered":"Pimp my Legacy Webapp! Integration von AngularJS und Struts1"},"content":{"rendered":"<div id=\"c5333\" class=\"csc-default\">\n<div class=\"csc-textpic csc-textpic-intext-left csc-textpic-caption-l\">\n<div class=\"csc-textpic-text\">\n<p><b>Im privaten Umfeld und im Gesch\u00e4ftsalltag verbreiten sich moderne Webtechnologien immer rasanter. Bei der Wartung alter Webanwendungen, sprich \u201eLegacy Webapps\u201c ger\u00e4t man deshalb unter den Druck, \u00e4hnliche Features sowie eine m\u00f6glichst komfortable Benutzerf\u00fchrung bereitzustellen. Dies ist jedoch mit den vorhandenen Technologien gar nicht oder nur mit sehr hohem Aufwand m\u00f6glich. Um die gew\u00fcnschten Anforderungen umzusetzen, ist daher die Integration moderner JavaScript Frameworks in Legacy Webapps unumg\u00e4nglich.<\/b><\/p>\n<p>Nach der Lekt\u00fcre dieses Artikels sollten Ihnen die wichtigsten Unterschiede von Legacy Webapps und modernen JavaScript Apps klar sein, damit auch Sie ihre Legacy Webapps mit AngularJS pimpen k\u00f6nnen!<\/p>\n<h3>Warum nicht einfach jQuery verwenden?<\/h3>\n<p>jQuery ist nun seit einigen Jahren eines der beliebtesten JavaScript-Frameworks am Markt. Im Vergleich zu purem JavaScript bietet es auch bahnbrechende Neuerungen und steigert die Entwicklungsgeschwindigkeit enorm. jQuery in eine bestehende Webanwendung zu integrieren ist sehr einfach m\u00f6glich, da einfach die ben\u00f6tigte jQuery-Bibliothek in den HTML-Code eingebunden werden muss. Die Architektur der Anwendung wird dadurch nicht beeinflusst. Die leichte Integration kommt daher, dass jQuery nur auf dem bestehenden HTML-Code arbeitet und gezielt DOM-Elemente manipuliert. Zumeist werden hier nur optische Anpassungen an bestehenden HTML-Seiten gemacht. Ein Beispiel sind die UI-Elemente von jQuery UI, mit denen sich sch\u00f6ne Dialoge und andere UI-Komponenten darstellen lassen. Die Steigerung der Benutzerfreundlichkeit kann mit jQuery sehr gut verbessert werden; die Entwicklungsgeschwindigkeit erh\u00f6ht sich allerdings noch in unbefriedigendem Umfang.<\/p>\n<h3>JavaScript-MVC-Frameworks<\/h3>\n<p>Gro\u00dfe Geschwindigkeitsvorteile bei der Entwicklung ergeben sich hingegen, wenn man eines der in den letzten Jahren immer popul\u00e4rer werdenden JavaScript-MVC-Frameworks einsetzt. Der prominenteste Vertreter dieser Gattung ist das von Google entwickelte AngularJS. Die Suchanfragen bei Google sind f\u00fcr AngularJS im Vergleich zu den konkurrierenden Frameworks deutlich h\u00f6her <a class=\"internal-link\" href=\"https:\/\/bit.ly\/1s1i3EW\" target=\"_blank\" rel=\"noopener noreferrer\">[1]<\/a>. Im Rahmen der \u00dcbersichtlichkeit wird hier auf einen Vergleich der konkurrierenden Frameworks verzichtet. Eine gute \u00dcbersicht findet sich aber auf der Webseite TodoMVC <a class=\"internal-link\" href=\"https:\/\/todomvc.com\/\">[2]<\/a>.<\/p>\n<p>Das MVC-Prinzip ist ein alter Bekannter in der Softwareentwicklung und fand bisher haupts\u00e4chlich in der Rich-Client-Entwicklung Verwendung. Die \u00dcbertragung des MVC-Prinzips auf die Webentwicklung kommt jedoch einer kleinen Revolution gleich. Denn im Vergleich zu Frameworks wie jQuery, f\u00fchren MVC-Frameworks aufgrund ihres h\u00f6heren Abstraktionsniveaus zu deutlich h\u00f6herer Entwicklungsgeschwindigkeit und besserer Codequalit\u00e4t. Aufgrund der klaren Trennung zwischen Model, View und Controller lassen sich zudem deutlich besser testbare Anwendungen erstellen.<\/p>\n<h2>Was ist AngularJs?<\/h2>\n<p>In AngularJS werden mit HTML-Code deklarativ die Oberfl\u00e4chen gestaltet. Ein wichtiger Aspekt ist, dass Anwendungslogik nur in den JavaScript-Dateien definiert wird. Dieser sollte weitm\u00f6glichst unabh\u00e4ngig von der Oberfl\u00e4che sein. Im Gegensatz zu manch anderen MVC-Frameworks erweitert AngularJS den HTML-Code aber nur, anstatt ihn zu abstrahieren.<\/p>\n<p>Um einen Bereich einer HTML-Seite von AngularJS verwalten zu lassen, muss dieser von einem Element mit dem Attribut \u201eng-app\u201c umschlossen sein. Nach dem Laden der Seite sucht AngularJS nach dem Atrribut \u201eng-app\u201c und analysiert den davon umschlossenen Bereich.<\/p>\n<p>\u201eController\u201c werden in AngularJS mit dem Attribut \u201eng-controller\u201c definiert. Controller und View kommunizieren \u00fcber den \u201eScope\u201c, einen Container auf dessen Inhalt von beiden Seiten aus zugegriffen werden kann. Mit der \u201e{{}}\u201c Notation kann mittels einem One-Way-Binding im HTML auf Elemente des \u201eScope\u201c zugegriffen werden. Die Daten k\u00f6nnen angezeigt, aber nicht zur\u00fcckgeschrieben werden. Two-Way-Bindings erm\u00f6glichen auch das Schreiben in den \u201eScope\u201c und k\u00f6nnen logischerweise nur an HTML-Input-Elementen verwendet werden.<\/p>\n<p>Die Beispiele in Listing 1 und Listing 2 zeigen eine simple AngularJS-Anwendung. In Listing 1 sehen wir die Definition der App \u201emyModule\u201c und des Controllers \u201eMyCtrl\u201c. In Zeile 2 wird dann \u00fcber ein One-Way-Bindung die L\u00e4nge der im \u201eScope&#8221; definierten Liste \u201elist\u201c ausgegeben. Danach folgt in den Zeilen 3-8 mit der AngularJS-Anweisung \u201eng-repeat\u201c die Iteration \u00fcber alle Elemente der Liste \u201elist\u201c. Innerhalb jedes \u201e&lt;li&gt;\u201c Elementes wird der Inhalt der Property \u201etext\u201c jedes Listenelementes ausgegeben. In Zeile 5 als Two-Way-Bindung in einem Eingabefeld, in Zeile 6 als One-Way-Binding.<\/p>\n<p>Schon an diesem simplen Beispiel zeigt sich die Leichtigkeit von AngularJS. Der HTML Code ist einfach zu verstehen, enth\u00e4lt jedoch keine Logik. Durch das von AngularJS kontrollierte Binding \u00e4ndert sich die Anzeige in Zeile 6, sobald in Zeile 5 ein Wert ge\u00e4ndert wird. Der vergleichbare jQuery Code w\u00e4re deutlich l\u00e4nger!<\/p>\n<pre class=\"lang:xhtml decode:true\">&lt;body ng-app=\"myModule\" ng-controller=\"MyCtrl\"&gt;&lt;br&gt; \r\n  &lt;span&gt;{{list.length}} elements&lt;\/span&gt;&lt;br&gt; \r\n  &lt;ul&gt;&lt;br&gt; \r\n    &lt;li ng-repeat=\"element in list\"&gt;&lt;br&gt; \r\n      &lt;input type=\"text\" ng-model=\"element.text\"&gt;&lt;br&gt; \r\n      &lt;span&gt;{{element.text}}&lt;\/span&gt;&lt;br&gt; \r\n    &lt;\/li&gt;&lt;br&gt; \r\n  &lt;\/ul&gt;&lt;br&gt;\r\n&lt;\/body&gt;<\/pre>\n<p>Listing 1<\/p>\n<p>Listing 2 zeigt den zugeh\u00f6rigen Controller \u201eMyCtrl\u201c. Als Funktionsparameter wird in Zeile 2 von AngularJS der \u201eScope\u201c injiziert. Dies demonstriert wie simpel Dependency Injection in AngularJS ist. \u201eController\u201c sind aufgrund von Dependancy Injection sehr gut testbar, worauf bei der Entwicklung von AngularJS von Anfang an sehr gro\u00dfen Wert gelegt wurde. In Zeile 3-5 erfolgt dann eine Zuweisung einer Liste von Objekten an den \u201eScope\u201c<\/p>\n<pre>angular.module('myModule', [])\r\n.controller(\"MyCtrl\", <b>function<\/b>($scope) {\r\n\u00a0 $scope.list = [\r\n\u00a0\u00a0\u00a0 {text:'angluarjs'},\r\n\u00a0\u00a0\u00a0 {text:'jQuery'}];\r\n});<\/pre>\n<p>Listing 2<\/p>\n<h3>Auch zur Teilmigration?<\/h3>\n<p>Obwohl AngularJS eigentlich f\u00fcr Single-Page-Anwendungen gedacht ist, kann es auch f\u00fcr andere Zwecke \u201emissbraucht\u201c werden. Vielleicht will man im ersten Schritt ja nur einen kleinen Teil einer Webseite \u201eh\u00fcbscher\u201c machen. Mit AngularJS ist dies kein Problem, denn es werden ja nur die von einem Element mit dem Attribut \u201eng-app\u201c umschlossenen HTML-Elemente analysiert.<\/p>\n<p>Da AngularJS relativ leichtgewichtig ist und schnell initialisiert wird, kann man es auch zur Gestaltung der Oberfl\u00e4chen einer serverseitigen Webanwendung verwenden. Wenn der JavaScript Code in Dateien ausgelagert wurde, wird dieser gechached und kostet keine wertvolle Ladezeit. Die Initialisierung von AngularJS nach dem Seitenaufruf geschieht sehr schnell und kann quasi vernachl\u00e4ssigt werden.<\/p>\n<p><a href=\"https:\/\/www.thecodecampus.de\/schulungen\/angular\" style=\"display: inline-block;\">\n<picture><source srcset=\"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2025\/04\/schulungen-tcc_sascha_WP_big.png\" media=\"(min-width: 1024px)\"><source srcset=\"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2025\/04\/schulungen-tcc_sascha_WP_medium.png\" media=\"(min-width: 600px)\"><img decoding=\"async\" src=\"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2025\/04\/schulungen-tcc_sascha_WP_small.png\" alt=\"Angular Schulungen\" class=\"alignnone size-full wp-image-38\">\n<\/picture>\n<\/a><\/p>\n<\/div>\n<\/div>\n<div class=\"csc-textpic-clear\"><\/div>\n<\/div>\n<div id=\"c5336\" class=\"csc-default\">\n<h2>Architekturvergleich<\/h2>\n<div class=\"csc-textpic-text\">\n<h3>Architektur serverseitiger Webframeworks<\/h3>\n<p>Bei serverseitigen Webframeworks wie Struts und JSF, aber auch PHP befindet sich sehr viel Logik auf dem Server. Benutzeranfragen werden auf dem Server ausgewertet, dann werden mittels Templating Mechanismen, wie JSP, HTML-Seiten auf dem Server generiert und an den Client gesendet. Der Zustand jedes Benutzers befindet sich auf dem Server, was bei gro\u00dfen Nutzerzahlen eine Beeintr\u00e4chtigung der Performance ist. Aktuellere Frameworks wie JSF 2 bieten Support f\u00fcr AJAX Features, allerdings bleibt auch hier die Problematik der Skalierung auf gro\u00dfe Benutzerzahlen aufgrund des zustandsbehafteten Servers.<\/p>\n<h3>Architektur von Single Page JavaScript-Apps<\/h3>\n<p>Bei Single Page-Apps gibt es klassisch nur noch einen vollen Page-Request zum Server beim Laden der Webseite (die eigentlich schon eine Webanwendung ist). Alle anderen Aktionen sowie die Navigation werden komplett via JavaScript gesteuert, wodurch sich ein fl\u00fcssigeres, einer nativen Anwendung \u00e4hnliches, Benutzererlebnis ergibt. Moderne Browser beinhalten hoch performante JavaScript-Engines (z.B. V8 <a class=\"internal-link\" href=\"https:\/\/code.google.com\/p\/v8\/\">[3]<\/a> in Chrome). Daher bietet es sich an, Anwendungslogik in den Client, d.h. in den Browser zu verlagern. Dies spart Server-Ressourcen und erm\u00f6glicht hohe Benutzerzahlen mit vergleichsweiser geringer Hardwareausstattung des Servers.<\/p>\n<p>Single Page-Apps halten zumeist den Zustand der Anwendung im Client und arbeiten daher oft mit zustandslosen Servern, die als reine Datenlieferanten dienen. State-of-the-Art sind hierf\u00fcr aktuell REST <a class=\"internal-link\" href=\"https:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\" target=\"_blank\" rel=\"noopener noreferrer\">[4]<\/a> Schnittstellen.<\/p>\n<h2>Teilmigration einer Struts-Anwendung<\/h2>\n<p>Im Folgenden wird eine M\u00f6glichkeit der Teilmigration von Legacy-Anwendungen am Beispiel einer Struts1-Anwendung gezeigt. Struts1 war zu Beginn der 2000er ein popul\u00e4res Webframework im Java-Umfeld. Alle Erkenntnisse lassen sich aber auch auf andere serverseitige Webframeworks \u00fcbertragen.<\/p>\n<\/div>\n<\/div>\n<div id=\"c5337\" class=\"csc-default\">\n<div class=\"csc-textpic csc-textpic-intext-left\">\n<div class=\"csc-textpic-imagewrap\">\n<dl class=\"csc-textpic-image csc-textpic-firstcol csc-textpic-lastcol\">\n<dt><a href=\"https:\/\/blog.thecodecampus.de\/wp-content\/uploads\/2015\/01\/struts.png\"><img loading=\"lazy\" decoding=\"async\" class=\" size-medium wp-image-210 alignnone\" src=\"https:\/\/blog.thecodecampus.de\/wp-content\/uploads\/2015\/01\/struts-300x232.png\" alt=\"struts\" width=\"300\" height=\"232\" srcset=\"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2015\/01\/struts-300x232.png 300w, https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2015\/01\/struts.png 350w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/dt>\n<dd class=\"csc-textpic-caption\">Abb.1: Struts. \u00a9 Jan Blankenhorn<\/dd>\n<\/dl>\n<\/div>\n<div class=\"csc-textpic-text\">\n<p>Normalerweise liefert Struts1 auf eine Anfrage als Antwort eine fertig gerenderte HTML-Seite. Abb.1 zeigt vereinfacht den Ablauf eines Requests in Struts. Auf die Anfrage des Browsers wird im Server eine \u201eAction\u201c-Klasse aufgerufen, welche Daten von der Business-Schicht l\u00e4dt und diese in eine \u201eForm\u201c schreibt. Die Inhalte der \u201eForm\u201c werden von Struts dann via JSP in HTML-Seiten geschrieben und an den Client gesendet. Bei jedem neuen Request wird dieser Zyklus neu durchlaufen. Dadurch wird die Anwendung sehr schwerf\u00e4llig und es werden viele redundante Daten an den Client gesendet.<\/p>\n<div id=\"c5337\" class=\"csc-default\">\n<div class=\"csc-textpic csc-textpic-intext-left\">\n<div class=\"csc-textpic-text\">\n<h3>M\u00f6glichkeiten der Integration von AngularJS<\/h3>\n<p>Will man nun die Oberfl\u00e4che einer Legacy-Webapp zumindest teilweise durch AngularJS ersetzen, dann ist wie oben beschrieben, eine REST-artige Schnittstelle auf dem Server vorgesehen. Die technologisch sauberste L\u00f6sung w\u00e4re die komplette Umstellung der Client-Server-Kommunikation auf eine REST-Schnittstelle. Im Java Umfeld stehen daf\u00fcr verschiedene Frameworks, wie z.b. Jersey <a class=\"internal-link\" href=\"https:\/\/jersey.java.net\/\">[5]<\/a> zur Verf\u00fcgung. Die Umstellung von einem zustandsbehafteten Server auf eine zustandslose REST-Schnittstelle ist jedoch sehr zeitaufw\u00e4ndig, risikoreich und teuer.<\/p>\n<p>Ein alternativer Ansatz ist die Integration der AngularJS Client-Server-Kommunikation in die bestehende Architektur. In diesem Fall kann die Anwendung schrittweise nach AngularJS migriert werden. Der bestehende Business-Code kann ohne gr\u00f6\u00dferen Aufwand wiederverwendet werden. Dasselbe gilt auch f\u00fcr Features der bestehenden Anwendungsarchitektur. Bei Struts1-Anwendungen sind hier unter anderem Sicherheit und Validierung relevant. Ein kleiner Nachteil ist allerdings, dass der Zustand bei einer ersten Migration im Server bleibt.<\/p>\n<p>Dieser alternative Ansatz wurde in einer Struts1-Anwendung umgesetzt und steigerte die Benutzerzufriedenheit deutlich. Im Folgenden werden die wichtigsten Migrationsschritte erkl\u00e4rt. Um die Client-Server-Kommunikation von der Auslieferung der HTML- und Javascript-Dateien zu trennen, wird eine 2-Teilung der Kommunikation durchgef\u00fchrt. Auf die erste Anfrage des Browsers werden HTML-Dateien und JavaScript-Dateien zur\u00fcckgegeben. Die JavaScript-Anwendung l\u00e4dt dann die ben\u00f6tigten Daten vom Server \u00fcber dieselbe URL nach.<\/p>\n<\/div>\n<\/div>\n<div class=\"csc-textpic-clear\"><\/div>\n<\/div>\n<div id=\"c5338\" class=\"csc-default\">\n<pre class=\"lang:java decode:true\">@Override\r\npublic ActionForward execute(final ActionMapping mapping, final ActionForm form, final HttpServletRequest request, final HttpServletResponse response) throws Exception {  \r\n    final String acceptType = request.getHeader(\"Accept\"); \r\n    final boolean jsonRequest = acceptType.startsWith(\"application\/json\");  \r\n\r\n    if (false == jsonRequest) {  \r\n        return mapping.findForward(\"template\");  \r\n    } else { \r\n        final String json = buildData(request, response, form);  \r\n        request.setAttribute(\"jsonResponse\", json); \r\n        return mapping.findForward(\"jsonResponse\");  \r\n    }\r\n}<\/pre>\n<p>Listing 3<\/p>\n<p>Wie im Listing1 zu sehen, wird in der \u201eexecute()<i><\/i>\u201c Methode der Action eine Unterscheidung gemacht, ob die Anfrage eine \u201enormale\u201c Struts-Anfrage ist oder ob nur Daten f\u00fcr die AngularJS-Anwendung geladen werden sollen. Um dies zu erm\u00f6glichen, nutzen wir aus, dass AngularJS bei der Anfrage automatisch den HTTP-Header Accept: application\/json <a class=\"internal-link\" href=\"https:\/\/docs.angularjs.org\/api\/ng\/service\/$http\" target=\"_blank\" rel=\"noopener noreferrer\">[6]<\/a> mitsendet.<\/p>\n<p>Bei der initialen Anfrage des Browsers (z.B. \/show.do) wird, wie in der alten Anwendung ein HTML-Template mit zugeh\u00f6rigen JS-Dateien zum Client gesendet. In Listing 3 wird daf\u00fcr das Mapping \u201etemplate\u201c aufgerufen, welches alle ben\u00f6tigten Daten enth\u00e4lt. Wie dies im Detail von Struts gemacht wird, w\u00fcrde den Rahmen des Artikels sprengen und wird hier nicht erl\u00e4utert.<\/p>\n<pre>$http({method: 'GET', url: '\/show.do'}).\r\n\u00a0 success(<b>function<\/b>(data, status, headers, config) {\r\n\u00a0\u00a0\u00a0 $scope.data = data;\r\n\u00a0 });<\/pre>\n<p>Listing 4<\/p>\n<p>Nachdem das Template im Browser geladen wurde, wird dort die JavaScript-Anwendung initialisiert. Diese verwendet den AngularJS-Service $http zur Kommunikation zum Server und ruft wiederum dieselbe Adresse \u201eshow.do\u201c auf (s. Listing 4).<\/p>\n<pre class=\"lang:java decode:true \">&lt;%@ page contentType=\"application\/json; charset=UTF-8\" pageEncoding=\"UTF-8\"%&gt;\r\n${jsonResponse}<\/pre>\n<p>Listing 5<\/p>\n<p>Daraufhin werden in der Action nun alle Daten aus der Datenbank geladen und mittels dem Framework Gson <a class=\"internal-link\" href=\"https:\/\/code.google.com\/p\/google-gson\/\" target=\"_blank\" rel=\"noopener noreferrer\">[7]<\/a> in JSON-Daten konvertiert. Gson kann ganze Java-Objektb\u00e4ume in JSON-Strings serialisieren. Auch der Weg zur\u00fcck funktioniert zuverl\u00e4ssig.<\/p>\n<p>Die serialisierten JSON-Daten k\u00f6nnen nun als Antwort an den Client gesendet und dort auch weiterverarbeitet werden. Daf\u00fcr wird der JSON-String, wie in Listing 3 zu sehen, an das Attribut \u201ejsonResponse\u201c des HTTP-Requests gebunden und dann von Struts in das JSP-Template aus Listing 5 geschrieben. Das Resultat wird als Response an den Server gesendet und dort von AngularJS weiterverarbeitet.<\/p>\n<p>Gro\u00dfe Vorteile bringt diese Umstellung in Situationen, in denen nach dem initialen Laden der Templates und Daten nicht weiternavigiert wird. Im zugrundeliegenden Projekt wurden mit diesem Mechanismus alle Listenansichten migriert und mit m\u00e4chtigen Web 2.0-Features versehen. Die Listenansichten sind nun mit modernen Tabellen ausgestattet und haben unter anderem eine Volltextsuche, die dem Benutzer direkt nach dem Tippen ein Feedback liefert. Dieses und weitere Features w\u00e4ren mit Struts1 oder jQuery nur sehr viel schlechter und komplizierter umzusetzen gewesen.<\/p>\n<\/div>\n<div id=\"c5339\" class=\"csc-default\">\n<h2>Fazit<\/h2>\n<p>Um die Kosten im Griff zu behalten und die Benutzer von den M\u00f6glichkeiten der neuen Technologien zu \u00fcberzeugen, bietet sich eine Teilmigration von Legacy-Webapps an. Im ersten Schritt empfiehlt es sich, isolierte Ansichten, wie z.B. Listenansichten zu migrieren. Im n\u00e4chsten Schritt kann man AngularJS auch nur in Teilen von HTML-Seiten einsetzen, um z.B. nur die hier nicht beschriebenen Validierungsmechanismen von AngularJS zu verwenden. Der n\u00e4chste Schritt ist dann die Ersetzung der kompletten UI, wie hier im Artikel beschrieben. Wenn man dabei vorsichtig vorgeht, ist auch eine sp\u00e4tere Migration des Servers zu einer \u201eechten\u201c REST-Schnittstelle im letzten Schritt umsetzbar.<\/p>\n<p>Die hier beschriebene Vorgehensweise hat den Vorteil, dass man durch schrittweises Vorgehen den Kunden von den neuen Technologien und der gesteigerten Entwicklungsgeschwindigkeit \u00fcberzeugen kann. Bestehende Logik im Server kann weitgehend wiederverwendet werden und senkt die Risiken und den Aufwand.<\/p>\n<h3>Ausblick<\/h3>\n<p>In diesem Artikel wurde darauf verzichtet, das Speichern von Daten zu beschreiben. Prinzipiell ist dies aber analog zum Laden, da die JSON Serialisierung mit Gson in beide Richtungen funktioniert. Auch hier bieten sich verschiedene denkbare Architekturen an. Speziell bei Struts1 k\u00f6nnen bei der Teilmigration bestehende Validierungsregeln im Server wiederverwendet werden.<\/p>\n<p>Auch AngularJS konnte leider nur ganz grob umrissen werden. Konzepte wie \u201eServices\u201c und \u201eDirektiven\u201c bieten sch\u00f6ne M\u00f6glichkeiten zur Strukturierung von JavaScript-Anwendungen.<\/p>\n<p>Ein weiteres interessantes Thema ist die Migration von Flash-Anwendungen nach AngularJS. Hingewiesen werden kann hier auf die AngularJS-Direktive w11k-flash <a class=\"internal-link\" href=\"https:\/\/github.com\/w11k\/w11k-flash\">[8]<\/a>, welche zur Integration von AngularJS und Flash verwendet werden kann. Eine ausf\u00fchrliche Anleitung findet sich hier <a href=\"https:\/\/www.thecodecampus.de\/\" target=\"_blank\" rel=\"noopener noreferrer\">[9].<\/a><\/p>\n<hr \/>\n<\/div>\n<div id=\"c5335\" class=\"csc-default\">\n<p><b>Quellen<\/b><\/p>\n<p>[1] <a class=\"external-link-new-window\" title=\"Google Trends\" href=\"https:\/\/www.google.de\/trends\/explore#q=angularjs,%20knockoutjs,%20ember%20js,%20backbone.js&amp;date=9\/2010%2040m&amp;cmpt=q\" target=\"_blank\" rel=\"noopener noreferrer\">Google Trends<\/a><br \/>\n[2] <a class=\"external-link-new-window\" title=\"ToDoMVC\" href=\"https:\/\/todomvc.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">TodoMVC<\/a><br \/>\n[3] <a class=\"external-link-new-window\" title=\"V8 JavaScript Engine\" href=\"https:\/\/code.google.com\/p\/v8\/\" target=\"_blank\" rel=\"noopener noreferrer\">V8 JavaScript Engine<\/a><br \/>\n[4] <a title=\"external-link-new-window\" href=\"https:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">Wikipedia<\/a><br \/>\n[5] <a class=\"external-link-new-window\" title=\"Jersey.java.net\" href=\"https:\/\/jersey.java.net\/\" target=\"_blank\" rel=\"noopener noreferrer\">Jersey.java.net<\/a><br \/>\n[6] <a class=\"external-link-new-window\" title=\"AngularJS.org\" href=\"https:\/\/docs.angularjs.org\/api\/ng\/service\/$http\" target=\"_blank\" rel=\"noopener noreferrer\">AngularJS.org<\/a><br \/>\n[7] <a class=\"external-link-new-window\" title=\"google.gson\" href=\"https:\/\/code.google.com\/p\/google-gson\/\" target=\"_blank\" rel=\"noopener noreferrer\">google.gson<\/a><br \/>\n[8] <a class=\"external-link-new-window\" title=\"GitHub\" href=\"https:\/\/github.com\/w11k\/w11k-flash\" target=\"_blank\" rel=\"noopener noreferrer\">GitHub<\/a><br \/>\n[9] <a class=\"external-link-new-window\" title=\"thecodecampus\" href=\"https:\/\/www.thecodecampus.de\/\" target=\"_blank\" rel=\"noopener noreferrer\">thecodecampus<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Im privaten Umfeld und im Gesch\u00e4ftsalltag verbreiten sich moderne Webtechnologien immer rasanter. Bei der Wartung alter Webanwendungen, sprich \u201eLegacy Webapps\u201c ger\u00e4t man deshalb unter den Druck, \u00e4hnliche Features sowie eine m\u00f6glichst komfortable Benutzerf\u00fchrung bereitzustellen. Dies ist jedoch mit den vorhandenen Technologien gar nicht oder nur mit sehr hohem Aufwand m\u00f6glich. Um die gew\u00fcnschten Anforderungen umzusetzen, [&#8230;]<br \/><a class=\"meta-big\" href=\"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/\"> READ MORE<\/a><\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[62,85,39,61,40],"class_list":["post-206","post","type-post","status-publish","format-standard","hentry","category-angularjs","tag-angularjs","tag-german","tag-java","tag-javascript","tag-legacy"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Pimp my Legacy Webapp! Integration von AngularJS und Struts1 - Web Development Blog<\/title>\n<meta name=\"description\" content=\"Revitalize your legacy web app! Pimp it with seamless integration of AngularJS and Struts 1. Upgrade user experience effortlessly.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Pimp my Legacy Webapp! Integration von AngularJS und Struts1 - Web Development Blog\" \/>\n<meta property=\"og:description\" content=\"Revitalize your legacy web app! Pimp it with seamless integration of AngularJS and Struts 1. Upgrade user experience effortlessly.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Development tips and tricks - theCodeCampus Blog\" \/>\n<meta property=\"article:published_time\" content=\"2015-01-23T12:37:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-22T08:46:05+00:00\" \/>\n<meta name=\"author\" content=\"Jan Blankenhorn\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jan Blankenhorn\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/\"},\"author\":{\"name\":\"Jan Blankenhorn\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#\\\/schema\\\/person\\\/623acdcedf59e3d9d86df17721a46188\"},\"headline\":\"Pimp my Legacy Webapp! Integration von AngularJS und Struts1\",\"datePublished\":\"2015-01-23T12:37:51+00:00\",\"dateModified\":\"2025-04-22T08:46:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/\"},\"wordCount\":2025,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/schulungen-tcc_sascha_WP_small.png\",\"keywords\":[\"AngularJS\",\"German\",\"Java\",\"JavaScript\",\"Legacy\"],\"articleSection\":[\"AngularJS 1\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/\",\"name\":\"Pimp my Legacy Webapp! Integration von AngularJS und Struts1 - Web Development Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/schulungen-tcc_sascha_WP_small.png\",\"datePublished\":\"2015-01-23T12:37:51+00:00\",\"dateModified\":\"2025-04-22T08:46:05+00:00\",\"description\":\"Revitalize your legacy web app! Pimp it with seamless integration of AngularJS and Struts 1. Upgrade user experience effortlessly.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/schulungen-tcc_sascha_WP_small.png\",\"contentUrl\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/04\\\/schulungen-tcc_sascha_WP_small.png\",\"width\":720,\"height\":400},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Pimp my Legacy Webapp! Integration von AngularJS und Struts1\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/\",\"name\":\"Web Development tips and tricks - theCodeCampus Blog\",\"description\":\"Tips, tricks, and experiences about developing web and mobile applications with Angular, TypeScript, and Testing.\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#organization\",\"name\":\"theCodeCampus\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/TCC-Logo-Bildmarke-quadratisch.jpg\",\"contentUrl\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/TCC-Logo-Bildmarke-quadratisch.jpg\",\"width\":156,\"height\":156,\"caption\":\"theCodeCampus\"},\"image\":{\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/#\\\/schema\\\/person\\\/623acdcedf59e3d9d86df17721a46188\",\"name\":\"Jan Blankenhorn\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/jan-blankenhorn-tcc-author-96x96.webp\",\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/jan-blankenhorn-tcc-author-96x96.webp\",\"contentUrl\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/06\\\/jan-blankenhorn-tcc-author-96x96.webp\",\"caption\":\"Jan Blankenhorn\"},\"description\":\"Jan Blankenhorn brings over 15 years of experience as a developer and trainer, specializing in web development with Angular. He enjoys engaging with people and shares practical examples in his training sessions with a touch of humor.\",\"sameAs\":[\"https:\\\/\\\/thecodecampus.de\\\/ueber-uns\\\/trainer\\\/jan-blankenhorn\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/jan-blankenhorn-w11k\\\/\"],\"url\":\"https:\\\/\\\/www.thecodecampus.de\\\/blog\\\/author\\\/jblankenhorn\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Pimp my Legacy Webapp! Integration von AngularJS und Struts1 - Web Development Blog","description":"Revitalize your legacy web app! Pimp it with seamless integration of AngularJS and Struts 1. Upgrade user experience effortlessly.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/","og_locale":"en_US","og_type":"article","og_title":"Pimp my Legacy Webapp! Integration von AngularJS und Struts1 - Web Development Blog","og_description":"Revitalize your legacy web app! Pimp it with seamless integration of AngularJS and Struts 1. Upgrade user experience effortlessly.","og_url":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/","og_site_name":"Web Development tips and tricks - theCodeCampus Blog","article_published_time":"2015-01-23T12:37:51+00:00","article_modified_time":"2025-04-22T08:46:05+00:00","author":"Jan Blankenhorn","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Jan Blankenhorn","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/#article","isPartOf":{"@id":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/"},"author":{"name":"Jan Blankenhorn","@id":"https:\/\/www.thecodecampus.de\/blog\/#\/schema\/person\/623acdcedf59e3d9d86df17721a46188"},"headline":"Pimp my Legacy Webapp! Integration von AngularJS und Struts1","datePublished":"2015-01-23T12:37:51+00:00","dateModified":"2025-04-22T08:46:05+00:00","mainEntityOfPage":{"@id":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/"},"wordCount":2025,"commentCount":0,"publisher":{"@id":"https:\/\/www.thecodecampus.de\/blog\/#organization"},"image":{"@id":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/#primaryimage"},"thumbnailUrl":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2025\/04\/schulungen-tcc_sascha_WP_small.png","keywords":["AngularJS","German","Java","JavaScript","Legacy"],"articleSection":["AngularJS 1"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/","url":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/","name":"Pimp my Legacy Webapp! Integration von AngularJS und Struts1 - Web Development Blog","isPartOf":{"@id":"https:\/\/www.thecodecampus.de\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/#primaryimage"},"image":{"@id":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/#primaryimage"},"thumbnailUrl":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2025\/04\/schulungen-tcc_sascha_WP_small.png","datePublished":"2015-01-23T12:37:51+00:00","dateModified":"2025-04-22T08:46:05+00:00","description":"Revitalize your legacy web app! Pimp it with seamless integration of AngularJS and Struts 1. Upgrade user experience effortlessly.","breadcrumb":{"@id":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/#primaryimage","url":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2025\/04\/schulungen-tcc_sascha_WP_small.png","contentUrl":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2025\/04\/schulungen-tcc_sascha_WP_small.png","width":720,"height":400},{"@type":"BreadcrumbList","@id":"https:\/\/www.thecodecampus.de\/blog\/pimp-my-legacy-webapp-integration-von-angularjs-und-struts1\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.thecodecampus.de\/blog\/"},{"@type":"ListItem","position":2,"name":"Pimp my Legacy Webapp! Integration von AngularJS und Struts1"}]},{"@type":"WebSite","@id":"https:\/\/www.thecodecampus.de\/blog\/#website","url":"https:\/\/www.thecodecampus.de\/blog\/","name":"Web Development tips and tricks - theCodeCampus Blog","description":"Tips, tricks, and experiences about developing web and mobile applications with Angular, TypeScript, and Testing.","publisher":{"@id":"https:\/\/www.thecodecampus.de\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.thecodecampus.de\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.thecodecampus.de\/blog\/#organization","name":"theCodeCampus","url":"https:\/\/www.thecodecampus.de\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.thecodecampus.de\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2024\/01\/TCC-Logo-Bildmarke-quadratisch.jpg","contentUrl":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2024\/01\/TCC-Logo-Bildmarke-quadratisch.jpg","width":156,"height":156,"caption":"theCodeCampus"},"image":{"@id":"https:\/\/www.thecodecampus.de\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.thecodecampus.de\/blog\/#\/schema\/person\/623acdcedf59e3d9d86df17721a46188","name":"Jan Blankenhorn","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2024\/06\/jan-blankenhorn-tcc-author-96x96.webp","url":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2024\/06\/jan-blankenhorn-tcc-author-96x96.webp","contentUrl":"https:\/\/www.thecodecampus.de\/blog\/wp-content\/uploads\/2024\/06\/jan-blankenhorn-tcc-author-96x96.webp","caption":"Jan Blankenhorn"},"description":"Jan Blankenhorn brings over 15 years of experience as a developer and trainer, specializing in web development with Angular. He enjoys engaging with people and shares practical examples in his training sessions with a touch of humor.","sameAs":["https:\/\/thecodecampus.de\/ueber-uns\/trainer\/jan-blankenhorn","https:\/\/www.linkedin.com\/in\/jan-blankenhorn-w11k\/"],"url":"https:\/\/www.thecodecampus.de\/blog\/author\/jblankenhorn\/"}]}},"_links":{"self":[{"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/posts\/206","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/comments?post=206"}],"version-history":[{"count":21,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/posts\/206\/revisions"}],"predecessor-version":[{"id":3449,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/posts\/206\/revisions\/3449"}],"wp:attachment":[{"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/media?parent=206"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/categories?post=206"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.thecodecampus.de\/blog\/wp-json\/wp\/v2\/tags?post=206"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}