<?xml version="1.0" encoding="utf-8" ?> <feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom"> <id>http://jmesnil.net/</id> <title>Jeff Mesnil</title> <author> <name>Jeff Mesnil</name> <email>jmesnil@gmail.com</email> </author> <updated>2025-09-01T12:52:18+00:00</updated> <link href="http://jmesnil.net/weblog/feed/atom/" rel="self" type="application/atom+xml"/> <link href="http://jmesnil.net/" rel="alternate" type="text/html"/> <entry> <title type="html">Working @ IBM</title> <link href="http://jmesnil.net/weblog/2025/09/01/working--ibm/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2025/09/01/working--ibm/</id> <updated>2025-09-01T12:52:18+00:00</updated> <published>2025-09-01T12:52:18+00:00</published> <content type="html"> &lt;p&gt;Short story: As of today, I&#39;m working for IBM. Same team, same project - with a shorter email.&lt;/p&gt; &lt;p&gt;Long story: Back in February, Red Hat &lt;a href=&quot;https://www.redhat.com/en/blog/evolving-our-middleware-strategy&quot;&gt;announced&lt;/a&gt; that they were transferring their middleware division to IBM.&lt;/p&gt; &lt;p&gt;My position as a Software engineer was moved as a part of this transfer, and I&#39;ve chosen to continue the journey here.&lt;/p&gt; &lt;p&gt;In the near term, I&#39;ll keep working on &lt;a href=&quot;https://www.wildfly.org&quot;&gt;WildFly&lt;/a&gt; and &lt;a href=&quot;https://www.redhat.com/en/technologies/jboss-middleware/application-platform&quot;&gt;JBoss EAP&lt;/a&gt; - focusing on their cloud &amp;amp; provisioning capabilities, user experience, and more. Business as usual.&lt;/p&gt; &lt;p&gt;As for the longer term, we&#39;ll see...&lt;/p&gt; &lt;p&gt;I had a great time at Red Hat and I will always look back fondly. Many of my colleagues in middleware are also moving to IBM, but I’ll miss those who stayed behind.&lt;/p&gt; &lt;p&gt;Red is in the past, blue is the color of the future. Here&#39;s to the next chapter of my career!&lt;/p&gt; </content> </entry> <entry> <title type="html">Script to format GitHub links</title> <link href="http://jmesnil.net/weblog/2025/05/06/script-to-format-github-links/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2025/05/06/script-to-format-github-links/</id> <updated>2025-05-06T09:47:36+00:00</updated> <published>2025-05-06T09:47:36+00:00</published> <content type="html"> &lt;p&gt;Almost all my code contributions go in various GitHub projects, either the original repositories or my forks.&lt;/p&gt; &lt;p&gt;Every time I use an URL to a GitHub issue or PR in Google Docs, Markdown or Asciidoc document, I update the link text to be more descriptive so instead of displaying the raw URL as &lt;a href=&quot;https://github.com/wildfly/wildfly.org/pull/787&quot;&gt;https://github.com/wildfly/wildfly.org/pull/787&lt;/a&gt;, it is displayed as &lt;a href=&quot;https://github.com/wildfly/wildfly.org/pull/787&quot;&gt;[wildfly/wildfly.org#787] Add Jeff Mesnil GPG Signing info&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;I&#39;m changing these links so often that I wrote a simple bash script to do it for me. The script can take an GitHub issue or PR argument and will output the corresponding text: &lt;code&gt;[&amp;lt;org&amp;gt;/&amp;lt;repo&amp;gt;#&amp;lt;pr_or_issue&amp;gt;] &amp;lt;title&amp;gt;&lt;/code&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;#!/bin/bash&amp;#x000A;&amp;#x000A;# Get URL from argument or clipboard&amp;#x000A;if [ -n &quot;$1&quot; ]; then&amp;#x000A; URL=&quot;$1&quot;&amp;#x000A;elif command -v pbpaste &amp;amp;&amp;gt;/dev/null; then&amp;#x000A; URL=&quot;$(pbpaste)&quot;&amp;#x000A;else&amp;#x000A; echo &quot;No URL provided and pbpaste is not available.&quot;&amp;#x000A; exit 1&amp;#x000A;fi&amp;#x000A;&amp;#x000A;# Extract repo and number from GitHub issue or PR URL&amp;#x000A;if [[ &quot;$URL&quot; =~ github\.com/([^/]+/[^/]+)/(issues|pull)/([0-9]+) ]]; then&amp;#x000A; REPO=&quot;${BASH_REMATCH[1]}&quot;&amp;#x000A; NUMBER=&quot;${BASH_REMATCH[3]}&quot;&amp;#x000A;else&amp;#x000A; echo &quot;Invalid GitHub issue or pull request URL: $URL&quot;&amp;#x000A; exit 1&amp;#x000A;fi&amp;#x000A;&amp;#x000A;# Fetch and parse the &amp;lt;title&amp;gt; content&amp;#x000A;HTML_TITLE=$(curl -s &quot;$URL&quot; | sed -n &#39;s:.*&amp;lt;title&amp;gt;\(.*\)&amp;lt;/title&amp;gt;.*:\1:p&#39; | head -n1)&amp;#x000A;&amp;#x000A;# Decode HTML entities&amp;#x000A;HTML_TITLE=$(echo &quot;$HTML_TITLE&quot; | sed -e &quot;s/&amp;amp;#39;/&#39;/g&quot; -e &#39;s/&amp;amp;quot;/\&quot;/g&#39; -e &#39;s/&amp;amp;amp;/\&amp;amp;/g&#39;)&amp;#x000A;&amp;#x000A;# Remove &#39; by AUTHOR&#39; (before any dot)&amp;#x000A;HTML_TITLE=$(echo &quot;$HTML_TITLE&quot; | sed -E &#39;s/ by [^·]+//&#39;)&amp;#x000A;&amp;#x000A;# Remove everything after the first literal &#39;·&#39; (U+00B7), regardless of spacing&amp;#x000A;CLEAN_TITLE=$(echo &quot;$HTML_TITLE&quot; | sed &#39;s/·.*//&#39;)&amp;#x000A;&amp;#x000A;# Final formatted output&amp;#x000A;OUTPUT=&quot;[$REPO#$NUMBER] $CLEAN_TITLE&quot;&amp;#x000A;&amp;#x000A;# Copy to clipboard&amp;#x000A;if command -v pbcopy &amp;amp;&amp;gt;/dev/null; then&amp;#x000A; echo &quot;$OUTPUT&quot; | pbcopy&amp;#x000A;else&amp;#x000A; echo &quot;Warning: Clipboard tool not found.&quot;&amp;#x000A;fi&amp;#x000A;&amp;#x000A;# Output to terminal&amp;#x000A;echo &quot;$OUTPUT&quot;&amp;#x000A;&amp;#x000A;afplay /System/Library/Sounds/Tink.aiff&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;To make it even simpler to use on my Mac, if there are no argument, it will instead use the content from the clipboard with &lt;code&gt;pbpaste&lt;/code&gt;. It also copies the title to the clibpboard with &lt;code&gt;pbcopy&lt;/code&gt; and play a sound when it is finished.&lt;/p&gt; &lt;p&gt;I saved this script as a &quot;Format GitHub Link&quot; shortcut with Apple Shortcuts to further streamline its use:&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2025-05-format-github-link-screenhsot.png&quot; alt=&quot;Screenshot of the shortcut&quot;&gt; &lt;figcaption&gt;Run the script as an Apple Shortcut &lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;Now, When I want to add a GitHub link to a document, all I need to do is:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;copy its link address (&lt;code&gt;⌘ C&lt;/code&gt;)&lt;/li&gt; &lt;li&gt;paste it in my doc (&lt;code&gt;⌘ V&lt;/code&gt;)&lt;/li&gt; &lt;li&gt;use the Spotligh launcher to run the script (&lt;code&gt;⌘ &amp;lt;space bar&amp;gt; &amp;gt; &quot;Format&quot;&lt;/code&gt;)&lt;/li&gt; &lt;li&gt;After I hear the sound, copy the formatted title from the clipboard (&lt;code&gt;⌘ V&lt;/code&gt;)&lt;/li&gt; &lt;/ol&gt; </content> </entry> <entry> <title type="html">Prototyping WildFly Applications with JBang (Video)</title> <link href="http://jmesnil.net/weblog/2025/03/26/prototyping-wildfly-applications-with-jbang/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2025/03/26/prototyping-wildfly-applications-with-jbang/</id> <updated>2025-03-26T08:34:33+00:00</updated> <published>2025-03-26T08:34:33+00:00</published> <content type="html"> &lt;p&gt;Yesterday was held the &lt;a href=&quot;https://www.wildfly.org/events/wmc-202503.html&quot;&gt;WildFly mini conference - March 2025&lt;/a&gt; where I presented how you can use &lt;a href=&quot;https://jbang.dev&quot;&gt;JBang&lt;/a&gt; to prototype Entreprise Java applications with &lt;a href=&quot;https://wildfly.org&quot;&gt;WildFly&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;The presentation was streamed on &lt;a href=&quot;https://www.youtube.com/@WildFlyAS&quot;&gt;YouTube WildFly channel&lt;/a&gt;:&lt;/p&gt; &lt;center style=&quot;overflow:hidden; padding-bottom:56.25%; position:relative; height:0;&quot;&gt; &lt;iframe style=&quot;left:0;top:0; height:100%;width:100%;position:absolute;&quot; src=&quot;https://www.youtube.com/embed/d8IExBP7rxw?si=wCBxPpMbnpmZOPYO&amp;amp;start=549&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;/center&gt; &lt;p&gt;Unfortunately, the streaming was a bit compressed and made it difficult to read the code so you might be bettre looking at the &lt;a href=&quot;https://docs.google.com/presentation/d/1zHDrOnGjqREIw8ldEqU0mwXELgBVbbwqmadCVJAnSyg/edit?slide=id.p#slide=id.p&quot;&gt;slides&lt;/a&gt; directly.&lt;/p&gt; &lt;p&gt;The conference was a great success. Don&#39;t hesitate to provide some &lt;a href=&quot;https://docs.google.com/forms/d/e/1FAIpQLSdfTM5f9VTW38CBdnU_XH_ngo-d4y-LvF6WP5dhzbSw28mqqQ/viewform&quot;&gt;feedback&lt;/a&gt; about the presentation and if you are interested to have similar content about the user experience improvements we are making around WildFly.&lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; Prototyping WildFly with JBang @ WildFly Mini Conference</title> <link href="https://www.youtube.com/live/d8IExBP7rxw" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2025/03/17/prototyping-wildfly-with-jbang--wildfly-mini-conference/</id> <updated>2025-03-17T10:06:19+00:00</updated> <published>2025-03-17T10:06:19+00:00</published> <content type="html"> &lt;p&gt;Next week, I&#39;ll talk about prototyping WildFly application with JBang at the &lt;a href=&quot;https://www.wildfly.org/events/wmc-202503.html&quot;&gt;WildFly mini-conference&lt;/a&gt; on March 25th.&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://jbang.dev/&quot;&gt;JBang&lt;/a&gt; is a tool to create, edit and run self-contained source-only Java programs with unprecedented ease. In this presentation, I will show how we can use JBang to prototype simple WildFly applications from a single Java source file. We start with a simple Web application and will prototype an AI chat bot.&lt;/p&gt; &lt;p&gt;The JBang integration was added to WildFly in &lt;a href=&quot;http://docs.wildfly.org/wildfly-proposals/user-experience/jbang.html&quot;&gt;this proposal&lt;/a&gt; and you can already use it and learn about it from the &lt;a href=&quot;https://docs.wildfly.org/wildfly-glow/#jbang&quot;&gt;WildFly Glow documentation&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;The presentation will be done live on the &lt;a href=&quot;https://www.youtube.com/live/d8IExBP7rxw&quot;&gt;WildFly YouTube channel&lt;/a&gt;. See you there!&lt;/p&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2025/03/17/prototyping-wildfly-with-jbang--wildfly-mini-conference/&quot; title=&quot;Permanent link to Prototyping WildFly with JBang @ WildFly Mini Conference&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> <entry> <title type="html">Deliver Go applications as containers</title> <link href="http://jmesnil.net/weblog/2024/10/31/deliver-go-applications-as-containers/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2024/10/31/deliver-go-applications-as-containers/</id> <updated>2024-10-31T11:07:26+00:00</updated> <published>2024-10-31T11:07:26+00:00</published> <content type="html"> &lt;p&gt;I switched to a Apple Silicon laptop running on a ARM architecture and I often want to develop Go applications that are running both on ARM architecture (to run it on my laptop) as well as on Intel.&lt;/p&gt; &lt;p&gt;Go makes it very easy to target different architectures at build time but it makes the delivery of the software more complex as I have to deliver multiple binaries (linux on ARM, linux on Intel, Darwin on ARM, Darwin on Intel, etc.) There are tools for this such as &lt;a href=&quot;https://goreleaser.com&quot;&gt;GoReleaser&lt;/a&gt; but it still makes the deployment of the software more complex. A potential solution is to have a script file that determines the OS &amp;amp; architecture of the target platform and then download the appropriate executable.&lt;/p&gt; &lt;p&gt;Another solution that I am using more often is to deliver the software as a multi-arch container image. The user then just has to pull the image and run it with &lt;code&gt;podman&lt;/code&gt; or &lt;code&gt;docker&lt;/code&gt;.&lt;/p&gt; &lt;p&gt;As as simplistic example, let&#39;s say I need to write a Go application that gives the SHA-256 checksum of strings.&lt;br/&gt; To do so, I can create a Go module with a simple &lt;code&gt;checksum&lt;/code&gt; application:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;$ mkdir checksum&amp;#x000A;$ cd checksum&amp;#x000A;$ go mod init checksum&amp;#x000A;$ mkdir cmd&amp;#x000A;$ touch cmd/checksum.go&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The content of the &lt;code&gt;cmd/checksum.go&lt;/code&gt; is:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;go&quot;&gt;package main&amp;#x000A;&amp;#x000A;import (&amp;#x000A; &quot;crypto/sha256&quot;&amp;#x000A; &quot;encoding/hex&quot;&amp;#x000A; &quot;fmt&quot;&amp;#x000A; &quot;os&quot;&amp;#x000A;)&amp;#x000A;&amp;#x000A;func main() {&amp;#x000A;&amp;#x000A; if len(os.Args) == 1 {&amp;#x000A; fmt.Printf(&quot;No arguments\n&quot;)&amp;#x000A; fmt.Printf(&quot;Usage: checksum &amp;lt;list of strings to hash&amp;gt;\n&quot;)&amp;#x000A; os.Exit(1)&amp;#x000A; }&amp;#x000A;&amp;#x000A; strs := os.Args[1:]&amp;#x000A;&amp;#x000A; hash := sha256.New()&amp;#x000A;&amp;#x000A; for i, str := range strs {&amp;#x000A; h.Reset()&amp;#x000A; hash.Write([]byte(str))&amp;#x000A; checksum := hash.Sum(nil)&amp;#x000A; if i &amp;gt; 0 {&amp;#x000A; fmt.Printf(&quot; &quot;)&amp;#x000A; }&amp;#x000A; fmt.Printf(&quot;%s&quot;, hex.EncodeToString(checksum))&amp;#x000A; }&amp;#x000A; fmt.Printf(&quot;\n&quot;)&amp;#x000A;}&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;I can test that the application is working as expected by running it with &lt;code&gt;go run&lt;/code&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;$ go run ./cmd/checksum.go foo&amp;#x000A;2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;Now, I need to create a container that provides this application for both the ARM and Intel architectures.&lt;/p&gt; &lt;p&gt;I need a simple &lt;code&gt;Containerfile&lt;/code&gt; to do so:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;nocode&quot;&gt;FROM golang:1.23 AS go-builder&amp;#x000A;&amp;#x000A;WORKDIR /workspace/&amp;#x000A;COPY . .&amp;#x000A;RUN GOOS=linux go build -o ./build/checksum ./cmd/checksum.go&amp;#x000A;&amp;#x000A;FROM scratch&amp;#x000A;&amp;#x000A;COPY --from=go-builder /workspace/build/checksum /&amp;#x000A;ENTRYPOINT [ &quot;/checksum&quot; ]&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The container build is done in two stages:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;I use the &lt;code&gt;golang:1.23&lt;/code&gt; builder to compile the code, targeting the &lt;code&gt;linux&lt;/code&gt; operating system.&lt;/li&gt; &lt;li&gt;I create an image from &lt;code&gt;scratch&lt;/code&gt; that only contains the executable compiled from the first stage.&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Then I can use &lt;code&gt;podman&lt;/code&gt; to build a multi-arch image (for both &lt;code&gt;linux/amd64&lt;/code&gt; and &lt;code&gt;linux/arm64&lt;/code&gt;):&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;$ podman build --platform linux/amd64,linux/arm64 --manifest localhost/checksum .&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The resulting &lt;code&gt;localhost/checksum&lt;/code&gt; image is small and contains only the &lt;code&gt;checksum&lt;/code&gt; executable.&lt;/p&gt; &lt;p&gt;I can run it locally with &lt;code&gt;podman&lt;/code&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;$ podman run localhost/checksum foo&amp;#x000A;&amp;#x000A;2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;Podman will run the &lt;code&gt;linux/arm64&lt;/code&gt; image on my ARM laptop but an user on a Intel machine would use the &lt;code&gt;linux/amd64&lt;/code&gt; image. I can force Podman to use the Intel variant on my ARM laptop and it would run fine too (with a warning that the image no longer matches my platform)&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;$ podman run --platform linux/amd64 localhost/checksum foo&amp;#x000A;&amp;#x000A;WARNING: image platform (linux/arm64) does not match the expected platform (linux/amd64)&amp;#x000A;2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;At this point, to make the application available for others, I just need to push it to a container registry on Quay.io or ghcr.io and they will be able to use it as I do on my laptop.&lt;/p&gt; &lt;p&gt;This solution works fine for programs that don&#39;t need heavy integration with the host operating system. If my input would need to access the file system, I would have to mount directories with &lt;code&gt;-v&lt;/code&gt; to make them available inside the image. If the integration with the host starts to be more complex, it would be better to provide a shell script that pulls the image and run Podman with the right configuration parameters.&lt;/p&gt; </content> </entry> <entry> <title type="html">Dikembe Mutombo (1966-2024)</title> <link href="http://jmesnil.net/weblog/2024/10/01/dikembe-mutombo/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2024/10/01/dikembe-mutombo/</id> <updated>2024-10-01T13:31:24+00:00</updated> <published>2024-10-01T13:31:24+00:00</published> <content type="html"> &lt;p&gt;&lt;figure class=&quot;portrait&quot;&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2024-10-dikembe-mutombo-all-star.jpg&quot; alt=&quot;Dikembe Mutombo All Star Card&quot;&gt; &lt;figcaption&gt;Dikembe Mutombo All Star Card &lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;I learnt yesterday the sad news that Dikembe Mutombo passed away at the age of 58 from a brain cancer.&lt;/p&gt; &lt;p&gt;He started his career in 1991 as I got interested in the NBA. He was a great player to watch as I enjoy the defensive side of Basket ball.&lt;/p&gt; &lt;p&gt;I fondly remember when he fell down the floor after upsetting the Seattle SuperSonics of Gary Payton and Shawn Kemp. That was the first time a 8&lt;sup&gt;th&lt;/sup&gt; seed won against a 1&lt;sup&gt;st&lt;/sup&gt; seed and his joy was contagious.&lt;/p&gt; &lt;p&gt;23 years later, I still have player cards from him that I scanned for this post.&lt;/p&gt; &lt;p&gt;&lt;figure class=&quot;portrait&quot;&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2024-10-dikembe-mutombo-player-card.jpg&quot; alt=&quot;Dikembe Mutombo Player Card&quot;&gt; &lt;figcaption&gt;Dikembe Mutombo Player Card &lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;Next time I play with my kids, I&#39;ll show them how he was wagging his finger when he blocked an opponent shot :)&lt;/p&gt; </content> </entry> <entry> <title type="html">20-year anniversary of jmesnil.net</title> <link href="http://jmesnil.net/weblog/2024/09/12/20-year-anniversary-of-jmesnilnet/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2024/09/12/20-year-anniversary-of-jmesnilnet/</id> <updated>2024-09-12T12:17:15+00:00</updated> <published>2024-09-12T12:17:15+00:00</published> <content type="html"> &lt;p&gt;I missed the date but I posted &lt;a href=&quot;/weblog/2004/06/11/distributed-computing-is-not-an-afterthought/&quot;&gt;the first article on this blog&lt;/a&gt; on June, 11th 2024.&lt;/p&gt; &lt;p&gt;Twenty years later, and 350 posts later, my server is still there serving all the content I wrote from the start.&lt;/p&gt; &lt;p&gt;I went through different hosts and visual presentation until I settled down with using a AWS S3 Buck to host this static server built with &lt;a href=&quot;https://github.com/awestruct/awestruct&quot;&gt;Awestruct&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Out of nostalgia, I played with the &lt;a href=&quot;https://web.archive.org/&quot;&gt;Wayback Machine&lt;/a&gt; to remember of my web site looked over the years.&lt;/p&gt; &lt;p&gt;The &lt;a href=&quot;https://web.archive.org/web/20040608163211/http://www.jmesnil.net/weblog/&quot;&gt;initial version&lt;/a&gt; was hosted on &lt;a href=&quot;https://www.movabletype.org&quot;&gt;Movable Type&lt;/a&gt; using their standard template. I made some &lt;a href=&quot;https://web.archive.org/web/20050305002431/http://www.jmesnil.net/weblog/&quot;&gt;terrible visual choice&lt;/a&gt; that I quickly removed for a &lt;a href=&quot;https://web.archive.org/web/20060718074004/http://jmesnil.net/weblog/&quot;&gt;cluttered look&lt;/a&gt; before going full page on the &lt;a href=&quot;https://web.archive.org/web/20101123153014/http://jmesnil.net/weblog/&quot;&gt;content&lt;/a&gt; that I stripped down to the &lt;a href=&quot;https://jmesnil.net/weblog/&quot;&gt;current design&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;On the technical side, I don&#39;t remember all the solutions but I used Movable Type, BlogPost, WordPress. Eventually, I switched to a static generation of the content from Markdown pages in a &lt;a href=&quot;https://github.com/jmesnil/jmesnil.net/&quot;&gt;Git repository&lt;/a&gt; that are pushed to a AWS S3 Bucket.&lt;/p&gt; &lt;p&gt;The latest technical changes I did were to use a container image to manage all the Ruby dependencies from Awestruct and adding a &lt;a href=&quot;https://jmesnil.net/weblog/2023/09/13/tls-certificate-on-jmesnil/&quot;&gt;TLS Certificate to the server&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;I have had bursts of activity on my web site and long periods of neglects but it is still great to have a place I can call my own on the Web...&lt;/p&gt; </content> </entry> <entry> <title type="html">My Professional Mission Statement</title> <link href="http://jmesnil.net/weblog/2024/09/10/my-mission-statement/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2024/09/10/my-mission-statement/</id> <updated>2024-09-10T10:09:11+00:00</updated> <published>2024-09-10T10:09:11+00:00</published> <content type="html"> &lt;p&gt;&lt;em&gt;[This week is Career Week at my &lt;a href=&quot;https://www.redhat.com/&quot;&gt;company&lt;/a&gt; and a great opportunity to reflect on my career and what lies ahead]&lt;/em&gt;&lt;/p&gt; &lt;p&gt;A few years ago, my manager, Stefano, introduced me to the concept of defining personal Mission and Vision statements to help me guide my career.&lt;/p&gt; &lt;p&gt;I updated my &lt;a href=&quot;/about/&quot;&gt;About page&lt;/a&gt; some time ago with my professional mission statement but never elaborated on it. This post is a good opportunity to do so.&lt;/p&gt; &lt;p&gt;My professional mission statement is:&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;&lt;i class=&quot;fa fa-quote-left&quot;&gt;&lt;/i&gt;&amp;nbsp;&amp;nbsp;I aim to build software based on sustainability, openness, and humane values, driving towards a more equitable world.&amp;nbsp;&amp;nbsp;&lt;i class=&quot;fa fa-quote-right&quot;&gt;&lt;/i&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I&#39;m an engineer at heart so building software is what I do and what I enjoy the most.&lt;/p&gt; &lt;p&gt;We are facing a climate change that is impacting all humanity and it is our duty for ourselves and future generations to do as much as we can to circumvent it. In my profession, the best I can do is build sustainable software that have minimal carbon impact on the planet.&lt;/p&gt; &lt;p&gt;There are many approaches to build software, but I only want to do it in a way that fosters openness, transparency and human-centered values. I have been fortunate to work for many years with great colleagues and users that are kind, knowledgeable, willing to listen, giving and receiving constructive feedback.&lt;/p&gt; &lt;p&gt;I can&#39;t imagine switching to another working environment as I believe in a variant of &lt;a href=&quot;https://en.wikipedia.org/wiki/Conway%27s_law&quot;&gt;Conway&#39;s law&lt;/a&gt;:&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;Organizations which design systems are constrained to produce designs which copy the &lt;em&gt;behaviours&lt;/em&gt; of these organizations.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;By acting with transparency and empathy, we are more likely to build software that creates a more open and humane world.&lt;/p&gt; &lt;p&gt;All I am doing professionally is making sure that I contribute to a better world for my kids, and the world I want for them is an equitable one where every individual has opportunities to grow, learn, and accomplish their goals.&lt;/p&gt; &lt;p&gt;I do not want to build software that benefits a few at the expense of the rest of the humanity. That is what attracted me to Open Source development at the beginning of my career, and I still believe in it more than 20 years later.&lt;/p&gt; &lt;p&gt;Unfortunately, my mission statement is at odds with most of the IT industry which aims for infinite growth at the expense of users, citizens, its own employees and the planet.&lt;/p&gt; &lt;p&gt;I have to live with that dichotomy and do my best to align the world with my values and beliefs. My mission statement is a simple effective way to never lose sight of what is truly meaningful to me.&lt;/p&gt; </content> </entry> <entry> <title type="html">Engineering is Problem-solving</title> <link href="http://jmesnil.net/weblog/2024/09/09/engineering-is-problem-solving/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2024/09/09/engineering-is-problem-solving/</id> <updated>2024-09-09T08:57:50+00:00</updated> <published>2024-09-09T08:57:50+00:00</published> <content type="html"> &lt;p&gt;Last weekend, I discussed with a friend the different approaches we had in our jobs.&lt;/p&gt; &lt;p&gt;I told him an anecdote from my study years.&lt;/p&gt; &lt;p&gt;I have a mathematical background and studied applied mathematics with a sprinkle of computing and applied physics.&lt;/p&gt; &lt;p&gt;During a trimester, our Physics teacher taught us a single theorem (sadly, I can&#39;t remember which one...). We had an upcoming exam and what could it be about if not this theorem? The day of the exam, we all applied the theorem as expected... and we all failed the exam.&lt;/p&gt; &lt;p&gt;During the correction, our teacher told us that we all applied the theorem to the stated problem without verifying that the constraints and boundaries were applicable. They were not and the theorem was not a solution to the problem.&lt;/p&gt; &lt;p&gt;The teacher explained to us that he &quot;tricked&quot; us on purpose. His objective was not to make us learn and apply the theorem but to make us think by ourselves:&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt; &lt;em&gt;First&lt;/em&gt;, understand the problem, its constraints, and its boundaries.&lt;br/&gt; &lt;em&gt;Then&lt;/em&gt; see if there is an equation, a theorem that &lt;em&gt;could&lt;/em&gt; apply to its resolution.&lt;br/&gt; &lt;em&gt;Finally&lt;/em&gt;, use this tool to solve the problem optimally.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I told this anecdocte to my friend because that might be the best advice I got during all my studies.&lt;/p&gt; &lt;p&gt;As an engineer, my main task is to solve &quot;problems&quot; that our users face with the toolkits at their disposal.&lt;/p&gt; &lt;p&gt;The toolkits in the IT industry are ever expanding (Cloud! Microservices! Blockchains! Now AI!) and an increasing part of my work is to figure out if a tool is relevant for a given problem.&lt;/p&gt; &lt;p&gt;The reasoning should follow the advice of my teacher: &lt;em&gt;first&lt;/em&gt; understand the problem to solve, &lt;em&gt;then&lt;/em&gt; find the solutions that can be applied to it and &lt;em&gt;finally&lt;/em&gt; find the optimal solution for the problem.&lt;/p&gt; &lt;p&gt;Of course, it is easier said than done as there is a strong industry push to find a technical solution to then apply it to any problem.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Let&#39;s move all our workloads to the cloud!&lt;/li&gt; &lt;li&gt;Let&#39;s add a chatbot to our applications!&lt;/li&gt; &lt;li&gt;Let&#39;s split our monolithic application into microservices!&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;These tools are fine and definitely suitable for many cases, but they are &lt;em&gt;never universally applicable&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;Following trends without ensuring they address the specific issue at hand can lead to wasted effort and resources, leaving us with all the downsides of a new technology without reaping its benefits.&lt;/p&gt; &lt;p&gt;Problem-solving is the most creative aspect of my engineering job, the one I enjoy the most and (talking about the latest IT trend) the one least likely to be replaced by artificial intelligence.&lt;/p&gt; </content> </entry> <entry> <title type="html">WildFly - The GitOps Way</title> <link href="http://jmesnil.net/weblog/2024/03/05/wildfly-gitops/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2024/03/05/wildfly-gitops/</id> <updated>2024-03-05T11:54:32+00:00</updated> <published>2024-03-05T11:54:32+00:00</published> <content type="html"> &lt;p&gt;We have improved the Maven plug-in for &lt;a href=&quot;https://wildfly.org&quot;&gt;WildFly&lt;/a&gt; to be able to provision and configure WildFly application server directly from the application source code. This make it very simple to control the server configuration and management model and make sure it is tailor-made for the application requirements.&lt;/p&gt; &lt;p&gt;This is a good model for DevOps team where a single team is responsible for the development and deployment of the application.&lt;/p&gt; &lt;p&gt;However, we have users that are in a different organisational structure where the Development team and the Operational team work in silos.&lt;/p&gt; &lt;p&gt;In this article, we will show how it is possible to leverage the WildFly Maven plugin to handle the configuration and deployment of WildFly separately from the application development in a loose &lt;strong&gt;GitOps&lt;/strong&gt; manner.&lt;/p&gt; &lt;h2&gt;Provision the WildFly Server&lt;/h2&gt; &lt;p&gt;We will use a Maven project to control the application server installation and configuration.&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;mkdir wildfly-gitops&amp;#x000A;cd wildfly-gitops&amp;#x000A;touch pom.xml&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The &lt;code&gt;pom.xml&lt;/code&gt; will configure the provisioning and configuration of WildFly&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;&amp;#x000A;&amp;lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot;&amp;#x000A; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&amp;#x000A; xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&amp;gt;&amp;#x000A; &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;org.wildfly.gitops&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;wildfly-gitops&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;version&amp;gt;1.0.0-SNAPSHOT&amp;lt;/version&amp;gt;&amp;#x000A;&amp;#x000A; &amp;lt;packaging&amp;gt;pom&amp;lt;/packaging&amp;gt;&amp;#x000A; &amp;lt;properties&amp;gt;&amp;#x000A; &amp;lt;!-- Specify the version of WildFly to provision --&amp;gt;&amp;#x000A; &amp;lt;version.wildfly&amp;gt;31.0.0.Final&amp;lt;/version.wildfly&amp;gt;&amp;#x000A; &amp;lt;version.wildfly.maven.plugin&amp;gt;4.2.2.Final&amp;lt;/version.wildfly.maven.plugin&amp;gt;&amp;#x000A; &amp;lt;/properties&amp;gt;&amp;#x000A;&amp;#x000A; &amp;lt;build&amp;gt;&amp;#x000A; &amp;lt;plugins&amp;gt;&amp;#x000A; &amp;lt;plugin&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;org.wildfly.plugins&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;wildfly-maven-plugin&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;version&amp;gt;${version.wildfly.maven.plugin}&amp;lt;/version&amp;gt;&amp;#x000A; &amp;lt;configuration&amp;gt;&amp;#x000A; &amp;lt;feature-packs&amp;gt;&amp;#x000A; &amp;lt;feature-pack&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;org.wildfly&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;wildfly-galleon-pack&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;version&amp;gt;${version.wildfly}&amp;lt;/version&amp;gt;&amp;#x000A; &amp;lt;/feature-pack&amp;gt;&amp;#x000A; &amp;lt;/feature-packs&amp;gt;&amp;#x000A; &amp;lt;/configuration&amp;gt;&amp;#x000A; &amp;lt;executions&amp;gt;&amp;#x000A; &amp;lt;execution&amp;gt;&amp;#x000A; &amp;lt;id&amp;gt;provision-widfly&amp;lt;/id&amp;gt;&amp;#x000A; &amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;&amp;#x000A; &amp;lt;goals&amp;gt;&amp;#x000A; &amp;lt;goal&amp;gt;provision&amp;lt;/goal&amp;gt;&amp;#x000A; &amp;lt;/goals&amp;gt;&amp;#x000A; &amp;lt;/execution&amp;gt;&amp;#x000A; &amp;lt;/executions&amp;gt;&amp;#x000A; &amp;lt;/plugin&amp;gt;&amp;#x000A; &amp;lt;/plugins&amp;gt;&amp;#x000A; &amp;lt;/build&amp;gt;&amp;#x000A;&amp;lt;/project&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;This &lt;code&gt;pom.xml&lt;/code&gt; will provision (install and configure) WildFly. The version of WildFly is configured with the &lt;code&gt;version.wildfly&lt;/code&gt; property (set &lt;code&gt;31.0.0.Final&lt;/code&gt; in the snippet above).&lt;/p&gt; &lt;p&gt;Let&#39;s now install it with:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;mvn clean package&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;Once the execution is finished, you have a WildFly server ready to run in &lt;code&gt;target/server&lt;/code&gt; and you can run it with the command:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;cd target/server&amp;#x000A;./bin/standalone.sh&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The last log will show that we indeed installed WildFly 31.0.0.Final:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;13:21:52,651 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Full 31.0.0.Final (WildFly Core 23.0.1.Final) started in 1229ms - Started 280 of 522 services (317 services are lazy, passive or on-demand) - Server configuration file in use: standalone.xml&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;At this point you can init a Git repository from this &lt;code&gt;wildfly-gitops&lt;/code&gt; directory and you have the foundation to manage WildFly in a GitOps way.&lt;/p&gt; &lt;p&gt;The Maven Plugin for WildFly provides rich features to configure WildFly including:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;using &lt;a href=&quot;https://docs.wildfly.org/31/Galleon_Guide.html#wildfly_galleon_layers&quot;&gt;Galleon Layers&lt;/a&gt; to trim the server according to the deployment capabilities&lt;/li&gt; &lt;li&gt;Running CLI scripts to configure its subsystems (for example, the &lt;a href=&quot;https://www.wildfly.org/guides/application-logging#configure-logging-in-the-wildfly-subsystem&quot;&gt;Logging Guide&lt;/a&gt; illustrates how you can add a Logging category for your own deployments)&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;[Aside] Create Application Deployments&lt;/h1&gt; &lt;p&gt;To illustrate how to manage the deployments of application in this server without direct control of the application source code, we must first create these deployments.&lt;/p&gt; &lt;p&gt;When Dev and Ops teams are separate, the Dev team will have done these steps and the Ops team would only need to know the Maven coordinates of the deployments.&lt;/p&gt; &lt;p&gt;For this purpose, we will compile and install 2 quickstarts examples from WildFly in our local maven repository:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;cd /tmp&amp;#x000A;git clone --depth 1 --branch 31.0.0.Final https://github.com/wildfly/quickstart.git&amp;#x000A;cd quickstart&amp;#x000A;mvn clean install -pl helloworld,microprofile-config&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;We have only built the &lt;code&gt;helloworld&lt;/code&gt; and &lt;code&gt;microprofile-config&lt;/code&gt; quickstarts and put them in our local Maven repository.&lt;/p&gt; &lt;p&gt;We now have two deployments that we want to deploy in our WildFly Server with the Maven coordinates:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;org.wildfly.quickstarts:helloworld:31.0.0.Final&lt;/code&gt;&lt;/li&gt; &lt;li&gt;&lt;code&gt;org.wildfly.quickstarts:microprofile-config:31.0.0.Final&lt;/code&gt;&lt;/li&gt; &lt;/ul&gt; &lt;h1&gt;Assemble The WildFly Server With Deployments&lt;/h1&gt; &lt;p&gt;Now that we have deployments to work with, let&#39;s see how we can include them in our WildFly server in a GitOps manner.&lt;/p&gt; &lt;p&gt;We will use a Maven assembly to control the deployments in our server. To do so, we will create a &lt;code&gt;assembly.xml&lt;/code&gt; file in the &lt;code&gt;wildfly-gitops&lt;/code&gt; directory:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&amp;lt;assembly xmlns=&quot;http://maven.apache.org/ASSEMBLY/2.1.1&quot;&amp;#x000A; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&amp;#x000A; xsi:schemaLocation=&quot;http://maven.apache.org/ASSEMBLY/2.1.1 http://maven.apache.org/xsd/assembly-2.1.1.xsd&quot;&amp;gt;&amp;#x000A; &amp;lt;id&amp;gt;gitops-server&amp;lt;/id&amp;gt;&amp;#x000A; &amp;lt;formats&amp;gt;&amp;#x000A; &amp;lt;format&amp;gt;dir&amp;lt;/format&amp;gt;&amp;#x000A; &amp;lt;/formats&amp;gt;&amp;#x000A; &amp;lt;fileSets&amp;gt;&amp;#x000A; &amp;lt;fileSet&amp;gt;&amp;#x000A; &amp;lt;directory&amp;gt;target/server&amp;lt;/directory&amp;gt;&amp;#x000A; &amp;lt;outputDirectory/&amp;gt;&amp;#x000A; &amp;lt;/fileSet&amp;gt;&amp;#x000A; &amp;lt;/fileSets&amp;gt;&amp;#x000A;&amp;#x000A; &amp;lt;dependencySets&amp;gt;&amp;#x000A; &amp;lt;dependencySet&amp;gt;&amp;#x000A; &amp;lt;includes&amp;gt;&amp;#x000A; &amp;lt;include&amp;gt;*:war&amp;lt;/include&amp;gt;&amp;#x000A; &amp;lt;/includes&amp;gt;&amp;#x000A; &amp;lt;outputDirectory&amp;gt;standalone/deployments&amp;lt;/outputDirectory&amp;gt;&amp;#x000A; &amp;lt;outputFileNameMapping&amp;gt;${artifact.artifactId}.${artifact.extension}&amp;lt;/outputFileNameMapping&amp;gt;&amp;#x000A; &amp;lt;/dependencySet&amp;gt;&amp;#x000A; &amp;lt;/dependencySets&amp;gt;&amp;#x000A;&amp;lt;/assembly&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;All this verbose file does is:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;create a directory that is composed of: &lt;ul&gt; &lt;li&gt;the content of the &lt;code&gt;target/server&lt;/code&gt; (that contains the WildFly Server)&lt;/li&gt; &lt;li&gt;add any &lt;code&gt;war&lt;/code&gt; dependency to the &lt;code&gt;standalone/deployments&lt;/code&gt; of this directoy &lt;ul&gt; &lt;li&gt;and rename them to &lt;code&gt;xxx.war&lt;/code&gt; (instead of the whole Maven coordinates)&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;/ul&gt; &lt;p&gt;We also need to update the &lt;code&gt;pom.xml&lt;/code&gt; to use this assembly:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&amp;lt;project&amp;gt;&amp;#x000A; [...]&amp;#x000A; &amp;lt;build&amp;gt;&amp;#x000A; [...]&amp;#x000A; &amp;lt;plugins&amp;gt;&amp;#x000A; [...]&amp;#x000A; &amp;lt;plugin&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;maven-assembly-plugin&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;configuration&amp;gt;&amp;#x000A; &amp;lt;finalName&amp;gt;wildfly&amp;lt;/finalName&amp;gt;&amp;#x000A; &amp;lt;/configuration&amp;gt;&amp;#x000A; &amp;lt;executions&amp;gt;&amp;#x000A; &amp;lt;execution&amp;gt;&amp;#x000A; &amp;lt;id&amp;gt;make-assembly&amp;lt;/id&amp;gt;&amp;#x000A; &amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;&amp;#x000A; &amp;lt;goals&amp;gt;&amp;#x000A; &amp;lt;goal&amp;gt;single&amp;lt;/goal&amp;gt;&amp;#x000A; &amp;lt;/goals&amp;gt;&amp;#x000A; &amp;lt;configuration&amp;gt;&amp;#x000A; &amp;lt;descriptors&amp;gt;&amp;#x000A; &amp;lt;descriptor&amp;gt;assembly.xml&amp;lt;/descriptor&amp;gt;&amp;#x000A; &amp;lt;/descriptors&amp;gt;&amp;#x000A; &amp;lt;/configuration&amp;gt;&amp;#x000A; &amp;lt;/execution&amp;gt;&amp;#x000A; &amp;lt;/executions&amp;gt;&amp;#x000A; &amp;lt;/plugin&amp;gt;&amp;#x000A; [...]&amp;#x000A;&amp;lt;/project&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;We can now run a Maven command to assemble our server:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;mvn clean package&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;When the command is finished, we now have an assembled server in &lt;code&gt;target/wildfly-gitops-server/wildfly&lt;/code&gt;&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;cd target/wildfly-gitops-server/wildfly&amp;#x000A;./bin/standalone.sh&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;hr /&gt; &lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: There are 2 different &quot;servers&quot; after &lt;code&gt;mvn package&lt;/code&gt; is executed:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;target/server&lt;/code&gt; contains the provisioned WildFly Server&lt;/li&gt; &lt;li&gt;&lt;code&gt;target/wildfly-gitops-server/wildfly&lt;/code&gt; contains the WildFly server (copied from the previous directory) with any additional deployments.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;But we did not add any deployment! Let&#39;s do it now.&lt;/p&gt; &lt;hr /&gt; &lt;p&gt;In the &lt;code&gt;wildfly-gitops/pom.xml&lt;/code&gt;, we will add a &lt;code&gt;dependency&lt;/code&gt; to specify that we want to include the &lt;code&gt;helloworld&lt;/code&gt; quickstart:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&amp;lt;project&amp;gt;&amp;#x000A; [...]&amp;#x000A; &amp;lt;dependencies&amp;gt;&amp;#x000A; &amp;lt;dependency&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;org.wildfly.quickstarts&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;helloworld&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;version&amp;gt;31.0.0.Final&amp;lt;/version&amp;gt;&amp;#x000A; &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;&amp;#x000A; &amp;lt;/dependency&amp;gt;&amp;#x000A; &amp;lt;/dependencies&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;And that&#39;s it!&lt;/p&gt; &lt;p&gt;Let&#39;s now run once more &lt;code&gt;mvn clean package&lt;/code&gt;.&lt;/p&gt; &lt;p&gt;If we now list the &lt;code&gt;standalone/deployments&lt;/code&gt; directory of the assembled server, the &lt;code&gt;helloworld.war&lt;/code&gt; deployment is listed:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;ls target/wildfly-gitops-server/wildfly/standalone/deployments&amp;#x000A;README.txt helloworld.war&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;When we run the assembled server, the HelloWorld application is deployed and ready to run:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;cd target/wildfly-gitops-server/wildfly&amp;#x000A;./bin/standalone.sh&amp;#x000A;&amp;#x000A;...&amp;#x000A;14:01:25,307 INFO [org.jboss.as.server] (ServerService Thread Pool -- 45) WFLYSRV0010: Deployed &quot;helloworld.war&quot; (runtime-name : &quot;helloworld.war&quot;)&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;We can access the application by opening our browser at &lt;a href=&quot;http://localhost:8080/helloworld/&quot;&gt;localhost:8080/helloworld/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;At this stage, we have complete control of the WildFly server and the application(s) we want to deploy on it from this &lt;code&gt;wildfly-gitops&lt;/code&gt; Git repository.&lt;/p&gt; &lt;p&gt;Let&#39;s see what we could do from here.&lt;/p&gt; &lt;h1&gt;Add Another Deployment to The Server&lt;/h1&gt; &lt;p&gt;We can now add the &lt;code&gt;microprofile-config&lt;/code&gt; deployment to the assembled server by adding it as a &lt;code&gt;dependency&lt;/code&gt; in the &lt;code&gt;pom.xml&lt;/code&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&amp;lt;project&amp;gt;&amp;#x000A; [...]&amp;#x000A; &amp;lt;dependencies&amp;gt;&amp;#x000A; [...]&amp;#x000A; &amp;lt;dependency&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;org.wildfly.quickstarts&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;microprofile-config&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;version&amp;gt;31.0.0.Final&amp;lt;/version&amp;gt;&amp;#x000A; &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;&amp;#x000A; &amp;lt;/dependency&amp;gt;&amp;#x000A; &amp;lt;/dependencies&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;Let&#39;s package the server again and start it:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;mvn clean package&amp;#x000A;cd target/wildfly-gitops-server/wildfly&amp;#x000A;CONFIG_PROP=&quot;Welcome to GitOps&quot; ./bin/standalone.sh&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The &lt;code&gt;microprofile-config&lt;/code&gt; application is deployed and can be accessed from &lt;a href=&quot;http://localhost:8080/microprofile-config/config/value&quot;&gt;localhost:8080/microprofile-config/config/value&lt;/a&gt;&lt;/p&gt; &lt;p&gt;We have added deployments using Maven dependencies but it is also possible to include them in the assembled server by other means (copy them from a local directory, fetch them from Internet, etc.). The &lt;a href=&quot;https://maven.apache.org/plugins/maven-assembly-plugin/&quot;&gt;Assembly Plugin&lt;/a&gt; provides additional information for this.&lt;/p&gt; &lt;h1&gt;Update The WildFly Server&lt;/h1&gt; &lt;p&gt;The version of WildFly that we are provisioning is specified in the &lt;code&gt;pom.xml&lt;/code&gt; with the &lt;code&gt;version.wildfly&lt;/code&gt; property. Let&#39;s change it to use a more recent version of WildFly 31.0.1.Final&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&amp;lt;project&amp;gt;&amp;#x000A; [...]&amp;#x000A; &amp;lt;properties&amp;gt;&amp;#x000A; &amp;lt;!-- Specify the version of WildFly to provision --&amp;gt;&amp;#x000A; &amp;lt;version.wildfly&amp;gt;31.0.1.Final&amp;lt;/version.wildfly&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;We can repackage the server and see that it is now running WildFly 31.0.1.Final:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;bash&quot;&gt;mvn clean package&amp;#x000A;cd target/wildfly-gitops-server/wildfly&amp;#x000A;...&amp;#x000A;14:15:23,909 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Full 31.0.1.Final (WildFly Core 23.0.3.Final) started in 1938ms - Started 458 of 678 services (327 services are lazy, passive or on-demand) - Server configuration file in use: standalone.xml&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;h1&gt;Use Dependabot to Be Notified of WildFly Updates&lt;/h1&gt; &lt;p&gt;WildFly provisioning is using Maven artifacts. We can take advantage of this to add a &quot;symbolic&quot; dependency to the WildFly Galleon Pack artifact in our &lt;code&gt;pom.xml&lt;/code&gt; so that Dependabot will periodically check and propose updates when new versions of WildFly are available:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;xml&quot;&gt;&amp;lt;project&amp;gt;&amp;#x000A; [...]&amp;#x000A; &amp;lt;dependencies&amp;gt;&amp;#x000A; [...]&amp;#x000A; &amp;lt;/dependency&amp;gt;&amp;#x000A; &amp;lt;!-- We add the WildFly Galleon Pack as a provided POM dependency&amp;#x000A; to be able to use dependabot to be notified of updates --&amp;gt;&amp;#x000A; &amp;lt;dependency&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;org.wildfly&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;wildfly-galleon-pack&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;version&amp;gt;${version.wildfly}&amp;lt;/version&amp;gt;&amp;#x000A; &amp;lt;type&amp;gt;pom&amp;lt;/type&amp;gt;&amp;#x000A; &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;&amp;#x000A; &amp;lt;/dependency&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;We use a &lt;code&gt;provided&lt;/code&gt; scope as we don&#39;t want to pull this dependency but this will ensure that Dependabot is aware of it and triggers updates when a new version is available.&lt;/p&gt; &lt;h1&gt;Summary&lt;/h1&gt; &lt;p&gt;In this article, we show how you can leverage the WildFly Maven Plug-in to manage WildFly in a GitOps way that is not directly tied to the development of the applications that are be deployed to the server.&lt;/p&gt; &lt;p&gt;The code snippets used in this article are available on GitHub at &lt;a href=&quot;https://github.com/jmesnil/wildfly-gitops&quot;&gt;github.com/jmesnil/wildfly-gitops&lt;/a&gt;.&lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; An Illustrated Guide to 12 Factor Apps</title> <link href="https://www.redhat.com/architect/12-factor-app" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2023/09/13/an-illustrated-guide-to-12-factor-apps/</id> <updated>2023-09-13T13:19:31+00:00</updated> <published>2023-09-13T13:19:31+00:00</published> <content type="html"> &lt;p&gt;Right after writing a wall of text that use the &lt;a href=&quot;https://12factor.net&quot;&gt;Twelve-Factor App&lt;/a&gt; methodology to frame &lt;a href=&quot;https://jmesnil.net/weblog/2023/09/13/wildfly-12-factor-app/&quot;&gt;what WildFly provides to develop and operate &quot;cloudy&quot; Entreprise Java applications&lt;/a&gt;, a colleague pointed me to this &lt;a href=&quot;https://www.redhat.com/architect/12-factor-app&quot;&gt;article&lt;/a&gt; on Red Hat web site that nicely illustrates each factor.&lt;/p&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2023/09/13/an-illustrated-guide-to-12-factor-apps/&quot; title=&quot;Permanent link to An Illustrated Guide to 12 Factor Apps&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> <entry> <title type="html">WildFly and the Twelve-factor App Methodology</title> <link href="http://jmesnil.net/weblog/2023/09/13/wildfly-12-factor-app/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2023/09/13/wildfly-12-factor-app/</id> <updated>2023-09-13T07:30:04+00:00</updated> <published>2023-09-13T07:30:04+00:00</published> <content type="html"> &lt;p&gt;In my daily job at &lt;a href=&quot;https://redhat.com&quot;&gt;Red Hat&lt;/a&gt;, I&#39;m focused these days on making &lt;a href=&quot;http://wildfly.org&quot;&gt;WildFly&lt;/a&gt; run great on container platforms such as &lt;a href=&quot;https://kubernetes.io&quot;&gt;Kubernetes&lt;/a&gt;.&lt;/p&gt; &lt;h2&gt;&quot;Traditional&quot; way to develop and run applications with WildFly&lt;/h2&gt; &lt;p&gt;WildFly is a &quot;traditional&quot; application server for Entreprise Java applications. To use it on the cloud, we are making it more flexible and closer to &quot;cloud-native&quot; applications so that it can be used to develop and run a &lt;a href=&quot;https://12factor.net&quot;&gt;12-Factor App&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Traditionally, if you were using WildFly on your own machine, the (simplified) steps would be:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Download WildFly archive and unzip it&lt;/li&gt; &lt;li&gt;Edit its XML configuration to match your application requirements&lt;/li&gt; &lt;li&gt;In your code repository, build your deployment (WAR, EAR, etc.) with Maven&lt;/li&gt; &lt;li&gt;Start WildFly&lt;/li&gt; &lt;li&gt;Copy your deployment&lt;/li&gt; &lt;li&gt;Run tests&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;At this point, your application is verified and ready to use.&lt;/p&gt; &lt;p&gt;There are a few caveats to be mindful of.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Whenever a new version of WildFly is available, you have to re-apply your configuration change and verify that the resulting configuration is valid.&lt;/li&gt; &lt;li&gt;You run tests against your &lt;em&gt;local&lt;/em&gt; download of WildFly with your &lt;em&gt;local&lt;/em&gt; modifications. Are you sure that these changes are up to date with the production servers?&lt;/li&gt; &lt;li&gt;If you are developing multiple applications, are you using different WildFly downloads to test them separately?&lt;/li&gt; &lt;/ul&gt; &lt;h2&gt;&quot;Cloudy&quot; way to develop and run applications with WildFly&lt;/h2&gt; &lt;p&gt;When you want to operate such application on the cloud, you want to automate all these steps in a reproduceable manner.&lt;/p&gt; &lt;p&gt;To achieve this, we inverted the traditional application server paradigm.&lt;/p&gt; &lt;p&gt;Before, WildFly was the top-level entity and you were deploying your applications (ie WARs and EARs) on it. Now, your application is the top-level entity and you are in control of the WildFly runtime.&lt;/p&gt; &lt;p&gt;With that new paradigm, the steps to use WildFly on the cloud are now:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;In your code repository, configure WildFly runtime (using a Maven plugin)&lt;/li&gt; &lt;li&gt;Use Maven to build your application&lt;/li&gt; &lt;li&gt;Deploy your application in your target container platform&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Step (2) is the key as it automates and centralizes most of the &quot;plumbing&quot; that was previously achieved by hand.&lt;/p&gt; &lt;p&gt;If we decompose this step, it actually achieves the following:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Compile your code and generate the deployment&lt;/li&gt; &lt;li&gt;&quot;Provision&quot; WildFly to download it, change its configuration to match the application requirements&lt;/li&gt; &lt;li&gt;deploy your deployment in the provisioned WildFly server&lt;/li&gt; &lt;li&gt;Run integration tests against the &lt;em&gt;actual&lt;/em&gt; runtime (WildFly + your deployments) that will be used in production&lt;/li&gt; &lt;li&gt;Optionally create a container image using &lt;code&gt;docker&lt;/code&gt;&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Comparing the two ways to develop and run WildFly can look deceiving. However, a closer examination shows that the &quot;Cloudy&quot; way unlocks many improvements in terms of productivity, automation, testing and, at least in my opinion, &lt;em&gt;developer joy&lt;/em&gt;.&lt;/p&gt; &lt;h2&gt;What does WildFly provide for 12-Factor App development?&lt;/h2&gt; &lt;p&gt;The key difference is that &lt;em&gt;your&lt;/em&gt; Maven project (and its &lt;code&gt;pom.xml&lt;/code&gt;) is the single &lt;a href=&quot;https://12factor.net/codebase&quot;&gt;12-factor&#39;s Codebase&lt;/a&gt; to track your application. Everything (your application dependencies, WildFly version and configuration changes) is tracked in this repo. You are sure that what is built from this repository will always be consistent. You are also sure that WildFly configuration is up to date with production server because &lt;em&gt;your&lt;/em&gt; project is &lt;em&gt;where&lt;/em&gt; its configuration is updated. You are not at risk of deploying your WAR in a different version of the server or a server that has not been properly configured for your application.&lt;/p&gt; &lt;p&gt;Using the &lt;a href=&quot;https://github.com/wildfly/wildfly-maven-plugin&quot;&gt;WildFly Maven Plugin&lt;/a&gt; to provision WildFly ensures that all your &lt;a href=&quot;https://12factor.net/dependencies&quot;&gt;12-factor&#39;s Dependencies&lt;/a&gt; are explicitly declared. Wheneve a new version of WildFly is released, you can be notified with something like Dependabot and automatically test your application with this new release.&lt;/p&gt; &lt;p&gt;We have enhanced WildFly configuration capabilities so that you can store your &lt;a href=&quot;https://12factor.net/config&quot;&gt;12-factor&#39;s Config&lt;/a&gt; in your environment. WildFly can now use &lt;a href=&quot;https://docs.wildfly.org/29/Admin_Guide.html#overridden-attribute-value&quot;&gt;environment variables to change any of its management attributes&lt;/a&gt; or &lt;a href=&quot;https://docs.wildfly.org/29/Admin_Guide.html#Expression_Resolution&quot;&gt;resolve their expressions&lt;/a&gt;. Eclipse MicroProfile Config is also available to store any of your application config in the environment.&lt;/p&gt; &lt;p&gt;Connecting to &lt;a href=&quot;https://12factor.net/backing-services&quot;&gt;12-factor&#39;s Backing Services&lt;/a&gt; is straightforward and WildFly is able to connect to a database with a few env vars representing its URL and credentials with the &lt;a href=&quot;https://github.com/wildfly-extras/wildfly-datasources-galleon-pack&quot;&gt;datasources feature pack&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Using the &lt;a href=&quot;https://github.com/wildfly/wildfly-maven-plugin&quot;&gt;WildFly Maven Plugin&lt;/a&gt; in your &lt;code&gt;pom.xml&lt;/code&gt;, you can simply have different stages to &lt;a href=&quot;https://12factor.net/build-release-run&quot;&gt;12-factor&#39;s Build, release, run&lt;/a&gt; and make sure you build once your release artifact (the application image) and runs it on your container platform as needed.&lt;/p&gt; &lt;p&gt;Entreprise Java application as traditionally stateful so it does not adhere to the &lt;a href=&quot;https://12factor.net/processes&quot;&gt;12-factor&#39;s Processes&lt;/a&gt; unless you refactor your Java application to make it stateless.&lt;/p&gt; &lt;p&gt;WildFly complies with &lt;a href=&quot;https://12factor.net/port-binding&quot;&gt;12-factor&#39;s Port binding&lt;/a&gt; and you can rely on accessing its HTTP port on &lt;code&gt;8080&lt;/code&gt; and its management interfance on &lt;code&gt;9990&lt;/code&gt;.&lt;/p&gt; &lt;p&gt;Scaling out your application to handle &lt;a href=&quot;https://12factor.net/concurrency&quot;&gt;12-factor&#39;s concurrency&lt;/a&gt; via the process model is depending on your application architecture. However WildFly can be provisioned in such a way that its runtime can exactly fit your application requirements and &quot;trim&quot; any capabilites that is not needed. You can also split a monolith Entreprise Java application in multiple applications to scale the parts that need it.&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://12factor.net/disposability&quot;&gt;12-factor&#39;s Disposability&lt;/a&gt; is achieved by having WildFly fast booting time as well as graceful shutdown capabilities to let applications finish their tasks before shutting down.&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://12factor.net/dev-prod-parity&quot;&gt;12-factor&#39;s Dev/prod parity&lt;/a&gt; is enabled when we are able to use continuous deployment and having a single codebase to keep the gap between what we develop and what we operate. Using WildFly with container-based testing tool (such as &lt;a href=&quot;https://testcontainers.com&quot;&gt;Testcontainers&lt;/a&gt;) ensures that what we test is very similar (if not identical) to what is operated.&lt;/p&gt; &lt;p&gt;WildFly has extensive logging capabilities (for its own runtime as well as your application code) and works out of the bow with &lt;a href=&quot;https://12factor.net/logs&quot;&gt;12-factor&#39;s Logs&lt;/a&gt; by outputting its content on the standard output. For advanced use cases, you can change its output to use a JSON formatter to query and monitor its logs.&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://12factor.net/admin-processes&quot;&gt;12-factor&#39;s Admin processes&lt;/a&gt; has been there from the start with WildFly that provides a extensive CLI tool to run management operations on a server (running or not). The same management operations can be executed when WildFly is provisioned by the WildFly Maven Plugin to adapt its configuration to your application.&lt;/p&gt; &lt;h2&gt;Summary&lt;/h2&gt; &lt;p&gt;We can develop and operate Entrprise Java applications with a modern software methodology. Some of these principles resonate more if you targeting cloud environment but most of them are still beneficical for traditional &quot;bare metal&quot; deployments.&lt;/p&gt; &lt;p&gt;&lt;i style=&quot;color: green;&quot; class=&quot;fa fa-solid fa-check&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/codebase&quot;&gt;I. Codebase&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Use the &lt;a href=&quot;https://github.com/wildfly/wildfly-maven-plugin&quot;&gt;WildFly Maven Plugin&lt;/a&gt; to store WildFly information with your application code.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i style=&quot;color: green;&quot; class=&quot;fa fa-solid fa-check&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/dependencies&quot;&gt;II. Dependencies&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;All dependencies (including WildFly) are managed by your application &lt;code&gt;pom.xml&lt;/code&gt;.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i style=&quot;color: green;&quot; class=&quot;fa fa-solid fa-check&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/config&quot;&gt;III. Config&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Use Eclipse MicroProfile Config and WildFly capabilities to read configuration from the environment.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i style=&quot;color: green;&quot; class=&quot;fa fa-solid fa-check&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/backing-services&quot;&gt;IV. Backing Services&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Jakarta EE is designed on this principle (eg JDBC, JMS, JCA, etc.).&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i style=&quot;color: green;&quot; class=&quot;fa fa-solid fa-check&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/build-release-run&quot;&gt;V. Build, release, run&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;With a single &lt;code&gt;mvn package&lt;/code&gt;, you can build your release artifact and deploy it wherever you want. The WildFly Maven Plugin can generate ate a directory or an application image to suit either bare-metal or container-based platform.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i class=&quot;fa fa-solid fa-question&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/processes&quot;&gt;VI. Processes&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;WildFly can run stateless application but you will have to design them this way :)&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i style=&quot;color: green;&quot; class=&quot;fa fa-solid fa-check&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/port-binding&quot;&gt;VII. Port Binding&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;code&gt;8080&lt;/code&gt; for the application, &lt;code&gt;9990&lt;/code&gt; for the management interface :)&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i class=&quot;fa fa-solid fa-question&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/concurrency&quot;&gt;VIII. Concurrency&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Entreprise Java application have traditionally be scaling up so there is some architecture and application changes to make them scale out instead. The lightweight runtime from WildFly is definitely a good opportunity for scaling out Entreprise Java applications.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i style=&quot;color: green;&quot; class=&quot;fa fa-solid fa-check&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/disposability&quot;&gt;IX. Disposability&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;WildFly boots fast and gracefully shuts down.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i style=&quot;color: green;&quot; class=&quot;fa fa-solid fa-check&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/dev-prod-parity&quot;&gt;X. Dev/prod parity&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Use the WildFly Maven Plugin to control WildFly, container-based testing to reduce the integration disparity and keep changes between dev, staging and production to a minimum.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i style=&quot;color: green;&quot; class=&quot;fa fa-solid fa-check&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://12factor.net/logs&quot;&gt;XI. Logs&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;WildFly outputs everything on the standard output. Optionally, you can use a JSON formatter to query and monitor your application logs.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;&lt;i style=&quot;color: green;&quot; class=&quot;fa fa-solid fa-check&quot;&gt;&lt;/i&gt;&lt;a href=&quot;https://12factor.net/admin-processes&quot;&gt;XII. Admin processes&lt;/a&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;WildFly tooling provides CLI scripts to run management operations. You can store them in your codebase to handle configuration changes, migration operations, maintenance operations.&lt;/li&gt; &lt;/ul&gt; &lt;h2&gt;Conclusion&lt;/h2&gt; &lt;p&gt;Using the &quot;cloudy&quot; way to develop and operate entreprise applications unlocks many benefits regardless of the deployment platform (container-based or bare metal).&lt;/p&gt; &lt;p&gt;It can automate most of the mundane tasks that reduce &lt;em&gt;developer joy &amp;amp; efficiency&lt;/em&gt; while improving the running operations of WildFly improving &lt;em&gt;operator joy &amp;amp; efficiency&lt;/em&gt;.&lt;/p&gt; </content> </entry> <entry> <title type="html">TLS certificate on jmesnil.net</title> <link href="http://jmesnil.net/weblog/2023/09/13/tls-certificate-on-jmesnil/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2023/09/13/tls-certificate-on-jmesnil/</id> <updated>2023-09-13T06:29:02+00:00</updated> <published>2023-09-13T06:29:02+00:00</published> <content type="html"> &lt;p&gt;Web browers now treats sites served by HTTP as &quot;Not secure&quot;. I finally caved in and added a TLS certificate to &lt;a href=&quot;https://jmesnil.net&quot;&gt;jmesnil.net&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;&lt;figure class=&quot;portrait&quot;&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2023-09-13-padlock-displayed.jpg&quot; alt=&quot;Displayed Padlock achievement: completed&quot;&gt; &lt;figcaption&gt;Displayed Padlock achievement: completed &lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;If you are visiting &lt;a href=&quot;https://jmesnil.net&quot;&gt;jmesnil.net&lt;/a&gt;, you can now browse it safely and be sure that your credit cards numbers will not be stolen. That&#39;s progress I suppose...&lt;/p&gt; &lt;p&gt;I host my site on Amazon AWS and use a bunch of their services (S3, Route 53, CloudFront, Certificate Manager) to be able to redirect the HTTP traffic to HTTPS (and the &lt;code&gt;www.jmesnil.net&lt;/code&gt; URLs to &lt;code&gt;jmesnil.net&lt;/code&gt;). I will see how much this increase the AWS bill...&lt;/p&gt; &lt;p&gt;More interestingly, I used &lt;a href=&quot;https://letsencrypt.org&quot;&gt;Let&#39;s Encrypt&lt;/a&gt; to generate the certificates. It took me less than 5 minutes to generate it (including the acme challenge to verify the ownership of the &lt;code&gt;jmesnil.net&lt;/code&gt; domain name). This project is a great example of simplifying and making accessible a complex technology to web publishers.&lt;/p&gt; </content> </entry> <entry> <title type="html">Health Update</title> <link href="http://jmesnil.net/weblog/2023/07/03/health-update/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2023/07/03/health-update/</id> <updated>2023-07-03T12:26:37+00:00</updated> <published>2023-07-03T12:26:37+00:00</published> <content type="html"> &lt;p&gt;On October 17th of last year, while playing basketball, I suffered a ruptured Achilles tendon.&lt;/p&gt; &lt;p&gt;Unfortunately, an initial misdiagnosis and a lengthy waitlist for necessary medical examinations resulted in me having to postpone surgery until December 9th. The tendon rupture measured approximately 6cm, necessitating the use of tissue from adjacent areas of my feet to construct a completely new tendon.&lt;/p&gt; &lt;p&gt;This led to a period of immobilization lasting 45 days. Although the Christmas break was not particularly enjoyable, I consider myself fortunate to have an incredible wife and children who provided unwavering support, showering me with love and kindness throughout the ordeal. My managers and colleagues at Red Hat were also very supportive so that I could focus on my health during that period.&lt;/p&gt; &lt;p&gt;When my boot was finally removed, I caught sight of my foot for the first time, revealing a 15cm scar that I could proudly boast about if I were on the &quot;Jaws&quot; boat :)&lt;/p&gt; &lt;p&gt;&lt;figure class=&quot;portrait&quot;&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2023-07-04-health-update.jpeg&quot; alt=&quot;Scar of my Achilles tendon&quot;&gt; &lt;figcaption&gt;Scar of my Achilles tendon &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff Mesnil&lt;/span&gt; &lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;By the end of January, I cautiously began walking again, albeit with a noticeable limp. Since then, my rehabilitation has been a gradual journey with its fair share of ups and downs. Yesterday, I was able to run 5 km, but today climbing stairs causes discomfort. I am hopeful that I will achieve a full recovery. As a symbolic &quot;endpoint&quot; to my rehab, I have set a goal to participate in a semi-marathon next year.&lt;/p&gt; &lt;p&gt;Although my competitive basketball days are over, I am still enthusiastic about playing with my kids and continuing to enjoy the sport. I&#39;ll play it less and watch it more :) Walking, running, and hiking at my own pace have become my main physical activities, whether I&#39;m by myself or accompanied by friends and family. They provide me energy, focus and a deep appreciation of a functional body.&lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; DPReview.com to close</title> <link href="https://www.dpreview.com/news/5901145460/dpreview-com-to-close" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2023/03/22/dpreviewcom-to-close/</id> <updated>2023-03-22T10:09:34+00:00</updated> <published>2023-03-22T10:09:34+00:00</published> <content type="html"> &lt;p&gt;Over the years, &lt;a href=&quot;https://www.dpreview.com/&quot;&gt;DPReview&lt;/a&gt; has been an invaluable help when I was searching for camera gears.&lt;/p&gt; &lt;p&gt;I seldom browse it now as I am mostly using my phone to take pictures but I am still subscribed to their newsfeed.&lt;/p&gt; &lt;p&gt;If I were to look for a replacement for my aging camera, I&#39;m not sure which site would provide the same quality of technical reviews...&lt;/p&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2023/03/22/dpreviewcom-to-close/&quot; title=&quot;Permanent link to DPReview.com to close&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; Writing Greener Java Applications</title> <link href="https://hollycummins.com/writing-greener-java-applications-jchampions/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2023/03/01/writing-greener-java-applications/</id> <updated>2023-03-01T09:23:45+00:00</updated> <published>2023-03-01T09:23:45+00:00</published> <content type="html"> &lt;p&gt;&lt;a href=&quot;https://hollycummins.com&quot;&gt;Holly Cummins&lt;/a&gt;, a colleague at Red Hat and Java Champion, is making a lot of great content about making software greener.&lt;/p&gt; &lt;p&gt;Her presentation focuses on &lt;a href=&quot;https://quarkus.io&quot;&gt;Quarkus&lt;/a&gt; which is a &lt;em&gt;greenfield&lt;/em&gt;&amp;nbsp;&lt;a id=&quot;fnr1-2023-03-01&quot; href=&quot;#fn1-2023-03-01&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; Java framework focused on Cloud-native applications while my job is on &lt;a href=&quot;https://www.wildfly.org&quot;&gt;WildFly&lt;/a&gt; and &lt;a href=&quot;https://www.redhat.com/fr/technologies/jboss-middleware/application-platform&quot;&gt;JBoss EAP&lt;/a&gt;, Java application servers that predate the Cloud.&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://hollycummins.com/writing-greener-java-applications-jchampions/&quot;&gt;Her presentation&lt;/a&gt; resonates with me professionally and personally.&lt;/p&gt; &lt;p&gt;Professionally, my focus these days is on making WildFly and EAP run great on the Cloud. Doing so in a sustainable manner is important as it has direct impact on our users&#39; costs and performance.&lt;/p&gt; &lt;p&gt;Personally, and more importantly, it resonates with my vision of my work and my life. All my career has been done around Open Source projects. They fit my idea of a good humane society with core values of Openness, Meritocracy and Accountability. Developping &lt;strong&gt;Open Source&lt;/strong&gt; code is now a given for me and I don&#39;t envision other ways to perform my job.&lt;/p&gt; &lt;p&gt;The next frontier is now to develop &lt;strong&gt;Sustainable&lt;/strong&gt; code that reduces our impact on the planet. I deeply believe now that any advancements we are making, whether it&#39;s the Cloud, Cryptocurrency, Machine-Learning, can not be at the expense at the planet and our future generations.&lt;/p&gt; &lt;p&gt;It&#39;s not simple to see how that translates in my daily tasks but we are past the point where we should include sustainability into our guiding principles and I&#39;m making a deliberate conscious choice to do that now at my own level.&lt;/p&gt; &lt;hr /&gt; &lt;ol&gt; &lt;li&gt;&lt;a id=&quot;fn1-2023-03-01&quot;&gt;&lt;/a&gt;Pun intended&amp;nbsp;&lt;a href=&quot;#fnr1-2023-03-01&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2023/03/01/writing-greener-java-applications/&quot; title=&quot;Permanent link to Writing Greener Java Applications&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> <entry> <title type="html">Storm Over Lake</title> <link href="http://jmesnil.net/weblog/2017/07/31/storm-over-lake/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2017/07/31/storm-over-lake/</id> <updated>2017-07-31T15:09:50+00:00</updated> <published>2017-07-31T15:09:50+00:00</published> <content type="html"> &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2017-07-30-storm-over-lake-900w.jpg, https://media.jmesnil.net/images/2017-07-30-storm-over-lake-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2017-07-30-storm-over-lake-480w.jpg, https://media.jmesnil.net/images/2017-07-30-storm-over-lake-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2017-07-30-storm-over-lake-480w.jpg, https://media.jmesnil.net/images/2017-07-30-storm-over-lake-960w.jpg 2x&quot; alt=&quot;Storm Over Lake&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2017-07-30-storm-over-lake-480w.jpg&quot; alt=&quot;Storm Over Lake&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt; &lt;figcaption&gt;&lt;a href=&quot;https://goo.gl/maps/ncubK26Ua1B2&quot;&gt;&lt;i class=&quot;fa fa-map-marker&quot;&gt;&lt;/i&gt;&lt;/a&gt;&amp;nbsp;Storm Over Lake &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-T2 &lt;span class=&quot;speed&quot;&gt;1/170&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;200&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;55&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;Yesterday, we made a 3-hour cruise on the &lt;em&gt;Lac du Bourget&lt;/em&gt; and the storm was coming right before we left the boat.&lt;/p&gt; </content> </entry> <entry> <title type="html">Eclipse MicroProfile Config 1.0 and WildFly implementation</title> <link href="http://jmesnil.net/weblog/2017/07/27/eclipse-microprofile-config-10/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2017/07/27/eclipse-microprofile-config-10/</id> <updated>2017-07-27T14:10:47+00:00</updated> <published>2017-07-27T14:10:47+00:00</published> <content type="html"> &lt;p&gt;&lt;a href=&quot;https://github.com/eclipse/microprofile-config/&quot;&gt;Eclipse MicroProfile Config 1.0&lt;/a&gt; has been released.&lt;/p&gt; &lt;p&gt;It is quite a milestone as it is the first specification released by the &lt;a href=&quot;https://microprofile.io&quot;&gt;Eclipse MicroProfile project&lt;/a&gt;. It covers a simple need: unify the configuration of Java application from various sources with a simple API:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;java&quot;&gt;@Inject&amp;#x000A;@ConfigProperty(name = &quot;app.timeout&quot;, defaultValue = &quot;5000&quot;)&amp;#x000A;long timeout;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The developer no longer needs to check for configuration files, System properties, etc. He or she just specifies the name of the configuration property (and an optional default value). The Eclipse MicroProfile Config specification ensures that several sources will be queried in a consistent order to find the most relevant value for the property.&lt;/p&gt; &lt;p&gt;With Eclipse MicroProfile Config 1.0 API available, I have released &lt;a href=&quot;https://github.com/wildfly-extras/wildfly-microprofile-config&quot;&gt;wildfly-microprofile-config 1.0.1&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;This project contains an &lt;a href=&quot;https://github.com/wildfly-extras/wildfly-microprofile-config/tree/master/implementation&quot;&gt;implementation of the specification&lt;/a&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;org.wildfly&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;wildfly-microprofile-config&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;version&amp;gt;1.0.1&amp;lt;/version&amp;gt;&amp;#x000A;&amp;lt;/dependency&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;This implementation passes the MicroProfile Config 1.0 TCK. It can be used by any CDI-aware container/server (i.e. that are able to load CDI extensions).&lt;/p&gt; &lt;p&gt;This project also contains a &lt;a href=&quot;http://wildfly.org&quot;&gt;WildFly&lt;/a&gt; extension so that any application deployed in WildFly can use the MicroProfile Config API. The &lt;code&gt;microprofile-config&lt;/code&gt; subsystem can be used to configure various config sources such as directory-based for OpenShift/Kubernetes config maps (as described in a &lt;a href=&quot;http://localhost:4242/weblog/2017/06/16/eclipse-microprofile-config-in-openshift/&quot;&gt;previous post&lt;/a&gt;) or the properties can be stored in the &lt;code&gt;microprofile-config&lt;/code&gt; subsystem itself):&lt;/p&gt; &lt;pre&gt;&lt;code&gt;&amp;lt;subsystem xmlns=&quot;urn:wildfly:microprofile-config:1.0&quot;&amp;gt;&amp;#x000A; &amp;lt;config-source name=&quot;appConfigSource&quot;&amp;gt;&amp;#x000A; &amp;lt;property name=&quot;app.timeout&quot; value=&quot;2500&quot; /&amp;gt;&amp;#x000A; &amp;lt;/config-source&amp;gt;&amp;#x000A; &amp;lt;config-source name=&quot;configSourceFromDir&quot; dir=&quot;/etc/config/numbers-app&quot; /&amp;gt;&amp;#x000A;&amp;lt;/subsystem&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;Finally, a Fraction is available for &lt;a href=&quot;http://wildfly-swarm.io&quot;&gt;WildFly Swarm&lt;/a&gt; so that any Swarm application can use the Config API as long as it depends on the appropriate Maven artifact:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;org.wildfly.swarm&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;microprofile-config&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;version&amp;gt;1.0.1&amp;lt;/version&amp;gt;&amp;#x000A;&amp;lt;/dependency&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;It is planned that this &lt;code&gt;org.wildfly.swarm:microprofile-config&lt;/code&gt; Fraction will eventually move to Swarm own Git repository so that it Swarm will be able to autodetect applications using the Config API and load the dependency automatically. But, for the time being, the dependency must be added explicitely.&lt;/p&gt; &lt;p&gt;If you have any issues or enhancements you want to propose for the WildFly MicroProfile Config implementation, do not hesitate to &lt;a href=&quot;https://github.com/wildfly-extras/wildfly-microprofile-config/issues&quot;&gt;open issues&lt;/a&gt; or &lt;a href=&quot;https://github.com/wildfly-extras/wildfly-microprofile-config/pulls&quot;&gt;propose contributions&lt;/a&gt; for it.&lt;/p&gt; </content> </entry> <entry> <title type="html">A Look At Eclipse MicroProfile Healthcheck</title> <link href="http://jmesnil.net/weblog/2017/07/07/a-look-at-eclipse-microprofile-health/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2017/07/07/a-look-at-eclipse-microprofile-health/</id> <updated>2017-07-07T12:44:18+00:00</updated> <published>2017-07-07T12:44:18+00:00</published> <content type="html"> &lt;p&gt;I recently looked at the &lt;a href=&quot;https://github.com/eclipse/microprofile-health&quot;&gt;Eclipse MicroProfile Healthcheck API&lt;/a&gt; to investigate its support in &lt;a href=&quot;http://wildfly.org&quot;&gt;WildFly&lt;/a&gt;.&lt;br/&gt; &lt;a href=&quot;http://wildfly-swarm.io&quot;&gt;WildFly Swarm&lt;/a&gt; is providing the sample implementation so I am very interested to make sure that WildFly and Swarm can both benefit from this specification.&lt;/p&gt; &lt;p&gt;This specification and its API are currently designed and anything written in this post will likely be obsolete when the final version is release. But without further ado...&lt;/p&gt; &lt;h2&gt;Eclipse MicroProfile Healthcheck&lt;/h2&gt; &lt;p&gt;The Eclipse MicroProfile Healthcheck is a &lt;a href=&quot;https://github.com/eclipse/microprofile-evolution-process/blob/master/proposals/0003-health-checks.md&quot;&gt;specification&lt;/a&gt; to determine the healthiness of an application. It defines a &lt;code&gt;HealthCheckProcedure&lt;/code&gt; interface that can be implemented by an application developer. It contains a single method that returns a &lt;code&gt;HealthStatus&lt;/code&gt;: either &lt;code&gt;UP&lt;/code&gt; or &lt;code&gt;DOWN&lt;/code&gt; (plus some optional metadata relevant to the health check). Typically, an application would provide one or more health check procedures to check healthiness of its parts. The overall healthiness of the application is then determined by the aggregation of all the procedures provided by the application. If any procedure is &lt;code&gt;DOWN&lt;/code&gt;, the overall outcome is &lt;code&gt;DOWN&lt;/code&gt;. Else the application is considered as &lt;code&gt;UP&lt;/code&gt;.&lt;/p&gt; &lt;p&gt;The specification has a &lt;a href=&quot;https://github.com/eclipse/microprofile-evolution-process/blob/master/proposals/0003-spec.md&quot;&gt;companion document&lt;/a&gt; that specifies an HTTP endpoint and JSON format to check the healthiness of an application.&lt;/p&gt; &lt;p&gt;Using the HTTP endpoint, a container can ask the application whether it is healthy. If it is not healthy, the container can take actions to deal with it. It can decide to stop the application and eventually respin a new instance. The canonical example is Kubernetes that can configure a &lt;a href=&quot;https://kubernetes.io/v1.0/docs/user-guide/walkthrough/k8s201.html#health-checking&quot;&gt;liveness probe&lt;/a&gt; to check this HTTP health URL (&lt;a href=&quot;https://docs.openshift.com/enterprise/3.0/dev_guide/application_health.html&quot;&gt;OpenShift&lt;/a&gt; also exposes this liveness probe).&lt;/p&gt; &lt;h2&gt;WildFly Extension prototype&lt;/h2&gt; &lt;p&gt;I have written a prototype of a WildFly extension to support health checks for applications deployed in WildFly &lt;em&gt;and&lt;/em&gt; some provided directly by WildFly:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;https://github.com/jmesnil/wildfly-microprofile-health&quot;&gt;https://github.com/jmesnil/wildfly-microprofile-health&lt;/a&gt;&lt;/p&gt; &lt;p&gt;The &lt;code&gt;microprofile-health&lt;/code&gt; subsystem supports an operation to check the health of the app server:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;[standalone at localhost:9990 /] /subsystem=microprofile-health:check&amp;#x000A;{&amp;#x000A; &quot;outcome&quot; =&amp;gt; &quot;success&quot;,&amp;#x000A; &quot;result&quot; =&amp;gt; {&amp;#x000A; &quot;checks&quot; =&amp;gt; [{&amp;#x000A; &quot;id&quot; =&amp;gt; &quot;heap-memory&quot;,&amp;#x000A; &quot;result&quot; =&amp;gt; &quot;UP&quot;,&amp;#x000A; &quot;data&quot; =&amp;gt; {&amp;#x000A; &quot;max&quot; =&amp;gt; &quot;477626368&quot;,&amp;#x000A; &quot;used&quot; =&amp;gt; &quot;156216336&quot;&amp;#x000A; }&amp;#x000A; }],&amp;#x000A; &quot;outcome&quot; =&amp;gt; &quot;UP&quot;&amp;#x000A; }&amp;#x000A;}&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;It also exposes an (unauthenticated) HTTP endpoint: &lt;a href=&quot;http://localhost:8080/health/&quot;&gt;http://localhost:8080/health/&lt;/a&gt;&lt;/p&gt; &lt;pre&gt;&lt;code&gt;$ curl http://localhost:8080/health/&amp;#x000A;{&amp;#x000A; &quot;checks&quot;:[&amp;#x000A; {&amp;#x000A; &quot;id&quot;:&quot;heap-memory&quot;,&amp;#x000A; &quot;result&quot;:&quot;UP&quot;,&amp;#x000A; &quot;data&quot;:{&amp;#x000A; &quot;max&quot;:&quot;477626368&quot;,&amp;#x000A; &quot;used&quot;:&quot;160137128&quot;&amp;#x000A; }&amp;#x000A; }&amp;#x000A; ],&amp;#x000A; &quot;outcome&quot;:&quot;UP&quot;&amp;#x000A;}&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;This HTTP endpoint can be used to configure OpenShift/Kubernetes liveness probe.&lt;/p&gt; &lt;p&gt;Any deployment that defines Health Check Procedures will have them registered to determine the overall healthiness of the process. The prototype has a simple example of a Web app that adds a health check procedure that randomly returns &lt;code&gt;DOWN&lt;/code&gt; (which is not very useful ;).&lt;/p&gt; &lt;h3&gt;WildFly Health Check Procedures&lt;/h3&gt; &lt;p&gt;The Healthcheck specification mainly targets user applications that can apply application logic to determine their healthiness. However I wonder if we could reuse the concepts &lt;em&gt;inside&lt;/em&gt; the application server (WildFly in my case). There are &quot;things&quot; that we could check to determine if the server runtime is healthy, e.g.:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;The amount of heap memory is close to the max&lt;/li&gt; &lt;li&gt;some deployments have failed&lt;/li&gt; &lt;li&gt;Excessive GC&lt;/li&gt; &lt;li&gt;Running out of disk space&lt;/li&gt; &lt;li&gt;Some threads are deadlocked&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;These procedures are relevant regardless of the type of applications deployed on the server.&lt;/p&gt; &lt;p&gt;Subsystems inside WildFly could provide Health check procedures that would be queried to check the overall healthiness. We could for example provide a health check that the used heap memory is less that 90% of the max:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;java&quot;&gt;HealthCheck.install(context, &quot;heap-memory&quot;, () -&amp;gt; {&amp;#x000A; MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();&amp;#x000A; long memUsed = memoryBean.getHeapMemoryUsage().getUsed();&amp;#x000A; long memMax = memoryBean.getHeapMemoryUsage().getMax();&amp;#x000A; HealthResponse response = HealthResponse.named(&quot;heap-memory&quot;)&amp;#x000A; .withAttribute(&quot;used&quot;, memUsed)&amp;#x000A; .withAttribute(&quot;max&quot;, memMax);&amp;#x000A; // status is is down is used memory is greater than 90% of max memory.&amp;#x000A; HealthStatus status = (memUsed &amp;lt; memMax * 0.9) ? response.up() : response.down();&amp;#x000A; return status;&amp;#x000A;});&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;Summary&lt;/h2&gt; &lt;p&gt;To better integrate WildFly with Cloud containers such as OpenShift (or Docker/Kunernetes), it should provide a way to let the container checks the healthiness of WildFly. The Healthcheck specification is a good candidate to provide such feature. It is worth exploring how we could leverage it for user deployments and also for WildFly internals (when that makes sense).&lt;/p&gt; </content> </entry> <entry> <title type="html">Eclipse MicroProfile Config in OpenShift</title> <link href="http://jmesnil.net/weblog/2017/06/16/eclipse-microprofile-config-in-openshift/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2017/06/16/eclipse-microprofile-config-in-openshift/</id> <updated>2017-06-16T14:51:29+00:00</updated> <published>2017-06-16T14:51:29+00:00</published> <content type="html"> &lt;p&gt;This is another post that covers some work I have been doing around the &lt;a href=&quot;https://github.com/eclipse/microprofile-config/&quot;&gt;Eclipse MicroProfile Config&lt;/a&gt; as a part of my job working on &lt;a href=&quot;https://wildlfy.org/&quot;&gt;WildFly&lt;/a&gt; and &lt;a href=&quot;http://wildfly-swarm.io/&quot;&gt;Swarm&lt;/a&gt; (first post is &lt;a href=&quot;/weblog/2017/04/25/eclipse-microprofile-config-part-i/&quot;&gt;here&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;This post is about some updates of the project status and work being done to leverage the Config API in &lt;a href=&quot;https://docs.openshift.org/latest/welcome/index.html&quot;&gt;OpenShift&lt;/a&gt; (or other &lt;a href=&quot;https://www.docker.com&quot;&gt;Docker&lt;/a&gt;/&lt;a href=&quot;https://kubernetes.io&quot;&gt;Kubernetes&lt;/a&gt;-based environment).&lt;/p&gt; &lt;h2&gt;Project update&lt;/h2&gt; &lt;p&gt;Since last post, WildFly and Swarm projects agreed to host the initial work I did in their GitHub projects and the Maven coordinates have been changed to reflect this. For the time being, everything is hosted at &lt;a href=&quot;https://github.com/wildfly-extras/wildfly-microprofile-config&quot;&gt;wildfly-extras/wildfly-microprofile-config&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;The Eclipse MicroProfile Config 1.0 API should be released soon. Once it is released, we can then release the 1.0 version of the WildFly implementation and subsystem. The Swarm fraction will be moved to the Swarm own Git repo and will be available with future Swarm releases.&lt;/p&gt; &lt;p&gt;Until the Eclipse MicroProfile Config 1.0 API is released, you still have to build everything from &lt;a href=&quot;https://github.com/wildfly-extras/wildfly-microprofile-config&quot;&gt;wildfly-extras/wildfly-microprofile-config&lt;/a&gt; and uses the Maven coordinates:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;org.wildfly.swarm&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;microprofile-config&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;&amp;#x000A;&amp;lt;/dependency&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;Directory-based Config Source&lt;/h2&gt; &lt;p&gt;We have added a new type of &lt;code&gt;ConfigSource&lt;/code&gt;, &lt;a href=&quot;https://github.com/wildfly-extras/wildfly-microprofile-config/blob/master/implementation/src/main/java/org/wildfly/microprofile/config/DirConfigSource.java&quot;&gt;DirConfigSource&lt;/a&gt;, that takes a &lt;code&gt;File&lt;/code&gt; as a parameter.&lt;/p&gt; &lt;p&gt;When this ConfigSource is created, it scans the file (if that is a directory) and creates a property for each file in the directory. The key of the property is the name of the file and its value is the content of the file.&lt;/p&gt; &lt;p&gt;For example, if you create a directory named &lt;code&gt;/etc/config/numbers-app&lt;/code&gt; and add a file in it named &lt;code&gt;num.size&lt;/code&gt; with its content being &lt;code&gt;5&lt;/code&gt;, it can be used to configure the following property:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;@Inject&amp;#x000A;@ConfigProperty(name = &quot;num.size&quot;)&amp;#x000A;int numSize;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;There are different ways to use the corresponding &lt;code&gt;DirConfigSource&lt;/code&gt; depending on the type of applications.&lt;/p&gt; &lt;h3&gt;WildFly Application&lt;/h3&gt; &lt;p&gt;If you are deploying your application in WildFly, you can add this config source to the &lt;code&gt;microprofile&lt;/code&gt; subsystem:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;&amp;lt;subsystem xmlns=&quot;urn:wildfly:microprofile-config:1.0&quot;&amp;gt;&amp;#x000A; ...&amp;#x000A; &amp;lt;config-source name=&quot;numbers-config-source&quot; dir=&quot;/etc/config/numbers-app&quot; /&amp;gt;&amp;#x000A;&amp;lt;/subsystem&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;Swarm Application&lt;/h3&gt; &lt;p&gt;If you are using Swarm, you can add it to the &lt;code&gt;MicroProfileFraction&lt;/code&gt; from your &lt;code&gt;main&lt;/code&gt; method:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;java&quot;&gt;swarm.fraction(new MicroProfileConfigFraction()&amp;#x000A; .configSource(&quot;numbers-config-source&quot;, (cs) -&amp;gt; {&amp;#x000A; cs.ordinal(600)&amp;#x000A; .dir(&quot;/etc/config/numbers-app/&quot;);&amp;#x000A;}));&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;h3&gt;Plain Java Application&lt;/h3&gt; &lt;p&gt;If you are using the WildFly implementation of the Config API outside of WildFly or Swarm, you can add it to a custom-made &lt;code&gt;Config&lt;/code&gt; using the Eclipse MicroProfile &lt;code&gt;ConfigBuilder&lt;/code&gt; API.&lt;/p&gt; &lt;h2&gt;OpenShift/Kubernetes Config Maps&lt;/h2&gt; &lt;p&gt;What is the use case for this new type of &lt;code&gt;ConfigSource&lt;/code&gt;?&lt;/p&gt; &lt;p&gt;It maps to the concept of &lt;strong&gt;&lt;a href=&quot;https://docs.openshift.org/latest/dev_guide/configmaps.html&quot;&gt;OpenShift/Kubernetes Config Maps&lt;/a&gt;&lt;/strong&gt; so that an application that uses the Eclipse MicroProfile Config API can be deployed in a container and used its config maps as a source of its configuration.&lt;/p&gt; &lt;p&gt;I have added an &lt;a href=&quot;https://github.com/wildfly-extras/wildfly-microprofile-config/tree/master/examples/openshift&quot;&gt;OpenShift example&lt;/a&gt; that shows a simple Java application running in a variety of deployment and configuration use cases.&lt;/p&gt; &lt;p&gt;The application uses two properties to configure its behaviour. The application returns a list of random positive integers (the number of generated integers is controlled by the &lt;code&gt;num.size&lt;/code&gt;property and their maximum value by the &lt;code&gt;num.max&lt;/code&gt; property):&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;java&quot;&gt;@Inject&amp;#x000A;@ConfigProperty(name = &quot;num.size&quot;, defaultValue = &quot;3&quot;)&amp;#x000A;int numSize;&amp;#x000A;&amp;#x000A;@Inject&amp;#x000A;@ConfigProperty(name = &quot;num.max&quot;, defaultValue = &quot;&quot; + Integer.MAX_VALUE)&amp;#x000A;int numMax;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The application can be run as a &lt;strong&gt;standalone Java application&lt;/strong&gt; configured with &lt;strong&gt;System Properties&lt;/strong&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;$ java -Dnum.size=5 -Dnum.max=10 -jar numbers-app-swarm.jar&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;It can also be run in &lt;strong&gt;Docker&lt;/strong&gt; configured with &lt;strong&gt;environment variables&lt;/strong&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;$ docker run -e &quot;num.size=2&quot; -e &quot;num.max=10&quot; -p 8080:8080 numbers/numbers-app&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;It can also be run in &lt;strong&gt;OpenShift&lt;/strong&gt; configured with &lt;strong&gt;Config Maps&lt;/strong&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;apiVersion: v1&amp;#x000A;kind: ConfigMap&amp;#x000A;metadata:&amp;#x000A; name: numbers-config&amp;#x000A; namespace: numbers&amp;#x000A; ...&amp;#x000A;data:&amp;#x000A; num.size: &#39;5&#39;&amp;#x000A; num.max: &#39;100&#39;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;This highlights the benefit of using the Eclipse MicroProfile Config API to configure a Java application: the application code remains simple and use the injected values from the Config API. The implementation then figures out all the sources where the values can come from (System properties, properties files, environment, &lt;strong&gt;and container config maps&lt;/strong&gt;) and inject the appropriate ones.&lt;/p&gt; </content> </entry> <entry> <title type="html">Eclipse MicroProfile Config (Part I)</title> <link href="http://jmesnil.net/weblog/2017/04/25/eclipse-microprofile-config-part-i/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2017/04/25/eclipse-microprofile-config-part-i/</id> <updated>2017-04-25T15:00:10+00:00</updated> <published>2017-04-25T15:00:10+00:00</published> <content type="html"> &lt;p&gt;This is the first post that will cover some work I have been doing around the &lt;a href=&quot;empcfg&quot;&gt;Eclipse MicroProfile Config&lt;/a&gt; as a part of my job working on &lt;a href=&quot;https://wildlfy.org/&quot;&gt;WildFly&lt;/a&gt; and &lt;a href=&quot;http://wildfly-swarm.io/&quot;&gt;Swarm&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;In this post, I will show how to use the Config API from a Java application. The remaining posts will be about developing such new features within the WildFly and Swarm ecosystem.&lt;/p&gt; &lt;h2&gt;Eclipse MicroProfile&lt;/h2&gt; &lt;p&gt;As stated on its &lt;a href=&quot;https://microprofile.io/&quot;&gt;Web site&lt;/a&gt;, the mission of the Eclipse MicroProfile is to define:&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;An open forum to optimize Enterprise Java for a microservices architecture by innovating across multiple implementations and collaborating on common areas of interest with a goal of standardization.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;One of the first new API that they are defining is the &lt;a href=&quot;https://github.com/eclipse/microprofile-config/&quot;&gt;Config API&lt;/a&gt; that provides a common way to retrieve &lt;em&gt;configuration&lt;/em&gt; coming from a variety of sources (properties file, system properties, environment variables, database, etc.). The API is very simple and consists mainly of 2 things:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;a &lt;code&gt;Config&lt;/code&gt; interface can be used to retrieve (possibly optional) values identified by a name from many config sources&lt;/li&gt; &lt;li&gt;a &lt;code&gt;@ConfigProperty&lt;/code&gt; annotation to directly inject a configuration value using CDI&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;The API provides a way to add different config source from where the properties are fetched. By default, they can come from:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;the JVM System properties (backed by &lt;code&gt;System.getProperties()&lt;/code&gt;)&lt;/li&gt; &lt;li&gt;the OS environment (backed by &lt;code&gt;System.getenv()&lt;/code&gt;)&lt;/li&gt; &lt;li&gt;properties file (stored in &lt;code&gt;META-INF/microprofile-config.properties&lt;/code&gt;)&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;A sampe code to use the Config API looks like this:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;java&quot;&gt;@Inject&amp;#x000A;Config config;&amp;#x000A;&amp;#x000A;@Inject&amp;#x000A;@ConfigProperty(name = &quot;BAR&quot;, defaultValue = &quot;my BAR property comes from the code&quot;)&amp;#x000A;String bar;&amp;#x000A;&amp;#x000A;@Inject&amp;#x000A;@ConfigProperty(name = &quot;BOOL_PROP&quot;, defaultValue = &quot;no&quot;)&amp;#x000A;boolean boolProp;&amp;#x000A;&amp;#x000A;...&amp;#x000A;Optional&amp;lt;String&amp;gt; foo = config.getOptionalValue(&quot;FOO&quot;, String.class);&amp;#x000A;...&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;There is really not much to the Config API. It is a simple API that hides all the complexity of gathering configuration from various places so that the application can focus on using the values.&lt;/p&gt; &lt;p&gt;One important feature of the API is that you can define the importance of the config sources. If a property is defined in many sources, the value from the config source with the higher importance will be used. This allows to have for example default values in the code or in a properties file (with low importance) that are used when the application is tested locally. When the application is deployed in a container, environment variables defined by the container will have higher importance and be used instead of the default ones.&lt;/p&gt; &lt;h2&gt;Instructions&lt;/h2&gt; &lt;p&gt;The code above comes from the &lt;a href=&quot;https://github.com/jmesnil/microprofile-config-extension/blob/master/example/src/main/java/net/jmesnil/microprofile/config/example/HelloWorldEndpoint.java&quot;&gt;example&lt;/a&gt; that I wrote as a part of my work on the Config API.&lt;/p&gt; &lt;p&gt;To run the example, you need to first install my &lt;a href=&quot;https://github.com/jmesnil/microprofile-config-extension&quot;&gt;project&lt;/a&gt; and then run the example project:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;$ cd example&amp;#x000A;$ mvn wildfly-swarm:run&amp;#x000A;...&amp;#x000A;2017-04-14 10:35:24,416 WARN [org.wildfly.swarm] (main) WFSWARM0013: Installed fraction: Eclipse MicroProfile Config - UNSTABLE net.jmesnil:microprofile-config-fraction:1.0-SNAPSHOT&amp;#x000A;...&amp;#x000A;2017-04-14 10:35:30,676 INFO [org.wildfly.swarm] (main) WFSWARM99999: WildFly Swarm is Ready&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;It is a simple Web application that will return the value of some variable and fields that are configured using the Config API:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;$ curl http://localhost:8080/hello&amp;#x000A;FOO property = Optional[My FOO property comes from the microprofile-config.properties file]&amp;#x000A;BAR property = my BAR property comes from the code&amp;#x000A;BOOL_PROP property = false&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;We then run the application again with environment variables:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;$ BOOL_PROP=&quot;yes&quot; FOO=&quot;my FOO property comes from the env&quot; BAR=&quot;my BAR property comes from the env&quot; mvn wildfly-swarm:run&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;If we call the application, we see that the environment variables are now used to configure the application:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;$ curl http://localhost:8080/hello&amp;#x000A;FOO property = Optional[my FOO property comes from the env]&amp;#x000A;BAR property = my BAR property comes from the env&amp;#x000A;BOOL_PROP property = true&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The example is using Swarm and for those familiar with it, only requires to add two fractions to use the Config API:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;org.wildfly.swarm&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;cdi&amp;lt;/artifactId&amp;gt;&amp;#x000A;&amp;lt;/dependency&amp;gt;&amp;#x000A;&amp;lt;dependency&amp;gt;&amp;#x000A; &amp;lt;groupId&amp;gt;net.jmesnil&amp;lt;/groupId&amp;gt;&amp;#x000A; &amp;lt;artifactId&amp;gt;microprofile-config-fraction&amp;lt;/artifactId&amp;gt;&amp;#x000A; &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;&amp;#x000A;&amp;lt;/dependency&amp;gt;&amp;#x000A;&amp;lt;/dependency&amp;gt;&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;I have not yet released a version of my implementation as it is not clear yet where it will actually be hosted (and which Maven coordinates will be used).&lt;/p&gt; &lt;h1&gt;Conclusion&lt;/h1&gt; &lt;p&gt;This first post is a gentle introduction to the Config API. The &lt;a href=&quot;https://github.com/eclipse/microprofile-config/blob/master/spec/src/main/asciidoc/microprofile-config-spec.asciidoc&quot;&gt;specification&lt;/a&gt; is not final and I have left outside some nice features (such as converters) that I will cover later.&lt;/p&gt; &lt;p&gt;The next post will be about my experience of writing an implementation of this API and the way to make it available to Java EE applications deployed in the WildFly application server or to MicroServices built with WildFly Swarm.&lt;/p&gt; </content> </entry> <entry> <title type="html">Dockerization of My Web Site</title> <link href="http://jmesnil.net/weblog/2016/03/09/dockerization-of-my-web-site/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2016/03/09/dockerization-of-my-web-site/</id> <updated>2016-03-09T20:18:59+00:00</updated> <published>2016-03-09T20:18:59+00:00</published> <content type="html"> &lt;p&gt;This web site is composed of static files generated by &lt;a href=&quot;http://awestruct.org&quot;&gt;Awestruct&lt;/a&gt;. I have extended the basic Awestruct project to provide some additional features (link posts, article templates, photo thumbnails, etc.) Unfortunately, some of these extensions uses Rubygems that depends on native libraries or uglier spaghetti dependencies.&lt;/p&gt; &lt;p&gt;I recently wanted to write an article but was unable to generate the web site because some Rubygems where no longer working with native libraries on my Mac. Using &lt;a href=&quot;http://bundler.io&quot;&gt;bundler&lt;/a&gt; to keep the gems relative to this project does not solve the issue of the native libraries that are upgraded either the OS or package system (such as &lt;a href=&quot;http://brew.sh&quot;&gt;Homebrew&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;This was the perfect opportunity to play with &lt;a href=&quot;https://www.docker.com&quot;&gt;Docker&lt;/a&gt; to create an image that I could use to generate the web site independantly of my OS.&lt;/p&gt; &lt;p&gt;I create this &lt;a href=&quot;https://hub.docker.com/r/jmesnil/jmesnil.net/&quot;&gt;jmesnil/jmesnil.net image&lt;/a&gt; by starting from the &lt;a href=&quot;https://hub.docker.com/r/goldmann/awestruct/&quot;&gt;vanilla awestruct image&lt;/a&gt; created by my colleague, Marek. I tweaked it because he was only installing the Awestruct gem from the &lt;code&gt;Dockerfile&lt;/code&gt; while I have a lot of other gems to install for my extensions.&lt;/p&gt; &lt;p&gt;I prefer to keep the gems listed in the &lt;code&gt;Gemfile&lt;/code&gt; so that the project can also work outside of Docker so I added the &lt;code&gt;Gemfile&lt;/code&gt; in the &lt;code&gt;Dockerfile&lt;/code&gt; before calling &lt;code&gt;bundle install&lt;/code&gt;.&lt;/p&gt; &lt;p&gt;This web site is hosted on &lt;a href=&quot;https://aws.amazon.com/s3/&quot;&gt;Amazon S3&lt;/a&gt; and use the &lt;a href=&quot;http://s3tools.org/s3cmd&quot;&gt;s3cmd&lt;/a&gt; tool to push the generated files to the S3 bucket. The s3cmd configuration is stored on my home directory and I need to pass it to the Docker image so that when the &lt;code&gt;s3cmd&lt;/code&gt; is run inside it, it can used by secret credentials. This is done in a &lt;a href=&quot;https://github.com/jmesnil/jmesnil.net/blob/master/docker.sh&quot;&gt;docker.sh&lt;/a&gt; script that I used to start the Docker image:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;# Read the s3cmd private keys from my own s3cmd config...&amp;#x000A;AWS_ACCESS_KEY_ID=`s3cmd --dump-config | grep access_key | grep -oE &#39;[^ ]+$&#39;`&amp;#x000A;AWS_SECRET_ACCESS_KEY=`s3cmd --dump-config | grep secret_key | grep -oE &#39;[^ ]+$&#39;`&amp;#x000A;&amp;#x000A;# ... and pass it to the s3cmd inside Docker using env variables&amp;#x000A;docker run -it --rm \&amp;#x000A; -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \&amp;#x000A; -e AWS_SECRET_KEY=$AWS_SECRET_ACCESS_KEY \&amp;#x000A; -v `pwd`/:/home/jmesnil/jmesnil.net \&amp;#x000A; -p 4242:4242 \&amp;#x000A; -w /home/jmesnil/jmesnil.net \&amp;#x000A; jmesnil/jmesnil.net&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;Once the Docker image is started by this script, I can then use regular Rake tasks to run a local Web server to write articles (&lt;code&gt;rake dev&lt;/code&gt;) or publish to Amazon S3 (&lt;code&gt;rake production&lt;/code&gt;).&lt;/p&gt; &lt;p&gt;This is a bit overkill to use a 1.144 GB Docker image to generate a 6MB web site (that only contains text, all the photos are stored in a different S3 bucket) but it is worthwhile as it will no longer be broken every time I upgrade the OS or Brew.&lt;/p&gt; &lt;p&gt;The image is generic enough that it could serve as the basis of any Ruby project using Bundler (as long as required native libs are added to the &lt;code&gt;yum install&lt;/code&gt; at the beginning of the Dockerfile).&lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; Austin Mann&#39;s iPhone 6s Camera Review</title> <link href="http://austinmann.com/trek/iphone-6s-camera-review-switzerland" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2015/10/09/austin-manns-iphone-6s-camera-review/</id> <updated>2015-10-09T16:38:31+00:00</updated> <published>2015-10-09T16:38:31+00:00</published> <content type="html"> &lt;p&gt;This is a great review of the iPhone 6s camera and summary of its new features.&lt;/p&gt; &lt;p&gt;Marion has bought an iPhone 6s and the camera is a definite improvement when I compare her photos to the ones from my iPhone 6.&lt;/p&gt; &lt;p&gt;Better low light performance and higher resolution are always a plus, but the new feature I prefer is Live Photos. When Apple announced it, I found that superfluous but I changed my mind after &lt;strike&gt;looking at&lt;/strike&gt; watching photos of Rapha&amp;euml;l and hearing him twittering...&lt;/p&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2015/10/09/austin-manns-iphone-6s-camera-review/&quot; title=&quot;Permanent link to Austin Mann&amp;#39;s iPhone 6s Camera Review&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> <entry> <title type="html">Stepping Out From Personal Open Source Projects</title> <link href="http://jmesnil.net/weblog/2015/09/04/stepping-out-from-personal-open-source-projects/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2015/09/04/stepping-out-from-personal-open-source-projects/</id> <updated>2015-09-04T09:58:05+00:00</updated> <published>2015-09-04T09:58:05+00:00</published> <content type="html"> &lt;p&gt;Our first child, Rapha&amp;euml;l, is born last September and we will soon celebrate his first birthday.&lt;/p&gt; &lt;p&gt;This year has been the happiest of my life. However, having a baby means that I have less free time than before, and I want to spend this time with my family or doing personal projects I feel passionate about.&lt;/p&gt; &lt;p&gt;These days I feel more passionate about making photography (mostly of Rapha&amp;euml;l and Marion) than writing software (I already have a full time job at Red Hat where I enjoy coding on &lt;a href=&quot;http://wildfly.org&quot;&gt;WildFly&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;Before our baby&#39;s birth, I could spend evenings and weekends working on personal Open Source projects. After one year, it is time to admit that I do not want to that anymore and act accordingly.&lt;/p&gt; &lt;p&gt;I have decided to flag my personal Open Source projects as &lt;em&gt;not maintained anymore&lt;/em&gt;. Some of these projects are still quite used, the three main are all dealing with messaging clients:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href=&quot;https://github.com/jmesnil/stomp-websocket&quot;&gt;stomp.js&lt;/a&gt; - a JavaScript library to write web apps/nodes.js client for STOMP protocol&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://github.com/mobile-web-messaging/StompKit&quot;&gt;StompKit&lt;/a&gt; - an Objective-C client for STOMP protocol&lt;/li&gt; &lt;li&gt;&lt;a href=&quot;https://github.com/mobile-web-messaging/MQTTKit&quot;&gt;MQTTKit&lt;/a&gt; - an Objective-C client for MQTT protocol&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;I&#39;ll modify these projects READMEs to warn that they are no longer maintained (with a link to that post to give some context).&lt;/p&gt; &lt;p&gt;It&#39;s not fair to users to spend time using them, reporting bugs and have no warning that their issues will be ignored.&lt;/p&gt; &lt;p&gt;If you are using these projects, I understand that you may be upset that your bugs are not fixed or that the enhancement you request will not be fixed in the original project. Fortunately, these projects are licensed under the Apache License V2. You can fork them (they are hosted on GitHub and use Git as their version control system) and modify them to suit your needs.&lt;/p&gt; &lt;p&gt;I also had some discussion to &lt;a href=&quot;http://activemq.2283324.n4.nabble.com/Code-donation-for-stomp-js-tp4694260.html&quot;&gt;donate stomp.js to Apache ActiveMQ&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;It is a tough decision to not maintain these projects anymore but it is a decision that I have subconsciously made months ago. Now I just have to acknowledge it.&lt;/p&gt; &lt;p&gt;I may revisit this decision when my child is older or when I feel passionate about these project again. Or I may create other Open Source projects, who knows?&lt;/p&gt; &lt;p&gt;The key thing is that by releasing these projects under an Open Source license, I ensured that their use could outlast my initial contributions to it.&lt;/p&gt; </content> </entry> <entry> <title type="html">Civilian Sponsorship of Rapha&amp;euml;l</title> <link href="http://jmesnil.net/weblog/2015/07/21/civilian-sponsorship-of-raphael/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2015/07/21/civilian-sponsorship-of-raphael/</id> <updated>2015-07-21T14:31:48+00:00</updated> <published>2015-07-21T14:31:48+00:00</published> <content type="html"> &lt;p&gt;Earlier this month, we celebrated the civilian sponsorship&lt;a id=&quot;fnr1-2015-07-21&quot; href=&quot;#fn1-2015-07-21&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; of our son, Rapha&amp;euml;l. It was a great sunny day full of laughs and emotion.&lt;/p&gt; &lt;p&gt;Now our son has a godfather and godmother that will be there to take care of him.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2015-07-04-JFM01868-900w.jpg, https://media.jmesnil.net/images/2015-07-04-JFM01868-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2015-07-04-JFM01868-480w.jpg, https://media.jmesnil.net/images/2015-07-04-JFM01868-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2015-07-04-JFM01868-480w.jpg, https://media.jmesnil.net/images/2015-07-04-JFM01868-960w.jpg 2x&quot; alt=&quot;Rapha&amp;amp;euml;l with his Godmother &amp;amp;amp; Godfather&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2015-07-04-JFM01868-480w.jpg&quot; alt=&quot;Rapha&amp;amp;euml;l With his Godmother &amp;amp;amp; Godfather&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Rapha&amp;euml;l with his Godmother &amp;amp; Godfather &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-E2 &lt;span class=&quot;speed&quot;&gt;1/80&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/5.6&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;2500&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;35&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;I took this opportunity to create a story on &lt;a href=&quot;https://exposure.co/&quot;&gt;Exposure&lt;/a&gt;. I learnt about this service from &lt;a href=&quot;http://scottkelby.com/&quot;&gt;Scott Kelby&lt;/a&gt; and this celebration was a good candidate to try this service.&lt;/p&gt; &lt;p&gt;&lt;figure style=&quot;max-width:900px&quot;&gt; &lt;a href=&quot;https://jmesnil.exposure.co/bapteme-civil-de-raphael&quot;&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2015-07-04-bapteme-civil-de-raphael.jpg&quot; alt=&quot;Bapt&amp;amp;ecirc;me Civil de Rapha&amp;amp;euml;l on Exposure&quot;&gt; &lt;/a&gt; &lt;figcaption&gt;Bapt&amp;ecirc;me Civil de Rapha&amp;euml;l on Exposure&lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;You can read the story (in French) &lt;a href=&quot;https://jmesnil.exposure.co/bapteme-civil-de-raphael/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Exposure service is really good (I only used their free offer). The image layout options are basic but good enough for such an image-oriented story. There is only one place where I would have preferred to use a grid layout with same size for all images. I also would have liked more typography options to better distinguish the (sparse) text.&lt;/p&gt; &lt;p&gt; &lt;a href=&quot;https://scottkelby.exposure.co/&quot;&gt;Scott Kelby&#39;s page&lt;/a&gt; provides some great examples of Exposure features.&lt;/p&gt; &lt;p&gt;I don&#39;t plan to upgrade to their pro offer but I&#39;ll keep playing with it as their offer improves.&lt;/p&gt; &lt;hr /&gt; &lt;ol&gt; &lt;li&gt;&lt;a id=&quot;fn1-2015-07-21&quot;&gt;&lt;/a&gt;A civilian sponsorship is not religious but republican. It is performed at the town hall and is a moral engagement&amp;nbsp;&lt;a href=&quot;#fnr1-2015-07-21&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt; </content> </entry> <entry> <title type="html">Marion &amp;amp; Rapha&amp;euml;l</title> <link href="http://jmesnil.net/weblog/2014/11/17/marion-raphael/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2014/11/17/marion-raphael/</id> <updated>2014-11-17T17:22:39+00:00</updated> <published>2014-11-17T17:22:39+00:00</published> <content type="html"> &lt;p&gt;Over the week-end I experimented with portraits of Marion holding our baby, Rapha&amp;euml;l. I wanted to go for an intimate moment between a mother and her baby. The idea was to have a soft portrait of Rapha&amp;euml;l and Marion wrapped in shadows.&lt;/p&gt; &lt;p&gt;Regardless of the darkness that surrounds them, their love is a bright light that will not be dimmed.&lt;/p&gt; &lt;p&gt;&lt;figure class=&quot;portrait&quot;&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-11-15-JFM07918-900w.jpg, https://media.jmesnil.net/images/2014-11-15-JFM07918-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-11-15-JFM07918-480w.jpg, https://media.jmesnil.net/images/2014-11-15-JFM07918-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-11-15-JFM07918-480w.jpg, https://media.jmesnil.net/images/2014-11-15-JFM07918-960w.jpg 2x&quot; alt=&quot;Marion &amp;amp;amp; Rapha&amp;amp;euml;l&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-11-15-JFM07918-480w.jpg&quot; alt=&quot;Marion &amp;amp;amp; Rapha&amp;amp;euml;l&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Marion &amp;amp; Rapha&amp;euml;l &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-E2 &lt;span class=&quot;speed&quot;&gt;1/180&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/5.6&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;56&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;The end result looks like a chiaroscuro painting of La Vierge &amp;agrave; l&#39;Enfant.&lt;/p&gt; &lt;h3&gt;Technical (boring) corner&lt;/h3&gt; &lt;p&gt;Technically, this is a simple photo with a soft light to preserve this private moment.&lt;/p&gt; &lt;p&gt;I used a one-light setup with a Yongnuo YN-560 III flash reflected by a &lt;a href=&quot;http://www.lastolite.com/product/18202.1067135.0.0.0/LL%2BLU2474F/_/Umbrella_Kit_99cm_%2B_Stand_%26_2422_Tilthead_Shoe_Lock&quot;&gt;34&quot; white umbrella&lt;/a&gt;. I positioned the flash at their right, at 45° above them. The light is feathered so they only catch the edge of the light (retrospectively, I should have feathered it even more to increase the intimacy).&lt;/p&gt; &lt;p&gt;The background is a &lt;a href=&quot;http://www.dynasun.com/shop/product_info.php?cPath=140_69_70&amp;amp;products_id=123000&quot;&gt;40&quot;x60&quot; reflector&lt;/a&gt; with its black surface. Since the light is feathered, almost none reaches the black background and it remains pure black.&lt;/p&gt; &lt;p&gt;I positioned Marion so that Rapha&amp;euml;l&#39;s face could catch most of the light and only her right side would be lit... plus a tiny bit of reflection on her left cheek thanks to the almost bald skull of our baby ;)&lt;/p&gt; &lt;p&gt;I used my Fuji X-E2 with its awesome 56mm &amp;#402;/1.2 lens that I opened at &amp;#402;/5.6 to have enough field of depth for both of them.&lt;/p&gt; &lt;p&gt;&lt;figure style=&quot;max-width:520px;&quot;&gt; &lt;picture&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-11-15-JFM07918.setup.png&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-11-15-JFM07918.setup.png&quot;&gt; &lt;/noscript&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;Rapha&amp;euml; was intrigued by the flash tests and I just had to make a few pictures to capture this one.&lt;/p&gt; &lt;p&gt;Simple stuff, and a lovely moment that all three of us shared.&lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; O&#39;Reilly Webcast: Using Messaging Protocols to Build Mobile and Web Applications</title> <link href="http://www.oreilly.com/pub/e/3151" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2014/11/17/oreilly-webcast-using-messaging-protocols-to-build-mobile-and-web-applications/</id> <updated>2014-11-17T09:57:38+00:00</updated> <published>2014-11-17T09:57:38+00:00</published> <content type="html"> &lt;p&gt;Last week, I made a &lt;a href=&quot;http://www.oreilly.com/pub/e/3151&quot;&gt;webcast for O&#39;Reilly about using messaging protocols to build mobile and web applications&lt;/a&gt; to promote my book, &lt;a href=&quot;http://mobile-web-messaging.net&quot;&gt;Mobile &amp;amp; Web Messaging&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;This webcast can be watched for free and you can also read the &lt;a href=&quot;https://media.jmesnil.net/slides/2014-11-13_oreilly_webcast.pdf&quot;&gt;slides&lt;/a&gt; I used for the presentation. They contain most of the information I talked about during this 1-hour long webcast.&lt;/p&gt; &lt;p&gt;Thanks to the people at O&#39;Reilly (and especially Yasmina Greco) to setup this presentation, it was a great and fun experience.&lt;/p&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2014/11/17/oreilly-webcast-using-messaging-protocols-to-build-mobile-and-web-applications/&quot; title=&quot;Permanent link to O&amp;#39;Reilly Webcast: Using Messaging Protocols to Build Mobile and Web Applications&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> <entry> <title type="html">Rapha&amp;euml;l Mesnil</title> <link href="http://jmesnil.net/weblog/2014/10/16/raphael-mesnil/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2014/10/16/raphael-mesnil/</id> <updated>2014-10-16T11:53:10+00:00</updated> <published>2014-10-16T11:53:10+00:00</published> <content type="html"> &lt;p&gt;Our first child, Rapha&amp;euml;l Mesnil, is born on September, 28&lt;sup&gt;th&lt;/sup&gt; at 52cm and 3.230kg.&lt;/p&gt; &lt;p&gt;Marion and the baby are fine and we enjoy every moment with him.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-10-08-JFM07250-900w.jpg, https://media.jmesnil.net/images/2014-10-08-JFM07250-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-10-08-JFM07250-480w.jpg, https://media.jmesnil.net/images/2014-10-08-JFM07250-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-10-08-JFM07250-480w.jpg, https://media.jmesnil.net/images/2014-10-08-JFM07250-960w.jpg 2x&quot; alt=&quot;Rapha&amp;amp;euml;l Mesnil&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-10-08-JFM07250-480w.jpg&quot; alt=&quot;Rapha&amp;amp;euml;l Mesnil&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Rapha&amp;euml;l Mesnil &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-E2 &lt;span class=&quot;speed&quot;&gt;1/180&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/2.8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;56&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;I am now a father which will make many photographs of his baby :)&lt;/p&gt; &lt;p&gt;I am already making good use of the Fujinon 56mm &amp;#402;/1.2 lens that I bought a few months ago when we learnt that Marion was pregnant.&lt;/p&gt; &lt;p&gt;I am not accustomed to baby photography (or portraits in general) but this will change now that Rapha&amp;euml;l is here. We were back at home for one day and I was already setting up a studio to shoot his portrait. Next step is to make photographs of Marion and the baby together.&lt;/p&gt; &lt;p&gt;So much fun, so much love.&lt;/p&gt; </content> </entry> <entry> <title type="html">Rainy Venezia</title> <link href="http://jmesnil.net/weblog/2014/09/09/rainy-venezia/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2014/09/09/rainy-venezia/</id> <updated>2014-09-09T16:17:13+00:00</updated> <published>2014-09-09T16:17:13+00:00</published> <content type="html"> &lt;p&gt;We went to Venezia last May and had a rainy day during our trip. We spent almost the whole afternoon at a coffee shop and I was shooting the soaked people rushing to cross the street.&lt;/p&gt; &lt;p&gt;This old man stood out with his red umbrella and his leisurely pace.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-05-02-Rainy%20Venezia-900w.jpg, https://media.jmesnil.net/images/2014-05-02-Rainy%20Venezia-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-05-02-Rainy%20Venezia-480w.jpg, https://media.jmesnil.net/images/2014-05-02-Rainy%20Venezia-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-05-02-Rainy%20Venezia-480w.jpg, https://media.jmesnil.net/images/2014-05-02-Rainy%20Venezia-960w.jpg 2x&quot; alt=&quot;Rainy Venezia&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-05-02-Rainy%20Venezia-480w.jpg&quot; alt=&quot;Rainy Venezia&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Rainy Venezia &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-E2 &lt;span class=&quot;speed&quot;&gt;1/100&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/9&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;1000&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;55&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; </content> </entry> <entry> <title type="html">How To Shoot a Bottle of Beer &amp;mdash; St. Stefanus Blonde</title> <link href="http://jmesnil.net/weblog/2014/09/05/how-to-shoot-a-bottle-of-beer/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2014/09/05/how-to-shoot-a-bottle-of-beer/</id> <updated>2014-09-05T11:21:42+00:00</updated> <published>2014-09-05T11:21:42+00:00</published> <content type="html"> &lt;div class=&quot;pull-left&quot; style=&quot;margin: 1em;&quot;&gt; &lt;a href=&quot;https://unepetitemousse.fr&quot;&gt;&lt;img src=&quot;https://unepetitemousse.fr/images/unepetitemousse-logo.140.150.png&quot; alt=&quot;Une Petite Mousse&quot;&gt;&lt;/a&gt; &lt;/div&gt; &lt;p&gt;For the past 18 months, I have photographed bottles of beer for my friends of &lt;a href=&quot;https://unepetitemousse.fr&quot;&gt;Une Petite Mousse&lt;/a&gt;. On their web site, you subscribe to receive every month a box of six bottle of beers. The selection changes every month and contains a mix of well-known beers and others from micro-breweries. It is a great way to discover and taste new beers that you can not find in a store near you.&lt;/p&gt; &lt;p&gt;They need pictures of the bottles for their &lt;a href=&quot;https://unepetitemousse.fr/box/degustations&quot;&gt;online catalogue&lt;/a&gt; and the paper guide that comes in the boxes.&lt;/p&gt; &lt;p&gt;Making photographs of a bottle of beer is suprisingly challenging. I want to give on overview of the color of the beer inside the bottle (which are often made of a dark glass) while highlighting the label on the front of the bottle. In order to build the catalogue, I want to have an uniform style for all pictures with a pure white background and a square format (to keep the respective size of the bottles).&lt;/p&gt; &lt;p&gt;In this post, I&#39;ll explain the process I have used for the latest box (available mid-september). For september 2014, one of the beers is the &lt;a href=&quot;http://www.st-stefanus.com/us/authentic-abbey-beer/belgian-blonde-beer&quot;&gt;St. Stefanus Blonde&lt;/a&gt;, brewed in Belgium.&lt;/p&gt; &lt;p&gt;&lt;figure style=&quot;max-width:319px;&quot;&gt; &lt;a href=&quot;http://www.st-stefanus.com/us/authentic-abbey-beer/belgian-blonde-beer&quot;&gt;&lt;img src=&quot;https://www.st-stefanus.com/sites/g/files/ogq301/f/blog_images/grand-cru_2.jpg&quot; alt=&quot;St. Stefanus Blonde&quot;&gt;&lt;/a&gt; &lt;figcaption&gt;St. Stefanus Blonde &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;St Stefanus&lt;/span&gt; &lt;figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;The picture above is from their web site (I really like how the strips of white emphasize the roundness of the small bottle).&lt;/p&gt; &lt;h2&gt;Gear&lt;/h2&gt; &lt;p&gt;To photograph this bottle, I used the following material:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Fuji X-E2 camera&lt;/li&gt; &lt;li&gt;Fuji 56mm &amp;#402;/1.2 lens (which is my lens with the longest focal length)&lt;/li&gt; &lt;li&gt;2 Flash Speedlights (Yongnuo YN560-III and Nikon SB-700) in manual mode. I plugged the Nikon SB-700 on a Yongnuo RF-603/N3 to trigger it remotely&lt;/li&gt; &lt;li&gt;a Yongnuo YN560-TX plugged on the camera hotshoe to control remotely the speedlights&lt;/li&gt; &lt;li&gt;my trusty Giotto&#39;s Vitruvian tripod to stabilize the camera&lt;/li&gt; &lt;li&gt;many white foam boards (for the background and below the bottle)&lt;/li&gt; &lt;li&gt;many black foam boards (used as gobos to block the light)&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Before explaining my process, I heartily recommend to read &lt;a href=&quot;http://www.amazon.com/gp/product/0240812255/ref=as_li_tl?ie=UTF8&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=0240812255&amp;amp;linkCode=as2&amp;amp;tag=jefmes-20&amp;amp;linkId=IELE64G4RXJWIIHJ&quot;&gt;Light Science and Magic: An Introduction to Photographic Lighting&lt;/a&gt;&lt;img src=&quot;http://ir-na.amazon-adsystem.com/e/ir?t=jefmes-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0240812255&quot; width=&quot;1&quot; height=&quot;1&quot; border=&quot;0&quot; alt=&quot;&quot; style=&quot;border:none !important; margin:0px !important;&quot; /&gt;. This book is an invaluable help to understand how light plays with shapes and textures.&lt;/p&gt; &lt;h2&gt;Setup&lt;/h2&gt; &lt;p&gt;The first step is to place the bottle and the various white and black foam boards that will give the bottle a distinctive shape. In order to highlight the color of the beer inside the bottle, I will light white foam boards in the background. The light will bounce on the boards and go through the bottle before reaching the camera. The background will be overexposed to be pure white.&lt;/p&gt; &lt;p&gt;I also want to have well-defined edges on the bottle. I place two black foam boards on each side of the white background. These black boards will appear on the edges of the bottle and increase the contrast and sharpness of its shape. Without these black boards, the light coming from the white background would &lt;em&gt;splill&lt;/em&gt; on the edges and make them too soft.&lt;/p&gt; &lt;p&gt;I put the bottle on a white foam board (with a plexiglass to have a small reflection at the bottom). Finally, I put other black foam boards on each side of the bottle and on top of it to prevent any leaking light to reach it.&lt;/p&gt; &lt;p&gt;I then place the camera at the right distance of the bottle to have it fill the image height. The image will be cropped to square in post-processing. I activate the X-E2 guides on its screen to have a good overview of the final size.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-IMG_2735-900w.jpg, https://media.jmesnil.net/images/2014-09-03-IMG_2735-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-IMG_2735-480w.jpg, https://media.jmesnil.net/images/2014-09-03-IMG_2735-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-09-03-IMG_2735-480w.jpg, https://media.jmesnil.net/images/2014-09-03-IMG_2735-960w.jpg 2x&quot; alt=&quot;Setup&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-09-03-IMG_2735-480w.jpg&quot; alt=&quot;Setup&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Setup &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;Once the camera is correctly placed, I fine tune the placement of the black boards on each side of the white background. They must be placed so that the edges of the bottle are dark but not too close so that they fill the inside of the bottle.&lt;/p&gt; &lt;p&gt;&lt;figure class=&quot;portrait&quot;&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-IMG_2740-900w.jpg, https://media.jmesnil.net/images/2014-09-03-IMG_2740-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-IMG_2740-480w.jpg, https://media.jmesnil.net/images/2014-09-03-IMG_2740-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-09-03-IMG_2740-480w.jpg, https://media.jmesnil.net/images/2014-09-03-IMG_2740-960w.jpg 2x&quot; alt=&quot;Placement of the black foam boards&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-09-03-IMG_2740-480w.jpg&quot; alt=&quot;Placement of the black foam boards&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Placement of the black foam boards &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;I put the bottle on top of a small box to be able to place the flashes below it (so that they do not appear on the photos) and angle them appropriately to light the scene.&lt;/p&gt; &lt;p&gt;I want to control the lighting and block any ambient light (the garage where I took the photos has lights coming from windows that can not be easily blocked). I configure my camera to 1/180 (the highest sync speed for the X-E2) and ISO 400. The lens is stopped down to &amp;#402;/8 to have enough depth of field.&lt;/p&gt; &lt;p&gt;With these settings, the image is so dark that I know I will not be bothered by any ambient light (the photo is cropped but no other postprocessing has been applied).&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stephanus-ambient-900w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stephanus-ambient-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stephanus-ambient-480w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stephanus-ambient-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stephanus-ambient-480w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stephanus-ambient-960w.jpg 2x&quot; alt=&quot;Ambient Light Only&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-09-03-st-stephanus-ambient-480w.jpg&quot; alt=&quot;Ambient Light Only&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Ambient Light Only &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;Next step is to place the two flashes and provide the lighting.&lt;/p&gt; &lt;h2&gt;Back (Main) Light&lt;/h2&gt; &lt;p&gt;The main light is provided by the flash behind the bottle. It is directed towards the white background and will light the bottle after bouncing on the background. I use the Yongnuo YN560-III zoomed at 24 mm with a diffuser to spread the light on the white background.&lt;/p&gt; &lt;p&gt;When I take the picture, I can see that the beer inside the bottle is well lit and the background is overexposed to pure white. Thanks to the black foam boards, the edges of the bottle are dark and sharp enough (the photo below is cropped but no other postprocessing has been applied).&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-main-900w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stefanus-main-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-main-480w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stefanus-main-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-main-480w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stefanus-main-960w.jpg 2x&quot; alt=&quot;Back (Main) Light&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-main-480w.jpg&quot; alt=&quot;Back (Main) Light&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Back (Main) Light &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-E2&amp;nbsp; &lt;span class=&quot;speed&quot;&gt;1/180&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;56&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;h2&gt;Front (Fill) Light&lt;/h2&gt; &lt;p&gt;The liquid inside the bottle is lit but there is no light reaching the label on the front of the bottle.&lt;/p&gt; &lt;p&gt;I then to use the second flash (Nikon SB-700) to light only the label. The placement of the flash is tricky because it can easily create highlights on the glass if it is not properly directed. I place it below the bottle with an angle of 45° or so. It is fully zoomed at 135 mm to focus its light on the label. With this angle and zoom, the flash will lit the paper label but most of the light reaching glass will not be captured by the camera.&lt;/p&gt; &lt;p&gt;The photo below shows the bottle lit by the front flash only (the photo below is cropped but no other postprocessing has been applied).&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stephanus-fill-900w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stephanus-fill-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stephanus-fill-480w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stephanus-fill-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stephanus-fill-480w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stephanus-fill-960w.jpg 2x&quot; alt=&quot;Font (Fill) Light&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-09-03-st-stephanus-fill-480w.jpg&quot; alt=&quot;Font (Fill) Light&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Font (Fill) Light &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-E2&amp;nbsp; &lt;span class=&quot;speed&quot;&gt;1/180&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;56&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt; We can see there are two highlights on the bottom of the bottle and near its neck. They are small enough that I will be able to remove it in post processing.&lt;/p&gt; &lt;h2&gt;Final Picture&lt;/h2&gt; &lt;p&gt;Once the two speedlights are setup, I tweak their power to have a correct ratio between the back and front lights. At then, I use the following ratio:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Back (main) light 1/16 +0.3EV&lt;/li&gt; &lt;li&gt;Front (fill) light 1/64 -0.3EV&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;When I take the picture with both the back and front lights, I capture the final (cropped but unprocessed) picture below.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-2-900w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stefanus-2-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-2-480w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stefanus-2-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-2-480w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stefanus-2-960w.jpg 2x&quot; alt=&quot;Back and Front Lights&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-2-480w.jpg&quot; alt=&quot;Back and Front Lights&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Back and Front Lights &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-E2&amp;nbsp; &lt;span class=&quot;speed&quot;&gt;1/180&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;56&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;Most of the work is now done and I just need a few touches of post-processing to finalize the image.&lt;/p&gt; &lt;h2&gt;Post-Processing&lt;/h2&gt; &lt;p&gt;I use &lt;a href=&quot;http://www.adobe.com/products/photoshop-lightroom.html&quot;&gt;Lightroom&lt;/a&gt; for the image post-processing.&lt;/p&gt; &lt;p&gt;Once the image is imported, I correct the lens distorsions and crop the image to a square format.&lt;/p&gt; &lt;p&gt;I slightly modify its global setting in the Basic module:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;I fix its white balance (using a photo of the scene with a grey card)&lt;/li&gt; &lt;li&gt;I punch its Tone &lt;ul&gt; &lt;li&gt;+0.75 Exposure&lt;/li&gt; &lt;li&gt;+41 Contrast&lt;/li&gt; &lt;li&gt;+26 White&lt;/li&gt; &lt;li&gt;-63 Black&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;I increase its Presence &lt;ul&gt; &lt;li&gt;+16 Clarity&lt;/li&gt; &lt;li&gt;+26 Vibrance&lt;/li&gt; &lt;li&gt;-4 Saturation&lt;/li&gt; &lt;/ul&gt; &lt;/li&gt; &lt;li&gt;I also increase the sharpness in the Details module (+52 Sharpening).&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;The numbers are meaningless. They are different for each bottle, depending mainly on the color and texture of the liquid and glass. The goal with any of these settings is to have a pure white background and a bottle that is well exposed and contrasted.&lt;/p&gt; &lt;p&gt;I use the Spot Removal tool to remove the highlights caused by the front flash at the bottom of the bottle and near its neck.&lt;/p&gt; &lt;p&gt;Last step is to use a few Adjustment Brushes to finalize the images:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;darken the bottle reflection on the plexiglass&lt;/li&gt; &lt;li&gt;lighten the bottom corners of the label (that&#39;s a mistake I did not catch when capturing the image)&lt;/li&gt; &lt;li&gt;sharpen and increase contrast of the label (to have the text standout)&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;I finally export it in JPEG and hand it over to Barbara, the graphist designer of Une Petite Mousse, that uses it for the paper guide and the web site.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-900w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stefanus-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-480w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stefanus-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-480w.jpg, https://media.jmesnil.net/images/2014-09-03-st-stefanus-960w.jpg 2x&quot; alt=&quot;St. Stefanus Blonde&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-09-03-st-stefanus-480w.jpg&quot; alt=&quot;St. Stefanus Blonde&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;St. Stefanus Blonde &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-E2&amp;nbsp; &lt;span class=&quot;speed&quot;&gt;1/180&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;56&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;Since March 2013, I have photographed more than one hundred different beers&lt;a id=&quot;fnr1-2014-09-05&quot; href=&quot;#fn1-2014-09-05&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; and each one is a different challenge. The shape of the bottle changes, the color of the liquid and the glass change too. Some have dark labels, others have golden labels. Some do not have labels at all and the text is put directly on the glass.&lt;/p&gt; &lt;p&gt;I am always tweaking and refining the process to capture all these subtle differences and I am sure that I will continue to do so for as long as I take pictures and enjoy it.&lt;/p&gt; &lt;p&gt;Sant&amp;eacute;! &amp;#x1f37B;&lt;/p&gt; &lt;hr /&gt; &lt;ol&gt; &lt;li&gt;&lt;a id=&quot;fn1-2014-09-05&quot;&gt;&lt;/a&gt;and I have tasted all of them! :)&amp;nbsp;&lt;a href=&quot;#fnr1-2014-09-05&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt; </content> </entry> <entry> <title type="html">Macarons au Chocolat</title> <link href="http://jmesnil.net/weblog/2014/04/21/macarons-au-chocolat/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2014/04/21/macarons-au-chocolat/</id> <updated>2014-04-21T18:35:56+00:00</updated> <published>2014-04-21T18:35:56+00:00</published> <content type="html"> &lt;p&gt;&lt;figure class=&quot;portrait&quot;&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-04-20-macarons-900w.jpg, https://media.jmesnil.net/images/2014-04-20-macarons-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-04-20-macarons-480w.jpg, https://media.jmesnil.net/images/2014-04-20-macarons-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-04-20-macarons-480w.jpg, https://media.jmesnil.net/images/2014-04-20-macarons-960w.jpg 2x&quot; alt=&quot;Macarons au Chocolat&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-04-20-macarons-480w.jpg&quot; alt=&quot;Macarons au Chocolat&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Macarons au Chocolat &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-E2&amp;nbsp; &lt;span class=&quot;speed&quot;&gt;1/180&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;200&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;56&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;I am experimenting how to light a dark background and had no other subjects on hands than the macarons we just cooked :)&lt;/p&gt; </content> </entry> <entry> <title type="html">Architecture</title> <link href="http://jmesnil.net/weblog/2014/03/12/architecture/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2014/03/12/architecture/</id> <updated>2014-03-12T20:37:00+00:00</updated> <published>2014-03-12T20:37:00+00:00</published> <content type="html"> &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-03-06-architecture-900w.jpg, https://media.jmesnil.net/images/2014-03-06-architecture-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-03-06-architecture-480w.jpg, https://media.jmesnil.net/images/2014-03-06-architecture-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-03-06-architecture-480w.jpg, https://media.jmesnil.net/images/2014-03-06-architecture-960w.jpg 2x&quot; alt=&quot;Architecture&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-03-06-architecture-480w.jpg&quot; alt=&quot;Architecture&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Architecture &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt;&amp;nbsp;Fuji&amp;nbsp;X-E2&amp;nbsp; &lt;span class=&quot;speed&quot;&gt;1/480&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/9&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;200&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;33&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; </content> </entry> <entry> <title type="html">Les Trois Pucelles</title> <link href="http://jmesnil.net/weblog/2014/02/24/les-trois-pucelles/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2014/02/24/les-trois-pucelles/</id> <updated>2014-02-24T11:57:00+00:00</updated> <published>2014-02-24T11:57:00+00:00</published> <content type="html"> &lt;p&gt;Les 3 Pucelles, &lt;em&gt;the Three Maiden&lt;/em&gt;, are three rocks high above Grenoble in the Vercors. It was an important location used by the Resistance during the 2&lt;sup&gt;nd&lt;/sup&gt; World War.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-02-22-Les+3+Pucelles-900w.jpg, https://media.jmesnil.net/images/2014-02-22-Les+3+Pucelles-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-02-22-Les+3+Pucelles-480w.jpg, https://media.jmesnil.net/images/2014-02-22-Les+3+Pucelles-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-02-22-Les+3+Pucelles-480w.jpg, https://media.jmesnil.net/images/2014-02-22-Les+3+Pucelles-960w.jpg 2x&quot; alt=&quot;Les 3 Pucelles&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-02-22-Les+3+Pucelles-480w.jpg&quot; alt=&quot;Les 3 Pucelles&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Les 3 Pucelles &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/80&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;250&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;25&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;This 90-metre springboard was used for the ski jumping competion during the 1968 Winter Olympic Games at Grenoble. It has been closed since the 80s and can no longer be used.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-02-22-Tremplin+des+3+Pucelles-900w.jpg, https://media.jmesnil.net/images/2014-02-22-Tremplin+des+3+Pucelles-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-02-22-Tremplin+des+3+Pucelles-480w.jpg, https://media.jmesnil.net/images/2014-02-22-Tremplin+des+3+Pucelles-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-02-22-Tremplin+des+3+Pucelles-480w.jpg, https://media.jmesnil.net/images/2014-02-22-Tremplin+des+3+Pucelles-960w.jpg 2x&quot; alt=&quot;Tremplin des 3 Pucelles&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-02-22-Tremplin+des+3+Pucelles-480w.jpg&quot; alt=&quot;Tremplin des 3 Pucelles&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;&lt;a href=&quot;http://goo.gl/maps/T368G&quot;&gt;&lt;i class=&quot;fa fa-map-marker&quot;&gt;&lt;/i&gt;&lt;/a&gt;&amp;nbsp;Tremplin des 3 Pucelles &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;210&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;18&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; </content> </entry> <entry> <title type="html">La Fourchette d&#39;Andr&amp;eacute; Kert&amp;eacute;sz</title> <link href="http://jmesnil.net/weblog/2014/01/27/andre-kertesz-fourchette/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2014/01/27/andre-kertesz-fourchette/</id> <updated>2014-01-27T10:01:36+00:00</updated> <published>2014-01-27T10:01:36+00:00</published> <content type="html"> &lt;p&gt;Yesterday, I was reading a book about &lt;a href=&quot;http://en.wikipedia.org/wiki/Andr%C3%A9_Kert%C3%A9sz&quot;&gt;Andr&amp;eacute; Kert&amp;eacute;sz&lt;/a&gt;, one of my favourite photographers. I tried to reproduce one of his most famous photographs, La Fourchette, that he made in 1928.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-01-26-Fourchette-2-900w.jpg, https://media.jmesnil.net/images/2014-01-26-Fourchette-2-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2014-01-26-Fourchette-2-480w.jpg, https://media.jmesnil.net/images/2014-01-26-Fourchette-2-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2014-01-26-Fourchette-2-480w.jpg, https://media.jmesnil.net/images/2014-01-26-Fourchette-2-960w.jpg 2x&quot; alt=&quot;La Fourchette&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2014-01-26-Fourchette-2-480w.jpg&quot; alt=&quot;La Fourchette&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;La Fourchette d&#39;Andr&amp;eacute; Kert&amp;eacute;sz &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/180&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/5.6&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;200&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;37&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;The shape of my fork and plates are different from the original ones but the lighting is pretty similar. I used a single strobe to get a unidirectional hard light and tried several positions to get the shadows of the plate, the fork and the teeth close to the original:&lt;/p&gt; &lt;p&gt;&lt;figure style=&quot;margin:auto; max-width:504px&quot;&gt; &lt;img src=&quot;http://upload.wikimedia.org/wikipedia/en/b/b5/Kertesz_The_Fork.jpg&quot; alt=&quot;La Fourchette&quot;&gt; &lt;figcaption&gt;La Fourchette, 1928 &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Andr&amp;eacute; Kert&amp;eacute;sz&lt;/span&gt; &lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; &lt;p&gt;The printing I have is more subtle and nuanced that this picture from Wikimedia that has too much contrast.&lt;/p&gt; </content> </entry> <entry> <title type="html">2013 in Photos</title> <link href="http://jmesnil.net/weblog/2014/01/02/2013-in-photos/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2014/01/02/2013-in-photos/</id> <updated>2014-01-02T12:32:41+00:00</updated> <published>2014-01-02T12:32:41+00:00</published> <content type="html"> &lt;p&gt;2013 has ended and it&#39;s the opportunity to look back at all the photos I made during the year.&lt;/p&gt; &lt;p&gt;They are mostly landscapes from our trips (Tuscany, Brittany, Barcelona), food and a plethora of portraits of Marion :)&lt;/p&gt; &lt;div class=&quot;video-wrapper&quot; style=&quot;width:900px&quot;&gt;&lt;div class=&quot;video&quot;&gt; &lt;iframe src=&quot;http://www.flickr.com/photos/jmesnil/11706818786/in/set-72157639305770774/player/&quot; width=&quot;900&quot; height=&quot;596&quot; frameborder=&quot;0&quot; allowfullscreen webkitallowfullscreen mozallowfullscreen oallowfullscreen msallowfullscreen&gt;&lt;/iframe&gt; &lt;/div&gt;&lt;/div&gt; &lt;p&gt;I expect more of the same in 2014 and continue to improve my craft and skills.&lt;/p&gt; </content> </entry> <entry> <title type="html">Rainy Sunday Cookies</title> <link href="http://jmesnil.net/weblog/2013/09/29/rainy-sunday-cookies/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/09/29/rainy-sunday-cookies/</id> <updated>2013-09-29T14:25:44+00:00</updated> <published>2013-09-29T14:25:44+00:00</published> <content type="html"> &lt;p&gt;There is nothing better for a rainy sunday than cooking some cookies with my girlfriend and make pictures of them to play with my flash and reflectors.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-09-29-Cookies-26-900w.jpg, https://media.jmesnil.net/images/2013-09-29-Cookies-26-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-09-29-Cookies-26-480w.jpg, https://media.jmesnil.net/images/2013-09-29-Cookies-26-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-09-29-Cookies-26-480w.jpg, https://media.jmesnil.net/images/2013-09-29-Cookies-26-960w.jpg 2x&quot; alt=&quot;Rainy Sunday Cookies&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-09-29-Cookies-26-480w.jpg&quot; alt=&quot;Rainy Sunday Cookies&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Rainy Sunday Cookies &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/80&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/5.6&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;42&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;Let&#39;s eat them now!&lt;/p&gt; </content> </entry> <entry> <title type="html">stomp.js for node.js apps</title> <link href="http://jmesnil.net/weblog/2013/09/25/stompjs-for-nodejs/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/09/25/stompjs-for-nodejs/</id> <updated>2013-09-25T17:50:49+00:00</updated> <published>2013-09-25T17:50:49+00:00</published> <content type="html"> &lt;p&gt;&lt;a href=&quot;http://jmesnil.net/stomp-websocket/doc/&quot;&gt;stomp.js&lt;/a&gt; is a simple JavaScript library to send and receive &lt;a href=&quot;http://stomp.github.io&quot;&gt;STOMP&lt;/a&gt; messages from a Web browser using Web Sockets.&lt;/p&gt; &lt;p&gt;Today, I have released its &lt;a href=&quot;https://github.com/jmesnil/stomp-websocket/releases/tag/v2.3.0&quot;&gt;version 2.3.0&lt;/a&gt; that adds support for &lt;a href=&quot;http://nodejs.org&quot;&gt;node.js&lt;/a&gt;. This makes it possible to send and receive STOMP message from any node.js app by connecting to a STOMP broker on its TCP port (usually 61613) &lt;em&gt;or on its Web Socket.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;I have registered a npm package &lt;a href=&quot;https://npmjs.org/package/stompjs&quot;&gt;stompjs&lt;/a&gt; that can be installed by typing:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;npm install stompjs&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;and in the code, requiring the module:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;var Stomp = require(&#39;stompjs&#39;);&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;To connect to a STOMP broker over a TCP socket, use the &lt;code&gt;Stomp.overTCP(host, port)&lt;/code&gt; method:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;var client = Stomp.overTCP(&#39;localhost&#39;, 61613);&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;To connect to a STOMP broker over a Web Socket, use instead the &lt;code&gt;Stomp.overWS(url)&lt;/code&gt; method:&lt;/p&gt; &lt;pre&gt;&lt;code&gt;var client = Stomp.overWS(&#39;ws://localhost:61614/stomp&#39;);&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;Apart from this initialization, the STOMP API remains the same whether it is running in a Web browser or in node.js application.&lt;/p&gt; &lt;p&gt;A simple node.js app that sends and receives a STOMP message can be coded in a few lines:&lt;/p&gt; &lt;pre&gt;&lt;code class=&#39;javascript&#39;&gt;var Stomp = require(&#39;stompjs&#39;);&amp;#x000A;&amp;#x000A;// Use raw TCP sockets&amp;#x000A;var client = Stomp.overTCP(&#39;localhost&#39;, 61613);&amp;#x000A;// uncomment to print out the STOMP frames&amp;#x000A;// client.debug = console.log;&amp;#x000A;&amp;#x000A;client.connect(&#39;user&#39;, &#39;password&#39;, function(frame) {&amp;#x000A; console.log(&#39;connected to Stomp&#39;);&amp;#x000A;&amp;#x000A; client.subscribe(&#39;/queue/myqueue&#39;, function(message) {&amp;#x000A; console.log(&quot;received message &quot; + message.body);&amp;#x000A;&amp;#x000A; // once we get a message, the client disconnects&amp;#x000A; client.disconnect();&amp;#x000A; });&amp;#x000A; &amp;#x000A; console.log (&#39;sending a message&#39;);&amp;#x000A; client.send(&#39;/queue/myqueue&#39;, {}, &#39;Hello, node.js!&#39;);&amp;#x000A;});&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;In this example, the client connect to the STOMP broker on its TCP socket by calling &lt;code&gt;Stomp.overTCP(host, port)&lt;/code&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code class=&#39;javascript&#39;&gt;var client = Stomp.overTCP(&#39;localhost&#39;, 61613);&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;To connect on its Web Socket, you only need to change the creation of the client by calling instead &lt;code&gt;Stomp.overWS(url)&lt;/code&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code class=&#39;javascript&#39;&gt;var client = Stomp.overWS(&#39;ws://localhost:61614&#39;);&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;This means that if your code uses stomp.js, you can run the &lt;em&gt;same code&lt;/em&gt; in the Web browser or in node.js That may prove handy for testing...&lt;/p&gt; &lt;p&gt;Why another STOMP client for node.js when there are already &lt;a href=&quot;https://npmjs.org/search?q=STOMP&quot;&gt;a dozen&lt;/a&gt;?&lt;/p&gt; &lt;p&gt;I believe the code of stomp.js is already the best of them.&lt;/p&gt; &lt;p&gt;It is distributed by the major STOMP brokers (&lt;a href=&quot;http://activemq.apache.org/&quot;&gt;ActiveMQ&lt;/a&gt;, &lt;a href=&quot;http://activemq.apache.org/apollo/&quot;&gt;Apollo&lt;/a&gt;, &lt;a href=&quot;http://hornetq.org/&quot;&gt;HornetQ&lt;/a&gt;, and &lt;a href=&quot;http://www.rabbitmq.com/&quot;&gt;RabbitMQ&lt;/a&gt;), widely used, thoroughly tested and &lt;em&gt;&lt;a href=&quot;http://jmesnil.net/stomp-websocket/doc/&quot;&gt;documented&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;The STOMP protocol implementation is the same whether the client is running in a Web browser or in node.js. The only differences are the timers and the socket implementations (native Web Socket for Web browser, net.Socket for node.js). The socket implementation can still be customized and many users run it over &lt;a href=&quot;https://github.com/sockjs/sockjs-client&quot;&gt;SockJS&lt;/a&gt;&lt;/p&gt; &lt;p&gt;There are likely some corner cases to iron out but the main features (including heart-beating) should work as expected.&lt;/p&gt; &lt;p&gt;Note that the node.js support is done outside the &lt;a href=&quot;https://github.com/jmesnil/stomp-websocket/releases/download/v2.3.0/stomp.js&quot;&gt;stomp.js&lt;/a&gt; file. If you only need to use STOMP from the Web browser, this changes nothing: you only need that file (or its &lt;a href=&quot;https://github.com/jmesnil/stomp-websocket/releases/download/v2.3.0/stomp.min.js&quot;&gt;minified version&lt;/a&gt;).&lt;/p&gt; &lt;p&gt;Enjoy!&lt;/p&gt; </content> </entry> <entry> <title type="html">Guitarist at Park G&amp;uuml;ell, Barcelona</title> <link href="http://jmesnil.net/weblog/2013/09/16/guitarist-at-park-gell-barcelona/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/09/16/guitarist-at-park-gell-barcelona/</id> <updated>2013-09-16T14:07:35+00:00</updated> <published>2013-09-16T14:07:35+00:00</published> <content type="html"> &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-08-27-Barcelona-97-900w.jpg, https://media.jmesnil.net/images/2013-08-27-Barcelona-97-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-08-27-Barcelona-97-480w.jpg, https://media.jmesnil.net/images/2013-08-27-Barcelona-97-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-08-27-Barcelona-97-480w.jpg, https://media.jmesnil.net/images/2013-08-27-Barcelona-97-960w.jpg 2x&quot; alt=&quot;Guitarist at Park G&amp;amp;uuml;ell, Barcelona&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-08-27-Barcelona-97-480w.jpg&quot; alt=&quot;Guitarist at Park G&amp;amp;uuml;ell, Barcelona&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Guitarist at Park G&amp;uuml;ell, Barcelona &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/100&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/5&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;800&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;40&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; Teahupo&#39;o: Inside the Monster</title> <link href="http://vimeo.com/72377770" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/09/16/teahupoo-inside-the-monster/</id> <updated>2013-09-16T09:31:43+00:00</updated> <published>2013-09-16T09:31:43+00:00</published> <content type="html"> &lt;p&gt;Breathtaking documentary about Teahupo&#39;o surf spot:&lt;/p&gt; &lt;div class=&quot;video-wrapper&quot; style=&quot;width:900px&quot;&gt;&lt;div class=&quot;video&quot;&gt; &lt;iframe src=&quot;//player.vimeo.com/video/72377770&quot; width=&quot;900&quot; height=&quot;384&quot; frameborder=&quot;0&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt; &lt;/div&gt;&lt;/div&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2013/09/16/teahupoo-inside-the-monster/&quot; title=&quot;Permanent link to Teahupo&amp;#39;o: Inside the Monster&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> <entry> <title type="html">Writing a Book for O&#39;Reilly about Mobile &amp; Web Messaging</title> <link href="http://jmesnil.net/weblog/2013/09/09/writing-a-book-for-oreilly-about-mobile--web-messaging/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/09/09/writing-a-book-for-oreilly-about-mobile--web-messaging/</id> <updated>2013-09-09T13:39:35+00:00</updated> <published>2013-09-09T13:39:35+00:00</published> <content type="html"> &lt;p&gt;The title says it all: I&#39;ve agreed with &lt;a href=&quot;http://oreilly.com&quot;&gt;O&#39;Reilly Media&lt;/a&gt; to write a book about &lt;em&gt;Mobile and Web Messaging&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;Almost all my career has been spent developing messaging platforms or clients using messaging. The last few years, I have focused on messaging for Mobile and Web platforms.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;I added &lt;a href=&quot;http://stomp.github.io&quot;&gt;STOMP&lt;/a&gt; support to &lt;a href=&quot;http://www.jboss.org/hornetq/&quot;&gt;HornetQ&lt;/a&gt; to be able to send and receive messages from iOS and Android apps.&lt;/li&gt; &lt;li&gt;I wrote &lt;a href=&quot;http://jmesnil.net/stomp-websocket/doc/&quot;&gt;stomp.js&lt;/a&gt; to send and receive messages from HTML5 Web Browsers&lt;a id=&quot;fnr1-2013-09-09&quot; href=&quot;#fn1-2013-09-09&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;. This small library is now used by the main Open Source messaging brokers (&lt;a href=&quot;http://activemq.apache.org&quot;&gt;ActiveMQ&lt;/a&gt;, &lt;a href=&quot;http://activemq.apache.org/apollo/index.html&quot;&gt;Apollo&lt;/a&gt;, &lt;a href=&quot;http://www.rabbitmq.com/&quot;&gt;RabbitMQ&lt;/a&gt; in addition to HornetQ).&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;This book is the result of all this work and will help mobile and Web developers leverage messaging protocols in their applications.&lt;/p&gt; &lt;p&gt;I plan to introduce messaging protocols and write about STOMP (and most likely &lt;a href=&quot;http://mqtt.org&quot;&gt;MQTT&lt;/a&gt; too) in details. The book will come with examples for mobile platforms and Web browsers.&lt;/p&gt; &lt;p&gt;I have setup a web site at &lt;a href=&quot;http://mobile-web-messaging.net&quot;&gt;mobile-web-messaging.net&lt;/a&gt; to promote the book and will tweet about it at &lt;a href=&quot;https://twitter.com/mobilewebmsg&quot;&gt;@mobilewebmsg&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;The target release for the book is June 2014.&lt;/p&gt; &lt;p&gt;For a long time, I wanted to write a technical book and it is a chance to do it about an interesting subject and be published by the best editor for programming books. O&#39;Reilly agreed to publish the book under an Open Source license and the source and examples will be hosted on &lt;a href=&quot;https://github.com/mobile-web-messaging/book/&quot;&gt;GitHub&lt;/a&gt; (when I have some material to show).&lt;/p&gt; &lt;p&gt;This opportunity is only possible because my employer, &lt;a href=&quot;http://www.redhat.com&quot;&gt;Red Hat&lt;/a&gt;, allows me to spend some of my work time on this book. Red Hat is an awesome company to work for and we are &lt;a href=&quot;http://jobs.redhat.com&quot;&gt;hiring&lt;/a&gt;!&lt;/p&gt; &lt;p&gt;I am incredibly excited about this book and look forward to sharing some sample chapters. I just need to start writing them now! :)&lt;/p&gt; &lt;hr /&gt; &lt;ol&gt; &lt;li&gt;&lt;a id=&quot;fn1-2013-09-09&quot;&gt;&lt;/a&gt; That&#39;s why I just &lt;a href=&quot;/weblog/2013/09/03/stompjs-210-is-released/&quot;&gt;released a new version&lt;/a&gt; of stomp.js. I plan to write a chapter about it and found some shortcomings that I wanted to fix.&amp;nbsp;&lt;a href=&quot;#fnr1-2013-09-09&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt; </content> </entry> <entry> <title type="html">stomp.js 2.1.0 is Released</title> <link href="http://jmesnil.net/weblog/2013/09/03/stompjs-210-is-released/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/09/03/stompjs-210-is-released/</id> <updated>2013-09-03T17:29:21+00:00</updated> <published>2013-09-03T17:29:21+00:00</published> <content type="html"> &lt;p&gt;I have released a new version of &lt;a href=&quot;http://jmesnil.net/stomp-websocket/doc/&quot;&gt;Stomp over WebSockets&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;During my summer holidays, I have simplified its API to make it more &lt;em&gt;object-oriented&lt;/em&gt; instead of a simple translation of the protocol frames. The new API is backwards compatible &lt;em&gt;except for the susbcription change&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;The &lt;a href=&quot;http://jmesnil.net/stomp-websocket/doc/&quot;&gt;documentation&lt;/a&gt; has been updated to reflect the new API.&lt;/p&gt; &lt;p&gt;I also created a &lt;a href=&quot;https://github.com/jmesnil/stomp-websocket/releases/tag/v2.1.0&quot;&gt;2.1.0 release&lt;/a&gt; on GitHub to provide a well-known location to download &lt;a href=&quot;https://github.com/jmesnil/stomp-websocket/releases/download/v2.1.0/stomp.js&quot;&gt;stomp.js&lt;/a&gt; (and its &lt;a href=&quot;https://github.com/jmesnil/stomp-websocket/releases/download/v2.1.0/stomp.min.js&quot;&gt;minified version&lt;/a&gt;).&lt;/p&gt; &lt;h2&gt;Connection&lt;/h2&gt; &lt;p&gt;The &lt;code&gt;connect()&lt;/code&gt; method accepts different number of arguments to provide a simple API to use in most cases:&lt;/p&gt; &lt;pre&gt;&lt;code class=&#39;javascript&#39;&gt;client.connect(login, passcode, connectCallback);&amp;#x000A;client.connect(login, passcode, connectCallback, errorCallback);&amp;#x000A;client.connect(login, passcode, connectCallback, errorCallback, host);&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;where &lt;code&gt;login&lt;/code&gt;, &lt;code&gt;passcode&lt;/code&gt; are strings and &lt;code&gt;connectCallback&lt;/code&gt; and &lt;code&gt;errorCallback&lt;/code&gt; are functions (some brokers also require to pass a &lt;a href=&quot;http://stomp.github.io/stomp-specification-1.1.html#CONNECT_or_STOMP_Frame&quot;&gt;host&lt;/a&gt; String).&lt;/p&gt; &lt;p&gt;The &lt;code&gt;connect()&lt;/code&gt; method also accepts two other variants if you need to pass additional headers:&lt;/p&gt; &lt;pre&gt;&lt;code class=&#39;javascript&#39;&gt;client.connect(headers, connectCallback);&amp;#x000A;client.connect(headers, connectCallback, errorCallback);&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;where &lt;code&gt;header&lt;/code&gt; is a map and &lt;code&gt;connectCallback&lt;/code&gt; and &lt;code&gt;errorCallback&lt;/code&gt; are functions.&lt;/p&gt; &lt;p&gt;Please note that if you use these forms, you &lt;strong&gt;must&lt;/strong&gt; add the &lt;code&gt;login&lt;/code&gt;, &lt;code&gt;passcode&lt;/code&gt; (and eventually &lt;code&gt;host&lt;/code&gt;) headers yourself:&lt;/p&gt; &lt;pre&gt;&lt;code class=&#39;javascript&#39;&gt;var headers = {&amp;#x000A; login: &#39;mylogin&#39;,&amp;#x000A; passcode: &#39;mypasscode&#39;,&amp;#x000A; // additional header&amp;#x000A; &#39;client-id&#39;: &#39;my-client-id&#39;&amp;#x000A;};&amp;#x000A;client.connect(headers, connectCallback);&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;Acknowledgement&lt;/h2&gt; &lt;p&gt;The message objects passed to the &lt;code&gt;subscribe&lt;/code&gt; callback now have &lt;code&gt;ack()&lt;/code&gt; and &lt;code&gt;nack()&lt;/code&gt; methods to directly acknowledge (or not) the message.&lt;/p&gt; &lt;pre&gt;&lt;code class=&#39;javascript&#39;&gt;var sub = client.subscribe(&quot;/queue/test&quot;,&amp;#x000A; function(message) {&amp;#x000A; // do something with the message&amp;#x000A; ...&amp;#x000A; // and acknowledge it&amp;#x000A; message.ack();&amp;#x000A; },&amp;#x000A; {ack: &#39;client&#39;}&amp;#x000A;);&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;Unsubscription&lt;/h2&gt; &lt;p&gt;Instead of returning an id from &lt;code&gt;client.subscribe()&lt;/code&gt;, &lt;code&gt;subscribe()&lt;/code&gt; returns an object with an &lt;code&gt;id&lt;/code&gt; property corresponding to the subscription ID and an &lt;code&gt;unsubscribe()&lt;/code&gt; method.&lt;/p&gt; &lt;pre&gt;&lt;code class=&#39;javascript&#39;&gt;var subscription = client.subscribe(...);&amp;#x000A;...&amp;#x000A;subscription.unsubscribe();&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;Transaction&lt;/h2&gt; &lt;p&gt;The &lt;code&gt;begin()&lt;/code&gt; method returns a JavaScript object with &lt;code&gt;commit()&lt;/code&gt; and &lt;code&gt;abort()&lt;/code&gt; methods to complete the transaction.&lt;/p&gt; &lt;pre&gt;&lt;code class=&#39;javascript&#39;&gt;var tx = client.begin();&amp;#x000A;message.ack({ transaction: tx.id, receipt: &#39;my-receipt&#39; });&amp;#x000A;...&amp;#x000A;tx.commit(); // or tx.abort();&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;A transaction ID is automatically generated when calling &lt;code&gt;&#39;begin()&lt;/code&gt; and is available in the returned object&#39;s &lt;code&gt;id&lt;/code&gt; property.&lt;/p&gt; &lt;h2&gt;Miscellaneous changes and fixes&lt;/h2&gt; &lt;ul&gt; &lt;li&gt;&lt;p&gt;default onreceive method&lt;/p&gt; &lt;p&gt;When a subscription is automatically created on the broker-side, the received messages are discarded by the Stomp.client that find no matching callback for the subscription headers. To workaround that, the client can set a default &lt;code&gt;onreceive&lt;/code&gt; callback that will be called if no matching subscription is found.&lt;/p&gt; &lt;p&gt;This is required to support &lt;a href=&quot;http://www.rabbitmq.com/stomp.html#d.tqd&quot;&gt;RabbitMQ temporary queue destinations&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt; &lt;li&gt;&lt;p&gt;By default, debug messages are now written in &lt;code&gt;window.console&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt; &lt;li&gt;&lt;p&gt;STOMP can now be used from a &lt;em&gt;WebWorker&lt;/em&gt; (an example shows how to use it).&lt;/p&gt;&lt;/li&gt; &lt;li&gt;&lt;p&gt;STOMP frame fragmentation&lt;/p&gt; &lt;p&gt;If the STOMP frames are big to send on a single WebSocket frame, some web server may have trouble process them. It is now possible to split a STOMP frame on multiple Web Socket frames by configuring the &lt;code&gt;client.maxWebSocketFrameSize&lt;/code&gt; (in bytes). If the STOMP frame is bigger than this size, it will be send over multiple Web Socket frames (default is &lt;code&gt;16KiB&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt; &lt;li&gt;&lt;p&gt;use the 1st value for repeated headers&lt;/p&gt; &lt;p&gt;Stomp.js was keeping the last value of &lt;a href=&quot;http://stomp.github.io/stomp-specification-1.2.html#Repeated_Header_Entrie&quot;&gt;repeated headers&lt;/a&gt;. This has been fixed according to the specification to take the &lt;strong&gt;1st&lt;/strong&gt; value of repeated headers.&lt;/p&gt;&lt;/li&gt; &lt;li&gt;&lt;p&gt;fix generation of timestamp on IE8&lt;/p&gt;&lt;/li&gt; &lt;/ul&gt; </content> </entry> <entry> <title type="html">Sunset At Saint-Malo</title> <link href="http://jmesnil.net/weblog/2013/08/08/sunset-at-saint-malo/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/08/08/sunset-at-saint-malo/</id> <updated>2013-08-08T13:45:19+00:00</updated> <published>2013-08-08T13:45:19+00:00</published> <content type="html"> &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-07-09-Bretagne-77-900w.jpg, https://media.jmesnil.net/images/2013-07-09-Bretagne-77-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-07-09-Bretagne-77-480w.jpg, https://media.jmesnil.net/images/2013-07-09-Bretagne-77-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-07-09-Bretagne-77-480w.jpg, https://media.jmesnil.net/images/2013-07-09-Bretagne-77-960w.jpg 2x&quot; alt=&quot;Sunset At Saint-Malo&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-07-09-Bretagne-77-480w.jpg&quot; alt=&quot;Sunset At Saint-Malo&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;&lt;a href=&quot;http://goo.gl/maps/XXkw3&quot;&gt;&lt;i class=&quot;fa fa-map-marker&quot;&gt;&lt;/i&gt;&lt;/a&gt;&amp;nbsp;Sunset At Saint-Malo (France) &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/250&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;100&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;58&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; </content> </entry> <entry> <title type="html">Velours de Mangue</title> <link href="http://jmesnil.net/weblog/2013/08/05/velours-de-mangue/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/08/05/velours-de-mangue/</id> <updated>2013-08-05T08:41:09+00:00</updated> <published>2013-08-05T08:41:09+00:00</published> <content type="html"> &lt;p&gt;We bought a siphon for cooking some time ago and are having fun with it to prepare desserts and starters (we made a &lt;em&gt;mousse de foie gras&lt;/em&gt; that was awesome). Yesterday, we prepared a &lt;em&gt;velours de mangue&lt;/em&gt; (velvet of mango).&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-08-04-Velours+de+Mangue-30-900w.jpg, https://media.jmesnil.net/images/2013-08-04-Velours+de+Mangue-30-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-08-04-Velours+de+Mangue-30-480w.jpg, https://media.jmesnil.net/images/2013-08-04-Velours+de+Mangue-30-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-08-04-Velours+de+Mangue-30-480w.jpg, https://media.jmesnil.net/images/2013-08-04-Velours+de+Mangue-30-960w.jpg 2x&quot; alt=&quot;Velours de Mangue&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-08-04-Velours+de+Mangue-30-480w.jpg&quot; alt=&quot;Velours de Mangue&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Velours de Mangue &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/60&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/2.8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;100&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;35&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; </content> </entry> <entry> <title type="html">JMS 2.0: Shared Subscription</title> <link href="http://jmesnil.net/weblog/2013/06/27/jms-20-shared-subscription/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/06/27/jms-20-shared-subscription/</id> <updated>2013-06-27T17:14:26+00:00</updated> <published>2013-06-27T17:14:26+00:00</published> <content type="html"> &lt;p&gt;JMS 2.0 has been released a few weeks ago. We are working hard to support it in &lt;a href=&quot;http://hornetq.org/&quot;&gt;HornetQ&lt;/a&gt; and &lt;a href=&quot;http://wildfly.org&quot;&gt;WildFly&lt;/a&gt; and I plan to write a few articles about it.&lt;/p&gt; &lt;p&gt;The main features are described on Oracle Web site in &lt;a href=&quot;http://www.oracle.com/technetwork/articles/java/jms20-1947669.html&quot;&gt;What&#39;s New in JMS 2.0, Part One: Ease of Use&lt;/a&gt; and &lt;a href=&quot;http://www.oracle.com/technetwork/articles/java/jms2messaging-1954190.html&quot;&gt;Part Two: New Messaging Features&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;One of the most important new features is &lt;em&gt;Shared Subscription&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;Let&#39;s assume you are using a topic to send messages. There are several components subscribed to this topic that are processing the messages in different fashion (for example to process jobs A and B).&lt;/p&gt; &lt;p&gt;When a message &lt;code&gt;M&lt;/code&gt; is sent to the topic, all consumers subscribed to the topic receive it:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;no-highlight&quot;&gt; M +--------------+&amp;#x000A; ---&gt; | consumer CA1 | &lt; a consumer for the job A &gt;&amp;#x000A; +----------+ M +-------+ / +--------------+&amp;#x000A; | producer | ---&gt; | topic | &amp;#x000A; +----------+ +-------+ \ M +--------------+&amp;#x000A; ---&gt; | consumer CB1 | &lt; a consumer for the job B &gt;&amp;#x000A; +--------------+&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;The consumer CB1 is subscribed to the topic. Every time, it receives a message, it processes the job B.&lt;/p&gt; &lt;p&gt;Unfortunately, this job is time-consuming and we would like to scale it out by having several consumers for the job B running on different machines.&lt;/p&gt; &lt;p&gt;We can &lt;em&gt;not&lt;/em&gt; have several consumers on the topic for this job, otherwise they would all receive copies of the same message and process it several times. What we need is a &lt;em&gt;set&lt;/em&gt; of consumers that receives a single message from the topic amongst them.&lt;/p&gt; &lt;p&gt;If the component is running inside a Java EE application server, you can use a Message-Drive Bean for that. If the component is a Java SE application, you are out of luck.&lt;/p&gt; &lt;p&gt;Before JMS 2.0, each messaging brokers has different ways to provide this feature.&lt;/p&gt; &lt;p&gt;With &lt;a href=&quot;http://hornetq.org/&quot;&gt;HornetQ&lt;/a&gt;, the workaround is to use a &lt;a href=&quot;http://docs.jboss.org/hornetq/2.3.0.Final/docs/user-manual/html/diverts.html&quot;&gt;divert&lt;/a&gt;:&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;Diverts allow you to transparently divert messages routed to one address to some other address, without making any changes to any client application logic.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;We use a divert to &lt;em&gt;route&lt;/em&gt; the messages sent to the topic to another &lt;em&gt;queue&lt;/em&gt; (let&#39;s called it &lt;code&gt;Queue_B&lt;/code&gt; since it&#39;s for the processing job B). Everytime a message is sent to the topic, a copy is also routed to the queue. Our divert is &lt;em&gt;non-exclusive&lt;/em&gt; since we want it to still be received by the topic consumers.&lt;/p&gt; &lt;p&gt;We can then create as many consumers we want for &lt;code&gt;Queue_B&lt;/code&gt;. Since this destination is a queue, only one of them will receive a message that was initially sent to the topic:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;no-highlight&quot;&gt; M +--------------+&amp;#x000A; ---&gt; | consumer CA1 |&amp;#x000A; +----------+ M +-------+ / +--------------+&amp;#x000A; | producer | ---&gt; | topic | &amp;#x000A; +----------+ +-------+ &amp;#x000A; \ +--------------+&amp;#x000A;  \ M ---&gt; | consumer CB1 |&amp;#x000A; divert \ / +--------------+&amp;#x000A; \ +---------+ / +--------------+ &amp;#x000A; | Queue_B | -- ---&gt; | consumer CB2 |&amp;#x000A; +---------+ \ +--------------+&amp;#x000A; \ M +--------------+&amp;#x000A; ---&gt; | consumer CB3 |&amp;#x000A; +--------------+&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;Among CB1, CB2 and CB3, only CB3 received the message sent to the topic.&lt;/p&gt; &lt;p&gt;There are still many shortcomings of using diverts (or similar features) to share consumers of a topic.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;for each set of shared consumers, a system administrator must create and administrate on the server one more divert and one more queue.&lt;/li&gt; &lt;li&gt;the shared consumers are no longer consuming from the original topic but from a specific queue. That makes the messaging topology more complex to setup and configure in the client applications.&lt;/li&gt; &lt;li&gt;the management of the messaging system becomes also more complex: there is no way to know how many subscribers are &quot;really&quot; listening to the topic, this information is lost when messages are routed by the divert.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;Enter JMS 2.0 and its &quot;shared subscription&quot;.&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;A non-durable shared subscription is used by a client which needs to be able to share the work of receiving messages from a topic subscription amongst multiple consumers. A non-durable shared subscription may therefore have more than one consumer. Each message from the subscription will be delivered to only one of the consumers on that subscription.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The basic idea behing sharing a subscription is to have a set of consumers (identified by a shared subscription name) receiving &lt;em&gt;exclusively&lt;/em&gt; a message from a topic.&lt;/p&gt; &lt;p&gt;That solves all the issues we originally had in a standard fashion. We can now create many shared consumers with the shared subscription name &lt;code&gt;&amp;lt;&amp;lt; sub B &amp;gt;&amp;gt;&lt;/code&gt; to have them process messages for the job B and scale out nicely:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;no-highlight&quot;&gt; M +--------------+&amp;#x000A; ----------------&gt; | consumer CA1 |&amp;#x000A; / +--------------+&amp;#x000A; / +--------------+&amp;#x000A; +----------+ M +-------+ / ---&gt; | consumer CB1 |&amp;#x000A; | producer | ---&gt; | topic | / +--------------+&amp;#x000A; +----------+ +-------+ \ / M +--------------+&amp;#x000A; &lt;&lt; sub B &gt;&gt; -- ---&gt; | consumer CB2 |&amp;#x000A; \ +--------------+&amp;#x000A; \ +--------------+&amp;#x000A; ---&gt; | consumer CB3 |&amp;#x000A; +--------------+&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;Among the shared consumers CB1, CB2 and CB3, only CB2 received the message sent to the topic.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;all our consumers are directly consuming from the topic&lt;/li&gt; &lt;li&gt;there are no additional resources to configure or administrate on the server&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;The JMS 2.0 API adds new methods to &lt;a href=&quot;https://jms-spec.java.net/2.0/apidocs/javax/jms/JMSContext.html#createSharedConsumer(javax.jms.Topic,%20java.lang.String)&quot;&gt;create &lt;em&gt;shared consumer&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;java&quot;&gt; JMSContext.createSharedConsumer(Topic topic, String sharedSubscriptionName)&amp;#x000A; JMSContext.createSharedConsumer(Topic topic, String sharedSubscriptionName, String messageSelector)&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;It is also possible to create &lt;em&gt;shared durable consumers&lt;/em&gt;:&lt;/p&gt; &lt;pre&gt;&lt;code class=&quot;java&quot;&gt; JMSContext.createSharedDurableConsumer(Topic topic, String name)&amp;#x000A; JMSContext.createSharedDurableConsumer(Topic topic, String name, String messageSelector)&amp;#x000A;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;Sharability and durability of subscriptions are two orthogonal notions and all the combination are possible:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;a &lt;em&gt;unshared non-durable&lt;/em&gt; subscription can only have one consumer that will not receive messages sent while its consumer was offline&lt;/li&gt; &lt;li&gt;a &lt;em&gt;unshared durable&lt;/em&gt; subscription can only have one consumer that will receive the messages sent while its consumer was offline&lt;/li&gt; &lt;li&gt;a &lt;em&gt;shared non-durable&lt;/em&gt; subscription can have many consumers that will not receive messages sent while all consumers were offline.&lt;/li&gt; &lt;li&gt;a &lt;em&gt;shared durable&lt;/em&gt; subscription can have many consumers that will not receive the messages sent while all consumers were offline.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;JMS 2.0 is an incremental update to JMS that should simplify any Java application using messages. Shared subscription is one of this interesting new features.&lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; Tim Duncan &amp;mdash; The Big Fundamental</title> <link href="http://nbcsports.msnbc.com/id/52056813/ns/sports-nba/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/06/03/tim-duncan---the-big-fundamental/</id> <updated>2013-06-03T17:53:14+00:00</updated> <published>2013-06-03T17:53:14+00:00</published> <content type="html"> &lt;p&gt;Insightful portrait of Tim Duncan on the cusp of his 5th NBA finals (he won his first fours):&lt;/p&gt; &lt;blockquote&gt;&lt;p&gt;Sometimes people will mention the swimming when trying to pinpoint the origin of Duncan’s remarkable discipline and relentless consistency. Duncan swam until he was 14 and seemed on a path toward the Olympics like his sister, Tricia. That was when Hurricane Hugo roared through the Island and wrecked the swimming pool. More, that was the year his mother, Ione, died of cancer. She had been his greatest fan, the loudest cheers at the pool, the voice inside his head. He would talk about the little nursery rhyme that she would repeat to him over and over and over …&lt;/p&gt; &lt;p&gt;&lt;em&gt;Good, better, best&lt;/em&gt;&lt;br/&gt; &lt;em&gt;Never let it rest&lt;/em&gt;&lt;br/&gt; &lt;em&gt;Until your good is better&lt;/em&gt;&lt;br/&gt; &lt;em&gt;And your better is your best&lt;/em&gt;&lt;/p&gt; &lt;p&gt;You can’t help but think that if you cut Tim Duncan open, those words would be etched on his heart.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;There has never been a basket-ball player so consistent for the whole span of his career (&lt;a href=&quot;http://www.basketball-reference.com/players/d/duncati01.html#per_minute::none&quot;&gt;stats per 36 minutes&lt;/a&gt;):&lt;/p&gt; &lt;ul&gt; &lt;li&gt;1st year - 21 year old, 19.4 points, 11 rebounds, 2.5 assists, 2.4 blocks, 57.7 true shooting %&lt;/li&gt; &lt;li&gt;7th year - 27 year old, 21.9 points, 12.2 rebounds, 3.0 assists, 2.6 blocks, 53.4 true shooting %&lt;/li&gt; &lt;li&gt;17th year - 36 year old, 21.3 points, 11.9 rebounds, 3.2 assists, 3.2, blocks, 55.4 true shooting %&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;I am rooting for the spurs for these finals! #GoSpursGo&lt;/p&gt; &lt;p&gt;(via &lt;a href=&quot;http://kottke.org/13/06/the-big-fundamental&quot;&gt;kottke&lt;/a&gt;)&lt;/p&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2013/06/03/tim-duncan---the-big-fundamental/&quot; title=&quot;Permanent link to Tim Duncan &amp;mdash; The Big Fundamental&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> <entry> <title type="html">Uriage Cabriolet Classic</title> <link href="http://jmesnil.net/weblog/2013/05/27/uriage-cabriolet-classic/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/05/27/uriage-cabriolet-classic/</id> <updated>2013-05-27T14:29:10+00:00</updated> <published>2013-05-27T14:29:10+00:00</published> <content type="html"> &lt;p&gt;This sunday was held the 2013 edition of &lt;em&gt;Uriage Cabriolet Classic&lt;/em&gt;, a large gathering of classic (and more recent) cars.&lt;/p&gt; &lt;p&gt;I am not a &lt;em&gt;connaisseur&lt;/em&gt; of cars but I can recognize a beautiful one when I see it. I really enjoy the attention to details of these cars and the love and care of their owners (the engines were all shining!).&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-1-900w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-1-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-1-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-1-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-1-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-1-960w.jpg 2x&quot; alt=&quot;Leather strap for car hood&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-1-480w.jpg&quot; alt=&quot;Leather strap for car hood&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Leather strap for car hood &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/1250&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/5&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;46&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-22-900w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-22-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-22-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-22-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-22-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-22-960w.jpg 2x&quot; alt=&quot;Star on car hood&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-22-480w.jpg&quot; alt=&quot;Star on car hood&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Star on car hood &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/2000&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/5.3&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;200&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;58&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-39-900w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-39-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-39-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-39-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-39-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-39-960w.jpg 2x&quot; alt=&quot;Car Engine&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-39-480w.jpg&quot; alt=&quot;Car Engine&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Car Engine &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/250&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/5.6&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;200&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;28&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;This gathering is an opportunity to appreciate all the shapes and colours of cars. Even the most modest cars look fantastic with out of the ordinary colours.&lt;/p&gt; &lt;p&gt;&lt;figure class=&quot;portrait&quot;&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-12-900w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-12-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-12-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-12-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-12-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-12-960w.jpg 2x&quot; alt=&quot;Citro&amp;amp;euml;n 2 CV&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-12-480w.jpg&quot; alt=&quot;Citro&amp;amp;euml;n 2 CV&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Citro&amp;euml;n 2 CV &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/400&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;78&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;&lt;figure class=&quot;portrait&quot;&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-7-900w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-7-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-7-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-7-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-7-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-7-960w.jpg 2x&quot; alt=&quot;Citro&amp;amp;euml;n 2 CV&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-7-480w.jpg&quot; alt=&quot;Citro&amp;amp;euml;n 2 CV&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Citro&amp;euml;n 2 CV &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/60&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/22&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;85&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;We were lucky having a beautiful weather for the gathering and enjoyed the familial atmosphere.&lt;/p&gt; &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-30-900w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-30-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-30-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-30-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-30-480w.jpg, https://media.jmesnil.net/images/2013-05-26-uriage-30-960w.jpg 2x&quot; alt=&quot;Blue child &amp;amp;amp; car&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-05-26-uriage-30-480w.jpg&quot; alt=&quot;Blue child &amp;amp;amp; car&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;Blue child &amp;amp; car &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt; &lt;/figure&gt;&lt;/p&gt; </content> </entry> <entry> <title type="html">Tuscany Countryside</title> <link href="http://jmesnil.net/weblog/2013/05/13/tuscany-countryside/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/05/13/tuscany-countryside/</id> <updated>2013-05-13T17:53:53+00:00</updated> <published>2013-05-13T17:53:53+00:00</published> <content type="html"> &lt;p&gt;&lt;figure&gt; &lt;picture&gt; &lt;!--[if IE 9]&gt;&lt;video style=&quot;display: none;&quot;&gt;&lt;![endif]--&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-03-tuscany-780-900w.jpg, https://media.jmesnil.net/images/2013-05-03-tuscany-780-1800w.jpg 2x&quot; media=&quot;(min-width: 768px)&quot;&gt; &lt;source srcset=&quot;https://media.jmesnil.net/images/2013-05-03-tuscany-780-480w.jpg, https://media.jmesnil.net/images/2013-05-03-tuscany-780-960w.jpg 2x&quot;&gt; &lt;!--[if IE 9]&gt;&lt;/video&gt;&lt;![endif]--&gt; &lt;img srcset=&quot;https://media.jmesnil.net/images/2013-05-03-tuscany-780-480w.jpg, https://media.jmesnil.net/images/2013-05-03-tuscany-780-960w.jpg 2x&quot; alt=&quot;Tuscany Countryside&quot;&gt; &lt;/picture&gt; &lt;noscript&gt; &lt;img src=&quot;https://media.jmesnil.net/images/2013-05-03-tuscany-780-480w.jpg&quot; alt=&quot;Tuscany Countryside&quot;&gt; &lt;/noscript&gt; &lt;figcaption&gt;&lt;a href=&quot;http://goo.gl/maps/NW7uP&quot;&gt;&lt;i class=&quot;fa fa-map-marker&quot;&gt;&lt;/i&gt;&lt;/a&gt;&amp;nbsp;Tuscany Countryside &lt;span class=&quot;copyright&quot;&gt;&amp;copy;&amp;nbsp;Jeff&amp;nbsp;Mesnil&lt;/span&gt; &lt;/figcaption&gt;&lt;/p&gt; &lt;div class=&quot;metadata&quot;&gt; &lt;i class=&quot;fa fa-camera&quot;&gt;&lt;/i&gt; &lt;span class=&quot;speed&quot;&gt;1/100&lt;/span&gt; &lt;span class=&quot;aperture&quot;&gt;&lt;i&gt;&amp;#402;&lt;/i&gt;/8&lt;/span&gt; &lt;span class=&quot;iso&quot;&gt;ISO&amp;nbsp;400&lt;/span&gt; &lt;span class=&quot;focal-length&quot;&gt;38&amp;nbsp;mm&lt;/span&gt; &lt;/div&gt; &lt;p&gt;&lt;/figure&gt;&lt;/p&gt; &lt;p&gt;My girlfriend and I spent one week in Tuscany. We loved every moment of it.&lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; David duChemin Reviews the Fuji XE-1</title> <link href="http://davidduchemin.com/2013/05/italy-and-the-fuji-xe-1/" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/05/13/david-duchemin-reviews-the-fuji-xe-1/</id> <updated>2013-05-13T16:15:19+00:00</updated> <published>2013-05-13T16:15:19+00:00</published> <content type="html"> &lt;p&gt;Spoiler: he loves the camera and, unsurprisingly, makes beautiful pictures with it.&lt;/p&gt; &lt;p&gt;I bought his book, &lt;a href=&quot;http://www.amazon.com/The-Print-Process-Compelling-Photographs/dp/0321842766/&quot;&gt;The Print and the Process&lt;/a&gt;, this week-end. It is a beautifully crafted book composed of 4 sections, Venic, Iceland, Kenya, and Antarctica providing a variety of scenes (it&#39;s mostly landscapes and portraits though, it&#39;s a David duChemin&#39;s book after all :) Each section is composed of a set of 20-30 images without any text that helps appreciate the flow of pictures without any interruption. At the end of each section, there is a text for each images where the author describes what his intent or feeling was when he took the picture.&lt;/p&gt; &lt;p&gt;The book is bound along the short edge in landscape mode. This design makes the beautiful landscape images really stand out.&lt;/p&gt; &lt;p&gt;Beautiful book, gorgeous photos and instructive reading. Heartily recommended.&lt;/p&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2013/05/13/david-duchemin-reviews-the-fuji-xe-1/&quot; title=&quot;Permanent link to David duChemin Reviews the Fuji XE-1&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; WildFly Application Server</title> <link href="http://wildfly.org" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/04/22/wildfly-application-server/</id> <updated>2013-04-22T11:28:58+00:00</updated> <published>2013-04-22T11:28:58+00:00</published> <content type="html"> &lt;p&gt;After a long wait, it was announced at &lt;a href=&quot;https://community.jboss.org/blogs/mark.little/2013/04/19/and-the-winner-is&quot;&gt;JUDcon Brazil&lt;/a&gt; that the JBoss Application Server has been renamed and is now &lt;a href=&quot;http://wildfly.org&quot;&gt;WildFly&lt;/a&gt;&lt;a id=&quot;fnr1-2013-04-22&quot; href=&quot;#fn1-2013-04-22&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;.&lt;/p&gt; &lt;div class=&quot;centered&quot; style=&quot;max-width: 800px&quot;&gt; &lt;a href=&quot;http://wildfly.org&quot;&gt; &lt;img style=&quot;width: 100%;&quot; src=&quot;http://www.wildfly.org/images/splash_wildflylogo.png&quot; title=&quot;WildFly Application Server&quot;&gt; &lt;/a&gt; &lt;/div&gt; &lt;p&gt;Onwards with WildFly!&lt;/p&gt; &lt;hr /&gt; &lt;ol&gt; &lt;li&gt;&lt;a id=&quot;fn1-2013-04-22&quot;&gt;&lt;/a&gt; With a upper case F, no relation with the &lt;a href=&quot;http://transformers.wikia.com/wiki/Wildfly&quot;&gt;Wildfly transformer&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnr1-2013-04-22&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2013/04/22/wildfly-application-server/&quot; title=&quot;Permanent link to WildFly Application Server&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> <entry> <title type="html">&amp;#8680; Yahoo! Weather App</title> <link href="https://itunes.apple.com/us/app/yahoo!-weather/id628677149?ls=1&amp;mt=8" rel="alternate" type="text/html"/> <id>http://jmesnil.net/weblog/2013/04/19/yahoo-weather-app/</id> <updated>2013-04-19T10:32:16+00:00</updated> <published>2013-04-19T10:32:16+00:00</published> <content type="html"> &lt;p&gt;The new weather app from Yahoo! looks gorgeous and is a pleasure to use with an intuitive navigation.&lt;/p&gt; &lt;div class=&quot;markdown-wrapper&quot;&gt; &lt;figure style=&quot;max-width: 320px&quot;&gt; &lt;a href=&quot;https://itunes.apple.com/us/app/yahoo!-weather/id628677149?ls=1&amp;mt=8&quot;&gt; &lt;img src=&quot;http://a1561.phobos.apple.com/us/r1000/113/Purple/v4/c8/1f/04/c81f044f-ae0c-1a93-fff7-0b6f35001b4d/mzl.svpuhnht.320x480-75.jpg&quot; alt=&quot;ahoo! Weather App&quot; height=&quot;480&quot; width=&quot;320&quot;&gt; &lt;/a&gt; &lt;figcaption&gt;Yahoo! Weather App&lt;/figcaption&gt; &lt;/figure&gt; &lt;/div&gt; &lt;p&gt;The photos are geolocated and taken from &lt;a href=&quot;http://www.flickr.com/groups/projectweather&quot;&gt;Flickr photo pool&lt;/a&gt;. That&#39;s a great way to leverage Flickr.&lt;/p&gt; &lt;p&gt;With the updated &lt;a href=&quot;https://itunes.apple.com/us/app/flickr/id328407587?mt=8&quot;&gt;Flickr app&lt;/a&gt; and this new weather app, Marissa Meyer is on the right track to hold her promise to make Flick awesome again.&lt;/p&gt; &lt;p&gt; &lt;a href=&quot;http://jmesnil.net/weblog/2013/04/19/yahoo-weather-app/&quot; title=&quot;Permanent link to Yahoo! Weather App&quot;&gt;&amp;#9873;&lt;/a&gt; &lt;/p&gt; </content> </entry> </feed>