Cet article est le premier d’une série dont l’objectif est d’expliquer le code du projet LoFiDroX. Dans ce premier épisode, on va analyser la configuration.

Configuration du projet

Pour builder ce projet, j’ai choisi (sans surprise) Maven. Si tu utilises JetBrain IntelliJ, il suffit de créer un nouveau projet de type “Maven” (ou l’ajouter). Pour les autres IDE, il doit y avoir une fonctionnalité similaire.

Ensuite, le front end du projet repose sur Svelte, il faut donc l’ajouter via npm. Pour cela, il faut attraper un terminal puis se rendre dans le dossier du projet (au même niveau que le pom.xml) puis taper:

    
1npm install svelte
2npm install svelte-routing

Fichier pom.xml

Comme d’habitude, j’ai mis en évidence les points importants ou particuliers

    
  1<?xml version="1.0" encoding="UTF-8"?>
  2<project xmlns="http://maven.apache.org/POM/4.0.0"
  3         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5    <modelVersion>4.0.0</modelVersion>
  6
  7    <groupId>ch.gobothegeek.pro</groupId>
  8    <artifactId>lofidrox</artifactId>
  9    <version>1.0-SNAPSHOT</version>
 10    <packaging>war</packaging>
 11
 12    <properties>
 13        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 14        <failOnMissingWebXml>false</failOnMissingWebXml>
 15        <maven.compiler.target>11</maven.compiler.target>
 16        <maven.compiler.source>11</maven.compiler.source>
 17        <deltaspike.version>1.9.5</deltaspike.version>
 18        <owb.version>1.6.3</owb.version>
 19        <tomee.version>8.0</tomee.version>
 20        <tomee.jaxrs.version>8.0.11</tomee.jaxrs.version>
 21        <slf4j.version>1.7.36</slf4j.version>
 22        <beanutils.version>1.9.4</beanutils.version>
 23        <collections.version>3.2.2</collections.version>
 24        <lang3.version>3.12.0</lang3.version>
 25        <io.version>2.11.0</io.version>
 26        <codec.version>1.15</codec.version>
 27        <jackson.core.version>2.13.2</jackson.core.version>
 28        <jackson.databind.version>2.13.2.2</jackson.databind.version>
 29        <openjpa.version>3.2.2</openjpa.version>
 30        <hsqldb.version>2.6.1</hsqldb.version>
 31        <urlrewrite.version>4.0.4</urlrewrite.version>
 32    </properties>
 33
 34    <name>LoFiDroX: share files over local network</name>
 35    <url>https://www.gobothegeek.ch</url>
 36
 37    <build>
 38        <finalName>lofidrox</finalName>
 39        <plugins>
 40            <plugin>
 41                <groupId>org.codehaus.mojo</groupId>
 42                <artifactId>exec-maven-plugin</artifactId>
 43                <version>3.0.0</version>
 44                <executions>
 45                    <execution>
 46                        <goals>
 47                            <goal>exec</goal>
 48                        </goals>
 49                    </execution>
 50                </executions>
 51                <configuration>
 52                    <executable>src/main/resources/sass_svelte.sh</executable>
 53                    <environmentVariables>
 54                        <LANG>en_US</LANG>
 55                    </environmentVariables>
 56                </configuration>
 57            </plugin>
 58            <plugin>
 59                <groupId>org.apache.tomee.maven</groupId>
 60                <artifactId>tomee-maven-plugin</artifactId>
 61                <version>8.0.8</version>
 62                <configuration>
 63                    <context>ROOT</context>
 64                </configuration>
 65            </plugin>
 66            <plugin>
 67                <groupId>org.apache.maven.plugins</groupId>
 68                <artifactId>maven-compiler-plugin</artifactId>
 69                <version>3.8.1</version>
 70                <configuration>
 71                    <source>11</source>
 72                    <target>11</target>
 73                </configuration>
 74                <executions>
 75                    <execution>
 76                        <goals>
 77                            <goal>compile</goal>
 78                        </goals>
 79                    </execution>
 80                </executions>
 81            </plugin>
 82            <plugin>
 83                <groupId>org.apache.maven.plugins</groupId>
 84                <artifactId>maven-war-plugin</artifactId>
 85                <version>3.3.1</version>
 86                <configuration>
 87                    <webXml>src/WebContent/WEB-INF/web.xml</webXml>
 88                    <webResources>
 89                        <resource>
 90                            <directory>src/WebContent</directory>
 91                            <includes>
 92                                <include>**/*</include>
 93                            </includes>
 94                        </resource>
 95                    </webResources>
 96                    <outputDirectory>/opt/tomee8/webapps/</outputDirectory>
 97                </configuration>
 98            </plugin>
 99        </plugins>
100    </build>
101
102    <dependencyManagement>
103        <dependencies>
104            <dependency>
105                <groupId>org.apache.deltaspike.distribution</groupId>
106                <artifactId>distributions-bom</artifactId>
107                <version>${deltaspike.version}</version>
108                <type>pom</type>
109                <scope>import</scope>
110            </dependency>
111        </dependencies>
112    </dependencyManagement>
113
114    <dependencies>
115        <dependency>
116            <groupId>org.apache.tomee</groupId>
117            <artifactId>javaee-api</artifactId>
118            <version>${tomee.version}</version>
119            <scope>provided</scope>
120        </dependency>
121        <dependency>
122            <groupId>org.slf4j</groupId>
123            <artifactId>slf4j-api</artifactId>
124            <version>${slf4j.version}</version>
125        </dependency>
126        <dependency>
127            <groupId>commons-beanutils</groupId>
128            <artifactId>commons-beanutils</artifactId>
129            <version>${beanutils.version}</version>
130        </dependency>
131        <dependency>
132            <groupId>commons-collections</groupId>
133            <artifactId>commons-collections</artifactId>
134            <version>${collections.version}</version>
135        </dependency>
136        <dependency>
137            <groupId>org.apache.commons</groupId>
138            <artifactId>commons-lang3</artifactId>
139            <version>${lang3.version}</version>
140        </dependency>
141        <dependency>
142            <groupId>commons-io</groupId>
143            <artifactId>commons-io</artifactId>
144            <version>${io.version}</version>
145        </dependency>
146        <dependency>
147            <groupId>commons-codec</groupId>
148            <artifactId>commons-codec</artifactId>
149            <version>${codec.version}</version>
150        </dependency>
151        <!-- Deltaspike -->
152        <dependency>
153            <groupId>org.apache.deltaspike.core</groupId>
154            <artifactId>deltaspike-core-api</artifactId>
155            <version>${deltaspike.version}</version>
156            <scope>compile</scope>
157        </dependency>
158        <dependency>
159            <groupId>org.apache.deltaspike.core</groupId>
160            <artifactId>deltaspike-core-impl</artifactId>
161            <version>${deltaspike.version}</version>
162            <scope>runtime</scope>
163        </dependency>
164        <dependency>
165            <groupId>org.apache.deltaspike.cdictrl</groupId>
166            <artifactId>deltaspike-cdictrl-api</artifactId>
167            <version>${deltaspike.version}</version>
168            <scope>compile</scope>
169        </dependency>
170        <dependency>
171            <groupId>org.apache.deltaspike.modules</groupId>
172            <artifactId>deltaspike-data-module-api</artifactId>
173            <version>${deltaspike.version}</version>
174            <scope>compile</scope>
175        </dependency>
176        <dependency>
177            <groupId>org.apache.deltaspike.modules</groupId>
178            <artifactId>deltaspike-data-module-impl</artifactId>
179            <version>${deltaspike.version}</version>
180            <scope>runtime</scope>
181        </dependency>
182        <dependency>
183            <groupId>org.apache.deltaspike.modules</groupId>
184            <artifactId>deltaspike-jpa-module-api</artifactId>
185            <version>${deltaspike.version}</version>
186            <scope>compile</scope>
187        </dependency>
188        <dependency>
189            <groupId>org.apache.deltaspike.modules</groupId>
190            <artifactId>deltaspike-jpa-module-impl</artifactId>
191            <version>${deltaspike.version}</version>
192            <scope>runtime</scope>
193        </dependency>
194        <dependency>
195            <groupId>org.apache.deltaspike.modules</groupId>
196            <artifactId>deltaspike-security-module-api</artifactId>
197            <version>${deltaspike.version}</version>
198            <scope>compile</scope>
199        </dependency>
200        <dependency>
201            <groupId>org.apache.deltaspike.modules</groupId>
202            <artifactId>deltaspike-security-module-impl</artifactId>
203            <version>${deltaspike.version}</version>
204            <scope>runtime</scope>
205        </dependency>
206        <dependency>
207            <groupId>com.fasterxml.jackson.core</groupId>
208            <artifactId>jackson-core</artifactId>
209            <version>${jackson.core.version}</version>
210        </dependency>
211        <dependency>
212            <groupId>com.fasterxml.jackson.core</groupId>
213            <artifactId>jackson-databind</artifactId>
214            <version>${jackson.databind.version}</version>
215        </dependency>
216        <dependency>
217            <groupId>org.apache.tomee</groupId>
218            <artifactId>tomee-jaxrs</artifactId>
219            <version>${tomee.jaxrs.version}</version>
220            <scope>test</scope>
221        </dependency>
222        <dependency>
223            <groupId>org.apache.openjpa</groupId>
224            <artifactId>openjpa-all</artifactId>
225            <version>${openjpa.version}</version>
226            <scope>provided</scope>
227        </dependency>
228        <dependency>
229            <groupId>org.hsqldb</groupId>
230            <artifactId>hsqldb</artifactId>
231            <version>${hsqldb.version}</version>
232        </dependency>
233        <dependency>
234            <groupId>org.tuckey</groupId>
235            <artifactId>urlrewritefilter</artifactId>
236            <version>${urlrewrite.version}</version>
237        </dependency>
238    </dependencies>
239</project>

Les deux lignes à noter (en plus des dépendances réduites) sont:

  • src/main/resources/sass_svelte.sh: cette ligne permet d’exécuter un script maison avant la compilation globale du projet
  • /opt/tomee8/webapps/: il s’agit ici du dossier de destination du fichier War contenant l’application (comme un bourrin, je déploie sur mon serveur de directement directement après la compilation)

Script sass_svelte.sh

Ce script shell doit être déposé dans le dossier src/main/resources du projet et contient le code suivant:

    
 1#!/bin/bash
 2
 3set -e
 4
 5echo "GTG# compiling svelte"
 6cd /home/DEV/Workspaces/intellij/lofidrox
 7npm run build
 8
 9echo "GTG# Copying resources"
10rm /home/DEV/Workspaces/intellij/lofidrox/src/WebContent/project/final/images/*
11cp /home/DEV/Workspaces/intellij/lofidrox/src/WebContent/project/img/* /home/DEV/Workspaces/intellij/lofidrox/src/WebContent/project/final/images/

Ce script réalise deux choses: il lance le build NPM puis copie les ressources statiques (les images en l’occurence) dans le dossier final du projet (parce que le build NPM ne le fait pas). L’instruction set -e est primordiale puisqu’elle permet de retourner un code d’erreur si le build NPM ne se termine pas correctement, stoppant ainsi la compilation par Maven.

Fichier src/main/resources/META-INF/apache-deltaspike.properties

    
1application.name=LoFiDroX
2application.storage.base=/opt/lofidrox/files/{source}
3application.password.algorithm=PBKDF2WithHmacSHA512
4application.password.iteration=12345
5application.password.keylength=128
6application.password.saltlength=16
7application.password.salt=245b8ca3fcf9425f09592a3330963618

Les propriétés sont les suivantes:

  • application.storage.base: dossier qui contiendra les fichiers envoyés (l’utilisateur associé au serveur TomEE doit pouvoir lire et écrire dans ce dossier)
  • application.password.algorithm: il s’agit de l’algorithme utilisé pour le chiffrement des mots de passe. A modifier avant de créer un compte! (Merci Captain Obvious)
  • application.password.iteration: le nombre d’itérations nécessaires pour chiffer le mot de passe. (Même remarque qu’au point précédent)
  • application.password.keylength: longueur de la clé de chiffrement. (Même remarque qu’au point précédent)
  • application.password.saltlength: longueur du salage de la clé. (Même remarque qu’au point précédent)
  • application.password.salt: le salage de la clé, en hexadécimal. (Même remarque qu’au point précédent)

Fichier persistence.xml

    
 1<persistence
 2    version="2.0"
 3    xmlns="http://java.sun.com/xml/ns/persistence"
 4    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
 6    <persistence-unit name="LfdPersistenceUnit" transaction-type="RESOURCE_LOCAL">
 7        <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
 8        <non-jta-data-source>lofidroxDB</non-jta-data-source>
 9        <properties>
10            <property name="openjpa.Log" value="SQL=Trace" />
11            <property name="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" />
12            <property name="openjpa.jdbc.DBDictionary" value="hsql" />
13        </properties>
14    </persistence-unit>
15</persistence>

Dans la version de développement, j’ai bien sûr activé l’affichage des requêtes. Pour la production, il faut bien sûr remettre la propriété openjpa.Log sur DefaultLevel=WARN, Runtime=INFO, Tool=INFO et openjpa.ConnectionFactoryProperties sur PrintParameters=false.

Fichier src/WebContent/WEB-INF/logback-access.xml

La configuration du logger n’a pas de point particulier, si ce n’est le dossier d’écriture des fichiers logs.

    
 1<configuration>
 2    <!-- always a good activate OnConsoleStatusListener -->
 3    <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
 4
 5    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 6        <encoder>
 7            <pattern>%h %l %u %user %date "%r" %s %b</pattern>
 8        </encoder>
 9    </appender>
10
11    <appender-ref ref="STDOUT" />
12
13    <appender name="lofidrox" class="ch.qos.logback.core.FileAppender">
14        <file>/opt/lofidrox/logs/lofidrox.log</file>
15        <encoder>
16            <pattern>%d %-5p: [%c] %m %rEx{3} %n</pattern>
17        </encoder>
18    </appender>
19
20    <root level="ERROR">
21        <appender-ref ref="lofidrox" />
22    </root>
23</configuration>

Fichier src/WebContent/WEB-INF/resources.xml

Ce fichier décrit la datasource qui sera utilisée pour se connecter à la base de données. Le port doit être le même que celui du serveur HSqlDB (voir article “HSQLDB ou la base de données facile”).

    
 1<?xml version="1.0" encoding="iso-8859-1" ?>
 2<resources>
 3    <Resource id="lofidroxDB" type="javax.sql.DataSource">
 4        UserName LOFIDROX
 5        Password XXXXX
 6        jtaManaged false
 7        JdbcDriver org.hsqldb.jdbcDriver
 8        JdbcUrl jdbc:hsqldb:hsql://localhost:12345/lofidrox
 9    </Resource>
10</resources>

Fichier src/WebContent/WEB-INF/urlrewrite.xml

Ce fichier est utilisé par le package org.tuckey.urlrewriterfilter et permet de configurer la redirection de certaines urls de l’application. C’est grâce à ces redirections qu’on peut différencier les appels “SPA” et les appels CRUD.

    
 1<urlrewrite>
 2	<rule>
 3		<note>
 4			Transfer all urls starting with /spa/ to index page so client can route itselfs correctly
 5		</note>
 6		<from>/spa/(.*)</from>
 7		<to type="redirect">%{context-path}/index.html?page=/lofidrox/spa/$1</to>
 8	</rule>
 9	<rule>
10		<note>
11			Transfer all urls starting with /img/ to folder /project/final/images
12		</note>
13		<from>/img/(.*)</from>
14		<to type="redirect">%{context-path}/project/final/images/$1</to>
15	</rule>
16</urlrewrite>

Fichier src/WebContent/WEB-INF/web.xml

Et voici le dernier fichier de configuration (ouf!). A part le filtre UrlFilterRewriter, les reste est standard.

    
 1<?xml version="1.0" encoding="ISO-8859-1"?>
 2<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
 3<web-app>
 4    <icon>
 5        <large-icon></large-icon>
 6    </icon>
 7    <display-name>LoFiDroX</display-name>
 8    <description>Share files over local network</description>
 9
10    <context-param>
11        <param-name>webmaster</param-name>
12        <param-value>tech@gobothegeek.ch</param-value>
13        <description></description>
14    </context-param>
15
16    <session-config>
17        <session-timeout>30</session-timeout>    <!-- 30 minutes -->
18    </session-config>
19
20    <welcome-file-list>
21        <welcome-file>index.html</welcome-file>
22    </welcome-file-list>
23
24    <resource-ref>
25        <res-ref-name>lofidroxDB</res-ref-name>
26        <res-type>javax.sql.DataSource</res-type>
27        <res-auth>Container</res-auth>
28        <res-sharing-scope>Shareable</res-sharing-scope>
29    </resource-ref>
30
31    <filter>
32        <filter-name>UrlRewriteFilter</filter-name>
33        <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
34    </filter>
35    <filter-mapping>
36        <filter-name>UrlRewriteFilter</filter-name>
37        <url-pattern>/spa/*</url-pattern>
38        <dispatcher>REQUEST</dispatcher>
39        <dispatcher>FORWARD</dispatcher>
40        <filter-name>UrlRewriteFilter</filter-name>
41        <url-pattern>/img/*</url-pattern>
42        <dispatcher>REQUEST</dispatcher>
43        <dispatcher>FORWARD</dispatcher>
44    </filter-mapping>
45</web-app>

La section mise en évidence permet de faire le lien entre le filtre et la configuration à appliquer.

Conclusion

Dans ce premier article, nous avons vu la base du projet. Les prochains épisodes traiteront du code Java (pour changer un peu): contrôleurs REST, services, entités, etc.

Code source

Comme annoncé dans l’article Fuyez GitHub, le code n’est plus disponible sur GitHub. L’intégralité du code est disponible sur mon CodeBerg: https://codeberg.org/GoboTheGeek/LoFiDroX