Kaum eine Metapher ist wichtiger für Softwareentwicklung als "technische Schulden". Aber sie hat leider einige Schwächen. Vor allem gehen Teams meistens die Schulden nicht bewusst ein.
Wie gut die Qualität des Codes einer Anwendung ist, können Benutzer oder Projektleiter kaum erkennen. Schließlich merken nur Entwickler, ob der Code besonders einfach geändert werden kann oder nicht. Leider ist das Spiel mit der Qualität aber gefährlich, denn schlechte Qualität bringt im Extremfall ein Projekt zum vollständigen Stillstand. Technische Schulden sollen als Metapher das Problem mit der Qualität besser vermittelbar machen. So können Benutzer oder Projektleiter besser verstehen, warum nicht jedes Feature schnell mal so implementiert werden sollte.
Wikipedia[1] beschreibt technische Schulden folgendermaßen: Ein Team, das in einem Softwareprojekt ohne besondere Rücksicht auf die Qualität Code sofort in Produktion bringt, liefert erst mal schneller. Dafür baut das Team aber Schulden auf. Genau wie bei Geldschulden müssen Zinsen gezahlt werden: Die Produktivität sinkt, denn die schlechte Codequalität hält das Team auf. Diese Beschreibung passt gut zu der Metapher: Wer einen Kredit aufnimmt, baut Schulden auf, um sich etwas schneller zu kaufen und muss die Schulden später mit Zinsen zurückzahlen.
Ursprünglich hat Ward Cunningham die Metapher der technischen Schulden aus der OOPSLA-Konferenz [2]1992 eingeführt. Er erklärt auf YouTube[3] den Begriff anders: Code repräsentiert immer das aktuelle Verständnis des durch die Software gelösten Problems. Wenn das Team Neues lernt, dann muss der Code durch Refactorings konsolidiert werden, sodass das Gelernte optimal repräsentiert ist. Wenn die Refactorings unterbleiben, entstehen technische Schulden und der Code ist schwieriger zu ändern. Cunningham schließt explizit aus, dass das Teams bei der Qualität Kompromisse macht und widerspricht damit eindeutig dem Wikipedia-Artikel. Das Team baut keine Schulden auf, sondern die Schulden entstehen unwillkürlich.
Martin Fowler hat eine andere Perspektive: Entweder das Projekt ist umsichtig (prudent) und trifft Entscheidungen über die Qualität oder es geht so rücksichtslos (reckless) vor, dass es die Qualität nicht beachtet. Außerdem geht das Team bewusst (deliberate) einen Qualitätskompromiss ein oder technische Schulden entstehen unbeabsichtigt (inadvertent). Aus den Eigenschaften umsichtig/ ücksichtlos auf der einen Seite und bewusst/unbeabsichtigt auf der anderen Seite entstehen vier Quadranten[4]. Der Wikipedia-Definition entspricht umsichtig/bewusst: Das Team kennt die Qualität (umsichtig) und trifft bewusst die Entscheidung, einen Qualitätskompromiss einzugehen. Cunninghams Erklärung ist umsichtig, weil das Team die Qualität kennt, aber die technischen Schulden entstehen nicht bewusst, sondern unbeabsichtigt, weil das Team lernt und der Code das Gelernte noch nicht abbildet.
Meiner Meinung nach gibt es noch eine weitere Quelle technischer Schulden: der technische Fortschritt. Neue Architekturen und Technologien machen das alte Vorgehen obsolet. Wenn der Code nicht passend aktualisiert wird, entstehen technische Schulden. Auch das ist unbeabsichtigt, weil es sich nicht verhindern lässt.
Das Wichtigste an technischen Schulden ist aber, wie man mit ihnen umgeht. Kein System ist perfekt. Es gibt immer etwas zu optimieren. Das bedeutet, dass Teams praktisch unbegrenzt optimieren können. Wenn das Team durch eine Optimierung keine Verbesserung der Produktivität erwartet, die mehr bringt, als die Optimierung an Aufwand kostet, dann sollte die Optimierung unterbleiben. Dafür können Investitionen[5] eine gute Metapher sein. Die Qualität ist kein Ziel an sich, sondern nur ein Mittel für bessere Produktivität. Auch bei diesem Vorgehen hat die Metapher der technischen Schulden einen Vorteil: Die Qualitätskompromisse können problematisch sein, weil sie für Benutzer oder Projektleiter nicht leicht zu erkennen sind und zum Stillstand des Projekts führen können. Der Begriff "technische Schulden" stellt genau das dar.
Technische Schulden sind eine Metapher für die Qualität in Softwareprojekten mit einigen Schwächen und unterschiedlichen Interpretationen. Am wichtigsten ist jedoch, wie Teams mit den technischen Schulden umgehen.
URL dieses Artikels:http://www.heise.de/-3969279
Links in diesem Artikel:[1] https://en.wikipedia.org/wiki/Technical_debt[2] http://c2.com/doc/oopsla92.html[3] https://www.youtube.com/watch?v=pqeJFYwnkjE[4] https://martinfowler.com/bliki/TechnicalDebtQuadrant.html[5] https://www.infoq.com/articles/no-more-technical-debt
Copyright © 2018 Heise Medien
YouTube ist schon lange keine reine Unterhaltungsplattform mehr. Es gibt inzwischen auch eine Vielzahl hochwertiger Inhalte über Java, Java EE und allgemeinere Softwareentwicklungsthemen.
Ich schaue inzwischen immer häufiger kurze Trainingsvideos oder auch ganze Konferenzvorträge auf YouTube. Es gibt keinen einfacheren und komfortableren Weg von den Besten unserer Branche zu lernen.
Hier sind, in ungeordneter Reihenfolge, ein paar Kanäle die mir in den letzten Monaten durch die regelmäßige Veröffentlichung qualitativ hochwertiger Videos aufgefallen sind:
Oracles YouTube Kanal dürfte vielen Java-Entwicklern bereits durch die aufgezeichneten Vorträge der JavaOne bekannt sein. Das Team veröffentlicht außerdem Vortragsmitschnitte des JVM Language Summit und Interviews mit bekannten Größen aus der Java-Community.
Adam zeigt in seinen Videos, wie einfach, effizient und leichtgewichtig die Entwicklung mit Java EE sein kann. In seiner sehr sehenswerten monatlichen Fragestunde beantwortet er außerdem die Fragen seiner Zuschauer und Leser.
Wenn du JPA oder Hibernate in deinen Projekten einsetzt, solltest du den "Thoughts on Java"-Kanal kennen. Hier veröffentliche ich jede Woche zwei neue Videos, in denen ich zeige, wie du deine Persistenzschicht einfach und effizient implementieren kannst.
Der offizielle Kanal der Devoxx veröffentlicht Vortragsmitschnitte der bekannten Devoxx- und Voxxed-Days-Konferenzen. Damit kannst du dir die besten Redner und interessantesten Vorträge direkt zu dir nach Hause holen.
Einfacher als bei der virtual Java User Group kann man nicht an einem JUG-Treffen teilnehmen. Mit regelmäßigen Livestreams, einer 24-stündigen Onlinekonferenz und einem Buchklub bietet der Kanal der vJUG jede Menge interessanter Inhalte.
Auf seinem Kanal veröffentlicht Sebastian sehr interessante Videos zu Java EE sowie zur Steigerung der Entwicklerproduktivität.
Das InfoQ-Team stellt auf seinem Kanal Vortragsmitschnitte zu verschiedenen Architektur- und Softwareentwicklungsthemen von den QCon-Konferenzen zur Verfügung.
Wer sich für Interviews und Diskussionspanels zu verschiedenen Java-Themen interessiert, findet auf dem NightHacking-Kanal viele sehenswerte Videos.
Die GOTO-Konferenzen zeichnen ebenfalls viele Vorträge auf und stellen diese auf ihrem YouTube-Kanal kostenlos zur Verfügung.
Der JetBrains-YouTube-Kanal bietet eine schöne Mischung aus Vortragsmitschnitten der KotlinConf, Webinaren zu verschiedenen Softwareentwicklungsthemen und Trainingsvideos zu ihren eigenen Entwicklungswerkzeugen.
Wer mit Spring arbeitet, sollte auch den Spring-Developer-Kanal kennen. Das Team von Pivotal veröffentlicht dort eine Vielzahl hochwertiger Konferenzvorträge, Webinare und Schulungsvideos.
Die brasilianische SouJava-Organisation bietet auf ihrem Kanal eine Mischung aus Interviews und Webinaren in englischer und portugiesischer Sprache.
URL dieses Artikels:http://www.heise.de/-3937979
Links in diesem Artikel:[1] https://www.youtube.com/user/java[2] https://www.youtube.com/user/bienadam[3] https://www.youtube.com/channel/UCYeDPubBiFCZXIOgGYoyADw[4] https://www.youtube.com/channel/UCCBVCTuk6uJrN3iFV_3vurg[5] https://www.youtube.com/user/virtualJUG[6] https://www.youtube.com/channel/UCG21GE2Go3vkj7mrs675ysA[7] https://www.youtube.com/user/MarakanaTechTV[8] https://www.youtube.com/channel/UCT0bL2CQIk1eANeXk57mxaA[9] https://www.youtube.com/user/GotoConferences[10] https://www.youtube.com/user/JetBrainsTV[11] https://www.youtube.com/user/SpringSourceDev[12] https://www.youtube.com/channel/UCH0qj1HFZ9jy0w87YfMSA7w
Copyright © 2018 Heise Medien
Microservices sind ein Hype. So dauert es nicht lange, bis sich die Kritiker melden und wieder zurück zu Monolithen wollen. Aber hilft das weiter?
Microservices teilen ein System in kleine, unabhängig deploybare Module auf. Die Alternative sind Deployment-Monolithen. Dann wird die gesamte Anwendung mit allen Modulen als Ganzes auf einmal deployt. Intern können Deployment-Monolithen aus Modulen wie Java-Packages, Namespaces oder Bibliotheken aufgebaut sein.
Aktuell ziehen Microservices Kritik auf sich, weil Microservice-System oft keine gute Struktur aufweisen. Aber Microservices definieren nur, wie die Struktur umgesetzt wird. Wie gut die Struktur ist, hängt nicht davon ab, ob die Module Microservices sind oder klassische Module. Domain-driven Design (DDD) und Bounded Context sind nützliche Techniken, um eine gute Struktur zu erreichen. Sie erleben dank Microservices gerade eine Renaissance. Wenn aus der Microservices-Diskussionein Fokus auf DDD und besser strukturierte Software entsteht, ist das schon ein wichtiger Erfolg – egal ob als Module Microservices genutzt werden oder nicht.
Ausgerechnet Deployment-Monolithen als Lösung für schlecht strukturierte Systeme zu propagieren, erscheint mir aber widersinnig. Ich habe viele Reviews von Deployment-Monolithen erstellt. Die Strukturen der untersuchten Monolithen ließ fast immer zu wünschen übrig. Meine Erklärung: Zu leicht schleichen sich im Sourcecode unbeabsichtigte Abhängigkeiten zwischen Modulen ein. Die einzige Ausnahme ist, wenn im Projekt ein Architekturmanagement-Werkzeug genutzt wird oder andere Maßnahmen ergriffen werden, um die Modulgrenzen zu erzwingen. Das war aber nur bei wenigen von mir untersuchten Deployment-Monolithen der Fall.
Da Microservices eigene Sourcecode-Projekte haben und Schnittstellen zwischen den Microservices zum Beispiel als REST-Schnittstellen implementiert sind, schleichen sich bei Microservices Abhängigkeiten nicht so einfach ein. Schließlich muss man eine Abhängigkeit zu einem anderen Sourcecode-Projekt erzeugen und eine Schnittstelle bedienen. Das ist viel aufwendiger als beispielsweise die Nutzung einer Klasse aus einem anderen Java-Package. Die Aufteilung in Microservices unterstützt also das Einhalten der Modulgrenzen.
Wenn eine gute Struktur festgelegt worden ist, lässt sie sich mit Microservices umsetzen. Deployment-Monolithen erfordern weitere Maßnahmen, um die Struktur dauerhaft abzusichern.
Es scheint so, als wäre von diesen beiden Alternativen ein Deployment-Monolith wegen der niedrigeren Komplexität die bessere Wahl. Nur ein System muss betrieben und ausgeliefert werden. Aber Microservices sind als Architekturansatz entstanden, um reale Probleme zu lösen:
Letztlich stehen Microservices für eine konsequente Entkopplung der Module: Technische Entscheidungen oder Deployment sind auf ein Microservice begrenzt. Ebenso führt der Ausfall eines Prozesses nur zum Absturz eines Microservices. Zwischen Microservices können beispielsweise durch Firewall zusätzliche Sicherheitsbarrieren errichtet werden und sie können unabhängig voneinander skaliert werden. Es entsteht also eine Entkopplung bezüglich Technologien, Deployment, Ausfall und Sicherheit. Auch die softwaretechnische Entkopplung kann sehr weit gehen, wie ein früherer Blog-Post[1] gezeigt hat.
So unterstützen Microservices Entkopplung und damit ein Hauptziel von Modulen.
Natürlich führen Microservices zu einer erhöhten Komplexität beispielsweise bei Tests oder im Betrieb. Diese zusätzliche Komplexität muss gegen die bessere Modularisierung, die stärkere Entkopplung und das unabhängige Deployment aufgewogen werden. Schließlich ist es nur sinnvoll, einen Architekturansatz zu wählen, wenn er für das Szenario die einfachste Lösung darstellt. Ursprünglich sind Microservices erfunden worden, weil sie nicht nur eine einfach Lösung sind, sondern große Teams und schnelles Deployment nur so möglich waren.
Microservices von Anfang an als "zu komplex" auszuschließen ist dabei genauso wenig hilfreich, wie Deployment-Monolithen grundsätzlich zu verdammen. Und wichtig bleibt, nicht nur die Frage nach der Modularisierungstechnologie zu stellen, sondern vor allem die fachliche Aufteilung vernünftig umzusetzen.
Microservices und Deployment-Monolithen sind unterschiedliche Modularisierungsansätze. Sie haben Vor- und Nachteile und passen zu verschiedenen Szenarien. Noch wichtiger als der Modularisierungsansatz ist, dass Struktur der Software gut ist.
URL dieses Artikels:http://www.heise.de/-3944829
Links in diesem Artikel:[1] https://www.heise.de/developer/artikel/Microservices-lassen-Komplexitaet-verschwinden-3194643.html
Copyright © 2018 Heise Medien
Das Warten hat ein Ende. Seit Ende letzten Jahres gibt es die 3. Auflage von Joshua Blochs Buch "Effective Java[1]". Die neue Auflage des in englischer Sprache erschienen Buchs umfasst nun auch Best Practices und Empfehlung für die mit Java 7, 8 und 9 eingeführten Features und Programmierparadigmen.
Bloch beschreibt in seinem Buch detailliert und gut verständlich, wann und wie verschiedene Java-Features eingesetzt werden sollten. "Effective Java[2]" sollte zur Pflichtlektüre eines jeden professionellen Java-Entwicklers gehören.
Jeder professionelle Java-Entwickler, der effizienten und wartbaren Code schreiben möchte.
Es gibt viele gute Bücher über Java, die die verschiedenen Sprachfeatures erklären. Das ist aber bekanntlich nur der erste Schritt. Um effiziente und wartbare Anwendungen entwickeln zu können, muss man nicht nur die einzelnen Features kennen, sondern auch verstehen, wann und wie diese einzusetzen sind.
Dabei hat Joshua Bloch vielen Entwicklern, mich eingeschlossen, bereits mit den vorherigen Auflagen seines Buchs "Effective Java" geholfen. Seine hervorragenden Erklärungen verdeutlichen die Funktionsweise und Auswirkungen verschiedener Sprachfeatures und zeigen Best Practices für die Erstellung von leicht verständlichem und zukunftssicherem Code. Dies setzt er nun mit der 3. Auflage seines Buchs fort, das er für die Verwendung der mit Java 7, 8 und 9 eingeführten Paradigmen und Sprachfeatures aktualisiert hat. Insbesondere die Kapitel zum Design von Interfaces sowie der Verwendung von Generics und Lambdas sollten allen Entwicklern bekannt sein.
Während der vergangenen zwei Woche, habe ich das Buch vollständig gelesen und kann dies nur jedem empfehlen. Es war unterhaltsam und sehr lehrreich. Aber es gibt auch gute Nachrichten für alle, die nicht die Zeit haben, das ganze Buch auf einmal zu lesen. Blochs Buch ist in 90 Items unterteilt, die gezielte Ratschläge und Erläuterungen für spezifische Aufgaben und Sprachfeatures bieten. Die Items verweisen zwar aufeinander, können jedoch auch gut einzeln gelesen werden.
Durch die Unterteilung kann das Buch auch als Nachschlagewerk bei der täglichen Entwicklungsarbeit verwendet werden. Ich bin mir bereits jetzt sicher, dass ich in naher Zukunft die komplexere Items zu Lambdas und Generics noch das eine oder andere Mal lesen werde. Wie auch bereits die vorherige Auflage, wird die 3. Auflage von "Effective Java" mein Begleiter bei der Entwicklung komplexer Aufgaben und der Erstellung neuer APIs werden.
Die im Buch enthaltenen 90 Items sind thematisch in folgende Kapitel unterteilt:
Einige Kapitel mögen auf den ersten Blick grundlegende Themen der Java-Entwicklung behandeln. Ich empfehle aber trotzdem, diese vollständig zu lesen. Auch mit mehr als 15 Jahren Erfahrung als Entwickler und Architekt habe ich aus jedem Kapitel neue Ideen und Erkenntnisse gewonnen.
Gerade deshalb möchte ich jedem professionellen Java-Entwickler die 3. Auflage[3] empfehlen.
URL dieses Artikels:http://www.heise.de/-3937945
Links in diesem Artikel:[1] https://www.amazon.de/Effective-Java-Joshua-Bloch/dp/0134685997/[2] https://www.amazon.de/Effective-Java-Joshua-Bloch/dp/0134685997/[3] https://www.amazon.de/Effective-Java-Joshua-Bloch/dp/0134685997/
Copyright © 2018 Heise Medien
Um ein verteiltes System verlässlich (a.k.a. reliable) zur Verfügung zu stellen, ist es wichtig, essenzielle Metriken zu monitoren. MicroProfile hat seit der Version 1.2 mit Health Check und Metrics gleich zwei passende APIs im Gepäck.
Microservice-Anwendungen zeichnen sich durch die Unabhängigkeit ihrer Services und einer damit verbundenen Verteiltheit des Gesamtsystems aus. Während bei einer klassischen Enterprise-Java-Anwendung ein Deployment-Artefakt in einem Server beziehungsweise einem Server-Cluster läuft und somit recht gut unter Kontrolle zu halten ist, setzt sich eine Microservice-Anwendung in der Regel aus einer Vielzahl von Services zusammen, die jeweils in eigenen Prozessen – zum Beispiel in Docker-Containern – laufen. Um ein solches Szenario in den Griff zu bekommen, sind ein ausgereiftes Monitoring zum Aufdecken aufkommender Problemsituationen sowie die automatisierte Reaktion auf die Ergebnisse des Monitorings notwendig.
Es kommt also nicht von ungefähr, dass das Eclipse-Projekt MicroProfile bereits in Version 1.2 entsprechend APIs zum Monitoren von Microservices in die Spezifikation aufgenommen hat: HealthCheck API, Metrcis APIs.
Warum aber gleich zwei APIs? Hätte denn eine nicht auch ausgereicht? Die beiden zur Verfügung stehenden APIs sprechen tendenziell unterschiedliche Bereiche des Monitorings an. Mithilfe der Health Check API[1] soll von außen festgestellt werden können, ob ein Service beziehungsweise eine Anwendung noch so läuft, wie geplant. Auf die einfache Frage "geht es dir gut?" bekommt der Anfragende ein genauso einfaches "Ja" oder "Nein" beziehungsweise die Statusmeldung "UP" oder "DOWN" als Antwort zurück. Diese Information lässt sich von Tools wie Kubernetes[2] nutzen, um den entsprechenden Service oder einzelne Komponenten des Service gezielt zu ersetzen oder zu beenden und im Anschluss neu zu starten. Die zweite API, Metrics API[3], dagegen dient dazu, gezielt Detailinformationen zum aktuellen "Gesundheitszustand" eines Service und dessen Verlauf abfragen zu können. Mithilfe von Langzeitmetriken lassen sich so zum Beispiel Wachstumspläne für die genutzte Infrastruktur aufstellen oder proaktiv auf sich abzeichnende Engpässe reagieren.
Erfinden wir hier das Rad nicht neu, wird sich jetzt der eine oder andere fragen? Wir haben doch bereits seit Jahren mit JMX und JSR 77 zwei mehr oder minder etablierte Standards im Enterprise-Java-Umfeld. Ja und nein. Insbesondere in einer per Definition als polyglott angelegten Welt – und das ist die Welt der Microservices – ist es wichtig, einen gemeinsamen und vor allem einfachen Standard für das Monitoren des Gesundheitszustandes der Services und das regelmäßige Abfragen von Metriken zu etablieren. Hierbei spielen, wie wir gleich noch sehen werden, Aspekte, wie ein standardisierter REST-Ressourcenpfad, einheitliche Datentypen oder aber auch die Definition der zu verwendenden HTTP Return-Codes eine wichtige Rolle.
Mithilfe der Eclipse MicroProfile Health Check API soll die generelle Verfügbarkeit sowie der Status ("UP" oder "DOWN") einer MicroProfile-Instanz – also eines auf dem MicroProfile basierenden Microservices – geprüft werden können. Die API ist weniger für den manuellen Gebrauch als vielmehr für Szenarien im Umfeld von Container-basierten Umgebungen gedacht (M2M). So wundert es nicht, dass als Vorbild für die API proprietäre Lösungen, wie Cloud Foundry Health Check[4] oder Kubernetes Liveness and Readiness Probes[5], herangezogen wurden. Dank der Health Check API können Monitoring- und Managment-Tools durch einen einfachen GET-REST-Call des Endpoints /health automatisiert feststellen, ob ein Service wie gewünscht läuft oder gegebenenfalls ersetzt oder neu gestartet werden muss.
GET /health200 OK
{
"outcome" : "UP"
"checks": []
}
Besteht der Service aus mehreren Teilkomponenten, kann die Antwort des Service bei Bedarf noch weiter aufgeschlüsselt werden. Im folgenden Beispiel wird der Status des Customer REST Endpoints sowie der zugehörigen Datenbank separat durchgeführt.
200 OK
{
"outcome": "UP",
"checks": [
{
"name": "datasource",
"state": "UP",
"data": {
"dbConnection": "...",
"dbName": "...",
"freeSpace": "..."
},
},
{
"name": "resources",
"state": "UP"
"data": {
"customers": "/customers",
"addresses": "/customers/{id}/addresses"
}
}]
}
Der aktuelle "Gesundheitszustand" des Service setzt sich in diesem Beispiel also aus zwei Komponenten zusammen. Nur wenn alle Checks den Status "UP" aufweisen, ist auch der Gesamtstatus des Services "UP", was mit einem HTTP-Status-Code 200 und entsprechender Payload quittiert wird. Andernfalls wird der Status von der Health Check API automatisch als "DOWN" interpretiert (HTTP-Status-Code 503). Konnte der gewünschte Gesundheits-Check aus irgendwelchen Gründen nicht durchgeführt werden, wird dies der aufrufenden Partei mit dem HTTP-Status-Code 500 signalisiert. In diesem Fall gilt der Status des Service als unbestimmt.
Die Implementierung und Einbindung der eben gezeigten Checks in den eigenen Microservice ist denkbar einfach. Die Health Check API stellt für diese Aufgabe sowohl ein entsprechendes Interface – HealthCheck – als auch eine Annotation - @Health - zur Verfügung.
@Health
@ApplicationScoped
public class ResourcesHealthCheck implements HealthCheck {public HealthCheckResponse call() {
return HealthCheckResponse
.named("resources")
.withData("customers","/customers" )
.withData("addresses","/customers/{id}/addresses" )
.state(checkCustomersResource()
&& checkAddressesResource ())
.build();
}private boolean checkCustomersResource() { return … }
private boolean checkAddressesResource() { return … }
Die Annotation werden im Kontext von CDI automatisch erkannt und die entsprechenden Beans beziehungsweise deren call()-Methoden aufgerufen, sobald ein externer Aufruf des /health-Endpoints auf dem Service erfolgt.
Was aber, wenn wir nicht nur wissen wollen, ob ein Service ordnungsgemäß läuft oder eben nicht? Was, wenn uns zum Beispiel die aktuelle CPU- oder Speicherauslastung oder aber die Anzahl der derzeit verwendeten Threads interessiert? Und was, wenn wir aus historischen Daten und deren aktuellen Pendants Rückschlüsse darauf treffen möchten, wie sich unser Systemzustand entwickelt, um so zum Beispiel bei Bedarf mehr Plattenplatz zur Verfügung zu stellen oder neue Service-Instanzen zu starten beziehungsweise bestehende Instanzen zu stoppen.
Die MicroProfile Metrcis API bietet eine genormte und individuell erweiterbare Schnittstelle zur Beantwortung genau dieser Fragestellungen – und vieler anderer mehr. Mithilfe eines REST-Calls gegen den Endpoint /metrics beziehungsweise einen von drei untergeordneten Metrik-Scopes (Sub-Ressourcen: base, vendor, application) lassen sich die gewünschten Telemetrie-Daten via HTTP abfragen und über Tools, wie Prometheus[6], automatisch auswerten, um so im Anschluss entsprechende Aktionen anzustoßen.
Die Rückgabe erfolgt dabei entweder im JSON-Format, bei Angabe des Accept-Headers "application/json" oder alternativ im Prometheus Text Format (bei fehlendem Accept-Header). Es ist davon auszugehen, dass zukünftig noch weitere Formate durch die Spezifikation oder aber durch herstellerspezifische Erweiterungen unterstützt werden.
Bei dem ersten Scopes – base – handelt es sich um Telemetriedaten, die jede MicroProfile-Implementierung beim Aufruf des allgemeinen Endpoints /metrics beziehungsweise des Scope-spezifischen Endpoints /metrics/base zur Verfügung stellen muss. Hier finden sich hauptsächlich JVM-relevante Informationen:
GET /metrics/base
Accept: application/json
Authorization: Basic ....200 OK
{
"classloader.totalLoadedClass.count": 12595,
"cpu.systemLoadAverage": 3.88525390625,
"gc.PSScavenge.time": 262,
"thread.count": 30,
"classloader.currentLoadedClass.count": 12586,
"jvm.uptime": 4795005,
"memory.committedHeap": 740818944,
"thread.max.count": 46,
"cpu.availableProcessors": 4,
"gc.PSMarkSweep.count": 3,
"thread.daemon.count": 28,
"classloader.totalUnloadedClass.count": 9,
"gc.PSScavenge.count": 13,
"memory.maxHeap": 3817865216,
"cpu.processCpuLoad": 0.00571799781527977,
"memory.usedHeap": 238923968,
"gc.PSMarkSweep.time": 448
}
Anmerkung: Wie der Beispielaufruf zeigt, geht die Spezifikation davon aus, dass der /metrics-Endpoint in irgendeiner Weise abgesichert werden kann. In welcher Art und Weise dies passiert, ist aktuell nicht spezifiziert und somit dem jeweiligen Hersteller überlassen.
Zusätzlich zu diesen universellen Metriken hat jeder Hersteller optional die Möglichkeit, eigene, in der Regel nicht portable Metriken via /metrics beziehungsweise /metrics/vendor anzubieten. Dies könnten zum Beispiel Informationen zum Zustand eines intern verwendeten Cache oder eines Messaging-Systems sein.
Besonders interessant, aus Sicht eines Microservices-Entwicklers, ist der dritte und letzte Scope: application. Auch dieser Scope ist optional und kann zur Bereitstellung von anwendungsspezifische Metriken genutzt werden.
Im folgenden Beispiel kann die Anzahl an Einschreibungen sowie die jeweils für die Einschreibungen benötigte Zeitspanne als Metrik abgefragt werden. Das Beispiel zeigt ebenfalls, dass sich, je nach gewählter Metrik, neben den aktuellen Werten auch Durchschnitts- und Trendwerte abfragen lassen:
GET /metrics/application
Accept: application/json
Authorization: Basic ....200 OK
{
"microprofile.demo.subscriptions": 6,
"microprofile.demo.doSubscribe": {
"fiveMinRate": 0.18984199379480962,
"max": 1949047687,
"count": 6,
"p50": 901908241,
"p95": 1949047687,
"p98": 1949047687,
"p75": 1909288320,
"p99": 1949047687,
"min": 423270500,
"fifteenMinRate": 0.19664645980623557,
"meanRate": 0.12968582020280628,
"mean": 1164575631.8269844,
"p999": 1949047687,
"oneMinRate": 0.148852445426026,
"stddev": 589520048.3135717
}
}
Der Abfrage von Metriken mittels Metrics API kann auf drei unterschiedlichen Ebenen erfolgen:
Jede Metrik ist optional mit einer Reihe von Metadaten verbunden. Sie sollen aufrufenden Tools, aber auch Menschen (Operators) dabei helfen, die gelieferten Wert besser interpretieren zu können. Neben Informationen wie description und displayName sind vor allem die beiden Metadaten type (counter, gauge, meter, timer, histogram) und unit von besonderem Interesse.
Welche Metadaten einer Metrik zugeordnet sind, lässt sich leicht erfragen, indem statt eines GET- ein OPTIONS-Request gegen den entsprechenden REST-Endpoint abgesetzt wird.
Während die Metadaten bei den Scopes base von der Spezifikation vorgegeben sind, können sie bei den beiden anderen Scopes – vendor und application – frei zugeordnet werden.
In dynamischen Welten, wie denen der Microservices, spielen Label beziehungsweise Tags eine besondere Rolle. Während sich die ID eines Service durch automatisches (Re-)Deployment ändern kann, können eindeutige Tags als gemeinsamer Aufhänger für gezielte Abfragen von Metriken durch Tools, wie Kubernetes und Prometheus, genutzt werden. So wäre es zum Beispiel denkbar, dass man die Metriken einer bestimmten Anwendung (app=myApp) oder alternativ einer bestimmten Schicht einer Anwendung (app=myApp && tier=database) abfragen und visuell darstellen beziehungsweise verdichtet auswerten möchte.
Damit dies möglich wird, erlaubt die Metrics API die Angabe von Tags. Dies kann entweder mithilfe der MicroProfile Config API [7]und dem Key MP_METRIC_TAGS geschehen oder alternativ über das Application Metrics Programming Model erfolgen.
Die Metrics API erlaubt es, neben den allgemeinen und herstellerspezifischen Metriken auch eigene, anwendungsspezifische Metriken im Scope application zu registrieren. Dies sind genau diejenigen Metriken, die bei einem Aufruf von /metrics/application zurückgeliefert werden.
Zur einfachen Handhabung gibt es für jeden Metrik-Typen eine eigene Annotation (@Counted, @Gauge, @Metered, @Metric, @Timed), die je nach Typ auf Klassen, Konstruktoren, Methoden oder Parametern angewandt werden können.
Das folgende Beispiel zeigt eine REST-Ressource zum Einschreiben in beziehungsweise Ausschreiben aus einem Online-Kurs. Mittels Metric API lässt sich die Anzahl der aktuellen Einschreibungen sowie Telemetrie-Daten zur dafür benötigten Zeit abfragen. Das Resultat des Aufrufs haben wir bereits weiter oben gesehen:
@Path("subscriptions")
public class SubscriptionResource {@Inject
@Metric(absolute = true,
name = "microprofile.demo.subscriptions",
description = "number of subscriptions ",
displayName = "current subscriptions for online course",
unit = MetricUnits.NONE)
Counter subscriptionCounter;
@POST
@Produces(MediaType.APPLICATION_JSON)
@Timed(absolute = true,
name = "microprofile.demo.doSubscribe",
displayName = "Subscription time",
description = "Time of subscription in ns",
unit = MetricUnits.NANOSECONDS)
public Response subscribe(...) {
// subscribe to online course
...
subscriptionCounter.inc();
return Response.ok()… build();
}
@DELETE
@Produces(MediaType.APPLICATION_JSON)
@Timed(absolute = true,
name = "microprofile.demo.doUnsubscribe",
displayName = "Unsubscription time",
description = "Time of unsubscription in ns",
unit = MetricUnits.NANOSECONDS)
public Response unsubscribe() {
// unsubscribe to online course
...
subscriptionCounter.dec();
return Response.ok()… build();
}
}
Wer jetzt denkt, dass ihm das Ganze bekannt vorkommt, der hat wahrscheinlich recht. Die Macher der Metrics API haben bewusst versucht, das Rad nicht neu zu erfinden und sich stattdessen an der etablierten DropWIzard Metrics API orientiert.
Wie das Beispiel zeigt, ist die Wahl des Metriknamens (name = "...") nicht ganz unwichtig. Und dies gilt gleich in zweierlei Hinsicht. Zum einen erleichtert die Wahl eines geeigneten Namens inklusive eindeutigem Namensraum, das gezielte Abfragen und Filtern von Metriken durch angebundene Tools enorm. Zum anderen verhindern versehentlich doppelt vergebene Namen das Deployment eines Microservices, da CDI dies zum Zeitpunkt des Scannings feststellt und eine IllegealArgumentException wirft. Eine Ausnahme ist nur dann erlaubt, wenn eine Metrik bewusst mit dem Attribut reusable markiert wird. In diesem Fall müssen aber alle Varianten vom selben Typ sein.
Um ein verteiltes System verlässlich (a.k.a. reliable) zur Verfügung zu stellen, ist es wichtig, essenzielle Metriken zu monitoren. MicroProfile hat seit der Version 1.2 mit Health Check und Metrics gleich zwei passende APIs im Gepäck. Während die Health Check API lediglich die Frage nach dem allgemeinen Gesundheitszustand eines Service klärt ("UP" oder "DOWN"), lassen sich dank Metrics API Rückschlüsse auf die allgemeine Entwicklung des Service und seiner Umgebung anstellen und so proaktiv auf Tendenzen, wie die negative Entwicklung von Speicherverbrauch oder Antwortzeiten, reagieren.
Metrics unterstützt als Austauschformat zur Anbindung von Monitoring- und Management- Tools sowohl JSON und auch das Prometheus Text Format[8]. Über weitere Formate wird bereits nachgedacht. Man darf gespannt sein.
URL dieses Artikels:http://www.heise.de/-3940913
Links in diesem Artikel:[1] https://github.com/eclipse/microprofile-health[2] https://kubernetes.io[3] https://github.com/eclipse/microprofile-metrics[4] https://docs.cloudfoundry.org/devguide/deploy-apps/healthchecks.html[5] https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes[6] https://prometheus.io[7] https://www.heise.de/developer/artikel/MicroProfile-unter-der-Lupe-Teil-1-Config-API-3928886.html[8] https://prometheus.io/docs/instrumenting/exposition_formats
Copyright © 2018 Heise Medien
Die Hibernate-Tipps-Serie bietet schnelle und einfache Lösungen zu verbreiteten Hibernate-Fragen. Dieses Mal geht es um Ergebnisse komplexer Abfragen und deren Abbildung auf managed Entitäten.
Ich musste meine Abfrage als native SQL Abfrage[1] implementieren, da sie zu komplex für JPQL[2] ist. Gibt es eine Möglichkeit das Abfrageergebnis auf Entitäten abzubilden, ohne diese separat laden zu müssen?
Wenn die Abfrage alle von der Entität abgebildeten Datenbankspalten selektiert, gibt es 2 Möglichkeiten das Ergebnis auf Entitäten abzubilden:
Für die meisten Abfragen stellt eine implizite Umwandlung des Abfrageergebnisses die einfachste und schnellste Lösung dar. Dazu muss lediglich die Klasse der selektierten Entität als zusätzlicher Parameter an die createNativeQuery Methode übergeben werden.
Book b = (Book) em.createNativeQuery("SELECT * FROM book b WHERE id = 1",
Book.class).getSingleResult();Der EntityManager verwendet dabei die für die Entität definierten Abbildungen der Spaltennamen auf deren Eigenschaften. Daher müssen die Spaltennamen der Ergebnismenge der nativen Abfrage den Spaltennamen der durch die Entität abgebildeten Datenbanktabelle entsprechen.
Wenn die Spaltennamen des Abfrageergebnisses von denen der Tabelle abweichen, kann eine explizite Abbildung mit Hilfe einer @SqlResultSetMapping Annotation definiert werden.
@SqlResultSetMapping(
name = "BookMapping",
entities = @EntityResult(
entityClass = Book.class,
fields = {
@FieldResult(name = "id", column = "id"),
@FieldResult(name = "version", column = "version"),
@FieldResult(name = "title", column = "title"),
@FieldResult(name = "publishingDate",
column = "publishingDate"),
@FieldResult(name = "publisher", column = "publisherid")}))
Dabei muss der Name, über den das Mapping später referenziert werden kann, und eine @EntityResul-Annotation angegeben werden. Die @EntityResult-Annotation spezifiziert, welche Klasse für jeden Datensatz instanziiert werden soll und beschreibt über eine Liste von @FieldResult-Annotationen wie die Spalten des Ergebnisses auf die Eigenschaften der Entität abgebildet werden.
Um diese Abbildung zu verwenden, muss dann lediglich der im @SqlResultSetMapping definierte Name als 2. Parameter an die createNativeQuery-Methode übergeben werden.
em.createNativeQuery("SELECT * FROM book b WHERE id = 1",
"BookMapping").getSingleResult();Auf diese Art und Weise kann das Ergebnis einer nativen SQL Abfrage auch auf mehrere Entitäten[3] oder auf nicht durch den Persistenzkontext verwaltete POJOs[4] abgebildet werden.
Mehr als 70 solcher Rezepte zu Themen wie einfache und komplexe Mappingdefinitionen, Logging, Unterstützung von Java 8, Caching sowie die statische und dynamische Erzeugung von Abfragen gibt es in meinem Buch "Hibernate Tips: More than 70 solutions to common Hibernate problems". Es ist als Taschenbuch und E-Book auf Amazon[5] und als PDF auf hibernate-tips.com[6] erhältlich.
URL dieses Artikels:http://www.heise.de/-3937917
Links in diesem Artikel:[1] https://www.thoughts-on-java.org/jpa-native-queries/[2] https://www.thoughts-on-java.org/jpql/[3] https://www.thoughts-on-java.org/result-set-mapping-complex-mappings/[4] https://www.thoughts-on-java.org/result-set-mapping-constructor-result-mappings/[5] https://www.amazon.de/Hibernate-Tips-solutions-common-problems/dp/1544869177[6] http://www.hibernate-tips.com/
Copyright © 2018 Heise Medien
Das Eclipse-MicroProfile-Projekt ist angetreten, eine portable Lösung für Microservices im Enterprise-Java-Umfeld zu liefern. Neue APIs sollen die Lücke zwischen dem Java-EE-Standard und den Praxisanforderungen von Microservices-Architekturen schließen.
Microservices und Java EE (a.k.a. EE4J)? Das passt nicht wirklich! So zumindest die landläufige Meinung, wenn es darum geht, Microservice-Anwendungen auf Grundlage des Java-Enterprise-Standard umzusetzen. Dabei bietet Java EE mit JAX-RS, CDI, JPA und JSON-P alles, was es braucht, um RESTful-Microservices zu implementieren. Und auch asynchrone, auf Messages oder Events basierende Services lassen sich dank JMS, WebSockets und Server-Sent Events (seit Java EE 8) mit wenigen Zeilen Code realisieren. Wo also liegt das Problem?
Microservice-Anwendungen zeichnen sich in der Regel dadurch aus, dass eine Vielzahl von Services, die jeweils in eigenen Prozessen laufen, miteinander interagieren und so ein großes Ganzes ergeben. Nicht selten werden diese Services zusätzlich in Containern verpackt und in der Cloud deployt. Unterm Strich haben wir es also mit einem hoch dynamischen, stark verteilten System zu tun.
Die eigentliche Herausforderung liegt somit weniger in der Umsetzung der (fachlichen) Logik eines einzelnen Service als vielmehr in der Realisierung des reibungslosen Zusammenspiels der Gesamtheit aller Services. Und genau hier liegt das Problem beziehungsweise die Schwachstelle von Java EE. Denn Java EE ist darauf ausgerichtet, dass die einzelnen Artefakte – in diesem Fall also die Services – innerhalb eines Application Server deployt werden, damit dieser übergreifende Dienste (Cross-Cutting Concerns) wie Configuration, Monitoring, Logging, Security et cetera übernehmen kann. Fällt der Server weg oder gibt es mehrere autarke Server-Instanzen, von denen jede einen eigenen Microservice verwaltet, fehlt die koordinierende Schaltzentrale.
Genau dieses Manko hat auch eine Reihe von Application-Server-Anbietern erkannt und 2016 die Initiative MicroProfile.io[1] ins Leben gerufen. Die inzwischen in der Eclipse Foundation beheimatete Initiative ist angetreten, die Lücke zwischen dem Java-Enterprise-Standard und den Praxisanforderungen Microservices-basierter Architekturen zu schließen. Laut eigener Aussagen möchte man das bestehende Momentum der Java-EE-Community als Hebel nutzen und organisch um den Bedarf der Microservices-Community ergänzen. Der Plan scheint aufzugehen. In nur wenigen Monaten ist es gelungen, eine Reihe sinnvoller Microservices-relevanter APIs mit bestehenden Java-EE-7/8-APIs zu kombinieren und diese in regelmäßigen MicroProfile-Releases zu veröffentlichen. Egal ob Health Check, Metrics, Fault Tolerance, JWT Propagation, Configuration, Tracing oder Open API, MicroProfile scheint die richtigen Antworten – sprich APIs – im Gepäck zu haben.
Dieser Blogbeitrag ist der erste Teil einer kleinen Serie, die sich mit den Microservice-spezifischen APIs des MicroProfiles beschäftigt. Also den APIs, die nicht Bestandteil der Java-EE-Spezifikation sind. Den Anfang macht die Config API, die erst vor wenigen Tagen in der Version 1.2 veröffentlicht wurde.
Die Idee, Anwendungslogik und Konfiguration voneinander zu trennen, ist nicht wirklich neu. Mithilfe einer ausgelagerten Konfiguration lässt sich die Anwendung beziehungsweise der Service von außen auf die jeweilige Laufzeitumgebung anpassen. Für die lokale Testumgebung nutzt man zum Beispiel im Test-Quellcode vorgegebene Einstellungen, während die Laufzeitumgebung des Containers in einer produktiven Umgebung innerhalb eines Containers in der Cloud die notwendigen Werte für die Konfiguration setzt.
Was einfach klingt, kann in der Praxis zu unerwarteten Herausforderungen führen. So stammen die einzelnen Werte für die Konfiguration einer Anwendung beziehungsweise eines Service in der Regel aus mehreren verschiedenen Quellen, wie System Properties, Umgebungsvariablen, Dateien, Datenbanken oder proprietären Konfigurationsquellen. Auch das Format, in dem die Werte abgelegt sind, ist oftmals nicht einheitlich und entspricht normalerweise nicht dem Objektformat, in dem die Konfigurationswerte innerhalb der Anwendung beziehungsweise des Service verwendet werden sollen. Während es bei statischen Konfigurationswerten ausreicht, diese einmalig beim Start zu laden, sind dynamische Werte permanent auf ihre Aktualität zu prüfen und bei Bedarf neu einzulesen. Und natürlich sollte eine Anwendung auch dann noch sinnvoll funktionieren, wenn eine Konfiguration einmal nicht gefunden werden kann.
All diese Aspekte und noch etliche mehr berücksichtigt die MicroProfile Config API (im Folgenden Config API). Sie bietet einen vereinheitlichen Zugriff auf verschiedenste Konfigurationsquellen an. Die einzelnen Quellen lassen sich dabei mit Prioritäten versehen, sodass ein gezieltes Überschreiben von Konfigurationen möglich wird. Von Haus aus kennt die Config API drei verschiedene Quellen:
Standardwerte für die Konfiguration können so in einer Datei mit dem Namen microproifile-config.properties im Verzeichnis META-INF abgelegt und bei Bedarf in den jeweiligen Deployment-Umgebungen überschrieben werden. Natürlich ist es auch möglich, eigene Quellen einzubinden und mit einer individuellen Priorität zu belegen. Zum Beispiel ließe sich ein zentraler Key-Value-Store als weitere Konfigurationsquelle verwenden.
Die Config API bietet zwei unterschiedliche Wege zum Zugriff auf die im Hintergrund verwalteten Konfigurationen. Zum einen kann der Zugriff programmatisch erfolgen, zum anderen via CDI Injection.
Der programmatische Zugriff erfolgt mithilfe einer Instanz der Config-Klasse, die sich im einfachsten Fall via ConfigProvider erzeugen lässt:
// get access to the Config instance via ConfigProvider
Config config = ConfigProvider.getConfig();// access config properties via Config instance
String someStringValue = config.getValue("SOME_STRING_KEY", String.class);
Boolean someBooleanValue = config.getValue("SOME_BOOL_KEY", Boolean.class);
Möchte man beim Erstellung der Config-Instanz mehr Einfluss nehmen, kann anstelle des ConfigProvider auf einen ConfigBuilder zurückgegriffen werden. Der Builder erlaubt die eine oder andere individuelle Anpassung. Der oben gezeigte Code würde mit einem ConfigBuilder wie folgt aussehen:
// get access to the Config instance via ConfigBuilder
ConfigBuilder builder = ConfigProviderResolver.getBuilder();
builder.addDefaultSources();
Config config = builder.build();// access config properties via Config instance
String someStringValue = config.getValue("SOME_STRING_KEY", String.class);
Boolean someBooleanValue = config.getValue("SOME_BOOL_KEY", Boolean.class);
Anmerkung: Bei der Verwendung des ConfigProvider wird die beim Aufruf der getConfig()-Methode zurückgelieferte Config-Instanz aus Gründen der Effizienz automatisch gecacht. Das ist bei der Verwendung des ConfigBuilder beziehungsweise des ConfigProviderResolver nicht der Fall.
Deutlich einfacher als der ebene gezeigte programmatische Zugriff ist der via CDI Injection:
@Inject @ConfigProperty("SOME_STRING_KEY")
String someStringValue; @Inject @ConfigProperty("SOME_BOOL_KEY")
String someBooleanValue;
Was aber, wenn sich der gesuchte Schlüssel in keiner der Konfigurationsquellen finden lässt? Im obigen Beispiel würde das automatisch zu einer Exception führen. Im ersten Beispiel, dem programmatischen Zugriff, wäre es eine NoSuchElementExeption zur Laufzeit. Im zweiten Beispiel dagegen, im Falle der CDI Injection, würde eine DeploymentException während des Start-ups geworfen werden.
Soll eine Konfiguration lediglich optional sein, um so zum Beispiel nur in speziellen Umgebungen Standardwerte zu überschreiben, in anderen dagegen nicht, ist dies ebenfalls für beide gezeigten Zugriffsmechanismen möglich. Im Falle des programmatischen Zugriffs sieht das wie folgt aus:
// get access to the Config instance
Config config = ConfigProvider.getConfig();// access optional string property
String someStringValue = config.getOptionalValue("SOME_KEY", String.class)
.orElse("someDefaultValue");
Bei CDI Injection dagegen reicht die einfache Angabe eines Default-Werts vom richtigen Typ:
// inject optional property
@Inject @ConfigProperty("SOME_KEY", defaultValue="someDefaultValue")
String someValue;
Auch wenn Microservice-basierte Anwendungen so entworfen sein sollten, dass sie einen Restart einzelner Services problemlos überleben, macht es sicherlich keinen Sinn, einen Service jedes Mal neu zu starten, nur weil sich ein Wert einer Konfiguration geändert hat. Aus diesem Grund sieht die Config API einen Mechanismus vor, Konfigurationswerte dynamisch in dem Moment der Verwendung zu laden.
Das macht natürlich wenig Sinn, wenn die Konfigurationsquelle eine gemeinsam mit dem WAR deployte Properties-Datei ist. Anders dagegen sieht es schon aus, wenn als Quelle eine Datenbank oder ein Konfigurationsserver angebunden wird.
Um in dem Moment der Nutzung einer Property tatsächlich immer ihren aktuellen Wert und nicht den Wert zum Zeitpunkt der Injection zu erhalten, muss anstelle der ConfigProperty ein Provider injiziert werden. Mithilfe des Providers und dessen get()-Methode kann anschließend eine Just-in-Time-Konfiguration erfolgen.
// inject property provider
@Inject @ConfigProperty("SOME_KEY")
ProvidersomeValueProvider;
...
// get property value "just-in-time" via provider
String someValue = someValueProvider.get();
Der Begriff "Just-in-Time" ist in diesem Fall allerdings eher relativ zu sehen und bedeutet lediglich, dass der gerade in der Konfigurationsquelle hinterlegte Wert herangezogen wird. Wie die Quelle wiederum die Werte aktualisiert und wann auf ihr ein Refresh durchgeführt wird, ist nicht spezifiziert und somit dem Autor der ConfigSource-Klasse überlassen. Die Implementierung von OpenLiberty zum Beispiel erlaubt die Angabe einer Refresh-Rate via System-Property microprofile.config.refresh.rate für die Konfigurationsquellen. Der Standardwert liegt bei 500 (ms), sodass bei Bedarf alle halbe Sekunde ein Refresh erfolgt.
Die Config API unterstützt, wie im ersten Beispiel gezeigt, nicht nur Properties vom Typ String. Dank sogenannter Converter lassen sich die in den Konfigurationsquellen hinterlegten String-Werte in beliebige Java-Typen überführen.
Für eine Reihe von Java-Typen existieren bereits sogenannte Build-in Converter. Neben den bisher gezeigten Typen String und Boolean werden unter anderem auch Integer, Long, Double, Float sowie Duration, LocalTime, LocalDate, LocalDateTime, Instant und URL "out of the box" unterstützt. Und auch die Verwendung von Arrays ist seit Version 1.2 möglich:
// injection list property via array converter
@Inject @ConfigProperty("SOME_LIST_KEY")
private ListsomeListValues; ...
// get access to the Config instance via ConfigProvider
Config config = ConfigProvider.getConfig();
// access config properties via Config instance
private String[] someArrayValues = config.getValue("SOME_ARRAY_KEY", String[].class);
Was aber, wenn nicht unterstützte oder eigene Datentypen via Config API gesetzt werden sollen? In diesem Fall lässt sich ein spezifischer Custom-Converter, der das Converter
@Priority(200)
public class EmailConverter implements Converter{ @Override
public Email convert(String email) throws IllegalArgumentException {
return new Email(email);
}
}
Damit der Converter zur Laufzeit automatisch herangezogen werden kann, muss er zusätzlich registriert werden. Dies kann entweder via Java ServiceLocator – durch Angabe des voll qualifizierten Klassennamens des Converters in einer entsprechenden Datei META-INF/services/org.eclipse.microprofile.config.spi.Converter – geschehen oder alternativ programmatisch mithilfe des ConfigBuilder:
// get access to the Config instance via ConfigBuilder
ConfigBuilder builder = ConfigProviderResolver.getBuilder();
builder.addDefaultSources();// add custom converter for Email class
ConverteremailConverter = new EmailConverter();
builder.withConverters(emailConverter);
Config config = builder.build();// read email property into email object
OptionalemailOpt = config.getOptionalValue("ADMIN_EMAIL", Email.class);
...
Wie das Listing des EmailConverter zeigt, lassen sich auch Converter mit einer Priorität versehen. Sind also mehrere Converter für denselben Typ registriert, dann überschreibt der Converter mit der höheren Priorität diejenigen mit geringerer Priorität. Der Standardwert ist 100.
Alles in allem macht die Config API einen runden Eindruck, was aber auch nicht wirklich verwundert, wenn man einmal einen genaueren Blick auf die Ursprünge der API wirft:
Wer ein wenig Lust bekommen hat, die API einmal auszuprobieren, kann das mit folgenden Implementierungen tun:
Für die Zukunft sind bereits weitere Features geplant. Ein Hauptaugenmerk wird darauf liegen, dynamische Konfigurationsänderungen besser zu unterstützen. Man darf gespannt sein.
URL dieses Artikels:http://www.heise.de/-3928886
Links in diesem Artikel:[1] https://microprofile.io[2] https://deltaspike.apache.org/documentation/configuration.html[3] http://tamaya.incubator.apache.org/index.html[4] https://github.com/apache/geronimo-config[5] https://developer.ibm.com/wasdev/[6] https://docs.payara.fish/documentation/microprofile/config.html[7] https://github.com/wildfly-extras/wildfly-microprofile-config/
Copyright © 2017 Heise Medien
Das Implementieren von Bestell- beziehungsweise Bezahlprozessen innerhalb von Webanwendungen kann mitunter recht komplex sein. Die sogenannte Payment Request API [1], die momentan beim W3C ausgearbeitet wird und vor etwa einem Monat zusammen mit den Payment Method Identifiers [2] als "Candidate Recommendation" veröffentlicht wurde, soll hier Abhilfe schaffen.
Die API sieht vor, den Browser als Vermittler zwischen folgenden bei einem Bestellprozess involvierten Akteuren einzusetzen: dem Zahlungsempfänger (beispielsweise einem Online-Händler), dem Zahlungssender (also dem Käufer) und demjenigen, der die Hilfsmittel für eine Zahlung bereitstellt (Kreditkarte etc.).
Folgende Typen werden durch die API bereitgestellt:
Ob die API vom aktuellen Browser unterstützt wird, lässt sich innerhalb einer Website wie gewohnt über Feature Detection prüfen, beispielsweise durch Überprüfung auf das PaymentRequest-Objekt:
if (window.PaymentRequest) {
// Payment Request API wird unterstützt
} else {
// Payment Request API wird nicht unterstützt
}
Momentan unterstützen lediglich Chrome, Opera und Microsoft Edge die API [3], in Firefox kann die API als experimentelles Feature über das Flag "dom.payments.request.enabled" unter "about:config" aktiviert werden.
Um eine Bezahlanfrage zu formulieren, erstellt man eine Instanz von PaymentRequest, wobei dem Konstruktor drei Konfigurationsobjekte als Parameter übergeben werden können:
const methodData = { /* siehe Listings unten */ };
const details = { /* siehe Listings unten */ };
const options = { /* siehe Listings unten */ };
const paymentRequest = new PaymentRequest(
methodData,
details,
options
);
Über methodData lassen sich die zur Verfügung stehenden Bezahlmethoden angeben. Der Eigenschaft supportedMethods kann dabei ein Array von Kennzeichnern für unterstützte Bezahlmethoden hinterlegt werden:
// Konfiguration der Bezahlmethoden
const methodData = [
{
supportedMethods: ['basic-card'],
data: {
supportedNetworks: ['visa', 'mastercard'],
supportedTypes: ['debit', 'credit'],
}
}
];
Nähere Angaben zu der Bestellung wie etwa Identifikationsnummer einer Bestellung, die zu bestellenden Artikel, Versandkosten etc. lassen sich über das Konfigurationsobjekt details konfigurieren:
// Konfiguration der Bestelldetails
const details = {
id: 'order-123-12312',
displayItems: [
{
label: 'Summe',
amount: { currency: 'EUR', value: '25.00' },
},
{
label: 'Mehrwertsteuer',
amount: { currency: 'EUR', value: '4.75' },
},
],
shippingOptions: [
{
id: 'standard',
label: 'Standardversand',
amount: { currency: 'EUR', value: '5.00' },
selected: true,
},
{
id: 'express',
label: 'Expressversand',
amount: { currency: 'EUR', value: '11.00' },
},
],
total: {
label: 'Gesamtsumme',
amount: { currency: 'EUR', value: '34.75' },
},
};
Über das dritte Konfigurationsobjekt options lässt sich definieren, welche Informationen der Nutzer während des Bestellvorgangs eingeben muss, beispielsweise Name, E-Mail-Adresse oder Telefonnummer:
// Konfiguration der Pflichtangaben
const options = {
requestPayerEmail: true,
requestPayerName: true,
requestPayerPhone: true,
requestShipping: true,
};
Um eine Bezahlanfrage zu starten und damit den entsprechenden Dialog zu öffnen, verwendet man die Methode show() am PaymentRequest-Objekt. Zurück gibt die Methode ein Promise-Objekt, das erfüllt wird, wenn der Nutzer den Bezahlprozess über den Dialog abschließt. Innerhalb des darauf folgenden Callbacks lässt sich dann auf die vom Nutzer eingegebenen Daten zugreifen, üblicherweise um sie zur Überprüfung an den Server zu senden (im Folgenden durch den Aufruf von verify() symbolisiert).
// Hier normalerweise Überprüfung durch Server
const verify = (paymentResponse) => Promise.resolve(true);
Der Aufruf der Methode complete() teilt dem Browser anschließend mit, dass der Bezahlprozess abgeschlossen wurde. Als Parameter lassen sich hier die Werte "success" für eine erfolgreiche Bezahlung oder "failure" bei Auftreten eines Fehlers übergeben. Dem Browser steht es laut Spezifikation dann frei, ob er eine entsprechende Meldung anzeigt oder nicht.
paymentRequest.show()
.then((paymentResponse) => {
// Zugriff auf die vom Nutzer
// eingegebenen Daten.
const {
requestId,
methodName,
details,
shipping,
shippingOption,
payerName,
payerEmail,
payerPhone
} = paymentResponse;
// verify() als imaginäre Funktion, mit der
// die Bezahlanfrage mit der Serverseite überprüft wird
verify(paymentResponse).then((success) => {
if (success) {
console.log('Bezahlung erfolgreich durchgeführt');
return paymentResponse.complete('success');
} else {
console.error('Fehler bei Bezahlung');
return paymentResponse.complete('failure');
}
});
})
.catch((error) => {
console.error('Fehler:', error);
});
Die Payment Request API will Bestell- bzw. Bezahlprozesse innerhalb von Webanwendungen vereinfachen und vereinheitlichen. Wer die API heute schon testen möchte, kann den oben gezeigten Code in einem der zuvor genannten Browser ausführen. Anmerkungen und Verbesserungsvorschläge zur API kann man übrigens über die Issue-Seite [4] des entsprechenden GitHub-Projekts loswerden.
URL dieses Artikels:http://www.heise.de/-3694012
Links in diesem Artikel:[1] https://www.w3.org/TR/payment-request/[2] https://www.w3.org/TR/payment-method-id/[3] http://caniuse.com/#feat=payment-request[4] https://github.com/w3c/browser-payment-api/issues
Copyright © 2017 Heise Medien
Gemeinsame Verantwortung für Code hört sich nach einer gute Idee an. Aber sie ignoriert wichtige Konzepte der Softwareentwicklung.
Collective Code Ownership stammt aus dem Extreme Programming (XP), einer frühen agilen Methode. Es bedeutet, dass alle Entwickler jedes Problem beheben müssen, das sie im Code finden. Gemeinsam die Verantwortung für ein System zu übernehmen, sorgt dafür, das Probleme beseitigt werden, statt sie einfach hinzunehmen. Moderne Ansätze für Projektarbeit setzten auf eigenverantwortliche Teams. Dafür ist bei Softwareentwicklung die Verantwortung für den Code sicherlich zentral.
Woher wissen die Entwickler, was verbessert werden muss und wie das geschehen soll? Im Buch "Extreme Programming Explained" von Kent Beck steht, dass nicht alle Entwickler Experten für jeden Codeteil sein können, aber sie müssen zumindest ein grundlegendes Verständnis für den gesamten Code haben.
Wissen über den gesamten Code widerspricht dem Information Hiding, das schon in einem anderen Beitrag[1] eine Rolle gespielt hat. Information Hiding bedeutet, dass Nutzer eines Moduls nur die Schnittstelle kennen, aber nicht die Interna. Das erleichtert die Nutzung des Modul, weil Nutzer weniger über das Modul wissen muss. Das Modul ist auch einfacher änderbar. Änderungen sind ohne Beeinträchtigung der Nutzer des Moduls möglich, so lange die Schnittstelle unverändert bleibt.
Collective Code Ownership fordert aber mehr als nur Wissen über die Schnittstelle. Jeder muss die Interna aller Module zumindest oberflächlich verstehen. Welche Alternativen gibt es?
Für jedes Modul könnte ein Entwickler verantwortlich sein. Das hat entscheidende Nachteile. Wenn die zuständigen Entwickler Urlaub haben oder krank werden, wird es schwierig, das Modul zu ändern, weil nur sie das Modul verstehen.
Eine Lösung ist, dass mehrere Entwickler jedes Modul kennen, aber nicht alle Entwickler jedes Modul kennen. Die Organisation spielt dabei eine wichtige Rolle: Das Gesetz von Conway[2] besagt, dass die Softwarearchitektur den Kommunikationsbeziehungen unter den Entwicklern entspricht. Die These: Entwickler sind jeweils für ein oder mehrere Module zuständig und müssen miteinander reden, wenn sie Module anderer Entwickler nutzen wollen. Auch das widerspricht dem Collective Code Ownership, weil nicht jeder Entwickler jeden Code versteht oder gar ändern kann
Kommunikation innerhalb eines Teams ist einfacher. Sie arbeiten oft in denselben Räumlichkeiten und haben gemeinsame Meetings. Das erleichtert die Kommunikation. Bessere Kommunikation kann nach dem Gesetz von Conway Auswirkungen auf die Architektur haben. Wenn Entwickler aus einem Team den Code anderer Teammitglieder kennen, kann das ein Zeichen guter Zusammenarbeit im Team sein. Wenn die Entwickler die Module anderer Teams kennen müssen, dann ist dazu aufwendige Kommunikation wie während extra organisierter Meetings notwendig. Also sollte Collective Code Ownership auf Teams beschränkt sein und nicht die gesamte Organisation umfassen.
Collective Code Ownership bedeutet, Verantwortung für Code zu übernehmen und Code zu verbessern. Das ist ein gute Sache. Den gesamten Code zu verstehen, ist dank Modularisierung zum Glück nicht notwendig.
URL dieses Artikels:http://www.heise.de/-3909449
Links in diesem Artikel:[1] https://www.heise.de/developer/artikel/Meine-Datenbank-gehoert-mir-3608372.html[2] http://www.melconway.com/Home/Conways_Law.html
Copyright © 2017 Heise Medien
Die Independent System Architecture (ISA) stellt Prinzipien für Microservices auf. ISA definiert grundlegende Eigenschaften von Microservices, die erhebliche Probleme aufwerfen, wenn sie nicht eingehalten werden.
Das Ziel ist, die fundamentalen Konzepte von Microservices darzustellen und nicht nur einen bestimmten Ansatz, Microservices umzusetzen, wie dies Self-contained Systems[1] (SCS) tun. SCS waren schon Thema eines anderen Blog-Beitrags[2].
Es gibt neun Prinzipien:
1. Das System ist in Module aufgeteilt. Module sind eine alte Idee. Das erste Prinzip stellt Microservices in diese Tradition. So wird deutlich, dass andere Modularisierungsansätze Alternativen zu Microservices sein können. Wegen des Modulbegriff treffen auch Konzepte wie Information Hiding auf Microservices zu. Microservices dürfen daher nicht von den Interna anderer Microservices abhängen. Beispiel: Wie Klassen in einem OO-System keine internen Daten anderer Klassen (Instanzvariablen) nutzen dürfen, so dürfen Microservices nicht Daten anderer Microservices direkt auslesen, indem sie beispielsweise auf die Datenbank-Schemata des Microservice zugreifen.
2. Die Module laufen als Docker-Container, Prozesse oder virtuelle Maschinen. Also würde ein Bestellprozess-Modul beispielsweise in einem eigenen Docker-Container laufen. Diese Implementierung unterscheidet ISA fundamental von anderen Modularisierungen und hat einige Vorteile. Beispielsweise können Module in unterschiedlichen Programmiersprachen geschrieben sein oder unabhängig voneinander deployt werden.
3. Die Architektur wird in die Mikro-Architektur, die nur einzelne Module betrifft, und die Makro-Architektur unterteilt, die das gesamte System umfasst. Die Makro-Architektur gibt die minimalen Regeln vor, um die langfristige Evolution sicherzustellen und zu garantieren, dass das System nach außen wie ein System erscheint. Die weiteren Prinzipien sind Teile der Makro-Architektur.
4. Die Integration der Module muss definiert sein. Die Module können synchron, asynchron oder auf der UI-Ebene integriert werden. Das ist notwendig, damit das System am Ende tatsächlich ein System ist und nicht etwa nur Module ohne Zusammenhalt.
5. Kommunikation beispielsweise per RESTful HTTP oder Messaging muss ebenfalls standardisiert sein, damit die Module miteinander kommunizieren können.
6. Jedes Modul hat eine eigene Continuous Delivery Pipeline. Die Module können prinzipiell unabhängig voneinander deployt werden, weil sie als Container umgesetzt sind. Mit einer getrennten Continuous Delivery Pipeline ist ein getrenntes Deployment auch tatsächlich möglich. Da die Pipeline vor allem Tests umfasst, müssen also insbesondere die Test der Module unabhängig voneinander sein.
7. Der Betrieb sollte standardisiert sein. Das betrifft zum Beispiel Logs, Monitoring, Konfiguration und Deployment. Die Standardisierung reduziert den Aufwand, weil so zwar die Anzahl der Containern steigt, aber sie zumindest einheitlich behandelt werden können.
8. Alle Standards sollen auf Ebene der Schnittstelle definiert sein. Eine Kommunikation per RESTful HTTP mit einem festen Datenschema oder ein bestimmtes Monitoring-System auf einem bestimmten Server sind Standardisierungen auf Ebene der Schnittstelle. Wenn die konkrete REST-Bibliothek oder eine Bibliothek für Monitoring vorgegeben wird, wird die Technologie standardisiert. Das schränkt die mit ISA gewonnenen Freiheiten ein. In einem Projekt kann sich natürlich dennoch ein einheitlicher Technologie-Stack durchsetzen und so Aufwände einsparen. Langfristig kann der Stack bei der Evolution des Systems durch einen anderen Stack abgelöst oder ergänzt werden, ohne die Standards zu verletzen. So kann der Technologie-Stack aktualisiert werden, und das System bleibt zukunftssicher.
9. Resilience ist die Fähigkeit eines Moduls, bei einem Ausfall eines anderen Moduls weiter zu funktionieren - gegebenenfalls mit schlechteren Ergebnissen. Das unterbindet Fehlerkaskaden, bei denen der Ausfall eines Moduls andere Module ebenfalls zum Ausfall bringt und so das gesamte System letztendlich ausfällt. Ebenso müssen Module damit umgehen können, dass sie auf einen anderen Server neu gestartet werden. Das erleichtert den Betrieb im Cluster, bei dem Module auf unterschiedlichen Servern laufen müssen und gegebenenfalls Server ausfallen oder gewartet werden müssen.
Dieser Blog-Beitrag bietet nur eine Einführung in die ISA-Prinzipien. Weitere Informationen finden sich unter isa-principles.org[3]. Insbesondere die Begründungen sind für ein besseres Verständnis interessant.
Die gesamte Website steht unter Creative Commons Attribution Share Alike. Der Quellcode der Website findet sich auf GitHub[4] wieder. Wer Verbesserungsvorschläge oder Kritik hat, kann einen Issue einstellen, einen Pull Request erstellen oder an der Diskussion[5] teilnehmen. Ebenso gibt es eine Präsentation[6], die man auch als PowerPoint[7] herunterladen kann und die ebenfalls unter Creative Commons Attribution Share Alike steht.
URL dieses Artikels:http://www.heise.de/-3889160
Links in diesem Artikel:[1] http://scs-architecture.org[2] https://www.heise.de/developer/artikel/Self-contained-Systems-ein-Architekturstil-stellt-sich-vor-3038718.html[3] http://isa-principles.org[4] https://github.com/ISA-Principles/isa-principles.org/[5] http://isa-principles.org/discussion.html[6] http://isa-principles.org/slidedeck/ISA.pptx[7] https://speakerdeck.com/isaprinciples/isa-principles
Copyright © 2017 Heise Medien

iX richtet sich an IT-Profis, gibt tiefe Einblicke und Orientierung in aktuelle IT-Entwicklungen. iX-Nutzer schätzen insbesondere den starken Praxisbezug und den unabhängigen Journalismus. Zu den treuen Lesern zählen IT-Leiter, Softwareentwickler, Systemadmins sowie Security-Spezialisten. Es erscheint monatlich - gedruckt und digital.
Jetzt sichern!
Die zweite Developer Preview von ARCore bringt neben erweiterten Funktionen eine C-API für Android. Das Projekt Tango ist nun endgültig Geschichte: Der Internetriese stellt den Support für das ambitionierte, frühe AR-Projekt ein.
Nachdem Google bereits im Sommer beschlossen hatte[1], die AR-Plattform (Augmented Reality) Tango durch das deutlich einfachere ARCore zu ersetzen, verkündet ein Blogbeitrag[2] nun das endgültige Aus für Tango mit dem Einstellen des Supports für das bereits 2014 offiziell gestartete AR-System. Die Erfahrungen aus dem Projekt, das mit Johnny Chung Lee einen ausgewiesenen Experten für Mensch-Computer-Interaktion als Leiter hatte, sind in ARCore eingeflossen. Lee war zuvor maßgeblich in Microsofts Kinect-Entwicklung eingebunden, ist aber wohl nicht in Googles aktuelle AR-Plattform involviert.
Mit dem Plattformwechsel verspiele der Internetriese auch den Vorsprung gegenüber Apple: ARKit ist zwar erst seit iOS 11 verfügbar, dafür läuft es inzwischen funktionsfähig auf mehreren Millionen Geräten. Google hat von ARCore dagegen noch keine Variante für Android-Endanwender, sondern veröffentlicht nun die zweite Developer Preview der Plattform. Allerdings wird der Internetriese wohl das Tempo noch weiter anziehen, um ebenfalls eine breite Palette an Endgeräten zu bedienen. Der Vorteil von ARCore gegenüber Tango ist, dass die Plattform keine spezielle Hardware benötigt, sondern lediglich die standardmäßig verfügbaren Sensoren und die Kamera nutzt.
Die zweite Developer Preview von ARCore bringt zudem erstmals eine Anbindung an die C-API für Android, sodass Entwickler AR-Anwendungen künftig mit dem Android NDK (Native Development Kit) schreiben können. ARCore lässt sich bereits mit Java sowie den Game-Engines Unity[3] und Unreal[4] verwenden. Auch Telerik entwickelt ein AR-Plug-in für NativeScript [5], das sowohl mit ARKit als auch mit ARCore zusammenarbeitet. Ebenfalls neu in der zweiten Developer Preview ist die Möglichkeit, AR-Sessions zu pausieren, um beispielsweise Anrufe anzunehmen. Außerdem vermeldet der Blogbeitrag eine erhöhte Genauigkeit und eine bessere Effizienz.
Ein genaues Datum für die Veröffentlichung von ARCore v1.0 bleibt der Blogbeitrag schuldig, stattdessen heißt es vage "innerhalb der nächsten Monate". Die ARCore-Projektseite[6] zeigt einige erste Anwendungen, und Google AR-Entwickler-Site[7] bietet Einstiegshilfen für Programmierer. Gerade die Anbindung an Unity und Unreal dürfte für Entwickler spannend sein, da sie damit ihre Mixed-Reality-Spiele plattformübergreifend für Apples und Googles Mobilsystem sowie möglicherweise zusätzlich für Windows Mixed Reality schreiben können.
URL dieses Artikels:http://www.heise.de/-3920207
Links in diesem Artikel:[1] https://www.heise.de/meldung/Googles-Augmented-Reality-Tango-ist-tot-es-lebe-ARCore-3817226.html[2] https://www.blog.google/products/google-vr/arcore-developer-preview-2/[3] https://www.heise.de/meldung/Spiele-Engine-Unity-2017-2-zielt-vor-allem-auf-2D-Entwicklung-und-Extended-Reality-3860769.html[4] https://www.heise.de/meldung/Unreal-Engine-4-18-bringt-verbesserte-Lichteffekte-3871165.html[5] https://www.heise.de/meldung/Cross-Platform-Entwicklung-NativeScript-bekommt-ein-AR-Plug-in-3829393.html[6] https://thisisarcore.com/[7] https://developers.google.com/ar/[8] mailto:rme@ct.de
Copyright © 2017 Heise Medien

(Bild: Google)
Google stellt die Entwicklung seiner Augmented-Reality-Umgebung "Tango" für Smartphones wie erwartet ein. Der Support endet am 1. März 2018. Das Nachfolgeprojekt "ARCore" stand bereits fest.
Das Augmented-Reality-Projekt "Tango" ist bald Geschichte: Google hat die Weiterentwicklung eingestellt und wird den Support am 1. März 2018 beenden [1], wie es im Entwicklerblog heißt. Dass Google seine ambitionierte AR-Plattform aufgeben wird [2], hatte sich bereits seit Längerem abgezeichnet. In Gestalt von ARCore [3] steht auch schon ein Nachfolger fest – ein technisch einfacheres System, das offensichtlich besser für den Massenmarkt taugt, da es auf zahlreichen Android-Geräten funktioniert.
Mit ARCore versucht Google, mit Apples ARKit [4] Schritt zu halten, das auf allen aktuellen iPhones funktioniert. Für Tango hingegen sind spezielle Smartphones notwendig. Doch es mangelte offenbar an Hardware-Herstellern, die sich von den Vorzügen dieser speziellen Plattform zum Einblenden virtueller Objekte in die Darstellung der realen Umgebung auf dem Mobilgerät überzeugen ließen.
URL dieses Artikels:
https://www.heise.de/ix/meldung/Google-gibt-AR-Plattform-Tango-auf-3919801.html
Links in diesem Artikel:
[1] https://plus.google.com/+ProjectTango/posts/SE8SHaDKLmu
[2] https://www.heise.de/ix/meldung/Googles-Augmented-Reality-Tango-ist-tot-es-lebe-ARCore-3817226.html
[3] https://developers.google.com/ar/
[4] https://www.heise.de/ix/meldung/ARKit-Schlaegt-Apple-Google-3771409.html
[5] mailto:un@ix.de

(Bild: Volker Weber )
Die größte Befürchtung der BlackBerry-Kritiker trifft ein. Genau zwei Jahre nach Vorstellung des PRIV beendet BlackBerry die Versorgung mit monatlichen Updates. Alternativen gibt es nicht.
BlackBerry stellt keine Smartphones mehr her. Von den BlackBerry-10-Geräten gibt es noch Restbestände, die ersten drei Android-Geräte PRIV[1], DTEK50[2] und DTEK60[3] sind im Abverkauf. Und nun lässt Alex Thurber die Bombe platzen. Er ist als Senior Vice-President and General Manager für die Mobility Solutions Division bei BlackBerry verantwortlich. Für den PRIV enden die monatlichen Updates[4]. Man kann sich ausrechnen, dass es den beiden anderen Geräten DTEK50 und DTEK60 genauso gehen wird, wenn die 24 Monate erreicht sind.
Als uns Thurber vor 14 Monaten ein Interview[5] gab, klang das alles noch ganz anders: "Wir unterstützen alle Produkte mindestens zwei Jahre über EOL (End of life) hinaus. Und dieser EOL liegt irgendwann in der Zukunft, er ist gar nicht abzusehen." Updates auf Nougat stellte Thurber ebenfalls in Aussicht. "Es läuft bereits in unserem Labor und wir arbeiten eng mit Google an unserer Weiterentwicklung." Auch das ist nicht passiert[6].
Mit dem Auslaufen der Sicherheits-Updates sind die Geräte keineswegs mehr so sicher, wie BlackBerry gerne in Anspruch nimmt. Und Alternativen gibt es nicht, da sich keine andere Firmware auf die Geräte spielen lässt. Das einzige Angebot, dass Thurber in Aussicht stellt, ist ein Upgrade-Programm auf KEYone[7] und Motion[8], die Geräte von TCL-Partner BlackBerry Mobile. Aber auch die haben nichts anderes versprochen als 24 Monate ab Vorstellung und ein Oreo Update nächstes Jahr.
(Volker Weber) /
URL dieses Artikels:http://www.heise.de/-3919087
Links in diesem Artikel:[1] https://www.heise.de/preisvergleich/blackberry-priv-schwarz-a1341632.html?hocid=newsticker&wt_mc=intern.newsticker.textlink-pvg.pvg_a1341632[2] https://www.heise.de/preisvergleich/blackberry-dtek50-schwarz-a1482972.html?hocid=newsticker&wt_mc=intern.newsticker.textlink-pvg.pvg_a1482972[3] https://www.heise.de/preisvergleich/blackberry-dtek60-schwarz-a1517352.html?hocid=newsticker&wt_mc=intern.newsticker.textlink-pvg.pvg_a1517352[4] http://blogs.blackberry.com/2017/12/status-of-priv-monthly-updates/[5] https://www.heise.de/meldung/BlackBerry-verspricht-Android-weitere-Updates-3341461.html[6] https://www.heise.de/meldung/Keine-Upgrades-mehr-fuer-BlackBerry-PRIV-3827231.html[7] https://www.heise.de/preisvergleich/blackberry-keyone-silber-a1584430.html?hocid=newsticker&wt_mc=intern.newsticker.textlink-pvg.pvg_a1584430[8] https://www.heise.de/preisvergleich/blackberry-motion-schwarz-a1706993.html?hocid=newsticker&wt_mc=intern.newsticker.textlink-pvg.pvg_a1706993[9] mailto:vowe@vowe.net
Copyright © 2017 Heise Medien

Mit der Freigabe des Programms der Konferenz zur Parallelprogrammierung wurde auch die Registrierung eröffnet. Mehr als ein Monat besteht nun Zeit, sich inklusive Frühbucherrabatt zu registrieren.
Das Programm der parallel 2018[1] steht nun online. Damit verbunden können sich interessierte Entwickler ab sofort für die Konferenz zur Parallelprogrammierung zum Frühbucherrabattpreis registrieren[2]. Die von heise Developer, iX und dem dpunkt.verlag von 6. bis 8. März 2018 organisierte Veranstaltung findet bereits zum siebten Mal statt – erneut in der Heidelberger Print Media Academy.
In ihrer siebten Auflage knüpft die parallel 2018 programmatisch am Charakter der bisherigen Ausgaben der Konferenz an. Im Programm finden sich verteilt auf zwei Tage über 30 Lang- und Kurzvorträge[3] zu Best Practises bei paralleler Programmierung, dem High-Performance Computing sowie aus dem spannenden Bereich des Deep beziehungsweise Machine Learning, wo sich einige der interessantesten Anwendungsszenarien im Bereich des parallelen Rechnens auftun. Einen Schwerpunkt bilden Vorträge zur Performance paralleler Anwendungen. Abgerundet wird das Programm durch zwei Keynotes.
Bis 20. Januar gilt für den Kauf des Konferenztickets noch ein Frühbucherpreis von 790 Euro: Statt des regulären Preises von 930 Euro lassen sich also für die zwei Konferenztage ganze 140 Euro sparen. Weiteren Rabatt gibt es bei der zusätzlichen Buchung eines von fünf Workshops am Vortag der Hauptkonferenz. Bei ihnen geht es um Themen wie die Programmiersprachen C++ und Java, die Wahl der richtigen Technik und Architektur für Projekte zur parallelen Programmierung sowie eine Schulung zur Entwicklung von robusten, nebenläufigen Systemen hoher Parallelität mit Erlang/OTP.
Wer über den weiteren Fortgang der Konferenz auf dem Laufenden gehalten werden möchte, kann sich über einen Newsletter[4] vormerken lassen oder den Veranstaltern auf Twitter[5] folgen.
Die Veranstalter der parallel sind heise Developer, iX und der dpunkt.verlag, die Teil der Heise Gruppe sind.
URL dieses Artikels:http://www.heise.de/-3918227
Links in diesem Artikel:[1] https://www.parallelcon.de/index.php[2] https://www.parallelcon.de/anmeldung.php[3] https://www.parallelcon.de/programm.php[4] https://www.parallelcon.de/benachrichtigen.php[5] https://twitter.com/parallelConf[6] mailto:map@heise.de
Copyright © 2017 Heise Medien

(Bild: Palo Alto Networks)
Kombinieren Angreifer drei Sicherheitslücken, könnten sie Firewalls von Palo Alto Networks kompromittieren, warnt ein Sicherheitsforscher.
Verschiedene Firewalls mit PAN-OS von Palto Alto Networks sind unter gewissen Umständen angreifbar. Das ist der Fall, wenn Admins das Management Interface so eingestellt haben, dass es aus dem Internet erreichbar ist. Das kommt häufig vor, warnt[1] ein Sicherheitsforscher. Derzeit sind fast 7000 Firewalls öffentlich erreichbar[2].
Angreifer könnten drei Sicherheitslücken zu einem gefährlichen Cocktail kombinieren. So sollen Attacken aus der Ferne ohne Authentifizierung möglich sein, die damit enden, dass Angreifer Code mit Root-Rechten auf betroffenen Firewalls ausführen können.
Die auf den Firewalls laufenden Betriebssystemversionen PAN-OS 6.1.19, 7.0.19, 7.1.14 und 8.0.6-h3 sind abgesichert. Alle vorigen Ausgaben sind bedroht, warnt[3] Palo Alto Networks.
[UPDATE, 15.12.2017 12:00 Uhr]
Weitere PAN-OS-Versionen hinzugefügt.
URL dieses Artikels:http://www.heise.de/-3918909
Links in diesem Artikel:[1] http://seclists.org/fulldisclosure/2017/Dec/38[2] https://www.shodan.io/report/mPWsUHOS[3] https://securityadvisories.paloaltonetworks.com/Home/Detail/102?AspxAutoDetectCookieSupport=1[4] mailto:des@heise.de
Copyright © 2017 Heise Medien

Bei der Weiterentwicklung des Java-Applikationsservers hat Red Hat den Fokus vor allem auf Performance und Sicherheit gelegt. Das aktuelle Enterprise Java spielt offenbar keine Rolle, aber HTTP/2 gehört nun zum Lieferumfang.
Red Hat hat Version 7.1 der JBoss Enterprise Application Platform (EAP) veröffentlicht. Trotz des vermeintlich kleinen Release-Schritts sind seit Version 7 inzwischen eineinhalb Jahre vergangen. Die im Bezug auf Java-Applikationsserver augenscheinlichste Neuerung seitdem ist die Veröffentlichung von Java EE 8 im September[1]. JBoss 7.1 setzt jedoch weiterhin auf Java EE 7. In den Release Notes[2] findet sich nicht einmal ein Verweis auf das aktuelle Enterprise Java.
Denkbar ist, dass Red Hat gleich den Nachfolger EE4J berücksichtigt, der als Open-Source-Projekt unter dem Dach der Eclipse Foundation entsteht[3]. So verweist der Red-Hat-Blog[4] auf den Übergang von Java EE zu EE4J. Oracles offizielle Liste[5] mit Java-EE-Servern und deren Kompatibilität zu den unterschiedlichen Versionen der Plattform ließ beim Schreiben dieses Beitrags einen Hinweis auf Java-EE-8-Server gänzlich vermissen.
Bei der Weiterentwicklung von JBoss standen wohl vor allem die Performance, Verfügbarkeit und Security im Fokus. So haben die Macher die Domain-Fehlertoleranz verbessert, indem der Applikationsserver automatisch die Host-Controller mit den Domain-Controllern über eine gecachete Konfiguration verbindet. Um den Status von Anwendungen besser zu überwachen, können Administratoren nun Listener-Module, darunter JMX-Listener (Java Management Extensions) registrieren.
Red Hat hat JBoss EAP um ein zusätzliches Subsystem für Security erweitert, das auf dem Community-Projekt WildFly Elytron[6] aufsetzt. Es enthält APIs und SPIs, über die Entwickler individuelle Funktionen integrieren können. Außerdem ermöglicht Elytron ein Container-verwaltetes Single-Sign-on-System und kann automatisch Zertifikate für Anwendungen ausstellen.
Eine der prominenten Neuerungen von Java EE 8 hat zumindest unabhängig von der offiziellen Plattform ihren Weg in JBoss EAP 7.1 gefunden: HTTP/2 ist eigentlich Bestandteil von Servlet 4.0, aber JBoss implementiert den Nachfolger des achtzehn Jahre alten HTTP/1.1 über die interne ALPN-Anbindung (Application Layer Protocol Negotiation), damit jedoch nur für OpenJDK und Oracle JDK, oder über JBoss Core Services OpenSSL, das allerdings nicht mit HP-UX zusammenarbeitet.
Siehe dazu auf heise Developer:
URL dieses Artikels:http://www.heise.de/-3918769
Links in diesem Artikel:[1] https://www.heise.de/meldung/Java-EE-8-ist-offiziell-erschienen-3838062.html[2] https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform/7.1/html-single/7.1.0_release_notes/[3] https://www.heise.de/meldung/Java-Enterprise-Edition-Java-EE-Nachfolger-EE4J-nimmt-Gestalt-an-3897130.html[4] https://www.redhat.com/en/blog/red-hat-releases-jboss-eap-71[5] http://www.oracle.com/technetwork/java/javaee/overview/compatibility-jsp-136984.html[6] https://docs.jboss.org/author/display/WFLY/WildFly+Elytron+Security[7] https://www.heise.de/meldung/Java-EE-8-ist-offiziell-erschienen-3838062.html[8] https://www.heise.de/meldung/Oracle-will-Java-EE-an-die-Open-Source-Community-uebertragen-3806673.html[9] https://www.heise.de/meldung/Java-Enterprise-Edition-Java-EE-Nachfolger-EE4J-nimmt-Gestalt-an-3897130.html[10] https://www.heise.de/developer/artikel/Mit-Java-auf-dem-HTTP-2-Zug-3918097.html[11] mailto:rme@ct.de
Copyright © 2017 Heise Medien