Showing posts with label scala. Show all posts
Showing posts with label scala. Show all posts

Friday, March 10, 2023

Deploying LogoRRR to Apple's App Store using JPackage


From the outset of this project, I had a strong desire to deploy
LogoRRR 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 reached my goal and put LogoRRR into the store. In hindsight, the process was easier than I anticipated.

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 jpackage, 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.

Here's a quick outline of my approach:

  • I used JavaFX as the GUI technology and Scala as the implementation language.
  • Maven was used as the build tool.
  • JPackage was used to create a pkg suitable for deployment to the App Store
  • Source code is available at github

To dive a little deeper into the deployment using JPackage:

  • I circumvented the modular JavaFX approach by using my own Launcher class.
  • I put everything application-related in a shaded jar.
  • I created a libs directory for everything else.
  • I created the necessary Entitlements and plist files for JPackage.
  • To keep things clean, I used an 'options' file for JPackage.

To verify my package, I used Apple's Transporter App, which gave me a quick response on any missing files in my package.

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.

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.

Sunday, September 11, 2022

ZIO and JavaFX - Hello World

As part of learning ZIO (http://www.zio.dev/)  for other projects I’m working on I’ve decided to use LogoRRR as a testbed to see which challenges have to be solved in the context of JavaFX application programming with Maven and Scala.

For context:

ZIO is a framework to perform type-safe, composable asynchronous and concurrent programming for Scala.  

LogoRRR is a desktop application written in Scala, leveraging JavaFX as desktop application technology. LogoRRR helps to analyse log files and its target audience are support/devops engineers.


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 Gluon’s  gluonfx-maven-plugin - that's the main reason why I'm using maven here. 


Anyway, now I’m confronted with following challenges:

  • How to setup a maven project with ZIO?
    • Is ZIO compatible with LogoRRR’s GraalVM compilation workflow?
  • How to integrate ZIO with JavaFX?

Monday, October 26, 2020

A native Scala JavaFX application via GraalVM

After successful attempts with Java, JavaFX and GraalVM I get closer to my goal to compile SudokuFX 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. Source code and binaries for windows and MacOsX for this blog post are available here.

03 - Sydney Harbour Bridge Construction
 Sydney Harbour Bridge Construction

JavaFX Logboard

As a vehicle for using JavaFX and FXML I chose to implement a simple log visualisation tool. I'll call it javafx-logboard. 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. 

A screenshot will make things clearer: 

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 little of XCopy, an ancestor of XCode (nerd joke). 

Motivation

I started this project and blog post with following promise:

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)

Side-note: I already successfully compiled an application with JavaCV for MacOsX with GraalVM, 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. 

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 may help twitter but is not really relevant for me ... or is it? 

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. 

Some takeaways after spending far too much time on this endeavour until everything worked


Scala Converters

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 ... )

FXML References 

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. 

fat-jar

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.

main-class not found with scala javafx apps?

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).

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.

multimodule maven project - mvn install

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?

long compile times - again

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. 

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. :( 

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!

scala-native - the other way 

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. 

file sizes acceptable

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. 

I tried my little toy project this time also with windows, and after following instructions from here it compiled without much hassle literally on the first try. Binary size on windows is roughly the same, at about 60 MB. 

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 stop by at pouet.net and ask yourself if you have made the right choices as a programmer in your life. 

low hanging fruits

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).

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. 

Source code and binaries for windows and MacOsX for this blog post are available here.

(*) 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 ;-)




Monday, May 11, 2020

Webcam Image Stream with JavaCV

JavaCV?

JavaCV is a very cool library which empowers Java users to access native libraries like OpenCV or FFmpeg and many others.

Among other things, it prepackages OpenCV with maven, as such you can jumpstart in OpenCV development in mere minutes. Even if it downloads the internet without special tuning, it is as far as I know the simplest and fastest way to try out computer vision algorithms on the Java platform.

As a bonus, it enables also writing applications for Android, not to mention the usual desktop platforms like Windows / Mac and Linux.

In the past I've created some applications using OpenCV 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.

In short, you save some time setting up your system if you just decide to use JavaCV.

Motivation

The motivation for devoting some time to JavaCV was to see if I could take advantage of the new PixelBuffer API which can use since JavaFX13 native arrays directly.

It seems clear that this should boost performance considerably and improves framerates for applications like my SudokuFX project. I've created a proof of concept  which compares different ways of using a webcam image stream based on the OpenCV stack.

In this project there are three implementations given:
  • a swing based, officially endorsed way to show a webcam / image
  • the classic JavaFX variant
  • the DirectBuffer approach
