Eclipse: JPDA Port (nachträglich) herausfinden

Ich habe einige Play-Anwendungen im Terminal laufen, plus einer weiteren in Eclipse. Die in Eclipse würde ich gerne debuggen, wozu play eclipsify einen entsprechenden Launcher “Connect JPDA to myapp.launch” anlegt. Der Launcher enthält einen Port “0”:

Nun ist der Port (ich glaube, “0” wählt den default 8000, aber das kann falsch sein) nicht erreichbar, vielleicht ist er durch die Anwendungen im Terminal belegt. Vielleicht wählt “0” auch jedes mal einen zufälligen Port, ich kann das gerade nicht gegenprüfen. Wie auch immer, der Punkt ist:

Beim Start der Anwendung gibt es eine Ausgabe im Log à la

Listening for transport dt_socket at address: <port number>

Läuft die Anwendung lange genug, sehe ich diese Ausgabe aber nicht mehr – wie finde ich nun den Port heraus? Unter OS X wie folgt: Zuerst suche ich in der Aktivitätsanzeige alle “java”-Prozesse:

Uns interessiert derjenige, der zu Eclipse gehört (diese Ansicht wird per Doppelklick auf den Prozessnamen geöffnet):

Die Liste der “geöffneten Dateien und Ports” ist recht lang, aber der Eintrag sticht durch seine Kürze hervor: Voilà, der gesuchte Port.

PS: Man kann den Logger von Play natürlich auch so konfigurieren, dass es die Ausgabe in ein File schreibt, siehe hier (via). Hier brauchte ich aber die Möglichkeit den Port herauszufinden, ohne die Applikation neu zu starten.

Spring (Boot) erweitern

Angenommen, ich würde Web-Applikationen verkaufen. Zum Teil customized auf Basis desselben Cores, zum Teil unabhängig davon. Mein Code müsste also modular sein; ich möchte Libraries wieder­­verwenden, ganze Features ein- und ausschalten können, vielleicht Teile nur für einen Kunden überschreiben. Wie würde ich das wohl mit Spring Boot machen?

Sucht man im Internet nach Modularisierung von Spring (Boot) Anwendungen, landet man recht schnell bei Microservices:

While there is no precise definition of this architectural style, there are certain common characteristics […]: an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API.

Zuerst mal nützt mir das noch nichts für wiederzuverwendende Libraries. Aber selbst wenn, dann ist mir zugegebenermaßen nicht ganz klar, wie man sich das in einer Webapplikation vorzustellen hat: Kommuniziert jeder Teil der Anwendung (Chat, Kalender, …) nur mit “seinem” Backend, separiert zum Beispiel über Ports? Oder läuft alles über Port 80 an den Server, und der verteilt das intern an den jeweiligen Prozess? So oder so müsste man das anwendungsweit berücksichtigen (richtig?). Nicht falsch verstehen: Ich sehe die Vorteile (schnelles Austauschen eines Service, Ausfallsicherheit der Dach-Anwendung. Skalierbarkeit), will mich hier aber auf einen anderen Ansatz konzentrieren:

Denn “schöner” (im Sinne von gewohnter) wäre es, wenn man die einzelnen Module zu einer Anwendung zusammenstecken könnte, trotzdem mit den o.g. Eigenschaften… Und letztendlich ist das genau, wie Spring Boot an sich funktioniert: Per Maven (jaja, oder Gradle) konfiguriert man, welche “Starter” man braucht, und plötzlich hat man zB JPA-Support, kann die Adapter aber frei austauschen oder umkonfigurieren. Interessant wäre es “nur” noch, wie die Starter an sich aussehen (wie gut oder schnell lassen sie sich (weiter-)entwickeln?) und ob sie zB auch eigene URL-Endpoints erlauben (nötig für Module mit Frontendanbindung wie Kalender oder Chat).

