Jekyll2019-01-09T19:43:50+01:00https://www.wizi.at/feed.xmlWizis BlogIch bin Java Backend Developer aus Leonding, Österreich. In diesem Blog geht es um die Entwicklung von Applikationen mit Java und dem Spring Framework.René WitzelspergerSpring Base Project by Wizi2018-03-03T13:37:00+01:002018-03-03T13:37:00+01:00https://www.wizi.at/blog/base-project<p>In diesem Beitrag möchte ich meine Projektstruktur vorstellen.</p>
<p>Bei meinen Projekten handelt es sich um Java / <a href="https://gradle.org" target="_blank">Gradle</a> / <a href="https://projects.spring.io/spring-boot" target="_blank">Spring Boot</a> Projekte. Die Basis der Projekte stellt somit immer das File <a href="https://github.com/wizison/blog-spring-boot-base-project/blob/master/build.gradle" target="_blank">build.gradle</a> da. In diesem File findet ihr die Konfiguration für die gesamte Applikation.<br />
Schon seit einigen Jahren verwendet ich als Entwicklungsumgebung <a href="https://www.jetbrains.com/idea/" target="_blank">IntelliJ IDEA</a>, habe aber auch schon mit der <a href="https://spring.io/tools/sts" target="_blank">Spring Tool Suite</a> bzw. <a href="https://eclipse.org/ide" target="_blank">Eclipse</a> gearbeitet. Da ich IntelliJ IDEA sowohl privat als auch in der Arbeit verwende, werde ich in meinen Beiträgen auch nur auf diese Entwicklungsumgebung eingehen.<br />
Da es sich bei den Projekten jedoch um Gradle Projekte handelt, könnt ihr diese auch in allen anderen Java Entwicklungsumgebungen mit Gradle Unterstützung öffnen (gegebenenfalls ist das File <code class="highlighter-rouge">build.gradle</code> anzupassen).<br />
Wie schon in meinem Beitrag “<a href="/blog/environments-with-spring-profiles">Environments mit Spring Profiles steuern</a>” erwähnt braucht ihr aber für meine Beispiel Projekte gar keine IDE um die Applikation starten zu können. Java reicht immer aus, da ich den <a href="https://docs.gradle.org/current/userguide/gradle_wrapper.html" target="_blank">gradle wrapper</a> mit ins Repository gebe (wie es auch üblich ist).<br />
Das funktioniert mit <code class="highlighter-rouge">./gradlew build</code> bzw. <code class="highlighter-rouge">gradlew.bat build</code>. Das ausführbare jar befindet sich dann in <code class="highlighter-rouge">build/libs/</code>. Mit Windows würde ich es jedoch mit <code class="highlighter-rouge">java -jar spring-profiles.jar</code> starten, da die Applikation sonst im Hintergrund gestartet wird und nur mehr über den Task Manager beendet werden kann.</p>
<p>In den meisten Projekten verwende ich <a href="https://projectlombok.org" target="_blank">Lombok</a>, d.h. ihr müsst Annotation Processing in IntelliJ IDEA aktivieren und eventuell das <a href="https://plugins.jetbrains.com/plugin/6317-lombok-plugin" target="_blank">Lombok Plugin</a> installieren, solltet ihr das Projekt in IDEA öffnen und bauen wollen.<br />
Mit Lombok müsst ich euch nicht mehr selber um Getter, Setter, toString, equals oder hashCode Methoden kümmern, da diese zur compile Zeit vom Lib erzeugt werden.</p>
<p>Für die Strukturierung des Java Codes verwende ich package by layer, d.h. ich teile meine Klasses nach ihrer Verwendung in Packages ein (Services, Repositories, Controller, DTOs, Configs, etc). Auch wenn ich über die Jahre auch einige Male package by feature ausprobiert habe, finde ich package by layer in den meisten Projekten passender bzw. übersichtlicher.</p>
<p>Die Struktur sieht dann wie folgt aus:<br />
<img src="/assets/blogposts/spring-base/source-structure.png" alt="source structure" class="img-responsive" /></p>René WitzelspergerIn diesem Beitrag möchte ich meine Projektstruktur vorstellen.Environments mit Spring Profiles steuern2018-02-18T13:37:00+01:002018-02-18T13:37:00+01:00https://www.wizi.at/blog/environments-with-spring-profiles<p>Wenn ihr Java Applications schreibt, wollt ihr diese bestimmt auch irgendwo deployen. Mal angenommen es existiert ein Test Server, ein Produktiv Server und auch ein Integration Environment, dann müsst ihr die verschiedenen Configs für Datenbanken, Logging, Services, usw. usf. ja irgendwo unter bekommen. Das Spring Framework bietet dafür mit den Spring Profiles einen sehr eleganten Weg die Configs zu organisieren. Damit erreicht ihr, dass alle eure Konfigurationen direkt mit der Applikation verpackt sind und ihr ein und das selbe Package für alle Environments verwenden könnt.</p>
<p>Aktive Spring Profiles könnt ihr mit Hilfe des JVM Argument Parameters <code class="highlighter-rouge">spring.profiles.active</code> setzen.</p>
<p>Habt ihr ein fat jar - beispielsweise jenes, welches aus meinem <a href="https://github.com/wizison/blog-environments-with-spring-profiles" target="_blank">verlinkten Spring Boot Projekt</a> entsteht - könnt ihr beim Ausführen die Profiles in den <code class="highlighter-rouge">JAVA_OPTS</code> setzen:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ JAVA_OPTS</span><span class="o">=</span><span class="nt">-Dspring</span>.profiles.active<span class="o">=</span><span class="nb">test</span> ./spring-profiles.jar</code></pre></figure>
<p>Habt ihr euch für ein Servlet Container Deployment entschieden, so könnt ihr auch dort die <code class="highlighter-rouge">JAVA_OPTS</code> entsprechend anpassen.</p>
<p>Es ist auch möglich mehrere Profile mit Beistrich getrennt anzugeben. Spring verwendet dann die Konfiguration der Profiles von links nach rechts und überschreibt die voran gestellten Werte, sollten welche vorhanden sein.<br />
Das bedeutet, wenn ihr beispielsweise als Profiles <code class="highlighter-rouge">prod,dude</code> angebt und ihr euch für eine <a href="https://en.wikipedia.org/wiki/YAML" target="_blank">YAML</a> Konfiguration entschieden habt, dann werden zuerst alle “default” Werte aus dem <code class="highlighter-rouge">resources/application.yml</code>, anschließend alle Werte aus dem <code class="highlighter-rouge">resources/application-prod.yml</code> und zuletzt alle Werte aus dem <code class="highlighter-rouge">resources/application-dude.yml</code> gelesen.<br />
Es gibt auch die Möglichkeit die Profiles direkt aus einem YAML File zu lesen, doch ich tendiere eher zu eigenen YAML Files für die Profile.<br />
Sollte für ein Profil kein YAML File existieren, ist das auch kein Problem.</p>
<p>Da wir nun wissen wie wir die Spring Profile an unsere Applikation übergeben, organisieren und schachteln können, sollten wir auch etwas damit machen. Dazu habe ich ein kleines Gradle / Java / Spring Boot Projekt geschrieben, welches oben im Header des Posts verlinkt ist.</p>
<p>Ihr könnt die Profiles nun beispielsweise in eurer Logback Konfiguration verwenden. Als Beispiel ein Auszug aus dem <a href="https://github.com/wizison/blog-environments-with-spring-profiles/blob/master/src/main/resources/logback-spring.xml" target="_blank">logback-spring.xml</a> vom verlinkten Projekt, in welchem ich für die Profile <code class="highlighter-rouge">test</code> und <code class="highlighter-rouge">prod</code> einen File Appender einrichte:</p>
<figure class="highlight"><pre><code class="language-xml" data-lang="xml"><span class="nt"><springProfile</span> <span class="na">name=</span><span class="s">"test,prod"</span><span class="nt">></span>
<span class="nt"><appender</span> <span class="na">name=</span><span class="s">"FILE"</span> <span class="na">class=</span><span class="s">"ch.qos.logback.core.rolling.RollingFileAppender"</span><span class="nt">></span>
<span class="nt"><encoder></span>
<span class="nt"><pattern></span>${FILE_LOG_PATTERN}<span class="nt"></pattern></span>
<span class="nt"></encoder></span>
<span class="nt"><file></span>${LOG_PATH}/${LOG_FILENAME}.log<span class="nt"></file></span>
<span class="nt"><rollingPolicy</span> <span class="na">class=</span><span class="s">"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"</span><span class="nt">></span>
<span class="nt"><fileNamePattern></span>${LOG_PATH}/${LOG_FILENAME}-%d{yyyy-MM-dd}.%i.log<span class="nt"></fileNamePattern></span>
<span class="nt"><maxHistory></span>7<span class="nt"></maxHistory></span>
<span class="nt"><maxFileSize></span>100MB<span class="nt"></maxFileSize></span>
<span class="nt"><totalSizeCap></span>1GB<span class="nt"></totalSizeCap></span>
<span class="nt"></rollingPolicy></span>
<span class="nt"></appender></span>
<span class="nt"><root</span> <span class="na">level=</span><span class="s">"INFO"</span><span class="nt">></span>
<span class="nt"><appender-ref</span> <span class="na">ref=</span><span class="s">"FILE"</span><span class="nt">/></span>
<span class="nt"></root></span>
<span class="nt"></springProfile></span></code></pre></figure>
<p>Wird die Applikation nun mit dem Profil <code class="highlighter-rouge">test</code> oder <code class="highlighter-rouge">prod</code> gestartet, so wird nicht mehr in die console (wie beim <code class="highlighter-rouge">default</code> und <code class="highlighter-rouge">ide</code> Profil - siehe <a href="https://github.com/wizison/blog-environments-with-spring-profiles/blob/master/src/main/resources/logback-spring.xml" target="_blank">logback-spring.xml</a>) geloggt, sondern in das angegebene File des Appenders.</p>
<p>Wenn ihr nun jedoch beides haben wollt - also Console und File Output - dann könnt ihr ganz einfach das <code class="highlighter-rouge">default</code> Profile zusätzlich selber angeben.</p>
<blockquote>
<p>Im Normalfall verwendet Spring das <code class="highlighter-rouge">default</code> Profil nur wenn kein Profil angegeben ist.</p>
</blockquote>
<p>Ihr könnt jedoch auch Spring Beans (beispielsweise Services) an bestimmte Profiles binden:</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@Service</span>
<span class="nd">@Profile</span><span class="o">({</span><span class="s">"test"</span><span class="o">,</span> <span class="s">"prod"</span><span class="o">})</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">StatusLoggingService</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">Logger</span> <span class="n">LOGGER</span> <span class="o">=</span> <span class="n">LoggerFactory</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="n">SchedulingConfig</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
<span class="nd">@Scheduled</span><span class="o">(</span><span class="n">fixedRate</span> <span class="o">=</span> <span class="mi">10000</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">logStatus</span><span class="o">()</span> <span class="o">{</span>
<span class="n">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"all fine."</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<p>In diesem Fall wird das <a href="https://github.com/wizison/blog-environments-with-spring-profiles/blob/master/src/main/java/at/wizi/blog/service/StatusLoggingService.java" target="_blank"><code class="highlighter-rouge">Service</code></a> nur erzeugt, wenn das Profil <code class="highlighter-rouge">test</code> oder <code class="highlighter-rouge">prod</code> gesetzt ist und da wir auch eine <code class="highlighter-rouge">Scheduled</code> Annotation auf der Methode haben, loggt es alle 10 Sekunden <code class="highlighter-rouge">all fine</code>. Da dieses Logging aber nicht sehr sinnvoll ist, könnte hier beispielsweise auch ein Speiseplan (kleiner Insider - liebe Grüße an Tanja) per eMail versendet werden - das würde ich jedoch nicht unbedingt alle 10 Sekunden machen. Geiler Scheiss, oder?</p>
<p>Das <a href="https://github.com/wizison/blog-environments-with-spring-profiles" target="_blank">verlinkten Spring Boot Projekt</a> startet einen Web Server und liefert dann unter der URL <code class="highlighter-rouge">http://localhost:8080/status/show</code> folgendes JSON:</p>
<figure class="highlight"><pre><code class="language-json" data-lang="json"><span class="p">{</span><span class="w">
</span><span class="s2">"code"</span><span class="p">:</span><span class="w"> </span><span class="mi">17</span><span class="p">,</span><span class="w">
</span><span class="s2">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"all fine"</span><span class="p">,</span><span class="w">
</span><span class="s2">"activeSpringProfiles"</span><span class="p">:</span><span class="w"> </span><span class="s2">"default,prod,dude"</span><span class="p">,</span><span class="w">
</span><span class="s2">"applicationConfig"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"size"</span><span class="p">:</span><span class="w"> </span><span class="mi">17</span><span class="p">,</span><span class="w">
</span><span class="s2">"environmentMessage"</span><span class="p">:</span><span class="w"> </span><span class="s2">"this is the dude environment"</span><span class="w">
</span><span class="p">}</span></code></pre></figure>
<p>Die Werte der <code class="highlighter-rouge">ApplicationConfig</code> sind in den verschiedenen YAML Files der Profile definiert. Wenn ihr also die gebaute Applikation mit verschiedenen Profilen, wie oben angegeben, startet, dann könnt ihr euch ansehen wie sich die Werte ändern.</p>
<blockquote>
<p>Das Projekt verwendet Lombok, d.h. ihr müsst Annotation Processing in IntelliJ IDEA aktivieren und eventuell das Lombok Plugin installieren, solltet ihr das Projekt in IDEA öffnen und ausführen wollen.</p>
</blockquote>
<blockquote>
<p>Wenn ihr keine IDE sondern nur Java installiert habt, könnt ihr das Projekt auch direkt über den gradle wrapper bauen. Das funktioniert mit <code class="highlighter-rouge">./gradlew build</code> bzw. <code class="highlighter-rouge">gradlew.bat build</code>. Das ausführbare jar befindet sich dann in <code class="highlighter-rouge">build/libs/</code>. Mit Windows würde ich es jedoch mit <code class="highlighter-rouge">java -jar spring-profiles.jar</code> starten, da ihr es sonst nur über den Task Manager beenden könnt :D</p>
</blockquote>
<blockquote>
<p>Das Projekt erstellt das Verzeichnis <code class="highlighter-rouge">/var/log/blog</code> wenn es mit dem Profil <code class="highlighter-rouge">test</code> oder <code class="highlighter-rouge">prod</code> gestartet wird. Sorgt bitte dafür, dass die nötigen Berechtigungen vorhanden sind, um das Verzeichnis zu erstellen. Sollte ihr Windows benutzen, dann wird das Verzeichnis auf dem verwendeten Laufwerk erstellt. Gegebenenfalls könnt ihr das Verzeichnis später auch natürlich wieder löschen oder ihr ändert den Pfad im <a href="https://github.com/wizison/blog-environments-with-spring-profiles/blob/master/src/main/resources/logback-spring.xml" target="_blank">logback-spring.xml</a> auf euer Environment.</p>
</blockquote>
<p>Hoffentlich hat euch mein Beitrag gefallen. Über Feedback würde ich mich sehr freuen!</p>
<blockquote>
<p>kleine Info noch: es wird bald einen Artikel über die generelle Struktur meiner Beispiel Projekte und deren Verwendung geben, dann muss ich das nicht immer bei den Themen Artikeln mitnehmen :)</p>
</blockquote>
<p>so long, and thanks for all the fish.</p>René WitzelspergerWenn ihr Java Applications schreibt, wollt ihr diese bestimmt auch irgendwo deployen. Mal angenommen es existiert ein Test Server, ein Produktiv Server und auch ein Integration Environment, dann müsst ihr die verschiedenen Configs für Datenbanken, Logging, Services, usw. usf. ja irgendwo unter bekommen. Das Spring Framework bietet dafür mit den Spring Profiles einen sehr eleganten Weg die Configs zu organisieren. Damit erreicht ihr, dass alle eure Konfigurationen direkt mit der Applikation verpackt sind und ihr ein und das selbe Package für alle Environments verwenden könnt.Warum existiert dieser Blog?2018-02-17T13:37:00+01:002018-02-17T13:37:00+01:00https://www.wizi.at/blog/why<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="nd">@EnableBlog</span>
<span class="nd">@SpringBootApplication</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">BlogApplication</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="n">LOGGER</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"hello world!"</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<h1 id="warum-existiert-dieser-blog">Warum existiert dieser Blog?</h1>
<p>Das meine Freunde ist eine sehr gute Frage, immerhin gibt es schon eine beinahe endlose Anzahl an dev blogs.</p>
<p>Der einfache Grund ist Faulheit!</p>
<p>Es soll etwas entwickelt werden und ihr denk euch… mhm… das habe ich doch schon mal gemacht. Nun ist es natürlich praktisch, wenn ihr eure früheren Projekte durchforsten könnt, um die Lösung für euer Software Problem zu finden. Blöd ist dann natürlich, wenn ihr den Job gewechselt habt und ihr keinen Zugriff mehr auf “eure” Projekte habt, da es ja eigentlich gar nicht eure Projekte sind!<br />
Da ich nun in genau dieser Situation bin und mich wieder durch die verschiedenen Dokumentationen durch quälen muss und mich nicht nur auf das Aktualisieren der Libs und Code Snippets beschränken kann, bevor ich mich dem eigentlichen Software Problemen widme, habe ich mir gedacht ich starte einfach einen Blog.</p>
<p>Versteht das jedoch jetzt bitte nicht falsch - ich bin sehr froh und glücklich in meinem neuen Job ;)</p>
<p>Mit diesem Blog möchte ich einfach verschiedene kleine (Teil-)Projekte sammeln, um so eine Anlaufstelle zu schaffen, wenn es um die Entwicklung von Applikationen mit Java und dem Spring Framework geht.<br />
Natürlich könnte ich das auch weiterhin in meinen privaten GIT Repositories machen, aber ich habe mir gedacht eventuell gibt es ja auch noch andere, welche von meinen Erfahrungen profitieren möchten.</p>
<p>Da ich blogtechnisch völlig unerfahren und auch in der Frontend Entwicklung samt Design und Styling nicht sehr versiert bin, möchte ich mich an dieser Stelle bei <a href="https://johannespichler.com" target="_blank">Fetzi (hier gehts zu seinem Blog)</a> bedanken!<br />
Sein Blog sieht meinem ziemlich ähnlich… das liegt daran, dass ich ihm alles geklaut habe :D<br />
Zu meiner Verteidigung möchte ich jedoch anmerken, dass ich ihn vorher gefragt habe und er damit einverstanden war.</p>
<p>Auch die Idee für den Blog <a href="https://jekyllrb.com" target="_blank">Jekyll</a> einzusetzen habe ich bei ihm bzw. dem <a href="https://dev.karriere.at" target="_blank">karriere.at dev blog</a> gesehen. Mit Jekyll generiere ich nun aus <a href="https://en.wikipedia.org/wiki/Markdown" target="_blank">Marksdowns</a> statische HTML Seiten, welche dann von meinem Webserver ausgeliefert werden.</p>
<p>Bin schon gespannt wie mein Blog ankommt - vorerst verbleibe ich mit:</p>
<p>so long, and thanks for all the fish.</p>René Witzelsperger@EnableBlog @SpringBootApplication public class BlogApplication { public static void main(String[] args) { LOGGER.info("hello world!"); } }