Sonntag, 8. Dezember 2013

AppFuse - what's inside

Im vorigen Post wurde die AppFuse-MultiMode-WebApp aufgesetzt und gestartet. Hier soll es darum gehen, wie diese Anwendung im Detail aussieht und welche Möglichkeiten out-of-the-box geboten werden. Am Ende des Artikels schaue ich mir auch noch an, wie und womit AppFuse umgesetzt wurde. Im nächsten Post folgt dann eine eigene Erweiterung der Applikation.

Den Login-Screen habe ich ja bereits im letzten Post gezeigt. Somit haben wir schon einmal eine Authentifizierung. Vorgeleistet sind bereits die beiden Accounts "user/user" und "admin/admin". Das lässt hoffen, das auch eine Autorisierung bereits integriert ist. Also melde ich mich erst einmal als "user" an.



Das Hauptmenü bietet die Möglichkeiten sein eigenes Profil zu bearbeiten, eine Datei hochzuladen und eine Ajax4JSF-Demo. Jetzt schaue ich mir das mal als "admin" an.



Zusätzlich zum den bereits bekannten Menüpunkten wird jetzt noch eine Administration angeboten. Darin enthalten ist eine funktionsfähige Nutzerverwaltung zum Benutzer hinzufügen, löschen oder sperren.



Was ich persönlich noch vermisse ist eine Verwaltung der Rollen. Aber das ist schon ein wenig viel verlangt. Dafür wird auf der Login-Seite ein Link angeboten, der mir den Hinweis zu meinem vergessenen Passwort zusendet. Das ist schon mal mehr, als ich in meiner letzten Software implementiert hatte. Darüber hinaus kann ich mich selbst registrieren.



Wahrscheinlich wurde auch versucht, mich per eMail über meine Registrierung zu informieren. Aber da ich nach wie vor keinen SMTP-Server aufgesetzt habe ging das schief. Auch die versendete eMail kann ich somit erst einmal nicht zeigen. Nichts desto trotz bin ich automatisch als der neue Nutzer angemeldet (siehe links unten auf dem Bild). Und natürlich habe ich die Möglichkeit, mich wieder abzumelden.

Aber AppFuse liefert nicht nur die reine Web-GUI sondern gleich eine komplette Web-Service Schnittstelle mit. Und das gleich in den Ausprägungen SOAP und REST. Man muss einfach nur die URL "http://localhost:8080/services/" aufrufen und bekommt die verfügbaren Dienste angezeigt.



Also gleich mal einen Test gemacht und die Url "http://localhost:8080/services/api/users.json" aufgerufen. An statt die Daten zu sehen, werde ich auf die Login-Seite weitergeleitet. Also sind die Web-Services auch gleich gesichert. Mein erster Versuch war mit dem user-Account. Ich erhielt eine Fehlermeldung, dass diese Seite nicht verfügbar ist. Mit dem admin-Account hingegegen kamen sofort folgende Daten:

[{"username":"admin","email":"matt@raibledesigns.com","roles":[{"name":"ROLE_ADMIN","id":-1,"authority":"ROLE_ADMIN","description":"Administrator role (can edit Users)"}],"confirmPassword":null,"passwordHint":"Not a female kitty.","firstName":"Matt","lastName":"Raible","phoneNumber":"","website":"http://raibledesigns.com","roleList":[{"value":"ROLE_ADMIN","label":"ROLE_ADMIN"}],"authorities":[{"name":"ROLE_ADMIN","id":-1,"authority":"ROLE_ADMIN","description":"Administrator role (can edit Users)"}],"accountExpired":false,"accountNonExpired":true,"accountLocked":false,"accountNonLocked":true,"credentialsExpired":false,"credentialsNonExpired":true,"address":{"city":"Denver","province":"CO","postalCode":"80210","address":"","country":"US"},"id":-2,"enabled":true,"fullName":"Matt Raible","version":1,"password":"a40546cc4fd6a12572828bb803380888ad1bfdab"},{"username":"user","email":"matt_raible@yahoo.com","roles":[{"name":"ROLE_USER","id":-2,"authority":"ROLE_USER","description":"Default role for all Users"}],"confirmPassword":null,"passwordHint":"A male kitty.","firstName":"Tomcat","lastName":"User","phoneNumber":"","website":"http://tomcat.apache.org","roleList":[{"value":"ROLE_USER","label":"ROLE_USER"}],"authorities":[{"name":"ROLE_USER","id":-2,"authority":"ROLE_USER","description":"Default role for all Users"}],"accountExpired":false,"accountNonExpired":true,"accountLocked":false,"accountNonLocked":true,"credentialsExpired":false,"credentialsNonExpired":true,"address":{"city":"Denver","province":"CO","postalCode":"80210","address":"","country":"US"},"id":-1,"enabled":true,"fullName":"Tomcat User","version":1,"password":"b6b1f4781776979c0775c71ebdd8bdc084aac5fe"}]


