KafkaClientFactory

Kafka is a real time data stream processing tool. In an understandable way. You can add a message onto Kafka and others can have a subscription on a messag for processing it. The sender is the Producer that publishes a message on a topic and the receiver is an Consumer that subsribes on a topic. For some basic info read the wiki page about Apache Kafka. As you know I’m Redwood RunMyJobs (RMJ) administrator and Jave developer (formerly plsql dev) at ASWatson. From the business it was required to als support Kafka processes.

RMJ in itself is an eventbased processautomation tool build in Java. Custom made Java code can be hooked into RMJ by creating a library and link that to processdefinitions. So there I had a base to start developing. First attempt where huge piles of serial code. No object no nothing ugly to the base. A mixed bag op repetitive code for consumer producers with and withou AVRO serializing. And worst of all. One of the consumers created piles of extra processes. Blocking the whole system. As we say in Dutch ‘Dit moest anders’.

So I started to think about building a Factory. A DTO (Pojo) that can be fed with a mixbag of parameters on which a producer or consumer can be started. Anything is in there. From base Credentials to kafka broker url string. From a Oracle jdbc connection that can handle stored procedure returning ref cursors to retreive data from a database to stored procedures to process the messages from a consumer. And of course the properties for AVRO or String based (de-)serializing.

This whole KafkaClientFactory can by found on my GitHub.

https://github.com/JohannesKalma/KafkaClientFactory

This KafkaClientFactory can run from any (maven based) java project. For linking this library to the RMJ way of working I wrote a Parameter Wrapper, that maps the parameters from a job onto the KafkaClientFactory. I create a seperate gitHub project for that.

https://github.com/JohannesKalma/RunMyJobsKafkaClientFactoryParameterMapper

Geschaatst

Laat me beginnen met de mensen van de Stichting IJsbaan Zeist te bedanken. Door hun harde werk van afgelopen dagen, maandagmiddag: zeister-ijsmakers-werken-hard-aan-gladde-ijsvloer, maandagavond: zeister-ijsbaan-gaat-naar-verwachting-dinsdag-om-8-00-uur-open. En dan uiteindelijk vanochtend kom-schaatsen-op-natuurijs-in-zeist. Ik heb vanochtend een paar heel lekkere rondjes kunnen schaatsen op een prachtige strakke ijsbaan.

Dit is toch genieten in optima forma

mastodon

With love from POJO/DTO – JAVA

It’s now few months ago I found the POJO/DTO way of serializing and deserializing of JSON and AVRO messages. Now using it everywhere. It’s just as easy as ‘describe’ your json message in a Java Class. Initize it. Fill it with your data and Map it to the Jackson ObjectMapper and ready to go.

Create 3 classes:

class NameDTO{
	String Name;
}
class EmailDTO{
	String email;
}
class TopdeskDTO{
	EmailDTO callerLookup;
	String status;
	String briefDescription;
	String request;
	NameDTO callType;
	NameDTO category;
	NameDTO subcategory;
}

Generate the needed getters and setters, for a new Topdesk ticket payload. Actually generating a json string is now no more than:

  TopdeskDTO dto = new TopdeskDTO();
  dto.setCallerLookup(new EmailDTO("mymail@mydomain.com"));
  dto.setStatus("open");
  dto.setBriefDescription("some brief description");
  dto.setRequest("Information about the issue, can even be something in base html");
  dto.setCallType(new NameDTO("Incident")); //fixed value
  dto.setCategory(new NameDTO("Valid Category from Topdesk"));
  dto.setSubcategory(new NameDTO("Valid Subcategory from Topdesk"));

  ObjectMapper mapper = new ObjectMapper();
  String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(dto);

This results in this json string:

{
  "callerLookup" : {
    "email" : "mymail@mydomain.com"
  },
  "status" : "open",
  "briefDescription" : "some brief description",
  "request" : "Information about the issue, can even be something in base html",
  "callType" : {
    "name" : "Incident"
  },
  "category" : {
    "name" : "Valid Category from Topdesk"
  },
  "subcategory" : {
    "name" : "Valid Subcategory from Topdesk"
  }
}

Fun thing with such a POJO is, that you can also use it in a reversed way. Map your (matching) json on the POJO and and the data is available in java.

String json = {[...]};