I've measured how fast each approach is, and like expected, on my machine it turns out that the last one using JavaFX with DirectBuffer is the fastest way to show a webcam image stream.

Here is the output for running the three different versions, with the swing approach being the slowest one.

home:target lad$ java -jar javacv-webcam-2020.2-SNAPSHOT-jar-with-dependencies.jar 
Mean: 719434
Mean: 628738
Mean: 601112
Mean: 579823
Mean: 565205
Mean: 552922

home:target lad$ java -jar javacv-webcam-2020.2-SNAPSHOT-jar-with-dependencies.jar classic
Mean: 9508516
Mean: 9461551
Mean: 9423204
Mean: 9419029
Mean: 9415144

home:target lad$ java -jar javacv-webcam-2020.2-SNAPSHOT-jar-with-dependencies.jar swing  
Mean: 35786482
Mean: 35410293
Mean: 35220229
Mean: 35092391
Mean: 35030641

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.

Conclusion

If you are using OpenCV and JavaFX, you should definitely give JavaCV and its enhanced API's for OpenCV a try.

Check out the source code for this blog post on github.

I would like to thank Samuel Audet who does a great job maintaining JavaCV and who also helped me get my webcam image to fit to JavaFX's PixelBuffer.

Version 2020.3.0 of javacv-webcam uses the same techniques, but is implemented in 100% Java. Check it out. 

Thursday, April 23, 2020

ScalaFix SudokuFX

I released a new version of SudokuFX, this time a maintenance release. I some warnings I got from compiling.

To make this a little bit more interesting, I used scalafix and autofix. What are those things?

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.

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:


        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>net.alchim31.maven</groupId>
                    <artifactId>scala-maven-plugin</artifactId>
                    <version>4.3.1</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>
                                <goal>testCompile</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <scalaVersion>${scala.major.version}</scalaVersion>
                        <args>
                        ...
                        </args>
                        <compilerPlugins>
                            <compilerPlugin>
                                <groupId>org.scalameta</groupId>
                                <artifactId>semanticdb-scalac_${scala.full.version}</artifactId>
                                <version>4.3.9</version>
                            </compilerPlugin>
                        </compilerPlugins>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>io.github.evis</groupId>
                    <artifactId>scalafix-maven-plugin</artifactId>
                    <version>0.1.2_0.9.5</version>
                    <dependencies>
                        <dependency>
                            <groupId>org.scalatest</groupId>
                            <artifactId>autofix_2.12</artifactId>
                            <version>3.1.0.0</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </pluginManagement>

Thats it ... more or less.

What is still missing is a configuration for scalafix, which is placed in a file called .scalafix.conf. (Note the '.' at the beginning of the file name). This file should be placed next to the main pom file.

Here is the file how I configured it:

rules = [
  RemoveUnused,RewriteDeprecatedNames,ProcedureSyntax,NoValInForComprehension,LeakingImplicitClassVal,NoAutoTupling
]

The inverted rule name is an autofix rule, which comes with the additional dependency for scalafix-maven-plugin. 

After configuring this, you have to call maven like that:

mvn clean compile test-compile scalafix:scalafix

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 and many other things.

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 ...

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.

Here is a list of available scalafix rules - or at least the closest to such a list I could find.


Hope I raised your interest in this amazing tooling, check out how to configure ScalaFix for maven (and try to solve some Sudokus and let me know if it worked ;-))

Tuesday, April 14, 2020

Artifact Dashboard: Custom Nexus Summary Page

Motivation

In this post I want to discuss a small project called artifact-dashboard which shows

how to use Nexus Repository Manager, Version 3, and it's Rest API. 

(This article is a part of a mini series of blog posts, see the second part here.)

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.

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.)

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. 

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.

(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. (UPDATE: I think there is an alternate (or maybe first hand) way to do what I describe by using well configured 'Content Selector's - a concept I didn't yet know starting this post); UPDATE 2: Obviously I'm not the only one who would like such a thing, it was resolved already, 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)

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.

Prerequisites

If you have not already done so, I would recommend installing IntelliJ Community Edition along with its excellent Scala plugin and checkout the github project which accompanies this post.

LPT: Checkout code and skip the whole blog post!

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 Sonatype's website for OSS Nexus Repository.

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.

You'll need also a small maven project to deploy to your test repository, I would recommend something small and simple without many dependencies or huge build times, or you deploy your artifacts directly to Nexus via the web gui. 

Step 1 - Basic Scala.js project setup

I start from scratch by creating more or less a Scala.js 'Hello world' minimal example.

For convenience, I made some releases in artifact-dashboard which covers different milestones during development, and can be downloaded as zip files.

Release v0.1 contains just a raw setup with more or less current versions of Scala.js and friends at the time of writing this post.

Nothing fancy here, just a minimal sbt build definition. On the sbt console you have to issue a 'fastOptJS' command such that Scala.js compiles (later then do a 'fullOptJS' to obtain the best optimized Javascript available ;-) ).

