Blog

Holen Sie das Java aus Ihrem Scala heraus

Jan Vermeir

Jan Vermeir

Aktualisiert Oktober 22, 2025
3 Minuten

Um die Konfiguration der Weblogic-Domänen und -Server bei meinem derzeitigen Kunden in den Griff zu bekommen, habe ich ein Tool entwickelt, das Domänenkonfigurationsdateien liest und in einen Graphen übersetzt. Ich beschloss, dieses Problem in Scala zu lösen, vor allem weil ich von den leistungsstarken nativen XML-Parsing-Funktionen gelesen hatte. Das Parsen von XML erwies sich als ein Kinderspiel, aber ich konnte etwas darüber lernen, wie man Probleme mit Scala lösen kann.

Um mein Problem zu lösen, musste ich die Konfigurationsdatei für eine Weblogic-Domäne analysieren, oder genauer gesagt (in meinem Fall) die Datei, in der Weblogic Informationen über JMS-Ressourcen speichert. Das Parsen einer dieser Dateien läuft folgendermaßen ab: [scala] val configData: Elem = XML.loadFile(jmsConfigFileName) [/scala] configData enthält nun eine geparste Version der Datei, deren Name in jmsConfigFileName gespeichert ist. Diese Datei enthält Dinge wie Warteschlangen- und Topic-Definitionen, wie das folgende Fragment: [xml] <Warteschlange name="queueTo"> <sub-deployment-name>domain</sub-deployment-name> <jndi-name>domain/jms/qto</jndi-name> </queue> <topic name="domainJMSTopic"> <sub-deployment-name>domain</sub-deployment-name> <jndi-name>domain/jms/topic</jndi-name> </topic> [/xml] Mein erster Versuch, alle Themendefinitionen aus dieser Konfigurationsdatei abzurufen, war folgender: [scala] def findTopics(configData: Elem): Set[JmsObject] = { val jmsObjects = for (topic <[/scala] - (configData "topic")) yield (new JmsTopic((topic "@name").text, (topic "jndi-name").text)) jmsObjects.toSet } Ich habe mich sehr gefreut, diese leistungsstarke und prägnante Schleife geschrieben zu haben. Das for-Konstrukt von Scala ist sehr leistungsfähig, ebenso wie sein XML-Parsing. Um die Warteschlangen abzurufen, habe ich die folgende Methode hinzugefügt: [scala] def findQueues(configData: Elem): Set[JmsObject] = { val jmsObjects = for (queue <[/scala] - (configData "queue")) yield (new JmsQueue((queue "@name").text, (queue "jndi-name").text)) jmsObjects.toSet } Die Duplizierung war offensichtlich, so dass ich mit meiner Lösung nicht ganz so glücklich war, aber ich konnte keinen einfachen Ausweg sehen. Da kam mein Kollege und Scala-Trainer Urs Peter ins Spiel. Er zeigte mir zwei Möglichkeiten zur Verbesserung des Codes. Unser erster Versuch sieht so aus: [scala] def buildListOfJmsObjectsFromConfigData[T] (configData:Elem, clazz:Class[T], startNode:String): Set[T] = { val jmsObjects = for (node <[/scala] - (configData startNode)) yield ( clazz.getConstructors.apply(0).newInstance( (node "@name").text , (node "jndi-name").text).asInstanceOf[T]) jmsObjects.toSet } Die Sie dann wie folgt aufrufen können: [scala] buildListOfJmsObjectsFromConfigData (configData, classOf[JmsConnectionFactory] , "connection-factory") [/scala] Das sah für mich ziemlich javamäßig aus, außerdem war es komplex und verschleiert. Unser zweiter Versuch entfernt die Schleife und verwendet Currying. Er sieht folgendermaßen aus: [scala] def buildListOfJmsObjectsFromConfigData[T] (configData:Elem, startNode:String) (f:(NodeSeq) => T): Set[T] = { (configData startNode).map(f).toSet } [/scala] Diese zweite Variante von buildListOfJmsObjectsFromConfigData[T] kann wie folgt aufgerufen werden: [scala] buildListOfJmsObjectsFromConfigData (configData, "topic") { node => new JmsTopic((node "@name").text, (node "jndi-name").text) } [/scala] Dies funktioniert, weil (configData startNode) einen Satz von Objekten liefert, auf denen wir map aufrufen. Map nimmt eine Funktion als Parameter an. Die oben gezeigte Funktion extrahiert ein JmsTopic-Objekt, so dass wir am Ende eine Sammlung von JmsTopic-Instanzen haben.Ich bin mit unserer endgültigen Version zufrieden. Sie ist prägnant und klar sowie erweiterbar; viel besser als meine erste Java-artige Version. Der Code ist hier angehängt. Ich habe drei Versionen erstellt, die in einem Einheitstest geübt werden. JmsConfigReaderV1 ist die erste Java-ähnliche Version, JmsConfigReaderV2 ist die kompakte, aber verschleierte Lösung und JmsConfigReaderV3 ist mein letzter Versuch. Ich bin sicher, dass es viele Möglichkeiten zur Verbesserung gibt, daher freue ich mich über Ihre Meinungen und Kommentare.

Verfasst von

Jan Vermeir

Developing software and infrastructure in teams, doing whatever it takes to get stable, safe and efficient systems in production.

Contact

Let’s discuss how we can support your journey.