<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Roberto Piva</title><description>Software and more.</description><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/</link><atom:link href="https://hugorefactor--stoic-volhard-25abce.netlify.app/" rel="self" type="application/rss+xml"/><pubDate>Fri, 25 Sep 2026 20:34:10 +0000</pubDate><lastBuildDate>Fri, 25 Sep 2026 20:34:10 +0000</lastBuildDate><generator>Hugo 0.131.0</generator><item><title>API-first development with Quarkus</title><description>&lt;p>When designing an API one of the first question you need to answer is who is the user of the API and how does an API solves his problems.
Once you defined your use case though, you need to define the API itself. One way to tackle the problem is to start coding the solution and rely on a library or tool to extract the API from the realized service. This approach is conventionally called &amp;ldquo;code first&amp;rdquo;, meaning you first code the solution and then extract a formal definition of the API. Typical API definitions are OpenAPI, WSDL, or GraphQL.&lt;/p>
&lt;h2 id="api-first">API-first&lt;/h2>
&lt;p>According to &lt;a href="https://opensource.zalando.com/restful-api-guidelines/#100">Zalando&amp;rsquo;s REST API design guide&lt;/a> and &lt;a href="https://www.thoughtworks.com/radar">Thoughtworks tech radar&lt;/a>, however, the preferred way to design an API is with an &amp;ldquo;API-first&amp;rdquo; approach.
The API-first approach inverts the order of operations, meaning you first design your API directly in the formal definition, and then you code the service that serves the API (pun not intended).&lt;/p>
&lt;p>This approach makes sure that one can develop server, clients, and tests all at once, since they all starts with the same specification.&lt;/p>
&lt;p>This is what an API is: the API is the product, the documentation and the formal definition is their User Interface, the error codes and mode of interactions are the User Experience.&lt;/p>
&lt;p>But how do we do it? Let&amp;rsquo;s see what tools we have in the Java world.&lt;/p>
&lt;h2 id="api-first-quarkus-server">API-first quarkus server&lt;/h2>
&lt;p>Suppose we have already defined an API in the form of OpenAPI. For simplicity and ease of comparison, we use the classic example: the pet store. We gather the OpenAPI specification from their &lt;a href="https://github.com/OAI/OpenAPI-Specification/tree/main/examples/v3.0">OpenAPI sample catalog&lt;/a> (&lt;a href="https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json">direct link to OpenAPI spec&lt;/a>), and then we need to generate the base code for our server.
We have multiple options here:&lt;/p>
&lt;ul>
&lt;li>if we are designing a server for a fixed API we may want to generate the project skeleton once and probably edit the generated files directly&lt;/li>
&lt;li>if on the other hand we are currenty developing the API itself or we want to promptly fail the build when we change the API, we should generate only standard beans and service interfaces.&lt;/li>
&lt;/ul>
&lt;p>What we will do for this example is the latter approach, and we will use two handy tools:&lt;/p>
&lt;ul>
&lt;li>OpenAPI official Java code generator tool and maven plugin&lt;/li>
&lt;li>quarkus framework for developing fast cloud-native applications&lt;/li>
&lt;/ul>
&lt;p>Let&amp;rsquo;s start!&lt;/p>
&lt;p>First, we assume we have the quarkus cli installed (use the great &lt;a href="https://sdkman.io/">SDKMAN!&lt;/a> if you want an easy install) and we start with a&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ quarkus create app pro.robertopiva:api-first-pet-store &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> --extension&lt;span class="o">=&lt;/span>resteasy-reactive-jackson,hibernate-validator
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ &lt;span class="nb">cd&lt;/span> api-first-pet-store
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>You can then remove the sample code and tests since we will replace them with generated code.
Then we want to download the OpenAPI spec for ease of use.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ curl https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore-expanded.json -o petstore.openapi.json
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">## for a fancier version:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ curl https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore-expanded.json &lt;span class="p">|&lt;/span> jq &amp;gt; petstore.openapi.json
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And now we need a way to generate the rest interfaces and the java beans, so we configure the &lt;a href="https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator-maven-plugin">OpenAPI maven generator plugin&lt;/a>. The plugin itself is very general, and can be used in a variety of contexts. Generator classes are all listed in &lt;a href="https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages">https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages&lt;/a> and configuration variables are also listed in &lt;a href="https://openapi-generator.tech/docs/generators/java">https://openapi-generator.tech/docs/generators/java&lt;/a>.&lt;/p>
&lt;p>For our case we will use:&lt;/p>
&lt;ul>
&lt;li>jaxrs-spec generator (JavaJAXRSSpecServerCodegen) to generate only the java REST interfaces&lt;/li>
&lt;li>of course generate models (java beans)&lt;/li>
&lt;li>java 8-compatible dates&lt;/li>
&lt;li>skip generation of swagger annotations (we start from openapi spec after all)&lt;/li>
&lt;li>also skip supporting files (maven project), generated tests, generated documentation&lt;/li>
&lt;li>skip authentication-related files&lt;/li>
&lt;/ul>
&lt;p>The corresponding maven plugin XML is written below:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-xml" data-lang="xml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;plugin&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;groupId&amp;gt;&lt;/span>org.openapitools&lt;span class="nt">&amp;lt;/groupId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;artifactId&amp;gt;&lt;/span>openapi-generator-maven-plugin&lt;span class="nt">&amp;lt;/artifactId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;version&amp;gt;&lt;/span>6.0.1&lt;span class="nt">&amp;lt;/version&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;executions&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;execution&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;goals&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;goal&amp;gt;&lt;/span>generate&lt;span class="nt">&amp;lt;/goal&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/goals&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;configuration&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;inputSpec&amp;gt;&lt;/span>${project.basedir}/petstore.openapi.json&lt;span class="nt">&amp;lt;/inputSpec&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;generatorName&amp;gt;&lt;/span>jaxrs-spec&lt;span class="nt">&amp;lt;/generatorName&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;configOptions&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;dateLibrary&amp;gt;&lt;/span>java8&lt;span class="nt">&amp;lt;/dateLibrary&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;useSwaggerAnnotations&amp;gt;&lt;/span>false&lt;span class="nt">&amp;lt;/useSwaggerAnnotations&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!--ensure we only generate java interfaces and no implementation skeleton--&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;interfaceOnly&amp;gt;&lt;/span>true&lt;span class="nt">&amp;lt;/interfaceOnly&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/configOptions&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;apiPackage&amp;gt;&lt;/span>pro.robertopiva.api&lt;span class="nt">&amp;lt;/apiPackage&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;modelPackage&amp;gt;&lt;/span>pro.robertopiva.beans&lt;span class="nt">&amp;lt;/modelPackage&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;generateModelTests&amp;gt;&lt;/span>false&lt;span class="nt">&amp;lt;/generateModelTests&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;generateModelDocumentation&amp;gt;&lt;/span>false&lt;span class="nt">&amp;lt;/generateModelDocumentation&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;generateSupportingFiles&amp;gt;&lt;/span>false&lt;span class="nt">&amp;lt;/generateSupportingFiles&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;generateApiTests&amp;gt;&lt;/span>false&lt;span class="nt">&amp;lt;/generateApiTests&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;generateApiDocumentation&amp;gt;&lt;/span>false&lt;span class="nt">&amp;lt;/generateApiDocumentation&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;auth&amp;gt;&lt;/span>false&lt;span class="nt">&amp;lt;/auth&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/configuration&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/execution&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/executions&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/plugin&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!--maven helper plugin to add generated sources to maven project--&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;plugin&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;groupId&amp;gt;&lt;/span>org.codehaus.mojo&lt;span class="nt">&amp;lt;/groupId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;artifactId&amp;gt;&lt;/span>build-helper-maven-plugin&lt;span class="nt">&amp;lt;/artifactId&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;executions&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;execution&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;phase&amp;gt;&lt;/span>generate-sources&lt;span class="nt">&amp;lt;/phase&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;goals&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;goal&amp;gt;&lt;/span>add-source&lt;span class="nt">&amp;lt;/goal&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/goals&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;configuration&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;sources&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;source&amp;gt;&lt;/span>${project.build.directory}/generated-sources/openapi/src/gen/java&lt;span class="nt">&amp;lt;/source&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/sources&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/configuration&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/execution&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;lt;/executions&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">&amp;lt;/plugin&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>After running the canonical &lt;code>./mvnw clean package&lt;/code> we should have:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ exa --tree target
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">target
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── &lt;span class="o">[&lt;/span>...&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── generated-sources
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── annotations
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── openapi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── src
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── gen
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── java
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── pro
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── robertopiva
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── api
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ └── PetsApi.java
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── beans
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── Error.java
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── NewPet.java
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── Pet.java
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── PetAllOf.java
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>...&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can clearly see that the plugin generated beans and interfaces.&lt;/p>
&lt;p>What now? We implement those interfaces!&lt;/p>
&lt;p>On our &lt;code>src/main/java&lt;/code> folder we can now implement &lt;code>PetsApi&lt;/code> interface in our new class.&lt;/p>
&lt;p>See here a snippet without implementation:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">class&lt;/span> &lt;span class="nc">Pets&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">implements&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">PetsApi&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nd">@Override&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Pet&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">addPet&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nd">@Valid&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nd">@NotNull&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">NewPet&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">newPet&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">null&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nd">@Override&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">deletePet&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Long&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">id&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nd">@Override&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Pet&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">findPetById&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Long&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">id&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">null&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nd">@Override&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">List&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Pet&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">findPets&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">List&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">tags&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Integer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">limit&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">null&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Please note that this class is not part of the generated code, we specifically skipped the generation of &amp;ldquo;basic implementation&amp;rdquo;.
As we can see, with the interface being already set in generation, we can focus on the implementation rather than on the definitions.&lt;/p>
&lt;p>You can see a quick in-memory implementation of PetsApi at &lt;a href="https://github.com/civitz/quarkus-api-first/blob/main/src/main/java/pro/robertopiva/api/Pets.java">https://github.com/civitz/quarkus-api-first/blob/main/src/main/java/pro/robertopiva/api/Pets.java&lt;/a>&lt;/p>
&lt;h2 id="changing-the-api">Changing the API&lt;/h2>
&lt;p>Another benefit of the API-first approach is that to change the API we need to first change it&amp;rsquo;s documentation, i.e. the OpenAPI spec.&lt;/p>
&lt;p>To do this, we try to add another optional parameter to the findPets API and see what happens.
If we add the following json snippet:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// last parameter
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;limit&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;in&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;query&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;maximum number of results to return&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;required&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;schema&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;integer&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;format&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;int32&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;span class="err">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// added optional parameter
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;page&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;in&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;query&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;page number (max &amp;#39;limit&amp;#39; items per page&amp;#39;)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;required&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;schema&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;integer&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;format&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;int32&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Once we compile with &lt;code>./mvnw clean package&lt;/code> we obtain:&lt;/p>
&lt;pre tabindex="0">&lt;code>[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ api-first-pet-store ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 6 source files to /workspace/api-first-pet-store/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /workspace/api-first-pet-store/src/main/java/pro/robertopiva/api/Pets.java:[18,8] pro.robertopiva.api.Pets is not abstract and does not override abstract method findPets(java.util.List&amp;lt;java.lang.String&amp;gt;,java.lang.Integer,java.lang.Integer) in pro.robertopiva.api.PetsApi
[ERROR] /workspace/api-first-pet-store/src/main/java/pro/robertopiva/api/Pets.java:[49,5] method does not override or implement a method from a supertype
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
&lt;/code>&lt;/pre>&lt;p>This is beneficial for any situation where you want to be sure that the code respect the contract, i.e. the API.&lt;/p>
&lt;h2 id="bonus-native-compilation">Bonus: native compilation&lt;/h2>
&lt;p>We are using quarkus and we are not adding any incompatible dependency, so we can also compile to native code using the specific maven profile: &lt;code>./mvnw clean package -Pnative&lt;/code>.&lt;/p>
&lt;p>Once compiled, our API-first project boots in microseconds:&lt;/p>
&lt;pre tabindex="0">&lt;code>$ ./target/api-first-pet-store-1.0.0-SNAPSHOT-runner
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,&amp;lt; / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2022-08-06 19:29:06,858 INFO [io.quarkus] (main) api-first-pet-store 1.0.0-SNAPSHOT native (powered by Quarkus 2.11.1.Final) started in 0.025s. Listening on: http://0.0.0.0:8080
2022-08-06 19:29:06,861 INFO [io.quarkus] (main) Profile prod activated.
2022-08-06 19:29:06,861 INFO [io.quarkus] (main) Installed features: [cdi, hibernate-validator, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, vertx]
&lt;/code>&lt;/pre>&lt;h2 id="concusions">Concusions&lt;/h2>
&lt;p>Some companies are organized so that API clients are automatically, and fully, generated from OpenAPI spec. This facilitate integration both within and outside the company: &lt;strong>documenting the API is part of the development process&lt;/strong>.&lt;/p>
&lt;p>The Quarkus framework and OpenAPI generator enable an API-first approach while simultaneously maintaining high performances and native compilation as a bonus.&lt;/p></description><pubDate>Sat, 06 Aug 2022 00:00:00 +0000</pubDate><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/2022/08/06/quarkus-api-first</link><guid isPermaLink="true">https://hugorefactor--stoic-volhard-25abce.netlify.app/2022/08/06/quarkus-api-first</guid></item><item><title>JWT for service-to-service auth</title><description>&lt;p>Microservice architecture has been around for years now, and I think it&amp;rsquo;s here to stay.
The approach has many advantages, but it brings some challenges along the way. One of which is authentication/authorization.&lt;/p>
&lt;p>Authentication and authorization are two very distinct concerns that are often treated together, expecially if the information used to verify them is the same (for example a username or a session identifier). From now on we will refer to both terms together as &amp;ldquo;auth&amp;rdquo;.&lt;/p>
&lt;h2 id="an-example-microservice-architecture">An example: microservice architecture&lt;/h2>
&lt;p>In this little essay we consider a web-facing application with a microservice architecture, we assume we have a cluster where internal connectivity is not exposed, and we also have one or more services that are exposed on the internet as part of their responsibility.&lt;/p>
&lt;p>In this context one would think that after the outermost services handle auth, then the auth problem &amp;ldquo;disappears&amp;rdquo; within microservices&amp;rsquo; network. This would result in inner services having no auth, meaning integration would be very easy. It would also let everyone within the network to access data and invoke procedures without any check. This scenario assumes good intentions, so a misconfigured process or a bad actor could access or change data from within the network.&lt;/p>
&lt;p>One way to partially deal with the unlimited access is acting at the network level by either firewall rules, network policies in kubernetes, or by solutions like a service mesh.
Another approach would be to authenticate each and every request even &lt;em>within&lt;/em> the cluster. And here is where JWT shines!&lt;/p>
&lt;h2 id="json-web-token">JSON Web Token&lt;/h2>
&lt;p>&lt;a href="https://jwt.io/">JWT&lt;/a> - or JSON Web Token - is a &lt;a href="https://tools.ietf.org/html/rfc7519">standardized&lt;/a> tool to carry data over the network, expecially over HTTP. It consists in a &lt;a href="https://www.json.org">JSON&lt;/a> object with conventions on fields and also customizable fields, which is then encoded with Base64URL. The encoding happens to be compatible with HTTP headers, which is convenient because it will be the way we use it. JWT is also optionally signed (JWS - JWT signature) and/or encrypted (JWE - JWT encryption).&lt;/p>
&lt;p>More in depth, a JWT is composed of two or more JSON objects:&lt;/p>
&lt;ul>
&lt;li>a header object which describes the token type and optional sign and encryption algorithms&lt;/li>
&lt;li>a payload object containing data&lt;/li>
&lt;li>an optional signature object&lt;/li>
&lt;li>one or more encryption objects depending on the chosen algorithm&lt;/li>
&lt;/ul>
&lt;p>The header object has standard fields:&lt;/p>
&lt;ul>
&lt;li>type (typ) represents the type of token, it can be a mime type for or &amp;ldquo;JOSE&amp;rdquo;&lt;/li>
&lt;li>algorythm (alg) optionally represents the signature or encryption algorithm. Note that &lt;strong>when type is encrypted/signed the algorithm can still be &amp;ldquo;none&amp;rdquo; and this renders the token unencrypted/unverifiable&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>The payload object has standard fields called &amp;ldquo;claims&amp;rdquo; for common concepts:&lt;/p>
&lt;ul>
&lt;li>unique identifiers&lt;/li>
&lt;li>validity timestamps and validity limits&lt;/li>
&lt;li>audience specification for the token&lt;/li>
&lt;li>token issuer specification&lt;/li>
&lt;li>the subject of the token, i.e. who is the verified user/person/service authorized with this token&lt;/li>
&lt;/ul>
&lt;p>The payload can be freely extended with custom claims, as long as they are represented with standard JSON. A possible use of this is mapping capabilities of the authenticated entity, or carrying user information if JWT is used to represent a session.&lt;/p>
&lt;h2 id="enhancing-the-example">Enhancing the example&lt;/h2>
&lt;p>So what does this bring to the context of microservices?
Consider extending the original scenario: the outermost service verifies the auth of the caller, and also creates a JWT that represents the caller. It additionally sign the token, obtaining a JWS. Now you get a verifiable token that can be used to auth the request within all the internal calls inside the microservice architecture.
In this scenario we only consider JWS (or JWE) because JWT by itself is easy to change, we need at least a signature to trust the caller.&lt;/p>
&lt;p>Other services should accept the call only if they:&lt;/p>
&lt;ul>
&lt;li>verify the signature of the token&lt;/li>
&lt;li>check whether they trust the issuer (&amp;ldquo;iss&amp;rdquo; claim in the payload)&lt;/li>
&lt;li>check whether they are part of the audience for the token. That is, if their name is in the &amp;ldquo;aud&amp;rdquo; list in the payload.&lt;/li>
&lt;li>check if token is still valid according to timestamp limits (&amp;ldquo;exp&amp;rdquo;, &amp;ldquo;nbf&amp;rdquo; claims, see RFC)&lt;/li>
&lt;/ul>
&lt;p>This is nothing new but the biggest advantages of JWT/JWS is that these verifications can happen without calling other services. In other words, properly crafted JWTs provide &lt;strong>stateless&lt;/strong> authentication/authorization.&lt;/p>
&lt;h2 id="final-remarks-and-conclusion">Final remarks and conclusion&lt;/h2>
&lt;p>There are added benefits of JWT:&lt;/p>
&lt;ul>
&lt;li>you can pass JWT along the next service in chained calls&lt;/li>
&lt;li>you can carry contextual information like transaction id, or user data&lt;/li>
&lt;li>for HTTP services you only add a header, so you get to keep a clean API&lt;/li>
&lt;li>testing can be enabled by ignoring JWT signature or by configuring a trusted issuer, no fancy setup is needed&lt;/li>
&lt;li>format is standard and uses formats and encodings that are easy to decode and debug&lt;/li>
&lt;li>it is becoming pretty common so it&amp;rsquo;s easy to find API gateways and framework libraries that support it&lt;/li>
&lt;/ul>
&lt;p>Limitations:&lt;/p>
&lt;ul>
&lt;li>you need to configure your gateway (or web-facing server) to create the JWS&lt;/li>
&lt;li>you need an infrastructure to handle certificates, although with solutions like letsencrypt this is becoming easier to do&lt;/li>
&lt;li>you need to whitelist accepted algorithms and issuers of JWT on each service&lt;/li>
&lt;li>any process that initiates calls to JWT-protected services from within the cluster has to either pass through an API gateway or have a mean to create a trusted JWT by itself&lt;/li>
&lt;li>since claims can be personalized and JWT does not have a fixed schema, you need to agree on the actual combination of claims you want to use&lt;/li>
&lt;/ul>
&lt;p>I would also add that JWT are not limited to a microservice environment. The standard is agnostic and has been successfully used:&lt;/p>
&lt;ul>
&lt;li>as a soft replacement for HTTP session in frontend-backend communication&lt;/li>
&lt;li>as a format for information exchange between trusting parties&lt;/li>
&lt;li>as part of OpenID Connect, a standardized mechanism to authenticate a user on a service via a third party identity provider&lt;/li>
&lt;/ul>
&lt;p>I think JWT is a nice versatile tool to encode information. I really liked what this tiny JSON enables in a microservice environment, enhancing the security of a system without disrupting the protocols or affecting the developer experience.&lt;/p></description><pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/2022/07/23/JWT-and-auth-in-microservices</link><guid isPermaLink="true">https://hugorefactor--stoic-volhard-25abce.netlify.app/2022/07/23/JWT-and-auth-in-microservices</guid></item><item><title>Test code performance with JMH</title><description>&lt;p>I was reviewing a piece of code for a template renderer lately, and noticed something was a little bit off.
A template renderer is used to make personalized documents given a fixed text (the template) and a set of parameters.&lt;/p>
&lt;p>For example: if we want to send postcards to 1000 friends, and the text is the same a part from the name we can make a template with a placeholder text in it in place of the name. The template&amp;rsquo;s placeholders usually follow a convention, for example if we want to make personalized documents with &lt;code>Hello name&lt;/code> inside, where &lt;code>name&lt;/code> is changed for every person we want to send this document, then the template will be something like &lt;code>Hello [name], ...&lt;/code>&lt;/p>
&lt;p>A template renderer is an algorithm which takes a template (a string with token or placeholders) and some parameters (a map of string to string) and returns a rendered text (also a string). In the rendered text the algorithm:&lt;/p>
&lt;ul>
&lt;li>replaces every matched placeholder with the parameters value (e.g. every occurrence of &lt;code>[name]&lt;/code> with &lt;code>John&lt;/code>)&lt;/li>
&lt;li>leaves placeholders if there is no replacement (e.g. if there is no replacement for &lt;code>[destination]&lt;/code> for the template &lt;code>We will reach [destination]&lt;/code>, then the result of the render is &lt;code>We will reach [destination]&lt;/code>)&lt;/li>
&lt;li>ignores any extra parameters that are not mentioned as placeholders&lt;/li>
&lt;li>ignores corner cases, like unmatched characters (&lt;code>hello, [i [like [brackets&lt;/code> ) or nested/unmatched template (&lt;code>this [is a nested [bracketName]]&lt;/code>)&lt;/li>
&lt;/ul>
&lt;p>To put it all together, if we have a template:&lt;/p>
&lt;pre tabindex="0">&lt;code>Hello [name],
Meet me at [place] at around [time].
&lt;/code>&lt;/pre>&lt;p>With parameters:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Jane&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;place&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;the park&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;noon&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then the result should be:&lt;/p>
&lt;pre tabindex="0">&lt;code>Hello Jane,
Meet me at the park at around noon.
&lt;/code>&lt;/pre>&lt;p>So I was reviewing a template renderer, and the code did not look very performant. How would I evaluate the different performance of a new algorithm? We need a benchmark!
The &lt;em>de facto&lt;/em> standard of benchmarks in the Java world is JMH - &lt;a href="https://github.com/openjdk/jmh">Java Microbenchmark Harness&lt;/a>.
JMH is a tool to build code benchmarks that accounts for some peculiarities of the JVM (Java Virtual Machine), such as compiler optimizations, bytecode optimizations, and JIT (Just In Time) optimizations.&lt;/p>
&lt;p>Suppose we have a sample &lt;em>naive&lt;/em> algorithm that accepts square brackets (&lt;code>[&lt;/code> and &lt;code>]&lt;/code>) as placeholder indicator in template - please note that in our sample we use the VAVR library:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">static&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">naiveRegexReplace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Map&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">values&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">values&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">foldLeft&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">replaced&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">kv&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">replaced&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">replaceAll&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;\\[[\\s]*&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">kv&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">_1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;[\\s]*\\]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">kv&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">_2&lt;/span>&lt;span class="p">));&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To test its performance we need to set up a JMH project. You can do it via the convenient maven archetype:&lt;/p>
&lt;pre tabindex="0">&lt;code>mvn archetype:generate \
-DinteractiveMode=false \
-DarchetypeGroupId=org.openjdk.jmh \
-DarchetypeArtifactId=jmh-java-benchmark-archetype \
-DgroupId=com.mycompany \
-DartifactId=benchmarks \
-Dversion=1.0-SNAPSHOT
&lt;/code>&lt;/pre>&lt;p>Then you can go straight to edit the &lt;code>MyBenchmark&lt;/code> class.&lt;/p>
&lt;p>For our case we need a sample data, which we can generate using the &lt;code>@State(Scope.Benchmark)&lt;/code> annotation on a class with a no-arg constructor. This avoids a compiler optimization which would make the compiler return the result of a computation, as long as it can calculate that the result at compile-time.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@State&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Scope&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">Benchmark&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">static&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">class&lt;/span> &lt;span class="nc">AllMatched10AverageText&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Map&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">values&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">AllMatched10AverageText&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">values&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Stream&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">10&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">toMap&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Tuple&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">of&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;key&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;value&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">));&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">mediumGap&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Stream&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">0&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">100&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">map&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ign&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s">&amp;#34;rand&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">mkString&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">values&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">map&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Tuple2&lt;/span>&lt;span class="p">::&lt;/span>&lt;span class="n">_1&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="na">mkString&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;[&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s">&amp;#34;]&amp;#34;&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="n">mediumGap&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="s">&amp;#34;[&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="s">&amp;#34;]&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The code above generates a template with 10 placeholders, evenly spaced with text, for a total of around 3.5KB of text. Then it also generate 10 values for the placeholder text, so that all placeholders have a matched value. This represents an average case for, say, an email.&lt;/p>
&lt;p>Now for the actual benchmark:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@Benchmark&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nd">@BenchmarkMode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Mode&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">AverageTime&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nd">@OutputTimeUnit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">TimeUnit&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">MICROSECONDS&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">_10_args_averageCase_naiveRegex&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AllMatched10AverageText&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">torender&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Blackhole&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">blackhole&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">blackhole&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">consume&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">TemplateRenderers&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">naiveRegexReplace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torender&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">template&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">torender&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">values&lt;/span>&lt;span class="p">));&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Notice the &lt;code>Blackhole&lt;/code> usage: if the compiler detects that we make no use of a certain result, and it can determine that it can delete code, then our benchmark would measure nothing. To avoid this we can use the Blackhole, which consumes the result, so that the compiler will not optimize our code away.&lt;/p>
&lt;p>We can run the benchmark by running the default &lt;code>main&lt;/code> method.
The results are shown in the coonsole like the following (text has been modified to fit this post):&lt;/p>
&lt;pre tabindex="0">&lt;code>Benchmark Mode Cnt Score Error Units
MyBenchmark._10_args_averageCase_naiveRegex avgt 6 224,164 ± 8,813 us/op
&lt;/code>&lt;/pre>&lt;p>Well, now we have a baseline! We can now work on a different algorithm. For the specific case we noticed that the string is being duplicated over and over for each round of &lt;code>replaceAll&lt;/code>. We implemented a windowed/scrolling template renderer, you can see the code below:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">static&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">scrolling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Map&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">values&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pendingBracketPos&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">1&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">StringBuilder&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">new&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">StringBuilder&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">length&lt;/span>&lt;span class="p">());&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">0&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">length&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kt">char&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">charAt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="sc">&amp;#39;[&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pendingBracketPos&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">!=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">1&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pendingBracketPos&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">pendingBracketPos&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">else&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="sc">&amp;#39;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pendingBracketPos&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">1&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">else&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">possibleKey&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">substring&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pendingBracketPos&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="na">trim&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">Option&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">possibleValue&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">values&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">possibleKey&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">possibleValue&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">isDefined&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">possibleValue&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">get&lt;/span>&lt;span class="p">());&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">else&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">template&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pendingBracketPos&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">1&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">pendingBracketPos&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">1&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">else&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">if&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pendingBracketPos&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">1&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">return&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">toString&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We now have two different algorithms we can compare between, so let&amp;rsquo;s do it! Add another benchmark:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-java" data-lang="java">&lt;span class="line">&lt;span class="cl">&lt;span class="nd">@Benchmark&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nd">@BenchmarkMode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Mode&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">AverageTime&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nd">@OutputTimeUnit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">TimeUnit&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">MICROSECONDS&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="kd">public&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nf">_10_args_averageCase_scrolling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">AllMatched10AverageText&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">torender&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Blackhole&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">blackhole&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">blackhole&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">consume&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">TemplateRenderers&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">scrolling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">torender&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">template&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">torender&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="na">values&lt;/span>&lt;span class="p">));&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now we can compare the two results by running another time the benchmark:&lt;/p>
&lt;pre tabindex="0">&lt;code>Benchmark Mode Cnt Score Error Units
MyBenchmark._10_args_averageCase_naiveRegex avgt 6 224,164 ± 8,813 us/op
MyBenchmark._10_args_averageCase_scrolling avgt 6 40,114 ± 1,729 us/op
&lt;/code>&lt;/pre>&lt;p>Well, that&amp;rsquo;s a speedup of ~5x!&lt;/p>
&lt;p>Now you&amp;rsquo;ve seen the basis of JMH performance testing, you can further test your algorithms&amp;rsquo; performance by:&lt;/p>
&lt;ul>
&lt;li>adding different combination of data&lt;/li>
&lt;li>confronting more algorithms together&lt;/li>
&lt;li>changing the benchmark parameters such as:
&lt;ul>
&lt;li>warmup runs to trigger JIT optimizations&lt;/li>
&lt;li>forks to run the test on multiple instance of the same JVM to account for slight context variations between runs (e.g. cpu power state, background activity, memory paging situation,etc&amp;hellip;)&lt;/li>
&lt;li>measurement iterations&lt;/li>
&lt;li>garbage collection&lt;/li>
&lt;li>profiling&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>We added a full example in the &lt;a href="https://github.com/civitz/java-experiments">java experiments repo&lt;/a>, you can see the code (with tests!) &lt;a href="https://github.com/civitz/java-experiments/tree/master/src/main/java/io/github/civitz/java/experiments/templater">here&lt;/a>.
The repo also contains:&lt;/p>
&lt;ul>
&lt;li>an even more optimized version of the &lt;code>scrolling&lt;/code> algorithm&lt;/li>
&lt;li>the possibility to generate a runnable jar to run the benchmark as a standalone app&lt;/li>
&lt;li>more benchmark cases&lt;/li>
&lt;li>unit tests for all the algorithms&lt;/li>
&lt;/ul>
&lt;p>Have a nice performance testing!&lt;/p></description><pubDate>Sun, 14 Nov 2021 00:00:00 +0000</pubDate><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/2021/11/14/benchmark-with-jmh</link><guid isPermaLink="true">https://hugorefactor--stoic-volhard-25abce.netlify.app/2021/11/14/benchmark-with-jmh</guid><category>jmh</category><category>java</category><category>benchmark</category><category>template</category><category>render</category></item><item><title>Pulizia e ottimizzazione di un computer Windows</title><description>&lt;p>&lt;strong>Nota: questo post è una libera traduzione di un &lt;a href="https://decentsecurity.com/holiday-tasks">post di decent security&lt;/a>.
Trovate il suo lavoro presso &lt;a href="">https://decentsecurity.com&lt;/a>&lt;/strong>&lt;/p>
&lt;p>** Questa pagina è in costruzione **&lt;/p>
&lt;p>&lt;strong>[Pagina aggiornata l&amp;rsquo;ultima volta il 2022-01-18]&lt;/strong>&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;Faccio del mio meglio per rendere tutto questo il più facile possibile, ma ci sono diverse tecniche avanzate in questa guida rispetto al resto del sito&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;p>Questa è una guida alla risoluzione di problemi e manutenzione per Windows 7 e successivi. Vi aiuterà inoltre a rimuovere molti virus e riparare i danni causati da essi. Queste procedure possono essere d&amp;rsquo;aiuto per macchine anche piuttosto vecchie. Se il vostro computer è una macchina di lavoro, chiedete consiglio al vostro referente tecnico IT prima di procedere.&lt;/p>
&lt;p>Tutti questi task sono stati eseguiti da me o da miei script su decine, centinaia o a volte migliaia di computer. Potete leggere le mie qualifiche &lt;a href="https://decentsecurity.com/#/introduction/">qui&lt;/a>.&lt;/p>
&lt;p>L&amp;rsquo;ordine delle sezioni è voluto. Per esempio - eliminare alcuni programmi, eliminare i file temporanei, e poi riavviare può lasciare i programmi in uno stato inconsistente.&lt;/p>
&lt;p>&lt;strong>Non usare strumenti per pulire il registro o ottimizzatori di sistema. &lt;a href="https://decentsecurity.com/#/registry-cleaners/">Leggi perchè.&lt;/a>&lt;/strong>&lt;/p>
&lt;p>&lt;strong>Prestare attenzione utilizzando strumenti per rimuovere le telemetrie o migliorare la privacy di Windows 10&lt;/strong>. Essi possono modificare parametri di sistema che non dovrebbero, e inavvertitamente &lt;strong>disattivare funzioni di sicurezza&lt;/strong>, rendendovi vulnerabili e danneggiando funzionalità di Windows. So che è invitante &amp;ldquo;mettere il turbo al tuo PC&amp;rdquo; con strategie tipiche dei tempi di Windows XP, ma ricordate che questi strumenti mettono mano a funzionalità di basso livello che non comprendete.&lt;/p>
&lt;p>&lt;strong>Se state aggiornando a Windows 7 un computer che è stato spento per oltre un anno, o state installando da zero&lt;/strong>, ci sono dei problemi noti. Seguite questa guida per risparmiarvi ore di lavoro: &lt;a href="https://decentsecurity.com/enterprise/#/windows-7-fast-update/">Windows 7 Fast Update&lt;/a>.&lt;/p>
&lt;h2 id="1-controllo-del-disco-fisso-e-eventuali-errori-prima-di-partire">1.) Controllo del disco fisso e eventuali errori prima di partire&lt;/h2>
&lt;ul>
&lt;li>I dischi fissi possono essere una causa silente di diversi errori inspiegabili, rallentamenti, e crash. Il mio strumento preferito è &lt;a href="http://download.wdc.com/windlg/WinDlg_v1_29.zip">WinDlg di Western Digital&lt;/a>. Non serve installarlo e funziona con qualunque disco di qualunque marca.
Scaricate il file, eseguite windlg.exe, e fate doppio-click sul disco per fare un controllo veloce. Ci vogliono dai 2 ai 10 minuti.&lt;/li>
&lt;li>Lo strumento integrato di &lt;a href="https://www.howtogeek.com/166911/reliability-monitor-is-the-best-windows-troubleshooting-tool-you-arent-using/">Monitoraggio Affidabilità o &amp;ldquo;Visualizza cronologia affidabilità&amp;rdquo;&lt;/a> vi mostrerà lo storico degli errori e dei problemi sulla vostra macchina.&lt;/li>
&lt;li>[Per esperti] Controllate se ci sono state schermate blu (bugcheck) con &lt;a href="https://www.nirsoft.net/utils/blue_screen_view.html">BlueScreenView&lt;/a>.&lt;/li>
&lt;/ul>
&lt;h2 id="2-rimozione-programmi-spazzatura">2.) Rimozione programmi spazzatura&lt;/h2>
&lt;p>Questa sezione è i più tecnici. Se non siete sicuri su cosa fare, riavviate e saltate questa sezione.&lt;/p>
&lt;ul>
&lt;li>Start &amp;gt; scrivi &amp;ldquo;Programmi e funzionalità&amp;rdquo;/&amp;ldquo;App e funzionalità&amp;rdquo; &amp;gt; Invio&lt;/li>
&lt;/ul>
&lt;p>Da questa finestra, disinstalla tutto quello che sembra essere non rilevante o indesiderato. Leggi le videate MOLTO ATTENTAMENTE per essere sicuro di non lasciare tracce dei programmi rimossi accettando qualche clausola. Se &lt;strong>non&lt;/strong> sai cosa sia rilevante o non sei sicuro, non rimuovere alcun programma.
Va tutto bene, vedremo più avanti il da farsi.&lt;/p>
&lt;p>Se l&amp;rsquo;antivirus è non aggiornato o scaduto o ha problemi, rimuovilo ora. Un antivirus che non sia aggiornato a &lt;em>ieri&lt;/em> è essenzialmente inutile. Se l&amp;rsquo;uninstaller dell&amp;rsquo;antivirus è rotto, potete usare questo strumento per la rimozione manuale: &lt;a href="https://help.eset.com/ees/6/en-US/?av_remover.htm">ESET AV Remover&lt;/a>.&lt;/p>
&lt;h1 id="break-1---riavvia-prima-di-procedere-con-i-passi-successivi">BREAK 1 - Riavvia prima di procedere con i passi successivi&lt;/h1>
&lt;h2 id="3-pulire-windows-con-cleanmgrexe">3.) Pulire windows con cleanmgr.exe&lt;/h2>
&lt;p>Potete liberare giga di spazio (spesso 6GB e oltre) pulendo WinSxS, cosa che nessuno strumento può toccare con tranquillità. Lo strumento integrato in windows è stato &lt;a href="https://blogs.technet.microsoft.com/askpfeplat/2013/10/08/breaking-news-reduce-the-size-of-the-winsxs-directory-and-free-up-disk-space-with-a-new-update-for-windows-7-sp1-clients/">migliorato con Windows Update nel 2013&lt;/a>. Non fate questo passo in Windows XP.&lt;/p>
&lt;ol>
&lt;li>Start &amp;gt; scrivi &amp;ldquo;cleanmgr&amp;rdquo; &amp;gt; premi &lt;strong>Ctrl+Shift+Invio&lt;/strong> per eseguire come amministratore.&lt;/li>
&lt;li>Seleziona la linguetta &amp;ldquo;Pulizia Disco&amp;rdquo; &amp;gt; seleziona tutto tranne &amp;ldquo;Downloads&amp;rdquo; o &amp;ldquo;Scaricati&amp;rdquo; &amp;gt; premi &lt;em>OK&lt;/em>&lt;/li>
&lt;/ol>
&lt;p>Lo strumento di pulizia si chiuderà da solo una volta che ha finito. Non è necessario aspettare che termini, procedete con il prossimo passo.&lt;/p>
&lt;h2 id="4-pulizia-cache-windows-update">4.) Pulizia cache Windows Update&lt;/h2>
&lt;p>Svuotate completamente la cache di Windows Update. Questa procedura è sicura. La cartella verrà rigenerata.&lt;/p>
&lt;ol>
&lt;li>Start &amp;gt; scrivi &amp;ldquo;servuces.msc&amp;rdquo; &amp;gt; premi Invio&lt;/li>
&lt;li>&amp;ldquo;Servizio trasferimento intelligente in background&amp;rdquo; &amp;gt; click destro &amp;gt; &lt;em>Stop&lt;/em>&lt;/li>
&lt;li>&amp;ldquo;Windows Update&amp;rdquo; &amp;gt; click destro &amp;gt; &lt;em>Stop&lt;/em>.&lt;/li>
&lt;li>Rimuovete la cartella &lt;code>C:\Windows\SoftwareDistribution&lt;/code>. Se non è consentito, fermate di nuovo i servizi con i punti 1-3.&lt;/li>
&lt;/ol>
&lt;p>Non è necessario riavviare manualmente i servizi di cui sopra.&lt;/p>
&lt;h2 id="5-rimozione-file-temporanei-con-bleachbit">5.) Rimozione file temporanei con Bleachbit&lt;/h2>
&lt;p>Normalmente non ci sarebbe ragione di ricorrere a strumenti come Bleachbit. Tuttavia questo ci rende molto facile e veloce il compito di ridurre il numero di file che l&amp;rsquo;antivirus deve scansionare. Preferisco non indicare ciascuna directory da pulire per farlo a mano.&lt;/p>
&lt;ol>
&lt;li>Scarica ed installa &lt;a href="https://www.bleachbit.org/">Bleachbit&lt;/a>&lt;/li>
&lt;li>Lancia Bleachbit&lt;/li>
&lt;li>Spunta le seguenti opzioni:
&lt;ol>
&lt;li>Flash &amp;gt; Everything&lt;/li>
&lt;li>Internet Explorer &amp;gt; Everything&lt;/li>
&lt;li>System &amp;gt; Logs&lt;/li>
&lt;li>System &amp;gt; Memory dumps&lt;/li>
&lt;li>System &amp;gt; Recycle bin&lt;/li>
&lt;li>System &amp;gt; Temporary files&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>Lancia la pulizia (clean)&lt;/li>
&lt;/ol>
&lt;p>Quando cleanmgr e Bleachbit hanno finito, &lt;strong>RIAVVIA&lt;/strong>.&lt;/p>
&lt;h1 id="break-2---riavvia-prima-di-procedere-con-quanto-segue">BREAK 2 - Riavvia prima di procedere con quanto segue&lt;/h1>
&lt;h2 id="6-scansione-veloce-con-antivirus">6.) Scansione veloce con antivirus&lt;/h2>
&lt;p>Lanciate la seguente anche se si ha un antivirus. Questi sono strumenti semplici per una scansione veloce.
A questo punto, &lt;strong>disattivate temporaneamente il vostro antivirus&lt;/strong> o rimuovetelo finchè non avete terminato di seguire questa guida.&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://www.microsoft.com/security/scanner/en-us/default.aspx">Microsoft Safety Scanner&lt;/a> - Questo è un antivirus senza installazione in un unico EXE (un unico eseguibile, ndt) direttamente da Microsoft. Lanciate una scansione veloce (quick scan). Dovrebbero bastare 10 minuti. Il file pesa circa 160 MB al momento della pubblicazione.&lt;/li>
&lt;li>&lt;a href="https://www.kaspersky.com/downloads/thank-you/free-virus-removal-tool?form=1">Kaspersky Virus Removal Tool&lt;/a>&lt;/li>
&lt;/ol>
&lt;h2 id="7-controllo-e-rimozione-di-malware-o-software-spazzatura">7.) Controllo e rimozione di malware o software spazzatura&lt;/h2>
&lt;p>Usate questi strumenti se avete il sospetto che il computer non sia pulito o se ha avuto una infezione in passato.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;a href="https://www.malwarebytes.com/adwcleaner/">MalwareBytes AdwCleaner&lt;/a> è uno strumento poco conosciuto ma molto efficace per rimuovere quelle piccole cose che insidiano un computer. Controllate con cura le raccomandazioni che vi si presentano prima di accettarle. Necessita di un riavvio dopo l&amp;rsquo;uso.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://www.malwarebytes.com/">MalwareBytes Anti-Malware&lt;/a> è il mio strumento di pulizia automatica più gettonato per la pulizia da software malevolo e contro cambiamenti non desiderati del sistema. Se l&amp;rsquo;utente del computer tende ad installare software di dubbia origine, considerate di acquistare la versione Premium.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;a href="https://www.google.com/chrome/cleanup-tool/">Google Chrome Cleanup Tool&lt;/a> è un piccolo strumento da Google che usa il motore antivirus ESET per rimuovere software spazzatura. Non è necessario resettare Chrome se non pensate che sia rotto o rovinato.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="8-controllo-di-windows-update-e-firewall">8.) Controllo di Windows Update e Firewall&lt;/h2>
&lt;p>Un classico segnale di infezione è se le seguenti impostazioni non possono essere abilitate o non funzionano. Sistematele.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;em>Start&lt;/em> &amp;gt; scrivete &amp;ldquo;Windows Update&amp;rdquo; &amp;gt; Invio&lt;/p>
&lt;p>Controllate gli aggiornamenti. Se non funziona, prendete nota e continuate.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;em>Start&lt;/em> &amp;gt; scrivete &amp;ldquo;Windows Firewall&amp;rdquo; &amp;gt; Invio&lt;/p>
&lt;p>Assicuratevi che sia attivo o che dica di essere gestito da un altro programma. Se desiderate tenerlo spento, almeno assicuratevi che si accenda se lo attivate.
Se non funziona, prendete nota e continuate.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>Se non funziona Windows Update, riparatelo con &lt;a href="https://aka.ms/diag_wu">Microsoft Windows Update FixIt tool&lt;/a>.&lt;/li>
&lt;li>Se non funziona Windows Firewall, riparatelo con &lt;a href="https://support2.microsoft.com/mats/windows_firewall_diagnostic/">Microsoft Windows Firewall FixIt tool&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p>Se nessuno dei precedenti funziona, potete provare &lt;a href="http://download.webroot.com/wsvcscan.exe">Windows services repair tool&lt;/a> di &lt;a href="http://www.webroot.com/">Webroot&lt;/a> o il &lt;a href="http://www.wintips.org/how-to-restore-windows-services-to-their-default-state/">Services repair tool&lt;/a> di &lt;a href="https://www.eset.com/">ESET&lt;/a>.&lt;/p>
&lt;h2 id="9-dism-restorehealth-windows-8-e-successivi">9.) DISM RestoreHealth (Windows 8 e successivi)&lt;/h2>
&lt;p>Questo comando scansionerà il sistema alla rierca di componenti Windows corrotti, e cercherà di ripararli. Ci vorranno 20 minuti.&lt;/p>
&lt;ol>
&lt;li>Start &amp;gt; scrivete &amp;ldquo;cmd.exe&amp;rdquo; &amp;gt; premete Ctrl + Shitf + Invio&lt;/li>
&lt;li>Apparirà una finestra nera&lt;/li>
&lt;li>Scrivete &amp;ldquo;dism /Online /Cleanup-Image /RestoreHealth&amp;rdquo;&lt;/li>
&lt;li>Se il testo (in inglese) dice che è stato riparato qualcosa, riavviate il computer.&lt;/li>
&lt;/ol>
&lt;h2 id="10-installate-gli-aggiornamenti-di-windows-e-configurate-laggiornamento-automatico">10.) Installate gli aggiornamenti di Windows e configurate l&amp;rsquo;aggiornamento automatico&lt;/h2>
&lt;p>Controllate gli aggironamenti e assicuratevi siano impostati per l&amp;rsquo;aggiornamento automatico.&lt;/p>
&lt;p>Se ci sono problemi ad installare gli aggiornamente, provate i passi di seguito. Sfortunatamente ci sono situazione per cui Windwos non può essere ragionevolmente riparato. Tuttavia da Windows 8 in avanti c&amp;rsquo;è il comando DISM a disposizione per riparare la maggior parte delle corruzioni se ce ne fosse bisogno.&lt;/p>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-0---procedura-microsoft">Se gli aggiornamenti falliscono Step 0 - Procedura Microsoft&lt;/h3>
&lt;p>Microsoft mantiene una &lt;a href="https://support.microsoft.com/en-us/help/10164/fix-windows-update-errors">procedura guidata di riparazione&lt;/a> per aiutarvi a sistemare gli errori di Windows. Siccome sono l&amp;rsquo;azienda autore di Windows, dovreste prima seguire le loro procedure.&lt;/p>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-1---microsoft-fixit">Se gli aggiornamenti falliscono Step 1 - Microsoft FixIt&lt;/h3>
&lt;p>Lanciate lo &lt;a href="https://support.microsoft.com/it-it/windows/strumento-di-risoluzione-dei-problemi-di-windows-update-per-windows-10-19bc41ca-ad72-ae67-af3c-89ce169755dd">strumento di riparazione Windows Update&lt;/a> e riavviate.&lt;/p>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-2---controllo-dellintegrità-dei-file-di-sistema">Se gli aggiornamenti falliscono Step 2 - Controllo dell&amp;rsquo;integrità dei file di sistema&lt;/h3>
&lt;ol>
&lt;li>Start &amp;gt; scrivete &amp;ldquo;cmd.exe&amp;rdquo; &amp;gt; premete Ctrl+Shift+INvio per avviare come Administrator&lt;/li>
&lt;li>Apparirà una finestra nera&lt;/li>
&lt;li>Scrivete &amp;ldquo;dism /online /cleanup-image /restorehealth&amp;rdquo; senza i doppi apici e premete Invio (non funziona su Windows 7)&lt;/li>
&lt;li>Scrivete &amp;ldquo;sfc /scannow&amp;rdquo; senza i doppi apici e premete Invio. Quanto ha finito continuate al passo successivo.&lt;/li>
&lt;li>Riavviate e ricontrollate gli aggiornamenti di Windows.&lt;/li>
&lt;/ol>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-3---microsoft-fixit-solo-windows-7">Se gli aggiornamenti falliscono Step 3 - Microsoft FixIt (solo Windows 7)&lt;/h3>
&lt;p>Se avete Windows 7, segutie le istruzioni per scaricare ed eseguire &lt;a href="https://go.microsoft.com/?linkid=9665683">Microsoft Fixit 50202&lt;/a> (link rotto al 2021-08-27).&lt;/p>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-4---ripristino-di-catroot2-e-componenti-di-windows-update">Se gli aggiornamenti falliscono Step 4 - Ripristino di catroot2 e componenti di Windows Update&lt;/h3>
&lt;ol>
&lt;li>&lt;a href="http://www.thewindowsclub.com/catroot-catroot2-folder-reset-windows">Ripristinate la cartella catroot2&lt;/a> (mi raccomando cancellate il contenuto, non la cartella!)&lt;/li>
&lt;li>Scaricate ed estraete il &amp;ldquo;Reset Windows Update Tool&amp;rdquo; in una cartella del vostro desktop (link rotto al 2021-08-27, provare con &lt;a href="https://docs.microsoft.com/en-us/windows/deployment/update/windows-update-resources">https://docs.microsoft.com/en-us/windows/deployment/update/windows-update-resources&lt;/a> per windows 10)&lt;/li>
&lt;li>Tasto destro su &lt;em>ResetWUEng.cmd&lt;/em> &amp;gt; Esegui come &lt;em>amministratore&lt;/em>&lt;/li>
&lt;li>Selezionare opzioni 2, 5, 8, 9, 10, 12, riavviate, poi verificare se la presenza di aggiornamenti windows&lt;/li>
&lt;/ol>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-5---controllare-se-esistono-soluzioni-a-problemi-noti">Se gli aggiornamenti falliscono Step 5 - Controllare se esistono soluzioni a problemi noti&lt;/h3>
&lt;p>Controllate questa pagina di Microsoft Answers se comprende il vostro codice di errore o sintomi e seguite le istruzioni:
&lt;a href="https://answers.microsoft.com/en-us/insider/wiki/insider_wintp-insider_install/how-to-troubleshoot-common-setup-and-stop-errors/324d5a5f-d658-456c-bb82-b1201f735683">How to: Troubleshoot Common Setup and Stop Errors&lt;/a>&lt;/p>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-6---strumento-microsoft-sur-solo-windows-7">Se gli aggiornamenti falliscono Step 6 - Strumento Microsoft SUR (solo Windows 7)&lt;/h3>
&lt;ol>
&lt;li>Scaricate ed installate &lt;a href="https://www.microsoft.com/en-us/download/details.aspx?id=20858">Microsoft System Update Readiness Tool&lt;/a>. (Windows 7 only) (link rotto al 2021-08-27)&lt;/li>
&lt;li>Cercate la sezione 21 a in fondo, &amp;ldquo;Install Windows 7 hotfix rollup&amp;rdquo;&lt;/li>
&lt;/ol>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-7---controllo-del-disco-con-chkdsk">Se gli aggiornamenti falliscono Step 7 - Controllo del disco con chkdsk&lt;/h3>
&lt;p>Controllate se il vostro disco rigido presenta problemi.&lt;/p>
&lt;ol>
&lt;li>Start &amp;gt; scrivete &amp;ldquo;cmd.exe&amp;rdquo; &amp;gt; Ctrl-Shift-Invio (esegui come amministratore)&lt;/li>
&lt;li>Apparrirà una finestra nera, il prompt dei comandi&lt;/li>
&lt;li>Scrivete &amp;ldquo;chkdsk /r&amp;rdquo; senza doppi apici.&lt;/li>
&lt;li>Premete &amp;ldquo;y&amp;rdquo; (o &amp;ldquo;s&amp;rdquo; in italiano) e premete Invio&lt;/li>
&lt;li>Riavviate il computer&lt;/li>
&lt;li>Ritornate al &amp;ldquo;Se gli aggiornamenit falliscono Step 1&amp;rdquo; se il controllo disco ripara qualcosa del vostro disco&lt;/li>
&lt;/ol>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-8---rimozione-antivirus-e-reset-componenti-di-rete">Se gli aggiornamenti falliscono Step 8 - Rimozione antivirus e reset componenti di rete&lt;/h3>
&lt;p>Disinstallate il vostro antivirus, riavviate, e &lt;a href="https://www.hanselman.com/blog/TheNuclearOptionResettingTheCrapOutOfYourNetworkAdaptersInVista.aspx">seguite le seguenti istruzioni&lt;/a>. Tenete a mente che dovrete reinstallare eventuali software tipo VPN dopo questa operazione. Se non sapete cosa sia una VPN, allora non dovete preoccuparvene.&lt;/p>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-9---aggiornamento-driver">Se gli aggiornamenti falliscono Step 9 - Aggiornamento driver&lt;/h3>
&lt;p>Seguite la sezione 20 di questa guida.&lt;/p>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-10---checksurlog">Se gli aggiornamenti falliscono Step 10 - CheckSUR.log&lt;/h3>
&lt;p>Questo vale solo per Windows 7, ed è estremamente raro che ce ne sia bisogno. Avviso: questa sezione è altamente tecnica.&lt;/p>
&lt;ol>
&lt;li>Prima di tutto lanciate una scansione per stabilire la salute del disco con &lt;a href="http://download.wdc.com/windlg/WinDlg_v1_29.zip">WinDlg&lt;/a> di Western Digital&lt;/li>
&lt;li>Seguite questa guida &lt;a href="https://support.microsoft.com/en-us/kb/2700601">https://support.microsoft.com/en-us/kb/2700601&lt;/a>&lt;/li>
&lt;/ol>
&lt;h3 id="se-gli-aggiornamenti-falliscono-step-11---modificate-la-sezione-components">Se gli aggiornamenti falliscono Step 11 - Modificate la sezione COMPONENTS&lt;/h3>
&lt;ol>
&lt;li>Start &amp;gt; scrivete &amp;ldquo;cmd.exe&amp;rdquo; &amp;gt; Ctrl-Shift-Invio (esegui come amministratore)&lt;/li>
&lt;li>Apparrirà una finestra nera, il prompt dei comandi&lt;/li>
&lt;li>Scrivete i seguenti comandi e premete invio dopo ciascuno:
&lt;ul>
&lt;li>&lt;code>REG LOAD HKLM\COMPONENTS C:\Windows\System32\config\COMPONENTS&lt;/code>&lt;/li>
&lt;li>&lt;code>REG DELETE HKLM\COMPONENTS /V PendingRequired&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Riavviate e controllate gli aggiornamenti di windows.&lt;/li>
&lt;/ol>
&lt;p>(&lt;a href="https://social.technet.microsoft.com/Forums/windows/en-US/8d63fe26-5e33-4c5e-ab4c-e19611aa95a7/update-install-error-0x80070308?forum=w7itproinstall">Fonte - Karen Hu&lt;/a>)&lt;/p>
&lt;h2 id="11-scansione-veloce-con-secureanywhere-system-analyzer">11.) Scansione veloce con SecureAnywhere System Analyzer&lt;/h2>
&lt;p>&lt;a href="http://anywhere.webrootcloudav.com/zerol/syswranalyzer.exe">SecureAnywhere System Analyzer&lt;/a> di &lt;a href="http://www.webroot.com/">Webroot&lt;/a> fa una scansione veloce di processi e parti importanti del sistema per oggetti catalogati come malevoli nel &amp;ldquo;cloud&amp;rdquo;. Il suo passaggio attiva virus e programmi spazzatura, e non pulisce, quindi normalmente volete lanciarlo dopo che avete fatto un po&amp;rsquo; di pulizia. Serve solo a raccogliere informazioni per la vostra diagnosi.&lt;/p>
&lt;h2 id="12-pulizia-di-winsxs-con-resetbase-windows-8">12.) Pulizia di WinSxS con ResetBase (Windows 8+)&lt;/h2>
&lt;p>Questa procedura di pulizia va più a fondo del comando che abbiamo lanciato all&amp;rsquo;inizio. Dovevamo essere sicuri che il sistema fosse funzionante prima di fare pulizia di vecchi file di Windows. &lt;a href="https://msdn.microsoft.com/en-us/windows/hardware/commercialize/manufacture/desktop/clean-up-the-winsxs-folder">Clicca qui per spiegazione tecnica su cosa avviene.&lt;/a>&lt;/p>
&lt;ol>
&lt;li>Start &amp;gt; type &lt;code>cmd.exe&lt;/code> &amp;gt; Ctrl-Shift-Invio (esegui come amministratore)&lt;/li>
&lt;li>Scrivete: &lt;code>Dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase&lt;/code>&lt;/li>
&lt;li>Invio&lt;/li>
&lt;/ol>
&lt;h2 id="13-controllo-dellaccount-utente-al-massimo">13.) Controllo dell&amp;rsquo;account utente al massimo&lt;/h2>
&lt;p>&lt;strong>Ascoltatemi&lt;/strong>. O ascoltate uno dei &lt;a href="https://blogs.msdn.microsoft.com/oldnewthing/20160816-00/?p=94105">programmatori Microsoft più esperti&lt;/a>. UAC (controllo account utente) è un sistema importante che ha impatti profondi nel sistema, in aree che normalmente non sono visibili. Non è come l&amp;rsquo;imballaggio con le bolle da togliere prima dell&amp;rsquo;uso. Esiste per ragioni importante, non è &lt;em>cool&lt;/em> toglierlo.&lt;/p>
&lt;p>&lt;a href="https://www.tenforums.com/tutorials/3577-change-user-account-control-uac-settings-windows-10-a.html">Segui queste istruzioni&lt;/a> (o &lt;a href="https://support.microsoft.com/it-it/topic/guida-interattiva-regolare-le-impostazioni-di-controllo-dell-account-utente-in-windows-7-e-windows-8-605f891d-42c5-2b93-4b4b-e4c5d4d35f60">segui queste per istruzioni in italiano&lt;/a>, ndt) per impostare UAC al massimo, o &amp;ldquo;Notifica sempre&amp;rdquo;. Qualsiasi valore minore permeterebbe ai malware di eseguire istantaneamente operazioni con privilegi di amministrazione. UAC non è magia, è uno livello di protezione che volete usare.&lt;/p>
&lt;h2 id="14-abilitare-smartscreen-windows-8">14.) Abilitare SmartScreen (Windows 8+)&lt;/h2>
&lt;p>Questo strumento verifica assieme a Microsoft e avvisa l&amp;rsquo;utente nel caso si scarichi ed esegua dei programmi non comunemente usati. Questo controllo previene la maggior parte delle infezioni originate da mail fasulle a meno che l&amp;rsquo;utente non scelga di procedere nonostante l&amp;rsquo;avviso di cautela.&lt;/p>
&lt;ol>
&lt;li>Start &amp;gt; Scrivete &lt;code>SmartScreen&lt;/code> (o &lt;code>Protezione basata sulla reputazione&lt;/code> nelle versioni italiane, ndt) &amp;gt; Clicca &amp;ldquo;Cambia impostazioni SmartScreen&amp;rdquo; (in versioni successive si dovrebbe arrivare già sulla schermata con le impostazioni di SmartScreen, ndt)&lt;/li>
&lt;li>Sulla sinistra, clicca &amp;ldquo;Cambia impostazioni Windows SmartScreen&amp;rdquo;&lt;/li>
&lt;li>Seleziona &amp;ldquo;Chiedi approvazione dell&amp;rsquo;amministratore&amp;rdquo; (Windows 8) o &amp;ldquo;Controlla app e file&amp;rdquo; (Windows 10)&lt;/li>
&lt;/ol>
&lt;p>Nota del traduttore: aggiornamenti recenti di windows hanno cambiato nomenclatura e abilitato nuove funzioni di SmartScreen, se si entra su &amp;ldquo;Protezione basata sulla reputazione&amp;rdquo; il consiglio è abilitare tutte le funzioni. Ogni selettore abilita una variante di SmartScreen focalizzata su diverse categorie di file e programmi. Come indicato sopra, questi controlli prevengono infezioni da programmi malevoli.&lt;/p>
&lt;h2 id="15-pulizia-e-re-inizializzazione-del-servizio-di-ricerca-di-windows-windows-search">15.) Pulizia e re-inizializzazione del servizio di ricerca di Windows (Windows Search)&lt;/h2>
&lt;p>Windows ha un sistema integrato di ricerca e indicizzazione chiamato Windows Search e per utenti con grandi quantità di dati i file di indice possono raggiungere dimensioni di diversi gigabyte. Inoltre Windows Search può occasionalmente corrompersi. Normalmente il servizio si fa manutenzione in autonomia, ma è possibile &amp;ldquo;resettarlo&amp;rdquo; al bisogno. La pulizia può liberare anche un gigabyte o più specie se si usa molto Outlook. Questa pulizia va oltre il normale comando di re-indicizzazione di Windows Search, che personalmente trovo poco efficace (a detta dell&amp;rsquo;autore, ndt).&lt;/p>
&lt;p>Questa procedura non è documentata, l&amp;rsquo;ho imparata dopo ore di ricerca e diagnosi su svariate istanze di Outlook con problemi di ricerca.&lt;/p>
&lt;ol>
&lt;li>Start &amp;gt; Scrivete &lt;code>cmd.exe&lt;/code> &amp;gt; Premete Ctrl-Shift-Invio (esegui come amministratore)&lt;/li>
&lt;li>Dare i seguenti comandi e premere Invio dopo ciascuno:
&lt;ol>
&lt;li>&lt;code>net stop WSearch&lt;/code>&lt;/li>
&lt;li>&lt;code>RD /S /Q &amp;quot;C:\ProgramData\Microsoft\Search&amp;quot;&lt;/code>&lt;/li>
&lt;li>&lt;code>regedit&lt;/code>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>In Regedit, trovate e cancellate le seguenti chiavi e cartelle (aiutetevi con la ricerca, ndt):
&lt;ul>
&lt;li>Sotto &amp;ldquo;Current User&amp;rdquo;: &lt;code>HKEY_CURRENT_USER\Software\Microsoft\Windows Search&lt;/code>&lt;/li>
&lt;li>Poi, sotto &amp;ldquo;Local Machine&amp;rdquo;: &lt;code>HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Search\SetupCompletedSuccessfully&lt;/code>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="16-pulizia-e-aggiornamento-browser">16.) Pulizia e aggiornamento browser&lt;/h2>
&lt;p>&lt;strong>Verificate manualmente che ogni browser che utilizzate sia alla sua ultima versione&lt;/strong>&lt;/p>
&lt;p>Se l&amp;rsquo;utente è prono a infettarsi con malware o altri programmi che prendono possesso del computer, o ad avere problemi di performance con i browser, probabilmente è il caso di cancellare la cache e resettare le impostazioni. In altri casi questo potrebbe risultare esagerato. Questi di seguito sono le modalità più semplici per reimpostare i browser, ma almeno sarete sicuri che il sistema sarà pulito.
&lt;strong>NOTA&lt;/strong>: Queste procedure cancellano tutte le password e altri dati salvati.&lt;/p>
&lt;h3 id="microsoft-edge">Microsoft Edge&lt;/h3>
&lt;p>Al momento non ho esperienza sul campo in merito a virus con questo browser, non ho suggerimenti.&lt;/p>
&lt;h3 id="google-chrome">Google Chrome&lt;/h3>
&lt;p>Reimposteremo Chrome da zero.&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://support.google.com/chrome/answer/96816?hl=it">Esportare i preferiti di Chrome&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://support.google.com/chrome/answer/95319?hl=it">Disinstallate Google Chrome&lt;/a>.&lt;/li>
&lt;li>Start &amp;gt; Scrivete &lt;code>%AppData%&lt;/code> &amp;gt; Premete Invio. Cancellate la cartella &amp;ldquo;Google&amp;rdquo;.&lt;/li>
&lt;li>Start &amp;gt; Scrivete &lt;code>%AppDataLocal%&lt;/code> &amp;gt; Premete Invio. Cancellate la cartella &amp;ldquo;Google&amp;rdquo;.&lt;/li>
&lt;li>Cancellate la cartella &lt;code>C:\Program Files (x86)\Google\Chrome&lt;/code>&lt;/li>
&lt;li>Start &amp;gt; Scrivete &lt;code>regedit.exe&lt;/code> &amp;gt; Premete Invio. Cancellate le chiavi &lt;code>HKCU\Software\Policies\Google&lt;/code> e &lt;code>HKLM\Software\Policies\Google&lt;/code>&lt;/li>
&lt;li>Installate Google Chrome con l&amp;rsquo;&lt;a href="https://cloud.google.com/chrome-enterprise/browser/download/">installer aziendale 64-bit MSI&lt;/a> (scorrete in basso nella pagina). Potete installarlo anche normalmente se volete. Non vi serve aiuto per questo.&lt;/li>
&lt;li>&lt;a href="https://support.google.com/chrome/answer/96816?hl=it">Reimportate i preferiti di Chrome&lt;/a>.&lt;/li>
&lt;/ol>
&lt;h3 id="mozilla-firefox">Mozilla Firefox&lt;/h3>
&lt;p>Reimposteremo Firefox da zero.&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://support.mozilla.org/it/kb/Esportare%20i%20segnalibri%20in%20Internet%20Explorer">Esportate i preferiti di Firefox&lt;/a>.&lt;/li>
&lt;li>Disinstallate Mozilla Firefox&lt;/li>
&lt;li>Start &amp;gt; Scrivete &lt;code>%AppData%\Mozilla&lt;/code> &amp;gt; Premete Invio. Cancellate la cartella &amp;ldquo;Firefox&amp;rdquo;.&lt;/li>
&lt;li>Start &amp;gt; Scrivete &lt;code>regedit.exe&lt;/code> &amp;gt; Premete Invio.Cancellate le chiavi &lt;code>HKCU\Software\Policies\Mozilla&lt;/code> e &lt;code>HKLM\Software\Policies\Mozilla&lt;/code>&lt;/li>
&lt;li>Cancellate la cartella &amp;ldquo;Mozilla Firefox&amp;rdquo; sotto &lt;code>C:\Program Files&lt;/code> e &lt;code>C:\Program Files (x86)&lt;/code>&lt;/li>
&lt;li>&lt;a href="https://www.mozilla.org/it/firefox/new/">Installate Firefox dal sito di Mozilla&lt;/a>.&lt;/li>
&lt;li>&lt;a href="https://support.mozilla.org/it/kb/Esportare%20i%20segnalibri%20in%20Internet%20Explorer">Reimportate i preferiti in Firefox&lt;/a>.&lt;/li>
&lt;/ol>
&lt;h3 id="internet-explorer">Internet Explorer&lt;/h3>
&lt;p>(Questa procedura andrebbe rivista perchè Microsoft ormai installa e raccomanda solo Edge e la sua modalità compatibilità, vi lascio la traduzione per comodità. ndr)
Riporteremo Internet Explorer alle sue impostazioni predefinite. Non è un reset al 100% ma ci si avvicina. Assicuratevi di avere Internet Explorer in versione 11. Per sicurezza faremo un backup dei preferiti (è una storia lunga, fidatevi).&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://kb.wisc.edu/helpdesk/page.php?id=1419">Esportate i preferiti di Internet Explorer&lt;/a>&lt;/li>
&lt;li>Internet Explorer &amp;gt; Premere Alt &amp;gt; Strumenti &amp;gt; Opzioni Internet &amp;gt; Avanzate &amp;gt; Reset&lt;/li>
&lt;li>Selezionate &amp;ldquo;Elimina impostazioni personalizzate&amp;rdquo; (la traduzione esatta potrebbe essere leggermente diversa, ndt) &amp;gt; Ok&lt;/li>
&lt;/ol></description><pubDate>Wed, 04 Aug 2021 00:00:00 +0000</pubDate><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/2021/08/04/holiday-tasks</link><guid isPermaLink="true">https://hugorefactor--stoic-volhard-25abce.netlify.app/2021/08/04/holiday-tasks</guid></item><item><title>Running gnash on Ubuntu 20.04 with docker</title><description>&lt;p>A couple weeks ago I helped my sister upgrade her laptop to the latest ubuntu version available, a process which went without issues.
The other day she calls me tell me she needs to play flash files and the player she used no longer works. I chuckled at the thought of flash files in 2020&amp;hellip;
It turns out academia and book editors still use this technology in their digital media to make it difficult to copy their precious data.&lt;/p>
&lt;p>Flash has always been a problem in linux, expecially in the web. Adobe provided a flash plugin for firefox, but for the poor souls who had to play standalone flash files there was no alternative. Then the gnash emerged: an open source flash player which reached a pretty good level of compatibility with the official format.
The problem is: gnash is no longer available in official ubuntu repos due to the use of unpatched libraries and the understandable lack of will
to update its code.&lt;/p>
&lt;p>So how to resolve this &lt;em>impasse&lt;/em>? Docker of course, because every other alternative sucks and it turns out it&amp;rsquo;s easier with docker with the aid of some tricks.&lt;/p>
&lt;p>My sister is already familiar with the basics of command line: she can navigate directories, launch commands, upgrade the system, etc&amp;hellip; But I cannot force her to learn a lot of docker options. She is not a developer after all.&lt;/p>
&lt;p>I stumbled upon this great article by Remy van Elst called &lt;a href="https://raymii.org/s/tutorials/Running_gnash_on_Ubuntu_20.04.html">Running gnash on Ubuntu 20.04 (in Docker with X11 forwarding)&lt;/a>, in which he shows how to launch gnash with X11 forwarding.&lt;/p>
&lt;p>I needed a more generic way to launch docker: I don&amp;rsquo;t know in advance which files my sister will need to play. I came up with this variation of the Dockerfile:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-Dockerfile" data-lang="Dockerfile">&lt;span class="line">&lt;span class="cl">&lt;span class="k">FROM&lt;/span>&lt;span class="s"> ubuntu:18.04&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apt-get update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt-get install -y sudo&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> apt-get update &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> apt-get install -y gnash&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">RUN&lt;/span> &lt;span class="nb">export&lt;/span> &lt;span class="nv">uid&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1000&lt;/span> &lt;span class="nv">gid&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">1000&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> mkdir -p /home/developer &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;developer:x:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">uid&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">gid&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:Developer,,,:/home/developer:/bin/bash&amp;#34;&lt;/span> &amp;gt;&amp;gt; /etc/passwd &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;developer:x:&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="nv">uid&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&amp;#34;&lt;/span> &amp;gt;&amp;gt; /etc/group &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> &lt;span class="nb">echo&lt;/span> &lt;span class="s2">&amp;#34;developer ALL=(ALL) NOPASSWD: ALL&amp;#34;&lt;/span> &amp;gt; /etc/sudoers.d/developer &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> chmod &lt;span class="m">0440&lt;/span> /etc/sudoers.d/developer &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="se">\
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="se">&lt;/span> chown &lt;span class="si">${&lt;/span>&lt;span class="nv">uid&lt;/span>&lt;span class="si">}&lt;/span>:&lt;span class="si">${&lt;/span>&lt;span class="nv">gid&lt;/span>&lt;span class="si">}&lt;/span> -R /home/developer&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">USER&lt;/span>&lt;span class="s"> developer&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENV&lt;/span> HOME /home/developer&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">WORKDIR&lt;/span>&lt;span class="s"> /home/developer&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="k">ENTRYPOINT&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;/usr/bin/gnash&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The same warning about uid and gid apply: we need to build this image on the target machine, and tweak the uid and gid so that they match the current user&amp;rsquo;s ids.
The meaningful change is the &lt;code>ENTRYPOINT&lt;/code> command: it lets us launch the docker image as it was a command.&lt;/p>
&lt;p>We can launch the image with this command line:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ docker run -it -e &lt;span class="nv">DISPLAY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nv">$DISPLAY&lt;/span> --net&lt;span class="o">=&lt;/span>host -v /tmp/.X11-unix:/tmp/.X11-unix -v &lt;span class="k">$(&lt;/span>&lt;span class="nb">pwd&lt;/span>&lt;span class="k">)&lt;/span>:/home/developer gnash filename.swf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>I also added a little script in &lt;code>~/.local/bin/gnash&lt;/code> with this content:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>docker run -it -e &lt;span class="nv">DISPLAY&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="nv">$DISPLAY&lt;/span> --net&lt;span class="o">=&lt;/span>host -v /tmp/.X11-unix:/tmp/.X11-unix -v &lt;span class="k">$(&lt;/span>&lt;span class="nb">pwd&lt;/span>&lt;span class="k">)&lt;/span>:/home/developer gnash &lt;span class="nv">$@&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This way the command is always available in the command line, with a simple:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ gnash filename.swf
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>which is almost the same as having gnash installed.&lt;/p>
&lt;p>Happy sister, horray for for docker!&lt;/p>
&lt;h2 id="update">Update&lt;/h2>
&lt;p>Remy van Elst recently pushed out a snap version of gnash, you can see his work here: &lt;a href="https://raymii.org/s/blog/Ive_packaged_up_Gnash_as_a_Snap_for_modern_linux.html">I&amp;rsquo;ve packaged up Gnash as a snap, for modern linux&lt;/a>.
All you need to do is:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ snap install gnash-raymii &lt;span class="c1"># install gnash&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">$ gnash-raymii.gnash filename.swf &lt;span class="c1"># use gnash&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The setup is much easier than using docker, hats off to Remy!&lt;/p></description><pubDate>Mon, 16 Nov 2020 00:00:00 +0000</pubDate><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/11/16/gnash-in-docker-ubuntu-20.04</link><guid isPermaLink="true">https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/11/16/gnash-in-docker-ubuntu-20.04</guid></item><item><title>It's never a network problem, until it is</title><description>&lt;p>You know when you have a problem and you struggle to find the solution?&lt;/p>
&lt;p>And you just try and try, maybe not even trying some solution because it could never be that THAT part is broken, right? Right?&lt;/p>
&lt;p>Well&amp;hellip; i struggled with git from within a VM and with a VPN: no git push, spotty git pull. I assumed it was a git problem, or a key problem. No, it was an MTU problem!&lt;/p>
&lt;p>Turns out when you hop between increasingly strict networks (virtual switches, vpn, wifi packets, you name it) sometimes fragmentations can&amp;rsquo;t cope with the whole thing&amp;hellip;&lt;/p>
&lt;p>So i had to run&lt;/p>
&lt;pre tabindex="0">&lt;code>sudo ip link set dev eth0 mtu 1400
&lt;/code>&lt;/pre>&lt;p>to lower the MTU and finally being able to operate git.&lt;/p>
&lt;p>(&lt;code>sudo ifconfig eth0 mtu 1458&lt;/code> does not work because ubuntu 18+ does not ship with &lt;code>ifconfig&lt;/code>)&lt;/p></description><pubDate>Mon, 26 Oct 2020 00:00:00 +0000</pubDate><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/10/26/never-a-network-problem</link><guid isPermaLink="true">https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/10/26/never-a-network-problem</guid></item><item><title>Viper configuration injection and Airhacks.tv</title><description>&lt;p>I had a chance of promoting &lt;a href="https://github.com/civitz/viper">civitz/viper&lt;/a> on Adam Bien&amp;rsquo;s airhacks.tv series.&lt;/p>
&lt;p>You can find the awesome adam bien series on airhacks.tv, and the episode with viper is &lt;a href="https://adambien.blog/roller/abien/entry/jax_rs_error_serialization_viper">here&lt;/a>:&lt;/p>
&lt;p>&lt;a href="https://www.youtube.com/watch?v=47rUZJe6BU0">&lt;img src="https://img.youtube.com/vi/47rUZJe6BU0/0.jpg" alt="79th airhacks.tv Questions &amp;amp; Answers">&lt;/a>&lt;/p>
&lt;p>It turns out developing a large array of tests was appreciated :)&lt;/p>
&lt;p>Thanks Adam for reviewing the library!&lt;/p></description><pubDate>Sun, 25 Oct 2020 00:00:00 +0000</pubDate><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/10/25/viper-config-adam-bien</link><guid isPermaLink="true">https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/10/25/viper-config-adam-bien</guid></item><item><title>A note taking system in vscode</title><description>&lt;p>I keep all my notes and interesting files in a single directory (e.g. &lt;code>$HOME/documents&lt;/code>) and open Visual Studio Code using that directory as base folder.&lt;/p>
&lt;p>Now I have&lt;/p>
&lt;ul>
&lt;li>fuzzy search out of the box for files (assuming I have some sort of naming conventions)&lt;/li>
&lt;li>a fast full-text search&lt;/li>
&lt;li>ready-to-use syntax highlighting for code snippets&lt;/li>
&lt;li>rendering for images/gifs&lt;/li>
&lt;/ul></description><pubDate>Sun, 09 Aug 2020 00:00:00 +0000</pubDate><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/08/09/note-taking-system-vscode</link><guid isPermaLink="true">https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/08/09/note-taking-system-vscode</guid></item><item><title>Build github pages with jekyll via docker</title><description>&lt;p>Every time I want to write something in my blog, I somehow manage to mess with my ruby/jekyll setup, so I guess it&amp;rsquo;s time for some docker.&lt;/p>
&lt;p>Starting from the awesome work of &lt;a href="https://github.com/Starefossen/docker-github-pages">Hans Kristian Flaatten&amp;rsquo;s docker github pages&lt;/a>, but it lacks draft rendering.
Instead of building another image with an hardcoded &lt;code>--drafts&lt;/code> parameter, I added an &lt;code>ENTRYPOINT&lt;/code> rather than &lt;code>CMD&lt;/code>, thus converting the image to a command line jekyll.&lt;/p>
&lt;p>I can then run&lt;/p>
&lt;pre tabindex="0">&lt;code>docker run -t -v &amp;#34;$PWD&amp;#34;:/usr/src/app -p &amp;#34;4000:4000&amp;#34; jekyll-gh --drafts
&lt;/code>&lt;/pre>&lt;p>to obtain a working site on &lt;code>localhost:4000&lt;/code> with rendered drafts.&lt;/p>
&lt;p>The example command above assumes I ran &lt;code>docker build -t jekyll-gh . &lt;/code> to build the image with the &lt;code>jekyll-gh&lt;/code> tag.&lt;/p>
&lt;p>You can find the Dockerfile &lt;a href="https://github.com/civitz/civitz.github.io/tree/netlify">in the code home of this blog&lt;/a> along with a handy script to run the whole thing.&lt;/p></description><pubDate>Sun, 09 Aug 2020 00:00:00 +0000</pubDate><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/08/09/jekyll-via-docker</link><guid isPermaLink="true">https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/08/09/jekyll-via-docker</guid></item><item><title>Openapi/swagger editor from docker</title><description>&lt;p>If you need to quickly edit or view a swagger/openapi spec, you can use the mighty swagger editor: &lt;a href="https://github.com/swagger-api/swagger-editor">https://github.com/swagger-api/swagger-editor&lt;/a>&lt;/p>
&lt;p>For a quick way to run it, use docker to run the editor itself:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">docker pull swaggerapi/swagger-editor
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker run -d -p 8080:8080 swaggerapi/swagger-editor
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Then open your browser on localhost to use the webapp.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">xdg-open http://127.0.0.1:8080
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description><pubDate>Thu, 20 Feb 2020 00:00:00 +0000</pubDate><link>https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/02/20/open-api-editor</link><guid isPermaLink="true">https://hugorefactor--stoic-volhard-25abce.netlify.app/2020/02/20/open-api-editor</guid></item></channel></rss>