Unser Blog ist umgezogen
2024/04/11 Hinterlasse einen Kommentar
Wir haben eine neue Adresse für unser Blog: https://gedoplan.de/javablog/.
Diese Seite wird noch für eine Weile online bleiben, aber neue Posts gibt’s nur noch dort.
Hier finden sich Neuigkeiten, Ideen und Kommentare rund um Java EE
2024/04/11 Hinterlasse einen Kommentar
Wir haben eine neue Adresse für unser Blog: https://gedoplan.de/javablog/.
Diese Seite wird noch für eine Weile online bleiben, aber neue Posts gibt’s nur noch dort.
2024/01/03 Hinterlasse einen Kommentar
Diese Reihe wirft einen kurzen Blick auf einige Highlights der Angular Versionen 16 und 17. Heute: „signals“.
Bereits in Version 16 enthalten und mit Version 17 als „stable“ deklariert sind „signals“ der neue reaktive Weg Daten in unseren Controllern zu verarbeiten. Neben diesem reaktiven Ansatz, der uns in vielen Fällen davon entbindet, mit zusätzlichen Observables zu arbeiten, wurde bei der Entwicklung auf die Optimierung der ChangeDetection abgezielt, die in Zukunft auf Basis von signals weiter optimiert wird.
Signals sind einfach ausgedrückt, ein generischer Wrapper der (ähnlich wie ein BehaviourSubject) einen initialen Wert entgegennimmt, auf dessen Änderung sich andere Programmteile registrieren können:
someId = signal(1);
material = signal({id: 5, name: 'some material'});
Der Abruf erfolgt dann als Methodenaufruf
<p>Id from signal: {{material().id}}</p>
(Allgemein wird von jeglichen Methodenaufrufen aus Gründen der Performance/ChangeDetection im Template abgeraten. Im Fall der Signals (genau wie bei gettern) wird ausdrücklich „Entwarnung“ gegeben).
Aktualisierungen der signal-Werte erfolgt über spezielle Methoden. Dabei wird empfohlen, mit immutable objects zu arbeiten, um unerwünschte Seiteneffekte bei der Weiterverarbeitung der Daten zu verhindern. Zwei Methoden existieren
this.material.update(current => {
const newMaterial = Object.assign({}, current);
newMaterial.id++;
return newMaterial;
})
//or
this.material.set({
id: 200,
name: 'some other'
});
Neben dem einfachen Lesen des Wertes lässt sich nun noch sehr einfach auf die Änderung der signal-Werte reagieren, ähnlich wie wir es mit einem zusätzlichen Observable/Subject realisieren würden.
materialLabel = computed(() => `${this.material().id}:${this.material().name}`);
constructor(myService: MyService) {
effect(() => {
console.log('Value has been changed...');
})
}
Sollten wir innerhalb unserer signals mit mutable objects arbeiten, ist etwas Vorsicht geboten. Im Standard erfolgt die Erkennung, ob sich der Wert eines signals geändert hat anhand von Objektgleichheit (===), „compute“ und „effect“ Abhängigkeiten werden also nicht aktualisiert, wenn wir z.B. Objekt-Attribute ändern. Bei der Deklaration des signals können wir jedoch zusätzlich einen equals-callback angeben, mit dessen Hilfe wir entscheiden können, ob ein Objekt sich geändert hat
material = signal({id: 5, name: 'some material'}, {equal: (a, b) => a.id === b.id});
Soweit so gut. Signals werden in Zukunft ein integraler Bestandteil unserer Angular-Anwendungen werden und die Möglichkeiten sind noch lange nicht ausgeschöpft. Besonders interessant: die Verwendung von signals als Alternative zu klassischem @Input-/@Output-Binding, die auf der Roadmap der Entwickler steht ( https://github.com/angular/angular/discussions/49682 ) Bleiben wir gespannt.
Wie immer. Live. In Farbe. bei Github
2023/12/15 Hinterlasse einen Kommentar
Application Server werden häufig als schwergewichtig characterisiert, was aber nicht an ihrer Größe liegt, sondern daran, dass man zum Betrieb einer Enterprise-Applikation zunächst einen Server installieren und konfigurieren muss, bevor die Anwendung darauf deployt werden kann.
Man kann die Vorbereitung allerdings auch im Anwendungsprojekt erledigen und automatisieren, sodass der zusätzliche Aufwand im Betrieb entfällt. Das geht bspw. mit einem Maven-Plugin für WildFly:
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-jar-maven-plugin</artifactId>
<version>10.0.0.Final</version>
<configuration>
<feature-packs>
<feature-pack>
<location>wildfly@maven(org.jboss.universe:community-universe)#27.0.1.Final</location>
</feature-pack>
</feature-packs>
<layers>
<layer>jaxrs</layer>
<layer>cdi</layer>
</layers>
<output-file-name>wildfly-bootable.jar</output-file-name>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
Ein mvn package erzeugt nun zusätzlich zum normalen Ergebnis des Builds – i. A. ein war-File – die Datei wildfly-bootable.jar, die den Server inklusive der Anwendung enthält. Sie kann mit java -jar wildfly-bootable.jar gestartet werden.
Wie oben zu sehen ist, wird der Server aus sog. Layers zusammengesetzt. Somit kann man also einen Server genau auf die Anwendung zuschneiden und die Teile weglassen, die nicht benötigt werden.
Weitere Möglichkeiten sind u.a.:
Weitere Details s. https://docs.wildfly.org/27/Bootable_Guide.html.
Wir nutzen das Plugin und insb. den Development Mode seit einiger Zeit in unseren Seminaren. Die Erfahrungen sind sehr gut. Angenehm ist, dass die Projekte ihre Serverkonfiguration mitbringen und für die Weiterentwicklung der Anwendungen keine besondere Integration in die IDE vonnöten ist.
2023/12/04 Hinterlasse einen Kommentar
Die Jakarta NoSQL Spezifikation hat das Ziel den Zugriff auf NoSQL-Datenbanken zu vereinheitlichen. Wollte man bisher bspw. eine MongoDB in seine Enterprise-Anwendung integrieren, musste man den proprietären Client dazu verwenden. Dieser arbeitete mit den entsprechenden Datentypen der MongoDB und den entsprechenden Zugriffsmechanismen. Damit verbunden ist immer eine Einarbeitung in die entsprechenden Eigenheiten eines solchen Clients.
Jakarta NoSQL liegt nun in einer ersten produktiven Version vor und wird voraussichtlich mit dem nächsten Jakarta EE 11 Release im nächsten Jahr veröffentlicht. In diesem Blogbeitrag möchte ich ein einfaches Beispiel für die Anbindung an eine dokumentenorientierte NoSQL-Datenbank beschreiben.
Wie üblich im Persistenzumfeld starten wir mit einer Entität:
@Entity
public class Customer {
@Id
private long id;
@Column
private String name;
@Column
private String street;
@Column
private String postcode;
@Column
private String city;
}
Der Zugriff auf die Datenbank kann nun entweder über eine Template-Klasse (DocumentTemplate) erfolgen. Oder es kann auf Basis der Jakarta Data Spezifikation ein Repository-Ansatz für den Zugriff gewählt werden.
Mit der Jakarta Data Spezifikation wurde ein vereinheitlichter Zugriff auf unterschiedliche Datenquellen definiert. Damit ist es möglich eine Implementierung auf Basis eines Interfaces automatisch generieren zu lassen.
@Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {
public List<Customer> findByName(String name);
}
Das CrudRepository-Interface definiert dabei die grundlegenden Zugriffsmethoden. Alle weiteren Methoden kann ich über eine entsprechende Namenskonvention ebenfalls automatisch implementieren lassen.
Die Verwendung kann dann einfach über eine DI an gewünschter Stelle erfolgen:
@Inject
CustomerRepository customerRepository;
...
customerRepository.findByName("Horst");
Die Kombination von Jakarta NoSQL und Jakarta Data ermöglicht den einfachen Einsatz von NoSQL-Datenbanken in Enterprise-Anwendungen. Über die Vereinheitlichung der NoSQL-Persistenzschicht und der Daten-Zugriffsschicht ist eine herstellerunabhängige Nutzung von NoSQL möglich.
Das Beispiel befindet sich in unserem Github-Repository.