Blog: Latest Entries (15):


Unmodifiable Maps in Java

Manchmal soll Logik auf Daten einer Map zugreifen können aber nicht ändern können. Ich habe für meine State-Implementierung Action-Dispatcher eingeführt, die Daten der Action anpassen dürfen und dafür auch Daten aus dem State zum Abgleich nutzen sollen, aber an der Stelle sollen sie nicht die Möglichkeit haben den State selbst zu ändern, weil ich an der Stelle keine Änderungen tracke. Action-Dispatcher sollen schnell und leichtgewichtig sein.


Map<String, Object> stateUnmod = Collections.unmodifiableMap(this.state);
for (ActionDispatcher dispatcher: this.dispatchers) {
dispatcher.dispatch(action, stateUnmod);
}


Zum Glück kann man mit Collections sich schnell eine unmodifiable Map erstellen. Was das für die Performance bedeutet habe ich noch nicht getestet, aber ich gehe davon aus, dass das Tracken und Behandeln von Änderungen am State am Ende auf wendiger wäre.

Unfertiges Shopware-Plugin jetzt bei GitHub

Ich habe ein älteres (letztes Jahr September) angefangenes aber nie fertig gewordenes Shopware Plugin nun bei GitHub hochgeladen, in der Hoffnung, dass noch jemand was damit anfangen kann. Es fügt z.B. ein zusätzliches Feld zum Product-Slider Emotion-Element hinzu und ändert das Template für bestimmte Artikel im Slider.

bbcode-image


https://github.com/annonyme/HPrArticleQuantityDiscountSlider

Das Plugin nutzt nur PHP und kein JavaScript.

Stored Procedures in MySQL

Viele Probleme lassen sich nicht durch einfache SQL-Queries lösen. Gerade wenn es um Daten-Generierung und Dinge geht, wo man die Logik nicht in allen Clients umsetzen möchte, die auch die Datenbank zugreifen.

Wärend Stored Procedures coole Dinge wie IF, WHILE und so können, haben die doch oft einen schlechten Ruf, weil man dann ja nicht mehr Datenbank unabhängig wäre, wenn man anfängt diese zu verwenden. Aber am Ende wird man sowie so nie wirklich die Datenbank wechseln und sollte man das tun, dann eher von SQL zu NoSQL und da ist es dann auch egal, da man alles alle neu anpassen muss.


Eine einfache Procdure in MySQL:


DELIMITER \\
DROP PROCEDURE IF EXISTS exampleProcedure\\
CREATE PROCEDURE exampleProcedure()
BEGIN
DECLARE checkval INT;
SET expectedval = 0;

START TRANSACTION;

-- implement your logic here

IF checkval = expectedval THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END \\
DELIMITER ;

CALL exampleProcedure();

DROP PROCEDURE IF EXISTS exampleProcedure;


Es gibt auch die klassischen IN und OUT Parameter. Alles ganz einfach und schnell zu schreiben. Sieht ein wenig aus wie Pascal. ABER im Vergleich zu PL/SQL fehlen doch eine Datentypen wie RECORDs, um komplexere Datenstrukturen anlegen zu können oder direkter mit Tables arbeiten zu können. SELECT .. INTO ist nett, aber RECORDs machen es doch sehr viel einfacher und strukturierter.

Aber an sich kommt man damit zurecht und man sollte doch mehr davon und auch öfters Stored Procedures verwenden, um sich in einigen Teilen das Leben etwas leichter zu machen.

Ich habe PL/SQL immer gerne verwendet, auch wenn ich oft genug daran verzweifelt bin.

GMX -Freemail zu unsicher?

Heute Nacht um 1:00 kam eine Email, dass bei einer GMX-Adresse das Passwort geändert worden sei. Man konnte sich nicht mehr anmelden, also war die Email korrekt.

Das Problem ist nun: 0900-Hotline ist über Mobile und VoIP nicht erreichbar. Live-Chat, Twitter, Email... gibt es alles nicht. Die einzige Hotline die geht, ist nur für zahlende Kunden.