ObjectMapper mapper = new ObjectMapper();
TopdeskDTO dto = mapper.readValue(json, TopdeskDTO.class);

Now the dto contains the data from the json string. Input can be anything. In this case it’s a string, but in most of the solutions, the input is of type inputStream (a file reader).

https://social.oarsnet.nl/@johannes/111600087614823900

Git en Github

Created a Github account today:

https://github.com/JohannesKalma

Linked the Github to my local Git repository. Now when I do a commit with a push to my local repository, I have to do another push to sync with Github. The local commit is for the bleeding edge (daily commits). When I want to make things available for the world, I’ll do the github push.

Plee kalender, dure kinderen

Vraag: “Op welke leeftijd is een kind het duurst?”

Antwoord: Zestien en zeventienjarigen.

Redenatie: Jonge kinderen hebben luiers, opvang en fruithapjes nodig. Volgens onderzoek is dat 17% van de gezinsbestedingen op een leeftijd van 0 tot 5 jaar. Maar zodra het puberstadium op zijn top is, slokken ze meer dan 20% van het gezinsbudget op. En als je er twee of meer van hebt, kan dat oplopen tot 33%, ja dat is een derde van het totale gezinsbudget. Pubers vreten je portemonnee op en eisen alleen maar meer geld voor sport kleding mobieltje chips cola snoep en zakgeld.

Plee kalender, vitamine dooddoeners?

Vanochtend weer even bijgepraat door mijn plee kalender. Laat ik met een dooddoener beginnen. Een echte dooddoener. Vraag: “Zijn toegevoegde vitamines in voeding wel gezond?”. Antwoord wat we allemaal wel weten. Het is een marketingtrucje volgens de Wageningen deskundigen. Vitamine C toevoegen aan vruchtensapjes of yoghurtjes is compleet nutteloos. Eet liever groente of fruit. Is niet alleen een normale bron van vitamines, maar is in 100% van de gevallen ook veel gezonder. Ik noem suiker en zeg verder niks. Gewoon normaal gezond eten, dan heb je al die gefabriceerde meuk helemaal niet nodig. Het is dus niet zozeer dat die toegevoegde vitamines nou ongezond zijn, maar de rest van de toevoegingen. Er is blijkbaar een uitzondering voor vitamine B12, maar dat is dan weer speciaal voor veganisten. Die hebben daar een tekort aan. Denk je dus op je veganistische tenenslippers gezond bezig te zijn, ga je toch nog dood aan vitamine B12 tekort. Maar dat is dan ook een keuze.

Conclusie. Niet alleen het toevoegen van vitamines is totaal nutteloos. Het produkt waar het aan is toegevoegd is nutteloos. Maar ja wel een hele groep marketingmensen die dan weer broodloos worden. Hopelijk werken er niet teveel veganisten als marketingmens op die afdelingen. Broodloos en ook nog eens een tekort aan vitamine B12. Einde.

NodeJS app weergeven p1monitor data

Voor het even snel bekijken waar onze zonnepanelen nu mee bezig zijn, heb ik een raspberry pi met daarop p1monitor gekoppeld aan onze slimme meter. p1monitor heeft een complete website geintegreerd, maar deze is niet responsive en schaalt helemaal niet lekker op een telefoon. En al die grafische metertjes zijn leuk, maar een eenvoudige tabelweergave is voor mij meer dan voldoende:

Dit is alles wat ik wil:

Een eenvoudig projectje, wat in een half uurtje is op te zetten.

Ik begin met het maken van een lege git repository op onze server. Deze repository wordt vervolgens op mijn chromebook gecloned naar een map die vervolgens in Visual Studio Code wordt geconfigureerd als workfolder. De ‘live’ app zal vervolgens met een pull bijgewerkt worden.

chromebook dev (vsc) — commit push –> central repository — pull — app

Hoe ik de git repo opzet, heb ik hier beschreven: New Git Repository.

In mijn geval heb ik een project gemaakt p1monitor-api. Deze ga ik eerst opzetten als een standaard nodejs express applicatie met ejs als template systeem. Deze app moet 2 dingen doen:

  1. data ophalen van de p1monitor api en deze ‘ombouwen’ naar een lokale api
  2. Deze api data op een heel eenvoudige website tonen, met een refresh-rate van 10 seconden.