The most interesting part are the few lines of Scala code shown below:


package net.ladstatt.adash

import org.scalajs.dom.document
import org.scalajs.dom.raw.Element

object ArtifactDashboard {

  def main(args: Array[String]): Unit = {
    document.body.appendChild(p("Paragraph filled via Scala.js"))
  }

  def p(text:String): Element = {
    val p = document.createElement("p")
    p.textContent = text
    p
  }

}

By importing 'org.scalajs.dom' 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.

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 maven plugin - I don't use for no particular reason - which should support Scala.js compilation. 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.

Step 2 - setup Nexus for a simple rest call

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 Sonatype's website. To make things easy for me and this blog post, I assume from now on that a running Nexus on localhost is present.

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.

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:


<?xml version="1.0" encoding="UTF-8"?>
<settings
        xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"
        xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <mirrors>
        <mirror>
            <id>local-nexus</id>
            <mirrorOf>*</mirrorOf>
            <url>http://127.0.0.1:8081/repository/maven-public/</url>
        </mirror>
    </mirrors>

</settings>


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)

Let's try the easiest api call, or is it, at least the first one, '/v1/assets'.

You have to provide which repository to query, just enter 'maven-public' and click on 'execute'.

Do it! Do it now. I'll wait.

Step 3 - implement rest call with Scala.js

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:

curl -X GET "http://127.0.0.1:8081/service/rest/v1/assets?repository=maven-public" -H "accept: application/json"

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.

... and then I rediscovered a thing called 'CORS' ;-) 

TLDR, 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. See this article for more information.

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.

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.

Version v0.2 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:


package net.ladstatt.adash

import org.scalajs.dom.document
import org.scalajs.dom.ext.Ajax
import org.scalajs.dom.raw.Element

import scala.concurrent.ExecutionContextExecutor
import scala.scalajs.js
import scala.scalajs.js.JSON
import scala.util.{Failure, Success}

@js.native
trait CheckSum extends js.Object {
  def md5: String

  def sha1: String
}

@js.native
trait Asset extends js.Object {
  def id: String

  def path: String

  def downloadUrl: String

  def repository: String

  def format: String

  def checksum: CheckSum
}

@js.native
trait AssetsResult[T] extends js.Object {
  def items: js.Array[T]

  def continuationToken: String
}


object ArtifactDashboard {

  def main(args: Array[String]): Unit = {
    queryNexus()
  }

  def queryNexus(): Unit = {
    // executioncontext needed for ajax call
    implicit val ec: ExecutionContextExecutor = scala.concurrent.ExecutionContext.global

    Ajax.get("http://127.0.0.1:8081/service/rest/v1/assets?repository=maven-public") onComplete {
      case Success(v) =>
        val assetsResult = JSON.parse(v.responseText).asInstanceOf[AssetsResult[Asset]]
        for (a <- assetsResult.items) {
          document.body.appendChild(p(a.id))
        }
        org.scalajs.dom.window.alert(assetsResult.continuationToken)
      case Failure(e) =>
        e.printStackTrace()
        org.scalajs.dom.window.alert(e.getMessage)
    }
  }

  def p(text: String): Element = {
    val p = document.createElement("p")
    p.textContent = text
    p
  }

}

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 ;-))

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.

Don't bother me with details! Nice.

Step 4 - Setup a test repository and deploy test data to it

For convenience, I've created a dedicated Nexus Maven2 hosted repository for my experiments. I've used my before mentioned toy project to deploy it to my test repository and checked on Nexus UI and API that a deployment was successful.

In order to make this happen you have to declare a distribution management section in your pom:

    <distributionManagement>
        <repository>
            <id>testrepo</id>
            <name>testrepo</name>
            <url>http://127.0.0.1:8081/repository/testrepo/</url>
        </repository>
        <snapshotRepository>
            <id>testrepo-snapshot</id>
            <name>testrepo-snapshot</name>
            <url>http://127.0.0.1:8081/repository/testrepo-snapshot/</url>
        </snapshotRepository>
    </distributionManagement>

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.

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?)

Step 5 - Give Rest call proper parameters

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:

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