Und wie machen die das jetzt? Zuerst habe ich mir das Web-Modul angeschaut. Da ich JSF als Framework ausgewählt hatte, war ich ein wenig überrascht, JSPs vorzufinden. Die Index-Seite, alle Fehlerseiten und auch die Login- sowie die Logout-Seiten sind als JSPs realisiert. Erst die nachfolgende Logik, z.B. die Registrierung, ist in JSF umgesetzt.

#> cd web/src/main/webapp
#> ls
403.jsp         common             images      mainMenu.xhtml    signup.xhtml
404.jsp         decorators         index.jsp   scripts           styles
admin           editProfile.xhtml  login.jsp   selectFile.xhtml  userForm.xhtml
ajax4jsf.xhtml  error.jsp          logout.jsp  showFile.xhtml    WEB-INF


Das gesamte Seitenlayout erfolgt über Sitemesh, wobei die Layoutdefinition in der Datei "decorators/default.jsp" stattfindet. Sitemesh selbst ist als Filter in der "web.xml" eingetragen. Die Konfiguration der zu verwendenden Layoutdefinition erfolgt in der Datei "decorators.xml" im Verzeichnis "WEB-INF".

Was sich mir noch nicht erschlossen hat, wozu auch noch die Template-Engine Velocity eingesetzt wird. Es gibt Templates für das Menü und für die eMail, also kann ich mir schon denken, wo der Einsatz erfolgt. Aber ist es sinnvoll zwei verschiedene Template-Engines in einem Projekt zu haben? Oder hat wirklich jede der Engines seine spezifischen Vorteile?

Jetzt zu JSF - interessanterweise befinden sich die Managed Beans im Verzeichnis "actions". Da fühle ich mich doch ein wenig in die "guten alten" Struts-Zeiten zurückversetzt. Weiterhin erfolgt die Zuordnung der Managed Beans zu den XHTML-Dateien noch nicht über Annotations, sondern klassisch über die "faces-config.xml" im Ordner "WEB-INF".

#> cd app/web/src/main/java/org/test/webapp/action
#> ls
ActiveUserList.java  FileUpload.java    SignupForm.java
BasePage.java        PasswordHint.java  UserForm.java
CountryModel.java    Reload.java        UserList.java


Überrascht hat mich die Wahl des Komponentenframeworks. Statt auf etablierte Größen wie PrimeFaces, IceFaces oder RichFaces zu setzen, wird eine Kombination aus Apache Tomahawk, jQuery und Twitter Bootstrap gesetzt. Da sich Bootstrap und jQuery von Hause aus aber nicht so richtig verstehen, wurde das Framework jQuery UI Bootstrap eingesetzt. Was diese Wahl letztendlich für Konsequenzen hat, kann ich auf die Schnelle nicht einschätzen. Vielleicht zeigt sich das ja in der kommenden Erweiterung.

Zur Authentifizierung und Autorisierung nutzt AppFuse das form-based Login des Spring Security Frameworks. Damit wird ebenso das Logout und die RememberMe-Funktionalität realisiert. Die Konfiguration erfolgt in der "security.xml" im WEB-INF-Verzeichnis.

Erwähnenswert finde ich auch das Vorhandensein einer Konfiguration für ehcache in der WebApp. Ob und wofür dieser Cache zum Einsatz kommt, werde ich später untersuchen. Ehcache bietet ja über den Second Level Cache hinaus die Möglichkeit des Cachens von security credentials und web pages.

Womit wir in der Core-App wären. Denn der verwendete JPA-Provider Hibernate ist in der Datei "applicationContext-dao.xml" mit ehcache als Second Level Cache konfiguriert.



Damit ist schon gesagt, dass als Persitence-Framework JPA zum Einsatz kommt. Es soll aber einfach möglich sein, dieses z.B. durch Ibatis auszutauschen. Mitgeliefert wird ein GenericDao, so dass für die allgemeinen CRUD-Methoden kein zusätzlicher Aufwand mehr anfällt.

Das entity model besteht aus Pojos, die mit JPA-Annotationen versehen sind. Spannender ist das Package "service". Darin enthalten sind sowohl Service- als auch Manager-Interfaces. Die Manager dienen der direkten Kommunikation mit dem Web-Frontent und die Services definieren die jeweilige WebService-Schnittstelle. Die Implementierungen sind mittels Annotation als Spring-Service ausgewiesen. Der UserManger implementiert das Manager- und das Service-Interface:



Als WebService-Framework wird Apache CXF eingesetzt. Und das soll es als erster Einblick in die Techniken von AppFuse gewesen sein. Im nächsten Post schaue ich mir an, wie einfach oder wie aufwändig sich eine eigene Erweiterung der Appfuse-Applikation gestaltet.

Keine Kommentare:

Kommentar veröffentlichen