Opzetten van een express applicatie (waarbij ik ervanuit ga dat een draaiende nodejs applicatie is geinstalleerd) is een fluitje van een cent. Draai daarvoor het volgende commando vanuit de werkfolder:

npx express-generator --view ejs --css --git

Na uitvoer van dit commando is dit de projectmap structuur:

Om de boel initieel draaiend te krijgen, voer ik in de folder het volgende 2 commando’s uit:

npm install
npm start

De eerste voert de installatie van de packages uit de package.json uit en het tweede commando start de applicatie op poort 3000.

Start in een browser de volgende url: localhost:3000 en als alles goed is krijg je deze pagina voorgeschoteld:

Het fundament van de applicatie werkt nu.

Het gaat hier om SPA een single page die gevoed wordt met data uit een rest api. Laten we met het eenvoudigste deel eerst verder gaan. Het allereenvoudigst nu is om de index.ejs aan te passen. Er zou ook voor een fixed index.html kunnen worden gekozen. Maar dat is voor nu meer aanpaswerk in de routers. Er wordt geen dynamic pagina data geproduceerd. De index.ejs is 100% html.

index.ejs:

<!DOCTYPE html>
<html>
  <head>
    <title>P1 data</title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h2>Huidig</h2>
    <p>Verbruik: <span id="wattcons"></span>&nbsp;<span>watt</span></p>
    <p>Levering: <span id="wattprod"></span>&nbsp;<span>watt</span></p>

    <h2>Dag</h2>
    <p>Verbruikt: <span id="kwhcons"></span>&nbsp;<span>kWh</span></p>
    <p>Geleverd: <span id="kwhprod"></span>&nbsp;<span>kWh</span></p>
    <br>
    <p>Gas: <span id="m3"></span>&nbsp;<span>m<sup>3</sup></span></p>
  </body>
</html>

Het ophalen van de data en deze realtime weergeven wordt met een brokje javascript gedaan. Omdat dit een zo minimale website is, heb ik het javascript in de body geplaatst. Om te beginnen heb ik Axios als http handler gebruikt:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

Vervolgens het script om api data op te halen (2 endpoints) en dit in de website te parsen.

<script>

async function getData() {
  try {
    let endpoints = [
    './api/current',
    './api/day'
  ];

  Promise.all(endpoints.map((endpoint) => axios.get(endpoint))).then(([{data: current}, {data: day}] )=> {
        document.getElementById('wattcons').innerHTML=current.CONSUMPTION_W;
        document.getElementById('wattprod').innerHTML=current.PRODUCTION_W;
        document.getElementById('kwhcons').innerHTML=day.CONSUMPTION_DELTA_KWH.toFixed(1);
        document.getElementById('kwhprod').innerHTML=day.PRODUCTION_DELTA_KWH.toFixed(1);
        document.getElementById('m3').innerHTML=day.CONSUMPTION_GAS_DELTA_M3.toFixed(1);
      });
  } catch (error) {
    console.error(error);
  }
}

getData();
setInterval(function(){
   getData();
}, 10000);

</script>

Deze pagina laadt nu wel, maar zal in de console 404 meldingen geven. Er moeten nog 2 api’s worden toegevoegd. /api/day en /api/current/. Allereerst de router zelf. Deze maakt gebruik van Axios om data van de p1 rest api te halen en door de routen naar onze rest api. Installeer deze eerst (en save als dependency):

npm install axios -s

Voor de router zelf herbruik de user.js in de routes folder. Deze hernoem ik naar api.js en vervang alles met deze code:

const createError = require('http-errors');

const express = require('express');
const router = express.Router();
const axios = require('axios');

router.get('/day', async function(req, res, next) {
    try {
        const response = await axios.get('http://p1monitor/api/v1/powergas/day?limit=1&json=object');
        console.log(response.data[0]);
        res.json(response.data[0]);
    } catch (error) {
        console.error(error);
        res.json({message:error});
      }
});

router.get('/current', async function(req, res, next) {
    try {
        const response = await axios.get('http://p1monitor/api/v1/smartmeter?limit=1&json=object');
        //console.log(response.data[0]);
        res.json(response.data[0]);
    } catch (error) {
        console.error(error);
        res.json({message:error});
      }
});

/* GET users listing. */
router.get('/', async function(req, res, next) {
    res.render('p1');
});