Das Passwort selbst ändern würde gehen, wenn die alte dort angegebene Email-Adresse von Hotmail noch existieren würde. Bei den meisten Benutzern wird wohl eine Email-Adresse angegeben sein, die nicht mehr im Zugriff ist. Handy-Nummer werden viele auch nicht angegeben haben.

Zum Glück war die Email Adresse nicht wichtig und alt.. aber bei einer aktuellen und genutzten Adresse wäre das jetzt eine wirklich Katastrophe, weil davon auszugehen ist, dass alle möglichen Dienste, wo die Adresse zum Login verwendet wurde, gefährdet sind und man keine Möglichkeit hat mit GMX in Kontakt zu treten, um den Account sperren zu lassen.

Hat wer eine Lösung bzw einen alternativen Kommunikationsweg als die 0900-Nummer?

Bei den wichtigen Adressen ist, jetzt auf jeden Fall Handynummer und eine Email-Adresse, die 100%ig unter meiner Kontrolle ist, angegeben und mal gucken, ob man nicht von GMX weg geht mit den dort vorhandenen Adressen.

Bei Yahoo hatte ich trotz alles Security-Leaks nie solche Probleme, wohl auch weil ich immer Weiterleitungen davor schalte.

CSS overflow und ellipsis

Ein kleiner Tipp, wenn man in einer Webapp zulange Listen- oder Tabelleneinträge zurecht schneiden möchte. Um anzuzeigen, dass der Text gekürzt ist will man oft ... am Ende stehen lassen. Das mit PHP, JavaScript, etc zu machen ist aber doof und overflow-hidden: hidden reicht nicht. Aber es gibt in CSS text-overflow.


.cut-ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}


Der Text wird einzeilig und abgeschnitten. Zusätzlich werden 3 Punkte angehängt. Alles gut? Nur solange man es nicht bei einem <li> mit Bullet-Points verwendet. Die gehen dabei leider auch verloren. Aber auch hier gibt es eine Lösung, wobei man aber die Abstände des <li> zum linken Rand neu anpassen muss.


li.cut-ellipsis {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
list-style-position: inside;
}

CURL und --data-binary mit CSV

Falls man mal CSV-Daten per CURL irgendwo hin schicken will und es funktioniert einfach nicht, wie gedacht.. dann sollte man überprüfen, ob man nicht --data-binary vergessen oder durch -d ausgetauscht hat und somit alle Zeilenumbrüche verloren gegangen sind.

Da zuerst zu gucken, dann einen viel Zeit bei der Fehlersuche ersparen.

JavaScript Promise Beispiel

Ein kleines Code-Snippet mit dem ich die Funktionsweise von einem Promise versucht habe zu erklären.


let key = "blubb";

function get(resolve, reject){
resolve({blubb: (new Date()).getUTCDate()});
};

(new Promise(get)).then(data => data[key]).then(val => console.log(val));


Die Frage war: Wie bekomme ich Daten in eine function für then(), wenn ich doch nur ein Argument übergeben bekomme?

So denkt man in JavaScript aber garnicht.... man muss, wie in dem Beispiel, key garnicht als Argument mit rein reichen.

Wenn eine function ein weiteres Promise zurück liefert, bezieht sich das darauf folgende then() auf die Rückgabe dieses Promises.. an sich logisch :-)

Eigenes Maven-Repository mit Github

Ich habe etwas mit State-Management in Java herum experimentiert und mir etwas geschrieben, um den State von Web-Apps (Vue.js, React, AngularJS,..) auf einen Server auszulagern. So dass sich die States und Actions der verschiedenen Clients gegenseitig beeinflussen können (Datenaustausch), aber private Daten wie Tokens trotzdem für die einzelnen Clients isoliert bleiben. Neben den Reducern gibt es noch Facets für die Anpassung der Ausgabe (so etwas wie Getter in Vuex).

Ich wollte dann einmal das Grundsystem (State-Manager, Interfaces, Server + Controller) in einem Mave-Repository ablegen und die konkrete Implementierung der Reducer, Facets und Filter dann sauber getrennt in einem eigenen Projekt haben.
Das Repository sollte einfach bei Github liegen und nicht in eines der öffentlichen und großen mit rein genommen werden, da es ja erstmal ein Proof-Of-Concept für meine Idee zu verteilten Daten ist. Ich habe mich dabei an diesem DZone-Artikel orientiert.

