How I git.

I always like this practical insights:

https://daniel.haxx.se/blog/2020/11/09/this-is-how-i-git/

Exclusively use git via console with modified prompt. Same here!

scm_info(){
    git_info=`git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'`
  if [ "${git_info}" ]; then
    if [ "$(git status -s)" ]; then
      git_color='\033[1;31m'
    else
      git_color='\033[1;36m'
    fi
    echo -e "${git_color}git:${git_info}"
  fi
}

PS1='\n\[\033[1;32m\][\w] $(scm_info)\[\033[0m\]\n\$ '

My advice for beginners is: 1. Do not hesitate to bring all sort of command line tools into position. Git offers nice tools for many situations but you don’t have to use them all. 2. Branch, Branch, Branch – it will help you to go back.

Learning JSF – The JSF Lifecycle

1. There is only one user interaction – it is called “the Request”. Please forget about GET,POST,PUT,DELETE. It is just “the request”. The request in general is not of your concern. Everything is handled by the framework. You don’t have to write controller code. In fact, you can not! The controller is already there. It is called “FacesServlet”.

2. The Framework handles all aspects of HTTP with  “the request lifecycle”.

3. You have to learn the request lifecycle.

The Request Lifecycle

  1.  User Request goes in.
  2.  FacesServlet (Controller) asks the Facelet(View) to build the view
  3.  The Facelet asks the BackingBean (Model) to provide data, e.g. from database.
  4.  For that the BackingBean often uses additional Beans.
  5.  The Facelet does a “Restore View“. Now the View is up to date. But…. only internally. Nothing is rendered yet because…
  6.  Now the “Apply Request Values” phase is entered. For that more data is fetched from the BackingBean.  The Request Values are applied. And an “ActionEvent” is queued.
  7.  Get data from BackingBean to “Process Validations
  8. Now a “ValueChangeEvent” is queued. This tells the FacesServlet that something has happend. Please notice, that the Servlet was the thing that originally startet the “postback request”.
  9. FacesServlet. Eventually invokes ValueChangeEvent at the Backing Bean. But wait, first it fetches again the old version of the BackingBean compares it to the new version, and only if changes where detected the “ValueChangeEvent” is sent.
  10. Now – tada – “Update Model Values” in the Facelet.
  11. Which then sets the values to the BackingBean. This hopefully applies, and…
  12. now an “ActionEvent” is invoked by the framework – because something might have happended. This is the point where all sort of registered Listeners are informed and can start running…1,2,3 go!
  13. This also gets noticed by the BackingBean which is now used in a phase named “Obtain Navigation Outcome“. Sure, because after all – how in the world should the controller know what view to render next? No, it is not determined by the controller endpoint, it is determined by a String that is send after each action in the BackingBean. Hopefully the String points to an existing xhtml  page (Facelet)! What should go wrong? Now everything is prepared and….
  14. Render Response” is done by the Facelet – No not the one you invoked inititally but the one that referenced by the last action of the BackingBean.
  15. Generate HTML output” is sent to FacesServlet
  16. Response is send the user.

Advantages

  • You can hook additional Beans into every phase and register listeners to the emitted events. This makes the framework very powerful and flexible.
  • The whole thing works heavily with Dependency Injection. You can easily provide different implementations for different contexts. This is especially useful for testing purposes and provides a mechanism to reuse components in different scenarios.
  • You can completely focus on the framework. You don’t have to care about working directly with HTTP or the database. Therefore the application can interact in different scenarios. Components can be reused.

Disadvantages

  • It is not possible to create a standard HTTP based webapp with the framework.
  • You won’t get citeable and stable URLs. There is only one hard implemented controller endpoint that handles all requests.
  • It is almost not possible to create an app that stays stateless. The result is an application that almost always depends on a server session. This makes the framework susceptible for polluted sessions, dangling sessions and is by principle not thread safe. Programmers really have to take care.
  • The navigation concept is a real mess. It is implicit, not safe and from client perspective unpredictable.
  • It is hard to google. Since JSF can be combined with different implementations CDI, EJB, JPA

 

Debian Repo

I started a debian repo at bintray, mostly for fun stuff and own usage.  Don’t expect more than random stuff.