module.exports = router;

Nu moet de api nog bekend worden gemaakt als router mogelijkheid. Hiervoor pas ik de user regel aan naar api in de app.js:

var indexRouter = require('./routes/index');
//var usersRouter = require('./routes/users');
var apiRouter = require('./routes/api');

en

app.use('/', indexRouter);
//app.use('/users', usersRouter);
app.use('/api', apiRouter);

Voordat dit alles geupload wordt naar de git repo, eerst nog 2 bestanden toevoegen .env en .gitignore. Die .env doen we nu nog even niks mee, maar de .gitignore wel. Zo hoeft de hele node_modules boom niet geimporteerd te worden. En nog wat andere directories ook niet. Er zijn talloze voorbeelden te vinden op internet, wat wel en wat niet. De mijne ziet er zo uit:

Deze variant werkt heel goed, binnen mijn eigen netwerk, waarbij aangenomen wordt dat de raspberry pi in de netwerk dns bekend is als p1monitor. Als je deze app ook buiten de deur wil gebruiken, dan zul je een portforward in je modem router moeten instellen. Deze instelling valt ver buiten de scope van deze blog en is per modem en provider anders. Voor de beeldvorming, bij ons thuis is het geconfigureerd in de fritzbox en is deze gekoppeld via een dynamic dns service.

Daarom toch nog maar even wat aanpassingen. Om de environment file beschikbaar te stellen, is het nodig om dotenv te installeren:

npm install dotenv -s

De .env file wordt nu gevuld met een aantal variabelen. Omdat ik deze app achter een proxie draai, is het in sommige gevallen nodig om het volledige pad op te nemen. Omdat ik meerdere apps draai, heb ik verschillende poortnummers. In ontwikkel is 3000 prima, maar in produktie zal het iets van 30006 worden. Het is de zevende app. Ook de url van de p1monitor is beter om die niet wereldkundig te maken. De eerste stap van security is de obscurity :-). Daarom 3 parameters, die ik in ontwikkel vul met ontwikkelwaardes:

Om dotenv te gebruiken, zet ik gewoonlijk deze regel ergens bovenin de app.js file, in ieder geval ergens voordat de config gebruikt moet worden.

require('dotenv').config()

Het gebruik van het poortnummer uit deze file wordt in de /bin/www file gebruikt. Hoeft niks voor te gebeuren.

Zie deze regel

Ik persoonlijk voeg aan het eind van deze file nog even een console message toe:

Als de app nu opnieuw gestart wordt, dan krijg je dit in de log te zien:

Vraag aan chatGPT: Ken je een goede voetreflex therapeut in Zeist.

Om een goede voetreflextherapeut in Zeist te vinden, raad ik je aan om de volgende stappen te volgen:

  1. Vraag om aanbevelingen: Vraag vrienden, familieleden of collega’s of ze een goede voetreflextherapeut in Zeist kennen. Persoonlijke aanbevelingen kunnen waardevol zijn.
  2. Online zoeken: Gebruik online zoekmachines en sociale media om voetreflextherapeuten in Zeist te vinden. Je kunt zoektermen zoals “voetreflextherapeut Zeist” gebruiken.
  3. Check recensies: Als je potentiële therapeuten hebt gevonden, zoek dan naar recensies en beoordelingen van hun diensten. Dit kan je een idee geven van de ervaringen van andere patiënten.
  4. Contact opnemen: Neem contact op met de therapeuten die je interesseren en stel vragen over hun achtergrond, ervaring en behandelingsaanpak. Dit kan je helpen om te bepalen of ze geschikt zijn voor jouw behoeften.
  5. Raadpleeg brancheorganisaties: Je kunt ook contact opnemen met brancheorganisaties voor complementaire en alternatieve geneeskunde, zoals de Vereniging van Nederlandse Reflexzone Therapeuten (VNRT), voor aanbevelingen.
  6. Overleg met je huisarts: Als je twijfelt of voetreflextherapie geschikt is voor jouw specifieke gezondheidssituatie, overleg dan met je huisarts voordat je een therapeut kiest.

Onthoud dat het belangrijk is om met een gekwalificeerde en erkende voetreflextherapeut te werken om de beste zorg te ontvangen.

Advies van Johannes : voetreflextherapie-zeist.nl