Meine pom.xml sieht so aus:

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

<groupId>hp-globalstate</groupId>
<artifactId>hp-globalstate-core</artifactId>
<version>0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>

<distributionManagement>
<repository>
<id>internal</id>
<url>file://${project.build.directory}/mvn-repo</url>
</repository>
</distributionManagement>

<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
<!-- .... und noch mehr ..... -->
</dependencies>
</project>


Den Inhalt aus target/mvn-repo/hp-globalstate/hp-globalstate-core/ habe ich dann in ein Github-Projekt gepackt und hochgeladen. Das 2. Projekt kommt dann dieses dann hinzu:


<repositories>
<repository>
<id>mvn-repo</id>
<url>https://github.com/annonyme/hpglobalstatemaven/tree/master</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>hp-globalstate</groupId>
<artifactId>hp-globalstate-core</artifactId>
<version>0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
</dependencies>


und ich kann mir so einen Server starten:


public class Server {
public static void main(String[] args){
GlobalStateServer server = new GlobalStateServer();
List<Reducer> reducers = new ArrayList<>();
reducers.add(new de.hannespries.test.Reducer());
List<FacetFilter> facets = new ArrayList<>();
facets.add(new DefaultFacetFilterByToken(true));

server.setReducers(reducers)
.setFacetFilters(facets)
.start(8085);
}
}


funktioniert soweit sehr gut. Also kann es bei dem Projekt in die konkrete Implementierung gehen.

DIY Überwachungskamera Setup

Bei Heise gibt es von Techstage einige Artikel über Sets von Überwachungskameras mit Netzwerk-Recordern und Teilweise mit Monitoren. Einmal fällt auf, dass die Begrifflichkeiten aus einer Zeit zu stammen scheinen in dem noch auf Videobändern aufgezeichnet wurde und andererseits fällt auch auf, dass die Preise mit min. 220 Euro doch schon sehr teuer sind. Gerade das Bild des offenen IP-Recorders von Abus zeigt ganz klar, dass hier sehr wenig "Magic" im Spiel ist, sondern diese Sets meistens nur aus einer Ansammlung von Standard-Komponenten bestehen die mit Standard-Protokollen unter einander kommunizieren.

Gerade das fällt in den Artikeln auf, dass nicht einmal der Begriff ONVIF fällt, der diese ganzen Sets relativ schnell entzaubert, wenn es sich nicht gerade um extrem proberietäre Cloud-Lösungen geht (bei China-Produkten bedeutet der Begriff Cloud meistens einfach nur FTP-Upload). Wenn man nun keine 220 Euro ausgeben kann oder möchte und trotzdem eine gute Lösung haben möchte, kann auf andere Komponenten zurück greifen, die genau so sich über ONVIF verbinden lassen und dabei noch sehr viel günstiger und teilweise hochwertiger sind. Die Einrichtung ist dann auch nicht komplizierter als bei den normalen China-Lösungen.

Wir werden ein Set aus einem "IP-Recorder" und 2 Kameras für weniger als 200 Euro zusammen stellen und dabei 1920x1080 als primäre Auflösung nutzen. Leider gibt es meine präferierte IP-Kamera nicht mehr zu kaufen, aber da WLAN sowie nett zu haben ist, nehmen wir die WLAN-Varianten. WLAN ist sowie so eine eher zu vernachlässigende Sache, wenn man eine Outdoor-Lösung anstrebt. Man muss immer beachten, dass man die Kameras mit Strom versorgen muss.
Die Netzteile sind zumeist nicht wetterfest und man müsste Verlängerungskabel verwenden. Damit man wetterfest bleibt ist die beste Lösung outdoor-CAT6 Kabel für PoE (Power over Ethernet). Wenn man also schon Ethernet-Kabel mit einem PoE-Switch für die Stromversorgung nutzt, ist es kaum Mehraufwand, das ganze mit dem vorhanden Netzwerk zu verbinden und hat damit zu meist auch eine bessere Verbindung als wenn jede Kamera einzeln sich mit dem WLAN verbinden würde. Bei Outdoor ist WLAN als eher optional, falls man irgendwie eine Kameras direkt neben einer Steckdose anbringen kann.

