Eine gängige Anforderung in Projekten ist der Datenaustausch mit Fremdsystemen und externen Partnern. IT-Systeme arbeiten schon lange nicht mehr isoliert vom Rest der Welt sondern sind oft hochintegriert, genau wie die Geschäftsprozesse, die sie unterstützen. Obwohl die Technologie der Wahl für den Austausch momentan eher Webservices oder REST-Services sein dürften, ist man als Entwickler nicht immer frei in der Wahl der Kommunikationsmittel. Für manche Zwecke haben eher althergebrachte Technologien wie FTP/SFTP oder auch E-Mail (siehe Versand von E-Mails mit Spring Batch ) durchaus ihre Daseinsberechtigung.
In diesem Artikel wird gezeigt, wie sich mit Hilfe von Spring Batch und Spring Integration ein SFTP-Upload realisieren lässt.
Wie in Spring Batch üblich, benötigt man einen Marshaller mit Reader und Writer. Die Zuständigkeit des Readers ist es, die zu transferierenden Daten aus der Datenbank auszulesen. Dazu bedient er sich eines RowMappers, der die Daten, die die Datenbank-Abfrage als Resultat liefert, in ein Domänen-Objekt transferiert.
Der Reader:
Der RowMapper, welcher vom Reader verwendet wird:
Das Domänen-Objekt, welches vom Reader verwendet wird:
Der Writer schreibt die Daten der Domänen-Objekte in eine CSV-Datei (hier sind natürlich auch beliebige andere Formate denkbar). Hierzu benutzt er den DelimitedLineAggregator aus dem Spring Batch Framework. Damit die CSV-Datei auch eine Kopfzeile bekommt, benutzen wir zusätzlich das Property headerCallback.
Der Writer:
Für die Erzeugung der Kopfzeile (s. o.) benutzen wir folgenden, denkbar einfachen Code:
Der eigentliche Versand per SFTP schließlich wird durch die SftpSessionFactory geregelt, welche auch die Zugangsdaten für den SFTP-Server als Properties bekommt.
Des Weiteren benötigt man einen Channel, welcher für den Versand der Daten verwendet wird. Das channel-Tag kommt aus dem Spring Integration Namensraum, der im XML-Header der applicationContext.xml deklariert werden muss (s. u.).
Damit Spring Batch auch weiß, auf welchem Weg der Versand erfolgen soll, muss man dies Spring Batch mitteilen. Hierfür verwendet man einen „outbound-channel-adapter“, welcher den Versandweg, die Referenz zur SftpSessionFactory und den Dateinamen für den Zielserver (remote-filename-generator) beinhaltet.
Wenn man es einfach halten möchte, speichert man die Datei auf dem Zielserver mit dem gleichen Namen wie auf dem sendenden Server. Hierfür benötigt man nur den DefaultFileNameGenerator von Spring Integration.
Um die Datei nun wirklich zu versenden, benötigt man noch ein Tasklet und den eigentlichen Batch Job. Für das Tasklet kann man eine kleine Java Klasse verwenden, welcher man den Dateinamen und den Channel als Parameter mitgibt.
Deklaration des Tasklets:
Der Javacode des Tasklets:
Und zu guter Letzt der XML-Code des Batch-Jobs:
Diesen Batch Job kann man nun wie gewohnt von der Kommandozeile (also z. B. auch als cronjob) starten.
Zur Vollständigkeit hier noch der Header-Teil der applicationContext.xml mit allen benötigten Namespace-Deklarationen:
Blog-Autor*in
Carsten Fröhlich
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.
Du hast noch Fragen zu diesem Thema? Dann sprich mich einfach an.