tag:blogger.com,1999:blog-31547048027407260312024-02-19T06:59:43.391+01:00Ladstattrladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.comBlogger73125tag:blogger.com,1999:blog-3154704802740726031.post-27830361903653287362023-03-10T16:13:00.000+01:002023-03-10T16:13:28.013+01:00Deploying LogoRRR to Apple's App Store using JPackage<p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXMH8d8Bg2gllgG3BX-OsboeHAU8NTVT8aVX59O7e9SLHX_rkoqwcwO6gK1OKQ63Lu2ssnMBnovX9WcZivzbev1XK0N9dQHaK1UR-imPqDXbgv8TY6GI-cruPInq3rJgoKpx5QfQ73ihp-GUu2lOYKt7T65kJ5Jpx-IWgJttE2WFimL9m4pmJYCANT1A/s1024/DALL%C2%B7E%202023-03-10%2016.10.10%20-%20market%20place,%20in%20center%20a%20holy%20grail,%20audience%20in%20awe,%20retro%20design,%20pixel%20art,%20800%20x%20600,%20cinematic,%20light%20from%20behind,%20mountains%20on%20the%20horizon.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1024" data-original-width="1024" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXMH8d8Bg2gllgG3BX-OsboeHAU8NTVT8aVX59O7e9SLHX_rkoqwcwO6gK1OKQ63Lu2ssnMBnovX9WcZivzbev1XK0N9dQHaK1UR-imPqDXbgv8TY6GI-cruPInq3rJgoKpx5QfQ73ihp-GUu2lOYKt7T65kJ5Jpx-IWgJttE2WFimL9m4pmJYCANT1A/s320/DALL%C2%B7E%202023-03-10%2016.10.10%20-%20market%20place,%20in%20center%20a%20holy%20grail,%20audience%20in%20awe,%20retro%20design,%20pixel%20art,%20800%20x%20600,%20cinematic,%20light%20from%20behind,%20mountains%20on%20the%20horizon.png" width="320" /></a></div><span style="caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space: pre-wrap;"><p><span style="caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space: pre-wrap;"><br /></span></p>From the outset of this project, I had a strong desire to deploy </span><a href="https://www.logorrr.app/" style="caret-color: rgb(55, 65, 81); font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space: pre-wrap;" target="_blank">LogoRRR</a><span style="caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space: pre-wrap;"> to the App Store. Despite my best efforts, I was unable to achieve this goal last year. However, with the release of version 23.2.0, I </span><a href="https://apps.apple.com/at/app/logorrr/id1583786769?l=en&mt=12" style="caret-color: rgb(55, 65, 81); font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space: pre-wrap;">reached my goal and put LogoRRR into the store</a><span style="caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space: pre-wrap;">. In hindsight, the process was easier than I anticipated.</span><p></p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space: pre-wrap;">Initially, I tried to call the necessary tools directly to create the pkg, and used jlink to create temporary app images, but this proved unnecessary. Instead, I used <a href="https://docs.oracle.com/en/java/javase/19/docs/specs/man/jpackage.html">jpackage</a>, which was able to assemble everything I needed in its latest release. I encourage you to use my findings as a starting point for delivering your application to a global audience.</p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space: pre-wrap;">Here's a quick outline of my approach:</p><span style="caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space: pre-wrap;"><ul style="text-align: left;"><li>I used JavaFX as the GUI technology and Scala as the implementation language.</li><li>Maven was used as the build tool.</li><li>JPackage was used to create a pkg suitable for deployment to the App Store</li><li><a href="https://github.com/rladstaetter/LogoRRR/">Source code is available at github</a></li></ul></span><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space: pre-wrap;">To dive a little deeper into the deployment using JPackage:</p><span style="caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space: pre-wrap;"><ul style="text-align: left;"><li>I circumvented the modular JavaFX approach by using my own Launcher class.</li><li>I put everything application-related in a shaded jar.</li><li>I created a libs directory for everything else.</li><li>I created the necessary Entitlements and plist files for JPackage.</li><li>To keep things clean, I used an 'options' file for JPackage.</li></ul></span><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space: pre-wrap;">To verify my package, I used <a href="https://apps.apple.com/at/app/transporter/id1450874784?l=en&mt=12">Apple's Transporter App</a>, which gave me a quick response on any missing files in my package.</p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space: pre-wrap;">One key technique to get a valid plist file was to create a stub project in XCode to investigate the syntax required for a successful deployment.</p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; caret-color: rgb(55, 65, 81); color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px 0px; white-space: pre-wrap;">In conclusion, deploying your application to the App Store using JPackage is a viable option. With careful attention to the steps outlined above, you too can achieve success in reaching a global audience.</p>rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-59137357185468135342022-10-02T11:45:00.007+02:002022-10-02T12:13:53.370+02:00 A JavaFX Fanboy forgets about his Parallels subscription - what happens next?<p><span style="font-family: "Helvetica Neue"; font-size: 13px;">Recently, I was informed by a friendly message on my phone that the yearly subscription fee for <a href="https://www.parallels.com/eu/">Parallels - THE best way to run windows on your mac</a> - was already sucked away from my bank account.</span><span style="font-family: "Helvetica Neue"; font-size: 13px;"> </span></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhVwD-dB9HKW9geRWCIqv4JRe8PN1-3zMwIQ2vh3i0FySENSe-Ha3riYS3RnITEU7VdrKP0eY8riKibCbANDdtF4Ubg84BNZee7JMR6MVkri6sdJMQ45pkI1QvNzLh25BhLLGL8Tplk1gJxm37zqzXzCcdzz39glsrTwc6tSCJV5AiBlGjooGKvab_Uw/s600/DALL%C2%B7E%202022-10-02%2011.17.13%20-%20an%20computer%20nerd%20fighting%20dragons%20and%20obstacles,%20bright,%20mountains%20behind,%20pixel%20art.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhVwD-dB9HKW9geRWCIqv4JRe8PN1-3zMwIQ2vh3i0FySENSe-Ha3riYS3RnITEU7VdrKP0eY8riKibCbANDdtF4Ubg84BNZee7JMR6MVkri6sdJMQ45pkI1QvNzLh25BhLLGL8Tplk1gJxm37zqzXzCcdzz39glsrTwc6tSCJV5AiBlGjooGKvab_Uw/s320/DALL%C2%B7E%202022-10-02%2011.17.13%20-%20an%20computer%20nerd%20fighting%20dragons%20and%20obstacles,%20bright,%20mountains%20behind,%20pixel%20art.png" width="320" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">I rarely use it, in fact I didn’t start it on my M1 Mac ever. </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Well, screw it! I recently brushed up <a href="https://github.com/rladstaetter/LogoRRR/issues/101" target="_blank">LogoRRR's UI</a> and was curious how the changes would look like on windows. </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">As such I went to the Parallels website, and in no time I had setup their product fresh on my computer. First thing I was informed was that I could throw away my old Windows Image which I transferred from my old macbook. The architectures wouldn't match, I was out of luck.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Great. Well as said before I didn’t really miss it too much and decided to proceed. Install everything from scratch. How to get a new Windows? Very conveniently, I just clicked “next”. </p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">There you go, in no time I had a brand new Windows for aarch64 running on my virtual PC! Thanks to my internet connection and I could solve my first world problems in no time here.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">My quest continued. </p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Only after having installed <a href="https://www.jetbrains.com/toolbox-app/">IntelliJ</a> and <a href="https://www.azul.com/downloads/?version=java-19-sts&os=windows&architecture=arm-64-bit&package=jdk">a proper JDK</a> on this virtual machine and after a clone of LogoRRR resided on my virtual HD I realised that there was no build for Windows and aarch64 for JavaFX base libraries available. </p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeDpA4ARwvjzg8kJ6oczqgZ6tgcXa53G4o58SZ_Ey7bltiMw0-z8glqhRQtX-aE6rQmkkwkcwdx0PTqLnyt3-sPkwY5MWVyE0Ndc7LqLhvN0j-LVQJwApXPnI-1Tjk-GIJkOV6ZLfabZj9-FCBtAIVCXV2n9KbIDdG_aIV1INpze078s4mm1dya5Rcvw/s555/Screenshot%202022-10-02%20at%2011.41.50.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="118" data-original-width="555" height="68" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeDpA4ARwvjzg8kJ6oczqgZ6tgcXa53G4o58SZ_Ey7bltiMw0-z8glqhRQtX-aE6rQmkkwkcwdx0PTqLnyt3-sPkwY5MWVyE0Ndc7LqLhvN0j-LVQJwApXPnI-1Tjk-GIJkOV6ZLfabZj9-FCBtAIVCXV2n9KbIDdG_aIV1INpze078s4mm1dya5Rcvw/s320/Screenshot%202022-10-02%20at%2011.41.50.png" width="320" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">I was already suspicious after not having a choice to download a JDKFx from Azul? I was seeing the wall approaching very fast. </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">But being on fire <a href="https://github.com/openjdk/jfx">I checked out the openjfx source code</a> as well, and tried to compile it. 🤷🏼♂️ </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">I followed <a href="https://wiki.openjdk.org/display/OpenJFX/Building+OpenJFX">OpenJFX's build instructions</a> - For example I downloaded Visual Studio. Which is available for Windows aarch64 in an early preview. Of course I realised this only after being informed by the 'normal' Visual studio installer that this platform I'm running on was not supported. </p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">I smiled along the way, no way this would work - but I continued.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">After installing cygwin as well I was sure jfx wouldn’t compile, since this was only a x86 version for it.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Anyway, I continued, and after ignoring all warnings and instructions on the openjfx wiki to install a certain gradle version I just went with the most current one.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Finally, I got to execute gradle with the default task ‘sdk’. </p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">It promptly aborted with a message ‘platform not supported’. </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">There you have it!</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Well, I just searched the whole jfx source for this message, found it and short circuited the if statement which aborted the build.</p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5Icb2h9sVoj7AW-edVq5dB8mVvcCdExNbosjgnYPuZGH7S1Y2BpVRRUMkjm2JZUapULuAq49JD8DvjNifEIantBg5R9KeW0WdYQsAskTBMA47F9FWnF-0NJnlImGI-rxMRYNUTq1NAEGOMlDZgyPNPGLobK99oXC0VKBYbhTEiDv_tQ3I9u7AznF8EA/s1004/Screenshot%202022-10-02%20at%2012.02.02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="95" data-original-width="1004" height="39" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5Icb2h9sVoj7AW-edVq5dB8mVvcCdExNbosjgnYPuZGH7S1Y2BpVRRUMkjm2JZUapULuAq49JD8DvjNifEIantBg5R9KeW0WdYQsAskTBMA47F9FWnF-0NJnlImGI-rxMRYNUTq1NAEGOMlDZgyPNPGLobK99oXC0VKBYbhTEiDv_tQ3I9u7AznF8EA/w400-h39/Screenshot%202022-10-02%20at%2012.02.02.png" width="400" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">To my suprise this was the only thing which was necessary for a successful build! I got all the jars and modules!?? </p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Well ... ok!</p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">But! I need maven artefacts to fire up LogoRRR - how go get those? The official docs state there existed some publish tasks for maven, but I couldn’t find it.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Being on fire I searched the source code again, and I was lucky again! <a href="https://stackoverflow.com/questions/71664637/how-to-build-openjfx-and-make-a-maven-artifact/73924427#73924427" target="_blank">There exists a property to activate those publish tasks, and I bravely activated them</a>.</p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzjk29PbepBbCasb3SzkNQO7uIH9Woll3kudp1aWY7sBurftLhJi2mU4xUg6DBOR-g3sNJS6fnnJiD1bsa-zjgUdk95Wvl23zHRd9JEbJXP5mgMJ6Dvu9IBaQWQHH7NsFZhBqvzb5BgP8dzxF7hfVIC0zNw125a--iQIzkQEKMLzYZsfOT-yU0m5OA-Q/s930/Screenshot%202022-10-02%20at%2012.04.35.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="73" data-original-width="930" height="32" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzjk29PbepBbCasb3SzkNQO7uIH9Woll3kudp1aWY7sBurftLhJi2mU4xUg6DBOR-g3sNJS6fnnJiD1bsa-zjgUdk95Wvl23zHRd9JEbJXP5mgMJ6Dvu9IBaQWQHH7NsFZhBqvzb5BgP8dzxF7hfVIC0zNw125a--iQIzkQEKMLzYZsfOT-yU0m5OA-Q/w400-h32/Screenshot%202022-10-02%20at%2012.04.35.png" width="400" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Having no idea what I was doing, but needing javafx modules graphics, control, swing and base in my local maven repository, I went on. I even defined my own version number for openjfx.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Now I changed the version for JavaFX in my LogoRRR’s code, changed the openjfx version and the module path in the run configuration and gave it a go.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">After a peculiar long compilation time, finally LogoRRR showed up. 🥳</p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiJ4bnfYto1chF9-1-B5a_XRrF2-5nX8zYY19XMDMK4Eo1Dx0ogJdVWIJ_g436d2dog3cG2QobOCkusTHuiXeqrT0hle0FfjRVOSpNwJKjnwgKLmkZBMwkLnKRPrv9bc1c_ekISp8zsbUR4jafT69aokT9suXJ8inBEdFHyh6UfqQMG6XZ3juf7P-DxA/s1432/Screenshot%202022-10-02%20at%2011.31.55.png" style="margin-left: 1em; margin-right: 1em;"><img alt="LogoRRR Screenshot" border="0" data-original-height="772" data-original-width="1432" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiJ4bnfYto1chF9-1-B5a_XRrF2-5nX8zYY19XMDMK4Eo1Dx0ogJdVWIJ_g436d2dog3cG2QobOCkusTHuiXeqrT0hle0FfjRVOSpNwJKjnwgKLmkZBMwkLnKRPrv9bc1c_ekISp8zsbUR4jafT69aokT9suXJ8inBEdFHyh6UfqQMG6XZ3juf7P-DxA/w320-h173/Screenshot%202022-10-02%20at%2011.31.55.png" title="Screenshot of Virtual Windows with LogoRRR" width="320" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<h3 style="text-align: left;">Lessons learned</h3>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;">I’m not really sure that I got a clean aarch64 build for openjfx on windows, more likely a mixture of an emulation and aarch64 bits of the build. Otherwise this would have been too easy. </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">At least LogoRRR started up and worked like it was supposed to do. Which it didn’t prior to my quest. The trigger here was the message 'javafx platform not supported' in IntelliJ. </p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">… The broader message is that open source can work for you in many ways, for everybody on his level.</p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Programming has to do with a certain attitude. Often one reads of ‘<a href="https://www.google.com/search?q=fearless+refactoring" target="_blank">fearless refactoring</a>’. What should I be afraid of? No laptop exploded so far (I know of) because somebody renamed a variable ...</p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">I also realised that openjfx is just a project like any other project - you can download it, inspect it, tinker with it ... you could even contribute to it in some or the other way - for example like i did with the <a href="https://stackoverflow.com/questions/71664637/how-to-build-openjfx-and-make-a-maven-artifact/73924427#73924427">answer on stackoverflow</a> - all contributions are valuable, even if it is not always technically correct or imperfect.</p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-74166331003073919292022-09-11T13:52:00.008+02:002022-09-11T14:08:29.980+02:00ZIO and JavaFX - Hello World<p><span style="font-family: "Helvetica Neue"; font-size: 13px;">As part of learning ZIO (</span><a href="http://www.zio.dev/" style="font-family: "Helvetica Neue"; font-size: 13px;"><span style="color: #dca10d;">http://www.zio.dev/</span></a><span style="font-family: "Helvetica Neue"; font-size: 13px;">) for other projects I’m working on I’ve decided to use </span><a href="https://www.logorrr.app/" style="font-family: "Helvetica Neue"; font-size: 13px;" target="_blank">LogoRRR</a><span style="font-family: "Helvetica Neue"; font-size: 13px;"> as a testbed to see which challenges have to be solved in the context of JavaFX application programming with Maven and Scala.</span></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;">For context:</p><blockquote><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;">ZIO is a framework to perform type-safe, composable asynchronous and concurrent programming for Scala. </p></blockquote><blockquote><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><a href="https://github.com/rladstaetter/LogoRRR" target="_blank">LogoRRR is a desktop application</a> written in Scala, leveraging JavaFX as desktop application technology. LogoRRR helps to analyse log files and its target audience are support/devops engineers.</p></blockquote><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Starting fresh with no relevant ZIO experience, I’m interested in the CI setup. LogoRRR uses maven as build system, which is rather uncommon for a Scala project. There are two reasons for that - I know maven quite well, and I’m using <a href="https://github.com/gluonhq/gluonfx-maven-plugin">Gluon’s gluonfx-maven-plugin</a> - that's the main reason why I'm using maven here. </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Anyway, now I’m confronted with following challenges:</p>
<ul><li style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">How to setup a maven project with ZIO?</li>
<ul>
<li style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-size: 12px; font-stretch: normal; line-height: normal;"></span>Is ZIO compatible with LogoRRR’s GraalVM compilation workflow?</li>
</ul>
<li style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-size: 12px; font-stretch: normal; line-height: normal;"></span>How to integrate ZIO with JavaFX?</li>
</ul>
<span><a name='more'></a></span><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><b>How to setup a maven project with ZIO </b></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">In any case, one has to add ZIO as a dependency in the pom.xml file:</p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl6UzJB7qLs6UwhOj3BOupuP9NixGUp-_ePNttohRVkIxwRgM7hmWs7laCpSpNRTUd7rgM-61gmAeIfFEkMa1iVkHGMF2RLc3BE6lKU5s9uf0f4gt4d3rDywTATHaShoAPzjWKGu_clsyUEXfTHSiL3xKtr2UmcJgHKOBT3oRxPxMIItGzXgvDfvvJrg/s1272/zio-maven.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="308" data-original-width="1272" height="98" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl6UzJB7qLs6UwhOj3BOupuP9NixGUp-_ePNttohRVkIxwRgM7hmWs7laCpSpNRTUd7rgM-61gmAeIfFEkMa1iVkHGMF2RLc3BE6lKU5s9uf0f4gt4d3rDywTATHaShoAPzjWKGu_clsyUEXfTHSiL3xKtr2UmcJgHKOBT3oRxPxMIItGzXgvDfvvJrg/w400-h98/zio-maven.png" width="400" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">At the time of writing, ZIO supports Scala 2.12, 2.13 and also Scala 3 which is great for LogoRRR. (There was an attempt to upgrade LogoRRR to Scala 3, but IntelliJ Support for Scala 3 isn’t there yet. When my motivation allows I’ll try again.) </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">The project still compiles without any issue, also GraalVM seems not to bother much about this new dependency. You can see the relevant commit here: <a href="https://github.com/rladstaetter/LogoRRR/commit/7d6fd36cdf92a97648786adee2748dd9652742d5"><span style="color: #dca10d;">https://github.com/rladstaetter/LogoRRR/commit/7d6fd36cdf92a97648786adee2748dd9652742d5</span></a> </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><b>How to integrate ZIO with JavaFX?</b></p><div><b><br /></b></div><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">To try out ZIO in LogoRRR, I start with copying ZIO HelloWorld to LogoRRR’s Source code:</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh21oqXXb_16KZst6iekp7nTALZ2BEIx7qLrG4jSNnn92SbZjffLPU-4HNgGwwKNEMIg-klhS4ycBN9FG0f1RVAe2ldfPJYILcHMVo7L7ObYVViRSv1QpOU0ARspOsSFFBeg0eCsbQin-Ly9zDQhi-LxZCYElLvmYCnrd02vwEOBPdghpwtslVRYrQVGw/s1318/zio-helloworld.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="762" data-original-width="1318" height="233" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh21oqXXb_16KZst6iekp7nTALZ2BEIx7qLrG4jSNnn92SbZjffLPU-4HNgGwwKNEMIg-klhS4ycBN9FG0f1RVAe2ldfPJYILcHMVo7L7ObYVViRSv1QpOU0ARspOsSFFBeg0eCsbQin-Ly9zDQhi-LxZCYElLvmYCnrd02vwEOBPdghpwtslVRYrQVGw/w400-h233/zio-helloworld.png" width="400" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">This works without any problems. That’s already great, but does not prove anything other than that classpath resolution works in IntelliJ. Better than nothing.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">JavaFX has it’s own Application class (javafx.application.Application) and ZIO as well (zio.ZIOAppDefault). Both of them initialise their environment. I’m stuck?</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Searching for information in ZIO’s Discord Channels yields some information which may be valuable - a discussion from 3 years ago between BrajEje and Kaiser gives some hints: (<a href="https://discord.com/channels/629491597070827530/630498701860929559/645653183422660608"><span style="color: #dca10d;">https://discord.com/channels/629491597070827530/630498701860929559/645653183422660608</span></a>) </p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Anyways, as far as I understand it at the time of writing, ZIO is all about describing WHAT should happen in certain datastructures and magic incantations. </p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">In short, my strategy for a JavaFX app backed by ZIO is:</p>
<ul><li style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">use JavaFX infrastructure to startup the application</li>
<li style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-size: 12px; font-stretch: normal; line-height: normal;"></span>describe ZIO effects</li>
<li style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><span style="font-size: 12px; font-stretch: normal; line-height: normal;"></span>run effects where necessary</li>
</ul>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;">As seen from ZIO, LogoRRR is no ‘greenfield’ project. For this usecase there is an explicit way to enter ZIO’s territory via a `Runtime` class. See <a href="https://zio.dev/overview/overview_running_effects#default-runtime"><span style="color: #dca10d;">https://zio.dev/overview/overview_running_effects#default-runtime</span></a> which I’ll follow here.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">I’m starting with a basic JavaFX startup class:</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXFuZtGSDaXlOxEZQHEAyMA7-CpRTq_FlXnuxtp9m-fEL6nDKe4m8C2ZSVRqAao5hD3HG7V7bNgR1XLCzfglc9haa3_GDrHloqA_y6wVOQPRy1khtWaTZzXibOhlxg5hPu3OEf28PA4ciO7yqI2bxR2v7exAw06MqQ6qZ0Or1PSjqQjNYe_a6Kayzm3Q/s1298/javafx-helloworld.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1040" data-original-width="1298" height="321" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXFuZtGSDaXlOxEZQHEAyMA7-CpRTq_FlXnuxtp9m-fEL6nDKe4m8C2ZSVRqAao5hD3HG7V7bNgR1XLCzfglc9haa3_GDrHloqA_y6wVOQPRy1khtWaTZzXibOhlxg5hPu3OEf28PA4ciO7yqI2bxR2v7exAw06MqQ6qZ0Or1PSjqQjNYe_a6Kayzm3Q/w400-h321/javafx-helloworld.png" width="400" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Apart from naming it fancy ‘LogoRRRZIO’ this code has nothing to do with ZIO at all at the moment. But it will serve as a starting point for a JavaFX ZIO application showcase I hope.</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">First thing I’m doing now is to instantiate a ZIO runtime and try to click a button:</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3OUn21y9yPtbEmR0fkIYIWLVoARSet8UBuTtZTfwGM_T9Fr0-2KUJTK4LmC1p2gz8DbokUg4R7vZ6CXwoYp1c5wFvt7gqqjiVvVbiSiXlJDazUDwr93j0n5pVRxnea95r5NTm3xhTJfxvaxSi_MacYtuT1Hf1ZPFgvz5sWBSkXJJ7xJ7CIDu1rQVKAQ/s1592/logorrr-zio.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1444" data-original-width="1592" height="364" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3OUn21y9yPtbEmR0fkIYIWLVoARSet8UBuTtZTfwGM_T9Fr0-2KUJTK4LmC1p2gz8DbokUg4R7vZ6CXwoYp1c5wFvt7gqqjiVvVbiSiXlJDazUDwr93j0n5pVRxnea95r5NTm3xhTJfxvaxSi_MacYtuT1Hf1ZPFgvz5sWBSkXJJ7xJ7CIDu1rQVKAQ/w400-h364/logorrr-zio.png" width="400" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">In order to start, JavaFX needs some command line parameters - see <a href="http://openjfx.io"><span style="color: #dca10d;">openjfx.io</span></a> for details on that. I’ll add them to the IntelliJ run configuration: </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL66dWLlJ3I3_YX7WnEDCkyoWj0o9NPT_gMcitkh_70dMOpZ8rVzjC-VdQ7CmyrSZLbyQk734UjeIG2KVEVK17Pad_hCButGlOwtOdpbQkgk_yqypur4FF777fYnWxEd2YBdzbdmX-GBzdQcmYCzutRN3qr1wEf_fFO0M-HUnTB7gmwPj6WQnqp_9SsA/s2296/javafx-startup-params.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1546" data-original-width="2296" height="269" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiL66dWLlJ3I3_YX7WnEDCkyoWj0o9NPT_gMcitkh_70dMOpZ8rVzjC-VdQ7CmyrSZLbyQk734UjeIG2KVEVK17Pad_hCButGlOwtOdpbQkgk_yqypur4FF777fYnWxEd2YBdzbdmX-GBzdQcmYCzutRN3qr1wEf_fFO0M-HUnTB7gmwPj6WQnqp_9SsA/w400-h269/javafx-startup-params.png" width="400" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">This seems to work:</p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikUZcGWNZayJM_QSqjB7c4O7mXh62eeP1gFg15HwhF12BTPgrbCvGCS8hf3PnW6Py1IJT5PTzb8W5HcgRt2fsc_p4AAkRor3UFHLiPzugNIKJUWWuFJi3k-trTDorhBLftm5CjyIi0ZHZDx8G8eRHaVeESqxD-nCK9AxMKj-xYKKAE_s3phQvLUn51aw/s1708/zio-javafx-runtime.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1130" data-original-width="1708" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEikUZcGWNZayJM_QSqjB7c4O7mXh62eeP1gFg15HwhF12BTPgrbCvGCS8hf3PnW6Py1IJT5PTzb8W5HcgRt2fsc_p4AAkRor3UFHLiPzugNIKJUWWuFJi3k-trTDorhBLftm5CjyIi0ZHZDx8G8eRHaVeESqxD-nCK9AxMKj-xYKKAE_s3phQvLUn51aw/w400-h266/zio-javafx-runtime.png" width="400" /></a></div><br /><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Great! From now on it should be <b>trivial</b> to use ZIO as backend for everything. ☺️ </p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px; min-height: 15px;"><br /></p>
<p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">… just joking, many challenges have to be solved ... but it is a start! :) </p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">See my work in progress on github and a presumably<a href="https://github.com/rladstaetter/LogoRRR/tree/98-introduce-effect-system" target="_blank"> long living branch</a>, this article refers to <a href="https://github.com/rladstaetter/LogoRRR/commit/42832fbd9ec92a4edfcca3ea9c69c1d58fed898f">https://github.com/rladstaetter/LogoRRR/commit/42832fbd9ec92a4edfcca3ea9c69c1d58fed898f</a></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;"><br /></p><p style="font-family: "Helvetica Neue"; font-size: 13px; font-stretch: normal; line-height: normal; margin: 0px;">Of course you can <a href="https://github.com/rladstaetter/LogoRRR/releases/tag/22.2.0" target="_blank">download latest builds of LogoRRR here</a> to try out the application itself. I didn't blog about it, but this application is already usable from an end point users view and I would be happy to hear from you either as a programmer discussing implementation details or an end user requesting features or finding bugs 🙌</p>rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-35063573145792375872020-10-26T20:35:00.005+01:002020-10-27T20:12:07.069+01:00A native Scala JavaFX application via GraalVM <p>After successful attempts with <a href="https://ladstatt.blogspot.com/2020/10/javacv-webcam-graal-edition.html">Java, JavaFX and GraalVM</a> I get closer to my goal to compile <a href="https://github.com/rladstaetter/sudokufx">SudokuFX</a> to a native binary. A milestone towards this goal is to compile a trivial Scala JavaFX application to native code, that is to say to a single, dependency free binary. <a href="https://github.com/rladstaetter/javafx-logboard/releases/tag/2020.3.0">Source code and binaries for windows and MacOsX for this blog post are available here</a>.</p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a data-flickr-embed="true" href="https://www.flickr.com/photos/royalaustralianhistoricalsociety/6433397003/in/photolist-aNuQMZ-JTbbqH-GkSYem-BKsEvn-HMPGeW-GhQyNs-H7sTJ5-PWpv3Q-dCXgGV-G93jxc-MHnwKu-BWoMQQ-nQFZ5f-HXQaZb-yUFsYz-ygSuEc-G8uHVG-GLK6T4-DnKPFK-ABWPbM-PqDGDh-DqNw8c-J26bZ3-DUM6z8-dCXgEX-qZokHw-tNqZB9-DFQVwc-GMHXg9-Eg8CPW-DgBiKx-FYXzhr-CGnkqW-o4k7jm-GtMadt-QiUCeN-DaoRBB-E35aU7-D8DkoH-cbQyb7-QvjP12-HT9gBT-HZ5Z6L-yHE9h3-o4meEi-LGHWRV-HSReD8-w87Zcc-Rauozu-CPa6m6" style="margin-left: auto; margin-right: auto;" title="03 - Sydney Harbour Bridge Construction"><img alt="03 - Sydney Harbour Bridge Construction" height="381" src="https://live.staticflickr.com/7154/6433397003_8dc78527b5.jpg" width="500" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"> Sydney Harbour Bridge Construction</td></tr></tbody></table><h4 style="text-align: left;">JavaFX Logboard</h4><p>As a vehicle for using JavaFX and FXML I chose to implement a simple log visualisation tool. I'll call it <a href="https://github.com/rladstaetter/javafx-logboard">javafx-logboard</a>. It is a JavaFX application which displays green, red, yellow and gray rectangles in a FlowPane, symbolizing INFO, SEVERE, WARNING and TRACE messages. It is nothing fancy, but helps identifying swiftly if there are problems or certain patterns in an application log. With this visualisation, it is easier to detect patterns. Try it! Honestly, I'm wondering why common log viewers don't have such a 'birds eye' feature. </p><p>A screenshot will make things clearer: </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiN3fgcD3QWLZIt-xWSqSXJJiMxQ3QVweQ-tGylyvOdKJXY5zkwjvAz4zHfJfNr-zUKsm_XzSCp-gtqMLNnO-fNiRy5TiXqKSsL3f_mWbLCU8YMALaaDQQUJ37ulYDpPdWR8CJaFan7dnk/s1078/javafx-logboard_and_javafx-logboard_%25E2%2580%2593_README_md__javafx-logboard_.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="658" data-original-width="1078" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiN3fgcD3QWLZIt-xWSqSXJJiMxQ3QVweQ-tGylyvOdKJXY5zkwjvAz4zHfJfNr-zUKsm_XzSCp-gtqMLNnO-fNiRy5TiXqKSsL3f_mWbLCU8YMALaaDQQUJ37ulYDpPdWR8CJaFan7dnk/w320-h197/javafx-logboard_and_javafx-logboard_%25E2%2580%2593_README_md__javafx-logboard_.png" width="320" /></a></div><p>The application helps to get a quick idea about what is going on in a log file. It even sports Tooltips for red rectangles (SEVERE entries) and Drag'n Drop. I always wanted to have such a tool, well I wrote it in 10 minutes (*). It reminds me visually a <a href="http://jope.fi/xcopy/index.html">little of XCopy</a>, an ancestor of XCode (nerd joke). </p><h4 style="text-align: left;">Motivation</h4><p>I started this project and blog post with following promise:</p><p><i>If javafx-logboard compiles to a native binary, I'll be a true believer in GraalVM and will AOT compile my way through various applications in the future. (at least try it)</i></p><p>Side-note: I already successfully compiled an application with <a href="https://ladstatt.blogspot.com/2020/10/javacv-webcam-graal-edition.html">JavaCV for MacOsX with GraalVM</a>, this dependency involves more native code I'll ever want to write in my life. But Seeing a Scala JavaFX app running with my own eyes, that should be the the mission for this blog post. </p><p>The motivation for having a native binary is primarily an easier way for distributing software in my mind, in regard of speed and memory consumption it <a href="https://www.oracle.com/mx/a/ocom/docs/graalvm-twitter-casestudy-constellation.pdf">may help twitter but is not really relevant for me</a> ... or is it? </p><p>I believe GraalVM produces more efficient Scala runtime code, it would be great to experience a perceptible difference for my own applications as well. There is no other way, you have to try it out. </p><h4 style="text-align: left;">Some takeaways after spending far too much time on this endeavour until everything worked</h4><div><i><br /></i></div><div><i>Scala Converters</i></div><div><br /></div><div>I have experienced some errors with GraalVM compilation which I traced back to scala.jdk.CollectionConverters, but I think it has something to do with implicit resolution of Scala methods. I'm not quite sure what is the issue with it, my solution was to use Java Collections just to get it to run. I'm sure GraalVM has no problem consuming Scala Collections via some extra configuration maybe (will have to solve / tackle this again in future projects anyway ... )</div><div><br /></div><div><i>FXML References</i> </div><div><br /></div><div>It took some time until I realised that classes won't get automatically included via GraalVM if you use UI elements in FXML without referencing them in your Controller. You have to explicitly add them in your reflection list, otherwise they get lost and you'll get weird runtime behaviour. Or reference them in your controllers. </div><div><br /></div><div><i>fat-jar</i></div><p>Antother thing I've learned is that you don't need to modularise your Java/Scala application in order to compile it with GraalVM. Just provide a shaded jar and there you go.</p><p><i>main-class not found with scala javafx apps?</i></p><p>I experienced something rather intriguing - if I tried to call GraalVM via maven client plugin in the same project like I compiled my Scala sources, I always would get an error - GraalVM compilation would not find the entry point to the appilation, it's main class (which was written in Scala).</p><p>Not thinking long about it, I created a multi module maven project which contains all relevant Scala source code, and one with a minimalistic Java main class which can be found by the maven client plugin. I don't know if I did something wrong here (again), it seems rather odd. But with a small Java bootstrapper it works fine.</p><p><i>multimodule maven project - mvn install</i></p><p>Since I use a trick to compile my Scala stuff to a shaded jar to trick client-maven-plugin to compile it as 'normal' byte code I have to use mvn install - otherwise it would not find the dependency (for example with mvn package). In my opinion this should not make any difference, but at the moment it does. Somebody an idea what's going on here?</p><p><i>long compile times - again</i></p><p>This multi-module approach is more or less inevitable anyways since compile times for GraalVM are long. For application development it is not really feasible to wait so long for testing features and such. </p><p>As such it is good practice to make sure your application runs on a VM (in a shaded fat jar for example) and only then try to compile it to native code. Beware: The added complexity for application developers not only to implement a feature but also keep control of the whole build chain doesn't really simplify application development. This is a huge problem in my opinion, and a hurdle for adoption. :( </p><p>Remember however that a little waiting and listening to the noise of the fan yields finally an AOT compiled binary, everything included, no JRE download, all in one package. Which is just mind-blowing and well worth the effort!</p><p><i>scala-native - the other way </i></p><p>Speaking of which - I want to mention Scala Native here as well, which is a project to compile Scala directly (via LLVM) to native code. With a tighter integration in the Scala compiler more specific optimisations are possible and hence faster, smaller binaries (compared to GraalVM) are possible. ... In theory. It is a shame that this project doesn't get as much attention, love and money it would need to reach a more mature state and really compete with GraalVM. For example, I doubt it would be able to compile JavaFX apps at the moment. </p><p><i>file sizes acceptable</i></p><p>Back to GraalVM: It is also interesting how big a Scala JavaFX application can be at minimum without any magic - at about 65 MB for MacOsX, which is not much larger than a Helloworld JavaFX (FXML) application directly from gluon samples project. </p><p>I tried my little toy project this time also with windows, and after following <a href="https://github.com/gluonhq/client-maven-plugin">instructions from here</a> it compiled without much hassle literally on the first try. Binary size on windows is roughly the same, at about 60 MB. </p><p>Depending on your background or internet access speed those sizes are negligible or a major drama, decide for yourself. If you are keen on minimal file sizes, you should <a href="https://www.pouet.net/prodlist.php?type%5B0%5D=64k&page=1&order=views">stop by at pouet.net</a> and ask yourself if you have made the right choices as a programmer in your life. </p><p><i>low hanging fruits</i></p><p>In retrospect it turns out that configuring native compilation with Maven, JavaFX client plugin, GraalVM and Scala is easier than it may sound. It heavily depends on a proper configuration of the toolchain, and this has to be learned. Since this whole process includes compiling your code with GraalVM, I should mention that normal compilation is said to be faster with GraalVM as well (for Scala code). Another reason to consider using it (just as compile vehicle, without creating native images).</p><p>For the time being, I'm happy with my GraalVM experiments and try to migrate codebases as soon as I can to be consumable by client-maven-plugin. Some of those journeys I may document here in the future. </p><p><a href="https://github.com/rladstaetter/javafx-logboard/releases/tag/2020.3.0">Source code and binaries for windows and MacOsX for this blog post are available here</a>.</p><p><i><span style="font-size: x-small;">(*) implementing Drag'n Drop took me 10 minutes, but debugging why it would not work the way I expected took hours. It had to do with GraalVM very aggressively stripping away JavaFX containers and no log output was given. Drag'n drop works fine, you just have to be cautious about making sure that everything is really contained in your exe file - afterwards it is always easy ;-)</span></i></p><p><br /></p><p><br /></p><p><br /></p>rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-85072584057032600342020-10-17T22:16:00.002+02:002020-10-17T22:28:44.637+02:00javacv-webcam: GraalVM edition<p>TLDR: <a href="https://github.com/rladstaetter/javacv-webcam/releases/tag/2020.3.1">java-webcam can be compiled with GraalVM to a native binary, source code available here.</a> </p><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto;"><tbody><tr><td style="text-align: center;"><a data-flickr-embed="true" href="https://www.flickr.com/photos/twm_news/26983773380/in/photolist-H7sTJ5-G93jxc-MHnwKu-DnKPFK-BWoMQQ-ABWPbM-nQFZ5f-HXQaZb-aNuQMZ-ygSuEc-PWpv3Q-dCXgGV-GLK6T4-PqDGDh-dCXgEX-yHE9h3-qZokHw-tNqZB9-DFQVwc-DgBiKx-Eg8CPW-GMHXg9-o4k7jm-GtMadt-QiUCeN-DaoRBB-E35aU7-QvjP12-cbQyb7-HT9gBT-o4meEi-HZ5Z6L-DqNw8c-J26bZ3-DUM6z8-FYXzhr-CGnkqW-D8DkoH-HSReD8-Rauozu-JQaozd-Cs32h6-9JmyEY-Hwgvxq-JsTknD-ztXPKh-DTewb9-Cvc63S-QiwAzP-BXQXMR/" style="margin-left: auto; margin-right: auto;" title="Preparing the slipway for a launch"><img alt="Preparing the slipway for a launch" height="377" src="https://live.staticflickr.com/7412/26983773380_e0e04fe0a8.jpg" width="500" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Tyne & Wear Archives & Museums<br /></td></tr></tbody></table><p>
<script async="" charset="utf-8" src="//embedr.flickr.com/assets/client-code.js"></script>
<br /></p><p>Recently, I managed to find some time to get a <a href="https://ladstatt.blogspot.com/2020/10/javacv-webcam-skeleton-project-to-do.html">custom java runtime image to work with JavaCV and a simple webcam application</a>, which opens nice possibilities to play around doing image processing with Java.</p><p>On the other hand, if you have followed the Java community lately, you've been surely pointed several times to the current big thing <a href="https://openjdk.java.net/projects/panama/">Panama</a> and <a href="https://github.com/openjdk/loom">Loom</a>, ah I mean of course <a href="https://www.graalvm.org">GraalVM</a>. </p><p>I'm very fond of the vision of GraalVM, which tries to provide a common platform for several different language eco systems (among other things), in my view a meta supplier for many business opportunities, not clear at the moment what the implications are really. </p><p>It goes without saying that it would be great to get JavaCV and JavaFX to run with GraalVM as well.</p><p><i>Disclaimer</i>: I'm just an interested developer who applies mentioned technologies, more or less successfully. I cannot stress enough how grateful one can be for enabler technologies like JavaFX, JavaCV or GraalVM. </p><p><b>Ok.</b> What is necessary for a webcam binary, written in Java, at the time of writing? </p><p>The good news is: not much. In retrospect (after hours - I still can't believe it works now, at least at the moment, for me, in my small bubble).</p><p>After much fiddling around the only thing really necessary was bringing together the right tools. I'm using GraalVM 2020.2.0 and Maven 3.6.2 at the moment, the most recent XCode, brew ... well ok ... probably much libraries and toolchains I'm not aware of (neither I want to be - to be honest). </p><p>But the good news is that apart from setting up your environment "properly" and checking out javacv-webcam 2020.3.1, all you have to do is to enter following command:</p><p><span style="font-family: courier;">mvn clean client:build client:run -Djavacpp.platform.custom -Djavacpp.platform.host -Dgraalvm.home=/path/to/graalvm</span></p><p>After downloading all dependencies (can take some time!) and compiling (forget about download times, this is the real deal), you'll get a huge binary AND a running webcam application (most probably after having been asked to grant permissions by your friendly OS). ... which made my day!</p><p>Alternatively, you can start javacv-webcam <b>binary </b>then like this:</p><p><span style="font-family: courier;">target/client/x86_64-darwin/net.ladstatt.javacv.javacv-webcam</span></p><p>Currently, this binary is huge (>500MB!), which is a little too much for my taste ;-) - a simple Hello World without JavaCV has around 60 MB (try compiling HelloFX in <a href="https://github.com/gluonhq/gluon-samples">gluon-samples project</a>). </p><p>In this regard I'm sure it is possible to reduce the size by applying a more specific configuration. The best - only - chance I see here is to tinker around with JavaCV's dependencies, be more explicit with exclusions, hope that still everything you need works. To be honest, I already had to exclude one transitive dependency, otherwise linking didn't work with GraalVM. </p><p>I just had luck my example app didn't need this specific library I guess. </p><p>Anyway, the road for an easier deployment of Java image processing applications is paved, which is simply exciting! <a href="https://www.youtube.com/davie504">Slap like now</a>!</p>rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-455498234894523222020-10-12T22:51:00.002+02:002020-10-17T22:17:52.054+02:00javacv-webcam: a skeleton project to do image processing with java<p>Recently I've simplified <a href="https://github.com/rladstaetter/javacv-webcam">JavaCV Webcam project</a> for an easy start with JavaCV and JavaFX.</p><p>If you follow me on this blog or my occasional posts on <a href="http://twitter.com/rladstaettter/">twitter</a>, you surely know that I like to explore new features for JavaFX in combination with Scala. Lately, I had migrated <a href="https://ladstatt.blogspot.com/2020/05/sudokufx-version-202020.html">SudokuFX to JavaCV</a>. With this release SudokuFX doesn't use OpenCV directly anymore but uses JavaCV's wrapper which provided at the point of writing a more low level API to the Mat data structure. </p><p>SudokuFX provides some examples on how to use JavaCV, however if you search for a simple example on how to use JavaCV and JavaFX and you want to access your webcam, <a href="https://github.com/rladstaetter/javacv-webcam">javacv-webcam</a> is the right project for you. </p><p>javacv-webcam is written in 100% Java. It shows how to configure <a href="https://github.com/openjfx/javafx-maven-plugin">javafx-maven-plugin</a> to create a custom java runtime image with jlink. </p><p>Another aspect which is worth mentioning is that javacv-webcam is an example for a modular java application. Here it is worth mentioning that IntelliJ in a recent version has good support for writing module-info.java and compiler errors are helpful as well. </p><p>I tried to make javacv-webcam a project with zero configuration, you should just be able to check out the project and just run it ... </p><p>Note: on windows or linux you have to apply small changes in module-info.java, but this should pose no problem. On MacOsX you may have to fiddle around with privacy / security settings for java. Speaking of which - you have to use Java11 and a recent maven distribution.</p><p>For build instructions, just checkout <a href="https://github.com/rladstaetter/javacv-webcam">github readme</a> page. This post refers to <a href="https://github.com/rladstaetter/javacv-webcam/releases/tag/2020.3.0">javacv-webcam version 2020.3.0</a>.</p><p>Note: There is an <a href="https://ladstatt.blogspot.com/2020/05/webcam-image-stream-with-javacv.html">older version for javacv-webcam</a> which is implemented in Scala and does some comparisons to other ways how to use JavaCV. Also, there is a <a href="https://ladstatt.blogspot.com/2020/10/javacv-webcam-graal-edition.html">newer version for javacv-webcam</a> which contains configuration to compile it to a native binary using GraalVM.</p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p>rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-21953123766229788552020-08-17T17:08:00.004+02:002020-09-18T20:09:22.866+02:00SudokuFX Version 2020.3.0<div dir="ltr" style="text-align: left;" trbidi="on">
After successfully <a href="https://ladstatt.blogspot.com/2020/05/webcam-image-stream-with-javacv.html" target="_blank">prototyping a webcam image stream with latest JavaFX goodies</a> my next step for my hobby project SudokuFX is clear - port everything to JavaCV and use it's implementation to speedup SudokuFX.<br /><br /></div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on"><div dir="ltr" trbidi="on">With version 2020.3.0, I rewrote almost everything; conceptually my application follows the original approach, but the implementation is simpler and yields itself better for future enhancements.</div><div><br /></div></div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">Some highlights:</div><div dir="ltr" style="text-align: left;" trbidi="on"><br />- SudokuFX uses JavaCV</div><div dir="ltr" style="text-align: left;" trbidi="on">- got rid of overcomplicated usage of Scala Future's</div><div dir="ltr" style="text-align: left;" trbidi="on">- improved image recognition by tweaking used templates</div><div dir="ltr" style="text-align: left;" trbidi="on">- improved visual appearance by a smarter approach to overlaying empty cells with numbers, not replacing them</div><div dir="ltr" style="text-align: left;" trbidi="on">- better memory and CPU utilisation</div><div dir="ltr" style="text-align: left;" trbidi="on"><div dir="ltr" trbidi="on">- Changed versioning scheme to use<a href="https://axelfontaine.com/blog/dead-burried.html" target="_blank"> revision / changelist</a><br />- Upgrade to JavaFX 15-ea+4</div><div dir="ltr" trbidi="on">- Upgrade to Scala 2.13.3</div></div><div dir="ltr" style="text-align: left;" trbidi="on">- many other small improvements and bug fixes ... </div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">There is one drawback - currently there is no android support anymore in the current version, but I'm trying to reactivate it again (maybe more, <a href="#" id="https://en.wikipedia.org/wiki/The_road_to_hell_is_paved_with_good_intentions" name="https://en.wikipedia.org/wiki/The_road_to_hell_is_paved_with_good_intentions">but you know how it works for hobby software side projects </a>... )</div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">I'll describe some of the mentioned points above now in more detail ...</div><div dir="ltr" style="text-align: left;" trbidi="on">
<br /><h3>SudokuFX uses JavaCV now ... why?</h3><br />Let me start with basic project setup, that is to say maven dependencies and stuff you need to get SudokuFX to work. </div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">Speaking of maven dependencies, this is the major reason why I'm switching from 'pure' OpenCV to JavaCV, since it is somehow - magically - fully mavenized and I can use OpenCV indirectly in my application by using JavaCV APIs. </div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">No need to compile OpenCV myself, no fiddling around with CMake, just staying in my cozy maven Java dependency world, which should lower the bar to start with this project substantially.<br /><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">Of course JavaCV imposes certain new rules and approaches for the programmer, you have to adapt a little bit and make yourself acquainted with another API. For this project however it payed off. </div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">I discovered some spots to improve the image processing. It runs way faster and more reliable now.</div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">On the other hand, one has to be careful not to run in subtle bugs which arise from off heap memory management which is a fancy way to say that you'll get exposed to native code behaviour. </div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">Anyway, starting point for the rewrite to JavaCV was to use raw data from Mat via ByteBuffers, which I only found in JavaCV's API, not in OpenCV. Maybe I'm right, there is no equivalent for this in pure OpenCV C++ / Java API, maybe someone points me to it. With my current approach I'm quite happy, 2020.3 release runs way faster than any other version of SudokuFX so far :)</div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><h3 style="text-align: left;">No more Scala Futures</h3><div dir="ltr" style="text-align: left;" trbidi="on">Scala has a Future implementation in it's standard lib, but it doesn't have the best reputation. All discussions in the Scala community lately made me rethink my approach, and in the end I realized that this pervasive usage of Scala's Future in my code didn't really speed up things, but only bloated the whole source and made it less understandable. As such I refactored this construct out of the source, with planning to later reintroduce it again after cleaning up structure. But I learned that my problem didn't really profit from Future's, as such they are left out completely at the current state of affairs. I can imagine that I'll reintroduce some parallelism again, but at the moment the algorithm runs faster than before. Maybe I'll come back to it and optimise it more, I don't know.</div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><h3 style="text-align: left;">Improved image processing by adapting templates</h3><div dir="ltr" style="text-align: left;" trbidi="on">I'm using template matching for recognising numbers, no third party library <a href="https://github.com/tesseract-ocr/tesseract">like tesseract for example</a>. This keeps it simple, but is certainly a weak point in the approach. Here the project could profit by using a simple neural net maybe. By tweaking and disambiguating the used templates however SudokuFX is now capable of recognising quite a lot of different fonts, which is great (some fonts however will fail miserably ;-) )</div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><h3 style="text-align: left;">Improved visual appearance</h3><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">One thing I'm quite fond of is that SudokuFX now overlays the computed solution with the original image, yielding a much better visual appearance of the solved Sudoku. It looks far more advanced than before, which is great. </div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">Improved resource handling</div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">CPU as well as memory footprint are now far better than they used to be. This was also one of the goals of the refactoring, SudokuFX uses less energy, memory and utilizes CPU far better than before.</div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><h3 style="text-align: left;">Versioning Scheme</h3><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on"><a href="https://axelfontaine.com/blog/dead-burried.html">A blog post from Axel Fontaine</a> made me curious as to not use maven release plugin anymore, but an approach far simpler - SudokuFX is using this approach now too.</div><div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<h3 style="text-align: left;">
JavaFX 15-ea+4 / Scala 2.13.3</h3>
<br />
Like I reported in a recent blogpost, I migrated SudokuFX to Java11, which is a LTS version of Java and one of the first releases which where JavaFX was decoupled. JavaFX now lives it's own life - but accidentally - or rather planned - has the same release cycles like Java. </div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">BUT in my usecase scenario I directly profit from the fact that I can use a 'newer' JavaFX with the Java11 LTS version.<br />
<br />
Why? Because at the moment of writing this lines here, I have troubles getting Scala to work with Java13, whereas with Java11 my project runs out of the box. </div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">Scala 2.13.3 is serving as a good starting point to finally change to Scala3, which will also be an interesting endeavour in the future.</div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">So, to sum up, try it out yourself, use SudokuFX to solve your Sudoku problems, have a look at the code to learn something about Scala or <a href="https://github.com/bytedeco/javacv">JavaCV</a> or report bugs you'll easily find and participate at <a href="https://github.com/rladstaetter/sudokufx">github</a>.</div><div dir="ltr" style="text-align: left;" trbidi="on"><br />
<a href="https://github.com/rladstaetter/sudokufx/releases/tag/v2020.3">Source code which is referred to by this article can be found here</a>.<br />
<br />
<br /></div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-35853028575963345832020-05-11T20:53:00.001+02:002020-10-13T07:32:19.481+02:00Webcam Image Stream with JavaCV<div dir="ltr" style="text-align: left;" trbidi="on">
<h4 style="text-align: left;">
JavaCV?</h4>
<a href="https://github.com/bytedeco/javacv">JavaCV is a very cool library</a> which empowers Java users to access native libraries like OpenCV or FFmpeg and many others.<br />
<br />
Among other things, it prepackages OpenCV with maven, as such you can jumpstart in OpenCV development in mere minutes. Even <a href="https://github.com/bytedeco/javacpp-presets/wiki/Reducing-the-Number-of-Dependencies">if it downloads the internet without special tuning</a>, it is as far as I know the simplest and fastest way to try out computer vision algorithms on the Java platform.<br />
<br />
As a bonus, it enables also writing applications for Android, not to mention the usual desktop platforms like Windows / Mac and Linux.<br />
<br />
In the past I've created <a href="https://github.com/rladstaetter/sudokufx">some applications</a> <a href="https://github.com/rladstaetter/OpenCVFilter2D">using OpenCV</a> and it's official Java API, which is also available via JavaCV as far as I know. But JavaCV additionally provides API's which give you an added value as it makes using OpenCV APIs more idiomatic for a Java user, which is always a good thing for adoption.<br />
<br />
In short, you save some time setting up your system if you just decide to use JavaCV.<br />
<br />
<h4 style="text-align: left;">
Motivation</h4>
The motivation for devoting some time to JavaCV was to see if I could take advantage of the <a href="https://bugs.openjdk.java.net/browse/JDK-8167148">new PixelBuffer API which can use since JavaFX13 native arrays directly</a>.<br />
<br />
It seems clear that this should boost performance considerably and improves framerates for applications like my <a href="https://ladstatt.blogspot.com/2020/04/sudokufx-migration-to-java11-lts.html">SudokuFX project</a>. I've created a <a href="https://github.com/rladstaetter/javacv-webcam">proof of concept</a> which compares different ways of using a webcam image stream based on the OpenCV stack.<br />
<br />
In this project there are three implementations given:<br />
<ul style="text-align: left;">
<li>a swing based, officially endorsed way to show a webcam / image</li>
<li>the classic JavaFX variant</li>
<li>the DirectBuffer approach</li>
</ul>
I've measured how fast each approach is, and like expected, on my machine it turns out that the last one using <b>JavaFX with DirectBuffer is the fastest way to show a webcam image stream</b>.<br />
<br />
Here is the output for running the three different versions, with the swing approach being the slowest one.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">home:target lad$ java -jar javacv-webcam-2020.2-SNAPSHOT-jar-with-dependencies.jar </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 719434</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 628738</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 601112</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 579823</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 565205</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 552922</span><br />
<div>
<br /></div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">home:target lad$ java -jar javacv-webcam-2020.2-SNAPSHOT-jar-with-dependencies.jar classic</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 9508516</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 9461551</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 9423204</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 9419029</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 9415144</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">home:target lad$ java -jar javacv-webcam-2020.2-SNAPSHOT-jar-with-dependencies.jar swing </span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 35786482</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 35410293</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 35220229</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 35092391</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Mean: 35030641</span><br />
<div>
<br />
Above numbers say that DirectBuffer approach is the way to go, no discussion about that! I didn't measure CPU load or memory behaviour, but I'm sure those numbers are better as well.<br />
<div>
<br /></div>
<h4 style="text-align: left;">
Conclusion</h4>
If you are using OpenCV and JavaFX, you should definitely give JavaCV and its enhanced API's for OpenCV a try.<br />
<br />
Check out the <a href="https://github.com/rladstaetter/javacv-webcam/releases/tag/2020.2.1">source code for this blog post on github</a>.</div>
<br />
I would like to thank Samuel Audet who does a great job maintaining JavaCV and <a href="https://groups.google.com/forum/#!topic/javacv/uTpd9FGRvyE">who also helped me get my webcam image to fit to JavaFX's PixelBuffer.</a><br />
<br />Version <a href="https://ladstatt.blogspot.com/2020/10/javacv-webcam-skeleton-project-to-do.html">2020.3.0 of javacv-webcam</a> uses the same techniques, but is implemented in 100% Java. Check it out. <br /></div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-84638871150235298292020-04-26T00:33:00.000+02:002020-04-27T08:43:42.578+02:00SudokuFX: Migration to Java11 LTS<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="font-family: "Helvetica Neue"; font-size: 17px; font-stretch: normal; line-height: normal;">
<span style="font-size: 12px;">Better late than never: now I want to migrate SudokuFX to Java11.</span></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
Up to version 2020.1.1, SudokuFX needs a <a href="https://www.azul.com/downloads/zulu-community/?version=java-8-lts&architecture=x86-64-bit&package=jdk-fx">Java Runtime with JavaFX integrated - version 8</a>. Choosing the correct Java version is the first hurdle for the casual internet visitor, very easy to 'do wrong'. Cryptic errors will drive away newcomers, will cost even pro's some time until they realize that the wrong platform is used.</div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<h4 style="text-align: left;">
Java != Java</h4>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
Choosing the wrong Java version is a common problem for beginners, I must admit that it becomes more and more complicated.</div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
Every half year a new Java version is released, with new features, and several organisations provide builds. This is a good thing, the industry has to evolve the platform, and it is good if there exist different sources for Java binaries. Many years of development went into a build process which is now simple enough for the average Bob D. Eveloper to build OpenJDK themselves, which is - considering the details - a huge accomplishment. </div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
For the rest of us, the question is which version of Java to choose? Oracle is still the place to go if you have much money to buy their licenses and subscriptions. Alternatives can be used from <a href="https://adoptopenjdk.net/">AdoptOpenJDK</a>, <a href="https://www.azul.com/downloads/zulu-community/?architecture=x86-64-bit&package=jdk">Azul</a> and others. To ease the migration costs, LTS versions are maintained for a longer period of time - Java version 11 is the one the industry migrates to at this very moment. </div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
And even me with my SudokuFX project.</div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
Still one has to keep in mind that everybody is advertising their latest release, as such often the <a href="https://www.java.com/">newest runtimes and jdks are downloaded</a>, and projects written for older incarnations of those technologies maybe just don't work. </div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
If your project has dependencies on libraries which are also only written for a specific version of the JDK the game becomes even more complex. Then, as a Scala User, you have even more troubles since libraries for a specific version of Scala doesn't really work together with a different Scala version ... </div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
I didn't even mention the modularization effort of the JDK itself, which - only very slowly but in a foundational manner - reinvents the whole ecosystem yet again. </div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
Don't get me wrong, everything happens because of a perfectly sound reason, but it is not trivial to get everything working, considering all those moving targets. There are also not many engineers around who can really cope with those topics to be honest.</div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
Well. Enough motivation to do the move to Java11, without any JavaFX backed in the java runtime. </div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
<br /></div>
<h4 style="text-align: left;">
SDK! Man!</h4>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
To easily switch between Java versions (and jvm based applications like sbt, lein, scala and others) a tool called <a href="https://sdkman.io/">sdkman</a> exists, which is very handy and lets you download and change used version of Java with a simple command. It's like a package manager, just for specific (java) applications. <b>Highly recommended!</b></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
Here is an example of how it looks if you want to change a java version from current one to to the version AdoptOpenJDK provided, Java version 11:</div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
<br /></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">homemac</span><span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">:sudokufx lad$ sdk list java</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">================================================================================</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">Available Java Versions</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">================================================================================</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> Vendor | Use | Version | Dist | Status | Identifier</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">--------------------------------------------------------------------------------</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> AdoptOpenJDK | | 14.0.1.j9 | adpt | | 14.0.1.j9-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 14.0.1.hs | adpt | | 14.0.1.hs-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 14.0.0.j9 | adpt | local only | 14.0.0.j9-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 13.0.2.j9 | adpt | | 13.0.2.j9-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 13.0.2.hs | adpt | | 13.0.2.hs-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 13.0.1.hs | adpt | local only | 13.0.1.hs-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 12.0.2.j9 | adpt | | 12.0.2.j9-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 12.0.2.hs | adpt | | 12.0.2.hs-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 11.0.7.j9 | adpt | | 11.0.7.j9-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 11.0.7.hs | adpt | installed | 11.0.7.hs-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 8.0.252.j9 | adpt | | 8.0.252.j9-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 8.0.252.hs | adpt | | 8.0.252.hs-adpt </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> Amazon | | 11.0.7 | amzn | | 11.0.7-amzn </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 8.0.252 | amzn | | 8.0.252-amzn </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 8.0.202 | amzn | | 8.0.202-amzn </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> Azul Zulu | | 14.0.1 | zulu | | 14.0.1-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 13.0.3 | zulu | | 13.0.3-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 13.0.3.fx | zulu | | 13.0.3.fx-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 12.0.2 | zulu | | 12.0.2-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 11.0.7 | zulu | | 11.0.7-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 11.0.7.fx | zulu | | 11.0.7.fx-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 11.0.5 | zulu | local only | 11.0.5-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 10.0.2 | zulu | | 10.0.2-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 9.0.7 | zulu | | 9.0.7-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 8.0.252 | zulu | | 8.0.252-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 8.0.252.fx | zulu | | 8.0.252.fx-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 8.0.232.fx | zulu | | 8.0.232.fx-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 8.0.202 | zulu | | 8.0.202-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 7.0.262 | zulu | | 7.0.262-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 7.0.181 | zulu | | 7.0.181-zulu </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> BellSoft | | 14.0.1.fx | librca | | 14.0.1.fx-librca </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 14.0.1 | librca | | 14.0.1-librca </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 13.0.2.fx | librca | | 13.0.2.fx-librca </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 13.0.2 | librca | | 13.0.2-librca </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 12.0.2 | librca | | 12.0.2-librca </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 11.0.7.fx | librca | | 11.0.7.fx-librca </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 11.0.7 | librca | | 11.0.7-librca </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 8.0.252.fx | librca | | 8.0.252.fx-librca </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 8.0.252 | librca | | 8.0.252-librca </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> GraalVM | | 20.0.0.r11 | grl | installed | 20.0.0.r11-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 20.0.0.r8 | grl | | 20.0.0.r8-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 19.3.1.r11 | grl | | 19.3.1.r11-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 19.3.1.r8 | grl | | 19.3.1.r8-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 19.3.0.r11 | grl | | 19.3.0.r11-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 19.3.0.r8 | grl | | 19.3.0.r8-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 19.3.0.2.r11 | grl | | 19.3.0.2.r11-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 19.3.0.2.r8 | grl | | 19.3.0.2.r8-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 19.2.1 | grl | installed | 19.2.1-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 19.1.1 | grl | | 19.1.1-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 19.0.2 | grl | | 19.0.2-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 1.0.0 | grl | | 1.0.0-rc-16-grl </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> Java.net | | 15.ea.20 | open | | 15.ea.20-open </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 14.0.1 | open | | 14.0.1-open </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 13.0.2 | open | | 13.0.2-open </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 12.0.2 | open | | 12.0.2-open </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 11.0.2 | open | | 11.0.2-open </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 10.0.2 | open | | 10.0.2-open </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 9.0.4 | open | | 9.0.4-open </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> SAP | | 14.0.1 | sapmchn | | 14.0.1-sapmchn </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 13.0.2 | sapmchn | | 13.0.2-sapmchn </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 12.0.2 | sapmchn | | 12.0.2-sapmchn </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> | | 11.0.7 | sapmchn | | 11.0.7-sapmchn </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> Unclassified | >>> | 8.0.201 | none | local only | 8.0.201-oracle </span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">================================================================================</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">Use the Identifier for installation:</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> $ sdk install java 11.0.3.hs-adpt</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">================================================================================</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">homemac</span><span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">:sudokufx lad$ sdk use java 11.0.7.hs-adpt</span></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
Now this shell is configured to use Java11. Neat, isn't it? (You also get a taste of how many different variations of Java distributions exist, and the list is surely not complete ... )</div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
I choose AdoptOpenJDK without JavaFX packaging, since I installed and experimented with it already some time ago. </div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
<br /></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">homemac:sudokufx lad$ java -version</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">openjdk version "11.0.7" 2020-04-14</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.7+10)</span></div>
<div style="font-stretch: normal; line-height: normal; min-height: 14px;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.7+10, mixed mode)</span></div>
<div>
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
In IntelliJ I have to change the used JDK as well of course.</div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
<br />
<h4 style="text-align: left;">
Nice. But what does it need to change for Java11 LTS support?</h4>
<div style="font-size: 12px; font-stretch: normal; line-height: normal;">
Here is an enforcer plugin rule to make sure we run at least at Java11 and with a certain maven version:</div>
<div style="font-size: 12px; font-stretch: normal; line-height: normal;">
<br />
<br />
<div style="background-color: #f0f0f0; background-position: initial initial; background-repeat: initial initial; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 15.000000953674316px;"> <span style="color: #062873; font-weight: bold;"><plugin></span>
<span style="color: #062873; font-weight: bold;"><groupId></span>org.apache.maven.plugins<span style="color: #062873; font-weight: bold;"></groupId></span>
<span style="color: #062873; font-weight: bold;"><artifactId></span>maven-enforcer-plugin<span style="color: #062873; font-weight: bold;"></artifactId></span>
<span style="color: #062873; font-weight: bold;"><version></span>3.0.0-M3<span style="color: #062873; font-weight: bold;"></version></span>
<span style="color: #062873; font-weight: bold;"><executions></span>
<span style="color: #062873; font-weight: bold;"><execution></span>
<span style="color: #062873; font-weight: bold;"><id></span>enforce-jdk<span style="color: #062873; font-weight: bold;"></id></span>
<span style="color: #062873; font-weight: bold;"><goals></span>
<span style="color: #062873; font-weight: bold;"><goal></span>enforce<span style="color: #062873; font-weight: bold;"></goal></span>
<span style="color: #062873; font-weight: bold;"></goals></span>
<span style="color: #062873; font-weight: bold;"><configuration></span>
<span style="color: #062873; font-weight: bold;"><rules></span>
<span style="color: #062873; font-weight: bold;"><requireMavenVersion></span>
<span style="color: #062873; font-weight: bold;"><version></span>3.6.2<span style="color: #062873; font-weight: bold;"></version></span>
<span style="color: #062873; font-weight: bold;"></requireMavenVersion></span>
<span style="color: #062873; font-weight: bold;"><requireJavaVersion></span>
<span style="color: #062873; font-weight: bold;"><version></span>11<span style="color: #062873; font-weight: bold;"></version></span>
<span style="color: #062873; font-weight: bold;"></requireJavaVersion></span>
<span style="color: #062873; font-weight: bold;"></rules></span>
<span style="color: #062873; font-weight: bold;"></configuration></span>
<span style="color: #062873; font-weight: bold;"></execution></span>
<span style="color: #062873; font-weight: bold;"></executions></span>
<span style="color: #062873; font-weight: bold;"></plugin></span>
</pre>
</div>
</div>
<div style="font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<br />
<div style="font-size: 12px; font-stretch: normal; line-height: normal;">
</div>
<br />
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<div style="margin: 0px;">
This rules out already some problems and support tickets which is nice. </div>
<div style="margin: 0px;">
<br /></div>
<div style="margin: 0px;">
Like mentioned above, I most certainly have to change some dependencies in my poms (my hobby).</div>
</div>
<span style="font-size: 12px;"><br /></span>
<span style="font-size: 12px;">A valuable resource for JavaFX is of course </span><a href="https://openjfx.io/" style="font-size: 12px;">openjfx.io</a>.<span style="font-size: 12px;"> Here you will find simple tutorials to get you up to speed with simple JavaFX projects which you can then use for your apps. They've developed a maven plugin which does almost everything you ever want concerning JavaFX, I hope I have time to look at this in more detail soon.</span><br />
<span style="font-size: 12px;"><br /></span>
<span style="font-size: 12px;">The company behind this is </span><a href="https://gluonhq.com/" style="font-size: 12px;">Gluon</a><span style="font-size: 12px;">, the most active contributor to JavaFX. They work very hard to provide a Java based platform for user interfaces on Desktop, embedded and mobile, which is very valuable for the Java community.</span></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal; min-height: 14px;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
Thanks to them - and others - JavaFX can be used as a 'normal' maven dependency in your project. Which is awesome, from a library developer point of view as well as a user who wants to use it in their next project. </div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br /></div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
As such, JavaFX got ripped out from the core JRE, like other elements of the JDK it got modularized in <a href="https://www.manning.com/books/the-java-module-system">Project Jigsaw. If you want to know more about this go buy this book</a>, thank me later.</div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br />
<span style="font-size: 12px;">We are getting closer to what I actually had to change in SudokuFX - namely introducing new dependencies and throwing out old unsupported ones.</span><br />
<span style="font-size: 12px;"><br /></span>
<span style="font-size: 12px;"><br /></span></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #f0f0f0; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"> <span style="color: #062873; font-weight: bold;"><dependency></span>
<span style="color: #062873; font-weight: bold;"><groupId></span>org.openjfx<span style="color: #062873; font-weight: bold;"></groupId></span>
<span style="color: #062873; font-weight: bold;"><artifactId></span>javafx-base<span style="color: #062873; font-weight: bold;"></artifactId></span>
<span style="color: #062873; font-weight: bold;"><version></span>11.0.2<span style="color: #062873; font-weight: bold;"></version></span>
<span style="color: #062873; font-weight: bold;"></dependency></span>
<span style="color: #062873; font-weight: bold;"><dependency></span>
<span style="color: #062873; font-weight: bold;"><groupId></span>org.openjfx<span style="color: #062873; font-weight: bold;"></groupId></span>
<span style="color: #062873; font-weight: bold;"><artifactId></span>javafx-swing<span style="color: #062873; font-weight: bold;"></artifactId></span>
<span style="color: #062873; font-weight: bold;"><version></span>11.0.2<span style="color: #062873; font-weight: bold;"></version></span>
<span style="color: #062873; font-weight: bold;"></dependency></span>
<span style="color: #062873; font-weight: bold;"><dependency></span>
<span style="color: #062873; font-weight: bold;"><groupId></span>org.openjfx<span style="color: #062873; font-weight: bold;"></groupId></span>
<span style="color: #062873; font-weight: bold;"><artifactId></span>javafx-fxml<span style="color: #062873; font-weight: bold;"></artifactId></span>
<span style="color: #062873; font-weight: bold;"><version></span>11.0.2<span style="color: #062873; font-weight: bold;"></version></span>
<span style="color: #062873; font-weight: bold;"></dependency></span>
<span style="color: #062873; font-weight: bold;"><dependency></span>
<span style="color: #062873; font-weight: bold;"><groupId></span>org.openjfx<span style="color: #062873; font-weight: bold;"></groupId></span>
<span style="color: #062873; font-weight: bold;"><artifactId></span>javafx-controls<span style="color: #062873; font-weight: bold;"></artifactId></span>
<span style="color: #062873; font-weight: bold;"><version></span>11.0.2<span style="color: #062873; font-weight: bold;"></version></span>
<span style="color: #062873; font-weight: bold;"></dependency></span>
</pre>
</div>
<div style="font-family: "Helvetica Neue"; font-size: 12px; font-stretch: normal; line-height: normal;">
<br />
<br />
In my case, I struggled a little bit with the javafx-swing dependency, since it was not obvious (at the time) it had to be included as well. As you can see I use four javafx maven dependencies.<br />
<br />
Along the way I had to get rid of jfxtras and jfxtras-labs, which don't provide builds for Java11, at least I found none. I also got problems with the scala compiler plugins and IntelliJ (<a href="https://ladstatt.blogspot.com/2020/04/scalafix-sudokufx.html">I introduced them in my last post</a>), but I need them only occasionally and as such I commented them out again.<br />
<br />
So to sum it up, the migration was quite painless, you can have a look at the result on <a href="https://github.com/rladstaetter/sudokufx/releases/tag/2020.2">github - version 2020.2 of SudokuFX</a> ....<br />
<br />
Thanks again for reading</div>
</div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-55351294895032156942020-04-23T23:08:00.003+02:002020-12-29T12:04:04.665+01:00ScalaFix SudokuFX<div dir="ltr" style="text-align: left;" trbidi="on">
I <a href="https://github.com/rladstaetter/sudokufx/releases/tag/v2020.1.1">released a new version of SudokuFX</a>, this time a maintenance release. I some warnings I got from compiling.<br />
<br />To make this a little bit more interesting, I used <a href="https://scalacenter.github.io/scalafix/">scalafix</a> and <a href="https://github.com/scalatest/autofix/tree/master/3.1.x">autofix</a>. What are those things?<br />
<br />
Scalafix is a compiler plugin on top of Scalameta which helps rewriting source code. It provides a framework which can be used for creating own code rewriting rules as well. Autofix is an example for that - it encodes migration rules specifically for ScalaTest.<br />
<br />
After a little bit of maven pom fiddling, autofix is configured for my project. All I needed to do was to add a compiler plugin and an additional plugin in my pluginsection of my root pom.xml:<br />
<br />
<!--HTML generated using hilite.me--><br />
<div style="background-color: #f8f8f8; background: #f8f8f8; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0px;"> <span style="color: green; font-weight: bold;"><pluginManagement></span>
<span style="color: green; font-weight: bold;"><plugins></span>
<span style="color: green; font-weight: bold;"><plugin></span>
<span style="color: green; font-weight: bold;"><groupId></span>net.alchim31.maven<span style="color: green; font-weight: bold;"></groupId></span>
<span style="color: green; font-weight: bold;"><artifactId></span>scala-maven-plugin<span style="color: green; font-weight: bold;"></artifactId></span>
<span style="color: green; font-weight: bold;"><version></span>4.3.1<span style="color: green; font-weight: bold;"></version></span>
<span style="color: green; font-weight: bold;"><executions></span>
<span style="color: green; font-weight: bold;"><execution></span>
<span style="color: green; font-weight: bold;"><goals></span>
<span style="color: green; font-weight: bold;"><goal></span>compile<span style="color: green; font-weight: bold;"></goal></span>
<span style="color: green; font-weight: bold;"><goal></span>testCompile<span style="color: green; font-weight: bold;"></goal></span>
<span style="color: green; font-weight: bold;"></goals></span>
<span style="color: green; font-weight: bold;"></execution></span>
<span style="color: green; font-weight: bold;"></executions></span>
<span style="color: green; font-weight: bold;"><configuration></span>
<span style="color: green; font-weight: bold;"><scalaVersion></span>${scala.major.version}<span style="color: green; font-weight: bold;"></scalaVersion></span>
<span style="color: green; font-weight: bold;"><args></span>
...
<span style="color: green; font-weight: bold;"></args></span>
<span style="color: green; font-weight: bold;"><compilerPlugins></span>
<span style="color: green; font-weight: bold;"><compilerPlugin></span>
<span style="color: green; font-weight: bold;"><groupId></span>org.scalameta<span style="color: green; font-weight: bold;"></groupId></span>
<span style="color: green; font-weight: bold;"><artifactId></span>semanticdb-scalac_${scala.full.version}<span style="color: green; font-weight: bold;"></artifactId></span>
<span style="color: green; font-weight: bold;"><version></span>4.3.9<span style="color: green; font-weight: bold;"></version></span>
<span style="color: green; font-weight: bold;"></compilerPlugin></span>
<span style="color: green; font-weight: bold;"></compilerPlugins></span>
<span style="color: green; font-weight: bold;"></configuration></span>
<span style="color: green; font-weight: bold;"></plugin></span>
<span style="color: green; font-weight: bold;"><plugin></span>
<span style="color: green; font-weight: bold;"><groupId></span>io.github.evis<span style="color: green; font-weight: bold;"></groupId></span>
<span style="color: green; font-weight: bold;"><artifactId></span>scalafix-maven-plugin<span style="color: green; font-weight: bold;"></artifactId></span>
<span style="color: green; font-weight: bold;"><version></span>0.1.2_0.9.5<span style="color: green; font-weight: bold;"></version></span>
<span style="color: green; font-weight: bold;"><dependencies></span>
<span style="color: green; font-weight: bold;"><dependency></span>
<span style="color: green; font-weight: bold;"><groupId></span>org.scalatest<span style="color: green; font-weight: bold;"></groupId></span>
<span style="color: green; font-weight: bold;"><artifactId></span>autofix_2.12<span style="color: green; font-weight: bold;"></artifactId></span>
<span style="color: green; font-weight: bold;"><version></span>3.1.0.0<span style="color: green; font-weight: bold;"></version></span>
<span style="color: green; font-weight: bold;"></dependency></span>
<span style="color: green; font-weight: bold;"></dependencies></span>
<span style="color: green; font-weight: bold;"></plugin></span>
<span style="color: green; font-weight: bold;"></plugins></span>
<span style="color: green; font-weight: bold;"></pluginManagement></span>
</pre>
</div>
<br />
Thats it ... more or less.<br />
<br />
What is still missing is a configuration for scalafix, which is placed in a file called <span style="font-family: "courier new" , "courier" , monospace;">.scalafix.conf</span>. (Note the '.' at the beginning of the file name). This file should be placed next to the main pom file.<br />
<br />
Here is the file how I configured it:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">rules = [</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> RemoveUnused,<span style="background-color: black; color: white;">RewriteDeprecatedNames</span>,ProcedureSyntax,NoValInForComprehension,LeakingImplicitClassVal,NoAutoTupling</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">]</span><br />
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
The inverted rule name is an autofix rule, which comes with the additional dependency for scalafix-maven-plugin. <br />
<br />
After configuring this, you have to call maven like that:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">mvn clean compile test-compile scalafix:scalafix</span><br />
<br />
After that, have a look at your git status, you'll see that many files have changed, and the plugin did what was promised: it rewrote source code, applied trivial but useful transformations. For example, it can remove unused imports out of the box, or rewrite code written in procedural style <a href="https://scalacenter.github.io/scalafix/docs/rules/overview.html">and many other things</a>.<br />
<br />Scalafix can be extended with own plugins, that means in theory you could implement your own rules, specific to your needs. This enables then automatic rewrites which are not only syntactic (which could also be achieved by clever scripting) but semantic: rewrite rules know about the structure of the code. This helps for automating tasks which otherwise would bind valuable developer time ...</div><div dir="ltr" style="text-align: left;" trbidi="on">
<br />I removed other warnings as well, albeit manually, from the source. By doing that, I got new 'unused imports', which swiftly went away by calling just beforementioned mvn command again while I gazed with amazement to my editor watching the computer doing the work for me.<br />
<br />
Here is a <a href="https://index.scala-lang.org/search?q=scalafix">list of available scalafix rules</a> - or at least the closest to such a list I could find.<br />
<br />
<br />
Hope I raised your interest in this amazing tooling, check out how to <a href="https://github.com/rladstaetter/sudokufx/releases/tag/v2020.1.1">configure ScalaFix for maven</a> (and try to solve some Sudokus and let me know if it worked ;-))</div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-7128017796342659782020-04-19T22:32:00.003+02:002020-04-20T22:09:55.047+02:00SudokuFx revisited<div dir="ltr" style="text-align: left;" trbidi="on">
This blog post covers my lazy sunday afternoon where I tried to get my <a href="https://github.com/rladstaetter/sudokufx">ancient Sudoku project running again</a>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnIXOFlORF9zyRORTO5vTZdIRzNyUdNZQxhwf9JACFQiOyEkeD94y0PUqLRSLvXAZNmSi_Uw5SlF25H_dGNCbW_oLW0IuEz6cYJt28Ukz7lnFe7kukBiP_mF3SI6IsHgnSiK01F-QA08Lt/s1600/s2.gif" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="540" data-original-width="640" height="337" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnIXOFlORF9zyRORTO5vTZdIRzNyUdNZQxhwf9JACFQiOyEkeD94y0PUqLRSLvXAZNmSi_Uw5SlF25H_dGNCbW_oLW0IuEz6cYJt28Ukz7lnFe7kukBiP_mF3SI6IsHgnSiK01F-QA08Lt/s400/s2.gif" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">screen capture of application</td></tr>
</tbody></table>
(If you wonder why those numbers dance around - depending on what the application recognises different solutions are calculated and presented ... yes it's not perfect ;-) )<br />
<br />
Years ago I played around with the idea of solving Sudokus with an algorithm and used JavaFX and OpenCV to do it. Quite an unusual combination, then as it is now - but it wasn't really a bad experience at all. In my view the Java OpenCV API is quite usable, and as such I wanted to prove at least for me that I could get it to run (albeit its far from perfect ;-))<br />
<br />
I remember spending hours playing around with different filters and effects, always proud of new things I discovered.<br />
<br />
Today, I decided to breathe life again into this project, let's see which problems I'll encounter.<br />
<br />
First, getting source code from github still works, my last commit already 4 years ago, zero contributors along all those years, that's what a normal OSS project looks like ;-).<br />
<br />
I try to revive it again, just the desktop version of it, leaving the android version on my todo list.<br />
<br />
First obstacle I hit is to compile it, OpenCV is missing on my system. <strike>OpenCV doesn't have a proper maven integration, there is an ancient issue about this, nobody had the mood or skills to solve it yet. </strike><br />
<br />
Update: <a href="https://github.com/opencv/opencv/tree/master/platforms/maven">I learned that there is somekind of maven integration in the meantime</a>! Great!! Anyway, I build OpenCV from scratch for this article, maybe I'll have a go at the maven build another time.<br />
<br />
<h4 style="text-align: left;">
Step 1 - download and compile OpenCV 4.3.0</h4>
<br />
First, I want to mention that there are several package mangers which provide prebuilt binaries for OpenCV, homebrew for example. It may well be that this is an option you prefer If you stumbled on this page by googling (seems to be rather unlikely but well).<br />
<br />
Ok, in the meantime they reached version 4.3.0 something, I download the <a href="https://github.com/opencv/opencv/releases/tag/4.3.0">zip from here</a> but I'm too dumb to find build instructions ... No obvious links are neither on the main page nor documentation. (They surely exist but I just didn't see them apparently)<br />
<br />
Finally,<a href="https://docs.opencv.org/master/d0/db2/tutorial_macos_install.html"> I found them</a>.<br />
<br />
<br />
There are numerous steps to follow, you'll need Cmake and quite some time during compilation, educated guesses what to choose, we'll go with defaults for the first try. Unzip it somewhere, I choose<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">~/custom-builds/opencv-4.3.0/src/ </span><br />
<br />
since we have the famous 'out of source' build CMake proposes as best practice. This means that there is a dedicated directory for build artifacts.<br />
<br />
As such I choose following setup:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">~/custom-builds/opencv-3.4.0/src/</span><actual contents of zip><br />
<span style="font-family: "courier new" , "courier" , monospace;">~/custom-builds/opencv-3.4.0/target/</span><here build artefacts will be placed><br />
<br />
I jump to this target directory and execute there following command:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">cmake ../src/</span><br />
<br />
... then CMake does it's job, checks for all available goodies found on my system, I pray that the right ones I need are contained, otherwise I will have to configure it and fight the dragons of OpenCV ... again.<br />
<br />
... But it seems that I'm lucky, at the end of the cmake output it says something about java bindings, which I'm interested in, as such it should compile it like I want.<br />
<br />
What I personally don't want is that it installs itself to some system directory, which will definitely pollute my system and break some stuff already fine tuned there, as such I have to Issue CMake again with a proper parameter:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">cmake ../src -DCMAKE_INSTALL_PREFIX=../out</span><br />
<br />
(Pro tip: delete your target directory beforehand completely, thank me later). This would put OpenCv then to a directory:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">~/custom-builds/opencv-3.4.0/out/</span><br />
<br />
Like that I can delete it again without any trace.<br />
<br />
I'm quite sure I don't need 98% what is going to be compiled, and some magic incantation of CMake or it's configuration would prevent compiling and linking it, but I don't want to go down that road, not today.<br />
<br />
After configuring CMake you have to invoke 'make' as well, and do it with full throttle, meaning with some concurrent threads to speed things up (yes, you can get your coffee break since it will take a while).<br />
<br />
That said, still being in the target directory, now execute<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">make -j8</span><br />
<br />
which will use 8 threads to compile OpenCV (takes 5min+ on my machine)<br />
<br />
<i>In the meantime, I want to mention it is a huge accomplishment that building from scratch 'just works' for many environments, be it MacOsX, Windows, Linux ... this is much work and should be praised!</i><br />
<br />
Everytime I compile something I'm amazed if it works first time without much hassle.... I've spent already countless hours on resolving build problems, it is a major time drain.<br />
<br />
Anyhow, make succeeded, and all build outputs are already somewhere lying in the target dir. But with<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">make install</span><br />
<br />
everything important for the runtime will be put to the ../out directory.<br />
<br />
Specifically, one can find dylibs in the out/lib and out/share/java/opencv4 directory.<br />
<br />
<h4 style="text-align: left;">
Step 2 - Make OpenCV available to Maven</h4>
<div>
<br /></div>
I tried to make this easy, all you have to do is to edit the main pom file and tweak some properties and point to your opencv installation directories. Here is an example configuration:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"> <span style="color: #007700;"><properties></span>
<span style="color: #007700;"><project.build.sourceEncoding></span>UTF-8<span style="color: #007700;"></project.build.sourceEncoding></span>
<span style="color: #007700;"><scala.major.version></span>2.12<span style="color: #007700;"></scala.major.version></span>
<span style="color: #007700;"><scala.full.version></span>${scala.major.version}.10<span style="color: #007700;"></scala.full.version></span>
<span style="color: #007700;"><opencv.major.version></span>4.3<span style="color: #007700;"></opencv.major.version></span>
<span style="color: #007700;"><opencv.full.version></span>${opencv.major.version}.0<span style="color: #007700;"></opencv.full.version></span>
<span style="color: #007700;"><opencv.install.path></span>/Users/lad/custom-builds/opencv-4.3.0/out/<span style="color: #007700;"></opencv.install.path></span>
<span style="color: #007700;"><opencv.java.jar></span>${opencv.install.path}share/java/opencv4/opencv-430.jar<span style="color: #007700;"></opencv.java.jar></span>
<span style="color: #007700;"></properties></span>
</pre>
</div>
<br />
After you've changed those settings to your liking, enter following command:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">mvn initialize -Pinstall-opencv -N </span><br />
<br />
Now you should be ready to go, build the project with<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">mvn package</span><br />
<br />
It shouldn't take too long, and everything should be set up correctly. OpenCV has many dylibs / dlls, which are referenced in this project, but via maven property filtering and some pseudo magic everything should just work.<br />
<br />
You can fire it up via (being in the main directory of the project)<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">java -jar sudoku-javafx/target/sudoku-javafx-2020.1-SNAPSHOT-jar-with-dependencies.jar</span><br />
<br />
A JavaFx Gui should appear, on the first invocation you maybe have to tell your Os that it is ok to give SudokuFx access to the webcam.<br />
<br />
I've blogged about this project in several <a href="https://ladstatt.blogspot.com/2013/07/sudoku-solver-with-scala-javafx-and.html">other blogposts</a>, maybe you want to<a href="http://ladstatt.blogspot.co.at/2013/07/sudoku-grabber-and-solver-part-ii.html"> read them as well</a>.<br />
<br />
This post is referencing code state from the <a href="https://github.com/rladstaetter/sudokufx/releases/tag/v2020.1">2020.1 resurrection release</a>.<br />
<br />
To sum up, compiling OpenCV turned out to be much easier now as it was years ago, only my code was a little bitrotten - still is - but at least it should be easier to get it to run now than it was before this little article.<br />
<br />
Thanks for reading!<br />
<br /></div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-32887524225174448332020-04-16T00:00:00.000+02:002020-04-16T00:00:33.029+02:00Artifact Dashboard: Make it pretty<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
In this blog post I'll cover how to use <a href="https://www.webjars.org/">webjars</a> in conjunction with sbt. The plan is to download <a href="https://getbootstrap.com/">bootstrap</a> and maybe other web techniques via maven artefacts. </div>
<div>
<br /></div>
This blog post is a <a href="https://ladstatt.blogspot.com/2020/04/artifact-dashboard-custom-nexus-summary.html">successor </a>to another blog post I made only recently, I had the feel it should have better looks, so here we go.<br />
<div>
<br /></div>
<h3 style="text-align: left;">
Motivation</h3>
<div>
I'm well aware that there are <a href="https://bower.io/">package</a> <a href="https://www.npmjs.com/">managers</a> <a href="https://yarnpkg.com/">for</a> <a href="https://jspm.io/">javascript</a>, at least I've heard of them - not overly good things - but I heard of them. Chances are high that if you continue to read to the end of this post there has been a new one invented.<br />
<br />
In my bubble, in the past - well, many years - I had to fiddle around with JVM de factor standard build systems like <a href="http://maven.apache.org/">maven</a> or <a href="https://www.gradle.org/">gradle</a>, and if i neglect countless hours of fustration with them I have to admit they served me well. As such, I'll stay with this ecosystem, at least I use it in creative ways. Well, sort of. I'll use <a href="https://www.scala-sbt.org/">sbt</a> to download dependencies and build the example project, I hope I got your head spinning in the meantime.</div>
<div>
<br /></div>
<div>
Reality chck: One thing I would advise to avoid is to have too many package managers in your corporate setting, it is a maintenance burden which gets multiplied by each new system. Naturally, every build system wants to outmatch the other ones, either in complexity or in the wealth of features it provides. (One advice: Sometimes it pays off to bet on the most conservative option, but I doubt you'll find such a thing in javascript land. 😉)</div>
<div>
<br /></div>
<div>
In some bright moments however, different worlds work together, and this blog post wants to shed a light on how to combine web techniques with tools used for corporate settings.</div>
<div>
<br /></div>
<blockquote class="tr_bq">
To put it bluntly, I try to download a jar file containing prepacked static content containing a bunch of javascript and other resources and put it at the right place - on demand.</blockquote>
<div>
<br /></div>
<div>
For example, I want to use bootstrap in my project - just go to their website, download it, extract things you are interested in, move on? </div>
<div>
<br /></div>
<div>
Of course this is a valid - and most probably - the most used approach by a majority of developer teams, but it has some drawbacks. </div>
<div>
<br /></div>
<div>
First, it is unclear where such frameworks come from. It is also hard to tell 'afterwards' which file belongs to which framework. You are left to best guessing based on directory or zip file names. A concern might be the licensing situation - how to tell if a bunch of code maybe inflicts legal issues in your code? What about if you want to update a certain library - often you can be glad if you even know which version you currently use. </div>
<div>
<br /></div>
<div>
Of course you can document it, but odds are high that this documentation is not really in sync with your code, at least you have to check manually that this is the case. Another anti pattern which comes to mind is that third party code will be checked in your code repository, no matter how hard you fight it, by some innocent but mindless colleague. The best thing about is, that you'll surely find the same library downloaded and checked in multiple times, maybe also in different versions, open doors for subtle bugs, o my god, in PRODUCTION. Insane! Mind blowing! (<a href="https://www.youtube.com/davie504">Yes I play bass and yes I slap and yes I know davie504</a>)</div>
<div>
<br />
There has to be a reason why such a zoo of package managers exist, for each programming language several of them, along with their ecosystems, everybody fighting for the attention of the very confused poor Mr. Bob Developer.<br />
<br /></div>
<div>
As such, for all of the good reasons cited above, there is an excuse to automate it yet again and write a blog post about it, mainly for <u>you</u> who reads this with intense boredom waiting for the anticlimax which is yet to come.</div>
<div>
<br /></div>
<h4 style="text-align: left;">
Implementation</h4>
<div>
I'll continue to work on the <a href="https://github.com/rladstaetter/artifact-dashboard">artifact-dashboard</a> project, and enhance <a href="https://github.com/rladstaetter/artifact-dashboard/releases/tag/v0.4">version 0.4</a> by adding necessary commands to the sbt build file to download <a href="https://getbootstrap.com/">bootstrap</a>.</div>
<div>
<br /></div>
<div>
Before reading on, maybe you want to inform yourself about <a href="http://webjars.org/">webjars.org</a>, whose mission statement is </div>
<blockquote class="tr_bq">
WebJars are client-side web libraries (e.g. jQuery & Bootstrap) packaged into JAR (Java Archive) files.</blockquote>
<div>
This is exactly what we need, what I tried to convey above with my ranting about problems if you don't use any sort of package manager. Webjars.org is a really cool project for all JVM engineers who don't want to get their hands too dirty with front end development, stay cozy in their own world, not to touch those strange javascript package managers alltogether.<br />
<br />
Besides, source code management is trivial, right?</div>
<div>
<br />
Don't worry, to download bootstrap via sbt is far less text than the rant above, but maybe more interesting.<br />
<br /></div>
<div>
To download and unpack it, not much is necessary, witness it here:</div>
<div>
<br /></div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;">enablePlugins<span style="color: #333333;">(</span><span style="color: #bb0066; font-weight: bold;">ScalaJSPlugin</span><span style="color: #333333;">)</span>
name <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">"artifact-dashboard"</span>
scalaVersion <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">"2.12.10"</span>
<span style="color: #888888;">// This is an application with a main method</span>
scalaJSUseMainModuleInitializer <span style="color: #333333;">:=</span> <span style="color: #008800; font-weight: bold;">true</span>
libraryDependencies <span style="color: #333333;">++=</span>
<span style="color: #bb0066; font-weight: bold;">Seq</span><span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"org.scala-js"</span> <span style="color: #333333;">%%%</span> <span style="background-color: #fff0f0;">"scalajs-dom"</span> <span style="color: #333333;">%</span> <span style="background-color: #fff0f0;">"1.0.0"</span>
<span style="color: #333333;">,</span> <span style="background-color: #fff0f0;">"org.webjars"</span> <span style="color: #333333;">%</span> <span style="background-color: #fff0f0;">"bootstrap"</span> <span style="color: #333333;">%</span> <span style="background-color: #fff0f0;">"4.4.1"</span><span style="color: #333333;">)</span>
<span style="color: #888888;">// defines sbt name filters for unpacking</span>
<span style="color: #008800; font-weight: bold;">val</span> bootstrapMinJs<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">NameFilter</span> <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"**/bootstrap.min.js"</span>
<span style="color: #008800; font-weight: bold;">val</span> bootstrapMinCss<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">NameFilter</span> <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"**/bootstrap.min.css"</span>
<span style="color: #008800; font-weight: bold;">val</span> bootstrapFilters<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">NameFilter</span> <span style="color: #333333;">=</span> bootstrapMinCss <span style="color: #333333;">|</span> bootstrapMinJs
<span style="color: #888888;">// magic to invoke unpacking stuff in the compile phase</span>
resourceGenerators in <span style="color: #bb0066; font-weight: bold;">Compile</span> <span style="color: #333333;">+=</span> <span style="color: #bb0066; font-weight: bold;">Def</span><span style="color: #333333;">.</span>task <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">val</span> jar <span style="color: #008800; font-weight: bold;">=</span> <span style="color: #333333;">(</span>update in <span style="color: #bb0066; font-weight: bold;">Compile</span><span style="color: #333333;">).</span>value
<span style="color: #333333;">.</span>select<span style="color: #333333;">(</span>configurationFilter<span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"compile"</span><span style="color: #333333;">))</span>
<span style="color: #333333;">.</span>filter<span style="color: #333333;">(</span><span style="color: #008800; font-weight: bold;">_</span><span style="color: #333333;">.</span>name<span style="color: #333333;">.</span>contains<span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"bootstrap"</span><span style="color: #333333;">))</span>
<span style="color: #333333;">.</span>head
<span style="color: #008800; font-weight: bold;">val</span> to <span style="color: #008800; font-weight: bold;">=</span> <span style="color: #333333;">(</span>target in <span style="color: #bb0066; font-weight: bold;">Compile</span><span style="color: #333333;">).</span>value
unpackjar<span style="color: #333333;">(</span>jar<span style="color: #333333;">,</span> to<span style="color: #333333;">,</span> bootstrapFilters<span style="color: #333333;">)</span>
<span style="color: #bb0066; font-weight: bold;">Seq</span><span style="color: #333333;">.</span>empty<span style="color: #333333;">[</span><span style="color: #333399; font-weight: bold;">File</span><span style="color: #333333;">]</span>
<span style="color: #333333;">}.</span>taskValue
<span style="color: #888888;">// a helper function which unzips files defined in given namefilter</span>
<span style="color: #888888;">// to a given directory, along with some reporting</span>
<span style="color: #008800; font-weight: bold;">def</span> unpackjar<span style="color: #333333;">(</span>jar<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">File</span><span style="color: #333333;">,</span> to<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">File</span><span style="color: #333333;">,</span> filter<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">NameFilter</span><span style="color: #333333;">)</span><span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">File</span> <span style="color: #333333;">=</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">val</span> files<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">Set</span><span style="color: #333333;">[</span><span style="color: #333399; font-weight: bold;">File</span><span style="color: #333333;">]</span> <span style="color: #008800; font-weight: bold;">=</span> <span style="color: #bb0066; font-weight: bold;">IO</span><span style="color: #333333;">.</span>unzip<span style="color: #333333;">(</span>jar<span style="color: #333333;">,</span> to<span style="color: #333333;">,</span> filter<span style="color: #333333;">)</span>
<span style="color: #888888;">// print it out so we can see some progress on the sbt console</span>
println<span style="color: #333333;">(</span>s<span style="background-color: #fff0f0;">"Processing $jar and unzipping to $to"</span><span style="color: #333333;">)</span>
files foreach println
jar
<span style="color: #333333;">}</span>
</pre>
</div>
<div>
<br /></div>
<div>
This is part of <a href="https://github.com/rladstaetter/artifact-dashboard/releases/tag/v0.5">v0.5 of the artifact-dashboard</a> project, and this is the complete sbt file which is necessary to download a version of bootstrap - at the time of writing the most current one - unpacking it to the right place and make it available for the javascript code.<br />
<br />
As usual, you only have to provide the correct paths in your html file to the javascript code, and you can profit from all the goodies bootstrap has to offer.<br />
<br />
As a side note, I tweaked also a little bit how Scala.js is used, have a look in the source code / html file.<br />
<br />
I think it is a nice combination of technologies, don't know if it is popular, at least it works for me.<br />
<br />
Using bootstrap, our download page looks far better, users will surely be more willing to click on a download link than ever before.<br />
<br />
Here is a little screenshot of the current state of affairs with v0.5 of artifact dashboard in action for my test instance:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-4PlJ4cXn2WDMiXjL0Ttnm3Ae7eYkclRJkSez81qtdxoTqDhQKutXqNbjR6-KNTNoCiAKOgRIlpsSKgTzUV21e0rGVFKdFdmtAgVnh4b5gfoG7PPku12VFNc3LaCGNW9fmKkIACvQsb7m/s1600/Artifact_Dashboard.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="306" data-original-width="1184" height="164" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-4PlJ4cXn2WDMiXjL0Ttnm3Ae7eYkclRJkSez81qtdxoTqDhQKutXqNbjR6-KNTNoCiAKOgRIlpsSKgTzUV21e0rGVFKdFdmtAgVnh4b5gfoG7PPku12VFNc3LaCGNW9fmKkIACvQsb7m/s640/Artifact_Dashboard.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Screenshot of Artifact Dashboard v0.5</td></tr>
</tbody></table>
<br /></div>
<div>
<br /></div>
<div>
Thanks for reading.</div>
<div>
<br /></div>
</div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-36773802697988896742020-04-14T22:45:00.000+02:002020-04-16T00:01:57.537+02:00Artifact Dashboard: Custom Nexus Summary Page<div dir="ltr" style="text-align: left;" trbidi="on">
<h3 style="text-align: left;">
Motivation</h3>
<div>
In this post I want to discuss a small project called <a href="https://github.com/rladstaetter/artifact-dashboard">artifact-dashboard</a> which shows<br />
<br />
<b>how to use Nexus Repository Manager, Version 3, and it's Rest API. </b></div>
<div>
<br />
(This article is a part of a mini series of blog posts, see the second part <a href="https://ladstatt.blogspot.com/2020/04/artifact-dashboard-make-it-pretty.html">here</a>.)</div>
<div>
<br />
I use my preferred technologies (and by doing that I almost successfully circumvent using Javascript entirely), namely Scala and Scala.js, maven, sbt powered by severe googling.</div>
<div>
<br /></div>
<div>
Introduced with version 3, Nexus Repo Manager's REST API provides means to query about the state of artifacts which are deployed on the server. (Of course, many other things are possible doing with this API - like for example query licensing status or health status etc.)<br />
<br />
<b>My plan is to create a self contained website with some 'dynamic' download links by using information retrieved from Nexus REST API, namely latest snapshots or 'interesting' artifacts like product packages, installers etc. </b><br />
<br />
In a typical small company setting, this alleviates engineering from daily questions like: 'where is the latest version of our software?...' since everything up to the point of downloading artifacts is automated. (I'm talking about SNAPSHOT / LATEST versions which potentially change permanently and don't have a stable url to download them from Nexus.<br />
<br />
(Thinking of it, maybe there is a custom workflow directly baked in to Nexus Repo Manager, I didn't check recent docs, maybe in the process of writing this I'll learn more about it. (<i>UPDATE: I think there is an alternate (or maybe first hand) way to do what I describe by using well configured '<a href="https://help.sonatype.com/repomanager3/configuration/repository-management#RepositoryManagement-ContentSelectors">Content Selector</a>'s - a concept I didn't yet know starting this post</i>); UPDATE 2: Obviously<a href="https://community.sonatype.com/t/latest-snapshot-artifact-version-from-snapshot-repository-through-api/1059"> I'm not the only one</a> who would like such a thing, <a href="https://issues.sonatype.org/browse/NEXUS-14407">it was resolved already</a>, but anyway I'll continue with my effort to learn more about it. UPDATE 3: My whole approach reduces itself mainly to a single rest call - which is nice)<br />
<br /></div>
<div>
Anyway, it will be a way to learn both about Scala.js and creating minimalistic UI's with it. My goal is to create a standalone html page which uses Javascript to automatically create correct download urls, just for the fun of it. So let's dive in.</div>
<div>
<br /></div>
<h4 style="text-align: left;">
Prerequisites</h4>
<div>
If you have not already done so, I would recommend installing <a href="https://www.jetbrains.com/idea/">IntelliJ Community Edition</a> along with its excellent Scala plugin and checkout the <a href="https://github.com/rladstaetter/artifact-dashboard">github project</a> which accompanies this post.<br />
<br />
LPT: Checkout code and skip the whole blog post!</div>
<div>
<br /></div>
<div>
We need a rest service which we want to query, the whole purpose of this post is to be able to talk to the Nexus Rest API. It is available starting with version 3 of this software package (in fact I learned that Nexus provided an API already in the 2.x series, but here I'll cover v3), which can be downloaded on <a href="https://www.sonatype.com/nexus-repository-oss">Sonatype's website for OSS Nexus Repository</a>.<br />
<br />
You'll have to register an account, then you can download a version for your platform. You have to do a basic setup, and create an administrative account, we'll see what we need along the way.<br />
<br />
You'll need also a small maven project to deploy to your test repository, I would recommend something <a href="https://github.com/rladstaetter/fx-animations">small and simple without many dependencies</a> or huge build times, or you deploy your artifacts directly to Nexus via the web gui. </div>
<div>
<br /></div>
<h4 style="text-align: left;">
Step 1 - Basic Scala.js project setup</h4>
<div>
I start from scratch by creating more or less a Scala.js 'Hello world' minimal example.<br />
<br />
For convenience, I made some releases in artifact-dashboard which covers different milestones during development, and can be downloaded as zip files.<br />
<br />
Release <a href="https://github.com/rladstaetter/artifact-dashboard/releases/tag/v0.1">v0.1 contains just a raw setup with more or less current versions of Scala.js</a> and friends at the time of writing this post.</div>
<div>
<br /></div>
<div>
Nothing fancy here, just a minimal sbt build definition. On the sbt console you have to issue a '<span style="font-family: "courier new" , "courier" , monospace;">fastOptJS</span>' command such that Scala.js compiles (later then do a '<span style="font-family: "courier new" , "courier" , monospace;">fullOptJS</span>' to obtain the best optimized Javascript available ;-) ).<br />
<br />
The most interesting part are the few lines of Scala code shown below:</div>
<div>
<br /></div>
<div>
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">package</span> <span style="color: #0e84b5; font-weight: bold;">net.ladstatt.adash</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">org.scalajs.dom.document</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">org.scalajs.dom.raw.Element</span>
<span style="color: #008800; font-weight: bold;">object</span> <span style="color: #bb0066; font-weight: bold;">ArtifactDashboard</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">def</span> main<span style="color: #333333;">(</span>args<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">Array</span><span style="color: #333333;">[</span><span style="color: #333399; font-weight: bold;">String</span><span style="color: #333333;">])</span><span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">Unit</span> <span style="color: #333333;">=</span> <span style="color: #333333;">{</span>
document<span style="color: #333333;">.</span>body<span style="color: #333333;">.</span>appendChild<span style="color: #333333;">(</span>p<span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"Paragraph filled via Scala.js"</span><span style="color: #333333;">))</span>
<span style="color: #333333;">}</span>
<span style="color: #008800; font-weight: bold;">def</span> p<span style="color: #333333;">(</span>text<span style="color: #008800; font-weight: bold;">:</span><span style="color: #333399; font-weight: bold;">String</span><span style="color: #333333;">)</span><span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">Element</span> <span style="color: #333333;">=</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">val</span> p <span style="color: #008800; font-weight: bold;">=</span> document<span style="color: #333333;">.</span>createElement<span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"p"</span><span style="color: #333333;">)</span>
p<span style="color: #333333;">.</span>textContent <span style="color: #008800; font-weight: bold;">=</span> text
p
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span>
</pre>
</div>
<br /></div>
<div>
By importing '<span style="font-family: "courier new" , "courier" , monospace;">org.scalajs.dom</span>' you'll get access to the page dom ... and there you go. We don't need much more than that (ignoring all the magic behind the scenes) to create more or less what we want on the html page. Attention: Don't forget to import a library in your build.sbt (scalajs-dom) otherwise it won't work.<br />
<br />
Side note: It would be more coherent if we would only use Scala + Maven (there is a plugin available for this) - sadly enough it doesn't support Scala.js compilation. However, there exists another <a href="https://github.com/random-maven/scalor-maven-plugin">maven plugin - I don't use for no particular reason - which should support Scala.js compilation</a>. Furthermore I learned that there is a possibility to execute Scala.js cross compiler as a command line tool which would also be a possible approach, but not today. We'll stick to sbt.<br />
<br />
<h4 style="text-align: left;">
Step 2 - setup Nexus for a simple rest call</h4>
Ok, up to here you should have a running Nexus 3 Instance somewhere. If you don't have access to one already, make sure to download a free OSS version from <a href="https://www.sonatype.com/nexus-repository-oss">Sonatype's website</a>. To make things easy for me and this blog post, I assume from now on that a running Nexus on localhost is present.<br />
<br />
When you download a fresh one, make sure that you execute Maven once - configured to use this local installation. This is necessary as to fill your Nexus instance with some data we can query later.<br />
<br />
The easiest way for that is to change your settings.xml file to point to your local Nexus, for me it worked to configure the 'mirror's section like shown below:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #557799;"><?xml version="1.0" encoding="UTF-8"?></span>
<span style="color: #007700;"><settings</span>
<span style="color: #0000cc;">xsi:schemaLocation=</span><span style="background-color: #fff0f0;">"http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"</span>
<span style="color: #0000cc;">xmlns=</span><span style="background-color: #fff0f0;">"http://maven.apache.org/SETTINGS/1.0.0"</span> <span style="color: #0000cc;">xmlns:xsi=</span><span style="background-color: #fff0f0;">"http://www.w3.org/2001/XMLSchema-instance"</span><span style="color: #007700;">></span>
<span style="color: #007700;"><mirrors></span>
<span style="color: #007700;"><mirror></span>
<span style="color: #007700;"><id></span>local-nexus<span style="color: #007700;"></id></span>
<span style="color: #007700;"><mirrorOf></span>*<span style="color: #007700;"></mirrorOf></span>
<span style="color: #007700;"><url></span>http://127.0.0.1:8081/repository/maven-public/<span style="color: #007700;"></url></span>
<span style="color: #007700;"></mirror></span>
<span style="color: #007700;"></mirrors></span>
<span style="color: #007700;"></settings></span>
</pre>
</div>
<br />
<br />
Now we should have some data in our Nexus, to my current understanding Nexus should now return some useful result on its API. Luckily enough Nexus provides itself a nice testbed for API calls, directly baked in in its user interface. The UI for the Rest API can be easily found in the administration console (default address: http://127.0.0.1:8081/#admin/system/api)<br />
<br />
Let's try the easiest api call, or is it, at least the first one, '/v1/assets'.<br />
<br />
You have to provide which repository to query, just enter 'maven-public' and click on 'execute'.<br />
<br />
Do it! Do it now. I'll wait.<br />
<br />
<h4 style="text-align: left;">
Step 3 - implement rest call with Scala.js</h4>
At this point you should now gaze with amazement on the Nexus Administrative Console, and see a response for the rest api call. The guys from sonatype even included a directly executable command line invocation for curl, which looks like this in my case:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">curl -X GET "http://127.0.0.1:8081/service/rest/v1/assets?repository=maven-public" -H "accept: application/json"</span><br />
<br />
I can copy paste this into a terminal, and it returns a json list of assets which proves that at least something is going on, and thus we can continue with implementing a corresponding call in Scala.js.<br />
<br />
<span style="color: red;">... and then I rediscovered a thing called 'CORS' ;-) </span><br />
<br />
<b>TLDR</b>, the approach of calling a REST api from an html page doesn't work if it is not from the same origin like the api, that means it has to be served from the same server. <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy">See this article for more information</a>.<br />
<br />
So curl is working perfectly, but having a website calling this rest api is not possible, which is a good thing security wise. There are ways to work around for this problem, the easiest one is to place the final html and javascript in the public folder of the Nexus installation itself, which may not be viable for a variety of reasons.<br />
<br />
For educational purposes I pursue this approach however. Keep in mind that the whole point of this blog post is to learn about how to work with Scala.js and communicate with webservices, not necessarily with Nexus, maybe create your own little rest service and play with it.<br />
<br />
<a href="https://github.com/rladstaetter/artifact-dashboard/releases/tag/v0.2">Version v0.2</a> of the project is tagged at a state where a minimal example for a webservice setup is given, for completeness and also to show how easy it is I'll include the source code here as well:<br />
<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">package</span> <span style="color: #0e84b5; font-weight: bold;">net.ladstatt.adash</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">org.scalajs.dom.document</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">org.scalajs.dom.ext.Ajax</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">org.scalajs.dom.raw.Element</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">scala.concurrent.ExecutionContextExecutor</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">scala.scalajs.js</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">scala.scalajs.js.JSON</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">scala.util.</span><span style="color: #333333;">{</span><span style="color: #bb0066; font-weight: bold;">Failure</span><span style="color: #333333;">,</span> <span style="color: #bb0066; font-weight: bold;">Success</span><span style="color: #333333;">}</span>
<span style="color: #555555; font-weight: bold;">@js</span><span style="color: #333333;">.</span>native
<span style="color: #008800; font-weight: bold;">trait</span> <span style="color: #bb0066; font-weight: bold;">CheckSum</span> <span style="color: #008800; font-weight: bold;">extends</span> js<span style="color: #333333;">.</span><span style="color: #bb0066; font-weight: bold;">Object</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">def</span> md5<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">String</span>
<span style="color: #008800; font-weight: bold;">def</span> sha1<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">String</span>
<span style="color: #333333;">}</span>
<span style="color: #555555; font-weight: bold;">@js</span><span style="color: #333333;">.</span>native
<span style="color: #008800; font-weight: bold;">trait</span> <span style="color: #bb0066; font-weight: bold;">Asset</span> <span style="color: #008800; font-weight: bold;">extends</span> js<span style="color: #333333;">.</span><span style="color: #bb0066; font-weight: bold;">Object</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">def</span> id<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">String</span>
<span style="color: #008800; font-weight: bold;">def</span> path<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">String</span>
<span style="color: #008800; font-weight: bold;">def</span> downloadUrl<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">String</span>
<span style="color: #008800; font-weight: bold;">def</span> repository<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">String</span>
<span style="color: #008800; font-weight: bold;">def</span> format<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">String</span>
<span style="color: #008800; font-weight: bold;">def</span> checksum<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">CheckSum</span>
<span style="color: #333333;">}</span>
<span style="color: #555555; font-weight: bold;">@js</span><span style="color: #333333;">.</span>native
<span style="color: #008800; font-weight: bold;">trait</span> <span style="color: #bb0066; font-weight: bold;">AssetsResult</span><span style="color: #333333;">[</span><span style="color: #333399; font-weight: bold;">T</span><span style="color: #333333;">]</span> <span style="color: #bb0066; font-weight: bold;">extends</span> js<span style="color: #333333;">.</span><span style="color: #bb0066; font-weight: bold;">Object</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">def</span> items<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">js.Array</span><span style="color: #333333;">[</span><span style="color: #333399; font-weight: bold;">T</span><span style="color: #333333;">]</span>
<span style="color: #008800; font-weight: bold;">def</span> continuationToken<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">String</span>
<span style="color: #333333;">}</span>
<span style="color: #008800; font-weight: bold;">object</span> <span style="color: #bb0066; font-weight: bold;">ArtifactDashboard</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">def</span> main<span style="color: #333333;">(</span>args<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">Array</span><span style="color: #333333;">[</span><span style="color: #333399; font-weight: bold;">String</span><span style="color: #333333;">])</span><span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">Unit</span> <span style="color: #333333;">=</span> <span style="color: #333333;">{</span>
queryNexus<span style="color: #333333;">()</span>
<span style="color: #333333;">}</span>
<span style="color: #008800; font-weight: bold;">def</span> queryNexus<span style="color: #333333;">()</span><span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">Unit</span> <span style="color: #333333;">=</span> <span style="color: #333333;">{</span>
<span style="color: #888888;">// executioncontext needed for ajax call</span>
<span style="color: #008800; font-weight: bold;">implicit</span> <span style="color: #008800; font-weight: bold;">val</span> ec<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">ExecutionContextExecutor</span> <span style="color: #333333;">=</span> scala<span style="color: #333333;">.</span>concurrent<span style="color: #333333;">.</span><span style="color: #bb0066; font-weight: bold;">ExecutionContext</span><span style="color: #333333;">.</span>global
<span style="color: #bb0066; font-weight: bold;">Ajax</span><span style="color: #333333;">.</span>get<span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"http://127.0.0.1:8081/service/rest/v1/assets?repository=maven-public"</span><span style="color: #333333;">)</span> onComplete <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">case</span> <span style="color: #bb0066; font-weight: bold;">Success</span><span style="color: #333333;">(</span>v<span style="color: #333333;">)</span> <span style="color: #008800; font-weight: bold;">=></span>
<span style="color: #008800; font-weight: bold;">val</span> assetsResult <span style="color: #008800; font-weight: bold;">=</span> <span style="color: #bb0066; font-weight: bold;">JSON</span><span style="color: #333333;">.</span>parse<span style="color: #333333;">(</span>v<span style="color: #333333;">.</span>responseText<span style="color: #333333;">).</span>asInstanceOf<span style="color: #333333;">[</span><span style="color: #333399; font-weight: bold;">AssetsResult</span><span style="color: #333333;">[</span><span style="color: #333399; font-weight: bold;">Asset</span><span style="color: #333333;">]]</span>
<span style="color: #008800; font-weight: bold;">for</span> <span style="color: #333333;">(</span>a <span style="color: #008800; font-weight: bold;"><-</span> assetsResult<span style="color: #333333;">.</span>items<span style="color: #333333;">)</span> <span style="color: #333333;">{</span>
document<span style="color: #333333;">.</span>body<span style="color: #333333;">.</span>appendChild<span style="color: #333333;">(</span>p<span style="color: #333333;">(</span>a<span style="color: #333333;">.</span>id<span style="color: #333333;">))</span>
<span style="color: #333333;">}</span>
org<span style="color: #333333;">.</span>scalajs<span style="color: #333333;">.</span>dom<span style="color: #333333;">.</span>window<span style="color: #333333;">.</span>alert<span style="color: #333333;">(</span>assetsResult<span style="color: #333333;">.</span>continuationToken<span style="color: #333333;">)</span>
<span style="color: #008800; font-weight: bold;">case</span> <span style="color: #bb0066; font-weight: bold;">Failure</span><span style="color: #333333;">(</span>e<span style="color: #333333;">)</span> <span style="color: #008800; font-weight: bold;">=></span>
e<span style="color: #333333;">.</span>printStackTrace<span style="color: #333333;">()</span>
org<span style="color: #333333;">.</span>scalajs<span style="color: #333333;">.</span>dom<span style="color: #333333;">.</span>window<span style="color: #333333;">.</span>alert<span style="color: #333333;">(</span>e<span style="color: #333333;">.</span>getMessage<span style="color: #333333;">)</span>
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span>
<span style="color: #008800; font-weight: bold;">def</span> p<span style="color: #333333;">(</span>text<span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">String</span><span style="color: #333333;">)</span><span style="color: #008800; font-weight: bold;">:</span> <span style="color: #333399; font-weight: bold;">Element</span> <span style="color: #333333;">=</span> <span style="color: #333333;">{</span>
<span style="color: #008800; font-weight: bold;">val</span> p <span style="color: #008800; font-weight: bold;">=</span> document<span style="color: #333333;">.</span>createElement<span style="color: #333333;">(</span><span style="background-color: #fff0f0;">"p"</span><span style="color: #333333;">)</span>
p<span style="color: #333333;">.</span>textContent <span style="color: #008800; font-weight: bold;">=</span> text
p
<span style="color: #333333;">}</span>
<span style="color: #333333;">}</span>
</pre>
</div>
<br />
I didn't yet mention two very cool things up there right before your eyes in the sourcecode. Firstly, it demonstrates how easy it is to parse a json response in Scala.js, and with a little more effort than just calling JSON.parse you get full fledged case classes back from your call, quite effortless, by using those magical @js.native annotations (and a little hardcore casting with asInstanceOf ;-))<br />
<br />
If you look closely you'll see that the example code uses those case classes innocently, as if this wouldn't be a big deal - but there you have it: a rest call, a json response, conversion to a case class.<br />
<br />
Don't bother me with details! Nice.<br />
<br />
<h4 style="text-align: left;">
Step 4 - Setup a test repository and deploy test data to it</h4>
For convenience, I've created a dedicated Nexus Maven2 hosted repository for my experiments. I've used my <a href="https://github.com/rladstaetter/fx-animations">before mentioned toy project</a> to deploy it to my test repository and checked on Nexus UI and API that a deployment was successful.<br />
<br />
In order to make this happen you have to declare a distribution management section in your pom: <br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"> <span style="color: #007700;"><distributionManagement></span>
<span style="color: #007700;"><repository></span>
<span style="color: #007700;"><id></span>testrepo<span style="color: #007700;"></id></span>
<span style="color: #007700;"><name></span>testrepo<span style="color: #007700;"></name></span>
<span style="color: #007700;"><url></span>http://127.0.0.1:8081/repository/testrepo/<span style="color: #007700;"></url></span>
<span style="color: #007700;"></repository></span>
<span style="color: #007700;"><snapshotRepository></span>
<span style="color: #007700;"><id></span>testrepo-snapshot<span style="color: #007700;"></id></span>
<span style="color: #007700;"><name></span>testrepo-snapshot<span style="color: #007700;"></name></span>
<span style="color: #007700;"><url></span>http://127.0.0.1:8081/repository/testrepo-snapshot/<span style="color: #007700;"></url></span>
<span style="color: #007700;"></snapshotRepository></span>
<span style="color: #007700;"></distributionManagement></span>
</pre>
</div>
<br />
As you can see above, in my test instance I've created two repositories: one where I can deploy releases, one where I deploy snapshots. The latter one can now also be queried, and we are done configuring Nexus for our purposes.<br />
<br />
Deploying to our testrepo-snapshot repository now only needs a 'mvn deploy' command, which should be issued several times to create more than one snapshot to test it on the server (since we want to have the url of the last SNAPSHOT artifact, remember?)<br />
<br />
<h4 style="text-align: left;">
Step 5 - Give Rest call proper parameters</h4>
Nexus Rest API provides a search functionality, which is exactly what we need. It can be configured in a way that we need to call it only once per artifact, like shown below:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">http://127.0.0.1:8081/service/rest/v1/search/assets?repository=testrepo-snapshot&maven.classifier=jar-with-dependencies&maven.baseVersion=1.0-SNAPSHOT&direction=asc&maven.extension=jar&maven.groupId=net.ladstatt&maven.artifactId=fx-animations&sort=version</span><br />
<br />
Nexus provides a convenient way to experiment with its search api, the url above yields all snapshot versions deployed on Nexus with Version <span style="font-family: "courier new" , "courier" , monospace;">1.0-SNAPSHOT</span>, groupId: <span style="font-family: "courier new" , "courier" , monospace;">net.ladstatt</span>, artifactId=<span style="font-family: "courier new" , "courier" , monospace;">fx-animations</span>. We just take the first element of the result list and can retrieve the correct url. See version <a href="https://github.com/rladstaetter/artifact-dashboard/releases/tag/v0.3">v0.3 for a source code snapshot containing described webservice call</a>. Note also the usage of scala's <span style="font-family: "courier new" , "courier" , monospace;">Future</span> or <span style="font-family: "courier new" , "courier" , monospace;">Either</span> construct which can be used in Scala.js as well.<br />
<br />
<h4 style="text-align: left;">
Step 6 - make it configurable</h4>
Lets recall what we have accomplished so far:<br />
<ul style="text-align: left;">
<li>setup a Scala.js project from scratch</li>
<li>setup a Nexus Webserver</li>
<li>fought against CORS</li>
<li>call a webservice</li>
<li>parse json</li>
<li>map 'native' javascript objects to Scala case classes</li>
<li>build a website's dom 'dynamically'.</li>
<li>...</li>
</ul>
<br />
What is left? The page should get a decent look, but also an easy way to configure different assets, maybe groups of assets ... For this to acheive we could again use Nexus and json parsing, or directly include the meta information (which artifacts should be displayed) in our source code itself. For simplicity, take this route first.<br />
<br />
We still have to solve issues like be able to query more than one repository on a nexus. We initially wanted to have this functionality for a way to get a link to the most current SNAPSHOT version of a maven artifact, but it is surely nice to include released artifacts as well.<br />
<div>
<br /></div>
<div>
To further elaborate, we want to include artifacts with a given groupId/artifactId/version scheme, with or without an extension or classifier; things that are not possible with version 0.3. </div>
<div>
<br /></div>
<a href="https://github.com/rladstaetter/artifact-dashboard/releases/tag/v0.4">See v0.4 for a version which has more artifacts configured and a case class structure prepared for easy configuration</a>.<br />
<br />
I'll stop here, maybe this project is of use for somebody or motivates to give Scala.js and / or Nexus a try.<br />
<br /></div>
<div>
I used <a href="http://hilite.me/">this website to hightlight some source</a> code snippets.<br />
<br />
Thanks for reading.</div>
<div>
<br /></div>
</div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-22236919634856732432018-01-04T17:36:00.000+01:002018-01-05T22:51:36.517+01:00Asciidoctor <div dir="ltr" style="text-align: left;" trbidi="on">
I've stumbled across a nice project called '<a href="http://asciidoctor.org/">Asciidoctor</a>'.<br />
<br />
Quoting their website:<br />
<blockquote class="tr_bq">
Asciidoctor - A fast text processor & publishing toolchain for converting AsciiDoc to HTML5, DocBook & more.</blockquote>
HTML, PDF, epub and .mobi files are supported amongst others.<br />
<div>
<br /></div>
It is a ruby project, but thanks to <a href="http://jruby.org/">jruby</a> it is also usable in JVM land. A <a href="https://github.com/asciidoctor/asciidoctor-maven-plugin/">maven</a> or <a href="https://github.com/mraible/infoq-mini-book">gradle</a> plugin helps for continuous integration scenarios.<br />
<br />
You can find an example project on github (<a href="https://github.com/asciidoctor/asciidoctor-maven-examples">asciidoctor-maven-examples</a>) which shows various ways to configure the <a href="https://github.com/asciidoctor/asciidoctor-maven-plugin/">maven</a> plugin, it gives you a head start for your own purposes.<br />
<br />
I created also a <a href="https://github.com/rladstaetter/asciidoc-template">asciidoctor-template project on github</a> which contains an example configuration to create reveal.js slides, pdf documents or epub target files for that matter. Not to forget that it is also possible to create .mobi files, which can be consumed by Amazon Kindle.<br />
<div>
<br /></div>
I used it for writing some technical documentation and was very satisfied with the results.<br />
<br />
Give it a try!<br />
<div>
<br /></div>
</div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-69910048001132049252017-12-18T19:56:00.002+01:002017-12-18T19:56:44.795+01:00Old skool plasma effect<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
<span style="font-size: small; font-weight: normal;">This time I wanted to investigate how to share code between a JavaFX project and a project which uses ScalaJS.</span></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia862e6f-Ri6zs0PH0iM4yFbYI2hECLr6I3L_ZuhPTJjMhxo9krjYQwbIaShs3orLQ4g-iv8JW5Zb7Ua7u54XQezjYQ7iOd8dlkv5hfp8sxsqnhnImOv5wq8KtGB2zHMa72AJhpUTUP78_/s1600/plasma-effect.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="362" data-original-width="365" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia862e6f-Ri6zs0PH0iM4yFbYI2hECLr6I3L_ZuhPTJjMhxo9krjYQwbIaShs3orLQ4g-iv8JW5Zb7Ua7u54XQezjYQ7iOd8dlkv5hfp8sxsqnhnImOv5wq8KtGB2zHMa72AJhpUTUP78_/s320/plasma-effect.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"> <a href="http://ladstatt.net/plasma/">Plasma Application Screenshot (Scala.js version)</a></td></tr>
</tbody></table>
The screenshot above shows a still <a href="http://ladstatt.net/plasma/">of the Javascript version </a>of this project, below you see the JavaFX version.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO-vOWhAWbTxq0Y31L7sFaXKaBlP97HUa1kQr7syT00ce2gllgE0by2SUbdaafljMe8GGSrzY2S2b1L_aZIewvP25ZnmYhFrG4Etl0nLIk9VPYlySL2Tawn-1kU_w7McQE-TvW2qCyPjxN/s1600/Plasma_Effect_and_plasma_%25E2%2580%2594_java_%25E2%2597%2582_sbt_%25E2%2580%2594_118%25C3%259735.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1042" data-original-width="1000" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgO-vOWhAWbTxq0Y31L7sFaXKaBlP97HUa1kQr7syT00ce2gllgE0by2SUbdaafljMe8GGSrzY2S2b1L_aZIewvP25ZnmYhFrG4Etl0nLIk9VPYlySL2Tawn-1kU_w7McQE-TvW2qCyPjxN/s320/Plasma_Effect_and_plasma_%25E2%2580%2594_java_%25E2%2597%2582_sbt_%25E2%2580%2594_118%25C3%259735.png" width="307" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Plasma effect in JavaFX</td></tr>
</tbody></table>
<br />
<br />
I'm quite fond of <a href="https://en.wikipedia.org/wiki/Demoscene">demos</a>, in fact those brought me into programming initially. As such I always wanted to implement a plasma effect, and here you are. I was surprised that it didn't really take much to generated graphics like the above, as such it always pays off to try out new things.<br />
<br />
In hindsight, for me the most interesting part is how to setup sbt in order to enable code sharing between JavaFX and Scala.js. Also, I had to apply some tricks in order to share code which accesses Arrays both in JavaFX and Scala.js. Implementation wise, it is interesting how the color values for each pixel get calculated. Here, we have literally unlimited ways to manipulate this data, you should really download the project and try out new variations of the algorithm yourself.<br />
<br />
Regarding performance. the algorithm updates every pixel at every frame, you can imagine this is not very performant neither in Scala.js nor in JavaFX. Something like this would be done in a shader I suppose. But to be fair it is not so bad, either.<br />
<br />
Have a look at the code on <a href="https://github.com/rladstaetter/plasma/">github</a>, it should be easy to set up and experiment yourself. </div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-34996252301916577662016-11-16T15:46:00.000+01:002016-11-20T16:02:03.626+01:00Scala, Gradle and Android Studio<div dir="ltr" style="text-align: left;" trbidi="on">
This post describes my experience with Scala, Gradle and Android Studio - (TL;DR - it works for me.)<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a data-flickr-embed="true" href="https://www.flickr.com/photos/practicalowl/248282683/in/photolist-nWvMV-nsrER-5uGGC8-rBwcD3-83PS1x-G7XJuZ-njz8AD-7bPqWh-FfDhzW-hDHiHr-bXKPxd-s5eAoN-9zohDj-4sUH3X-FRzDBd-8Bneah-ERMrEo-2YJpz2-o5X6Nr-C3Sga-79ydNg-753vTm-b9FKhF-qyAVFD-9rxgvG-6kLaF2-suNUYB-5rfCRY-5bAd31-vXWEri-opLZEi-s6wpS2-dY15Dg-rJuUnJ-83dEfE-canbZG-zz3YHf-rTVnV7-remUf1-FnYGH-59fDRz-JH6Wk5-DHMa3h-FK4uX9-a9zdLi-GeuMeB-afmzvc-oFhHp-owLKV9-JmKoRV" style="margin-left: auto; margin-right: auto;" title="Old keys"><img alt="Old keys" height="404" src="https://c4.staticflickr.com/1/94/248282683_09189454db.jpg" width="500" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Photo credits: <a href="https://www.flickr.com/photos/practicalowl/248282683/in/photolist-nWvMV-nsrER-5uGGC8-rBwcD3-83PS1x-G7XJuZ-njz8AD-7bPqWh-FfDhzW-hDHiHr-bXKPxd-s5eAoN-9zohDj-4sUH3X-FRzDBd-8Bneah-ERMrEo-2YJpz2-o5X6Nr-C3Sga-79ydNg-753vTm-b9FKhF-qyAVFD-9rxgvG-6kLaF2-suNUYB-5rfCRY-5bAd31-vXWEri-opLZEi-s6wpS2-dY15Dg-rJuUnJ-83dEfE-canbZG-zz3YHf-rTVnV7-remUf1-FnYGH-59fDRz-JH6Wk5-DHMa3h-FK4uX9-a9zdLi-GeuMeB-afmzvc-oFhHp-owLKV9-JmKoRV">Kit</a> </td></tr>
</tbody></table>
<script async="" charset="utf-8" src="//embedr.flickr.com/assets/client-code.js"></script>
<br />
<h3 style="text-align: left;">
Motivation</h3>
<br />
Android Studio is the default IDE for Android Development, and the same applies for Gradle as Android's "native" build system. Applications for Android are written predominantly in Java.<br />
<br />
Another way to write apps for Android is to use Scala. This choice is not an easy one, since the build gets a little more involved, and the build time also increases significantly. However, this can be circumvented to a huge part, since there is an effort for writing android apps with Scala and<a href="http://scala-android.org/"> its own ecosystem</a> evolved around that idea. Those guys made a good progress.<br />
<br />
For the scope of this blog post, I was just interested on how much a switch to Scala would affect the normal workflow in Android Studio. For this reason, I tried to stay with gradle, not switching to sbt and not using maven for this.<br />
<br />
It turns out that Scala and Gradle play well together. At least this is my first impression, I'm sure gradle can't deliver all the functionality one is accustomed to when using sbt.<br />
<br />
Regarding the user experience in Android Studio: An impact on the workflow can't be denied, since there is no development for Android and Scala without Proguard, which is known to be slow; Instant Run is not really as instant when using Scala with Android Studio.<br />
<br />
If you can live with this, I would say one could give it a try and develop Android Apps with Scala and Gradle.<br />
<br />
<h3 style="text-align: left;">
Case Study: Basic Multitouch</h3>
<br />
I thought it would be a good idea to port a small project to Scala and see what problems I would run into.<br />
<br />
Here is what I did:<br />
<br />
- I forked android-scala-gradle plugin and applied an existing <a href="https://github.com/saturday06/gradle-android-scala-plugin/pull/89">pull request</a> such that the plugin works together with Android Studio 2.2.2<br />
- forked <a href="https://github.com/googlesamples/android-BasicMultitouch">android-BasicMultiTouch example</a> project from google samples<br />
- added necessary tweaks to the Gradle build to support Scala<br />
- installed Scala Plugin in Android Studio<br />
- ported all java code to scala code - <strike>IntelliJ</strike> Android Studio helps here a lot<br />
- got it to compile and work on a physical android device (and simulator as well)<br />
- "instarun" runs almost instantly ;-)<br />
<br />
In the process of installing my environment, I've stumbled over <a href="http://sdkman.io/">http://sdkman.io/</a>, which helps a lot managing different versions of gradle (or other java based libraries for that matter) - check it out!<br />
<br />
<h3 style="text-align: left;">
Summary</h3>
<br />
It went well. I've downloaded half of the internet during the process, but after this initial hurdle the work was straightforward.<br />
<br />
All the code is in github, so this time no screenshots or code listings.<br />
<br />
Check out the github repositories for the patched <a href="https://github.com/rladstaetter/gradle-android-scala-plugin">android-scala-gradle</a> plugin as well as the<a href="https://github.com/rladstaetter/android-BasicMultitouch"> toy multitouch project</a> which can be used as starting points for your own experiments.<br />
<br />
<br />
<br />
<br />
<br /></div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-16944208852835780132016-02-15T22:36:00.002+01:002016-02-15T22:36:55.851+01:00fx-tictactoe: Deploy a JavaFX app into the google play store<div dir="ltr" style="text-align: left;" trbidi="on">
This time I'll describe what is necessary to get a <b>JavaFX application into the google play store</b>.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a data-flickr-embed="true" href="https://www.flickr.com/photos/llgc/6346813233/in/photolist-aER5sn-rKnubY-woGuGJ-4Tysun-jrbktQ-ijfQ9j-81qC6f-kddKQR-kddMn8-g5mdva-qrQ7tB-dtfipt-bSk28z-7VEYbL-g5bUad-7yQRUy-g5kMuQ-npgkA9-g5bWwf-7yQQb9-9yT4a3-kdd8PV-kddL8p-wr24zt-5kdzNv-jLM1pT-9JpESf-4WMzfe-ijfXqw-cXCg9A-55vUn2-g5bY5L-81huHX-6nxYVK-rL7yHK-bBPThy-zdXZT1-kdfeSm-7yM5Za-4ARt1u-kddufn-858ChF-oyRHxv-aRChza-7yQT6j-AegLYS-kdd4Az-y6tWyo-5V5Zxn-DGKfMA" title="[The postman on his round in the mountains between Tregaron and Abergwesyn]"><img alt="[The postman on his round in the mountains between Tregaron and Abergwesyn]" height="380" src="https://farm7.staticflickr.com/6035/6346813233_00a5277a1a.jpg" width="500" /></a><script async="" charset="utf-8" src="//embedr.flickr.com/assets/client-code.js"></script></div>
<script async="" charset="utf-8" src="//embedr.flickr.com/assets/client-code.js"></script>
<br />
<b><br /></b>
<br />
To start with, you'll need a JavaFX application first. For this blog post I thought it would be a good idea to continue the work on my <a href="http://ladstatt.blogspot.co.at/2016/01/fx-tictactoe-tictactoe-javafx.html">fx-tictactoe game</a> - which is in no way finished or 'production ready' - but it shows in principle what has to be done. If you haven't read the <a href="http://ladstatt.blogspot.co.at/2016/01/fx-tictactoe-tictactoe-javafx.html">blog post about how to deploy the app to an android device yet, I would recommend to do it now</a>.<br />
<br />
Ok, we have an application which deploys happily on the android platform, but one last obstacle has to be taken to really nag all your relatives and friends for downloading your newest app from the google store.<br />
<br />
Again I'm happy that the obstacle is rather a small one, since again it seems that the <a href="https://bitbucket.org/javafxports/javafxmobile-plugin">javafxmobile-plugin</a> does the hard work for us. In fact, you only have to provide a small addition to the build.gradle file which handles the signing part, that is it points the wrapped android plugin to your keystore file.<br />
<br />
Here is the build.gradle file:<br />
<br />
<script src="https://gist.github.com/rladstaetter/60fed7a54b22f69517c2.js"></script>
<br />
You can see that not much changed since the last blog post, only the signing information had to be added. Another small thing which should get your attention is the AndroidManifest.xml file, which serves as a bootstrapper to launch your JavaFX application on Android.<br />
<br />
If we have a closer look at it:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPnkrbfH6F7nssyqZii2BQDLG3IT5T3fg8ZZwwimi2TBzm8N1TaqCiPd7ONYcy88JVS-bC_d8SLu1lZ37K_8f579crXkSBYrfYX64ldnVf447cjmm0z0eczQX19byR9DOt-2Km0JzvJX-_/s1600/AndroidManifest_xml_-_fx-tictactoe_-____Documents_fx-tictactoe__-_IntelliJ_IDEA__Community_Edition__IC-144_3891_8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPnkrbfH6F7nssyqZii2BQDLG3IT5T3fg8ZZwwimi2TBzm8N1TaqCiPd7ONYcy88JVS-bC_d8SLu1lZ37K_8f579crXkSBYrfYX64ldnVf447cjmm0z0eczQX19byR9DOt-2Km0JzvJX-_/s400/AndroidManifest_xml_-_fx-tictactoe_-____Documents_fx-tictactoe__-_IntelliJ_IDEA__Community_Edition__IC-144_3891_8.png" width="400" /></a></div>
<br />
we can see that there is the <span style="font-family: "courier new" , "courier" , monospace;">javafxports.android.FXActivity</span> class which delegates the control flow sometime to our main app - the FXActivity ensures that Mr. Bob Developer doesn't have to struggle with Android specifics at all and can concentrate on the hurdles of app development itself.<br />
<br />
(Of course there are huge differences between those systems which can't be neglected, but this is not in scope for this discussion.)<br />
<br />
Anyhow, I'm very happy to be able to deploy JavaFX apps to the app store - in fact it took me longer to answer all compliance questions and do the artwork for the app and the store listing than to "port" the app to Android (ok exaggerating - but close ;-) )<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://play.google.com/store/apps/details?id=net.ladstatt.tictactoe"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHVfKwEpo5wg0hJ7vgFkE9E7BaWKhztRKl9RplSApSGrGzO1Ev3IFsAbA_aRc_7p_wKxxVu6dtTkduz17vswGhEJX5pK-OUCVgg8eL5hB7GowAA_ZhnAhpGxYOF1YQ38UNZzapC60qG4b7/s400/jout.gif" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">fx-tictactoe in action</td></tr>
</tbody></table>
<br />
<a href="https://play.google.com/store/apps/details?id=net.ladstatt.tictactoe">Click here if you want to see the google app store listing for fx-tictactoe</a>, or <a href="https://github.com/rladstaetter/fx-tictactoe">click here for the source code on github</a>.<br />
<br />
<div>
<br /></div>
<br />
<br />
<br />
<br />
<br /></div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-26994846389757147622016-01-17T16:04:00.002+01:002016-01-20T16:44:18.415+01:00fx-tictactoe - A TicTacToe JavaFX application on Android<div dir="ltr" style="text-align: left;" trbidi="on">
This post describes how you can install a JavaFX application on an Android device.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a data-flickr-embed="true" href="https://www.flickr.com/photos/osucommons/6478851407/in/photolist-aSvNNB-6vkR1u-wxoPVz-npgkA9-g5mdva-8bojRL-6HAbCC-6fPE3V-8f9rqa-AegLYS-npPhKQ-aF64kt-7pqS3s-pfjfrC-ifHZqy-phj9PE-kdqnPK-g5bTAs-ffEHhH-8bojcf-6aiY4X-4ARt7w-5khSpo-5kdzNv-7yM45a-aEzehS-8bogio-dncc1u-5QuvCR-kbedjz-5QyNyY-dmXooP-9yT4a3-6HAexq-eqPJuG-aHXr62-8o4bzs-nktaS4-fJ4Jpo-9GH4WE-7vsWHg-6Hw9wx-6HA8UQ-nrzxxC-7412Dd-aFa8jM-dmXo2e-oyRHxv-isSY7o-bufKSm" style="margin-left: 1em; margin-right: 1em;" title="Mt. Hood, Oregon, in summer garb"><img alt="Mt. Hood, Oregon, in summer garb" height="398" src="https://farm8.staticflickr.com/7149/6478851407_b18490f14f.jpg" width="500" /></a></div>
<script async="" charset="utf-8" src="//embedr.flickr.com/assets/client-code.js"></script>
<br />
<div>
<br /></div>
<div>
I <a href="http://ladstatt.blogspot.co.at/2016/01/fx-tictactoe-tictactoe-app-using-javafx.html">recently created fx-tictactoe</a> which is a simple tic tac toe game with a computer opponent. I wondered how easy it would be to port it to Android.</div>
<div>
<br />
<b>TL;DR:</b> It is easy, you'll need the <a href="https://bitbucket.org/javafxports/javafxmobile-plugin">javafxmobile plugin</a>.<br />
<br /></div>
<div>
To start from scratch, there would be two approaches to do something like this:</div>
<div>
<br /></div>
<div>
- implement game logic in its own module, create a dedicated android gui</div>
<div>
- reuse almost everything from the original javafx based game and use javafxports to run it</div>
<div>
<br />
The first variant is more conservative and more work: you have to partition your original implementation to a gui and backend layer and reprogram from scratch your gui layer in order to fit the android api's needs. I did something like that in the <a href="http://ladstatt.blogspot.co.at/2016/01/sudoku-capturer-release-17.html">sudokufx application</a>.<br />
<br /></div>
<div>
For fx-tictactoe, out of curiosity I used the second approach.<br />
<br />
Ok, so what has to be done to get a JavaFX app to the android platform?</div>
<div>
<br />
<h3 style="text-align: left;">
Step 0: Install Gradle</h3>
<br />
The <i>javafxmobile-plugin</i> demands a rather recent version of Gradle, so make sure you've downloaded and installed at least Gradle 2.2. You can <a href="http://gradle.org/gradle-download/">download Gradle</a> here.<br />
<br />
<h3 style="text-align: left;">
Step 1: Setup gradle build</h3>
<br /></div>
<div>
<a href="http://docs.gluonhq.com/javafxports/">javafxports</a> uses, like Javafx itself, <a href="http://gradle.org/">Gradle</a> as its build system.<br />
<br />
<a href="https://twitter.com/johanvos">Johan Vos</a> and his team have been doing a remarkable great job in tooling support for JavaFX on Android, thus setting up a build system for a JavaFX project for Android is a rather easy task like you can see in the simple gradle.build script below.<br />
<br />
<script src="https://gist.github.com/rladstaetter/cc1320285229cb4eb34d.js"></script><br />
<br />
<br />
<br />
At the time of writing, the javafxmobile-plugin was not yet published in maven central. To get things going, I had to check out the source code of the plugin from <a href="https://bitbucket.org/javafxports/javafxmobile-plugin">here and install</a> it myself on my local machine (which worked out of the box). If you want to do this as well, the only command which was necessary for this was<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">gradle install</span><br />
<br />
Note: I saw that the <a href="https://oss.sonatype.org/content/repositories/snapshots/org/javafxports/jfxmobile-plugin/1.0.8-SNAPSHOT/">1.0.8-SNAPSHOT version already resides at the sonatype snapshot repository</a>, so it won't take long until it is deployed as a release there I assume.<br />
<br />
You can see that among other things I'm using the Gradle Scala plugin and the javafxmobile-plugin together. Luckily those two guys work together nicely, which whas my greatest concern for this blog post.<br />
<br />
But back to the example javafx project I want to see on my android device:<br />
<br />
The only thing which is necessary to add to the fx-tictactoe project in order to make it run on the android platform was the build.gradle file.<br />
<br />
After creating the build.gradle (see gist above) file, all you need to do is type following command:<br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">gradle android</span><br />
<br />
And if you want to deploy the app to a (connected) device:<br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">gradle androidInstall</span><br />
<br />
<br />
This should deploy the apk with a debug configuration to your device.<br />
<br />
Like stated in the official docs, the <a href="https://bitbucket.org/javafxports/javafxmobile-plugin/">javafxmobile-plugin</a> downloads everything what is necessary, which is great. I can't repeat often enough that it amazes me when I try out projects and they work without much hassle since I know that this very much work and some quality piece of engineering.<br />
<br />
I would like to invite you to watch at the final result of my explorations, the video shows a working fx-tictactoe on Android:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/Pna51-od2QA/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/Pna51-od2QA?feature=player_embedded" width="320"></iframe></div>
<br />
<br />
These are the basic steps for a proof of concept that the application works on the android device. For deploying it to the app store, some more steps are required, optimizing the apk and wiping out stuff which is not used or needed is also a thing to remember. But for first experiments this should suffice.<br />
<br />
As always, I've pushed the source code for the app to <a href="https://github.com/rladstaetter/fx-tictactoe/">my github site</a>.</div>
<div>
<br /></div>
</div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-79759549442297718192016-01-07T18:24:00.000+01:002016-01-07T18:24:17.799+01:00AnimationTimer Example<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
This blog entry just shows a screenshot and the code for a little JavaFX AnimationTimer test I wrote.</div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcDVL7-kKzvIYkVK2wg5giE52CvGB5WS8Iml58QeGMgEJt_gMuXTOoRibkK6YlTp5p1AHAVDqTx0KSpay3A25Y_LkOCttdOoAo1Z9ia04vn6SOXkXAyXn3mPZpMfTzaHzGx6lh_gBjdZhN/s1600/AnimationTimerExample.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcDVL7-kKzvIYkVK2wg5giE52CvGB5WS8Iml58QeGMgEJt_gMuXTOoRibkK6YlTp5p1AHAVDqTx0KSpay3A25Y_LkOCttdOoAo1Z9ia04vn6SOXkXAyXn3mPZpMfTzaHzGx6lh_gBjdZhN/s400/AnimationTimerExample.png" width="400" /></a></div>
<br />
<div>
<br />
<a href="http://download.java.net/jdk8/jfxdocs/javafx/animation/AnimationTimer.html">AnimationTimer </a>is a JavaFX class which comes in handy if you are in need of a callback hook which should be called on every frame. With this class it is possible to implement simple animations for example, but it could be used for various other things as well. The example code below shows how to make hundreds of circles wiggle.<br />
<br />
<br /></div>
<div>
<script src="https://gist.github.com/rladstaetter/317a26e5125c0f35ac1e.js"></script>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
A self contained project <a href="https://github.com/rladstaetter/fx-animations">is available here</a>. </div>
<div>
<br /></div>
</div>
</div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-58073814008705347352016-01-06T15:40:00.001+01:002016-01-06T15:44:26.277+01:00Sudoku Capturer Release 1.7<div dir="ltr" style="text-align: left;" trbidi="on">
Hi everyone, I'm happy to announce a new release for my Android Sudoku Solver application.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a data-flickr-embed="true" href="https://www.flickr.com/photos/sdasmarchives/8091770474/in/photolist-dk3rs3-oeW7aJ-da5nUA-5VytgL-ayQakw-ayQax3-7DhHLy-7yM8Jx-6ogbD5-51Fdm5-7vQtuM-4WywKZ-acU9rJ-r6jKhG-f3qCLw-66gqwS-4i9HbX-d7dpz5-6AQ7Yy-4VCqhL-qdBsrC-5gr7tz-irRBvt-ap2Z7q-fmbfBL-j2VnXK-osYcwq-icBa2Z-i7UqS5-i7UBH1-eSf9GF-fpS3sW-n96cVk-edvv6T-e2T9Qx-4jCrhA-8nxTf8-6GXWyP-7WLxKP-dk3por-dk3pk8-dk3rq3-e2T9QX-fyagxX-hvAZPx-7uX1ka-6YUiJ2-idEt98-fyaxyX-fkkAq6" style="margin-left: 1em; margin-right: 1em;" title="Refueling ""Spokane Sun God"""><img alt="Refueling ""Spokane Sun God""" height="357" src="https://farm9.staticflickr.com/8050/8091770474_8d325343d4.jpg" width="500" /></a></div>
<script async="" charset="utf-8" src="//embedr.flickr.com/assets/client-code.js"></script>
<br />
This release is mainly a service release, I've polished the source a little bit and made it compatible with current developments on the underlying image processing library, OpenCV.<br />
<br />
For this I had to update the application to API Level 21, which makes it incompatible with many devices. I'll see how things will develop here, with the current implementation you will need a rather recent phone with a high quality camera, which support this API level anyways. One advantage now is that I've managed to encapsulate the OpenCV API such that I can reuse it in other apps as well, which is a nice thing.<br />
<br />
If you are interested in the details, have a look at the <a href="https://github.com/rladstaetter/sudokufx">source code on github</a>. The application is also an example how to develop image processing algorithms on a desktop environment (using JavaFX) and reusing the code then on a mobile device. Like this you save yourself much development time.<br />
<br />
Give it a try and let me know what you think. You can download it for free on the <a href="https://play.google.com/store/apps/details?id=net.ladstatt.apps.sudoku.android">google play store</a>. </div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-78733709776504424822016-01-06T00:18:00.000+01:002016-01-06T11:24:34.446+01:00Encapsulate OpenCV 3.1 as Android AAR<div dir="ltr" style="text-align: left;" trbidi="on">
In this post I describe how to encapsulate OpenCV as an Android AAR package such that it is easier to include it as a maven dependency.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a data-flickr-embed="true" href="https://www.flickr.com/photos/library_of_congress/8621263447/in/photolist-e8Qege-pyof8D-4juHNM-d9fypu-4YDSay-8zFqRs-pyoz7Y-5q8yhp-8QfuU1-puGVmN-pQVogC-4RRGR1-4ARs1S-pMxhJg-fKJxK7-5JNtac-drM5BH-puGVm7-eJALe7-eHDz7P-54FaBb-f1Wbih-ngBuEr-dZAiBL-bhVzbk-gtoPkj-bUCjSx-9292a5-7z3Get-pLqpgt-54FcnA-bzGf9t-w2gwCd-agttL7-5BcecJ-cXWrC9-bQt9AF-91Q72X-bpGskJ-e4mKvM-54Fd1L-6tyan8-9GE1rH-jMtmbi-5iMKdS-8Hc1Ga-e69ioC-6qrVWY-cCZjjy-bUCjKn" style="margin-left: 1em; margin-right: 1em;" title="[High Street, Guildford, England] (LOC)"><img alt="[High Street, Guildford, England] (LOC)" height="376" src="https://farm9.staticflickr.com/8109/8621263447_f3bf188d5b.jpg" width="500" /></a></div>
<script async="" charset="utf-8" src="//embedr.flickr.com/assets/client-code.js"></script>
<br />
<br />
Disclaimer: Apparently there exist many <a href="http://docs.opencv.org/3.1.0/d5/df8/tutorial_dev_with_OCV_on_Android.html#gsc.tab=0">other tutorials about OpenCV</a>, my approach is a little bit unconventional. I also have to mention that there is a very well maintained library called <a href="https://github.com/bytedeco/javacv">JavaCV</a> which does essentially the same.<br />
<br />
The motivation for this blog post is that I want to have an convenient way to use OpenCV with my Android applications. Below I describe what I had to do to achieve this.<br />
<br />
<h3 style="text-align: left;">
Step 1: Download the OpenCV library</h3>
<div>
<br /></div>
On <a href="http://www.opencv.org/">www.opencv.org</a> there is a link to download the library for Android. Download it, unpack it.<br />
<br />
If you've followed the <a href="http://ladstatt.blogspot.co.at/2015/12/opencv-31-with-java-support-on-osx-el.html">post about compiling OpenCV</a> yourself, you already have a directory in your<br />
homedirectory somewhere:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">opencv/</span><br />
<span style="font-family: Courier New, Courier, monospace;">opencv/opencv-3.1/</span><br />
<span style="font-family: Courier New, Courier, monospace;">opencv/build/</span><br />
<br />
now, add the unpacked Android SDK:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">opencv/</span><br />
<span style="font-family: Courier New, Courier, monospace;">opencv/opencv-3.1/</span><br />
<span style="font-family: Courier New, Courier, monospace;">opencv/build/</span><br />
<div>
<span style="font-family: Courier New, Courier, monospace;">opencv/OpenCV-android-sdk-3/</span></div>
<div>
<br /></div>
<div>
You'll find the usual suspects in the directory, some samples, javadoc for the API, already pre build apk's:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">apk/</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">samples/</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">sdk/</span></div>
<div>
<br /></div>
<div>
Now I want to discuss briefly the contents of those directories.<br />
<br /></div>
<div>
<h3>
Directory apk: OpenCV Manager</h3>
OpenCV encourages you to use a separate application called OpenCV Manager which sole purpose is to make sure you have installed a compatible OpenCV library on your phone. This approach is fine but requires your users to install a second app on their phone. For the technical inclined this is no problem, but for end users this may seem a little bit awkward. I prefer to deliver a self contained app which has no apparent third party dependencies.<br />
<br />
The apk directory contains this Manager application for environments where you don't want to use the OpenCV Manager from the play store.<br />
<br />
<br /></div>
<h3 style="text-align: left;">
Directory samples: OpenCV Android Samples</h3>
<div>
<br />
The samples directory contains several example apps which demonstrate various aspects of the OpenCV API for android.<br />
<br /></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;">./samples/example-15-puzzle.apk</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">./samples/example-camera-calibration.apk</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">./samples/example-color-blob-detection.apk</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">./samples/example-face-detection.apk</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">./samples/example-image-manipulations.apk</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">./samples/example-tutorial-1-camerapreview.apk</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">./samples/example-tutorial-2-mixedprocessing.apk</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">./samples/example-tutorial-3-cameracontrol.apk</span></div>
</div>
<div>
<br /></div>
<div>
I recommend to install some of the apk's on your device:</div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> adb install <example.apk></span></div>
<div>
<br /></div>
<div>
This is the best way to get a feeling what can be done with the OpenCV Android API, so I suggest to play around with the samples. The source code for those samples is also included.</div>
<h3 style="text-align: left;">
Directory sdk: Android OpenCV Java API</h3>
<div>
Here you'll find what you will need for your own app. There are pre-built android libraries for various architectures and one java API to use the native code. The directory structure you'll find on the top of this directory looks like follows:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">etc/ </span><span style="font-family: Arial, Helvetica, sans-serif;">... some configuration for special routines you could use</span><span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;">java/ </span><span style="font-family: Arial, Helvetica, sans-serif;">... the java glue code you will program against</span><br />
<span style="font-family: Courier New, Courier, monospace;">native/ </span><span style="font-family: Arial, Helvetica, sans-serif;">... prebuilt binaries for the android platform</span><br />
<br />
Since I use maven for most of my projects and all of my open source stuff, I need some way to use the provided java glue code and the binaries in my projects. As long as you just use the default API for OpenCV, you can take the code provided almost off the shelf.<br />
<br />
<h3 style="text-align: left;">
Create an OpenCV AAR ready to use with Maven</h3>
The following approach shows how you can create a maven module containing the OpenCV bindings - thanks to the <a href="https://github.com/simpligility/android-maven-plugin">android-maven-plugin</a> it can then be used like a 'normal' maven dependency. The plugin will take care about <a href="http://simpligility.github.io/android-maven-plugin/aar.html">including the AAR</a> in the final APK, you just have to declare it as a dependency (see below).<br />
<br />
For this to happen, I've restructured the source code in the following way:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiaYPZBSwK9X1pGYbsOmJjA8e0L-9eg4P1DdUN3ngb9jKUCezdnYqE_4yb9DS0sxH0RWCTvzjtIGrUQBlhDvh266zfij63V_Jk_f6AV2JTf3nAraSGg-O7p3Uk2by1Uvg_Ommi2hwbiQvI/s1600/android-opencv_-_sudokufx_-____Documents_sudokufx__-_IntelliJ_IDEA__Community_Edition__IC-144_2608_2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiaYPZBSwK9X1pGYbsOmJjA8e0L-9eg4P1DdUN3ngb9jKUCezdnYqE_4yb9DS0sxH0RWCTvzjtIGrUQBlhDvh266zfij63V_Jk_f6AV2JTf3nAraSGg-O7p3Uk2by1Uvg_Ommi2hwbiQvI/s1600/android-opencv_-_sudokufx_-____Documents_sudokufx__-_IntelliJ_IDEA__Community_Edition__IC-144_2608_2.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Restructuring of the sdk subfolder</td></tr>
</tbody></table>
This is the default structure which works together with the android-maven-plugin and includes only code and binaries you'll need at runtime. The pom looks as follows:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe6iDldmQ5-7x3ZhzHd_8thCHu1A_RQ6L-DC9WBaScGp46UCJI7OHMsRUZxlsOcfxtO-n94o90pqV-3CwvpgD-dY9kDEtccmK6b0SuONKrzwBe7vjpCs66bN9H560VEQLnyJtLj1qNFs7Q/s1600/android-opencv_-_sudokufx_-____Documents_sudokufx__-_IntelliJ_IDEA__Community_Edition__IC-144_2608_2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe6iDldmQ5-7x3ZhzHd_8thCHu1A_RQ6L-DC9WBaScGp46UCJI7OHMsRUZxlsOcfxtO-n94o90pqV-3CwvpgD-dY9kDEtccmK6b0SuONKrzwBe7vjpCs66bN9H560VEQLnyJtLj1qNFs7Q/s320/android-opencv_-_sudokufx_-____Documents_sudokufx__-_IntelliJ_IDEA__Community_Edition__IC-144_2608_2.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">pom.xml for an opencv aar</td></tr>
</tbody></table>
<br />
You can see that I'm referring to the standard android api of a certain version - this is needed in order to properly compile the OpenCV Java API.<br />
<br />
In order to get the standard android api, you have to clone yet another project named <a href="https://github.com/simpligility/maven-android-sdk-deployer">maven-android-sdk-deployer</a> and install the proper API level in your local maven repository. This can be done for<br />
example by issuing following command:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">mvn install -P 5.0</span><br />
<br />
A prerequisite for this command to finish successfully is however that you have already installed the Android SDK itself.<br />
<br />
Hint: It seems that the OpenCV 3.1 bindings for Android need at least API level 21, maybe you save some time by just downloading this API Level.<br />
<br />
Anyway, if you look closely at the pom.xml you'll notice it is using a custom packaging method, namely 'aar' - this is possible since the android-maven-plugin provides the capabilities for maven to properly create such a file type.<br />
<br />
Aar's are <a href="http://tools.android.com/tech-docs/new-build-system/aar-format">bundles which contain libraries</a> (Java code, resources or native code) ready to use in Android Applications. Luckily, android-maven-plugin makes it possible to use aar's like normal maven dependencies.<br />
<br />
By using this approach you can deploy the OpenCV bindings in your maven repository. OpenCV can then be treated like any other maven dependency, which is a nice thing.<br />
<br />
To recap:<br />
<br />
After a successful deploy or local install of this maven module (with mvn install) all you need is to include it in the dependency list of your main app, just like shown below:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7GJV8TpGnkpd4ZFB11OMtrIPsTThht40F57I0zF2osSXZsqwwFFTM9yOoS3tvgvssjfgXyHTZwwQP57BOJRGvmOXlUMncJX-sONhe7mwPZRHlhZjroRGlVoDYUNL7OLy-noDT34R0eBQc/s1600/sudoku-android_-_sudokufx_-____Documents_sudokufx__-_IntelliJ_IDEA__Community_Edition__IC-144_2608_2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7GJV8TpGnkpd4ZFB11OMtrIPsTThht40F57I0zF2osSXZsqwwFFTM9yOoS3tvgvssjfgXyHTZwwQP57BOJRGvmOXlUMncJX-sONhe7mwPZRHlhZjroRGlVoDYUNL7OLy-noDT34R0eBQc/s1600/sudoku-android_-_sudokufx_-____Documents_sudokufx__-_IntelliJ_IDEA__Community_Edition__IC-144_2608_2.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">dependency declaration for your homebrew opencv maven module</td></tr>
</tbody></table>
<br />
That's all there is to it - you should be able now to use OpenCV in your project. Of course, the maven coordinates change depending on which you've chosen before. <br />
<br />
One nice aspect is that the download of the OpenCV Manager is not needed anymore. The drawback is of course that your apk is getting bigger - nothing comes without a price.<br />
<br />
For a complete example have a look at the <a href="https://github.com/rladstaetter/sudokufx">SudokuFX project</a>. Thanks for reading.<br />
<br /></div>
<div>
<br /></div>
</div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com1tag:blogger.com,1999:blog-3154704802740726031.post-25732314713416435882016-01-03T12:01:00.001+01:002016-01-03T12:01:05.619+01:00fx-tictactoe - A TicTacToe App using JavaFX and Scala<div dir="ltr" style="text-align: left;" trbidi="on">
This post describes fx-tictactoe, a <a href="https://en.wikipedia.org/wiki/Tic-tac-toe">tictactoe game</a> written in Scala with JavaFX.<br />
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEtg-pRTyaEq74pqJYlSf1SbaaPVgT6BM70X-yaS0iutYrtJNE8hGRMMMfUK8DTpYAK5hLogkARPLwTiLtuWm2OQLD9zgGKttwnF3C7x-nRT-GimU57xcbQpy9nIdZay4Hb7kc2Nn2HnJ0/s1600/TicTacToe_App_and_New_Tab.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="362" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEtg-pRTyaEq74pqJYlSf1SbaaPVgT6BM70X-yaS0iutYrtJNE8hGRMMMfUK8DTpYAK5hLogkARPLwTiLtuWm2OQLD9zgGKttwnF3C7x-nRT-GimU57xcbQpy9nIdZay4Hb7kc2Nn2HnJ0/s400/TicTacToe_App_and_New_Tab.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Screenshot of the TicTacToe application</td></tr>
</tbody></table>
<div>
<br />
I was inspired to write this application because I recently watched an old 80's film with <a href="https://en.wikipedia.org/wiki/Matthew_Broderick">Matthew Broderick</a> called "<a href="https://en.wikipedia.org/wiki/WarGames">War games</a>". Moreover, I used this topic as an assignment for an introductory JavaFX / Scala course I held in autumn 2015.<br />
<div>
<br /></div>
To get a little bit into the mood for playing TicTacToe, you could watch <a href="https://youtu.be/F7qOV8xonfY?list=PLZbXA4lyCtqpGOS2KC1mAAKaGwbup-DQt">one scene of this film on youtube</a>, where the evil master program learns how to play the game.<br />
<br />
TicTacToe is one of the games which is simple enough such that you can pre-calculate all possible game states. This "<a href="https://en.wikipedia.org/wiki/Game_tree">game tree</a>" approach allows you then to choose one of the remaining moves which leads to a win.<br />
<br />
To make the application a bit more interesting, it also shows some css wrangling which could be used for your experiments as well.<br />
<br />
Here is a snippet of the source code which shows the relevant part of the solving algorithm.<br />
<br />
<script src="https://gist.github.com/rladstaetter/bdfbe977271a01ddefea.js"></script>
<br />
Have a look at the self contained source code for the whole app <a href="https://github.com/rladstaetter/fx-tictactoe">on my github site</a>.<br />
<br />
Ps: For some readers the most interesting part maybe is the background photo, which shows a frozen lake on one of my last mountain hikes at about 2700 meters above sea level in the Austrian alps.<br />
<br />
<br />
<br />
<br /></div>
</div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0tag:blogger.com,1999:blog-3154704802740726031.post-24801653807286080272015-12-23T17:07:00.002+01:002015-12-23T17:10:51.263+01:00OpenCV 3.1 with Java Support on OsX El Capitan V10.11.1<div dir="ltr" style="text-align: left;" trbidi="on">
In this blog post I'll describe what you have to do in order to build <a href="http://www.opencv.org/">OpenCV 3.1</a> with Java Support on a Mac with El Capitan.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a data-flickr-embed="true" href="https://www.flickr.com/photos/twm_news/15986630107/in/photolist-qmFEaz-nHbjom-8TFntJ-5SnHvN-5SKagk-4jCjgm-uTsnsR-4jyhck-fbo1Hr-pUkZMZ-ef8A6N-pS3rVd-ef2VeB-55LpeC-4jydGx-ef2Tma-pRBz4r-oq6Ya6-ef8A8b-dC1uYY-6KvAKA-zPPZNi-pkVjgj-ef8CPE-ysnS3u-ef8A5y-zWbrpd-8R131S-9CL9AC-ef8A7C-nuJpqk-4THmJc-8R19r3-dC1sgf-9qaZcN-p5bXom-B1bMrF-4jyTqj-bDRy53-ef2NKM-ef2NHT-4jCjjN-4icX57-cdv54U-4jyEjp-55Lpgm-pa3ebv-pUUg6Q-7vwWy3-ef2NJx" style="margin-left: 1em; margin-right: 1em;" title="Painting the tanker 'Borgsten'"><img alt="Painting the tanker 'Borgsten'" height="366" src="https://farm8.staticflickr.com/7577/15986630107_a8d4e0c97d.jpg" width="500" /></a></div>
<script async="" charset="utf-8" src="//embedr.flickr.com/assets/client-code.js"></script>
<br />
<br />
(If you don't want to do source builds and you don't have all necessary tools installed, there are also some alternatives like <a href="http://brew.sh/">brew</a> or <a href="https://www.macports.org/">macports</a> available. In fact, <a href="http://ladstatt.blogspot.co.at/2013/04/opencv-on-macosx-with-java-support.html">I blogged about using this approach some years ago</a>.)<br />
<div>
<br />
<h4 style="text-align: left;">
Compiling OpenCV 3.1</h4>
<br /></div>
First, you will have to download the sources directly from the official opencv.org site. It is a rather large source distribution, so the download may take a while.<br />
<br />
Unpack the source ball into a directory, I did it like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">~/opencv/ (1)</span><br />
<span style="font-family: Courier New, Courier, monospace;">~/opencv/opencv-3.1.0/ (2)</span><br />
<br />
I created a directory named "build"<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">~/opencv/build/ (3)</span><br />
<br />
(1) ... a directory which includes all opencv versions, so you have everything in place if you want to follow more than one version and you don't use git for doing this<br />
(2) ... the sources like you've downloaded them<br />
(3) ... the build directory which will be cluttered up by cmake with all kinds of stuff<br />
<br />
Change to the directory (3) and issue following command:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">cmake ../opencv-3.1.0/</span><br />
<br />
This command will investigate what is already installed on your system. It will do its best to download stuff it will need to compile what is possible. Certain tools or libraries you still need to download manually, though. This command will finish in a minute and end with a thorough report of how the build is configured. Check this list and see if your feature is configured aswell. To my surprise and as opposed to the last try with version 2.4.6 the java bindings are activated per default which is great. Huge thanks for the build guys of this library.<br />
<br />
The cmake command is setup in a way that in theory you just have to invoke another command, named<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">make</span><br />
<br />
which will invoke by itself all programs which contribute to the final build artifacts. This means it will invoke c++ compilers, c compilers, helper programs and whatnot. This command will also take some time to complete.<br />
<br />
After waiting for some minutes the command exits successfully and in the <span style="font-family: Courier New, Courier, monospace;">bin</span> folder there is a jar file which contains all bindings to the opencv library. This API is then the entrance for using the excellent library from your Java applications.<br />
<br />
<h3 style="text-align: left;">
Using OpenCV 3.1.0 with Maven</h3>
<br />
After having compiled opencv like described above, several directories and files had been created. Amongst those, in the 'bin' folder, there is a file called<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">opencv-310.jar</span><br />
<br />
This jar file can be installed in the local maven repository like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">mvn install:install-file </span><br />
<span style="font-family: Courier New, Courier, monospace;"> -Dfile=opencv-310.jar </span><br />
<span style="font-family: Courier New, Courier, monospace;"> -DgroupId=org.opencv </span><br />
<span style="font-family: Courier New, Courier, monospace;"> -DartifactId=opencv-java </span><br />
<span style="font-family: Courier New, Courier, monospace;"> -Dversion=3.1.0 </span><br />
<span style="font-family: Courier New, Courier, monospace;"> -Dpackaging=jar</span><br />
<br />
From now on you should be able to reference the library with maven in the pom.xml like this:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"><dependency></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <groupId>org.opencv</groupId></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <artifactId>opencv-java</artifactId></span><br />
<span style="font-family: Courier New, Courier, monospace;"> <version>3.1.0</version></span><br />
<span style="font-family: Courier New, Courier, monospace;"></dependency></span><br />
<br />
Still, in order to get OpenCV to work, you'll need the native part of the library which contains "the real thing" - the Java code is just a thin wrapper which makes it more convenient to call the native code. Those files are generated in the "lib" folder:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">libopencv_objdetect.3.1.0.dylib</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">libopencv_calib3d.3.1.0.dylib</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">libopencv_objdetect.3.1.dylib</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">libopencv_calib3d.3.1.dylib</span><br />
<span style="font-family: Courier New, Courier, monospace;">...</span><br />
<span class="Apple-tab-span" style="font-family: 'Courier New', Courier, monospace; white-space: pre;"> </span><br />
<div>
One of them is called "libopencv_java310.so" - this library contains the native code for the api which is accessible through the jar file. Make sure this library is loaded before you call the first time into the jar file via </div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">System.load(new File("/path/to/libopencv_java310.so"))</span></div>
<br />
This should help you start developing against the OpenCV API with Java and MacOsX.<br />
<br />
It may happen however, like mentioned, that you will need to install additional software packages such that the compilation step of OpenCV is successful for you.<br />
<br /></div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com2tag:blogger.com,1999:blog-3154704802740726031.post-3609836725424047702015-12-11T12:29:00.000+01:002015-12-15T15:40:46.218+01:00JavaFX Tableview<div dir="ltr" style="text-align: left;" trbidi="on">
In this very short blogpost I'll present you an example for the usage of the JavaFX tableview component.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlosEol6Xu8WIGuySFGL2OO4p8Rgjzs4-tebybg3qjVWYF2cqAeDvmQynbHgvhb9SJBWlWAD6rnUFnu6kwp8ZUBXrakuIBQgc6rHNXseBs-YodLURBa8M1vACP_p8PA1R756SXpqGPe4Ac/s1600/TableView_Example_App_and_Failed_to_open_page.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlosEol6Xu8WIGuySFGL2OO4p8Rgjzs4-tebybg3qjVWYF2cqAeDvmQynbHgvhb9SJBWlWAD6rnUFnu6kwp8ZUBXrakuIBQgc6rHNXseBs-YodLURBa8M1vACP_p8PA1R756SXpqGPe4Ac/s400/TableView_Example_App_and_Failed_to_open_page.png" width="381" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A JavaFX TableView Screenshot</td></tr>
</tbody></table>
<div>
<br />
Yes, the app does not much - it displays some random data in a javafx TableView control. </div>
<div>
<br /></div>
<div>
The interesting thing maybe is how the table columns are initialized:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEJbopSARkrdj_fGDl3N4Q0Y-KaDUmgPJ4vS1URjisPDDqs7x0kqKgCrwCJf-yOv_XqBo_ilZNNk9TanIRnf1IBwoBkQl3LKUB6wZDUctl8sV36sUymKPcS4QqaqlftCxBSvoXCU9LVbwQ/s1600/TableViewApp_scala_-_swengb_-____Documents_fhj__-_IntelliJ_IDEA__Community_Edition__IC-143_1183_10.png" imageanchor="1"><img border="0" height="97" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEJbopSARkrdj_fGDl3N4Q0Y-KaDUmgPJ4vS1URjisPDDqs7x0kqKgCrwCJf-yOv_XqBo_ilZNNk9TanIRnf1IBwoBkQl3LKUB6wZDUctl8sV36sUymKPcS4QqaqlftCxBSvoXCU9LVbwQ/s400/TableViewApp_scala_-_swengb_-____Documents_fhj__-_IntelliJ_IDEA__Community_Edition__IC-143_1183_10.png" width="400" /></a></div>
<div>
<br /></div>
<div>
I think it is quite obvious what is going on - the columns are somehow connected to the properties of ... erm ... the row entries.</div>
<div>
<br /></div>
<div>
More often than not this is what you want from a tableview, just display some data. </div>
<div>
<br /></div>
<div>
Consulting javadocs for <a href="http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TableView.html">TableView</a> or <a href="http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TableColumn.html">TableColumn</a> never hurts, but sometimes it can be a little bit hard to get the big picture, especially when you don't have much experience with JavaFX.<br />
<br /></div>
<div>
The abstractions provided here help you to display some data quickly (in terms of development time) and can be reused in various scenarios. A self contained project is hosted on <a href="https://github.com/rladstaetter/fx-scala-tableview">my github site</a>, but for the impatient i'll repost the essential parts here as a gist:<br />
<br />
<br />
<br />
<br /></div>
<div>
<script src="https://gist.github.com/rladstaetter/685ee5d0d9b80c43a426.js"></script>
</div>
<div>
Thanks for reading.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
</div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0Graz, Austria47.070714 15.43950399999994346.897685 15.116780499999942 47.243743 15.762227499999943tag:blogger.com,1999:blog-3154704802740726031.post-12482652321324530082015-06-21T16:37:00.000+02:002015-06-22T06:41:01.689+02:00Sudoku Capturer Release 1.6<div dir="ltr" style="text-align: left;" trbidi="on">
Sudoku Capturer presents itself now as a self contained app, without the need of OpenCV Manager as a separate download.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://www.flickr.com/photos/sdasmarchives/9971203995" style="margin-left: auto; margin-right: auto;" title="Carter Buton Album Loan_00115 by SDASM Archives, auf Flickr"><img alt="Carter Buton Album Loan_00115" height="283" src="https://c2.staticflickr.com/6/5476/9971203995_cf4af43efb_n.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">From <a href="https://www.flickr.com/photos/sdasmarchives/9971203995/">a album</a> belonging to barnstormer/daredevil Carter Buton.</td></tr>
</tbody></table>
<br />
I've decided to use the possibility to integrate OpenCV as a native library without the OpenCV Manager functionality since it improves dramatically the user experience for the application.<br />
<br />
Many people had been asking themselves why a "third party" dependency had to be installed for the Sudoku Capturer application, and thus I've decided to go the "deprecated" road and link the OpenCV libraries "statically".<br />
<br />
In retrospect I should have done this much earlier, since I've learned that I don't have to include every static lib which is offered by OpenCV, I get away with only a subset of those libraries, and the download is in sum even smaller than with the OpenCV Manager.<br />
<br />
Since OpenCV is the only native library I need it suffices to copy the libs to the appropriate place and thankfully the android maven plugin does the rest. Sudoku Capturer supports with armeabi-v7a architecture.<br />
<br />
<h3 style="text-align: left;">
About Sudoku Capturer</h3>
<br />
<a href="https://play.google.com/store/apps/details?id=net.ladstatt.apps.sudoku.android">Sudoku Capturer is an app to solve Sudokus</a> by using your mobile phone camera. The app uses OpenCV and and Scala, and runs on Android. Furthermore a testbed exists which targets JavaFX on the desktop which makes the development process and debugging of the image processing part much more practical than the typical mobile development workflow would ever permit. The whole <a href="https://github.com/rladstaetter/sudokufx">source code is hosted on GitHub</a> and can be used for your own experiments.<br />
<br />
<br /></div>
rladstaetterhttp://www.blogger.com/profile/09821109125840048026noreply@blogger.com0