bbcode-image
PoE Hub aus China


Indoor sieht es natürlich ganz anders aus. Hier ist WLAN schon sehr praktisch, weil hier auch keine wetterfeste Stromversorgung von Nöten ist.

Aber egal ob indoor oder outdoor angestrebt ist, der zentrale Punkt bleibt der "IP-Recoder". Aber was ist so ein Recorder überhaupt? Auf der einen Seite ist es ein einfacher Netzwerkspeicher, aber auf der anderen Seite bietet er auch Motion-Detection und übernimmt die Aufzeichnung der Bilder und Videos. Meistens können die Kameras dieses aber schon selber und man braucht nur einen Netzwerkspeicher wie ein NAS oder eine Fritzbox. Eine Fritzbox mit einer externen Festplatte könnte also schon reichen solange die Kameras die Daten per FTP hochladen können. Aber man müsste für die Live-Ansicht jede Kamera direkt ansteuern (P2P-Modus mal ignoriert). Gerade diese Zentralität und Einheitlichkeit in der Konfigurierung, wenn man verschiedene Kameras verwenden sollte, machen so einen Recorder sehr praktisch. Zum Glück muss so ein Recoder nicht teuer sein.

Variante Mini-PC:
Ein Mini-/Tiny-PC von HP oder Lenovo ist nicht teuer und bietet sehr viel Leistung, im vergleich zu den Varianten aus den Sets bei Techstage. Ein i3 mit 4-8GB RAM ist sehr viel leistungsfähiger als ein ARM Singleboard-Computer. Auch kann man hier einfacher eine große HDD oder SSD einbauen und mit externen Festplatten erweitern und spart sich damit ein zusätzliches NAS. Auch haben diese PCs mehrere USB-Anschlüsse für USB-Kameras (was indoor eine gute Alternative zu IP-Kameras sein kein). Wenn eine Windows-Version dabei ist, kann man diese nutzen oder sich ein Linux installieren.
Mit Windows kann man iSpy verwenden, das sehr viele Einstellmöglichkeiten hat und dabei sogar einen viel Arbeit abnimmt, in dem z.B. ONVIF-Kameras fast automatisch gefunden und eingerichtet werden. Die Motion-Detection funktioniert sehr zuverlässig und auch ein zusätzlicher FTP-Upload ist möglich. Der Nachteil ist, dass es eben eine Windows-Programm ist und man somit nicht einfach die Oberfläche auf ein Smartphone holen kann.
Mit Linux hat man die Möglichkeit motionEye zu verwenden, dass man als Package installieren kann. Diese Lösung bietet eine Web-UI an, die sowohl auf Desktops als auch Smartphone gut funktioniert. Man muss aber teilweise RTSP-Urls per Hand eingeben und bekommt alle Einstellmöglichkeiten direkt und ungefiltert präsentiert. Dennoch ist die übersichtliche Ansicht egal ob auf dem Desktop oder dem Smartphone immer sehr gut und leicht und schnell zu bedienen. Wenn man also auch mal von Unterwegs einen Blick auf die Kamera-Stream werfen will, halte ich motionEye für die bessere Lösung.

bbcode-image
Ein Fujitsu Thinclient mit x86-64 Prozessor


Variante ARM-SBC:
Wer einen Raspberry PI oder Orange Pi hat (als Set zwischen 20 und 40 Euro) kann mit einer 32GB SD-Karte und motionEye OS sich eine gleichwertige Lösung in sehr günstiger, kompakter und stromsparender Version zusammen stellen. motionEye OS auf der SD-Karte am PC installieren, dann in den ARM-PC stecken und einschalten. Nach 1-2 Minuten kann man die Web-UI aufrufen und mit der Einrichtung der ersten Kamera beginnen. Die Downloads findet man hier : https://github.com/ccrisan/motioneyeos/releases

bbcode-image
Orange Pi One Kompletset