Accept the bintray gpg key.

curl -sSL \
'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x379ce192d401ab61' \
| sudo apt-key add -

Add my repo

echo "deb https://dl.bintray.com/jschnasse/debian buster main" | sudo tee -a /etc/apt/sources.list.d/jschnasse.list
sudo apt update

Bash hacks. Structured directory listings.

$ lscsv -l /etc/profile |oi -t yaml -i csv --header "type,perm,hlinks,user,group,size,modified,name"
---
data:
- group: "root"
  hlinks: "1"
  modified: "Sep 16  2019"
  name: "/etc/profile"
  perm: "rw-r--r--"
  size: "902"
  type: "-"
  user: "root"

With `lscsv` (gist)

and `oi` (java)

wget https://schnasse.org/deb/oi_0.0.1.deb
sudo apt install ./oi_0.0.1.deb

 

A tool to convert CSV, YML, XML, JSON and JSON-LD – oi v0.1

First release of oi is ready for testing. oi is an experimental command line tool to convert structured data from one format into another. The first release comes with rudimentary support for CSV, JSON, XML, YML and JSON-LD. The basic idea is to provide a straight in-out/out-in command that might not work completely correct but complements with other tools (jq, xsltproc,  sed, grep, awk, etc. ) to manipulate structured data on the command line.

Install

wget https://schnasse.org/deb/oi_0.0.1.deb
sudo apt install ./oi_0.0.1.deb # installs openjdk-11-jre

Example Usage

  1. Convert passwd to yml (use -t to print different formats)
oi /etc/passwd -d":" --header="login,password,uid,gid,comment,home,shell" -icsv
  1. List some disk info in yml (use -t to print different formats)
lsblk |grep -o sd.*|awk '{print $1 ";" $4 ";" $NF}'|oi -d";" --header="device,size,mount" -icsv
  1. Create adhoc Json-Ld Context for some arbitrary Json-API
curl https://api.github.com/users/jschnasse|oi -ijson -tcontext

Java: Simple Read/Write of Maps as Json

You can use tools like Jackson to serialize and deserialize maps to json an vice versa.

Example

@Test
public void loadMapFromFileAndSaveIt(){
    Map<Object, Object> map = loadMap("map.json");
    map.put("8", "8th");
    map.remove("7");
    saveMap(map,"/path/to/map2.txt");
}

private Map<Object, Object> loadMap(String string) {
    ObjectMapper mapper = new ObjectMapper(); //should be initialized outside!
    try (InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("map.json")) {
        return mapper.readValue(in, HashMap.class);
    }catch (Exception e) {
        throw new RuntimeException(e);
    }
}

private void saveMap(Map<Object, Object> map,String path) {
    try (PrintWriter out = new PrintWriter(path)) {
        out.println(toString(map));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public String toString(Object obj) {
    try (StringWriter w = new StringWriter();) {
        new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true).writeValue(w, obj);
        return w.toString();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

If the file map.json on your classpath contains

{
 "1":"1th",
 "2":"2th",
 "3":"3th",
 "4":"4th",
 "5":"5th",
 "6":"6th",
 "7":"7th"
}

The code above will modify it and writes it to a file /path/to/map2.txt that will contain the modified map.

{
  "1" : "1th",
  "2" : "2th",
  "3" : "3th",
  "4" : "4th",
  "5" : "5th",
  "6" : "6th",
  "8" : "8th"
}

 

JPackage – Launch Java Apps without JVM

The jpackage tool of Java 14 can be used to create platform specific packages of java apps.  The app does not require a JVM to run.

Example

/opt/jdk-14/bin/jpackage --name etctoy --input target --main-jar etctoy.jar

The call is made from within a maven project. etctoy.jar is a fat-jar (size 6.6M) but the call should also work for regular jars with further dependencies in the target directory (see –input parameter).

The result is a debian package that installs the app under /opt/etctoy

sudo dpkg -i etctoy_1.0-1_amd64.deb

The installation uses 140M of disk space.

To make the tool available via command line on should link the binary into /usr/bin

sudo ln -s /opt/etctoy/bin/etctoy /usr/bin