Vorab – das geht alles.

  • Jeder Starter ist für sich eine vollwertige eigenständige Webanwendung, kann aber trotzdem ohne Änderung als Dependency eingebunden werden. Das macht das Entwickeln extrem komfortabel.
  • Die Dependencies bringen eigene Endpoints mit, die aber ebenfalls dynamisch “woanders hingeroutet” werden können. Konfiguration etc. ist ebenfalls, auch partiell, überschreibbar.
  • Es gibt im einbindenden Projekt keine zwingende Abhängigkeit im Code zum Starter. Man kann aber, und das sogar komfortabel über konditionale Annotations, darauf reagieren, ob eine Dependency da ist oder nicht. Und zB default-Implementierungen aus der Dependency überschreiben.

Im Detail: Hier gibt es ein exzellentes Tutorial, das ich mir erlaubt habe zu übernehmen; hier gibt es meine entzerrte, “white-label”-Implementierung der interessantesten Punkte:

  1. Jeder Starter (“Service A”, “Service B”) ist ein vollständiges Spring Boot Projekt, und standalone lauffähig. (“Some Projekt” ist natürlich auch standalone, allerdings müssen “Service A” und “Service B” in das lokale Repo installiert sein, siehe README)
  2. Wenn ein Starter in ein anderes Projekt eingebunden wird, muss man Spring sagen, welche Klasse die Basis-Konfiguration enthält. Dazu legt man /src/main/resources/META-INF/spring.factories an und hinterlegt die Klasse wie im Beispiel-Code.
  3. Um Namenskonflikte der Beans zu vermeiden, sollte man @ComponentScan.nameGenerator verwenden – zur Not tut es aber auch das name-Feld von @Component wie im Beispiel.
  4. Konfigurationsdateien werden per @PropertySource(“classpath:acme-aservice.properties”) eingebunden. Werte daraus werden per @Value(“${aservice.messages.test1}”) private String test1; injected oder bsplw. per @RequestMapping(“${aservice.mapping.url:/service-a}”) in einem dadurch konfigurierbaren Routing verwendet (nach dem Doppelpunkt folgt der default).
  5. Konfigurationsdateien können von haus aus nur komplett überschrieben werden, indem sie unter demselben Dateinamen im Rahmenprojekt abgelegt werden. In der Beispielimplementierung habe ich eine Methode @PostConstruct public void initialize() in “Some Project”, die das aufbohrt, und das Überschreiben von einzelnen Settings erlaubt, auch wenn diese in einer anders benannten Datei definiert sind.
  6. Das folgende Konstrukt in com.acme.bservice.IndexController erlaubt das Ersetzen von Beispielimplementierungen (MessageProvider ist ein Interface):
        @Autowired(required = false)
         public void setMessageProvider(MessageProvider messageProvider)
    Ersetzt wird der default dann völlig transparent, indem man nur das Interface MessageProvider implementiert und die Implementierung als @Component annotiert.

Für Details der Implementierung siehe Code auf Github – der ist wirklich überschaubar: “Service A” hat zwei Klassen plus eine Config, “Service B” drei Klassen, “Some Project” zwei Klassen plus Config :-)

Gson: JSON-Serializer für bestimmte Typen überschreiben

Play nutzt (zumindest in Version 1.3?) Gson für JSON-Serialisierung. Gson macht aus Float.NaN die Zahl NaN, was für JSON nicht erlaubt ist:

play.exceptions.JavaExecutionException: NaN is not a valid double value as per JSON specification. To override this behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method.

Schöner wäre es, daraus den String “NaN” zu machen.

Ansatz 1, wie empfohlen:

Gleicher Fehler. Deshalb Ansatz 2:

mit:

und DoubleSerializer analog.

Spring Data JPA: Subqueries

JPQL-Subqueries können nicht im FROM stehen – aber Native Queries haben diese Einschränkung nicht (zwingend). Klar, denn native Queries sind eben nativ, sprich in der Sprache der jeweiligen Datenbank. Wer also damit leben kann, die Portabilität zu verlieren, der kann wie folgt “beliebige” Queries verwenden:

Ajax Interceptor mit jQuery und Angular

jQuery:

Angular:

Für die CSRF-Token siehe hier.