Egal welche Variante man nimmt sollte der Computer nahe dem Router stehen und benötigt so kein WLAN sondern nur ein kurzes LAN-Kabel. Bei der PC-Variante braucht man noch einen Monitor, eine Tastatur und eine Maus. Bei der ARM-Variante reicht eine SD-Karte, weil die Einrichtung rein über die Web-UI erfolgen kann (SSH ist natürlich auch möglich, aber nicht zwingend nötig).

Da wir nun einen "Recoder" haben, mit dem wir USB- und ONVIF-Kameras bedienen können brauchen wir nur noch die Kameras und etwas Zubehör.

bbcode-image
WLAN Outdoor-Kamera


Outdoor:
2x ieGeek FullHD WLAN (schwarz ist unauffäliger als weiß) = 110 EUR
2x 15m CAT6 Kabel (oder was man eben braucht) = 21 EUR
1x Universal-Netzteil = 13 EUR
1x PoE-Hub = 28 EUR
2x PoE-Adapter = 8 EUR

Wenn man dazu ein Orange PI One Set von AliExpress rechnet ist man sehr genau bei 200 EUR Gesamtpreis. Wenn man PoE-Hub und Adapter auch in China bestellt, kann man dort auch nochmal etwas Geldsparen. Die Kameras können auch direkt per FTP auf das NAS einer Fritzbox schreiben.

Indoor:
2x ieGeek FullHD WLAN (schwarz ist unauffäliger als weiß) = 110 EUR

Indoor muss eine Steckdose in der Nähe sein und man kann sich den ganzen PoE-Part ersparen bzw. einsparen. Aber es ist zu überlegen im Haus kleinere Kameras zu verwenden, die weniger direkt ins Auge stechen, wenn man nicht gerade dadurch einen abschreckenden Effekt erzielen will (in Ladengeschäften sollten Kameras immer gut sichtbar sein).

Wenn man die Kameras mit dem WLAN verbinden möchte ist die einfachste Einrichtungsart, die Kamera per LAN-Kabel einmal an den Router zu hängen und dann per Web-Browser auf die Kamera zu zugreifen und dort das WLAN einzustellen. Alle anderen Lösungen waren bis jetzt immer umständlicher oder funktionierten garnicht. Ich halte wenig davon die Kameras per Smartphone-App einzurichten, weil man gerade bei der Eingabe von Text und WLAN-Schlüssel mit einer echten Tastatur sehr viel schneller ist.

Wem 960p als Auflösung der Kameras reicht (selbst 720p ist im Indoor-Bereich oft ausreichend) kann bei den Kameras noch so um die 15 EUR pro Stück sparen.

Das wichtigste Werkzeug hier ist die Übersicht der Netzwerk-Geräte und IP-Adressen des Routers oder auch das Programm ONVIF Device Manager.

Während die Installation von motionEye auf einem ARM-SBC und iSpy auf Windows sehr einfach ist, ist die Installation von motionEye auf einem Mini/Tiny PC unter einem Ubuntu-System leicht aufwendiger. Dafür hat man die Vorteile, dass man ein komplettes Linux-System hat und den PC auf für andere Serveraufgaben verwenden kann oder den PC auf direkt mit einem großen Monitor verbinden kann und Live-Streams der Kameras anzeigen kann (localhost im Webbrowser öffnen und man hat seine UI). ARM-SBC können das an sich auch, aber hier sind oft Grafik und Leistung nicht dafür ausgelegt viele Aufgaben auf einmal zu erledigen.

Hier habe ich ein mal zusammen getragen wie man motionEye auf einem Fujitsu Futro S900 installieren kann. Dieser PC kostet um die 30 Euro bei Ebay und mit einer mSATA SSD und einem WLAN-Stick bekommt man extrem flexibelen kleinen und günstigen PC für viele Anwendungszwecke.


sudo apt-get install motion ffmpeg v4l-utils
sudo apt-get install python-pip python-dev curl libssl-dev libcurl4-openssl-dev libjpeg-dev
sudo apt-get install python-setuptools
sudo apt-get update
sudo apt-get upgrade
sudo pip install motioneye
sudo mkdir -p /etc/motioneye
sudo cp /usr/local/share/motioneye/extra/motioneye.conf.sample /etc/motioneye/motioneye.conf
sudo mkdir -p /var/lib/motioneye
sudo cp /usr/local/share/motioneye/extra/motioneye.systemd-unit-local /etc/systemd/system/motioneye.service
sudo systemctl daemon-reload
sudo systemctl enable motioneye
sudo systemctl start motioneye