Nexus provides a convenient way to experiment with its search api, the url above yields all snapshot versions deployed on Nexus with Version 1.0-SNAPSHOT, groupId: net.ladstatt, artifactId=fx-animations. We just take the first element of the result list and can retrieve the correct url. See version  v0.3 for a source code snapshot containing described webservice call. Note also the usage of scala's Future or Either construct which can be used in Scala.js as well.

Step 6 - make it configurable

Lets recall what we have accomplished so far:
  • setup a Scala.js project from scratch
  • setup a Nexus Webserver
  • fought against CORS
  • call a webservice
  • parse json
  • map 'native' javascript objects to Scala case classes
  • build a website's dom 'dynamically'.
  • ...

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.

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.

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. 

See v0.4 for a version which has more artifacts configured and a case class structure prepared for easy configuration.

I'll stop here, maybe this project is of use for somebody or motivates to give Scala.js and / or Nexus a try.

I used this website to hightlight some source code snippets.

Thanks for reading.

Wednesday, November 16, 2016

Scala, Gradle and Android Studio

This post describes my experience with Scala, Gradle and Android Studio - (TL;DR - it works for me.)

Old keys
Photo credits: Kit 

Motivation


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.

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 its own ecosystem evolved around that idea. Those guys made a good progress.

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.

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.

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.

If you can live with this, I would say one could give it a try and develop Android Apps with Scala and Gradle.

Case Study: Basic Multitouch


I thought it would be a good idea to port a small project to Scala and see what problems I would run into.

Here is what I did:

- I forked android-scala-gradle plugin and applied an existing pull request such that the plugin works together with Android Studio 2.2.2
- forked android-BasicMultiTouch example project from google samples
- added necessary tweaks to the Gradle build to support Scala
- installed Scala Plugin in Android Studio
- ported all java code to scala code - IntelliJ Android Studio helps here a lot
- got it to compile and work on a physical android device (and simulator as well)
- "instarun" runs almost instantly ;-)

In the process of installing my environment, I've stumbled over http://sdkman.io/, which helps a lot managing different versions of gradle (or other java based libraries for that matter) - check it out!

Summary


It went well. I've downloaded half of the internet during the process, but after this initial hurdle the work was straightforward.

All the code is in github, so this time no screenshots or code listings.

Check out the github repositories for the patched android-scala-gradle plugin as well as the toy multitouch project which can be used as starting points for your own experiments.





Sunday, January 17, 2016

fx-tictactoe - A TicTacToe JavaFX application on Android

This post describes how you can install a JavaFX application on an Android device.

Mt. Hood, Oregon, in summer garb


I recently created fx-tictactoe which is a simple tic tac toe game with a computer opponent. I wondered how easy it would be to port it to Android.

TL;DR: It is easy, you'll need the javafxmobile plugin.

To start from scratch, there would be two approaches to do something like this:

- implement game logic in its own module, create a dedicated android gui
- reuse almost everything from the original javafx based game and use javafxports to run it

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 sudokufx application.

For fx-tictactoe, out of curiosity I used the second approach.

Ok, so what has to be done to get a JavaFX app to the android platform?

Step 0: Install Gradle


The javafxmobile-plugin demands a rather recent version of Gradle, so make sure you've downloaded and installed at least Gradle 2.2. You can download Gradle here.

Step 1: Setup gradle build


javafxports uses, like Javafx itself, Gradle as its build system.

Johan Vos 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.





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 here and install 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

gradle install

Note: I saw that the 1.0.8-SNAPSHOT version already resides at the sonatype snapshot repository, so it won't take long until it is deployed as a release there I assume.

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.

But back to the example javafx project I want to see on my android device:

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.

After creating the build.gradle (see gist above) file, all you need to do is type following command:

gradle android

And if you want to deploy the app to a (connected) device:

gradle androidInstall


This should deploy the apk with a debug configuration to your device.

Like stated in the official docs, the javafxmobile-plugin 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.

I would like to invite you to watch at the final result of my explorations, the video shows a working fx-tictactoe on Android:



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.

As always, I've pushed the source code for the app to my github site.

Thursday, January 7, 2016

AnimationTimer Example

This blog entry just shows a screenshot and the code for a little JavaFX AnimationTimer test I wrote.


AnimationTimer 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.




A self contained project is available here

Sunday, January 3, 2016

fx-tictactoe - A TicTacToe App using JavaFX and Scala

This post describes fx-tictactoe, a tictactoe game written in Scala with JavaFX.

Screenshot of the TicTacToe application

I was inspired to write this application because I recently watched an old 80's film with Matthew Broderick called "War games". Moreover, I used this topic as an assignment for an introductory JavaFX / Scala course I held in autumn 2015.

