wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

By Date: December 2021

Deploying your frontend as webJar


In an API driven world back-end and front-end are clearly separated and might live on different servers alltogether. However for smaller applications serving static files happens from the same place as your backend lives

So many choices

The web server that proxies your application server could have a rule for static files, your firewall could so that, you use a static directory on your application server or pack, that's the story here, your front-end into a jar. I'm not discussing the merits of the different approaches here, that's a story for another time, but describe the workflow and tools for the JAR approach.

vert.x static routes

In Vertx a static route can be declared with a few lines of code:

Router router = Router.router(vertx);
router.route("/ui/*")
      .handler(StaticHandler.create("uitarget"));

Vertx will then look for the folder uitarget in its current working directory or on the classpath. So you will need to put your jar on the classpath

The swagger-ui example

There are lots of prepackaged UI jars available and easy to integrate into vert.x. For example the Swagger UI. Define a dependency in your pom.xml and a one liner to access the code:

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>swagger-ui</artifactId>
    <version>4.1.3</version>
</dependency>
Router router = Router.router(vertx);
router.route("/assets/lib/*").handler(StaticHandler.create("META-INF/resources/webjars"));

Packing your own front-end

Most modern build front-ends owe their executable form to an npm build command. If you are not sure check the documentation for React, Angular, Lightning, Vue, Ionic or whatever framework you fancy.

There are two plugins for maven that can process front-end work:

  • The Frontend Maven Plugin: Specialized module that handles download of NodeJS and running your NodeJS based build tools. Great when you don't have NodeJS installed anyway
  • The Exec Maven Plugin: Generic plugin to run stuff. Doesn't download NodeJS for you. More work to setup (that's what I picked)

The steps you will need to perform, actually not you, but your mvn package run:

  • run npm install
  • run npm build
  • move files into the target directory structure
  • build the Jar

All of this can be wrapped into your pom.xml. I usually add the front-end as a module to the whole project, so a build is always complete


Read more

Posted by on 27 December 2021 | Comments (0) | categories: Java JavaScript vert.x

Refresh local git repositories


I keep all my software that is under version control below a few directories only. E.g. OpenSource projects I cloned to learn from them live below ~/OpenSource. Keeping up with updates requires to pull them all.

Pulling the main branch

My little helper does:

  • change into each first level sub directory
  • check if it is under version control
  • capture the current branch
  • switch to main or master branch, depending on which one is there
  • capture the name of the tracked remote
  • fetch all remotes
  • pull the tracked remote
  • switch back to the branch it was in

The script does not check if the current branch is dirty (preventing checkout) or pushing back changes. Enjoy

#!/bin/bash
# Pull all repos below the current working directory

do_the_sync() {
  for f in *; do
      if [ -d $f -a ! -h $f ]; then
         cd -- "$f";
         if [ -d ".git" ]; then
            curBranch=$(git branch --show-current)
            mainBranch=nn
            echo "Working on $f";
            if [ "`git branch --list main`" ]; then
              mainBranch=main
            else
              mainBranch=master
            fi
            remoteBranch=$(git rev-parse --abbrev-ref ${mainBranch}@{upstream})
            IFS='/' read -r remoteSrv string <<< "$remoteBranch"
            echo "working on $mainBranch tracking $remoteSrv"
            git fetch --all
            git pull $remoteSrv
            git checkout $curBranch
         fi
         cd ..
      fi;
  done;
};

do_the_sync
echo "DONE!"

As usual YMMV


Posted by on 23 December 2021 | Comments (0) | categories: GitHub Software

Spotless code with a git hook


When developing software in a team, a source of constant annoyment is code formatting. Each IDE has slightly different ideas about it, not even getting into the tabs vs. spaces debate. Especially annoying in Java land is the import sort order

Automation to the rescue

I switch between editors (if you need to know: Eclipse, Visual Studio Code, OxygenXML, IntelliJ, Sublime, Geany, nano or vi (ESC :!wq)) frequently, so an editor specific solution isn't an option.

Spotless to the rescue. It's a neat project using Maven or Gradle to format pretty (pun inteded) much all code types I use. The documentation states:

Spotless can format <antlr | c | c# | c++ | css | flow | graphql | groovy | html | java | javascript | json | jsx | kotlin | less | license headers | markdown | objective-c | protobuf | python | scala | scss | sql | typeScript | vue | yaml | anything> using <gradle | maven | anything>.

Setup

I opted for the eclipse defined Java formatting, using almost the Google formatting rules with the notable exception not merging line breaks back.

There are 3 steps involved for the Maven setup:

  • Obtaining the formatting files, outlined here. Just make sure you are happy with the format first
  • Add the maven plugin (see below)
  • Add a git hook (see below)

pom.xml

This is what I added to my pom.xml. By default spotless would run check only, so I added apply to enforce the formatting

<properties>
   <spotless.version>2.4.1</spotless.version>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>com.diffplug.spotless</groupId>
            <artifactId>spotless-maven-plugin</artifactId>
            <version>${spotless.version}</version>
            <executions>
               <execution>
                 <goals>
                   <goal>apply</goal>
                 </goals>
               </execution>
            </executions>
            <configuration>
                <formats>
                    <format>
                        <!-- Markdown, JSON and gitignore -->
                        <includes>
                            <include>*.md</include>
                            <include>*.json</include>
                            <include>.gitignore</include>
                        </includes>
                        <trimTrailingWhitespace />
                        <endWithNewline />
                        <indent>
                            <spaces>true</spaces>
                            <spacesPerTab>2</spacesPerTab>
                        </indent>
                    </format>
                </formats>
                <!-- ECLIPSE Java format -->
                <java>
                    <toggleOffOn />
                    <importOrder>
                        <file>${maven.multiModuleProjectDirectory}/spotless.importorder</file>
                    </importOrder>
                    <removeUnusedImports />
                    <eclipse>
                        <file>${maven.multiModuleProjectDirectory}/eclipse-java-keep-style.xml</file>
                    </eclipse>
                </java>
            </configuration>
        </plugin>
    </plugins>
</build>

A few remarks:

  • I run apply rather than check
  • the directory variable ${maven.multiModuleProjectDirectory} is needed, so sub projects work
  • you want to extend the configuration to include JS/TS eventually

.git/hooks/pre-commit

Create or edit your [projectroot]/.git/hooks/pre-commit file:

#!/bin/bash
# Run formatting on pre-commit
files=`git status --porcelain | cut -c 4-`
fulllist=''
for f in $files; do
    fulllist+=(.*)$(basename $f)$'\n'
done;
list=`echo "${fulllist}" | paste -s -d, /dev/stdin`
echo Working on $list
# Activate Java 11
export JAVA_HOME=`/usr/libexec/java_home -v 11.0`
/usr/local/bin/mvn spotless:apply -Dspotless.check.skip=false -DspotlessFiles=$list
  • You might not need the line with Java
  • swap apply for check when you just want to check

As usual YMMV


Posted by on 10 December 2021 | Comments (0) | categories: GitHub Java Maven Software

Factory based dependency injection


No man is an island and no code you write lives without dependencies (even your low-level assembly code depends on the processor's microcode). Testing (with) dependencies can be [insert expletive]

Dependency injection to the rescue

The general approach to make dependent code testable is Dependency injection. Instead of calling out and create an instance of the dependency, the dependency is hand over as parameter. This could be in a constructor, a property setter or as method parameter.

A key requirement for successful dependency injection: the injected object gets injected as an Interface rather than a concrete class. So do your homework and build your apps around interfaces.

An example to illustrate how not to do, and how to change:

public Optional<Customer> findCustomer(final String id) {
 // Some processing here, omitted for clarity

 // actual find
 final CustomerDbFind find = CustomerDb.getFinder();
 return Optional.ofNullable(find.customerById(id));

}

When you try to test this function, you depend on the static method of the CustomerDb which is a pain to mock out. So one consideration could be to hand the CustomerDb as dependency. But this would violate "provide interface, not class". The conclusion, presuming CustomerDbFind is an interface will be:

public Optional<Customer> findCustomer(final CustomerDbFind find, final String id) {
 // Some processing here, omitted for clarity

 // actual find

 return Optional.ofNullable(find.customerById(id));

}

This now allows to construct the dependency outside the method to test by implementing the interface or using a Mock library

Not so fast


Read more

Posted by on 09 December 2021 | Comments (0) | categories: Domino Java