Danach kann man über den Port 8765 die motionEye Web-UI aufrufen.

Man kann ohne Probleme viele USB- und IP-Kameras anschließen und hat keine Probleme mit Updates und kompatiblen Kameras, was bei Komplettsets schnell passieren kann, weil hier alle ONVIF kompatiblen Kameras funktionieren. Während mein Setup mit dem Futro S900 Thin-Client eine eher eingeschränkte Leistung hat, kann man mit z. B. Lenovo Tiny-PCs und i-Serie CPUs auf kleine Geschäfte oder mittelgroße Gebäude und Gelände überwachen (mit ~10 Kameras).

Um bei ONVIF-Kameras die URL für den Video-Stream heraus zu bekommen hilft der ONVIF Device Manager.

bbcode-image
RTSP-URL einer ONVIF-Kamera in motionEye

Hier sieht man wie eine ONVIF-Kamera per RTSP angebunden wird.

Wer iSpy verwendet, hat den Vorteil, dass auch eingebaute Microphone von Kameras ausgewertet werden können und bei bestimmten Geräuschen ein Alarm ausgelöst werden kann. Plugins für die Erkennung von KFZ-Kennzeichen oder QR-Codes gibt es auch.

Wenn man sich also für eine "Selbstbaulösung" entschiedet, kann man viel Geld sparen und bekommt zusätzlich noch einen sehr viel leistungsfähigere Recorder für einen Bruchteil des Geldes. Bei dem Preis für die Abus-Lösung (siehe den Techstage-Test), bekommt man einen refurbished PC mit i3 oder sogar i5 CPU und mehr Festplattenspeicher und kann sicher trotzdem die selben Kameras verwenden.

Meinung zu Solid

Mal meine Ansichten zu Tim Bernes-Lees Solid. Kurz: Ich halte von der Idee garnichts. Grund: Die Benutzer. Ich mag ja dezentrale Lösungen und selbst Dateien hosten ist oft günstiger als OneDrive oder DropBox. Nur die Idee, dass durch diese Pods die großen Konzerne weniger Datensammeln und nutzen würden halte ich für eine falsche Annahme.

Denn es ist ja nicht so dass Google, Facebook und andere durch das Web ziehen und einfach Daten und Bilder klauen. Diese Daten werden ihen ja von den Nutzern bereit gestellt. Aber die Benutzer bekommen ja auch was dafür. Sie bekommen kostenlosen Zugang zu den Diensten. Es ist ja ein Tausch, den die Menschen eingehen und ich glaube kaum, dass sich da was ändern würde.

- Es beginnt schon beim Anbieter für den Pod-Speicher. Keiner wird dafür zahlen wollen. Deswegen wird am Ende wieder in Daten bezahlt werden.
- Soziale Netzwerke wie Facebook haben ihre AGB, um dabei da mitmachen zu dürfen, muss man diese annehmen. Am Ende ist es denen egal, ob man die Text da schreibt und die Bilder dort hoch lädt oder man denen eine URI übermittelt, wo sie die Inhalte finden
- Suchen und Werbung, wo die meisten Daten gesammelt und ausgewertet werden.. das ist da von gar nicht betroffen

Außerdem werden die Daten per Caching immer bei den Diensten zwischengespeichert, weil kein normaler Benutzer eine entsprechende Internetanbindung hat, um wirklich selbst zu hosten und kaum einer wird einen V-Host administrieren können oder wollen.

Das Argument, dass dezentrale Netzwerke aber sehr gut funktionieren (wie Mastodon), zählt nicht, weil es eben oben schon so funktioniert und man eher untersuchen sollte warum es funktioniert, bevor man etwas entwickelt, was sofort so viele Probleme offenbart, wenn man nur länger als 10min drüber nachdenkt (ind in den News-Foren fallen die Probleme fast allen sofort auf).

