<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-1859167416855250911</atom:id><lastBuildDate>Fri, 03 Apr 2026 11:52:51 +0000</lastBuildDate><category>HowTo</category><category>Source code</category><category>Java</category><category>JUnit</category><category>Linux</category><category>Oracle</category><category>Windows</category><category>Microsoft</category><category>SQL</category><category>Web</category><category>Publications</category><category>Ubuntu</category><category>TIBCO</category><category>PL/SQL</category><category>Music</category><category>Spring</category><category>Spotfire</category><category>Debian</category><category>LUbuntu</category><category>Apache</category><category>XUbuntu</category><category>CentOS</category><category>Fedora</category><category>Games</category><category>Python</category><category>Maven</category><category>Spring Boot</category><category>docker</category><category>JavaScript</category><category>OSGi</category><category>PHP</category><category>Android</category><category>Cplusplus</category><category>Eclipse</category><category>GRUB</category><category>Google</category><category>Xfce</category><category>bash</category><category>APT</category><category>Cryptography</category><category>Excel</category><category>GNOME</category><category>IronPython</category><category>LXDE</category><category>Suse</category><category>BusinessWorks</category><category>VmWare</category><category>Yum</category><category>testcontainers</category><category>Apache Kafka</category><category>Apple</category><category>C#</category><category>Google Chrome</category><category>Google Sheets</category><category>Matlab</category><category>MySQL</category><category>Tomcat</category><category>Unity</category><category>VirtualBox</category><category>iPhone</category><category>xorg</category><category>ActiveSpaces</category><category>Avaloq</category><category>BusinessEvents</category><category>FileZilla</category><category>HTML</category><category>Hibernate</category><category>Kodi</category><category>MATE</category><category>PostgreSQL</category><category>SSL</category><category>Vim</category><category>WSL</category><category>XML</category><category>git</category><category>sed</category><category>ACPI</category><category>ALSA</category><category>AMD</category><category>Access</category><category>Apache Avro</category><category>ApacheDS</category><category>Bing</category><category>Bitbucket</category><category>CORS</category><category>CSRF</category><category>CUDA</category><category>DOS</category><category>EMS</category><category>Edge</category><category>Enchant</category><category>FPGA</category><category>Fortify</category><category>GIS</category><category>Ghostscript</category><category>GitHub</category><category>GitLab</category><category>Gradle</category><category>HANA</category><category>JMS</category><category>JPA</category><category>JaCoCo</category><category>Kerberos</category><category>LDAP</category><category>Lenovo</category><category>Liferay</category><category>LightDM</category><category>MPlayer</category><category>MozillaFirefox</category><category>MyTracks</category><category>NLTK</category><category>OSIsoft</category><category>OpenSSH</category><category>PDF</category><category>PRAW</category><category>PulseAudio</category><category>Quartz</category><category>RPM</category><category>Reddit</category><category>Remmina</category><category>SAP</category><category>SFTP</category><category>SQLite</category><category>Security</category><category>TOAD</category><category>Tampermonkey</category><category>Tesla</category><category>Thymeleaf</category><category>Tweepy</category><category>Twitter</category><category>TypeScript</category><category>UEFI</category><category>VLC</category><category>Verilog</category><category>Visual Basic</category><category>WineHQ</category><category>Wireshark</category><category>X-Frame-Options</category><category>XSD</category><category>cURL</category><category>checkstyle</category><category>ciso8601</category><category>pyenchant</category><category>xterm</category><title>Scumm Bar</title><description>Spreading happiness since 1987</description><link>http://groglogs.blogspot.com/</link><managingEditor>noreply@blogger.com (omgrog)</managingEditor><generator>Blogger</generator><openSearch:totalResults>610</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-4187017221875837460</guid><pubDate>Fri, 23 Jan 2026 12:20:00 +0000</pubDate><atom:updated>2026-01-23T13:20:14.888+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><title>[Source code] Determine to which subsquare does a cell belong to in a sudoku grid</title><description>Given a valid sudoku grid of size NxN, we might need to determine (for example for validation purposes), in which subsquare a specific cell belongs:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;int squareIndex = (i / subsquareSize) * subsquareSize + (j / subsquareSize);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;where &lt;span style=&quot;font-family: courier;&quot;&gt;subsquareSize = Math.sqrt(N);&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2026/01/source-code-determine-to-which.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-715086332123836741</guid><pubDate>Fri, 23 Jan 2026 11:58:00 +0000</pubDate><atom:updated>2026-01-23T12:58:31.571+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Maven</category><title>[Maven] Replace backslashes in property</title><description>&lt;p&gt;Using Maven to build code on both Windows and Unix systems, you might end up with some quirky situations especially related to file path handling.&lt;/p&gt;&lt;p&gt;It is possible to generate altered Maven properties so that for example backslashes are converted to forward slashes:&lt;/p&gt;&lt;p&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;pre style=&quot;margin: 0; line-height: 125%;&quot;&gt; 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;&lt;pre style=&quot;margin: 0; line-height: 125%;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.codehaus.mojo&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;build-helper-maven-plugin&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;id&amp;gt;&lt;/span&gt;normalize-property&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;phase&amp;gt;&lt;/span&gt;initialize&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/phase&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;regex-property&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;normalized.property&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;value&amp;gt;&lt;/span&gt;${property}&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/value&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;regex&amp;gt;&lt;/span&gt;\\&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/regex&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;replacement&amp;gt;&lt;/span&gt;/&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/replacement&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #BBB&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #070&quot;&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;/p&gt;&lt;p&gt;This can be used to alter properties that are not directly controlled by the developer, such as &lt;span style=&quot;font-family: courier;&quot;&gt;${project.baseDir}&lt;/span&gt;, and then you can use the result as a property itself: &lt;span style=&quot;font-family: courier;&quot;&gt;${normalized.property}&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2026/01/maven-replace-backslashes-in-property.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-2472841869772087457</guid><pubDate>Thu, 06 Nov 2025 17:37:00 +0000</pubDate><atom:updated>2025-11-06T18:37:11.954+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>[Windows] Delete recovery partition</title><description>&lt;a href=&quot;https://support.microsoft.com/en-us/windows/disk-management-in-windows-ad88ba19-f0d3-0809-7889-830f63e94405&quot; target=&quot;_blank&quot;&gt;Windows disk manager&lt;/a&gt; lets you create, delete, modify partitions on connected drives, but does not allow deleting the recovery partition. To do that, you can use the &lt;a href=&quot;https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/diskpart&quot; target=&quot;_blank&quot;&gt;diskpart&lt;/a&gt; utility which can be run from an Administator command line. The following commands will allow you to delete the partition, replace &lt;i&gt;X&lt;/i&gt; with the desired disk and partition&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;diskpart&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;list disk&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;select disk X&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;list partition&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;select partition X&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;delete partition override&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/11/windows-delete-recovery-partition.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-4074131917229790944</guid><pubDate>Sat, 01 Nov 2025 08:20:00 +0000</pubDate><atom:updated>2025-11-01T09:20:52.022+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>[Windows 11] Disable lnk resolver</title><description>Windows has a set of features on NTFS file systems called &quot;shortcut resolver&quot; that allow the system to search for a shortcut target in the filesystem if it gets moved around after a link to it is created.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is convenient normally in case you create a shortcut to something, then move said something somewhere else as usually the shortcut would stop working and throw an error when accessed instead. However, it can lead to security issues as a new attack vector is introduced that could allow a malicious actor to hijack the target and point to something unwanted instead.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The features can be disabled on Windows 11 by enabling some &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/configuration/start/policy-settings?tabs=start&amp;amp;pivots=windows-11#dont-use-the-search-based-method-when-resolving-shell-shortcuts&quot; target=&quot;_blank&quot;&gt;group policies&lt;/a&gt; (Start-&amp;gt;Run-&amp;gt;gpedit.msc):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;i&gt;User Configuration\Administrative Templates\Start Menu and Taskbar\Do not use the search-based method when resolving shell shortcuts&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;User Configuration\Administrative Templates\Start Menu and Taskbar\Do not use the tracking-based method when resolving shell shortcuts&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;User Configuration\Administrative Templates\Windows Components\File Explorer\Do not track shell shortcuts during roaming&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Additionally the &quot;&lt;i&gt;Distributed Link Tracking Client&lt;/i&gt;&quot; service can be disabled (Start-&amp;gt;Run-&amp;gt;services.msc)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/11/windows-11-disable-lnk-resolver.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-8481938108064311042</guid><pubDate>Wed, 06 Aug 2025 07:21:00 +0000</pubDate><atom:updated>2025-08-06T09:21:28.383+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Bing</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><category domain="http://www.blogger.com/atom/ns#">Web</category><title>[Bing] Disable AI search clutter</title><description>AI is seemingly unescapable these days and annoying generated content is being shoved everywhere without consent.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To disable AI content clutter (copilot answers, video results, similar content and related searches) on &lt;a href=&quot;https://www.bing.com/&quot; target=&quot;_blank&quot;&gt;Bing&lt;/a&gt; searches you can add a small rule to &lt;a href=&quot;https://ublockorigin.com/&quot; target=&quot;_blank&quot;&gt;uBlock Origin extension&lt;/a&gt; under &quot;My Filters&quot; section:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;www.bing.com##.b_ans&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This will obviously break as soon as Microsoft pushes any update that changes the page content setup, however the workaround will be the same and will simply require finding out which element(s) to block.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;uBlock Origin also has a very handy &lt;a href=&quot;https://github.com/gorhill/uBlock/wiki/Element-picker&quot; target=&quot;_blank&quot;&gt;element picker&lt;/a&gt; mode that allows selecting a page component to create a rule to block it. Naturally the same can be achieved also by inspecting the page with Developer Tools (F12 usually) and finding the element tag(s) to block.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/08/bing-disable-ai-search-clutter.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-6974863174890229731</guid><pubDate>Sat, 26 Jul 2025 17:30:00 +0000</pubDate><atom:updated>2025-07-26T19:30:24.281+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">AMD</category><category domain="http://www.blogger.com/atom/ns#">Lenovo</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>[Lenovo] Fix PSR screen issues with AMD graphics</title><description>Some recent Lenovo laptops come with displays theoretically supporting PSR (Panel Self Refresh) techology which supposedly would improve battery life.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On systems with AMD graphics, both the proprietary drivers and the ones packaged by Lenovo incorrectly implement support for it, leading to issues such as screen flickering, screen tearing and video stuttering.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The workaround is to force disable PSR in Windows registry, by opening regedit and looking for this entry:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0000&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;then modifying or creating a key DWORD 32 bit named&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;DalPSRFeatureEnable&lt;/span&gt; with value 0&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Afterwards simply reboot the system.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Even though in theory disabling PSR could lead to worse battery life and higher GPU temperatures, I have not seen noticeable differences after a month of use, naturally it might vary for others, therefore monitor your system to detect issues in case.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To reenable it, simply change the value to 1&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/07/lenovo-fix-psr-screen-issues-with-amd.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-6865901008728574876</guid><pubDate>Thu, 24 Apr 2025 14:38:00 +0000</pubDate><atom:updated>2025-04-24T16:38:30.434+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>[Windows 11] Uninstall widgets app</title><description>If you do not need the widgets functionality on your Windows machine, you can disable it from settings or completely remove it with:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;winget uninstall &quot;windows web experience pack&quot;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/04/windows-11-uninstall-widgets-app.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-4634021215355330237</guid><pubDate>Thu, 24 Apr 2025 07:51:00 +0000</pubDate><atom:updated>2025-04-24T09:51:48.998+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>[Windows] Hash a file</title><description>Windows offers a builtin tool to compute the hash of a file (example MD5):&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;CertUtil -hashfile FILENAME MD5&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To view the list of supported options and hash algorithms:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;CertUtil -hashfile -?&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/04/windows-hash-file.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-9078803816566979369</guid><pubDate>Wed, 23 Apr 2025 09:44:00 +0000</pubDate><atom:updated>2025-04-23T11:44:05.958+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>[Windows 11] Disable telemetry and diagnostic data</title><description>&lt;p&gt;Windows 11 collects some data and allows some configuration under Settings &amp;gt; Privacy &amp;amp; Security &amp;gt; Diagnostics &amp;amp; Feedback however you are not allowed to completely disable it. If you wanted to do so, you could apply a policy using the Local Group Policy Editor app (gpedit).&lt;/p&gt;&lt;p&gt;Find the Local Computer Policy &amp;gt; Administrative Templates &amp;gt; Windows Components &amp;gt; Data Collection and Preview Builds &amp;gt; Allow Diagnostic Data&lt;/p&gt;&lt;p&gt;Click to modify it, enable it and set it to &quot;Diagnostic data off&quot;&lt;/p&gt;&lt;p&gt;You can then logout and login again or run from a terminal the command to force reload policies:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;gpupdate /force&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/04/windows-11-disable-telemetry-and.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-5270004595904892082</guid><pubDate>Wed, 23 Apr 2025 09:36:00 +0000</pubDate><atom:updated>2025-04-23T11:36:25.206+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>[Windows 11] Remove PhoneLink app</title><description>&lt;p&gt;Removing the&amp;nbsp;&lt;a href=&quot;https://www.microsoft.com/en-us/windows/sync-across-your-devices&quot; target=&quot;_blank&quot;&gt;PhoneLink&lt;/a&gt;&amp;nbsp;app on Windows, is as easy as running (from administrator shell):&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Get-AppxPackage Microsoft.YourPhone -AllUsers | Remove-AppxPackage&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/04/windows-11-remove-phonelink-app.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-3641376707646303717</guid><pubDate>Wed, 12 Mar 2025 15:55:00 +0000</pubDate><atom:updated>2025-03-12T16:55:43.685+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Microsoft</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>[Windows 11] Initial setup without forced login</title><description>When setting up Windows 11 from a new installation, you will be guided through a graphical setup at boot.&amp;nbsp;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since every other company decided to force onto users annoying choices without much backlash, also Microsoft though to participate in the fun now by forcing you to login to your Microsoft account (or create a new one) during this process.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To avoid this for the moment, you can run a couple commands during the setup. After choosing the language for the setup process, press SHIFT+F10 to open a command prompt, then enter:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;OOBE\BYPASSNRO&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;which will make the PC reboot. Once you are back into the setup process, choose the language again (if prompted) and press again SHIFT+F10 to get back into the command prompt, this time enter:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;ipconfig /release&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;to disconnect from any network you might be connected to.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finally moving forward in the process, when you reach the &quot;connect to the internet&quot; stage, you will have the option to click on a small link saying &quot;&lt;i&gt;I don&#39;t have internet&lt;/i&gt;&quot;, you will then be prompted to create a local account on your PC.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/03/windows-11-initial-setup-without-forced.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-9040530330015427326</guid><pubDate>Sun, 12 Jan 2025 16:21:00 +0000</pubDate><atom:updated>2025-02-06T17:02:55.045+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Android</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Publications</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><title>[Android] Sprescia app for run activity tracking</title><description>&lt;p&gt;No it is not Christmas today, but here is another free, no ads, no trackers, no data collection, minimalistic app to track your run activity!&lt;/p&gt;&lt;p&gt;Built for Android 14+ using help from ChatGPT and icons from SVG Repo this app writes to a local Rooom DB in 1 table: &lt;i&gt;run&lt;/i&gt;&lt;/p&gt;&lt;p&gt;Run view allows you to add, edit, delete run details and calculates average speed for each entry, comparing it with the previous one, giving you a quick view of your training progression. You can also export and import data to/from csv for quick backup and restore logic.&lt;/p&gt;&lt;p&gt;Daily stats view allows you to see daily run data and compare it to previous runs using key metrics: steps, average speed, distance, time.&lt;/p&gt;&lt;p&gt;Monthly stats view provides the same capability but averages the data grouping per month instead.&lt;/p&gt;&lt;p&gt;You can find the &lt;a href=&quot;https://github.com/steghio/sprescia&quot; target=&quot;_blank&quot;&gt;Sprescia&lt;/a&gt; project on my GitHub&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/01/android-sprescia-app-for-run-activity.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-3021579797244722359</guid><pubDate>Sun, 12 Jan 2025 13:11:00 +0000</pubDate><atom:updated>2025-02-06T17:02:44.966+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Android</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Publications</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><title>[Android] MaiCar app for car expense management (refuels and maintenance)</title><description>Finally a free, no ads, no trackers, no data collection, minimalistic app to track your car expenses!&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Built for Android 14+ using help from &lt;a href=&quot;https://chatgpt.com/&quot; target=&quot;_blank&quot;&gt;ChatGPT&lt;/a&gt; and icons from &lt;a href=&quot;https://www.svgrepo.com/&quot; target=&quot;_blank&quot;&gt;SVG Repo&lt;/a&gt; this app writes to a local Rooom DB in 2 tables: &lt;i&gt;fuel&lt;/i&gt; and &lt;i&gt;maintenance&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Fuel view &lt;/b&gt;allows you to add, edit, delete refuel details (partial and full tank) and calculates efficiency for each entry, comparing it with the previous one, giving you a quick view of your trip efficiency progression.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Maintenance view&lt;/b&gt; allows you to add, edit, delete maintenance details for multiple maintenance types, it also allows you to filter the view on a specific maintenance type to quickly find a specific item.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Both views allow you to &lt;b&gt;export and import&lt;/b&gt; data to/from &lt;b&gt;csv &lt;/b&gt;for quick backup and restore logic.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can find the &lt;a href=&quot;https://github.com/steghio/maicar&quot; target=&quot;_blank&quot;&gt;MaiCar&lt;/a&gt; project on my GitHub&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2025/01/android-maicar-app-for-car-expense.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-900027443188266924</guid><pubDate>Sun, 15 Dec 2024 09:38:00 +0000</pubDate><atom:updated>2024-12-15T10:38:26.170+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Android</category><category domain="http://www.blogger.com/atom/ns#">HowTo</category><title>[Android] Recompile and sign APK</title><description>Each new Android version introduces changes that usually require app developers to put some effort into keeping their app compatible with the latest OS releases. As a result, sometimes, your favorite free apps have issues if the developer does not update it.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Depending on the required changes, the effort varies, however you can often adapt the app yourself by simply decompiling it, updating whatever needs to be updated, and repackage it with a new Android version as target. Here are the simple steps to achieve this.&lt;/div&gt;&lt;span&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Install the required tools&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You have a couple choices, either installing the full &lt;a href=&quot;https://developer.android.com/studio&quot; target=&quot;_blank&quot;&gt;Android studio&lt;/a&gt; IDE or just installing the command line tools you need. We will take a look at the command line tools here.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, download and extract&amp;nbsp;&lt;a href=&quot;https://developer.android.com/tools/sdkmanager&quot; target=&quot;_blank&quot;&gt;sdkmanager&lt;/a&gt;&amp;nbsp;wherever you like.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then, we need to install at least &lt;a href=&quot;https://developer.android.com/tools/releases/build-tools&quot; target=&quot;_blank&quot;&gt;build-tools&lt;/a&gt; and &lt;a href=&quot;https://developer.android.com/tools/releases/platform-tools&quot; target=&quot;_blank&quot;&gt;platform-tools&lt;/a&gt;, you can verify the available versions with:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;sdkmanager --list --channel=0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;choose the version you want and install it with:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;sdkmanager &quot;platform-tools&quot; &quot;build-tools;VERSION&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You will also need a JDK or JRE to have access to &lt;a href=&quot;https://docs.oracle.com/en/java/javase/11/tools/keytool.html&quot; target=&quot;_blank&quot;&gt;keytool&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Obtain the APK&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You will need to obtain the APK of the app you want to modify, there are many ways to achieve this, Google is your friend&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Decompile the APK&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We need to unpack and extract all the files from the APK in order to be able to modify it:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;apktool d YOUR_APK.apk -o FOLDER_WHERE_TO_UNPACK&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Make the required changes&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Inside &lt;i&gt;FOLDER_WHERE_TO_UNPACK&lt;/i&gt; you will have the content of the APK, usually it is enough to modify the &lt;i&gt;apktool.yml&lt;/i&gt; file and bump the &lt;i&gt;targetSdkVersion&lt;/i&gt; (you can find &lt;a href=&quot;https://developer.android.com/tools/releases/platforms&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; the API level for each Android version, you will need to set the API version number there, NOT the Android release)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another place you might need to touch is the &lt;i&gt;AndroidManifest.xml&lt;/i&gt; where services and permissions are configured&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Repackage the app&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;apktool B FOLDER_WHERE_TO_UNPACK&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Will generate inside &lt;i&gt;FOLDER_WHERE_TO_UNPACK&lt;/i&gt; a new folder &lt;i&gt;dist&lt;/i&gt;, where the compiled APK will be placed&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Optimize the app build&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can read more about &lt;a href=&quot;https://developer.android.com/tools/zipalign&quot; target=&quot;_blank&quot;&gt;zipalign&lt;/a&gt; here, long story short, let it optimize your build:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;zipalign -v 4 RECOMPILED_APK.apk ALIGNED_APK.apk&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;(Optional) Generate a signing key&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All app packages need to be signed (even self-signed), you can skip this step if you already have a valid keystore.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can use keytool from Java to achieve this, we have covered it already in a &lt;a href=&quot;https://groglogs.blogspot.com/2018/08/java-useful-keytool-commands.html&quot; target=&quot;_blank&quot;&gt;past blog post&lt;/a&gt;, you can reference that, check the &quot;generate a new key and place it in a keystore&quot; step.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Sign the APK&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We will use &lt;a href=&quot;https://developer.android.com/tools/apksigner&quot; target=&quot;_blank&quot;&gt;apksigner&lt;/a&gt; tool for this step:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;apksigner&amp;nbsp; sign --ks YOUR_KEYSTORE --v1-signing-enabled true --v2-signing-enabled true ALIGNED_APK.apk&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finally you can install the APK on your phone, you can either copy it somwhere on the phone, then open it and install from there (you might need to confirm you want to proceed after all safety warnings), or you can install from command line after connecting the phone to a computer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;(Optional) Install APK from command line&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You need to enable &lt;a href=&quot;https://developer.android.com/studio/debug/dev-options&quot; target=&quot;_blank&quot;&gt;developer options&lt;/a&gt; on your phone (the guide is a bit off). In general, find the phone info section in your settings and tap on the build number until you get the notification you are a developer. Then find the developer options menu and enable USB debugging.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When you connect the phone via USB, you should get a notification on the phone to trust the connected computer, allow it, and finall using &lt;a href=&quot;https://developer.android.com/tools/adb&quot; target=&quot;_blank&quot;&gt;adb&lt;/a&gt; tool you can install the app:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;adb install ALIGNED_APK.apk&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hopefully that is enough to give new life to your favourite app, if not, you still learned something or can use this as a basis for further changes to keep what you like running for longer.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/12/android-recompile-and-sign-apk.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-923878081073650080</guid><pubDate>Fri, 08 Nov 2024 20:07:00 +0000</pubDate><atom:updated>2024-11-08T21:08:55.214+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Google</category><category domain="http://www.blogger.com/atom/ns#">Google Sheets</category><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">JavaScript</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><title>[Google Sheets] Import data from Investing.com</title><description>&lt;p&gt;&lt;b&gt;DISCLAIMER: This is not a stock picking recommendation, the tickers shown are used as example and not provided as financial or investment advice.&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;DISCLAIMER2: Web scraping can go against usage policies so read them, understand them and abide by them. Also web scraping is notoriously flaky as small changes in the retrieved page can affect the location of the desired element(s).&lt;/b&gt;&lt;/p&gt;&lt;p&gt;We have already seen how to import data from &lt;a href=&quot;https://groglogs.blogspot.com/2023/12/google-sheets-import-data-from-yahoo.html&quot; target=&quot;_blank&quot;&gt;Yahoo Finance&lt;/a&gt; and &lt;a href=&quot;https://groglogs.blogspot.com/2024/10/google-sheets-import-crypto-data-from.html&quot; target=&quot;_blank&quot;&gt;Coingecko&lt;/a&gt;, now we try to add &lt;a href=&quot;https://www.investing.com/&quot;&gt;Investing.com&lt;/a&gt; as source which unfortunately does not provide API, so we have to do some HTML scraping instead.&lt;/p&gt;&lt;p&gt;We would like to retrieve the current price of an ETF called &lt;a href=&quot;https://www.investing.com/etfs/jpna&quot; target=&quot;_blank&quot;&gt;JPNA&lt;/a&gt;. By looking at that page we can luckily identify a specific locator, which then allows us to do a couple string manipulation operations before getting the desired value:&lt;/p&gt;&lt;p&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;pre style=&quot;margin: 0; line-height: 125%&quot;&gt;&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;function&lt;/span&gt; getInvestingData(path) {
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;var&lt;/span&gt; result &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; UrlFetchApp.fetch(&lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;https://www.investing.com/etfs/&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;+&lt;/span&gt; path.toLowerCase());
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;var&lt;/span&gt; response &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; result.getContentText();
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;var&lt;/span&gt; start &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; response.indexOf(&lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;#39; data-test=&amp;quot;instrument-price-last&amp;quot;&amp;gt;&amp;#39;&lt;/span&gt;) &lt;span style=&quot;color: #333333&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #0000DD; font-weight: bold&quot;&gt;35&lt;/span&gt;;
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;var&lt;/span&gt; end &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; response.indexOf(&lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;#39;&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;, start)
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;var&lt;/span&gt; out &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; response.substring(start, end);
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;var&lt;/span&gt; strip &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; out.replace(&lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;,&amp;quot;&lt;/span&gt;, &lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;);
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #007020&quot;&gt;Number&lt;/span&gt;(strip);
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/11/google-sheets-import-data-from.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-677034286568346278</guid><pubDate>Sat, 19 Oct 2024 07:05:00 +0000</pubDate><atom:updated>2024-10-19T09:05:19.172+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Google</category><category domain="http://www.blogger.com/atom/ns#">Google Sheets</category><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">JavaScript</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><title>[Google Sheets] Import crypto data from Coingecko</title><description>&lt;div&gt;&lt;b&gt;DISCLAIMER: I do not recommend investing in crypto, all tokens you will see are used as sample and not provided as financial or investment advice.&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;We&#39;ve already seen how to &lt;a href=&quot;https://groglogs.blogspot.com/2023/12/google-sheets-import-data-from-yahoo.html&quot; target=&quot;_blank&quot;&gt;add custom functions to our Google Sheets projects&lt;/a&gt;, importing Yahoo Finance data. Now we expand this to import cryptocurrency data from &lt;a href=&quot;https://www.coingecko.com/&quot; target=&quot;_blank&quot;&gt;Coingecko&lt;/a&gt;.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I could have picked any of the million sources, but this one has a simple free plan which for light usage works well.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After registering and getting your API key, &lt;a href=&quot;https://docs.coingecko.com/v3.0.1/reference/endpoint-overview&quot; target=&quot;_blank&quot;&gt;RTFM&lt;/a&gt; to find that they provide a lot of stuff, what we care about is the pricing data in this example, you will need to find the ID of the currency you want (NOT the token) by querying the &lt;a href=&quot;https://docs.coingecko.com/v3.0.1/reference/coins-list&quot; target=&quot;_blank&quot;&gt;list&lt;/a&gt; and then you can get the data you want by calling (add your API key at the end):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;pre style=&quot;margin: 0; line-height: 125%&quot;&gt;&lt;span style=&quot;color: #FF0000; background-color: #FFAAAA&quot;&gt;&amp;quot;https://api.coingecko.com/api/v3/simple/price?ids=&amp;quot; + token + &amp;quot;&amp;amp;vs_currencies=usd&amp;amp;x_cg_demo_api_key=&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can put this in a Google Sheet function as well (you can extend input parameters to get quote in different currencies as well):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;pre style=&quot;margin: 0; line-height: 125%&quot;&gt;&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;function&lt;/span&gt; getCoingeckoData(path) {
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;var&lt;/span&gt; result &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; UrlFetchApp.fetch(&lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;https://api.coingecko.com/api/v3/simple/price?ids=&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;+&lt;/span&gt; path &lt;span style=&quot;color: #333333&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;&amp;amp;vs_currencies=usd&amp;amp;x_cg_demo_api_key=YOUR_API_KEY&amp;quot;&lt;/span&gt;);
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;var&lt;/span&gt; response &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; result.getContentText();
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;var&lt;/span&gt; json &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; JSON.parse(response);
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;return&lt;/span&gt; json[path][&lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;#39;usd&amp;#39;&lt;/span&gt;];
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/10/google-sheets-import-crypto-data-from.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-7167742657343205837</guid><pubDate>Fri, 04 Oct 2024 07:23:00 +0000</pubDate><atom:updated>2024-10-04T09:25:15.565+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><title>[Java] Get type of elements in collection using reflection</title><description>&lt;a href=&quot;https://docs.oracle.com/javase/tutorial/java/generics/erasure.html&quot; target=&quot;_blank&quot;&gt;Java type erasure&lt;/a&gt; logic means that at runtime some information is removed/replaced from generic declarations, which poses a minor challenge when trying to identify the actual parameter types using reflection at runtime.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is a way:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;pre style=&quot;margin: 0; line-height: 125%&quot;&gt;&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0e84b5; font-weight: bold&quot;&gt;java.lang.reflect.Field&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0e84b5; font-weight: bold&quot;&gt;java.lang.reflect.ParameterizedType&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;;&lt;/span&gt;


&lt;span style=&quot;color: #888888&quot;&gt;//maybe you are looping over fields or have a field of type Field f&lt;/span&gt;
ParameterizedType collectionType &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;ParameterizedType&lt;span style=&quot;color: #333333&quot;&gt;)&lt;/span&gt; f&lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;getGenericType&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;();&lt;/span&gt;
Class&lt;span style=&quot;color: #333333&quot;&gt;&amp;lt;?&amp;gt;&lt;/span&gt; actualClassOfElementInCollection &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;Class&lt;span style=&quot;color: #333333&quot;&gt;&amp;lt;?&amp;gt;)&lt;/span&gt; collectionType&lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;getActualTypeArguments&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;()[&lt;/span&gt;&lt;span style=&quot;color: #0000DD; font-weight: bold&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;];&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/10/java-get-type-of-elements-in-collection.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-7926401316625095402</guid><pubDate>Fri, 27 Sep 2024 09:57:00 +0000</pubDate><atom:updated>2024-09-29T10:46:32.946+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Hibernate</category><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">JPA</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><title>[Java] Load entity with lazy children collections</title><description>&lt;p&gt;When using JPA and lazy collection loading, at the time the parent entity is retrieved from DB, the lazy children are NOT also loaded in memory, instead, a proxy reference is added, which is used to retrieve the data if that particular field is ever accessed.&lt;/p&gt;&lt;p&gt;In some scenarios you might want to load the whole entity, including the lazy children in memory instead (eg you want to clone/serialize it, whatever).&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;If you want to load ONE child together with the parent, a &lt;a href=&quot;https://docs.oracle.com/cd/E11035_01/kodo41/full/html/ejb3_langref.html#:~:text=A%20FETCH%20JOIN%20enables%20the%20fetching%20of%20an%20association%20as&quot; target=&quot;_blank&quot;&gt;JOIN FETCH&lt;/a&gt;&amp;nbsp;clause would do the trick:&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;SELECT p&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;FROM Parent p&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;LEFT JOIN FETCH p.childField c&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;WHERE p.id = :id&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;But if you try to load more than one child at the same time, you will get a MultipleBagFetchException. A workaround is to call the load with JOIN FETCH for all entities you need sequentially, for example:&lt;/p&gt;&lt;p&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;pre style=&quot;margin: 0; line-height: 125%&quot;&gt;&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;private&lt;/span&gt; Parent &lt;span style=&quot;color: #0066BB; font-weight: bold&quot;&gt;loadChildViaQuery&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;ID id&lt;span style=&quot;color: #333333&quot;&gt;,&lt;/span&gt; String childClause&lt;span style=&quot;color: #333333&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;{&lt;/span&gt;
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;return&lt;/span&gt; entityManager
    &lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;createQuery&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;
      &lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;select p &amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;+&lt;/span&gt;
      &lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;from Parent p &amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;+&lt;/span&gt;
      &lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;left join fetch &amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;+&lt;/span&gt;
      childClause &lt;span style=&quot;color: #333333&quot;&gt;+&lt;/span&gt;
      &lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot; where p.id = :id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;,&lt;/span&gt;
      Parent&lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;class&lt;/span&gt;
    &lt;span style=&quot;color: #333333&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;setParameter&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;,&lt;/span&gt; id&lt;span style=&quot;color: #333333&quot;&gt;)&lt;/span&gt;
    &lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;getSingleResult&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;();&lt;/span&gt;
&lt;span style=&quot;color: #333333&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/p&gt;&lt;p&gt;Where &lt;i&gt;childClause&lt;/i&gt;&amp;nbsp;input is the join statement you need, for example:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&quot;p.childField c&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Also remember that if the parent entity is not found, the operation would throw a NoResultException, while if the child is not found, no exception is raised, the child is simply null/empty.&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/09/java-load-entity-with-lazy-children.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-6875176609969490744</guid><pubDate>Thu, 26 Sep 2024 16:34:00 +0000</pubDate><atom:updated>2024-09-27T11:27:56.096+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">JUnit</category><category domain="http://www.blogger.com/atom/ns#">Publications</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><category domain="http://www.blogger.com/atom/ns#">Spring</category><category domain="http://www.blogger.com/atom/ns#">Spring Boot</category><title>[Java] Using annotation processing (and validating it) to execute logic at runtime</title><description>&lt;p&gt;Sample project showcasing how to use annotations to perform runtime logic to log changes in object values.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Remember it is a SAMPLE&lt;/b&gt;, so obviously (lazy me) most null-safe checks and so are not included and obviously some logic is a showcase, should be replaced with a real business scenario to implement.&lt;/p&gt;&lt;p&gt;In this SAMPLE, we tag fields to be included in a diff logic to then print to output when those fields values change by comparing two instances of the same object.&lt;/p&gt;&lt;p&gt;Logic can obviously be made much more complex including collections and maps and whatnot (Java Generics are your friends there).&lt;/p&gt;&lt;p&gt;Also worth mentioning &lt;a href=&quot;https://javers.org/&quot; target=&quot;_blank&quot;&gt;JaVers&lt;/a&gt; can do most of it for you, unless you have fancy business requirements that force you to write custom code..&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Key points:&lt;/p&gt;&lt;p&gt;- How to create an &lt;a href=&quot;https://github.com/steghio/diff-annotation-processing/blob/main/annotation/src/main/java/com/blogspot/groglogs/sample/annotation/MyAnnotation.java&quot; target=&quot;_blank&quot;&gt;annotation&lt;/a&gt;&lt;/p&gt;&lt;p&gt;- How to create an &lt;a href=&quot;https://github.com/steghio/diff-annotation-processing/blob/main/annotation/src/main/java/com/blogspot/groglogs/sample/annotation/MyAnnotationProcessor.java&quot; target=&quot;_blank&quot;&gt;annotation processor&lt;/a&gt; to validate the annotation parameters at compile time&lt;/p&gt;&lt;p&gt;- How to &lt;a href=&quot;https://github.com/steghio/diff-annotation-processing/blob/main/annotation/src/main/resources/META-INF/services/javax.annotation.processing.Processor&quot; target=&quot;_blank&quot;&gt;register an annotation processor&lt;/a&gt;&lt;/p&gt;&lt;p&gt;- How to &lt;a href=&quot;https://github.com/steghio/diff-annotation-processing/blob/main/sample/pom.xml#L49&quot; target=&quot;_blank&quot;&gt;configure a multi-module Maven project to use a custom annotation processor&lt;/a&gt;&amp;nbsp;(also, in the &lt;a href=&quot;https://github.com/steghio/diff-annotation-processing/blob/main/pom.xml#L15&quot; target=&quot;_blank&quot;&gt;pom of the root project&lt;/a&gt; ensure the module containing the processor is built BEFORE everything else)&lt;/p&gt;&lt;p&gt;- How to &lt;a href=&quot;https://github.com/steghio/diff-annotation-processing/blob/main/annotation/src/test/java/com/blogspot/groglogs/sample/annotation/MyAnnotationProcessorTest.java&quot; target=&quot;_blank&quot;&gt;test an annotation processor&lt;/a&gt; by &lt;a href=&quot;https://github.com/steghio/diff-annotation-processing/blob/main/annotation/src/test/java/com/blogspot/groglogs/sample/annotation/MyAnnotationProcessorTest.java#L113&quot; target=&quot;_blank&quot;&gt;generating classes at runtime&lt;/a&gt; and &lt;a href=&quot;https://github.com/steghio/diff-annotation-processing/blob/main/annotation/src/test/java/com/blogspot/groglogs/sample/annotation/MyAnnotationProcessorTest.java#L128&quot; target=&quot;_blank&quot;&gt;trigger compilation tasks&lt;/a&gt; agains them. Includes verifying compilation warnings are properly triggered as expected.&lt;/p&gt;&lt;p&gt;- How to &lt;a href=&quot;https://github.com/steghio/diff-annotation-processing/blob/main/sample/src/main/java/com/blogspot/groglogs/sample/processor/SampleProcessor.java#L76&quot; target=&quot;_blank&quot;&gt;use reflection to get fields annotated with a given annotation&lt;/a&gt;&amp;nbsp;(and then execute whatever logic on them)&lt;/p&gt;&lt;p&gt;- How to &lt;a href=&quot;https://github.com/steghio/diff-annotation-processing/blob/main/sample/src/main/java/com/blogspot/groglogs/sample/processor/SampleProcessor.java#L98&quot; target=&quot;_blank&quot;&gt;use reflection to invoke methods&lt;/a&gt; (including static methods)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The full project is available on my &lt;a href=&quot;https://github.com/steghio?tab=repositories&quot; target=&quot;_blank&quot;&gt;GitHub&lt;/a&gt; repo with commented code:&amp;nbsp;&lt;a href=&quot;https://github.com/steghio/diff-annotation-processing&quot;&gt;https://github.com/steghio/diff-annotation-processing&lt;/a&gt;&lt;/p&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/09/java-using-annotation-processing-and.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-7488353656001166944</guid><pubDate>Thu, 05 Sep 2024 13:37:00 +0000</pubDate><atom:updated>2024-09-05T15:37:54.285+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><category domain="http://www.blogger.com/atom/ns#">XML</category><title>[Java] Serialize POJO to XML according to XSD</title><description>If you &lt;a href=&quot;https://groglogs.blogspot.com/2024/09/java-generate-pojo-from-xsd-in-maven.html&quot; target=&quot;_blank&quot;&gt;generate a class from an XSD schema&lt;/a&gt;, it will come with the necessary annotations to serialize it to an XML String.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can therefore easily convert it with:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;pre style=&quot;margin: 0; line-height: 125%&quot;&gt;&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0e84b5; font-weight: bold&quot;&gt;jakarta.xml.bind.JAXBContext&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0e84b5; font-weight: bold&quot;&gt;jakarta.xml.bind.Marshaller&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;;&lt;/span&gt;
&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #0e84b5; font-weight: bold&quot;&gt;java.io.StringWriter&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;;&lt;/span&gt;

&lt;span style=&quot;color: #888888&quot;&gt;/**&lt;/span&gt;
&lt;span style=&quot;color: #888888&quot;&gt; * Provides utility methods for serialization scenarios&lt;/span&gt;
&lt;span style=&quot;color: #888888&quot;&gt; */&lt;/span&gt;
&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #BB0066; font-weight: bold&quot;&gt;SerializationUtils&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;{&lt;/span&gt;

  &lt;span style=&quot;color: #888888&quot;&gt;/**&lt;/span&gt;
&lt;span style=&quot;color: #888888&quot;&gt;   * Serialize the given object to XML String using JAXBContext&lt;/span&gt;
&lt;span style=&quot;color: #888888&quot;&gt;   * It will set the output to be pretty printed&lt;/span&gt;
&lt;span style=&quot;color: #888888&quot;&gt;   * It relies on the object annotations to correctly place and annotate all fields&lt;/span&gt;
&lt;span style=&quot;color: #888888&quot;&gt;   * @param object&lt;/span&gt;
&lt;span style=&quot;color: #888888&quot;&gt;   * @return the string representation of this object as XML&lt;/span&gt;
&lt;span style=&quot;color: #888888&quot;&gt;   * @param &amp;lt;T&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #888888&quot;&gt;   */&lt;/span&gt;
  &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&quot;color: #333333&quot;&gt;&amp;gt;&lt;/span&gt; String serializeXml&lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;T object&lt;span style=&quot;color: #333333&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;{&lt;/span&gt;
    &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;try&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;{&lt;/span&gt;
      JAXBContext jc &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; JAXBContext&lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;newInstance&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;object&lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;getClass&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;());&lt;/span&gt;

      Marshaller marshaller &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; jc&lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;createMarshaller&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;();&lt;/span&gt;
      marshaller&lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;setProperty&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;Marshaller&lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;JAXB_FORMATTED_OUTPUT&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;);&lt;/span&gt;
      &lt;span style=&quot;color: #888888&quot;&gt;//to completely remove the xml preamble `&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;yes&amp;quot;?&amp;gt;` add this line:&lt;/span&gt;
      &lt;span style=&quot;color: #888888&quot;&gt;//marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);&lt;/span&gt;

      &lt;span style=&quot;color: #888888&quot;&gt;//marshaller cannot output to string directly&lt;/span&gt;
      StringWriter sw &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;new&lt;/span&gt; StringWriter&lt;span style=&quot;color: #333333&quot;&gt;();&lt;/span&gt;

      marshaller&lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;marshal&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;object&lt;span style=&quot;color: #333333&quot;&gt;,&lt;/span&gt; sw&lt;span style=&quot;color: #333333&quot;&gt;);&lt;/span&gt;

      &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;return&lt;/span&gt; sw&lt;span style=&quot;color: #333333&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #0000CC&quot;&gt;toString&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;();&lt;/span&gt;
    &lt;span style=&quot;color: #333333&quot;&gt;}&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;catch&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;Exception e&lt;span style=&quot;color: #333333&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #333333&quot;&gt;{&lt;/span&gt;
      &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;throw&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #0066BB; font-weight: bold&quot;&gt;RuntimeException&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;Failed to convert payload to xml. &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;,&lt;/span&gt; e&lt;span style=&quot;color: #333333&quot;&gt;);&lt;/span&gt;
    &lt;span style=&quot;color: #333333&quot;&gt;}&lt;/span&gt;
  &lt;span style=&quot;color: #333333&quot;&gt;}&lt;/span&gt;
&lt;span style=&quot;color: #333333&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/09/java-serialize-pojo-to-xml-according-to.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-3950800347018138616</guid><pubDate>Thu, 05 Sep 2024 13:33:00 +0000</pubDate><atom:updated>2024-09-05T15:39:03.600+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Maven</category><category domain="http://www.blogger.com/atom/ns#">XML</category><category domain="http://www.blogger.com/atom/ns#">XSD</category><title>[Java] Generate POJO from XSD in Maven</title><description>Assuming you have a nice correct XSD file with proper namespace references and all, then you could convert it to a POJO (or more) using &lt;a href=&quot;https://github.com/evolvedbinary/jvnet-jaxb-maven-plugin&quot; target=&quot;_blank&quot;&gt;jaxb-maven-plugin&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are multiple plugins that would achieve the same result and multiple versions of this plugin even, so searching on the web can be confusing. In year 2024, this works simply with adding a plugin in the POM:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;pre style=&quot;margin: 0; line-height: 125%&quot;&gt;&lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
  &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.jvnet.jaxb&lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;jaxb-maven-plugin&lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;4.0.8&lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
  &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
    &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
      &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;id&amp;gt;&lt;/span&gt;NAME_FOR_THIS_RUN&lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;
      &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
        &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;generate&lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
      &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
      &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
        &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;schemaDirectory&amp;gt;&lt;/span&gt;src/main/resources/FOLDER/USE_CASE&lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/schemaDirectory&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #888888&quot;&gt;&amp;lt;!-- here will be the XSD --&amp;gt;&lt;/span&gt;
      &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
    &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
  &lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #007700&quot;&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/09/java-generate-pojo-from-xsd-in-maven.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-8830820303363053912</guid><pubDate>Wed, 21 Aug 2024 07:13:00 +0000</pubDate><atom:updated>2024-08-21T09:13:43.807+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><category domain="http://www.blogger.com/atom/ns#">TypeScript</category><title>[TypeScript] Debounce function in vanilla TypeScript</title><description>&lt;div&gt;Debouncing is a technique to execute a function only once during a configured period while specific trigger conditions are true. This can be used to improve performance and user experience.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The idea is to track the last time the desired function was invoked, and update such timer on each subsequent invocation, resetting the timer to the new time. If no other call is made within the configured delay after the last time of invocation, the function will finally be triggered at the end of the period.&lt;/div&gt;&lt;span&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;div&gt;Here is a sample generic debounce function that will accept any number or arguments and has no return value, it could be easily changed to produce an output as well instead. It will return a debounced version of the function received in input, maintaining same signature.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;pre style=&quot;margin: 0; line-height: 125%&quot;&gt;&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;function&lt;/span&gt; debounce&lt;span style=&quot;color: #333333&quot;&gt;&amp;lt;&lt;/span&gt;T &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;extends&lt;/span&gt; (...args: &lt;span style=&quot;color: #333399; font-weight: bold&quot;&gt;any&lt;/span&gt;[]) &lt;span style=&quot;color: #333333&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;void&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;&amp;gt;&lt;/span&gt;(func: &lt;span style=&quot;color: #333399; font-weight: bold&quot;&gt;T&lt;/span&gt;, delay: &lt;span style=&quot;color: #333399; font-weight: bold&quot;&gt;number&lt;/span&gt;)&lt;span style=&quot;color: #333333&quot;&gt;:&lt;/span&gt; (...args: &lt;span style=&quot;color: #333399; font-weight: bold&quot;&gt;Parameters&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&quot;color: #333333&quot;&gt;&amp;gt;&lt;/span&gt;) &lt;span style=&quot;color: #333333&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;void&lt;/span&gt; {
    &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;let&lt;/span&gt; timeout: &lt;span style=&quot;color: #333399; font-weight: bold&quot;&gt;ReturnType&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;typeof&lt;/span&gt; setTimeout&lt;span style=&quot;color: #333333&quot;&gt;&amp;gt;&lt;/span&gt;;

    &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;function&lt;/span&gt;(&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;:&lt;/span&gt; ThisParameterType&lt;span style=&quot;color: #333333&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&quot;color: #333333&quot;&gt;&amp;gt;&lt;/span&gt;, ...args: &lt;span style=&quot;color: #333399; font-weight: bold&quot;&gt;Parameters&lt;/span&gt;&lt;span style=&quot;color: #333333&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&quot;color: #333333&quot;&gt;&amp;gt;&lt;/span&gt;)&lt;span style=&quot;color: #333333&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;void&lt;/span&gt; {
        &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;if&lt;/span&gt; ( timeout &lt;span style=&quot;color: #333333&quot;&gt;!==&lt;/span&gt; &lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;null&lt;/span&gt;) {
            clearTimeout(timeout);
        }

        timeout &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; setTimeout(() &lt;span style=&quot;color: #333333&quot;&gt;=&amp;gt;&lt;/span&gt; {
            func.apply(&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;this&lt;/span&gt;, args);
        }, delay);
    };
}
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;To be independent from the framework we are using, we detect the timer type (since TypeScript does not have one) returned by the setTimeout function, wherever that is implemented.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This specific implementation will delay every execution, including the first invocation. If you prefer to have the first call trigger immediately, you can modify the code in the null check.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is no way with this implementation to cancel the execution of the debounced function before it is scheduled to be invoked, should you require this, you might want to modify the provided code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We can now pass any function to the debounce function to create a debounced version of it:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;pre style=&quot;margin: 0; line-height: 125%&quot;&gt;&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;function&lt;/span&gt; foo(){
  console.log(&lt;span style=&quot;background-color: #fff0f0&quot;&gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;);
}

&lt;span style=&quot;color: #008800; font-weight: bold&quot;&gt;const&lt;/span&gt; debouncedFoo &lt;span style=&quot;color: #333333&quot;&gt;=&lt;/span&gt; debounce(foo, &lt;span style=&quot;color: #0000DD; font-weight: bold&quot;&gt;1000&lt;/span&gt;);

debouncedFoo();
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Executing this code sample, will trigger the function when run, but execute the function &lt;i&gt;foo&lt;/i&gt; only after the configured delay of 1 second has passed. If we link &lt;i&gt;debouncedFoo&lt;/i&gt; to a trigger event (scroll, type in a text field, press a button, etc), and we fire the trigger event multiple times within 1 second, we will see that &lt;i&gt;foo&lt;/i&gt; will only be executed after 1 second from the last trigger time, as expected.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/08/typescript-debounce-function-in-vanilla.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-7379869824401161043</guid><pubDate>Mon, 19 Aug 2024 14:51:00 +0000</pubDate><atom:updated>2024-08-19T16:51:11.904+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">JUnit</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><title>[Java] Prim algorithm to find Minimum Spanning Tree in a graph</title><description>The minimum spanning tree (MST) is a subset of all edges in a weighted, undirected, connected graph such that the resulting graph is still connected and the sum of all edge weights is minimal.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If we are not given a list of edges, but only a list of vertices and a formula to calculate the edge weight given two graph nodes, we can run a preprocessing step to generate ALL possible edges between ALL graph nodes and calculate their weight in O(V^2).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then, starting from a random node, we greedily choose one reachable vertex which has minimal distance from the current node. We continue exploring until all graph nodes have been touched.&lt;/div&gt;&lt;div&gt;There might be multiple valid MSTs for a given graph, this algorithm will return one of them.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We use a queue sorted by weight to determine which edge (and therefore node) to visit next, this ensures that if a node is reachable via multiple edges, we always pick the smallest weight for it. Since the graph is fully connected, we are ensured eventually we will have picked ONE edge between each node in the graph, and the sum of weight of all the chosen edges is minimal.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This runs using O(E) space since we might add all edges to the queue and O(E log(E)) time since for each edge we add to the queue we pay the O(log(E)) cost of insert and remove operation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If the graph was NOT connected, this will NOT return the MST, only the MST for the connected component where the chosen start node resides. We could adapt the algorithm to verify whether there are extra nodes not yet visited, and repeat the processing for each until we have created a MST for each connected component in the graph.&lt;/div&gt;&lt;div&gt;In case the graph is not conencted, an alternatve can also be Kruskal&#39;s algorithm.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can find my implementation of&amp;nbsp;&lt;i&gt;primMinimumSpanningTree&lt;/i&gt; on my &lt;a href=&quot;https://gist.github.com/steghio/adcdc51e4babf732451ec018f084fc05&quot; target=&quot;_blank&quot;&gt;Gist&lt;/a&gt; along with some tests in&amp;nbsp;&lt;a href=&quot;https://gist.github.com/steghio/adcdc51e4babf732451ec018f084fc05#file-primmstjtests-java&quot; target=&quot;_blank&quot;&gt;PrimMSTJTests&lt;/a&gt;.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/08/java-prim-algorithm-to-find-minimum.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-8535299487760319794</guid><pubDate>Sat, 17 Aug 2024 12:46:00 +0000</pubDate><atom:updated>2024-08-17T14:46:20.112+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">HowTo</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">JUnit</category><category domain="http://www.blogger.com/atom/ns#">Source code</category><title>[Java] Graph union find algorithm</title><description>&lt;div&gt;For an undirected graph, we can compute the disjointed sets that represent all connected nodes in the subgraph where each node resides.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For each set, we elect a representative, all nodes reachable in a set will have the same representative. The resulting view will be a tree where the representative sits at the root and all connected nodes are its children.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Example applications include: quickly verify whether 2 nodes in a graph have a path to each other (they must belong to same set) or calculating the minimum number of edges to add to a graph to make it fully connected (or the opposite).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It is based on 2 operations:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;find(Vertex x)&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;which will return for a given node, the representative of its subset. We recurse up the tree where this node resides until the representative is found. We optimize the operation for future searches by including path compression, where once a representative is found, all nodes along the same path are updated to track it. This makes it so that the find operation runs in O(inverse Ackermann(V)), which is considered O(1) but more realistically is &lt;i&gt;O(log(log(...(V)))&lt;/i&gt; or how many times we need to apply log(x) to its result starting with V until the output is less than 1. It is an extremely slowly increasing sequence.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;union(Vertex x, Vertex y)&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;which will connect the subtree where node x resides to the subtree of node y, unless they are already part of the same subtree. To improve efficiency we track in O(V) extra space the rank of each subtree (its depth) and when merging two subtrees, we connect the one with minimum depth to the other, so the overall height of the resulting tree is kept as flat as possible.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It uses O(V) extra space, to track for each node who is the representative of its subset and O(V) to track the rank of the subtree rooted at each node.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It runs in O(V Ackermann(V)) time since we run 2 find operation for each edge (pair of nodes) we unite and use the union by rank with path compression method.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can check my implementation of &lt;i&gt;unionFind&lt;/i&gt; on my &lt;a href=&quot;https://gist.github.com/steghio/adcdc51e4babf732451ec018f084fc05&quot; target=&quot;_blank&quot;&gt;Gist&lt;/a&gt; along with some tests in &lt;a href=&quot;https://gist.github.com/steghio/adcdc51e4babf732451ec018f084fc05#file-unionfindjtests-java&quot; target=&quot;_blank&quot;&gt;UnionFindJTests&lt;/a&gt;.&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/08/java-graph-union-find-algorithm.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-1859167416855250911.post-3283311527502904907</guid><pubDate>Fri, 12 Jul 2024 11:37:00 +0000</pubDate><atom:updated>2024-07-12T13:37:27.690+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">git</category><category domain="http://www.blogger.com/atom/ns#">GitLab</category><title>[git] Add git options to Gitlab pushes</title><description>Using git it is possible to specify options during push operations to perform specific actions, for example you can have a successful push autocreate the PR/MR and even set additional flags.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can do this by adding &lt;a href=&quot;https://git-scm.com/docs/git-push&quot; target=&quot;_blank&quot;&gt;push-options&lt;/a&gt;&amp;nbsp;&lt;span style=&quot;font-family: courier;&quot;&gt;-o OPTION&lt;/span&gt; directly via CLI when pushing or setting them globally in your &lt;span style=&quot;font-family: courier;&quot;&gt;.gitconfig&lt;/span&gt; file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example, when using GitLab adding the following options to gitconfig:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;!-- HTML generated using hilite.me --&gt;&lt;div style=&quot;background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;&quot;&gt;&lt;pre style=&quot;margin: 0; line-height: 125%&quot;&gt;[&lt;span style=&quot;color: #996633&quot;&gt;push&lt;/span&gt;]
    pushOption = merge_request.create
    pushOption = merge_request.target=main
    pushOption = merge_request.squash
    pushOption = merge_request.merge_when_pipeline_succeeds
    pushOption = merge_request.remove_source_branch
    pushOption = merge_request.title=&amp;quot;TODO CHANGE ME&amp;quot;
    pushOption = merge_request.draft
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;after each push you will:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;- automatically create a &lt;b&gt;draft &lt;/b&gt;MR&lt;/div&gt;&lt;div&gt;- set target branch main&lt;/div&gt;&lt;div&gt;- set title &quot;TODO CHANGE ME&quot;&lt;/div&gt;&lt;div&gt;- assign it to you (and respect any MR template you have eg for default reviewers)&amp;nbsp;&lt;/div&gt;&lt;div&gt;- set the flags to squash commits on merge&lt;/div&gt;&lt;div&gt;- set the flag to delete source branch on merge&lt;/div&gt;&lt;div&gt;- enable the automerge when all configured checks (pipeline success, required approvals, etc) pass&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This small automation will likely help you speed up your development and help you include the &lt;a href=&quot;https://linearb.io/blog/what-is-continuous-merge&quot; target=&quot;_blank&quot;&gt;CM&lt;/a&gt; concepts in your CICD pipelines&lt;/div&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;script async src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot;&gt;&lt;/script&gt;
&lt;ins class=&quot;adsbygoogle&quot;
     style=&quot;display:block&quot;
     data-ad-format=&quot;fluid&quot;
     data-ad-layout-key=&quot;-6t+ed+2i-1n-4w&quot;
     data-ad-client=&quot;ca-pub-7695515873967122&quot;
     data-ad-slot=&quot;6269936280&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;&lt;/div&gt;</description><link>http://groglogs.blogspot.com/2024/07/git-add-git-options-to-gitlab-pushes.html</link><author>noreply@blogger.com (omgrog)</author><thr:total>0</thr:total></item></channel></rss>