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:
1
2
| npm install svelte
npm install svelte-routing
|
Fichier pom.xml#
Comme d’habitude, j’ai mis en évidence les points importants ou particuliers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
| <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>ch.gobothegeek.pro</groupId>
<artifactId>lofidrox</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<failOnMissingWebXml>false</failOnMissingWebXml>
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
<deltaspike.version>1.9.5</deltaspike.version>
<owb.version>1.6.3</owb.version>
<tomee.version>8.0</tomee.version>
<tomee.jaxrs.version>8.0.11</tomee.jaxrs.version>
<slf4j.version>1.7.36</slf4j.version>
<beanutils.version>1.9.4</beanutils.version>
<collections.version>3.2.2</collections.version>
<lang3.version>3.12.0</lang3.version>
<io.version>2.11.0</io.version>
<codec.version>1.15</codec.version>
<jackson.core.version>2.13.2</jackson.core.version>
<jackson.databind.version>2.13.2.2</jackson.databind.version>
<openjpa.version>3.2.2</openjpa.version>
<hsqldb.version>2.6.1</hsqldb.version>
<urlrewrite.version>4.0.4</urlrewrite.version>
</properties>
<name>LoFiDroX: share files over local network</name>
<url>https://www.gobothegeek.ch</url>
<build>
<finalName>lofidrox</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>src/main/resources/sass_svelte.sh</executable>
<environmentVariables>
<LANG>en_US</LANG>
</environmentVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomee.maven</groupId>
<artifactId>tomee-maven-plugin</artifactId>
<version>8.0.8</version>
<configuration>
<context>ROOT</context>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<webXml>src/WebContent/WEB-INF/web.xml</webXml>
<webResources>
<resource>
<directory>src/WebContent</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</webResources>
<outputDirectory>/opt/tomee8/webapps/</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.deltaspike.distribution</groupId>
<artifactId>distributions-bom</artifactId>
<version>${deltaspike.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>javaee-api</artifactId>
<version>${tomee.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>${beanutils.version}</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${collections.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${io.version}</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${codec.version}</version>
</dependency>
<!-- Deltaspike -->
<dependency>
<groupId>org.apache.deltaspike.core</groupId>
<artifactId>deltaspike-core-api</artifactId>
<version>${deltaspike.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.core</groupId>
<artifactId>deltaspike-core-impl</artifactId>
<version>${deltaspike.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.cdictrl</groupId>
<artifactId>deltaspike-cdictrl-api</artifactId>
<version>${deltaspike.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-data-module-api</artifactId>
<version>${deltaspike.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-data-module-impl</artifactId>
<version>${deltaspike.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-jpa-module-api</artifactId>
<version>${deltaspike.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-jpa-module-impl</artifactId>
<version>${deltaspike.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-security-module-api</artifactId>
<version>${deltaspike.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-security-module-impl</artifactId>
<version>${deltaspike.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.core.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.databind.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>tomee-jaxrs</artifactId>
<version>${tomee.jaxrs.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-all</artifactId>
<version>${openjpa.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
</dependency>
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>${urlrewrite.version}</version>
</dependency>
</dependencies>
</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
2
3
4
5
6
7
8
9
10
11
| #!/bin/bash
set -e
echo "GTG# compiling svelte"
cd /home/DEV/Workspaces/intellij/lofidrox
npm run build
echo "GTG# Copying resources"
rm /home/DEV/Workspaces/intellij/lofidrox/src/WebContent/project/final/images/*
cp /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#
1
2
3
4
5
6
7
| application.name=LoFiDroX
application.storage.base=/opt/lofidrox/files/{source}
application.password.algorithm=PBKDF2WithHmacSHA512
application.password.iteration=12345
application.password.keylength=128
application.password.saltlength=16
application.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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| <persistence
version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="LfdPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<non-jta-data-source>lofidroxDB</non-jta-data-source>
<properties>
<property name="openjpa.Log" value="SQL=Trace" />
<property name="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" />
<property name="openjpa.jdbc.DBDictionary" value="hsql" />
</properties>
</persistence-unit>
</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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| <configuration>
<!-- always a good activate OnConsoleStatusListener -->
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%h %l %u %user %date "%r" %s %b</pattern>
</encoder>
</appender>
<appender-ref ref="STDOUT" />
<appender name="lofidrox" class="ch.qos.logback.core.FileAppender">
<file>/opt/lofidrox/logs/lofidrox.log</file>
<encoder>
<pattern>%d %-5p: [%c] %m %rEx{3} %n</pattern>
</encoder>
</appender>
<root level="ERROR">
<appender-ref ref="lofidrox" />
</root>
</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
2
3
4
5
6
7
8
9
10
| <?xml version="1.0" encoding="iso-8859-1" ?>
<resources>
<Resource id="lofidroxDB" type="javax.sql.DataSource">
UserName LOFIDROX
Password XXXXX
jtaManaged false
JdbcDriver org.hsqldb.jdbcDriver
JdbcUrl jdbc:hsqldb:hsql://localhost:12345/lofidrox
</Resource>
</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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| <urlrewrite>
<rule>
<note>
Transfer all urls starting with /spa/ to index page so client can route itselfs correctly
</note>
<from>/spa/(.*)</from>
<to type="redirect">%{context-path}/index.html?page=/lofidrox/spa/$1</to>
</rule>
<rule>
<note>
Transfer all urls starting with /img/ to folder /project/final/images
</note>
<from>/img/(.*)</from>
<to type="redirect">%{context-path}/project/final/images/$1</to>
</rule>
</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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
| <?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<icon>
<large-icon></large-icon>
</icon>
<display-name>LoFiDroX</display-name>
<description>Share files over local network</description>
<context-param>
<param-name>webmaster</param-name>
<param-value>tech@gobothegeek.ch</param-value>
<description></description>
</context-param>
<session-config>
<session-timeout>30</session-timeout> <!-- 30 minutes -->
</session-config>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<resource-ref>
<res-ref-name>lofidroxDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/spa/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/img/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
</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