Man muss Dinge wie Mastodon cool machen.. dann lösen sich die Probleme von ganz allein.

Docker und wait-for-it

Wer kennt das Problem nicht? Der Java-Appserver ist schon beim hochfahren, während der DB-Server noch Daten importiert und Hibernate fängt an wild Exceptions zu werfen.

Die Lösung ist das Script wait-for-it, das einfach wartet, bis ein Server auf einem bestimmten Port erreichbar ist.


FROM openjdk:12-alpine

RUN apk add --no-cache bash
ADD utils/wait-for-it.sh /wait-for-it.sh
RUN chmod +x /wait-for-it.sh

COPY /build/your-springboot-app.jar /app/

EXPOSE 8080

ENTRYPOINT [ \
"/wait-for-it.sh", "db:3306", "--", \
"java", \
"-noverify", \
"-XX:TieredStopAtLevel=1", \
"-Djav.security.egd=file:/dev/urandom", \
"-Dspring.jmx.enabled=false", \
"-jar", \
"/app/your-springboot-app.jar" \
]


Bargeldloses Bezahlen und die Mentalität einiger Menschen

Ich bin über diese Artikel bei T3N gestolpert, der ein Thema aufgreift, dass mir auch in letzter Zeit öfters auffiel. Es geht um das Bezahlen mit Bargeld. Das letzte mal wurde mir der Konflikt in diesem Bereich zu Weihnachten wieder deutlich, wo man viel Bargeld geschenkt bekommt. Bei der Erzählung, dass man nun ja mal wieder zur Bank müsse, um das ganze Bargeld einzuzahlen, erntete man von verschiedenen Seiten doch sehr ungläubige Blicke.

Wieso sollte man das Geld zur Bank bringen? Man müsse dann doch kurze Zeit später wieder hin und es wieder abheben!

Wenn dann gesagt wurde, man würde ja an sich nur per Karte zahlen, gingen die Gespräche in zwei verschiedene Richtungen:

1) Was ist aber bei den Sachen, wo du Bargeld brauchst?
Bei bestimmten Käufen bräuchte man das Bargeld ja einfach, weil man dort nicht mit Karte zahlen könne. Das stand so im Raum und alle Leute nickten zustimmend. Auf die Frage, wo das dann wäre, fingen alle an nachzudenken und kamen zum Schluss, dass man das nicht wisse. Es klang für alle vollkommen einleuchtend und erst beim genauen betrachten fiel allen auch auf, dass wir nicht mehr 1990 haben, wo es bei einigen Geschäftsbereichen noch "on vogue" war, Kartenzahlungen aufgrund von Preisen oder persönlichen Befinden per se abzulehnen. Aber heute kosten Zahlvorgänge über die klassische Maestro-Karte kaum noch was und die Miete der Geräte ist auch kein Kostenfaktor mehr. Selbst auf Weihnachtsbasaren kann bei den Ständen oft schon mit Karte bezahlen.

2) Dann kannst du aber mal mit Bargeld bezahlen!
Von dieser Gruppe von Menschen wird ein riesiger Unterschied zwischen dem "klassischen" Bezahlen mit Bargeld und dem bargeldlosen Bezahlen gemacht. Zahlen mit Karte wird in Notfällen benutzt, aber auch gerade bei hohen Beträgen, wo viele Angst hätten mit so viel
Bargeld rum zu laufen, wird Bargeld besonders vorgezogen. In deren Darstellung ist einfach der Bezahlvorgang mit Bargeld hochwertiger als bargeldloses bezahlen. Es geht nicht darum, das es Vorteile hätte oder ähnliches, sondern es besteht wirklich die Annahme, dass es einen Unterschied in Qualität des Vorganges gibt, auch wenn die Ergebnisse gleich sind. Das sind auch oft die Leute die Auszüge bei der Bank holen und wichtige Schreiben per Hand aufsetzen (und nicht am PC schreiben und Ausdrucken). Wenn man es genau nimmt sind es diese Leute die somit bewusst auch viel Sicherheit verzichten (Diebstahl von Bargeld.. keine PIN.. alles per Handschreiben.. verschicken und keine Kopie mehr haben, weil es nur ein Original gibt). Da kann man mit Argumenten nichts ausrichten, weil die höhere Qualität inhärent ist und damit keinem Beweis benötigt.
Die Vorstellung wird dann auch oft vorgeschoben, um sich auf keinen Fall mit modernen oder neueren Technologien und Entwicklungen beschäftigen zu müssen, weil diese per se mit einer schlechteren Qualität des Vorgangs gleich gesetzt werden. Lebensmittel online bestellen und damit mehr Freizeit haben? Unsinn... im Laden einzukaufen ist besser und Hochwertiger, auch wenn man am Ende die selben Waren zu hause stehen hat.