To get a little bit into the mood for playing TicTacToe, you could watch one scene of this film on youtube, where the evil master program learns how to play the game.

TicTacToe is one of the games which is simple enough such that you can pre-calculate all possible game states. This "game tree" approach allows you then to choose one of the remaining moves which leads to a win.

To make the application a bit more interesting, it also shows some css wrangling which could be used for your experiments as well.

Here is a snippet of the source code which shows the relevant part of the solving algorithm.


Have a look at the self contained source code for the whole app on my github site.

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.




Friday, December 11, 2015

JavaFX Tableview

In this very short blogpost I'll present you an example for the usage of the JavaFX tableview component.

A JavaFX TableView Screenshot

Yes, the app does not much - it displays some random data in a javafx TableView control. 

The interesting thing maybe is how the table columns are initialized:


I think it is quite obvious what is going on - the columns are somehow connected to the properties of ... erm ... the row entries.

More often than not this is what you want from a tableview, just display some data. 

Consulting javadocs for TableView or TableColumn 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.

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 my github site, but for the impatient i'll repost the essential parts here as a gist:




Thanks for reading.





Sunday, June 21, 2015

Sudoku Capturer Release 1.6

Sudoku Capturer presents itself now as a self contained app, without the need of OpenCV Manager as a separate download.

Carter Buton Album Loan_00115
From a album belonging to barnstormer/daredevil Carter Buton.

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.

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".

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.

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.

About Sudoku Capturer


Sudoku Capturer is an app to solve Sudokus 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 source code is hosted on GitHub and can be used for your own experiments.


Wednesday, July 2, 2014

Akka 2.3.4 and Scala 2.11.1 - on Android

This post outlines what is necessary to set up a Maven project to deploy a Scala application which utilizes Akka to Android.


Is Akka not a server framework?

Well, it is. I just wanted to see if I could manage to come up with a configuration for Maven and its Android plugin - not to forget the wonder tool every Android developer is always very happy to configure - Proguard :)

Besides, there are also others who want to get it to run on the mobile devices or did it already.

Why Scala on Android? Maven???

I do a little bit of Android programming also in my spare time, I even <shameless plug>created an app which you definitely should check out</shameless plug>, albeit I'm not using Akka for this one.
You can tell by reading my blog that I'm struggling with Maven on a daily basis - that is why I gave it a shot (because of work/life balance you know.)

I know that the 'normal' way to build scala projects is to "use the sbt", and like others  I do use it for some projects successfully. Sometimes however Maven is just ... here.

If you have the choice you should check out sbt and one of the android plugins available. The  proguard step is mandatory in the presented setup, without it it won't work. You can ease the pain of waiting for the proguard step to finish a little bit by tweaking the proguard configuration file and comment out the optimization steps.

If you still want to do it with Maven, read on or jump directly to the source on github.

Prerequisites

For this project, I used the exciting maven-android-sdk-deployer project which deploys everything you need in your local maven repository. Just follow the installation instructions on the project website.

Macroid Akka Fragments

An important piece in the puzzle is also the macroid project - check it out. For the example project I've stolen borrowed some code from the macroid-akka-fragment project which provides the necessary glue code for Akka.

In order to compile the example project, you don't need to do anything, the links were provided for reference.

Some remarks on the pom

Have a look at the configuration of the scala-maven-plugin in the project pom.xml - there are some interesting flags which enable various warnings/features for the scala compiler which help you write more correct code. See this blog post for more details.

In my opinion, the most precious thing about the whole post is the proguard configuration file. In my experience, it is quite cumbersome to come up with a working proguard configuration.

Rant: The typical user experience is that in the first few minutes you hunt for an "optimal" proguard file, after fiddling around for some hours you'll turn of all warnings and stick to the first "working" configuration.

Finally ... I get a compile error.

The maven configuration for the scala plugin is set to "incremental" - This incremental mode only works if the zinc server is also running. That means you have to start it via "zinc -start" once. I used zinc 0.3.5-SNAPSHOT for the compilation.

In theory, after cloning the repository from here and after entering

mvn clean package android:deploy

You should see something similar like this:

[INFO] --- scala-maven-plugin:3.1.6:compile (default) @ android-akka ---
[INFO] Using zinc server for incremental compilation

[info] Compiling 2 Scala sources and 2 Java sources to /Users/lad/temp/android-akka/target/classes...

- dont forget to connect your android device and activate the usb debugging mode

The app will look like this:

screenshot of the app (created with genymotion, a great android emulator!)
The app doesn't do anything interesting - it uses just one Actor (and one button), but it could serve as a start project for your own experiments with Akka, Scala, Maven and Android.

Thanks for reading!