L'utilitaire JavaDoc ne fonctionne pas avec du code Kotlin (normal me direz-vous). Heureusement, Jetbrains fourni Dokka sous la forme de plugin Maven et Gradle permettant de faire la même chose.
Les annotations et syntaxes Dokka diffèrent un peu de la JavaDoc, voici un résumé :
@param Identique à JavaDoc
@property Pour documenter un attribut
@constructor Pour documenter un constructeur primaire
@return Identique à JavaDoc
Pour faire un lien vers une _classe/method/autre_ simplement écrire ceci
/** Je veux faire un lien vers [MaClass] **/
et Dokka fera le job
Attention, Java 6 n'étant plus supportée les dépendances kotlin-stdlib-jdk7 et kotlin-stdlib-jdk8 n'existent plus (puisque c'est Java 8 la version minimale requise pour Kotlin à présent).
Il faut donc les remplacer par kotlin-stdlib. Une migration simple qui va poser de nombreux problèmes à certains, sans aucun doute.
Je cite :
« À mesure qu'Android passe de C/C++ à Java/Kotlin/Rust, nous nous attendons à ce que le nombre de vulnérabilités liées à la sécurité de la mémoire continue de diminuer. Vivement un avenir où les bogues de corruption de la mémoire sur Android seront rares », a conclu Google.
Rust et Kotlin sont deux superbes langages (avec une petite préférence pour Kotlin). J'ai pourtant quelques reproches à faire à l'un est à l'autre mais quand je vois que le marché avance vers eux à grands pas, autant vous dire que j'en suis toute chose <3
Que du beau sous le soleil.
En un exemple court et simple :
package com.memorynotfound;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
public class GetUpTime {
public static void main(String... args) throws InterruptedException {
RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
System.out.println("Up time: " + rb.getUptime() + " ms");
}
}
Edit
En complément il y a ce projet sur lequel jcefmaven est basé.
Problème
- J'ai besoin de développer un client lourd.
- Je préfère mourir que de me remettre à Swig ou d'utiliser JFX (dont la réputation d'API instable avait fait le tour du web il y a quelques années).
Solution
Cette dépendance Maven qui intègre un moteur de rendu WebKit :
<dependency>
<groupId>me.friwi</groupId>
<artifactId>jcefmaven</artifactId>
<version>105.3.36</version>
</dependency>
Avec le tuto pour Java
//Create a new CefAppBuilder instance
CefAppBuilder builder = new CefAppBuilder();
//Configure the builder instance
builder.setInstallDir(new File("jcef-bundle")); //Default
builder.setProgressHandler(new ConsoleProgressHandler()); //Default
builder.addJcefArgs("--disable-gpu"); //Just an example
builder.getCefSettings().windowless_rendering_enabled = true; //Default - select OSR mode
//Set an app handler. Do not use CefApp.addAppHandler(...), it will break your code on MacOSX!
builder.setAppHandler(new MavenCefAppHandlerAdapter(){...});
//Build a CefApp instance using the configuration above
CefApp app = builder.build();
Ceci se fait en deux étapes :
1) Déclarer la property dans le plugin Surefire comme suit
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>LAST_SUREFIRE_VERSION</version>
<configuration>
<systemProperties>
<property>
<name>name-the-property-will-have-in-test</name>
<value>${my-property}</value>
</property>
</systemProperties>
</configuration>
</plugin>
2) La récupérer en tant que propriété système dans les TU
val property = System.getProperty("name-the-property-will-have-in-test")
Kotiln, Rust et Python progressent et de plus en plus de développeurs les adoptent (et c'est très bien).
J'ai été une grande utilisatrice de Python il y a un peu plus d'une quinzaine d'années lorsque je travaillais en labo sur du Data-Mining (l'ancêtre du Machine Learning). J'avais laissé de côté Python pour trois raisons à l'époque :
- Les problèmes de performance.
- Les problèmes d'outillage autour du build.
- Le fait que les programmes écrits en Python, pour être rapides, doivent utiliser des libs écrites en C, et donc avec un code orienté procédure.
Aujourd'hui, si je devais produire un système temps-réel et très peu énergivore, je partirais sur Rust.
Dans tous les autres cas de figure, je prendrais Kotlin sur OpenJDK ou Kotlin native (via le compilateur Kotlin-native ou GraalVM).
Par contre Python n'est plus du tout dans ma liste car pour moi à présent, si l'exécution d'un langage n'est pas prouvée à la compilation, c'est un stop immédiat. La majorité des développeurs n'écrivant pas de tests et maîtrisant mal le code (en tout cas en industrie) c'est indispensable.
Kotlin 1.7 se profile à l'horizon. Je vais rester sur Koltin 1.6 cette année, mais si les évolutions sur Kotlin-JS et Kotlin-Native débarquent, je vais vite changer d'avis :P
Ahhh Java... Je me souviens de mon tout premier code en Java. J'étais encore au lycée, je voulais apprendre à faire des sites web pour notre club d'anglais et j'avais entendu parlé de JavaScript. Alors j'ai demandé un bouquin à mes parents mais vu le prix des livres à l'époque j'avais fait une croix dessus... Puis à Noël...
J'ai reçu un libre qui s'appelait Total Java ! Et mes parents tout fiers à l'époque : "Le libraire nous a dit que tu pourrais faire des sites avec ça"... Oui avec des Applets Maman #Facepalm.
En réalité, j'ai très vite adoré Java et puis j'ai appris à le détester en migrant vers Kotlin. Le langage en lui-même n'est trop pas mal :
- Il gère la programmation par structures.
- Il gère la programmation orientée objets.
- Il gère la programmation fonctionnelle.
- Il gère la programmation par aspects.
- Il gère la programmation asynchrone.
- Il gère la programmation concurrentielle.
- Il gère programmation réactive.
- Il gère la programmation événementielle.
A présent je me rends compte de la lourdeur de sa syntaxe, que sa capacité à gérer autant de paradigmes différents font de lui un langage dont la syntaxe devient au final incohérente, que la rétro-compatibilité ascendante garantie n'a jamais permis à Java de trier le bon grain de l'ivraie pour ne se focaliser que sur le nouveau ; rétro-compatibilité depuis 1995 quand même !
@Warrior Du Dimanche si tu as des questions en Java demande, je tâcherai d'y répondre :-*. Mais quitte à bosser sur JVM, je te recommande Kotlin, bien plus élégant, bien plus expressif, bien mieux !
Excellente idée ! Merci à @Philou pour le lien.
Retour d'expérience d'une équipe d'Amazon Prime sur l'utilisation de Kotlin à la place de Java.
Overall : 75% de devs satisfaits de la transition.
Excellent, je cherchais un moteur Kotlin 2D sympa pour un kata un peu gros. C'est top !
Merci @Riduidel
La polygot maven extension permet de produit des pom en Yaml (j'avais fait un tuto ici en son temps) et maintenant en Kotlin. Vous savez que j'adore Kotlin et pourtant je vois dans cette opportunité une immondice sans nom pour ne pas dire la plus grande des saloperies !
Pourquoi ?
Parce que le DSL Kotlin permet de coder dans le pom dont le but est qu'il soit pourtant 100 % déclaratif. Car du code dans un pom n'aura jamais de TU, a un probabilité très haute de ne pas être portable et surtout, chaque évolution du code ne profitera ni à la communauté (car pas de plugin) et deviendra un risque pour l'entreprise qui va accentuer l'effet "copier-coller".
Non vraiment, si c'était pour faire de Maven la même horreur de maintenance que l'est Gradle, mais les performances en moins, je pense qu'il valait mieux s'abstenir.
Voici l'exemple qui m'a fait vomir deux fois (vous saurez apprécier le code à copier-coller dans chaque projet d'entreprise en début de pom n'est-ce pas ?) :
import java.io.File
// define a comparable data class to simplify handling versions
data class Version(val major: Int, val minor: Int, val patch: Int) : Comparable<Version> {
override fun compareTo(other: Version): Int =
compareValuesBy(this, other, Version::major, Version::minor, Version::patch)
override fun toString(): String = "$major.$minor.$patch"
}
// define a function to execute the git command and return its standard output
fun git(vararg args: String): String {
// use the basedir of the project as the command's working dir if it contains a '.git' subdir
// otherwise use the current working directory of this script if it contains a '.git' subdir
// if both conditions are false the result will be null; the git command will probably fail
val workingDir = basedir.takeIf { it.resolve(".git").exists() }
?: File(".").takeIf { it.resolve(".git").exists() }
// run the git command with the provided arguments
val process = ProcessBuilder()
.directory(workingDir)
.redirectErrorStream(true)
.command(listOf("git") + args)
.start()
// read the standard output completely as a String
val output = process.inputStream.bufferedReader().readText().trim()
// return the output if the exit value is 0 or throw an exception otherwise
if (process.waitFor() == 0) return output
else throw IllegalStateException(output)
}
val gitVersions by lazy {
// run the `git tag` command
git("tag")
// the returned list of tags is separated by newlines
.split("\n")
// filter out only tags that are versions (such as 1.231.15)
.filter { it.matches(Regex("[0-9]+\\.[0-9]+\\.[0-9]")) }
// the separate parts of each version are separated by dots,
// also parse each part as an int
.map { it.split('.').map { it.toInt() } }
// map each triple of numbers to an instance of the `Version` class
.map { (major, minor, patch) -> Version(major, minor, patch) }
// sort the list of versions
.sorted()
}
// the last release is always the tag with the highest version number
val lastRelease by lazy {
gitVersions.max()
}
// the next version is determined based on the git commit log
val nextVersion by lazy {
// use the lsat released version as the base
val baseVersion = lastRelease
// if there are no releases yet, we use the version 0.0.1
if (baseVersion == null) Version(0, 0, 1)
else {
// split the base version in each separate part using destructuring
val (major, minor, patch) = baseVersion
// create a separator to split each log message on (log messages are multiline)
val separator = "-".repeat(5) + "commit" + "-".repeat(5)
// get all log messages from the last release tag until the current HEAD
// for each commit the separator is printed + the full commit message
val logMessages = git("log", "--pretty=format:$separator%n%B", "$baseVersion..HEAD")
// split the output on each separator generated earlier
.split(separator)
// trim each message, removing excess newlines
.map { it.trim() }
// only keep non-empty messages
.filter { it.isNotEmpty() }
when {
// increment the major and reset the minor + patch if any
// message contains the words 'BREAKING CHANGE'
logMessages.any { it.contains("BREAKING CHANGE") } -> Version(major + 1, 0, 0)
// increment the minor and reset the patch if any message starts with 'feat'
logMessages.any { it.startsWith("feat") } -> Version(major, minor + 1, 0)
// increment the patch in all other cases
else -> Version(major, minor, patch + 1)
}
}
}
project {
// use the next version calculated above when defining our project id
id("nl.craftsmen.blog.kotlin:kotlin-rest-service:${nextVersion}")
dependencies {
compile("org.glassfish.jersey.inject:jersey-hk2:2.29")
compile("org.glassfish.jersey.containers:jersey-container-netty-http:2.29")
compile("org.glassfish.jersey.media:jersey-media-json-jackson:2.29")
runtime("ch.qos.logback:logback-classic:1.2.3")
}
properties {
"project.build.sourceEncoding" to "UTF-8"
"maven.compiler.source" to "11"
"maven.compiler.target" to "11"
}
distributionManagement {
repository("local") {
url(basedir.resolve("repo").toURI().toASCIIString())
}
}
build {
execute(id = "release", phase = "deploy") {
// create a new tag using the next version calculated above
git("tag", "-am", "Release $nextVersion", "$nextVersion")
// print some output
println("Tagged current HEAD as $nextVersion")
}
}
}
Une lib Java rikiki de 153 Ko permet d'écrire des logs plus rapidement qu'avec LogBack ou Log4J2 et qui implémente les interfaces de SLF4J. #Nice
De mon côté Kotlin est constaté dans deux banques et un géant de l'énergie (secteur Parisien) et nous sommes en train de le pousser comme langage par défaut sur le développements d'API qui doivent être utilisées sur des infrastructures ultra legacy (Weblogic + Java 7 #Pleure) pour les remplacer, car Kotlin permet justement de coder avec les features de 2021 et de transcompiler le bytecode vers de vielles JVM 6/7/8.
Rappelons que Java a mis 10 ans pour devenir Java et que quelques années plus tard il est à 1/8ème de son paroxysme, cf. cette Google Trend du 1er janvier 2004 au 7 mars 2021 montrant l'évolution de Java sur ces 17 dernières années.
En comparaison, Kotlin va seulement fêter sa 6ème année... Laissons-lui encore 4 ou 5 ans histoire de voir.
Un framework de test de mutation pour JRE, donc qui marche avec Kotlin et Java.
Encore une très bonne nouvelle pour Kotlin ! Le fait d'avoir une fondation à part, disposant d'un modèle économique clair et qui assure au langage sa survit et mieux encore son évolution est ce qu'il fallait faire.
Le parfait contre-exemple que je pourrais donner est ce qu'a fait la fondation Apache avec Maven dans le sens où Apache étant "anti-argent", la fondation a toujours refusé que des contributeurs majeurs de Maven mettent en place un modèle économique de financement de leurs contributions. 15 ans plus tard, le projet n'a qu'une mise à jour tous les 18 mois... Heureusement, des forks sont apparus comme Maven Daemon mais cela fragmente le marché.
Bref, je suis très contente pour Kotlin.
Très simple :
- Vous installez GraalVM en tant que JAVA_HOME.
- Vous installez native-image dans GraalVM via la commande
gu install native-image
. - Vous installer les GCC + build-essential :
sudo apt install gcc build-essential
- Vous ajoutez le plugin Maven dans votre projet.
Enjoy :D
Parser des fichiers CSV avec la lib OpenCSV en Java et en Kotlin.
Extrait du petit code qui va bien pour une lecture de trèèèès gros fichiers :
try (CSVReader reader = new CSVReader(new FileReader("file.csv"))) {
String[] lineInArray;
while ((lineInArray = reader.readNext()) != null) {
System.out.println(lineInArray[0] + lineInArray[1] + "etc...");
}
}
Cela fait pas mal d'années que je cherche un serveur web à embarquer dans mes applications à destination d'une JRE (Java Runtime Environment) et qui soit :
- Léger, quelques Ko maximum.
- Rapide à démarrer, quelques millisecondes maximum.
- Perfomant, qui encaisse une charge de plusieurs dizaines de milliers de requêtes par secondes sur mon core I5.
- Asynchrone, pour tirer partie du multithread.
- Compilable nativement, via Kotlin Native ou GraalVM.
- Ayant une syntaxe avec et surtout sans annotations, car la réflexion du code rend compliqué la compilation native.
- Libre, gratuit et interropérable.
- Présent dans le répo Maven Central.
- Modulaire, si j'ai besoin du routing alors je ne veux embarquer que les jars dédiés au routing.
Jooby répond à toutes ces conditions. Donc après avoir utilisé Glassfish (outch), Tomcat, Websphere (hur), Jonas (damned), Weblogic (hur again), Jetty, Sparkjava, Undertow, Javalin, Rapidoid et dernièrement Netty, je pense que je vais migrer vers Jooby qui en plus a de meilleures performances que les autres (d'un facteur 2 par rapport à son meilleur challenger, il est même au niveau des serveurs à destination du C++).