Das beschreibt auch oft die Probleme Digitalisierung und Automatisierung, die gerade die Jobs gefährden, die oft solche Ansichten vertreten. Aber da wird keine Problem gesehen, weil direkt damit argumentiert wird, dass die Arbeit des Menschen eine höhere Qualität habe.
Nicht das Ergebnis! Aber der Vorgang der zu dem Ergebnis mit der selben Qualität führt. Daher wären Faktoren wie Kosten und Zeit auch relevant.

Wer jetzt glaubt ich schreibe hier von Menschen ab 50 aufwärts.. nein.. ich habe das genug bei Leuten erlebt die noch nicht 30 sind. Ich bin gespannt, wie lange solche Meinungen noch überdauern können. Wenn man Leute über 60 sieht, die nie ein Smartphone haben wollten, weil es viel zu kompliziert sei. Internet und Homebanking sein ja sowie so unsicher und zu kompliziert. 5 Jahre später wird alles dies von diesen Menschen wie selbst verständlich verwendet und ein Verzicht darauf stünde auch gar nicht mehr zur Diskussion. Die Welt entwickelt sich weiter und das betrifft nicht nur einzelne Generationen sondern immer alle Menschen auf einmal. Alle müssen sich anpassen und keiner kann es in dem Sinne aussitzen (durch wegaltern).

Ein kleiner heißer Blick in die Vergangenheit

Wer erinnert sich noch an den FAST- AV-Master? Eine PCI Videograbber-Karte für Win9x, die in voller PAL-Auflösung aufnehmen konnte. Mit Ulead Media Studio Pro konnte man echt gute Videos schneiden. Hardware MJPEG-Encoder.
Nur wenn man damit 30min Video aufgenommen hatte, sollte man aufpassen den hinteren Teil der Karte zu berühren... der war dann extrem heiß. Aber kein Kühlkörper drauf... hätte echt geholfen.

bbcode-image


Den DV-Master habe ich dann doch leider nie benutzt. Eine einfache Firewire-Karte (Miro/Pinnacle DV200) hat gereicht.

JavaScript Values von Sub-Objects per Pfad-String

Wenn man sich generische Componenten in React oder Vue bastelt, wie Lists oder Grids/Tables kommt man schnell zu dem Punkt, wo man Werte aus einem Object extrahieren muss. Z. B. wenn man sich in einer Table eine Column definiert. Man könnte eine function rein reichen, die auf die konkrete Implementierung des Item zugeschnitten ist, aber oft will man nur die vorhandenen Werte im Object zur Anzeige bringen und nicht zu viel schreiben.

Wenn man einen Key hat und auf der ersten/obersten Ebene agiert wie bei item.id ist alles einfach. Bei item.sub.moreSub.verySub.id ist es schon schwieriger.. naja eigentlich nicht und jeder hat so etwas schon mal gebastelt. Hier meine Lösung die vielleicht jemanden 5 Minuten Arbeit ersparen kann :-)


function getObjectValue(obj, path){
let curObj = obj;
const parts = path.split(".");
for(let i = 0; i < parts.length; i++){
if(curOjb[parts] !== undefinded){
curObj = curObj[parts];
}
else {
return undefined;
}
}
return curObj;
}



getObjectValue({sub:{id: 23}}, "sub.id") == 23

Older posts:

Möchtest Du AdSense-Werbung erlauben und mir damit helfen die laufenden Kosten des Blogs tragen zu können?