Java classpath

Kérdés: melyik jvm verziónál fog szöget ütni valaki fejében a gondolat, hogy a classpath paraméterében az egyik platformon pontosvesszővel, a másikon kettőspont az elválasztó karakter?

Linux: java -cp “.:lib/*”

Windows: -cp “.;lib/*”

Mondjuk így legalább mindenki gyorsan megtanulja, mit értenek a fejlesztők platformfüggetlen megoldások alatt.

Flutter 2 install

Nekem is úgy mondták (öregszem), de már egy napja megjelent a Flutter 2, ami mindennél is jobb. Mindig is szerettem a UI absztrakciókat, és azokat a durvábbnál durvább hackeket amibe aztán mindenki belebonyolódik az absztrakciók következményeként (SWT és társai ugye). Gondoltam felrakom, és jól megnézem, 2021-ben mit sikerült összehozni.

A telepítés (ami másolás) gond nélkül lement, aztán azt javasolták futtassam a flutter doctort, ami azt mondta, fogadjam el az android licenszeket egy újabb flutter doctor futtatással. Mégpedig ezzel:

flutter doctor --android-licenses

Lelkes voltam, futtattam és mint lenni szokott, megint egy szuper kis kaland vette kezdetét. Ugyanis a várt nyomj Y-t és fogadd el a licenszek helyett ezt kaptam:

C:\Users\voji\AppData\Local\Android\Sdk\tools\bin>flutter doctor --android-licenses
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
        at com.android.repository.api.SchemaModule$SchemaModuleVersion.<init>(SchemaModule.java:156)
        at com.android.repository.api.SchemaModule.<init>(SchemaModule.java:75)
        at com.android.sdklib.repository.AndroidSdkHandler.<clinit>(AndroidSdkHandler.java:81)
        at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:73)
        at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:48)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:606)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:168)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        ... 5 more

Nem igazán értettem a dolgot. Na jó értettem, ez a class ugyanis a jaxb része, ami már java 9 óta deprecated 11 óta meg benne sincs a JDK-ban. Elég sokan, elég sokat szívtak már ez miatt a nagyvilágban.

Szóval vagy átírogatom mindig a környezeti változókat, hogy java8-java15-java8 vagy keresek valami értelmesebb megoldást. Az utóbbit preferáltam, így legalább lehetőségem nyílt kicsit megismerkedni a dart nyelvvel is, ami állítólag flutterhez nem hátrány.

Szóval az történt, hogy flutter doki megpróbálja nyaggatni az android sdk parancssoros kezelőjét, az sdkmanager.bat-ot. Ha ezt önmagában lefuttatjuk, akkor ugyanezt a hibát fogjuk kapni, mert ott még valaki nem vette észre, hogy egy 2017 óta deprecated dolgot használ.

A megoldás innen már egyszerű: le kell tölteni egy jaxb-t, és megoldani, hogy a classpath-on legyen.

A letöltés viszonylag egyszreű, innen lehet megtenni. FYI a jobb oldali Download felirat nem egy menü, hanem funkció. Lehet a JDK fejlesztők se találták elsőre a letöltés gombot, azért maradt ki a jaxb a JDK-ból. Tanúság: tessék jól látható letöltés gombokat használni, lehetőleg az oldal közepén.

Na de visszatérve a problémára, azt az sdkmanager.bat generálta, célszerű itt is megoldani. Ez alapesetben itt található:

%USERPROFILE%\AppData\Local\Android\Sdk\tools\bin\sdkmanager.bat

A problémás rész pedig itt (ahol látható, hogy szépen felülírják a classpath-ot, pedig az első próbálkozásom az volt, hogy oda felteszem a dependenciákat mint környezeti változó):

set CLASSPATH=%APP_HOME%\lib\dvlib-26.0.0-dev.jar;%APP_HOME%\lib\jimfs-1.1.jar;%APP_HOME%...

Ha belematatjuk ezt a kis kiegészítést (ide lett kitömörítve a csomag: d:\work\libs\jaxb-ri):

set CLASSPATH=d:\work\libs\jaxb-ri\mod\jaxb-api.jar;d:\work\libs\jaxb-ri\mod\jaxb-runtime.jar;d:\work\libs\jaxb-ri\mod\istack-commons-runtime.jar;d:\work\libs\jaxb-ri\mod\javax.activation-api.jar;%APP_HOME%\lib\dvlib-26.0.0...

Máris boldogabb lesz egy flutter pingvin a google főhadiszállásán…

C:\Users\voji>flutter doctor --android-licenses
                                                                                
7 of 7 SDK package licenses not accepted. 100% Computing updates...
Review licenses that have not been accepted (y/N)?

Gradle parametrizált task

A gradle task-ok nem tudnak paramétereket fogadni by design. Globális build paramétereket lehet olvasni belőlük, de hát azért a gányolásnak is van határa…

És bár paramétert nem lehet task-nak adni, task-ot viszonylag egyszerűen lehet létrehozni. És igény esetén kicsit bonyolultabban is.

Tegyük fel angular-t szeretnénk fordítani, különböző build target-ekkel. Vagy másolunk sokat, vagy csinálunk egy ilyet:

def createAngularTask(build, language) {
    return tasks.create("buildAngular_${build}_${language}", Exec) {
        group = "generated"
        workingDir = project.ANGULAR_APP_PATH
        inputs.dir(Paths.get(workingDir.toString(), "/src"))
        outputs.dir(Paths.get(workingDir.toString(), "/dist_hu"))
        def cmdArray = ["npm", "run", "${build}:${language}"]
        if (System.getProperty('os.name').toUpperCase().contains('WINDOWS')) {
            cmdArray.addAll(0, ["cmd", "/c"])
        }
        commandLine cmdArray
    }
}

Kicsit emlékeztet ez a C-s define varázslásokra, de úgy tűnik a groovy-s csapatot ez nem rettentette el. Szóval ha csináltunk egy ilyet, akkor már csinálhatunk ilyesmiket is:

createAngularTask("aembuild", "hu")
createAngularTask("aembuild", "en")
createAngularTask("jarbuild", "hu")
createAngularTask("jarbuild", "en")

És ha ilyeneket csináltunk, akkor már csinálhatunk csoportos build task-okat copy paste nélkül:

task buildAngularAem {
    group = BasePlugin.BUILD_GROUP
    dependsOn('buildAngular_aembuild_hu')
    dependsOn('buildAngular_aembuild_en')
}

A fenti játékot el lehet játszani akár string tömbökből is, ha nagyon sok task lenne. Így a task-oknak, csak a képzeletünk szab határt…

Microsoft Xbox wireless controller

A Microsoftnak valahogy mindig sikerül félre pozícionálni egy terméket, bármennyire is jó az. Elkezdték ezt a dolgot a konzolok nevével (tegye fel a kezét, akinek nincs xbox-ja, és sorrendbe tudja tenni, hogy az xbox, xbox one, xbox360, xbox s, xbox x volt előbb vagy utóbb) de a controllerekkel se jobb a helyzet.

De ne szaladjunk ennyire előre. Kezdjük onnan, hogy minek is controller PC-hez? A válasz egyszerű, mert jobb vele játszani. Főleg ha egy laptop, Tv, vagy esetleg mobil eszközök kerülnek a képbe. És mobil eszközök alatt nem csak a telefont értem, hanem mondjuk tabletet, a Steam in home streaming-jét, vagy a geforceNow-t. És persze ott vannak maguk a játékok. A csak controllerrel élvezhető játékok első zászlóshajója a Resident Evil széria volt (kb. az összes rész), de mostani játékokból is van bőven, ami egyszerűen játszhatatlan egérrel (pl. Detroit: become human), és azok amik jobbak controllerrel (pl. a Cyberpunk 2077).

A fentiek önmagukban még nem győznének meg arról, hogy Microsoft által gyártott controllert kell vennem, ugyanis elérhető közelségben van egy Nintendo Pro controller, ami papíron hasnálható PC-vel. Csak sajnos a Nintendo ezt a feature-t nem gondolta túl: ha kábellel próbálod használni PC-n, akkor utána a controller nem kapcsol ki soha, amíg le nem merül, vagy újra nem párosítod a switch-hez ami ki tudja kapcsolni. Amit biztos meg kell tenned, mert egy kábeles PC-s használat elég ahhoz, hogy elfelejtse ő valójában egy Nintendo Switch-el párosított controller, szóval onnantól nincs se távoli bekapcsolás, se instant játék… Tehát papíron a feature pipa, gyakorlatban használhatatlan.

És ha ez nem lenne elég, a Microsoft megcsinálta azt, amit a Nintendon’t. Képesek voltak szabványos bluetooth protokollt is implementálni a vezérlőjükbe, ami kommunikál androiddal és IOS-el. Ez volt az a pont, ami meggyőzött, hogy jó lesz még egy controller a háznál.

Szóval az első probléma, ha controllert akarunk venni, hogy melyiket. Szerencsére ezen a részlegen már nem voltak olyan kreatívok a marketingesek, mint a gép név választásnál, így csak számokat kaptak a controllerek nevek helyett, amik növekednek, de… Na lépjünk is tovább, a lényeg, hogy a legújabb controller a 1914-es.

A webshop-ok kínálatában a beszédes Microsoft Xbox Wireless Controller néven fogjuk megtalálni a legtöbb helyen, akárcsak az összes többit… Természetesen a számot nem szokták odaírni.

Viszont ha ezt vesszük, akkor az IOS támogatásra még várni kell, mert az még csak “coming in the future”. Szóval vagy a legújabb controller IOS támogatás nélkül, vagy az egyel régebbi a 1708-as. A típusokat leginkább csak kép alapján lehet megkülönböztetni egymástól, a Microsoft is különböző körülírásokkal hivatkozik az egyes controller generálciókra (a vezérlő, amin van share gomb, vagy a verzérlő aminek a felső része egybe van a gobokkal, stb), ami valahol azért elég vicces…

Ha már választunk controllert, akkor arra is érdemes figyelni, hogy az adott típusból is több van, nagyjából egy árban. A csak vezérlő (xbox-hoz), vagy a pc-hez csomagolt kábellel, és a wireless dongle-s. Itt fontos látni, hogy a controller ugyanaz, de usb-usb-c kábelt pár ezer forintból be lehet szerezni az ebay-en, viszont Microsoft USB dongle-t nem, és az boltban bőven tízezer forint fölötti összeg. Plusz infó, hogy az usb dongle nem bluetooth dongle, egyedi protokollon keresztül kommunikál, ami hatékonyabb jelátvitelt, rövidebb latency-t, és extra feature-ket is tud, mint pl. 8 vezérő is csatlakoztatható hozzá egyidőben (Bluetooth-on keresztül max. 1).

Ha megérkezik a csoda controller, akkor jön csak az igazi nagy meglepetés. Mégpedig ez:

Bizony. A Microsoft Windows 10 nem ismeri fel, a Microsoft XBOX dongle-t. Semmi leírás, semmi driver, elviekben plug and play. Nem akartam elhinni, és ma is nehezen hiszem, hogy ezt így ebben a formában sikerült összerakni a Microsoftnak, de sikerült.

Ha valaki mégis szeretné Microsoft Windows alatt használni, a Microsoft által gyártott eszközét, akkor az alábbit kell tenni:

  1. Elolvasni a Microsoft FAQ-t, ahol azt állítják, hogy minden plug and play, szóval, arrafelé sötétség van a fejekben.
  2. Különféle forum bejegyzéseket keresni, amiből elég sok lesz (nem meglepő módon), és megtalálni azt, ami a mi vezérlőnkről szól, és működik.
  3. Vagy egyszerűen csak tovább olvasni ezt a szuper leírást 🙂

Első körben meg kell néznünk, milyen típusú vezérlőnk van. Ezt a Device Managerben az alábbi képernyőn viszonylag egyszerűen megtehetjük:

Ezek után kell túrni egy hozzá megfelelő drivert a windows update catalog-ban:

http://www.catalog.update.microsoft.com/Search.aspx?q=USB%5CVID_045E%26PID_02FE

2 találat lesz, a nagyobb méretű kell:

Az eredmény egy cab file lesz, amit az explorer megnyit és pár fájl lesz benne:

Ezt másoljuk ki egy könyvtárba, és a Device Managerben mondjunk egy Update Driver-t.

Ne is próbálkozzunk drivereket találni, használjuk a sajátunkat.

Adjuk meg a könyvtárat ahova a fájlokat tettük a cab-ból, és láss csodát:

A jelenség nem egyedi, 3 teljesen külön win10-en is kipróbáltam, amiből kettő már átesett a 20H2 update-n is. Pedig maga a hardware job mint a Nintendo Pro controller (a dpad biztos), a funkciói is jobbak, hogy pont a telepítését sikerült így elszúrni, arra nem számítottam…

Ha ezzel megvagyunk, akkor még nincs vége a megpróbáltatásainknak. A vezérlőt a windows update nem frissíti, ahhoz egy külön programot kell letöltenünk, amit a Microsoft Store-ba találunk meg. A neve:

Miután ezt letöltöttük, és elindítottuk el is indul a firmware frissítés, amennyiben szükséges.

Securing apache

Ha esélyt szeretnénk adni Apache szerverünknek az életre, érdemes az alap beállításokon módosítani pár dolgot.

A legfontosabb szabály, a szerverünk mindig legyen naprakész (apt update, apt upgrade, esetleg a paranoiásaknak chkrootkit)

Aztán érdemes meggyőzni az Apache-ot, hogy ne mondja el mindenkinek a verziószámát, így talán nehezebb lesz expolit-ot keresni benne:

ServerSignature Off
ServerTokens Prod

A második a mod_security. Ezt sajnos kicsit macerásabb beállítani, de megéri. Ehhez az alábbi lépésekre van szükség:

apt-get install libapache2-mod-security2
cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

Ezután érdemes bekapcsolni a security használatát az újonnan létrehozott (modsecurity.conf) konfig fájlban (alapból csak detektálásra van állítva)

SecRuleEngine On

Ha ez megvan, már nincs másra szükségünk, csak friss biztonsági szabályokra (persze csak egy gyors backup után).

mv /usr/share/modsecurity-crs /usr/share/modsecurity-crs.bak
git clone https://github.com/coreruleset/coreruleset.git /usr/share/modsecurity-crs

Majd ezt lehet frissítgetni időnként az alábbi paranccsal:

cd /usr/share/modsecurity-crs
git pull

Ezután még példányosítani kell a configot:

cp /usr/share/modsecurity-crs/crs-setup.conf.example /usr/share/modsecurity-crs/crs-setup.conf

Ha ez megvan, és a szerveren futtatunk valamilyen speciális dolgot (Pl. WordPress) akkor érdemes azt kivételként megadni. Az új configunkban (crs-setup.conf) az alábbi sorokat kell kicommentelni, és a megfelelő rendszerhez 1-est írni:

 SecAction \
  "id:900130,\
   phase:1,\
   nolog,\
   pass,\
   t:none,\
   setvar:tx.crs_exclusions_cpanel=0,\
   setvar:tx.crs_exclusions_dokuwiki=0,\
   setvar:tx.crs_exclusions_drupal=0,\
   setvar:tx.crs_exclusions_nextcloud=0,\
   setvar:tx.crs_exclusions_phpbb=0,\
   setvar:tx.crs_exclusions_wordpress=1,\
   setvar:tx.crs_exclusions_xenforo=0"

És már meg is tettük az első lépéseket egy biztonságosabb Apache szerver felé.

Sose feledjétek: biztonságos rendszer nincs, max. biztonságosabb…

JDK on Ubuntu

A Java telepítés nem egy nagy varázslat. Rendszerint arról szól, hogy kitömörítjük valahova a fájlokat, és elérjük, hogy amikor beírjuk hogy java, akkor az általunk kitömörített cucc induljon el.

Ez windows alatt egy download, total commander, és a PATH környezeti változó módosításával elérhető.

Ubuntu alatt főként csak terminált használok, szóval beírtam a google-be, hogy jdk install ubuntu, és vadabbnál vadabb dolgokat láttam, és nagyjából semmi se működött. Szóval ha valaki jdk-t szeretne telepíteni ubuntura, akkor az alábbit kell tenni:

Ellátogatni az OpenJdk oldalára, és kimásolni a nekünk tetsző JDK csomag URL-jét

Letölteni a kívánt csomagot:

wget https://download.java.net/java/GA/jdk15.0.1/51f4f36ad4ef43e39d0dfdbaf6549e32/9/GPL/openjdk-15.0.1_linux-x64_bin.tar.gz

Ki kell tömöríteni a cuccot amit letöltöttünk:

sudo tar -xvf openjdk-15.0.1_linux-x64_bin.tar.gz -C /usr/lib/jvm/

Fel kell venni az újonnan létrehozott JDK-a az alternatives közé:

sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk-15.0.1/bin/java 1151

Utána pedig beállíthatjuk a használni kívánt java verziót az alábbi paranccsal:

sudo update-alternatives --config java

Adobe Creative Cloud – ERROR 184

Valamiért az Adobe CC egyik gépemen sem akar frissülni, mert mindig a 184-es hibát mond.

Process monitorral pillanatok alatt kideríthető a hiba oka: az adobe szakértők beregisztrálták az alábbi helyen lévő fájlt mint interop service:

“c:\Program Files (x86)\Common Files\Adobe\CoreSyncExtension\CoreSync_x64.dll”

Amit az explorer ezek után – nem meglepő módon – használ. A telepítő meg megpróbálja felülírni, ami – ugyancsak nem meglepő módon – nem sikerül neki.

A fájlt törölni nem lehet, mert használatban van, és ennyire nem linux a windows.

Szóval vagy az explorert be kell zárni a frissítés előtt – ami lássuk be kevéssé felhasználóbarát- vagy át kell nevezni a könyvtárat (mert ennyire már linux a windows is) és akkor a telepítő létrehozza az új fájlt, frissíti a komponens regisztrációt, és restart után már törölhető is a régi…

Netflix magyar content

A netflix már egy ideje hivatalosan is elérhető Magyarországon. Aztán lokalizálták a honlapot is magyarra, és az utóbbi időben elszaporodtak a magyar feliratok, és ami meglepett a magyar szinkronos filmek is. Bár ezekre az embedded app-okon belül nem nagyon lehet keresni, és a webes felületen se triviális, az alábbi linket megnyitva szépen le lehet szűrni a magyar nyelvű contentet:

https://www.netflix.com/browse/audio

Spotify számcímek a lejátszási listákból

Ha valaki ki szeretné másolni a spotify playlist-ből az előadók és számok címeit, akkor az alábbi javascript kóddal érdemes próbálkozni:

var tracks = document.getElementsByClassName("track-name-wrapper");
for(var i = 0; i < tracks.length; i++)
{
   var trackTitle = tracks[i].getElementsByClassName("tracklist-name")[0].innerHTML;
   var trackArtist = tracks[i].getElementsByClassName("tracklist-row__artist-name-link")[0].innerHTML;
   console.log(trackArtist + " - " + trackTitle);
}